From 61bc334df1eff953d93866c1b107bf5fbf38a2f1 Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Mon, 14 Jan 2013 09:21:30 -0500 Subject: [PATCH 001/188] Ensure output table formatting does not contain NaNs. For (0 eval ref calls)/(0 comp ref calls), set the proportion to 0.00. Added integration tests (checked against manual tabulation) --- .../variantutils/GenotypeConcordance.java | 25 +++++--- .../GenotypeConcordanceIntegrationTest.java | 63 +++++++++++++++++++ 2 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index de7b14ddb..ab137d4d5 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -85,6 +85,13 @@ public class GenotypeConcordance extends RodWalker nrsEntry : metrics.getPerSampleNRS().entrySet() ) { @@ -210,4 +217,4 @@ public class GenotypeConcordance extends RodWalker Date: Fri, 11 Jan 2013 18:05:45 -0500 Subject: [PATCH 002/188] getAdaptorBoundary returns an int, not an Integer, as this was taking 30% of the allocation effort for LIBS --- .../sting/utils/clipping/ReadClipper.java | 4 ++-- .../sting/utils/sam/ReadUtils.java | 16 ++++++++------- .../sting/utils/sam/ReadUtilsUnitTest.java | 20 +++++++++---------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java b/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java index 524c29d64..87526545d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java +++ b/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java @@ -381,9 +381,9 @@ public class ReadClipper { * @return a new read without adaptor sequence */ private GATKSAMRecord hardClipAdaptorSequence () { - final Integer adaptorBoundary = ReadUtils.getAdaptorBoundary(read); + final int adaptorBoundary = ReadUtils.getAdaptorBoundary(read); - if (adaptorBoundary == null || !ReadUtils.isInsideRead(read, adaptorBoundary)) + if (adaptorBoundary == ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY || !ReadUtils.isInsideRead(read, adaptorBoundary)) return read; return read.getReadNegativeStrandFlag() ? hardClipByReferenceCoordinatesLeftTail(adaptorBoundary) : hardClipByReferenceCoordinatesRightTail(adaptorBoundary); diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index b61628d4d..b43b590df 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -169,8 +169,8 @@ public class ReadUtils { * @return whether or not the base is in the adaptor */ public static boolean isBaseInsideAdaptor(final GATKSAMRecord read, long basePos) { - Integer adaptorBoundary = getAdaptorBoundary(read); - if (adaptorBoundary == null || read.getInferredInsertSize() > DEFAULT_ADAPTOR_SIZE) + final int adaptorBoundary = getAdaptorBoundary(read); + if (adaptorBoundary == CANNOT_COMPUTE_ADAPTOR_BOUNDARY || read.getInferredInsertSize() > DEFAULT_ADAPTOR_SIZE) return false; return read.getReadNegativeStrandFlag() ? basePos <= adaptorBoundary : basePos >= adaptorBoundary; @@ -199,26 +199,28 @@ public class ReadUtils { * in these cases the adaptor boundary is at the start of the read plus the inferred insert size (plus one) * * @param read the read being tested for the adaptor boundary - * @return the reference coordinate for the adaptor boundary (effectively the first base IN the adaptor, closest to the read. NULL if the read is unmapped or the mate is mapped to another contig. + * @return the reference coordinate for the adaptor boundary (effectively the first base IN the adaptor, closest to the read. + * CANNOT_COMPUTE_ADAPTOR_BOUNDARY if the read is unmapped or the mate is mapped to another contig. */ - public static Integer getAdaptorBoundary(final SAMRecord read) { + public static int getAdaptorBoundary(final SAMRecord read) { final int MAXIMUM_ADAPTOR_LENGTH = 8; final int insertSize = Math.abs(read.getInferredInsertSize()); // the inferred insert size can be negative if the mate is mapped before the read (so we take the absolute value) if (insertSize == 0 || read.getReadUnmappedFlag()) // no adaptors in reads with mates in another chromosome or unmapped pairs - return null; + return CANNOT_COMPUTE_ADAPTOR_BOUNDARY; - Integer adaptorBoundary; // the reference coordinate for the adaptor boundary (effectively the first base IN the adaptor, closest to the read) + int adaptorBoundary; // the reference coordinate for the adaptor boundary (effectively the first base IN the adaptor, closest to the read) if (read.getReadNegativeStrandFlag()) adaptorBoundary = read.getMateAlignmentStart() - 1; // case 1 (see header) else adaptorBoundary = read.getAlignmentStart() + insertSize + 1; // case 2 (see header) if ( (adaptorBoundary < read.getAlignmentStart() - MAXIMUM_ADAPTOR_LENGTH) || (adaptorBoundary > read.getAlignmentEnd() + MAXIMUM_ADAPTOR_LENGTH) ) - adaptorBoundary = null; // we are being conservative by not allowing the adaptor boundary to go beyond what we belive is the maximum size of an adaptor + adaptorBoundary = CANNOT_COMPUTE_ADAPTOR_BOUNDARY; // we are being conservative by not allowing the adaptor boundary to go beyond what we belive is the maximum size of an adaptor return adaptorBoundary; } + public static int CANNOT_COMPUTE_ADAPTOR_BOUNDARY = Integer.MIN_VALUE; /** * is the read a 454 read? diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java index 71c7d1bb0..4194aa6d5 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java @@ -40,7 +40,7 @@ public class ReadUtilsUnitTest extends BaseTest { final int mateStart = 1000; final int BEFORE = mateStart - 2; final int AFTER = mateStart + 2; - Integer myStart, boundary; + int myStart, boundary; GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, cigar); read.setMateAlignmentStart(mateStart); @@ -51,43 +51,43 @@ public class ReadUtilsUnitTest extends BaseTest { read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(false); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertEquals(boundary.intValue(), myStart + fragmentSize + 1); + Assert.assertEquals(boundary, myStart + fragmentSize + 1); // Test case 2: positive strand, second read myStart = AFTER; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(false); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertEquals(boundary.intValue(), myStart + fragmentSize + 1); + Assert.assertEquals(boundary, myStart + fragmentSize + 1); // Test case 3: negative strand, second read myStart = AFTER; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(true); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertEquals(boundary.intValue(), mateStart - 1); + Assert.assertEquals(boundary, mateStart - 1); // Test case 4: negative strand, first read myStart = BEFORE; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(true); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertEquals(boundary.intValue(), mateStart - 1); + Assert.assertEquals(boundary, mateStart - 1); // Test case 5: mate is mapped to another chromosome (test both strands) read.setInferredInsertSize(0); read.setReadNegativeStrandFlag(true); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertNull(boundary); + Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setReadNegativeStrandFlag(false); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertNull(boundary); + Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setInferredInsertSize(10); // Test case 6: read is unmapped read.setReadUnmappedFlag(true); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertNull(boundary); + Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setReadUnmappedFlag(false); // Test case 7: reads don't overlap and look like this: @@ -99,7 +99,7 @@ public class ReadUtilsUnitTest extends BaseTest { read.setInferredInsertSize(20); read.setReadNegativeStrandFlag(true); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertNull(boundary); + Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); // second read: myStart = 1000; @@ -107,6 +107,6 @@ public class ReadUtilsUnitTest extends BaseTest { read.setMateAlignmentStart(980); read.setReadNegativeStrandFlag(false); boundary = ReadUtils.getAdaptorBoundary(read); - Assert.assertNull(boundary); + Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); } } From 83fcc06e28b5d4d85e84183465f7c118536688f5 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 12 Jan 2013 12:41:13 -0500 Subject: [PATCH 003/188] LIBS optimizations and performance tools -- Made LIBSPerformance a full featured CommandLineProgram, and it can be used to assess the LIBS performance by reading a provided BAM -- ReadStateManager now provides a clean interface to iterate in sample order the per-sample read states, allowing us to avoid many map.get calls -- Moved updateReadStates to ReadStateManager -- Removed the unnecessary wrapping of an iterator in ReadStateManager -- readStatesBySample is now a LinkedHashMap so that iteration occurs in LIBS sample order, allowing us to avoid many unnecessary calls to map.get iterating over samples. Now those are just map native iterations -- Restructured collectPendingReads for simplicity, removing redundant and consolidating common range checks. The new piece is code is much clearer and avoids several unnecessary function calls --- .../locusiterator/AlignmentStateMachine.java | 10 ++ .../locusiterator/LocusIteratorByState.java | 40 ++--- .../utils/locusiterator/ReadStateManager.java | 144 ++++++++++-------- .../ReadStateManagerUnitTest.java | 2 +- 4 files changed, 99 insertions(+), 97 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java index 32e56866b..50bc9e25b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java @@ -113,6 +113,16 @@ public class AlignmentStateMachine { return read; } + /** + * Get the reference index of the underlying read + * + * @return the reference index of the read + */ + @Ensures("result == getRead().getReferenceIndex()") + public int getReferenceIndex() { + return getRead().getReferenceIndex(); + } + /** * Is this the left edge state? I.e., one that is before or after the current read? * @return true if this state is an edge state, false otherwise diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java index 01c9e564e..9499bfa35 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java @@ -34,8 +34,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.pileup.PileupElement; -import org.broadinstitute.sting.utils.pileup.ReadBackedPileupImpl; +import org.broadinstitute.sting.utils.pileup.*; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import org.broadinstitute.sting.utils.sam.ReadUtils; @@ -234,17 +233,16 @@ public class LocusIteratorByState extends LocusIterator { final GenomeLoc location = getLocation(); final Map fullPileup = new HashMap(); - // TODO: How can you determine here whether the current pileup has been downsampled? - boolean hasBeenSampled = false; - - for (final String sample : samples) { - final Iterator iterator = readStates.iterator(sample); - final List pile = new ArrayList(readStates.size(sample)); + for (final Map.Entry sampleStatePair : readStates ) { + final String sample = sampleStatePair.getKey(); + final ReadStateManager.PerSampleReadStateManager readState = sampleStatePair.getValue(); + final Iterator iterator = readState.iterator(); + final List pile = new ArrayList(readState.size()); while (iterator.hasNext()) { // state object with the read/offset information final AlignmentStateMachine state = iterator.next(); - final GATKSAMRecord read = (GATKSAMRecord) state.getRead(); + final GATKSAMRecord read = state.getRead(); final CigarOperator op = state.getCigarOperator(); if (op == CigarOperator.N) // N's are never added to any pileup @@ -263,29 +261,9 @@ public class LocusIteratorByState extends LocusIterator { fullPileup.put(sample, new ReadBackedPileupImpl(location, pile)); } - updateReadStates(); // critical - must be called after we get the current state offsets and location + readStates.updateReadStates(); // critical - must be called after we get the current state offsets and location if (!fullPileup.isEmpty()) // if we got reads with non-D/N over the current position, we are done - nextAlignmentContext = new AlignmentContext(location, new ReadBackedPileupImpl(location, fullPileup), hasBeenSampled); - } - } - - /** - * Advances all fo the read states by one bp. After this call the read states are reflective - * of the next pileup. - */ - private void updateReadStates() { - for (final String sample : samples) { - Iterator it = readStates.iterator(sample); - while (it.hasNext()) { - AlignmentStateMachine state = it.next(); - CigarOperator op = state.stepForwardOnGenome(); - if (op == null) { - // we discard the read only when we are past its end AND indel at the end of the read (if any) was - // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe - // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. - it.remove(); // we've stepped off the end of the object - } - } + nextAlignmentContext = new AlignmentContext(location, new ReadBackedPileupImpl(location, fullPileup), false); } } diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 2dcf01d72..0a8d3a108 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -28,6 +28,7 @@ package org.broadinstitute.sting.utils.locusiterator; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.picard.util.PeekableIterator; +import net.sf.samtools.CigarOperator; import org.broadinstitute.sting.gatk.downsampling.Downsampler; import org.broadinstitute.sting.gatk.downsampling.LevelingDownsampler; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -48,11 +49,18 @@ import java.util.*; * Date: 1/5/13 * Time: 2:02 PM */ -class ReadStateManager { +final class ReadStateManager implements Iterable> { private final List samples; private final PeekableIterator iterator; private final SamplePartitioner samplePartitioner; - private final Map readStatesBySample = new HashMap(); + + /** + * A mapping from sample name -> the per sample read state manager that manages + * + * IT IS CRITICAL THAT THIS BE A LINKED HASH MAP, SO THAT THE ITERATION OF THE MAP OCCURS IN THE SAME + * ORDER AS THE ORIGINL SAMPLES + */ + private final Map readStatesBySample = new LinkedHashMap(); private LinkedList submittedReads; private final boolean keepSubmittedReads; @@ -70,6 +78,7 @@ class ReadStateManager { this.submittedReads = new LinkedList(); for (final String sample : samples) { + // because this is a linked hash map the order of iteration will be in sample order readStatesBySample.put(sample, new PerSampleReadStateManager(LIBSDownsamplingInfo)); } @@ -77,29 +86,16 @@ class ReadStateManager { } /** - * Returns a iterator over all the reads associated with the given sample. Note that remove() is implemented - * for this iterator; if present, total read states will be decremented. + * Returns a iterator over all the sample -> per-sample read state managers with each sample in this read state manager. * - * @param sample The sample. - * @return Iterator over the reads associated with that sample. + * The order of iteration is the same as the order of the samples provided upon construction to this + * ReadStateManager. + * + * @return Iterator over sample + per sample read state manager pairs for this read state manager. */ - public Iterator iterator(final String sample) { - // TODO -- why is this wrapped? - return new Iterator() { - private Iterator wrappedIterator = readStatesBySample.get(sample).iterator(); - - public boolean hasNext() { - return wrappedIterator.hasNext(); - } - - public AlignmentStateMachine next() { - return wrappedIterator.next(); - } - - public void remove() { - wrappedIterator.remove(); - } - }; + @Override + public Iterator> iterator() { + return readStatesBySample.entrySet().iterator(); } public boolean isEmpty() { @@ -126,10 +122,9 @@ class ReadStateManager { } public AlignmentStateMachine getFirst() { - for (final String sample : samples) { - PerSampleReadStateManager reads = readStatesBySample.get(sample); - if (!reads.isEmpty()) - return reads.peek(); + for ( final PerSampleReadStateManager manager : readStatesBySample.values() ) { + if ( ! manager.isEmpty() ) + return manager.peek(); } return null; } @@ -138,51 +133,65 @@ class ReadStateManager { return totalReadStates > 0 || iterator.hasNext(); } - // fast testing of position - /** - * TODO -- this function needs to be optimized - * - * Notes: - * -- the only place where it's called is in a block where we know isEmpty is false - * -- getFirst() is quite expensive, and it seems that we could cache this value in the outer - * block, and then pass this in as an argument - * - * @param read - * @return + * Advances all fo the read states by one bp. After this call the read states are reflective + * of the next pileup. */ - private boolean readIsPastCurrentPosition(GATKSAMRecord read) { - if (isEmpty()) - return false; - else { - final AlignmentStateMachine state = getFirst(); - final GATKSAMRecord ourRead = state.getRead(); - return read.getReferenceIndex() > ourRead.getReferenceIndex() || read.getAlignmentStart() > state.getGenomePosition(); + public void updateReadStates() { + for (final PerSampleReadStateManager readStateManager : readStatesBySample.values() ) { + final Iterator it = readStateManager.iterator(); + while (it.hasNext()) { + final AlignmentStateMachine state = it.next(); + final CigarOperator op = state.stepForwardOnGenome(); + if (op == null) { + // we discard the read only when we are past its end AND indel at the end of the read (if any) was + // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe + // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. + it.remove(); // we've stepped off the end of the object + } + } } } + /** + * Does read start at the same position as described by currentContextIndex and currentAlignmentStart? + * + * @param read the read we want to test + * @param currentContigIndex the contig index (from the read's getReferenceIndex) of the reads in this state manager + * @param currentAlignmentStart the alignment start of the of the left-most position on the + * genome of the reads in this read state manager + * @return true if read has contig index and start equal to the current ones + */ + private boolean readStartsAtCurrentPosition(final GATKSAMRecord read, final int currentContigIndex, final int currentAlignmentStart) { + return read.getAlignmentStart() == currentAlignmentStart && read.getReferenceIndex() == currentContigIndex; + } + + /** + * Pull all of the reads off the iterator that overlap the left-most position among all + * reads this ReadStateManager + */ public void collectPendingReads() { if (!iterator.hasNext()) return; - // the next record in the stream, peeked as to not remove it from the stream + // determine the left-most boundary that determines which reads to keep in this new pileup + final int firstContigIndex; + final int firstAlignmentStart; if ( isEmpty() ) { - final int firstContigIndex = iterator.peek().getReferenceIndex(); - final int firstAlignmentStart = iterator.peek().getAlignmentStart(); - while (iterator.hasNext() && iterator.peek().getReferenceIndex() == firstContigIndex && iterator.peek().getAlignmentStart() == firstAlignmentStart) { - submitRead(iterator.next()); - } + // there are no reads here, so our next state is the next read in the stream + firstContigIndex = iterator.peek().getReferenceIndex(); + firstAlignmentStart = iterator.peek().getAlignmentStart(); } else { - // Fast fail in the case that the read is past the current position. - if (readIsPastCurrentPosition(iterator.peek())) - return; - - while (iterator.hasNext() && !readIsPastCurrentPosition(iterator.peek())) { - submitRead(iterator.next()); - } + // there's a read in the system, so it's our targeted first read + final AlignmentStateMachine firstState = getFirst(); + firstContigIndex = firstState.getReferenceIndex(); + // note this isn't the alignment start of the read, but rather the alignment start position + firstAlignmentStart = firstState.getGenomePosition(); } - samplePartitioner.doneSubmittingReads(); + while ( iterator.hasNext() && readStartsAtCurrentPosition(iterator.peek(), firstContigIndex, firstAlignmentStart) ) { + submitRead(iterator.next()); + } for (final String sample : samples) { final Collection newReads = samplePartitioner.getReadsForSample(sample); @@ -271,11 +280,11 @@ class ReadStateManager { if (reads.isEmpty()) return; - Collection newReadStates = new LinkedList(); + final LinkedList newReadStates = new LinkedList(); - for (GATKSAMRecord read : reads) { - AlignmentStateMachine state = new AlignmentStateMachine(read); - if ( state.stepForwardOnGenome() != null ) + for (final GATKSAMRecord read : reads) { + final AlignmentStateMachine state = new AlignmentStateMachine(read); + if ( state.stepForwardOnGenome() != null ) // todo -- should be an assertion not a skip // explicitly filter out reads that are all insertions / soft clips newReadStates.add(state); } @@ -283,6 +292,7 @@ class ReadStateManager { readStates.addStatesAtNextAlignmentStart(newReadStates); } + // TODO -- refactor into separate class with pointer to ReadStateManager for updates to the total counts protected class PerSampleReadStateManager implements Iterable { private List> readStatesByAlignmentStart = new LinkedList>(); private final Downsampler> levelingDownsampler; @@ -295,12 +305,16 @@ class ReadStateManager { : null; } - public void addStatesAtNextAlignmentStart(Collection states) { + /** + * Assumes it can just keep the states linked lists without making a copy + * @param states + */ + public void addStatesAtNextAlignmentStart(LinkedList states) { if ( states.isEmpty() ) { return; } - readStatesByAlignmentStart.add(new LinkedList(states)); + readStatesByAlignmentStart.add(states); thisSampleReadStates += states.size(); totalReadStates += states.size(); diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java index 1db0605c7..76b324d85 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java @@ -71,7 +71,7 @@ public class ReadStateManagerUnitTest extends LocusIteratorByStateBaseTest { makeReads(); for ( ArrayList stackRecordStates : recordStatesByAlignmentStart ) { - perSampleReadStateManager.addStatesAtNextAlignmentStart(stackRecordStates); + perSampleReadStateManager.addStatesAtNextAlignmentStart(new LinkedList(stackRecordStates)); } // read state manager should have the right number of reads From 19288b007d77c597f75bf9ce639df9ebf6601709 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 12 Jan 2013 13:39:19 -0500 Subject: [PATCH 004/188] LIBS bugfix: kept reads now only (correctly) includes reads that at least passed the reservoir -- Added unit tests to ensure this behavior is correct --- .../utils/locusiterator/ReadStateManager.java | 12 ++- .../LocusIteratorByStateUnitTest.java | 93 +++++++++++++------ 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 0a8d3a108..955dbcef7 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -195,7 +195,15 @@ final class ReadStateManager implements Iterable newReads = samplePartitioner.getReadsForSample(sample); - PerSampleReadStateManager statesBySample = readStatesBySample.get(sample); + +// // if we're keeping reads, take the (potentially downsampled) list of new reads for this sample +// // and add to the list of reads. Note this may reorder the list of reads someone (it groups them +// // by sample, but it cannot change their absolute position on the genome as they all must +// // start at the current location + if ( keepSubmittedReads ) + submittedReads.addAll(newReads); + + final PerSampleReadStateManager statesBySample = readStatesBySample.get(sample); addReadsToSample(statesBySample, newReads); } @@ -208,8 +216,6 @@ final class ReadStateManager implements Iterable tests = new LinkedList(); - for ( final boolean doSampling : Arrays.asList(true, false) ) { - for ( final int nReadsPerLocus : Arrays.asList(1, 10) ) { + for ( final int downsampleTo : Arrays.asList(-1, 1, 2, 5, 10, 30)) { + for ( final int nReadsPerLocus : Arrays.asList(1, 10, 60) ) { for ( final int nLoci : Arrays.asList(1, 10, 25) ) { for ( final int nSamples : Arrays.asList(1, 2, 10) ) { for ( final boolean keepReads : Arrays.asList(true, false) ) { for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true, false) ) { -// for ( final int nReadsPerLocus : Arrays.asList(1) ) { -// for ( final int nLoci : Arrays.asList(1) ) { -// for ( final int nSamples : Arrays.asList(1) ) { -// for ( final boolean keepReads : Arrays.asList(true) ) { -// for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true) ) { - tests.add(new Object[]{nReadsPerLocus, nLoci, nSamples, keepReads, grabReadsAfterEachCycle, doSampling}); +// for ( final int downsampleTo : Arrays.asList(1)) { +// for ( final int nReadsPerLocus : Arrays.asList(10) ) { +// for ( final int nLoci : Arrays.asList(25) ) { +// for ( final int nSamples : Arrays.asList(1) ) { +// for ( final boolean keepReads : Arrays.asList(true) ) { +// for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true) ) { + tests.add(new Object[]{nReadsPerLocus, nLoci, nSamples, + keepReads, grabReadsAfterEachCycle, + downsampleTo}); } } } @@ -432,14 +436,15 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { return tests.toArray(new Object[][]{}); } - @Test(enabled = true && ! DEBUG, dataProvider = "LIBSKeepSubmittedReads") - public void testLIBSKeepSubmittedReads(final int nReadsPerLocus, - final int nLoci, - final int nSamples, - final boolean keepReads, - final boolean grabReadsAfterEachCycle, - final boolean downsample) { - logger.warn(String.format("testLIBSKeepSubmittedReads %d %d %d %b %b %b", nReadsPerLocus, nLoci, nSamples, keepReads, grabReadsAfterEachCycle, downsample)); + //@Test(enabled = true && ! DEBUG, dataProvider = "LIBS_ComplexPileupTests") + @Test(enabled = true && ! DEBUG, dataProvider = "LIBS_ComplexPileupTests") + public void testLIBS_ComplexPileupTests(final int nReadsPerLocus, + final int nLoci, + final int nSamples, + final boolean keepReads, + final boolean grabReadsAfterEachCycle, + final int downsampleTo) { + //logger.warn(String.format("testLIBSKeepSubmittedReads %d %d %d %b %b %b", nReadsPerLocus, nLoci, nSamples, keepReads, grabReadsAfterEachCycle, downsample)); final int readLength = 10; final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100000); @@ -453,10 +458,9 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { header.addReadGroup(rg); } - final int maxCoveragePerSampleAtLocus = nReadsPerLocus * readLength / 2; - final int maxDownsampledCoverage = Math.max(maxCoveragePerSampleAtLocus / 2, 1); + final boolean downsample = downsampleTo != -1; final DownsamplingMethod downsampler = downsample - ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, maxDownsampledCoverage, null, false) + ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) : new DownsamplingMethod(DownsampleType.NONE, null, null, false); final List reads = ArtificialSAMUtils.createReadStream(nReadsPerLocus, nLoci, header, 1, readLength); li = new LocusIteratorByState(new FakeCloseableIterator(reads.iterator()), @@ -472,6 +476,8 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { final AlignmentContext alignmentContext = li.next(); final ReadBackedPileup p = alignmentContext.getBasePileup(); + AssertWellOrderedPileup(p); + if ( downsample ) { // just not a safe test //Assert.assertTrue(p.getNumberOfElements() <= maxDownsampledCoverage * nSamples, "Too many reads at locus after downsampling"); @@ -480,22 +486,29 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { Assert.assertTrue(p.getNumberOfElements() >= minPileupSize); } + // the number of reads starting here + int nReadsStartingHere = 0; + for ( final GATKSAMRecord read : p.getReads() ) + if ( read.getAlignmentStart() == alignmentContext.getPosition() ) + nReadsStartingHere++; + + // we can have no more than maxDownsampledCoverage per sample + final int maxCoveragePerLocus = downsample ? downsampleTo : nReadsPerLocus; + Assert.assertTrue(nReadsStartingHere <= maxCoveragePerLocus * nSamples); + seenSoFar.addAll(p.getReads()); if ( keepReads && grabReadsAfterEachCycle ) { final List locusReads = li.transferReadsFromAllPreviousPileups(); - // the number of reads starting here - int nReadsStartingHere = 0; - for ( final GATKSAMRecord read : p.getReads() ) - if ( read.getAlignmentStart() == alignmentContext.getPosition() ) - nReadsStartingHere++; - if ( downsample ) + if ( downsample ) { // with downsampling we might have some reads here that were downsampled away - // in the pileup + // in the pileup. We want to ensure that no more than the max coverage per sample is added Assert.assertTrue(locusReads.size() >= nReadsStartingHere); - else + Assert.assertTrue(locusReads.size() <= maxCoveragePerLocus * nSamples); + } else { Assert.assertEquals(locusReads.size(), nReadsStartingHere); + } keptReads.addAll(locusReads); // check that all reads we've seen so far are in our keptReads @@ -543,6 +556,26 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { for ( final GATKSAMRecord read : seenSoFar ) { Assert.assertTrue(keptReads.contains(read), "A read that appeared in a pileup wasn't found in the kept reads: " + read); } + + if ( ! downsample ) { + // check that every read in the list of keep reads occurred at least once in one of the pileups + for ( final GATKSAMRecord keptRead : keptReads ) { + Assert.assertTrue(seenSoFar.contains(keptRead), "There's a read " + keptRead + " in our keptReads list that never appeared in any pileup"); + } + } + } + } + + private void AssertWellOrderedPileup(final ReadBackedPileup pileup) { + if ( ! pileup.isEmpty() ) { + int leftMostPos = -1; + + for ( final PileupElement pe : pileup ) { + Assert.assertTrue(pileup.getLocation().getContig().equals(pe.getRead().getReferenceName()), "ReadBackedPileup contains an element " + pe + " that's on a different contig than the pileup itself"); + Assert.assertTrue(pe.getRead().getAlignmentStart() >= leftMostPos, + "ReadBackedPileup contains an element " + pe + " whose read's alignment start " + pe.getRead().getAlignmentStart() + + " occurs before the leftmost position we've seen previously " + leftMostPos); + } } } } From a4334a67e088d9cd221dadc011edd1478dc7b28f Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 12 Jan 2013 19:22:36 -0500 Subject: [PATCH 005/188] SamplePartitioner optimizations and bugfixes -- Use a linked hash map instead of a hash map since we want to iterate through the map fairly often -- Ensure that we call doneSubmittingReads before getting reads for samples. This function call fell out before and since it wasn't enforced I only noticed the problem while writing comments -- Don't make unnecessary calls to contains for map. Just use get() and check that the result is null -- Use a LinkedList in PassThroughDownsampler, since this is faster for add() than the existing ArrayList, and we were's using random access to any resulting --- .../downsampling/PassThroughDownsampler.java | 14 +- .../utils/locusiterator/ReadStateManager.java | 10 +- .../locusiterator/SamplePartitioner.java | 124 +++++++++++++++--- 3 files changed, 122 insertions(+), 26 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/downsampling/PassThroughDownsampler.java b/public/java/src/org/broadinstitute/sting/gatk/downsampling/PassThroughDownsampler.java index 600834012..b06d5f5b4 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/downsampling/PassThroughDownsampler.java +++ b/public/java/src/org/broadinstitute/sting/gatk/downsampling/PassThroughDownsampler.java @@ -27,8 +27,8 @@ package org.broadinstitute.sting.gatk.downsampling; import net.sf.samtools.SAMRecord; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; /** @@ -41,7 +41,7 @@ import java.util.List; */ public class PassThroughDownsampler implements ReadsDownsampler { - private ArrayList selectedReads; + private LinkedList selectedReads; public PassThroughDownsampler() { clear(); @@ -59,9 +59,13 @@ public class PassThroughDownsampler implements ReadsDownsam } public boolean hasFinalizedItems() { - return selectedReads.size() > 0; + return ! selectedReads.isEmpty(); } + /** + * Note that this list is a linked list and so doesn't support fast random access + * @return + */ public List consumeFinalizedItems() { // pass by reference rather than make a copy, for speed List downsampledItems = selectedReads; @@ -74,7 +78,7 @@ public class PassThroughDownsampler implements ReadsDownsam } public T peekFinalized() { - return selectedReads.isEmpty() ? null : selectedReads.get(0); + return selectedReads.isEmpty() ? null : selectedReads.getFirst(); } public T peekPending() { @@ -90,7 +94,7 @@ public class PassThroughDownsampler implements ReadsDownsam } public void clear() { - selectedReads = new ArrayList(); + selectedReads = new LinkedList(); } public void reset() { diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 955dbcef7..b5dbe2ddb 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -193,13 +193,15 @@ final class ReadStateManager implements Iterable newReads = samplePartitioner.getReadsForSample(sample); -// // if we're keeping reads, take the (potentially downsampled) list of new reads for this sample -// // and add to the list of reads. Note this may reorder the list of reads someone (it groups them -// // by sample, but it cannot change their absolute position on the genome as they all must -// // start at the current location + // if we're keeping reads, take the (potentially downsampled) list of new reads for this sample + // and add to the list of reads. Note this may reorder the list of reads someone (it groups them + // by sample, but it cannot change their absolute position on the genome as they all must + // start at the current location if ( keepSubmittedReads ) submittedReads.addAll(newReads); diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java index 1653c6a92..7dada292b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java @@ -25,6 +25,8 @@ package org.broadinstitute.sting.utils.locusiterator; +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.downsampling.Downsampler; import org.broadinstitute.sting.gatk.downsampling.PassThroughDownsampler; @@ -33,49 +35,137 @@ import org.broadinstitute.sting.gatk.downsampling.ReservoirDownsampler; import java.util.*; /** - * Divides reads by sample and (if requested) does a preliminary downsampling pass with a ReservoirDownsampler. + * Divides reads by sample and (if requested) does a preliminary downsampling pass + * with a ReservoirDownsampler. * * Note: stores reads by sample ID string, not by sample object */ class SamplePartitioner { - private Map> readsBySample; + /** + * Map from sample name (as a string) to a downsampler of reads for that sample + */ + final private Map> readsBySample; + /** + * Are we in a state where we're done submitting reads and have semi-finalized the + * underlying per sample downsampler? + */ + boolean doneSubmittingReads = false; + + /** + * Create a new SamplePartitioner capable of splitting reads up into buckets of reads for + * each sample in samples, and perform a preliminary downsampling of these reads + * (separately for each sample) if downsampling is requested in LIBSDownsamplingInfo + * + * Note that samples must be comprehensive, in that all reads every submitted to this + * partitioner must come from one of the samples provided here. If not, submitRead + * will throw an exception. Duplicates in the list of samples will be ignored + * + * @param LIBSDownsamplingInfo do we want to downsample, and if so to what coverage? + * @param samples the complete list of samples we're going to partition reads into + */ + @Ensures({ + "readsBySample != null", + "! readsBySample.isEmpty()", + "readsBySample.size() == new HashSet(samples).size()" + }) public SamplePartitioner(final LIBSDownsamplingInfo LIBSDownsamplingInfo, final List samples) { - readsBySample = new HashMap>(samples.size()); - for ( String sample : samples ) { + if ( LIBSDownsamplingInfo == null ) throw new IllegalArgumentException("LIBSDownsamplingInfo cannot be null"); + if ( samples == null || samples.isEmpty() ) throw new IllegalArgumentException("samples must be a non-null, non-empty list but got " + samples); + + readsBySample = new LinkedHashMap>(samples.size()); + for ( final String sample : samples ) { readsBySample.put(sample, createDownsampler(LIBSDownsamplingInfo)); } } + /** + * Create a new, ready to use downsampler based on the parameters in LIBSDownsamplingInfo + * @param LIBSDownsamplingInfo the parameters to use in creating the downsampler + * @return a downsampler appropriate for LIBSDownsamplingInfo. If no downsampling is requested, + * uses the PassThroughDownsampler, which does nothing at all. + */ + @Requires("LIBSDownsamplingInfo != null") + @Ensures("result != null") private Downsampler createDownsampler(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { return LIBSDownsamplingInfo.isPerformDownsampling() ? new ReservoirDownsampler(LIBSDownsamplingInfo.getToCoverage()) : new PassThroughDownsampler(); } - public void submitRead(T read) { - String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null; - if (readsBySample.containsKey(sampleName)) - readsBySample.get(sampleName).submit(read); + /** + * Offer this read to the partitioner, putting it into the bucket of reads for the sample + * of read (obtained via the read's read group). + * + * If the read group is missing, uses the special "null" read group + * + * @throws IllegalStateException if the sample of read wasn't present in the original + * set of samples provided to this SamplePartitioner at construction + * + * @param read the read to add to the sample's list of reads + */ + @Requires("read != null") + @Ensures("doneSubmittingReads == false") + public void submitRead(final T read) { + final String sampleName = read.getReadGroup() != null ? read.getReadGroup().getSample() : null; + final Downsampler downsampler = readsBySample.get(sampleName); + if ( downsampler == null ) + throw new IllegalStateException("Offered read with sample name " + sampleName + " to SamplePartitioner " + + "but this sample wasn't provided as one of possible samples at construction"); + + downsampler.submit(read); + doneSubmittingReads = false; } + /** + * Tell this partitioner that all reads in this cycle have been submitted, so that we + * can finalize whatever downsampling is required by each sample. + * + * Note that we *must* call this function before getReadsForSample, or else that + * function will exception out. + */ + @Ensures("doneSubmittingReads == true") public void doneSubmittingReads() { - for ( Map.Entry> perSampleReads : readsBySample.entrySet() ) { - perSampleReads.getValue().signalEndOfInput(); + for ( final Downsampler downsampler : readsBySample.values() ) { + downsampler.signalEndOfInput(); } + doneSubmittingReads = true; } - public Collection getReadsForSample(String sampleName) { - if ( ! readsBySample.containsKey(sampleName) ) - throw new NoSuchElementException("Sample name not found"); + /** + * Get the final collection of reads for this sample for this cycle + * + * The cycle is defined as all of the reads that occur between + * the first call to submitRead until doneSubmittingReads is called. At that + * point additional downsampling may occur (depending on construction arguments) + * and that set of reads is returned here. + * + * Note that this function can only be called once per cycle, as underlying + * collection of reads is cleared. + * + * @param sampleName the sample we want reads for, must be present in the original samples + * @return a non-null collection of reads for sample in this cycle + */ + @Ensures("result != null") + public Collection getReadsForSample(final String sampleName) { + if ( ! doneSubmittingReads ) throw new IllegalStateException("getReadsForSample called before doneSubmittingReads was called"); - return readsBySample.get(sampleName).consumeFinalizedItems(); + final Downsampler downsampler = readsBySample.get(sampleName); + if ( downsampler == null ) throw new NoSuchElementException("Sample name not found"); + + return downsampler.consumeFinalizedItems(); } + /** + * Resets this SamplePartitioner, indicating that we're starting a new + * cycle of adding reads to each underlying downsampler. + */ + @Ensures("doneSubmittingReads == false") public void reset() { - for ( Map.Entry> perSampleReads : readsBySample.entrySet() ) { - perSampleReads.getValue().clear(); - perSampleReads.getValue().reset(); + for ( final Downsampler downsampler : readsBySample.values() ) { + downsampler.clear(); + downsampler.reset(); } + doneSubmittingReads = false; } } From 5c2799554aca87f3a5a0d95c609baff574f5e261 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 13 Jan 2013 12:23:51 -0500 Subject: [PATCH 006/188] Refactor updateReadStates into PerSampleReadStateManager, add tracking of downsampling rate --- .../utils/locusiterator/LIBSPerformance.java | 4 +- .../utils/locusiterator/ReadStateManager.java | 70 ++++++++++++++----- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java index 0985ed196..2d074f420 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java @@ -63,6 +63,8 @@ public class LIBSPerformance extends CommandLineProgram { @Argument(fullName = "L", shortName = "L", doc = "Query location", required = false) public String location = null; + @Argument(fullName = "dt", shortName = "dt", doc = "Enable downsampling", required = false) + public boolean downsample = false; @Override public int execute() throws IOException { @@ -86,7 +88,7 @@ public class LIBSPerformance extends CommandLineProgram { for ( final SAMReadGroupRecord rg : reader.getFileHeader().getReadGroups() ) samples.add(rg.getSample()); - final LIBSDownsamplingInfo ds = new LIBSDownsamplingInfo(false, -1); + final LIBSDownsamplingInfo ds = new LIBSDownsamplingInfo(downsample, 250); final LocusIteratorByState libs = new LocusIteratorByState( diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index b5dbe2ddb..3276291ef 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -29,6 +29,7 @@ import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.picard.util.PeekableIterator; import net.sf.samtools.CigarOperator; +import org.apache.log4j.Logger; import org.broadinstitute.sting.gatk.downsampling.Downsampler; import org.broadinstitute.sting.gatk.downsampling.LevelingDownsampler; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -50,6 +51,8 @@ import java.util.*; * Time: 2:02 PM */ final class ReadStateManager implements Iterable> { + private final static Logger logger = Logger.getLogger(ReadStateManager.class); + private final static boolean CAPTURE_DOWNSAMPLING_STATS = true; private final List samples; private final PeekableIterator iterator; private final SamplePartitioner samplePartitioner; @@ -138,18 +141,8 @@ final class ReadStateManager implements Iterable it = readStateManager.iterator(); - while (it.hasNext()) { - final AlignmentStateMachine state = it.next(); - final CigarOperator op = state.stepForwardOnGenome(); - if (op == null) { - // we discard the read only when we are past its end AND indel at the end of the read (if any) was - // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe - // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. - it.remove(); // we've stepped off the end of the object - } - } + for (final PerSampleReadStateManager perSampleReadStateManager : readStatesBySample.values() ) { + perSampleReadStateManager.updateReadStates(); } } @@ -301,13 +294,17 @@ final class ReadStateManager implements Iterable { + protected final class PerSampleReadStateManager implements Iterable { private List> readStatesByAlignmentStart = new LinkedList>(); private final Downsampler> levelingDownsampler; - private int thisSampleReadStates = 0; + private final int downsamplingTarget; + private int nSitesNeedingDownsampling = 0; + private int nSites = 0; + public PerSampleReadStateManager(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { + this.downsamplingTarget = LIBSDownsamplingInfo.isPerformDownsampling() ? LIBSDownsamplingInfo.getToCoverage() : -1; this.levelingDownsampler = LIBSDownsamplingInfo.isPerformDownsampling() ? new LevelingDownsampler, AlignmentStateMachine>(LIBSDownsamplingInfo.getToCoverage()) : null; @@ -326,7 +323,8 @@ final class ReadStateManager implements Iterable downsamplingTarget; + if ( downsampling ) { + nSitesNeedingDownsampling++; + message = "Downsampling"; + } + + if ( downsampling || nSites % 10000 == 0 ) + logger.info(String.format("%20s at %s: coverage=%d, max=%d, fraction of downsampled sites=%.2e", + message, loc, thisSampleReadStates, downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites))); + } + } + public boolean isEmpty() { return readStatesByAlignmentStart.isEmpty(); } @@ -351,11 +371,25 @@ final class ReadStateManager implements Iterable it = iterator(); + while (it.hasNext()) { + final AlignmentStateMachine state = it.next(); + final CigarOperator op = state.stepForwardOnGenome(); + if (op == null) { + // we discard the read only when we are past its end AND indel at the end of the read (if any) was + // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe + // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. + it.remove(); // we've stepped off the end of the object + } + } + } + public Iterator iterator() { return new Iterator() { - private Iterator> alignmentStartIterator = readStatesByAlignmentStart.iterator(); - private LinkedList currentPositionReadStates = null; - private Iterator currentPositionReadStatesIterator = null; + private final Iterator> alignmentStartIterator = readStatesByAlignmentStart.iterator(); + private LinkedList currentPositionReadStates; + private Iterator currentPositionReadStatesIterator; public boolean hasNext() { return alignmentStartIterator.hasNext() || From 5a5422e4f8220ecde133490eeef6b58fa3084397 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 13 Jan 2013 13:02:17 -0500 Subject: [PATCH 007/188] Refactor PerSampleReadStates into a separate class -- No longer update the total counts in each per-sample state manager, but instead return delta counts that are updated by the overall ReadStateManager -- One step on the way to improving the underlying representation of the data in PerSampleReadStateManager -- Make LocusIteratorByState final --- .../locusiterator/LocusIteratorByState.java | 6 +- .../PerSampleReadStateManager.java | 203 ++++++++++++++++++ .../utils/locusiterator/ReadStateManager.java | 138 +----------- .../LocusIteratorByStateUnitTest.java | 5 +- ...=> PerSampleReadStateManagerUnitTest.java} | 11 +- 5 files changed, 214 insertions(+), 149 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java rename public/java/test/org/broadinstitute/sting/utils/locusiterator/{ReadStateManagerUnitTest.java => PerSampleReadStateManagerUnitTest.java} (92%) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java index 9499bfa35..e7b75f1f2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java @@ -65,7 +65,7 @@ import java.util.*; * occurs, if requested. This allows users of LIBS to see both a ReadBackedPileup view of the data as well as * a stream of unique, sorted reads */ -public class LocusIteratorByState extends LocusIterator { +public final class LocusIteratorByState extends LocusIterator { /** * our log, which we want to capture anything from this class */ @@ -233,9 +233,9 @@ public class LocusIteratorByState extends LocusIterator { final GenomeLoc location = getLocation(); final Map fullPileup = new HashMap(); - for (final Map.Entry sampleStatePair : readStates ) { + for (final Map.Entry sampleStatePair : readStates ) { final String sample = sampleStatePair.getKey(); - final ReadStateManager.PerSampleReadStateManager readState = sampleStatePair.getValue(); + final PerSampleReadStateManager readState = sampleStatePair.getValue(); final Iterator iterator = readState.iterator(); final List pile = new ArrayList(readState.size()); diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java new file mode 100644 index 000000000..c2a47bbdb --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java @@ -0,0 +1,203 @@ +/* + * 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.utils.locusiterator; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import net.sf.samtools.CigarOperator; +import org.apache.log4j.Logger; +import org.broadinstitute.sting.gatk.downsampling.Downsampler; +import org.broadinstitute.sting.gatk.downsampling.LevelingDownsampler; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * ReadStateManager for a single sample + * + * User: depristo + * Date: 1/13/13 + * Time: 12:28 PM + */ +final class PerSampleReadStateManager implements Iterable { + private final static Logger logger = Logger.getLogger(ReadStateManager.class); + private final static boolean CAPTURE_DOWNSAMPLING_STATS = true; + + private List> readStatesByAlignmentStart = new LinkedList>(); + private final Downsampler> levelingDownsampler; + private int thisSampleReadStates = 0; + + private final int downsamplingTarget; + private int nSitesNeedingDownsampling = 0; + private int nSites = 0; + + public PerSampleReadStateManager(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { + this.downsamplingTarget = LIBSDownsamplingInfo.isPerformDownsampling() ? LIBSDownsamplingInfo.getToCoverage() : -1; + this.levelingDownsampler = LIBSDownsamplingInfo.isPerformDownsampling() + ? new LevelingDownsampler, AlignmentStateMachine>(LIBSDownsamplingInfo.getToCoverage()) + : null; + } + + /** + * Assumes it can just keep the states linked lists without making a copy + * @param states the new states to add to this manager + * @return The change in the number of states, after including states and potentially downsampling + */ + @Requires("states != null") + @Ensures("result >= 0") + public int addStatesAtNextAlignmentStart(LinkedList states) { + if ( states.isEmpty() ) { + return 0; + } + + readStatesByAlignmentStart.add(states); + int nStatesAdded = states.size(); + + if ( isDownsampling() ) { + captureDownsamplingStats(); + levelingDownsampler.submit(readStatesByAlignmentStart); + levelingDownsampler.signalEndOfInput(); + + nStatesAdded -= levelingDownsampler.getNumberOfDiscardedItems(); + + // use returned List directly rather than make a copy, for efficiency's sake + readStatesByAlignmentStart = levelingDownsampler.consumeFinalizedItems(); + levelingDownsampler.reset(); + } + + thisSampleReadStates += nStatesAdded; + return nStatesAdded; + } + + private boolean isDownsampling() { + return levelingDownsampler != null; + } + + private AlignmentStateMachine getFirst() { + if (readStatesByAlignmentStart.isEmpty()) + return null; + else + return readStatesByAlignmentStart.get(0).getFirst(); + } + + @Requires("isDownsampling()") + private void captureDownsamplingStats() { + if ( CAPTURE_DOWNSAMPLING_STATS ) { + nSites++; + final int loc = getFirst().getGenomePosition(); + String message = "Pass through"; + final boolean downsampling = thisSampleReadStates > downsamplingTarget; + if ( downsampling ) { + nSitesNeedingDownsampling++; + message = "Downsampling"; + } + + if ( downsampling || nSites % 10000 == 0 ) + logger.info(String.format("%20s at %s: coverage=%d, max=%d, fraction of downsampled sites=%.2e", + message, loc, thisSampleReadStates, downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites))); + } + } + + /** + * Is there at least one alignment for this sample in this manager? + * @return true if there's at least one alignment, false otherwise + */ + public boolean isEmpty() { + return readStatesByAlignmentStart.isEmpty(); + } + + public AlignmentStateMachine peek() { + return isEmpty() ? null : readStatesByAlignmentStart.get(0).peek(); + } + + /** + * Get the number of read states currently in this manager + * @return the number of read states + */ + @Ensures("result >= 0") + public int size() { + return thisSampleReadStates; + } + + /** + * Advances all read states forward by one element, removing states that are + * no long aligned to the current position. + * @return the number of states we're removed after advancing + */ + public int updateReadStates() { + int nRemoved = 0; + final Iterator it = iterator(); + while (it.hasNext()) { + final AlignmentStateMachine state = it.next(); + final CigarOperator op = state.stepForwardOnGenome(); + if (op == null) { + // we discard the read only when we are past its end AND indel at the end of the read (if any) was + // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe + // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. + it.remove(); // we've stepped off the end of the object + nRemoved++; + } + } + + return nRemoved; + } + + // todo -- reimplement + public Iterator iterator() { + return new Iterator() { + private final Iterator> alignmentStartIterator = readStatesByAlignmentStart.iterator(); + private LinkedList currentPositionReadStates; + private Iterator currentPositionReadStatesIterator; + + @Override + public boolean hasNext() { + return alignmentStartIterator.hasNext() || + (currentPositionReadStatesIterator != null && currentPositionReadStatesIterator.hasNext()); + } + + @Override + public AlignmentStateMachine next() { + if ( currentPositionReadStatesIterator == null || ! currentPositionReadStatesIterator.hasNext() ) { + currentPositionReadStates = alignmentStartIterator.next(); + currentPositionReadStatesIterator = currentPositionReadStates.iterator(); + } + + return currentPositionReadStatesIterator.next(); + } + + @Override + public void remove() { + currentPositionReadStatesIterator.remove(); + thisSampleReadStates--; + + if ( currentPositionReadStates.isEmpty() ) { + alignmentStartIterator.remove(); + } + } + }; + } +} diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 3276291ef..4011875a6 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -28,10 +28,7 @@ package org.broadinstitute.sting.utils.locusiterator; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.picard.util.PeekableIterator; -import net.sf.samtools.CigarOperator; import org.apache.log4j.Logger; -import org.broadinstitute.sting.gatk.downsampling.Downsampler; -import org.broadinstitute.sting.gatk.downsampling.LevelingDownsampler; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import java.util.*; @@ -50,9 +47,7 @@ import java.util.*; * Date: 1/5/13 * Time: 2:02 PM */ -final class ReadStateManager implements Iterable> { - private final static Logger logger = Logger.getLogger(ReadStateManager.class); - private final static boolean CAPTURE_DOWNSAMPLING_STATS = true; +final class ReadStateManager implements Iterable> { private final List samples; private final PeekableIterator iterator; private final SamplePartitioner samplePartitioner; @@ -97,7 +92,7 @@ final class ReadStateManager implements Iterable> iterator() { + public Iterator> iterator() { return readStatesBySample.entrySet().iterator(); } @@ -142,7 +137,7 @@ final class ReadStateManager implements Iterable { - private List> readStatesByAlignmentStart = new LinkedList>(); - private final Downsampler> levelingDownsampler; - private int thisSampleReadStates = 0; - - private final int downsamplingTarget; - private int nSitesNeedingDownsampling = 0; - private int nSites = 0; - - public PerSampleReadStateManager(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { - this.downsamplingTarget = LIBSDownsamplingInfo.isPerformDownsampling() ? LIBSDownsamplingInfo.getToCoverage() : -1; - this.levelingDownsampler = LIBSDownsamplingInfo.isPerformDownsampling() - ? new LevelingDownsampler, AlignmentStateMachine>(LIBSDownsamplingInfo.getToCoverage()) - : null; - } - - /** - * Assumes it can just keep the states linked lists without making a copy - * @param states - */ - public void addStatesAtNextAlignmentStart(LinkedList states) { - if ( states.isEmpty() ) { - return; - } - - readStatesByAlignmentStart.add(states); - thisSampleReadStates += states.size(); - totalReadStates += states.size(); - - if ( isDownsampling() ) { - captureDownsamplingStats(); - levelingDownsampler.submit(readStatesByAlignmentStart); - levelingDownsampler.signalEndOfInput(); - - thisSampleReadStates -= levelingDownsampler.getNumberOfDiscardedItems(); - totalReadStates -= levelingDownsampler.getNumberOfDiscardedItems(); - - // use returned List directly rather than make a copy, for efficiency's sake - readStatesByAlignmentStart = levelingDownsampler.consumeFinalizedItems(); - levelingDownsampler.reset(); - } - } - - private boolean isDownsampling() { - return levelingDownsampler != null; - } - - @Requires("isDownsampling()") - private void captureDownsamplingStats() { - if ( CAPTURE_DOWNSAMPLING_STATS ) { - nSites++; - final int loc = getFirst().getGenomePosition(); - String message = "Pass through"; - final boolean downsampling = thisSampleReadStates > downsamplingTarget; - if ( downsampling ) { - nSitesNeedingDownsampling++; - message = "Downsampling"; - } - - if ( downsampling || nSites % 10000 == 0 ) - logger.info(String.format("%20s at %s: coverage=%d, max=%d, fraction of downsampled sites=%.2e", - message, loc, thisSampleReadStates, downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites))); - } - } - - public boolean isEmpty() { - return readStatesByAlignmentStart.isEmpty(); - } - - public AlignmentStateMachine peek() { - return isEmpty() ? null : readStatesByAlignmentStart.get(0).peek(); - } - - public int size() { - return thisSampleReadStates; - } - - public void updateReadStates() { - final Iterator it = iterator(); - while (it.hasNext()) { - final AlignmentStateMachine state = it.next(); - final CigarOperator op = state.stepForwardOnGenome(); - if (op == null) { - // we discard the read only when we are past its end AND indel at the end of the read (if any) was - // already processed. Keeping the read state that returned null upon stepForwardOnGenome() is safe - // as the next call to stepForwardOnGenome() will return null again AND will clear hadIndel() flag. - it.remove(); // we've stepped off the end of the object - } - } - } - - public Iterator iterator() { - return new Iterator() { - private final Iterator> alignmentStartIterator = readStatesByAlignmentStart.iterator(); - private LinkedList currentPositionReadStates; - private Iterator currentPositionReadStatesIterator; - - public boolean hasNext() { - return alignmentStartIterator.hasNext() || - (currentPositionReadStatesIterator != null && currentPositionReadStatesIterator.hasNext()); - } - - public AlignmentStateMachine next() { - if ( currentPositionReadStatesIterator == null || ! currentPositionReadStatesIterator.hasNext() ) { - currentPositionReadStates = alignmentStartIterator.next(); - currentPositionReadStatesIterator = currentPositionReadStates.iterator(); - } - - return currentPositionReadStatesIterator.next(); - } - - public void remove() { - currentPositionReadStatesIterator.remove(); - thisSampleReadStates--; - totalReadStates--; - - if ( currentPositionReadStates.isEmpty() ) { - alignmentStartIterator.remove(); - } - } - }; - } + totalReadStates += readStates.addStatesAtNextAlignmentStart(newReadStates); } } diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index 727023b83..7ae2d97a1 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -418,8 +418,8 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { for ( final boolean keepReads : Arrays.asList(true, false) ) { for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true, false) ) { // for ( final int downsampleTo : Arrays.asList(1)) { -// for ( final int nReadsPerLocus : Arrays.asList(10) ) { -// for ( final int nLoci : Arrays.asList(25) ) { +// for ( final int nReadsPerLocus : Arrays.asList(1) ) { +// for ( final int nLoci : Arrays.asList(1) ) { // for ( final int nSamples : Arrays.asList(1) ) { // for ( final boolean keepReads : Arrays.asList(true) ) { // for ( final boolean grabReadsAfterEachCycle : Arrays.asList(true) ) { @@ -436,7 +436,6 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { return tests.toArray(new Object[][]{}); } - //@Test(enabled = true && ! DEBUG, dataProvider = "LIBS_ComplexPileupTests") @Test(enabled = true && ! DEBUG, dataProvider = "LIBS_ComplexPileupTests") public void testLIBS_ComplexPileupTests(final int nReadsPerLocus, final int nLoci, diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java similarity index 92% rename from public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java index 76b324d85..b9f2fb29a 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/ReadStateManagerUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java @@ -38,11 +38,7 @@ import java.util.*; /** * testing of the new (non-legacy) version of LocusIteratorByState */ -public class ReadStateManagerUnitTest extends LocusIteratorByStateBaseTest { - /////////////////////////////////////// - // Read State Manager Tests // - /////////////////////////////////////// - +public class PerSampleReadStateManagerUnitTest extends LocusIteratorByStateBaseTest { private class PerSampleReadStateManagerTest extends TestDataProvider { private List readCountsPerAlignmentStart; private List reads; @@ -63,10 +59,7 @@ public class ReadStateManagerUnitTest extends LocusIteratorByStateBaseTest { } public void run() { - final List samples = LocusIteratorByState.sampleListForSAMWithoutReadGroups(); - final Iterator iterator = new LinkedList().iterator(); - ReadStateManager readStateManager = new ReadStateManager(iterator, samples, LIBSDownsamplingInfo.NO_DOWNSAMPLING, false); - ReadStateManager.PerSampleReadStateManager perSampleReadStateManager = readStateManager.new PerSampleReadStateManager(LIBSDownsamplingInfo.NO_DOWNSAMPLING); + PerSampleReadStateManager perSampleReadStateManager = new PerSampleReadStateManager(LIBSDownsamplingInfo.NO_DOWNSAMPLING); makeReads(); From c7f0ca8ac53e320d2762da917158be51a9b2d8ae Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 13 Jan 2013 14:36:25 -0500 Subject: [PATCH 008/188] Optimization for LIBS: PerSampleReadStateManager now uses a simple LinkedList of AlignmentStateMachine -- Instead of storing a list of list of alignment starts, which is expensive to manipulate, we instead store a linear list of alignment starts. Not grouped as previously. This enables us to simplify iteration and update operations, making them much faster -- Critically, the downsampler still requires this list of list. We convert back and forth between these two representations as required, which is very rarely for normal data sets (WGS NA12878 on chr20 is 0.2%, 4x WGS is even less). --- .../PerSampleReadStateManager.java | 170 ++++++++++++------ .../utils/locusiterator/ReadStateManager.java | 2 +- 2 files changed, 115 insertions(+), 57 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java index c2a47bbdb..3f3bc706f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java @@ -26,6 +26,7 @@ package org.broadinstitute.sting.utils.locusiterator; import com.google.java.contract.Ensures; +import com.google.java.contract.Invariant; import com.google.java.contract.Requires; import net.sf.samtools.CigarOperator; import org.apache.log4j.Logger; @@ -43,18 +44,42 @@ import java.util.List; * Date: 1/13/13 * Time: 12:28 PM */ +@Invariant({ + "readStartsAreWellOrdered()", + "! isDownsampling() || downsamplingTarget > 0", + "nSites >= 0", + "nSitesNeedingDownsampling >= 0", + "nSitesNeedingDownsampling <= nSites" +}) final class PerSampleReadStateManager implements Iterable { private final static Logger logger = Logger.getLogger(ReadStateManager.class); - private final static boolean CAPTURE_DOWNSAMPLING_STATS = true; + private final static boolean CAPTURE_DOWNSAMPLING_STATS = false; + + /** + * A list (potentially empty) of alignment state machines. + * + * The state machines must be ordered by the alignment start of their underlying reads, with the + * lowest alignment starts on the left, and the largest on the right + */ + private LinkedList readStatesByAlignmentStart = new LinkedList(); - private List> readStatesByAlignmentStart = new LinkedList>(); private final Downsampler> levelingDownsampler; - private int thisSampleReadStates = 0; - private final int downsamplingTarget; + + /** + * The number of sites where downsampling has been invoked + */ private int nSitesNeedingDownsampling = 0; + + /** + * The number of sites we've visited + */ private int nSites = 0; + /** + * Create a new PerSampleReadStateManager with downsampling parameters as requested by LIBSDownsamplingInfo + * @param LIBSDownsamplingInfo the downsampling params we want to use + */ public PerSampleReadStateManager(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { this.downsamplingTarget = LIBSDownsamplingInfo.isPerformDownsampling() ? LIBSDownsamplingInfo.getToCoverage() : -1; this.levelingDownsampler = LIBSDownsamplingInfo.isPerformDownsampling() @@ -62,55 +87,118 @@ final class PerSampleReadStateManager implements Iterable : null; } + /** + * Group the underlying readStatesByAlignmentStart into a list of list of alignment state machines, + * where each list contains machines with a unique genome site. The outer list is ordered + * by alignment start. + * + * For example, if the flat list has alignment starts [10, 10, 11, 12, 12, 13] then + * the resulting grouping will be [[10, 10], [11], [12, 12], [13]]. + * + * @return a non-null list of lists + */ + @Ensures("result != null") + private List> groupByAlignmentStart() { + final LinkedList> grouped = new LinkedList>(); + + AlignmentStateMachine last = null; + for ( final AlignmentStateMachine stateMachine : readStatesByAlignmentStart ) { + if ( last == null || stateMachine.getGenomeOffset() != last.getGenomeOffset() ) { + // we've advanced to a place where the state machine has a different state, + // so start a new list + grouped.add(new LinkedList()); + last = stateMachine; + } + grouped.getLast().add(stateMachine); + } + + return grouped; + } + + /** + * Flattens the grouped list of list of alignment state machines into a single list in order + * @return a non-null list contains the state machines + */ + @Ensures("result != null") + private LinkedList flattenByAlignmentStart(final List> grouped) { + final LinkedList flat = new LinkedList(); + for ( final List l : grouped ) + flat.addAll(l); + return flat; + } + + /** + * Test that the reads are ordered by their alignment starts + * @return true if well ordered, false otherwise + */ + private boolean readStartsAreWellOrdered() { + int lastStart = -1; + for ( final AlignmentStateMachine machine : readStatesByAlignmentStart ) { + if ( lastStart > machine.getRead().getAlignmentStart() ) + return false; + lastStart = machine.getRead().getAlignmentStart(); + } + return true; + } + /** * Assumes it can just keep the states linked lists without making a copy * @param states the new states to add to this manager - * @return The change in the number of states, after including states and potentially downsampling + * @return The change in the number of states, after including states and potentially downsampling. Note + * that this return result might be negative, if downsampling is enabled, as we might drop + * more sites than have been added by the downsampler */ @Requires("states != null") - @Ensures("result >= 0") - public int addStatesAtNextAlignmentStart(LinkedList states) { + public int addStatesAtNextAlignmentStart(final LinkedList states) { if ( states.isEmpty() ) { return 0; } - readStatesByAlignmentStart.add(states); + readStatesByAlignmentStart.addAll(states); int nStatesAdded = states.size(); - if ( isDownsampling() ) { + if ( isDownsampling() && readStatesByAlignmentStart.size() > downsamplingTarget ) { + // only go into the downsampling branch if we are downsampling and the coverage > the target captureDownsamplingStats(); - levelingDownsampler.submit(readStatesByAlignmentStart); + levelingDownsampler.submit(groupByAlignmentStart()); levelingDownsampler.signalEndOfInput(); nStatesAdded -= levelingDownsampler.getNumberOfDiscardedItems(); // use returned List directly rather than make a copy, for efficiency's sake - readStatesByAlignmentStart = levelingDownsampler.consumeFinalizedItems(); + readStatesByAlignmentStart = flattenByAlignmentStart(levelingDownsampler.consumeFinalizedItems()); levelingDownsampler.reset(); } - thisSampleReadStates += nStatesAdded; return nStatesAdded; } + /** + * Is downsampling enabled for this manager? + * @return true if we are downsampling, false otherwise + */ private boolean isDownsampling() { return levelingDownsampler != null; } - private AlignmentStateMachine getFirst() { - if (readStatesByAlignmentStart.isEmpty()) - return null; - else - return readStatesByAlignmentStart.get(0).getFirst(); + /** + * Get the leftmost alignment state machine, or null if the read states is empty + * @return a potentially null AlignmentStateMachine + */ + public AlignmentStateMachine getFirst() { + return isEmpty() ? null : readStatesByAlignmentStart.getFirst(); } + /** + * Capture some statistics about the behavior of the downsampling, but only if CAPTURE_DOWNSAMPLING_STATS is true + */ @Requires("isDownsampling()") private void captureDownsamplingStats() { if ( CAPTURE_DOWNSAMPLING_STATS ) { nSites++; final int loc = getFirst().getGenomePosition(); String message = "Pass through"; - final boolean downsampling = thisSampleReadStates > downsamplingTarget; + final boolean downsampling = size() > downsamplingTarget; if ( downsampling ) { nSitesNeedingDownsampling++; message = "Downsampling"; @@ -118,7 +206,7 @@ final class PerSampleReadStateManager implements Iterable if ( downsampling || nSites % 10000 == 0 ) logger.info(String.format("%20s at %s: coverage=%d, max=%d, fraction of downsampled sites=%.2e", - message, loc, thisSampleReadStates, downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites))); + message, loc, size(), downsamplingTarget, (1.0 * nSitesNeedingDownsampling / nSites))); } } @@ -130,17 +218,13 @@ final class PerSampleReadStateManager implements Iterable return readStatesByAlignmentStart.isEmpty(); } - public AlignmentStateMachine peek() { - return isEmpty() ? null : readStatesByAlignmentStart.get(0).peek(); - } - /** * Get the number of read states currently in this manager * @return the number of read states */ @Ensures("result >= 0") public int size() { - return thisSampleReadStates; + return readStatesByAlignmentStart.size(); } /** @@ -166,38 +250,12 @@ final class PerSampleReadStateManager implements Iterable return nRemoved; } - // todo -- reimplement + /** + * Iterate over the AlignmentStateMachine in this manager in alignment start order. + * @return a valid iterator + */ + @Ensures("result != null") public Iterator iterator() { - return new Iterator() { - private final Iterator> alignmentStartIterator = readStatesByAlignmentStart.iterator(); - private LinkedList currentPositionReadStates; - private Iterator currentPositionReadStatesIterator; - - @Override - public boolean hasNext() { - return alignmentStartIterator.hasNext() || - (currentPositionReadStatesIterator != null && currentPositionReadStatesIterator.hasNext()); - } - - @Override - public AlignmentStateMachine next() { - if ( currentPositionReadStatesIterator == null || ! currentPositionReadStatesIterator.hasNext() ) { - currentPositionReadStates = alignmentStartIterator.next(); - currentPositionReadStatesIterator = currentPositionReadStates.iterator(); - } - - return currentPositionReadStatesIterator.next(); - } - - @Override - public void remove() { - currentPositionReadStatesIterator.remove(); - thisSampleReadStates--; - - if ( currentPositionReadStates.isEmpty() ) { - alignmentStartIterator.remove(); - } - } - }; + return readStatesByAlignmentStart.iterator(); } } diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 4011875a6..09ec3b264 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -122,7 +122,7 @@ final class ReadStateManager implements Iterable Date: Sun, 13 Jan 2013 20:43:10 -0500 Subject: [PATCH 009/188] ReservoirDownsampler optimizations -- Add an option to not allocate always ArrayLists of targetSampleSize, but rather the previous size + MARGIN. This helps for LIBS as most of the time we don't need nearly so much space as we allow -- consumeFinalizedItems returns an empty list if the reservior is empty, which it often true for our BAM files with low coverage -- Allow empty sample lists for SamplePartitioner as these are used by the RefTraversals and other non-read based traversals Make the reservoir downsampler use a linked list, rather than a fixed sized array list, in the expectFewOverflows case --- .../downsampling/ReservoirDownsampler.java | 76 +++++++++++++++---- .../locusiterator/SamplePartitioner.java | 9 ++- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/downsampling/ReservoirDownsampler.java b/public/java/src/org/broadinstitute/sting/gatk/downsampling/ReservoirDownsampler.java index 0d7a0dd14..4331fd723 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/downsampling/ReservoirDownsampler.java +++ b/public/java/src/org/broadinstitute/sting/gatk/downsampling/ReservoirDownsampler.java @@ -29,9 +29,7 @@ import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; /** * Reservoir Downsampler: Selects n reads out of a stream whose size is not known in advance, with @@ -42,10 +40,25 @@ import java.util.List; * @author David Roazen */ public class ReservoirDownsampler implements ReadsDownsampler { + private final int targetSampleSize; - private ArrayList reservoir; + /** + * if true, this downsampler will be optimized for the case + * where most of the time we won't fill up anything like the + * targetSampleSize elements. If this is false, we will allocate + * internal buffers to targetSampleSize initially, which minimizes + * the cost of allocation if we often use targetSampleSize or more + * elements. + */ + private final boolean expectFewOverflows; - private int targetSampleSize; + /** + * At times this can be a linked list or an array list, depending on how we're accessing the + * data and whether or not we're expecting few overflows + */ + private List reservoir; + + private boolean isLinkedList; private int totalReadsSeen; @@ -56,17 +69,35 @@ public class ReservoirDownsampler implements ReadsDownsampl * * @param targetSampleSize Size of the reservoir used by this downsampler. Number of items retained * after downsampling will be min(totalReads, targetSampleSize) + * @param expectFewOverflows if true, this downsampler will be optimized for the case + * where most of the time we won't fill up anything like the + * targetSampleSize elements. If this is false, we will allocate + * internal buffers to targetSampleSize initially, which minimizes + * the cost of allocation if we often use targetSampleSize or more + * elements. */ - public ReservoirDownsampler ( int targetSampleSize ) { + public ReservoirDownsampler ( final int targetSampleSize, final boolean expectFewOverflows) { if ( targetSampleSize <= 0 ) { throw new ReviewedStingException("Cannot do reservoir downsampling with a sample size <= 0"); } this.targetSampleSize = targetSampleSize; + this.expectFewOverflows = expectFewOverflows; clear(); reset(); } + /** + * Construct a ReservoirDownsampler + * + * @param targetSampleSize Size of the reservoir used by this downsampler. Number of items retained + * after downsampling will be min(totalReads, targetSampleSize) + */ + public ReservoirDownsampler ( int targetSampleSize ) { + this(targetSampleSize, false); + } + + public void submit ( T newRead ) { totalReadsSeen++; @@ -74,7 +105,12 @@ public class ReservoirDownsampler implements ReadsDownsampl reservoir.add(newRead); } else { - int randomSlot = GenomeAnalysisEngine.getRandomGenerator().nextInt(totalReadsSeen); + if ( isLinkedList ) { + reservoir = new ArrayList(reservoir); + isLinkedList = false; + } + + final int randomSlot = GenomeAnalysisEngine.getRandomGenerator().nextInt(totalReadsSeen); if ( randomSlot < targetSampleSize ) { reservoir.set(randomSlot, newRead); } @@ -93,10 +129,15 @@ public class ReservoirDownsampler implements ReadsDownsampl } public List consumeFinalizedItems() { - // pass by reference rather than make a copy, for speed - List downsampledItems = reservoir; - clear(); - return downsampledItems; + if ( reservoir.isEmpty() ) { + // if there's nothing here, don't both allocating a new list completely + return Collections.emptyList(); + } else { + // pass by reference rather than make a copy, for speed + List downsampledItems = reservoir; + clear(); + return downsampledItems; + } } public boolean hasPendingItems() { @@ -119,9 +160,18 @@ public class ReservoirDownsampler implements ReadsDownsampl // NO-OP } + /** + * Clear the data structures used to hold information + */ public void clear() { - reservoir = new ArrayList(targetSampleSize); - totalReadsSeen = 0; // an internal stat used by the downsampling process, so not cleared by reset() below + // if we aren't expecting many overflows, allocate a linked list not an arraylist + reservoir = expectFewOverflows ? new LinkedList() : new ArrayList(targetSampleSize); + + // it's a linked list if we allocate one + isLinkedList = expectFewOverflows; + + // an internal stat used by the downsampling process, so not cleared by reset() below + totalReadsSeen = 0; } public void reset() { diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java index 7dada292b..9bb474e4d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java @@ -62,16 +62,17 @@ class SamplePartitioner { * will throw an exception. Duplicates in the list of samples will be ignored * * @param LIBSDownsamplingInfo do we want to downsample, and if so to what coverage? - * @param samples the complete list of samples we're going to partition reads into + * @param samples the complete list of samples we're going to partition reads into. Can be + * empty, but in that case this code cannot function properly if you + * attempt to add data to it. */ @Ensures({ "readsBySample != null", - "! readsBySample.isEmpty()", "readsBySample.size() == new HashSet(samples).size()" }) public SamplePartitioner(final LIBSDownsamplingInfo LIBSDownsamplingInfo, final List samples) { if ( LIBSDownsamplingInfo == null ) throw new IllegalArgumentException("LIBSDownsamplingInfo cannot be null"); - if ( samples == null || samples.isEmpty() ) throw new IllegalArgumentException("samples must be a non-null, non-empty list but got " + samples); + if ( samples == null ) throw new IllegalArgumentException("samples must be a non-null list"); readsBySample = new LinkedHashMap>(samples.size()); for ( final String sample : samples ) { @@ -89,7 +90,7 @@ class SamplePartitioner { @Ensures("result != null") private Downsampler createDownsampler(final LIBSDownsamplingInfo LIBSDownsamplingInfo) { return LIBSDownsamplingInfo.isPerformDownsampling() - ? new ReservoirDownsampler(LIBSDownsamplingInfo.getToCoverage()) + ? new ReservoirDownsampler(LIBSDownsamplingInfo.getToCoverage(), true) : new PassThroughDownsampler(); } From b8b2b9b2de6270e1aead4f17ecf01b27d7f123f7 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 13 Jan 2013 20:44:28 -0500 Subject: [PATCH 010/188] ManagingReferenceOrderedView optimization: don't allow a fresh RefMetaDataTracker in the frequent case where there's no reference meta data --- .../providers/ManagingReferenceOrderedView.java | 14 +++++++++----- .../sting/gatk/refdata/RefMetaDataTracker.java | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/ManagingReferenceOrderedView.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/ManagingReferenceOrderedView.java index 7d3cac33d..09b72f5eb 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/ManagingReferenceOrderedView.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/ManagingReferenceOrderedView.java @@ -77,13 +77,17 @@ public class ManagingReferenceOrderedView implements ReferenceOrderedView { * @return A tracker containing information about this locus. */ public RefMetaDataTracker getReferenceOrderedDataAtLocus( GenomeLoc loc, ReferenceContext referenceContext ) { - List bindings = states.isEmpty() ? Collections.emptyList() : new ArrayList(states.size()); + if ( states.isEmpty() ) + return RefMetaDataTracker.EMPTY_TRACKER; + else { + List bindings = new ArrayList(states.size()); - for ( ReferenceOrderedDataState state: states ) - // todo -- warning, I removed the reference to the name from states - bindings.add( state.iterator.seekForward(loc) ); + for ( ReferenceOrderedDataState state: states ) + // todo -- warning, I removed the reference to the name from states + bindings.add( state.iterator.seekForward(loc) ); - return new RefMetaDataTracker(bindings); + return new RefMetaDataTracker(bindings); + } } /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/RefMetaDataTracker.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/RefMetaDataTracker.java index 9cb38b840..5a1b015fe 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/RefMetaDataTracker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/RefMetaDataTracker.java @@ -61,6 +61,7 @@ public class RefMetaDataTracker { final Map bindings; final protected static Logger logger = Logger.getLogger(RefMetaDataTracker.class); + public final static RefMetaDataTracker EMPTY_TRACKER = new RefMetaDataTracker(); // ------------------------------------------------------------------------------------------ // From 39bc9e999d8215486708a77a8cff31b9084f7dca Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Mon, 14 Jan 2013 08:34:42 -0500 Subject: [PATCH 011/188] Add a test to LocusIteratorByState to ensure that we aren't holding reads anywhere -- Run an iterator with 100Ks of reads, each carrying MBs of byte[] data, through LIBS, all starting at the same position. Will crash with an out-of-memory error if we're holding reads anywhere in the system. -- Is there a better way to test this behavior? --- .../LocusIteratorByStateUnitTest.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index 7ae2d97a1..37494903c 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -27,6 +27,7 @@ package org.broadinstitute.sting.utils.locusiterator; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMFileHeader; +import net.sf.samtools.SAMReadGroupRecord; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.ReadProperties; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; @@ -577,4 +578,94 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { } } } + + // --------------------------------------------------------------------------- + // make sure that downsampling isn't holding onto a bazillion reads + // + @DataProvider(name = "LIBS_NotHoldingTooManyReads") + public Object[][] makeLIBS_NotHoldingTooManyReads() { + final List tests = new LinkedList(); + + for ( final int downsampleTo : Arrays.asList(1, 10)) { + for ( final int nReadsPerLocus : Arrays.asList(100, 1000, 10000, 100000) ) { + for ( final int payloadInBytes : Arrays.asList(0, 1024, 1024*1024) ) { + tests.add(new Object[]{nReadsPerLocus, downsampleTo, payloadInBytes}); + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(enabled = true && ! DEBUG, dataProvider = "LIBS_NotHoldingTooManyReads") +// @Test(enabled = true, dataProvider = "LIBS_NotHoldingTooManyReads", timeOut = 100000) + public void testLIBS_NotHoldingTooManyReads(final int nReadsPerLocus, final int downsampleTo, final int payloadInBytes) { + logger.warn(String.format("testLIBS_NotHoldingTooManyReads %d %d %d", nReadsPerLocus, downsampleTo, payloadInBytes)); + final int readLength = 10; + + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100000); + final int nSamples = 1; + final List samples = new ArrayList(nSamples); + for ( int i = 0; i < nSamples; i++ ) { + final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord("rg" + i); + final String sample = "sample" + i; + samples.add(sample); + rg.setSample(sample); + rg.setPlatform(NGSPlatform.ILLUMINA.getDefaultPlatform()); + header.addReadGroup(rg); + } + + final boolean downsample = downsampleTo != -1; + final DownsamplingMethod downsampler = downsample + ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) + : new DownsamplingMethod(DownsampleType.NONE, null, null, false); + + // final List reads = ArtificialSAMUtils.createReadStream(nReadsPerLocus, nLoci, header, 1, readLength); + + final WeakReadTrackingIterator iterator = new WeakReadTrackingIterator(nReadsPerLocus, readLength, payloadInBytes, header); + + li = new LocusIteratorByState(iterator, + createTestReadProperties(downsampler, false), + genomeLocParser, + samples); + + while ( li.hasNext() ) { + final AlignmentContext next = li.next(); + Assert.assertTrue(next.getBasePileup().getNumberOfElements() <= downsampleTo, "Too many elements in pileup " + next); + // TODO -- assert that there are <= X reads in memory after GC for some X + } + } + + private static class WeakReadTrackingIterator implements Iterator { + final int nReads, readLength, payloadInBytes; + int readI = 0; + final SAMFileHeader header; + + private WeakReadTrackingIterator(int nReads, int readLength, final int payloadInBytes, final SAMFileHeader header) { + this.nReads = nReads; + this.readLength = readLength; + this.header = header; + this.payloadInBytes = payloadInBytes; + } + + @Override public boolean hasNext() { return readI < nReads; } + @Override public void remove() { throw new UnsupportedOperationException("no remove"); } + + @Override + public GATKSAMRecord next() { + readI++; + return makeRead(); + } + + private GATKSAMRecord makeRead() { + final SAMReadGroupRecord rg = header.getReadGroups().get(0); + final String readName = String.format("%s.%d.%s", "read", readI, rg.getId()); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, 1, readLength); + read.setReadGroup(new GATKSAMReadGroupRecord(rg)); + if ( payloadInBytes > 0 ) + // add a payload byte array to push memory use per read even higher + read.setAttribute("PL", new byte[payloadInBytes]); + return read; + } + } } From 94800771e3c48e39fcef5280e5c31919031e8066 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Tue, 15 Jan 2013 10:19:18 -0500 Subject: [PATCH 012/188] 1. Initial implementation of bam writing for the HaplotypeCaller with -bam argument; currently only assembled haplotypes are emitted. 2. Framework is set up in the VariantAnnotator for the HaplotypeCaller to be able to call in to annotate dbSNP plus comp RODs. Until the HC uses meta data though, this won't work. --- .../annotator/VariantAnnotatorEngine.java | 27 ++++++--- .../haplotypecaller/HaplotypeCaller.java | 57 ++++++++++++++++++- .../HaplotypeCallerIntegrationTest.java | 5 ++ .../broadinstitute/sting/utils/Haplotype.java | 12 ++++ 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java index 99dadea54..f03a25c04 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java @@ -52,6 +52,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.*; +import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -214,10 +215,10 @@ public class VariantAnnotatorEngine { Map infoAnnotations = new LinkedHashMap(vc.getAttributes()); // annotate db occurrences - vc = annotateDBs(tracker, ref, vc, infoAnnotations); + vc = annotateDBs(tracker, ref.getLocus(), vc, infoAnnotations); // annotate expressions where available - annotateExpressions(tracker, ref, infoAnnotations); + annotateExpressions(tracker, ref.getLocus(), infoAnnotations); // go through all the requested info annotationTypes for ( InfoFieldAnnotation annotationType : requestedInfoAnnotations ) { @@ -254,10 +255,22 @@ public class VariantAnnotatorEngine { return builder.genotypes(annotateGenotypes(null, null, null, vc, perReadAlleleLikelihoodMap)).make(); } - private VariantContext annotateDBs(RefMetaDataTracker tracker, ReferenceContext ref, VariantContext vc, Map infoAnnotations) { + public VariantContext annotateDBs(final RefMetaDataTracker tracker, final GenomeLoc loc, VariantContext vc) { + final Map newInfoAnnotations = new HashMap(0); + vc = annotateDBs(tracker, loc, vc, newInfoAnnotations); + + if ( !newInfoAnnotations.isEmpty() ) { + final VariantContextBuilder builder = new VariantContextBuilder(vc).attributes(newInfoAnnotations); + vc = builder.make(); + } + + return vc; + } + + private VariantContext annotateDBs(final RefMetaDataTracker tracker, final GenomeLoc loc, VariantContext vc, final Map infoAnnotations) { for ( Map.Entry, String> dbSet : dbAnnotations.entrySet() ) { if ( dbSet.getValue().equals(VCFConstants.DBSNP_KEY) ) { - final String rsID = VCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbSet.getKey(), ref.getLocus()), vc.getType()); + final String rsID = VCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbSet.getKey(), loc), vc.getType()); // add the ID if appropriate if ( rsID != null ) { @@ -273,7 +286,7 @@ public class VariantAnnotatorEngine { } } else { boolean overlapsComp = false; - for ( VariantContext comp : tracker.getValues(dbSet.getKey(), ref.getLocus()) ) { + for ( VariantContext comp : tracker.getValues(dbSet.getKey(), loc) ) { if ( !comp.isFiltered() && ( !requireStrictAlleleMatch || comp.getAlleles().equals(vc.getAlleles()) ) ) { overlapsComp = true; break; @@ -287,9 +300,9 @@ public class VariantAnnotatorEngine { return vc; } - private void annotateExpressions(RefMetaDataTracker tracker, ReferenceContext ref, Map infoAnnotations) { + private void annotateExpressions(final RefMetaDataTracker tracker, final GenomeLoc loc, final Map infoAnnotations) { for ( VAExpression expression : requestedExpressions ) { - Collection VCs = tracker.getValues(expression.binding, ref.getLocus()); + Collection VCs = tracker.getValues(expression.binding, loc); if ( VCs.size() == 0 ) continue; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 439a9b3b8..00db62bff 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -47,6 +47,8 @@ package org.broadinstitute.sting.gatk.walkers.haplotypecaller; import com.google.java.contract.Ensures; +import com.sun.corba.se.impl.logging.UtilSystemException; +import net.sf.samtools.*; import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; @@ -57,6 +59,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.gatk.filters.BadMateFilter; +import org.broadinstitute.sting.gatk.io.StingSAMFileWriter; import org.broadinstitute.sting.gatk.iterators.ReadTransformer; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; @@ -67,6 +70,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedArgumentCollection import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; import org.broadinstitute.sting.gatk.walkers.genotyper.VariantCallContext; import org.broadinstitute.sting.utils.*; +import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; import org.broadinstitute.sting.utils.clipping.ReadClipper; @@ -142,6 +146,17 @@ public class HaplotypeCaller extends ActiveRegionWalker implem @Output(fullName="graphOutput", shortName="graph", doc="File to which debug assembly graph information should be written", required = false) protected PrintStream graphWriter = null; + /** + * The assembled haplotypes will be written as BAM to this file if requested. Really for debugging purposes only. Note that the output here + * does not include uninformative reads so that not every input read is emitted to the bam. + */ + @Hidden + @Output(fullName="bamOutput", shortName="bam", doc="File to which assembled haplotypes should be written", required = false) + protected StingSAMFileWriter bamWriter = null; + private SAMFileHeader bamHeader = null; + private long uniqueNameCounter = 1; + private final String readGroupId = "ArtificialHaplotype"; + /** * The PairHMM implementation to use for genotype likelihood calculations. The various implementations balance a tradeoff of accuracy and runtime. */ @@ -242,6 +257,8 @@ public class HaplotypeCaller extends ActiveRegionWalker implem // the genotyping engine private GenotypingEngine genotypingEngine = null; + private VariantAnnotatorEngine annotationEngine = null; + // fasta reference reader to supplement the edges of the reference sequence private CachingIndexedFastaSequenceFile referenceReader; @@ -286,7 +303,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem UG_engine_simple_genotyper = new UnifiedGenotyperEngine(getToolkit(), simpleUAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); // initialize the output VCF header - final VariantAnnotatorEngine annotationEngine = new VariantAnnotatorEngine(Arrays.asList(annotationClassesToUse), annotationsToUse, annotationsToExclude, this, getToolkit()); + annotationEngine = new VariantAnnotatorEngine(Arrays.asList(annotationClassesToUse), annotationsToUse, annotationsToExclude, this, getToolkit()); Set headerInfo = new HashSet(); @@ -320,6 +337,21 @@ public class HaplotypeCaller extends ActiveRegionWalker implem assemblyEngine = new SimpleDeBruijnAssembler( DEBUG, graphWriter, minKmer ); likelihoodCalculationEngine = new LikelihoodCalculationEngine( (byte)gcpHMM, DEBUG, pairHMM ); genotypingEngine = new GenotypingEngine( DEBUG, annotationEngine, USE_FILTERED_READ_MAP_FOR_ANNOTATIONS ); + + if ( bamWriter != null ) { + // prepare the bam header + bamHeader = new SAMFileHeader(); + bamHeader.setSequenceDictionary(getToolkit().getSAMFileHeader().getSequenceDictionary()); + final List readGroups = new ArrayList(1); + final SAMReadGroupRecord rg = new SAMReadGroupRecord(readGroupId); + rg.setSample("HC"); + rg.setSequencingCenter("BI"); + readGroups.add(rg); + bamHeader.setReadGroups(readGroups); + bamHeader.setSortOrder(SAMFileHeader.SortOrder.coordinate); + bamWriter.writeHeader(bamHeader); + bamWriter.setPresorted(true); + } } //--------------------------------------------------------------------------------------------------------------- @@ -408,7 +440,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem //--------------------------------------------------------------------------------------------------------------- @Override - public Integer map( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion, final RefMetaDataTracker metaDataTracker ) { + public Integer map( final ActiveRegion activeRegion, final RefMetaDataTracker metaDataTracker ) { if ( justDetermineActiveRegions ) // we're benchmarking ART and/or the active region determination code in the HC, just leave without doing any work return 1; @@ -461,9 +493,30 @@ public class HaplotypeCaller extends ActiveRegionWalker implem activeRegion.getLocation(), getToolkit().getGenomeLocParser(), activeAllelesToGenotype ) ) { + annotationEngine.annotateDBs(metaDataTracker, getToolkit().getGenomeLocParser().createGenomeLoc(call), call); vcfWriter.add( call ); } + if ( bamWriter != null ) { + Collections.sort( haplotypes, new Haplotype.HaplotypePositionComparator() ); + final GenomeLoc paddedRefLoc = getPaddedLoc(activeRegion); + for ( Haplotype haplotype : haplotypes ) { + // TODO -- clean up this code + final GATKSAMRecord record = new GATKSAMRecord(bamHeader); + record.setReadBases(haplotype.getBases()); + record.setAlignmentStart(paddedRefLoc.getStart() + haplotype.getAlignmentStartHapwrtRef()); + record.setBaseQualities(Utils.dupBytes((byte) '!', haplotype.getBases().length)); + record.setCigar(haplotype.getCigar()); + record.setMappingQuality(bestHaplotypes.contains(haplotype) ? 60 : 0); + record.setReadName("HC" + uniqueNameCounter++); + record.setReadUnmappedFlag(false); + record.setReferenceIndex(activeRegion.getReferenceLoc().getContigIndex()); + record.setAttribute(SAMTag.RG.toString(), readGroupId); + record.setFlags(16); + bamWriter.addAlignment(record); + } + } + if( DEBUG ) { System.out.println("----------------------------------------------------------------------------------"); } return 1; // One active region was processed during this map call diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 8f5e275e6..e39975ea0 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -75,6 +75,11 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); } + @Test(enabled = false) + public void testHaplotypeCallerSingleSampleWithDbsnp() { + HCTest(NA12878_BAM, "-D " + b37dbSNP132, ""); + } + @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index efe9460cb..2706f2f99 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -191,6 +191,10 @@ public class Haplotype { public static class HaplotypeBaseComparator implements Comparator, Serializable { @Override public int compare( final Haplotype hap1, final Haplotype hap2 ) { + return compareHaplotypeBases(hap1, hap2); + } + + public static int compareHaplotypeBases(final Haplotype hap1, final Haplotype hap2) { final byte[] arr1 = hap1.getBases(); final byte[] arr2 = hap2.getBases(); // compares byte arrays using lexical ordering @@ -203,6 +207,14 @@ public class Haplotype { } } + public static class HaplotypePositionComparator implements Comparator, Serializable { + @Override + public int compare( final Haplotype hap1, final Haplotype hap2 ) { + final int comp = hap1.getAlignmentStartHapwrtRef() - hap2.getAlignmentStartHapwrtRef(); + return comp == 0 ? HaplotypeBaseComparator.compareHaplotypeBases(hap1, hap2) : comp; + } + } + public static LinkedHashMap makeHaplotypeListFromAlleles(final List alleleList, final int startPos, final ReferenceContext ref, From 3c37ea014b91a57e55e56b0ac93033f7e3597ac8 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 15 Jan 2013 10:24:45 -0500 Subject: [PATCH 013/188] Retire original TraverseActiveRegion, leaving only the new optimized version -- Required some updates to MD5s, which was unexpected, and will be sorted out later with more detailed unit tests --- .../HaplotypeCallerIntegrationTest.java | 12 +- .../sting/gatk/GenomeAnalysisEngine.java | 2 +- .../arguments/GATKArgumentCollection.java | 5 - .../sting/gatk/executive/MicroScheduler.java | 7 +- .../traversals/TraverseActiveRegions.java | 214 ++++++- .../TraverseActiveRegionsOptimized.java | 253 --------- .../TraverseActiveRegionsOriginal.java | 262 --------- ...TraverseActiveRegionsOriginalUnitTest.java | 523 ------------------ ...ava => TraverseActiveRegionsUnitTest.java} | 6 +- 9 files changed, 214 insertions(+), 1070 deletions(-) delete mode 100644 public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimized.java delete mode 100644 public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginal.java delete mode 100644 public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginalUnitTest.java rename public/java/test/org/broadinstitute/sting/gatk/traversals/{TraverseActiveRegionsOptimizedUnitTest.java => TraverseActiveRegionsUnitTest.java} (99%) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 8f5e275e6..780934c03 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -67,18 +67,18 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "b8f7b741445ce6b6ea491c794ce75c17"); + HCTest(CEUTRIO_BAM, "", "1e2671557b01ad0497557097282965fc"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); + HCTest(NA12878_BAM, "", "2bd237a7e1e63eebe755dbe7963e430a"); } @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "c679ae7f04bdfda896b5c046d35e043c"); + "a938cdd7262968597fc8eb6c1c0a69f1"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -96,7 +96,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "1a034b7eb572e1b6f659d6e5d57b3e76"); + "d590c8d6d5e58d685401b65a23846893"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -129,7 +129,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "29f1125df5ab27cc937a144ae08ac735"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "50a26224b9e863ee47a0619eb54a0323"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -140,7 +140,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("8b1b8d1bd7feac1503fc4ffa6236cff7")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("4439496472eb1e2f5c91b30ba525be37")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index a5926aeae..f9d6955c0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -842,7 +842,7 @@ public class GenomeAnalysisEngine { if (argCollection.keepProgramRecords) removeProgramRecords = false; - final boolean keepReadsInLIBS = walker instanceof ActiveRegionWalker && argCollection.newART; + final boolean keepReadsInLIBS = walker instanceof ActiveRegionWalker; return new SAMDataSource( samReaderIDs, diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index b6f0d5f90..ab09064dd 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -448,10 +448,5 @@ public class GATKArgumentCollection { @Hidden public boolean generateShadowBCF = false; // TODO -- remove all code tagged with TODO -- remove me when argument generateShadowBCF is removed - - @Hidden - @Argument(fullName="newART", shortName = "newART", doc = "use the new ART traversal", required=false) - public boolean newART = false; - } diff --git a/public/java/src/org/broadinstitute/sting/gatk/executive/MicroScheduler.java b/public/java/src/org/broadinstitute/sting/gatk/executive/MicroScheduler.java index c127899f6..371cce778 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/executive/MicroScheduler.java +++ b/public/java/src/org/broadinstitute/sting/gatk/executive/MicroScheduler.java @@ -245,12 +245,7 @@ public abstract class MicroScheduler implements MicroSchedulerMBean { } else if (walker instanceof ReadPairWalker) { return new TraverseReadPairs(); } else if (walker instanceof ActiveRegionWalker) { - if ( engine.getArguments().newART ) { - // todo -- create optimized traversal - return new TraverseActiveRegionsOptimized(); - } else { - return new TraverseActiveRegionsOriginal(); - } + return new TraverseActiveRegions(); } else { throw new UnsupportedOperationException("Unable to determine traversal type, the walker is an unknown type."); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 45dbb6dc8..03aaf95f2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -31,6 +31,7 @@ import org.broadinstitute.sting.gatk.WalkerManager; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.datasources.providers.*; +import org.broadinstitute.sting.gatk.datasources.reads.Shard; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; @@ -43,8 +44,7 @@ import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; import org.broadinstitute.sting.utils.progressmeter.ProgressMeter; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import java.util.LinkedList; -import java.util.List; +import java.util.*; /** * Created with IntelliJ IDEA. @@ -53,7 +53,7 @@ import java.util.List; * Time: 4:45 PM * To change this template use File | Settings | File Templates. */ -public abstract class TraverseActiveRegions extends TraversalEngine,LocusShardDataProvider> { +public class TraverseActiveRegions extends TraversalEngine,LocusShardDataProvider> { protected final static boolean DEBUG = false; // set by the tranversal @@ -66,14 +66,6 @@ public abstract class TraverseActiveRegions extends TraversalEngine workQueue = new LinkedList(); - abstract protected T processActiveRegion(final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker); - - /** - * Special function called in LinearMicroScheduler to empty out the work queue. - * Ugly for now but will be cleaned up when we push this functionality more into the engine - */ - public abstract T endTraversal(final Walker walker, T sum); - protected int getActiveRegionExtension() { return activeRegionExtension; } @@ -160,4 +152,204 @@ public abstract class TraverseActiveRegions extends TraversalEngine myReads = new LinkedList(); + private Shard lastShard = null; + + @Override + public T traverse( final ActiveRegionWalker walker, + final LocusShardDataProvider dataProvider, + T sum) { + if ( DEBUG ) logger.warn(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); + + final HashSet maybeDuplicatedReads = new HashSet(); + // TODO -- there's got to be a better way to know this + if ( lastShard != dataProvider.getShard() ) { + maybeDuplicatedReads.addAll(myReads); + logger.info("Crossing shard boundary requires us to check for duplicates against " + maybeDuplicatedReads.size() + " reads"); + if ( DEBUG ) logger.warn("Clearing myReads"); + } + lastShard = dataProvider.getShard(); + + final LocusView locusView = new AllLocusView(dataProvider); + + final LocusReferenceView referenceView = new LocusReferenceView( walker, dataProvider ); + + final List activeRegions = new LinkedList(); + ActivityProfile profile = new ActivityProfile(engine.getGenomeLocParser(), walker.hasPresetActiveRegions() ); + + ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); + + // We keep processing while the next reference location is within the interval + GenomeLoc prevLoc = null; + while( locusView.hasNext() ) { + final AlignmentContext locus = locusView.next(); + final GenomeLoc location = locus.getLocation(); + + // Grab all the previously unseen reads from this pileup and add them to the massive read list + // Note that this must occur before we leave because we are outside the intervals because + // reads may occur outside our intervals but overlap them in the future + final Collection reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); + for( final GATKSAMRecord read : reads ) { + notifyOfCurrentPosition(read); + // most of the time maybeDuplicatedReads is empty + // TODO -- I believe that because of the ordering of reads that as soon as we don't find a read in the + // TODO -- potential list of duplicates we can clear the hashset + if ( ! maybeDuplicatedReads.isEmpty() && maybeDuplicatedReads.contains(read) ) { + if ( DEBUG ) logger.warn("Skipping duplicated " + read.getReadName()); + } else { + if ( DEBUG ) logger.warn("Adding read " + read.getReadName() + " at " + engine.getGenomeLocParser().createGenomeLoc(read) + " from provider " + dataProvider); + myReads.add((GATKSAMRecord)read); + } + } + + // skip this location -- it's not part of our engine intervals + if ( outsideEngineIntervals(location) ) + continue; + + if ( prevLoc != null && location.getStart() != prevLoc.getStop() + 1 ) { + // we've move across some interval boundary, restart profile + profile = incorporateActiveRegions(profile, activeRegions); + } + + dataProvider.getShard().getReadMetrics().incrementNumIterations(); + + // create reference context. Note that if we have a pileup of "extended events", the context will + // hold the (longest) stretch of deleted reference bases (if deletions are present in the pileup). + final ReferenceContext refContext = referenceView.getReferenceContext(location); + + // Iterate forward to get all reference ordered data covering this location + final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataAtLocus(locus.getLocation(), refContext); + + // Call the walkers isActive function for this locus and add them to the list to be integrated later + profile.add(walkerActiveProb(walker, tracker, refContext, locus, location)); + + prevLoc = location; + + printProgress(locus.getLocation()); + } + + updateCumulativeMetrics(dataProvider.getShard()); + + if ( ! profile.isEmpty() ) + incorporateActiveRegions(profile, activeRegions); + + // add active regions to queue of regions to process + // first check if can merge active regions over shard boundaries + if( !activeRegions.isEmpty() ) { + if( !workQueue.isEmpty() ) { + final ActiveRegion last = workQueue.getLast(); + final ActiveRegion first = activeRegions.get(0); + if( last.isActive == first.isActive && last.getLocation().contiguousP(first.getLocation()) && last.getLocation().size() + first.getLocation().size() <= getMaxRegionSize() ) { + workQueue.removeLast(); + activeRegions.remove(first); + workQueue.add( new ActiveRegion(last.getLocation().union(first.getLocation()), first.isActive, this.engine.getGenomeLocParser(), getActiveRegionExtension()) ); + } + } + workQueue.addAll( activeRegions ); + } + + logger.debug("Integrated " + profile.size() + " isActive calls into " + activeRegions.size() + " regions." ); + + // now go and process all of the active regions + sum = processActiveRegions(walker, sum, false); + + return sum; + } + + private GenomeLoc startOfLiveRegion = null; + + protected void notifyOfCurrentPosition(final GATKSAMRecord read) { + notifyOfCurrentPosition(engine.getGenomeLocParser().createGenomeLoc(read)); + } + + protected void notifyOfCurrentPosition(final GenomeLoc currentLocation) { + if ( startOfLiveRegion == null ) + startOfLiveRegion = currentLocation; + else + startOfLiveRegion = startOfLiveRegion.max(currentLocation.getStartLocation()); + } + + protected GenomeLoc getStartOfLiveRegion() { + return startOfLiveRegion; + } + + protected boolean regionCompletelyWithinDeadZone(final GenomeLoc region, final boolean includeExtension) { + return (region.getStop() < (getStartOfLiveRegion().getStart() - (includeExtension ? getActiveRegionExtension() : 0))) + || ! region.onSameContig(getStartOfLiveRegion()); + } + + private T processActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { + if( walker.activeRegionOutStream != null ) { + writeActiveRegionsToStream(walker); + return sum; + } else { + return callWalkerMapOnActiveRegions(walker, sum, forceRegionsToBeActive); + } + } + + private T callWalkerMapOnActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { + // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them + // TODO can implement parallel traversal here + while( workQueue.peek() != null ) { + final GenomeLoc extendedLoc = workQueue.peek().getExtendedLoc(); + if ( forceRegionsToBeActive || regionCompletelyWithinDeadZone(extendedLoc, false) ) { + final ActiveRegion activeRegion = workQueue.remove(); + if ( DEBUG ) logger.warn("Processing active region " + activeRegion + " dead zone " + getStartOfLiveRegion()); + sum = processActiveRegion( activeRegion, sum, walker ); + } else { + break; + } + } + + return sum; + } + + @Override + public String toString() { + return "TraverseActiveRegions"; + } + + private boolean readIsDead(final GATKSAMRecord read, final GenomeLoc readLoc, final ActiveRegion activeRegion) { + return readLoc.getStop() < activeRegion.getLocation().getStart() && regionCompletelyWithinDeadZone(readLoc, true); + } + + protected T processActiveRegion(final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker) { + final Iterator liveReads = myReads.iterator(); + while ( liveReads.hasNext() ) { + boolean killed = false; + final GATKSAMRecord read = liveReads.next(); + final GenomeLoc readLoc = this.engine.getGenomeLocParser().createGenomeLoc( read ); + + if( activeRegion.getLocation().overlapsP( readLoc ) ) { + activeRegion.add(read); + + if ( ! walker.wantsNonPrimaryReads() ) { + if ( DEBUG ) logger.warn("Removing read " + read.getReadName() + " at " + readLoc + " with dead zone start " + getStartOfLiveRegion()); + liveReads.remove(); + killed = true; + } + } else if( walker.wantsExtendedReads() && activeRegion.getExtendedLoc().overlapsP( readLoc )) { + activeRegion.add( read ); + } + + if ( ! killed && readIsDead(read, readLoc, activeRegion) ) { + if ( DEBUG ) logger.warn("Removing read " + read.getReadName() + " at " + readLoc + " with dead zone start " + getStartOfLiveRegion()); + liveReads.remove(); + } + } + + logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); + final M x = walker.map(activeRegion, null); + return walker.reduce( x, sum ); + } + + + /** + * Special function called in LinearMicroScheduler to empty out the work queue. + * Ugly for now but will be cleaned up when we push this functionality more into the engine + */ + public T endTraversal(final Walker walker, T sum) { + return processActiveRegions((ActiveRegionWalker)walker, sum, true); + } } diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimized.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimized.java deleted file mode 100644 index 809c7ea6a..000000000 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimized.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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.traversals; - -import net.sf.samtools.SAMRecord; -import org.broadinstitute.sting.gatk.contexts.AlignmentContext; -import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.sting.gatk.datasources.providers.*; -import org.broadinstitute.sting.gatk.datasources.reads.Shard; -import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; -import org.broadinstitute.sting.gatk.walkers.Walker; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.activeregion.ActiveRegion; -import org.broadinstitute.sting.utils.activeregion.ActivityProfile; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; - -import java.util.*; - -/** - * Created by IntelliJ IDEA. - * User: rpoplin - * Date: 12/9/11 - */ - -public class TraverseActiveRegionsOptimized extends TraverseActiveRegions { - private LinkedList myReads = new LinkedList(); - private Shard lastShard = null; - - @Override - public T traverse( final ActiveRegionWalker walker, - final LocusShardDataProvider dataProvider, - T sum) { - if ( DEBUG ) logger.warn(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); - - final HashSet maybeDuplicatedReads = new HashSet(); - // TODO -- there's got to be a better way to know this - if ( lastShard != dataProvider.getShard() ) { - maybeDuplicatedReads.addAll(myReads); - logger.info("Crossing shard boundary requires us to check for duplicates against " + maybeDuplicatedReads.size() + " reads"); - if ( DEBUG ) logger.warn("Clearing myReads"); - } - lastShard = dataProvider.getShard(); - - final LocusView locusView = new AllLocusView(dataProvider); - - final LocusReferenceView referenceView = new LocusReferenceView( walker, dataProvider ); - - final List activeRegions = new LinkedList(); - ActivityProfile profile = new ActivityProfile(engine.getGenomeLocParser(), walker.hasPresetActiveRegions() ); - - ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); - - // We keep processing while the next reference location is within the interval - GenomeLoc prevLoc = null; - while( locusView.hasNext() ) { - final AlignmentContext locus = locusView.next(); - final GenomeLoc location = locus.getLocation(); - - // Grab all the previously unseen reads from this pileup and add them to the massive read list - // Note that this must occur before we leave because we are outside the intervals because - // reads may occur outside our intervals but overlap them in the future - final Collection reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); - for( final GATKSAMRecord read : reads ) { - notifyOfCurrentPosition(read); - // most of the time maybeDuplicatedReads is empty - // TODO -- I believe that because of the ordering of reads that as soon as we don't find a read in the - // TODO -- potential list of duplicates we can clear the hashset - if ( ! maybeDuplicatedReads.isEmpty() && maybeDuplicatedReads.contains(read) ) { - if ( DEBUG ) logger.warn("Skipping duplicated " + read.getReadName()); - } else { - if ( DEBUG ) logger.warn("Adding read " + read.getReadName() + " at " + engine.getGenomeLocParser().createGenomeLoc(read) + " from provider " + dataProvider); - myReads.add((GATKSAMRecord)read); - } - } - - // skip this location -- it's not part of our engine intervals - if ( outsideEngineIntervals(location) ) - continue; - - if ( prevLoc != null && location.getStart() != prevLoc.getStop() + 1 ) { - // we've move across some interval boundary, restart profile - profile = incorporateActiveRegions(profile, activeRegions); - } - - dataProvider.getShard().getReadMetrics().incrementNumIterations(); - - // create reference context. Note that if we have a pileup of "extended events", the context will - // hold the (longest) stretch of deleted reference bases (if deletions are present in the pileup). - final ReferenceContext refContext = referenceView.getReferenceContext(location); - - // Iterate forward to get all reference ordered data covering this location - final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataAtLocus(locus.getLocation(), refContext); - - // Call the walkers isActive function for this locus and add them to the list to be integrated later - profile.add(walkerActiveProb(walker, tracker, refContext, locus, location)); - - prevLoc = location; - - printProgress(locus.getLocation()); - } - - updateCumulativeMetrics(dataProvider.getShard()); - - if ( ! profile.isEmpty() ) - incorporateActiveRegions(profile, activeRegions); - - // add active regions to queue of regions to process - // first check if can merge active regions over shard boundaries - if( !activeRegions.isEmpty() ) { - if( !workQueue.isEmpty() ) { - final ActiveRegion last = workQueue.getLast(); - final ActiveRegion first = activeRegions.get(0); - if( last.isActive == first.isActive && last.getLocation().contiguousP(first.getLocation()) && last.getLocation().size() + first.getLocation().size() <= getMaxRegionSize() ) { - workQueue.removeLast(); - activeRegions.remove(first); - workQueue.add( new ActiveRegion(last.getLocation().union(first.getLocation()), first.isActive, this.engine.getGenomeLocParser(), getActiveRegionExtension()) ); - } - } - workQueue.addAll( activeRegions ); - } - - logger.debug("Integrated " + profile.size() + " isActive calls into " + activeRegions.size() + " regions." ); - - // now go and process all of the active regions - sum = processActiveRegions(walker, sum, false); - - return sum; - } - - private GenomeLoc startOfLiveRegion = null; - - protected void notifyOfCurrentPosition(final GATKSAMRecord read) { - notifyOfCurrentPosition(engine.getGenomeLocParser().createGenomeLoc(read)); - } - - protected void notifyOfCurrentPosition(final GenomeLoc currentLocation) { - if ( startOfLiveRegion == null ) - startOfLiveRegion = currentLocation; - else - startOfLiveRegion = startOfLiveRegion.max(currentLocation.getStartLocation()); - } - - protected GenomeLoc getStartOfLiveRegion() { - return startOfLiveRegion; - } - - protected boolean regionCompletelyWithinDeadZone(final GenomeLoc region, final boolean includeExtension) { - return (region.getStop() < (getStartOfLiveRegion().getStart() - (includeExtension ? getActiveRegionExtension() : 0))) - || ! region.onSameContig(getStartOfLiveRegion()); - } - - private T processActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { - if( walker.activeRegionOutStream != null ) { - writeActiveRegionsToStream(walker); - return sum; - } else { - return callWalkerMapOnActiveRegions(walker, sum, forceRegionsToBeActive); - } - } - - private T callWalkerMapOnActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { - // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them - // TODO can implement parallel traversal here - while( workQueue.peek() != null ) { - final GenomeLoc extendedLoc = workQueue.peek().getExtendedLoc(); - if ( forceRegionsToBeActive || regionCompletelyWithinDeadZone(extendedLoc, false) ) { - final ActiveRegion activeRegion = workQueue.remove(); - if ( DEBUG ) logger.warn("Processing active region " + activeRegion + " dead zone " + getStartOfLiveRegion()); - sum = processActiveRegion( activeRegion, sum, walker ); - } else { - break; - } - } - - return sum; - } - - @Override - public String toString() { - return "TraverseActiveRegionsOptimized"; - } - - private boolean readIsDead(final GATKSAMRecord read, final GenomeLoc readLoc, final ActiveRegion activeRegion) { - return readLoc.getStop() < activeRegion.getLocation().getStart() && regionCompletelyWithinDeadZone(readLoc, true); - } - - @Override - protected T processActiveRegion(final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker) { - final Iterator liveReads = myReads.iterator(); - while ( liveReads.hasNext() ) { - boolean killed = false; - final GATKSAMRecord read = liveReads.next(); - final GenomeLoc readLoc = this.engine.getGenomeLocParser().createGenomeLoc( read ); - - if( activeRegion.getLocation().overlapsP( readLoc ) ) { - activeRegion.add(read); - - if ( ! walker.wantsNonPrimaryReads() ) { - if ( DEBUG ) logger.warn("Removing read " + read.getReadName() + " at " + readLoc + " with dead zone start " + getStartOfLiveRegion()); - liveReads.remove(); - killed = true; - } - } else if( walker.wantsExtendedReads() && activeRegion.getExtendedLoc().overlapsP( readLoc )) { - activeRegion.add( read ); - } - - if ( ! killed && readIsDead(read, readLoc, activeRegion) ) { - if ( DEBUG ) logger.warn("Removing read " + read.getReadName() + " at " + readLoc + " with dead zone start " + getStartOfLiveRegion()); - liveReads.remove(); - } - } - - logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); - final M x = walker.map(activeRegion, null); - return walker.reduce( x, sum ); - } - - - /** - * Special function called in LinearMicroScheduler to empty out the work queue. - * Ugly for now but will be cleaned up when we push this functionality more into the engine - */ - @Override - public T endTraversal(final Walker walker, T sum) { - return processActiveRegions((ActiveRegionWalker)walker, sum, true); - } - -} diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginal.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginal.java deleted file mode 100644 index 0786bc800..000000000 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginal.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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.traversals; - -import org.apache.log4j.Logger; -import org.broadinstitute.sting.gatk.WalkerManager; -import org.broadinstitute.sting.gatk.contexts.AlignmentContext; -import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.sting.gatk.datasources.providers.*; -import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; -import org.broadinstitute.sting.gatk.walkers.DataSource; -import org.broadinstitute.sting.gatk.walkers.Walker; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.activeregion.ActiveRegion; -import org.broadinstitute.sting.utils.activeregion.ActivityProfile; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; -import org.broadinstitute.sting.utils.pileup.PileupElement; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; - -import java.util.*; - -/** - * Created by IntelliJ IDEA. - * User: rpoplin - * Date: 12/9/11 - */ - -public class TraverseActiveRegionsOriginal extends TraverseActiveRegions { - private final LinkedHashSet myReads = new LinkedHashSet(); - - @Override - public T traverse( final ActiveRegionWalker walker, - final LocusShardDataProvider dataProvider, - T sum) { - logger.debug(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); - - final LocusView locusView = new AllLocusView(dataProvider); - - final LocusReferenceView referenceView = new LocusReferenceView( walker, dataProvider ); - final int activeRegionExtension = walker.getClass().getAnnotation(ActiveRegionExtension.class).extension(); - final int maxRegionSize = walker.getClass().getAnnotation(ActiveRegionExtension.class).maxRegion(); - - int minStart = Integer.MAX_VALUE; - final List activeRegions = new LinkedList(); - ActivityProfile profile = new ActivityProfile(engine.getGenomeLocParser(), walker.hasPresetActiveRegions() ); - - ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); - - // We keep processing while the next reference location is within the interval - GenomeLoc prevLoc = null; - while( locusView.hasNext() ) { - final AlignmentContext locus = locusView.next(); - final GenomeLoc location = locus.getLocation(); - - // Grab all the previously unseen reads from this pileup and add them to the massive read list - // Note that this must occur before we leave because we are outside the intervals because - // reads may occur outside our intervals but overlap them in the future - // TODO -- this whole HashSet logic should be changed to a linked list of reads with - // TODO -- subsequent pass over them to find the ones overlapping the active regions - for( final PileupElement p : locus.getBasePileup() ) { - final GATKSAMRecord read = p.getRead(); - if( !myReads.contains(read) ) { - myReads.add(read); - } - - // If this is the last pileup for this shard calculate the minimum alignment start so that we know - // which active regions in the work queue are now safe to process - minStart = Math.min(minStart, read.getAlignmentStart()); - } - - // skip this location -- it's not part of our engine intervals - if ( outsideEngineIntervals(location) ) - continue; - - if ( prevLoc != null && location.getStart() != prevLoc.getStop() + 1 ) { - // we've move across some interval boundary, restart profile - profile = incorporateActiveRegions(profile, activeRegions, activeRegionExtension, maxRegionSize); - } - - dataProvider.getShard().getReadMetrics().incrementNumIterations(); - - // create reference context. Note that if we have a pileup of "extended events", the context will - // hold the (longest) stretch of deleted reference bases (if deletions are present in the pileup). - final ReferenceContext refContext = referenceView.getReferenceContext(location); - - // Iterate forward to get all reference ordered data covering this location - final RefMetaDataTracker tracker = referenceOrderedDataView.getReferenceOrderedDataAtLocus(locus.getLocation(), refContext); - - // Call the walkers isActive function for this locus and add them to the list to be integrated later - profile.add(walkerActiveProb(walker, tracker, refContext, locus, location)); - - prevLoc = location; - - printProgress(locus.getLocation()); - } - - updateCumulativeMetrics(dataProvider.getShard()); - - if ( ! profile.isEmpty() ) - incorporateActiveRegions(profile, activeRegions, activeRegionExtension, maxRegionSize); - - // add active regions to queue of regions to process - // first check if can merge active regions over shard boundaries - if( !activeRegions.isEmpty() ) { - if( !workQueue.isEmpty() ) { - final ActiveRegion last = workQueue.getLast(); - final ActiveRegion first = activeRegions.get(0); - if( last.isActive == first.isActive && last.getLocation().contiguousP(first.getLocation()) && last.getLocation().size() + first.getLocation().size() <= maxRegionSize ) { - workQueue.removeLast(); - activeRegions.remove(first); - workQueue.add( new ActiveRegion(last.getLocation().union(first.getLocation()), first.isActive, this.engine.getGenomeLocParser(), activeRegionExtension) ); - } - } - workQueue.addAll( activeRegions ); - } - - logger.debug("Integrated " + profile.size() + " isActive calls into " + activeRegions.size() + " regions." ); - - // now go and process all of the active regions - sum = processActiveRegions(walker, sum, minStart, dataProvider.getLocus().getContig()); - - return sum; - } - - /** - * Take the individual isActive calls and integrate them into contiguous active regions and - * add these blocks of work to the work queue - * band-pass filter the list of isActive probabilities and turn into active regions - * - * @param profile - * @param activeRegions - * @param activeRegionExtension - * @param maxRegionSize - * @return - */ - private ActivityProfile incorporateActiveRegions(final ActivityProfile profile, - final List activeRegions, - final int activeRegionExtension, - final int maxRegionSize) { - if ( profile.isEmpty() ) - throw new IllegalStateException("trying to incorporate an empty active profile " + profile); - - final ActivityProfile bandPassFiltered = profile.bandPassFilter(); - activeRegions.addAll(bandPassFiltered.createActiveRegions( activeRegionExtension, maxRegionSize )); - return new ActivityProfile( engine.getGenomeLocParser(), profile.hasPresetRegions() ); - } - - // -------------------------------------------------------------------------------- - // - // code to handle processing active regions - // - // -------------------------------------------------------------------------------- - - private T processActiveRegions( final ActiveRegionWalker walker, T sum, final int minStart, final String currentContig ) { - if( walker.activeRegionOutStream != null ) { - writeActiveRegionsToStream(walker); - return sum; - } else { - return callWalkerMapOnActiveRegions(walker, sum, minStart, currentContig); - } - } - - private T callWalkerMapOnActiveRegions( final ActiveRegionWalker walker, T sum, final int minStart, final String currentContig ) { - // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them - // TODO can implement parallel traversal here - while( workQueue.peek() != null ) { - final GenomeLoc extendedLoc = workQueue.peek().getExtendedLoc(); - if ( extendedLoc.getStop() < minStart || (currentContig != null && !workQueue.peek().getExtendedLoc().getContig().equals(currentContig))) { - final ActiveRegion activeRegion = workQueue.remove(); - sum = processActiveRegion( activeRegion, sum, walker ); - } else { - break; - } - } - - return sum; - } - - @Override - protected T processActiveRegion( final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker ) { - final ArrayList placedReads = new ArrayList(); - for( final GATKSAMRecord read : myReads ) { - final GenomeLoc readLoc = this.engine.getGenomeLocParser().createGenomeLoc( read ); - if( activeRegion.getLocation().overlapsP( readLoc ) ) { - // The region which the highest amount of overlap is chosen as the primary region for the read (tie breaking is done as right most region) - long maxOverlap = activeRegion.getLocation().sizeOfOverlap( readLoc ); - ActiveRegion bestRegion = activeRegion; - for( final ActiveRegion otherRegionToTest : workQueue ) { - if( otherRegionToTest.getLocation().sizeOfOverlap(readLoc) >= maxOverlap ) { - maxOverlap = otherRegionToTest.getLocation().sizeOfOverlap( readLoc ); - bestRegion = otherRegionToTest; - } - } - bestRegion.add( read ); - - // The read is also added to all other regions in which it overlaps but marked as non-primary - if( walker.wantsNonPrimaryReads() ) { - if( !bestRegion.equals(activeRegion) ) { - activeRegion.add( read ); - } - for( final ActiveRegion otherRegionToTest : workQueue ) { - if( !bestRegion.equals(otherRegionToTest) ) { - // check for non-primary vs. extended - if ( otherRegionToTest.getLocation().overlapsP( readLoc ) ) { - otherRegionToTest.add( read ); - } else if ( walker.wantsExtendedReads() && otherRegionToTest.getExtendedLoc().overlapsP( readLoc ) ) { - otherRegionToTest.add( read ); - } - } - } - } - placedReads.add( read ); - // check for non-primary vs. extended - } else if( activeRegion.getLocation().overlapsP( readLoc ) ) { - if ( walker.wantsNonPrimaryReads() ) { - activeRegion.add( read ); - } - } else if( walker.wantsExtendedReads() && activeRegion.getExtendedLoc().overlapsP( readLoc )) { - activeRegion.add( read ); - } - } - myReads.removeAll( placedReads ); // remove all the reads which have been placed into their active region - // WARNING: This hashset relies on reads being exactly equal when they are placed in the list as when they are removed. So the ActiveRegionWalker can't modify the reads in any way. - - logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); - final M x = walker.map( activeRegion, null ); - return walker.reduce( x, sum ); - } - - /** - * Special function called in LinearMicroScheduler to empty out the work queue. - * Ugly for now but will be cleaned up when we push this functionality more into the engine - */ - public T endTraversal( final Walker walker, T sum) { - return processActiveRegions((ActiveRegionWalker) walker, sum, Integer.MAX_VALUE, null); - } -} diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginalUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginalUnitTest.java deleted file mode 100644 index 35a0931df..000000000 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOriginalUnitTest.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * 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.traversals; - -import com.google.java.contract.PreconditionError; -import net.sf.samtools.*; -import org.broadinstitute.sting.commandline.Tags; -import org.broadinstitute.sting.gatk.datasources.reads.*; -import org.broadinstitute.sting.gatk.resourcemanagement.ThreadAllocation; -import org.broadinstitute.sting.gatk.walkers.Walker; -import org.broadinstitute.sting.utils.GenomeLocSortedSet; -import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; -import org.broadinstitute.sting.utils.interval.IntervalMergingRule; -import org.broadinstitute.sting.utils.interval.IntervalUtils; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import net.sf.picard.reference.IndexedFastaSequenceFile; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.sting.gatk.contexts.AlignmentContext; -import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.sting.gatk.datasources.providers.LocusShardDataProvider; -import org.broadinstitute.sting.gatk.datasources.rmd.ReferenceOrderedDataSource; -import org.broadinstitute.sting.gatk.executive.WindowMaker; -import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.activeregion.ActiveRegion; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; -import org.broadinstitute.sting.utils.sam.ReadUtils; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.*; - - -/** - * Created with IntelliJ IDEA. - * User: depristo - * Date: 1/10/13 - * Time: 8:03 PM - * To change this template use File | Settings | File Templates. - */ -public class TraverseActiveRegionsOriginalUnitTest extends BaseTest { - - private class DummyActiveRegionWalker extends ActiveRegionWalker { - private final double prob; - private EnumSet states = super.desiredReadStates(); - - protected List isActiveCalls = new ArrayList(); - protected Map mappedActiveRegions = new HashMap(); - - public DummyActiveRegionWalker() { - this.prob = 1.0; - } - - public DummyActiveRegionWalker(double constProb) { - this.prob = constProb; - } - - public DummyActiveRegionWalker(EnumSet wantStates) { - this.prob = 1.0; - this.states = wantStates; - } - - @Override - public EnumSet desiredReadStates() { - return states; - } - - @Override - public ActivityProfileResult isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { - isActiveCalls.add(ref.getLocus()); - return new ActivityProfileResult(ref.getLocus(), prob); - } - - @Override - public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) { - mappedActiveRegions.put(activeRegion.getLocation(), activeRegion); - return 0; - } - - @Override - public Integer reduceInit() { - return 0; - } - - @Override - public Integer reduce(Integer value, Integer sum) { - return 0; - } - } - - private final TraverseActiveRegions t = new TraverseActiveRegionsOriginal(); - - private IndexedFastaSequenceFile reference; - private SAMSequenceDictionary dictionary; - private GenomeLocParser genomeLocParser; - - private List intervals; - - private static final String testBAM = "TraverseActiveRegionsUnitTest.bam"; - private static final String testBAI = "TraverseActiveRegionsUnitTest.bai"; - - @BeforeClass - private void init() throws FileNotFoundException { - reference = new CachingIndexedFastaSequenceFile(new File(hg19Reference)); - dictionary = reference.getSequenceDictionary(); - genomeLocParser = new GenomeLocParser(dictionary); - - // TODO: reads with indels - // TODO: reads which span many regions - // TODO: reads which are partially between intervals (in/outside extension) - // TODO: duplicate reads - // TODO: read at the end of a contig - // TODO: reads which are completely outside intervals but within extension - // TODO: test the extension itself - // TODO: unmapped reads - - intervals = new ArrayList(); - intervals.add(genomeLocParser.createGenomeLoc("1", 10, 20)); - intervals.add(genomeLocParser.createGenomeLoc("1", 1, 999)); - intervals.add(genomeLocParser.createGenomeLoc("1", 1000, 1999)); - intervals.add(genomeLocParser.createGenomeLoc("1", 2000, 2999)); - intervals.add(genomeLocParser.createGenomeLoc("1", 10000, 20000)); - intervals.add(genomeLocParser.createGenomeLoc("2", 1, 100)); - intervals.add(genomeLocParser.createGenomeLoc("20", 10000, 10100)); - intervals = IntervalUtils.sortAndMergeIntervals(genomeLocParser, intervals, IntervalMergingRule.OVERLAPPING_ONLY).toList(); - - List reads = new ArrayList(); - reads.add(buildSAMRecord("simple", "1", 100, 200)); - reads.add(buildSAMRecord("overlap_equal", "1", 10, 20)); - reads.add(buildSAMRecord("overlap_unequal", "1", 10, 21)); - reads.add(buildSAMRecord("boundary_equal", "1", 1990, 2009)); - reads.add(buildSAMRecord("boundary_unequal", "1", 1990, 2008)); - reads.add(buildSAMRecord("boundary_1_pre", "1", 1950, 2000)); - reads.add(buildSAMRecord("boundary_1_post", "1", 1999, 2050)); - reads.add(buildSAMRecord("extended_and_np", "1", 990, 1990)); - reads.add(buildSAMRecord("outside_intervals", "1", 5000, 6000)); - reads.add(buildSAMRecord("shard_boundary_1_pre", "1", 16300, 16385)); - reads.add(buildSAMRecord("shard_boundary_1_post", "1", 16384, 16400)); - reads.add(buildSAMRecord("shard_boundary_equal", "1", 16355, 16414)); - reads.add(buildSAMRecord("simple20", "20", 10025, 10075)); - - createBAM(reads); - } - - private void createBAM(List reads) { - File outFile = new File(testBAM); - outFile.deleteOnExit(); - File indexFile = new File(testBAI); - indexFile.deleteOnExit(); - - SAMFileWriter out = new SAMFileWriterFactory().setCreateIndex(true).makeBAMWriter(reads.get(0).getHeader(), true, outFile); - for (GATKSAMRecord read : ReadUtils.sortReadsByCoordinate(reads)) { - out.addAlignment(read); - } - out.close(); - } - - @Test - public void testAllBasesSeen() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); - - List activeIntervals = getIsActiveIntervals(walker, intervals); - // Contract: Every genome position in the analysis interval(s) is processed by the walker's isActive() call - verifyEqualIntervals(intervals, activeIntervals); - } - - private List getIsActiveIntervals(DummyActiveRegionWalker walker, List intervals) { - List activeIntervals = new ArrayList(); - for (LocusShardDataProvider dataProvider : createDataProviders(walker, intervals, testBAM)) { - t.traverse(walker, dataProvider, 0); - activeIntervals.addAll(walker.isActiveCalls); - } - - return activeIntervals; - } - - @Test (expectedExceptions = PreconditionError.class) - public void testIsActiveRangeLow () { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(-0.1); - getActiveRegions(walker, intervals).values(); - } - - @Test (expectedExceptions = PreconditionError.class) - public void testIsActiveRangeHigh () { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(1.1); - getActiveRegions(walker, intervals).values(); - } - - @Test - public void testActiveRegionCoverage() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); - - Collection activeRegions = getActiveRegions(walker, intervals).values(); - verifyActiveRegionCoverage(intervals, activeRegions); - } - - private void verifyActiveRegionCoverage(List intervals, Collection activeRegions) { - List intervalStarts = new ArrayList(); - List intervalStops = new ArrayList(); - - for (GenomeLoc interval : intervals) { - intervalStarts.add(interval.getStartLocation()); - intervalStops.add(interval.getStopLocation()); - } - - Map baseRegionMap = new HashMap(); - - for (ActiveRegion activeRegion : activeRegions) { - for (GenomeLoc activeLoc : toSingleBaseLocs(activeRegion.getLocation())) { - // Contract: Regions do not overlap - Assert.assertFalse(baseRegionMap.containsKey(activeLoc), "Genome location " + activeLoc + " is assigned to more than one region"); - baseRegionMap.put(activeLoc, activeRegion); - } - - GenomeLoc start = activeRegion.getLocation().getStartLocation(); - if (intervalStarts.contains(start)) - intervalStarts.remove(start); - - GenomeLoc stop = activeRegion.getLocation().getStopLocation(); - if (intervalStops.contains(stop)) - intervalStops.remove(stop); - } - - for (GenomeLoc baseLoc : toSingleBaseLocs(intervals)) { - // Contract: Each location in the interval(s) is in exactly one region - // Contract: The total set of regions exactly matches the analysis interval(s) - Assert.assertTrue(baseRegionMap.containsKey(baseLoc), "Genome location " + baseLoc + " is not assigned to any region"); - baseRegionMap.remove(baseLoc); - } - - // Contract: The total set of regions exactly matches the analysis interval(s) - Assert.assertEquals(baseRegionMap.size(), 0, "Active regions contain base(s) outside of the given intervals"); - - // Contract: All explicit interval boundaries must also be region boundaries - Assert.assertEquals(intervalStarts.size(), 0, "Interval start location does not match an active region start location"); - Assert.assertEquals(intervalStops.size(), 0, "Interval stop location does not match an active region stop location"); - } - - @Test - public void testActiveRegionExtensionOnContig() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); - - Collection activeRegions = getActiveRegions(walker, intervals).values(); - for (ActiveRegion activeRegion : activeRegions) { - GenomeLoc loc = activeRegion.getExtendedLoc(); - - // Contract: active region extensions must stay on the contig - Assert.assertTrue(loc.getStart() > 0, "Active region extension begins at location " + loc.getStart() + ", past the left end of the contig"); - int refLen = dictionary.getSequence(loc.getContigIndex()).getSequenceLength(); - Assert.assertTrue(loc.getStop() <= refLen, "Active region extension ends at location " + loc.getStop() + ", past the right end of the contig"); - } - } - - @Test - public void testPrimaryReadMapping() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); - - // Contract: Each read has the Primary state in a single region (or none) - // This is the region of maximum overlap for the read (earlier if tied) - - // simple: Primary in 1:1-999 - // overlap_equal: Primary in 1:1-999 - // overlap_unequal: Primary in 1:1-999 - // boundary_equal: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_post: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // extended_and_np: Non-Primary in 1:1-999, Primary in 1:1000-1999, Extended in 1:2000-2999 - // outside_intervals: none - // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927 - // shard_boundary_1_post: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // shard_boundary_equal: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // simple20: Primary in 20:10000-10100 - - Map activeRegions = getActiveRegions(walker, intervals); - ActiveRegion region; - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999)); - verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999)); - verifyReadMapping(region, "boundary_unequal", "extended_and_np", "boundary_1_pre"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); - verifyReadMapping(region, "boundary_equal", "boundary_1_post"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); - verifyReadMapping(region, "shard_boundary_1_pre"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); - verifyReadMapping(region, "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); - verifyReadMapping(region, "simple20"); - } - - @Test - public void testNonPrimaryReadMapping() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker( - EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY)); - - // Contract: Each read has the Primary state in a single region (or none) - // This is the region of maximum overlap for the read (earlier if tied) - - // Contract: Each read has the Non-Primary state in all other regions it overlaps - - // simple: Primary in 1:1-999 - // overlap_equal: Primary in 1:1-999 - // overlap_unequal: Primary in 1:1-999 - // boundary_equal: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_post: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // extended_and_np: Non-Primary in 1:1-999, Primary in 1:1000-1999, Extended in 1:2000-2999 - // outside_intervals: none - // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927 - // shard_boundary_1_post: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // shard_boundary_equal: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // simple20: Primary in 20:10000-10100 - - Map activeRegions = getActiveRegions(walker, intervals); - ActiveRegion region; - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999)); - verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal", "extended_and_np"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999)); - verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); - verifyReadMapping(region, "boundary_equal", "boundary_unequal", "boundary_1_pre", "boundary_1_post"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); - verifyReadMapping(region, "simple20"); - } - - @Test - public void testExtendedReadMapping() { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker( - EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED)); - - // Contract: Each read has the Primary state in a single region (or none) - // This is the region of maximum overlap for the read (earlier if tied) - - // Contract: Each read has the Non-Primary state in all other regions it overlaps - // Contract: Each read has the Extended state in regions where it only overlaps if the region is extended - - // simple: Primary in 1:1-999 - // overlap_equal: Primary in 1:1-999 - // overlap_unequal: Primary in 1:1-999 - // boundary_equal: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // boundary_unequal: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_pre: Primary in 1:1000-1999, Non-Primary in 1:2000-2999 - // boundary_1_post: Non-Primary in 1:1000-1999, Primary in 1:2000-2999 - // extended_and_np: Non-Primary in 1:1-999, Primary in 1:1000-1999, Extended in 1:2000-2999 - // outside_intervals: none - // shard_boundary_1_pre: Primary in 1:14908-16384, Non-Primary in 1:16385-16927 - // shard_boundary_1_post: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // shard_boundary_equal: Non-Primary in 1:14908-16384, Primary in 1:16385-16927 - // simple20: Primary in 20:10000-10100 - - Map activeRegions = getActiveRegions(walker, intervals); - ActiveRegion region; - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1, 999)); - verifyReadMapping(region, "simple", "overlap_equal", "overlap_unequal", "extended_and_np"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 1000, 1999)); - verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); - verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); - verifyReadMapping(region, "simple20"); - } - - @Test - public void testUnmappedReads() { - // TODO - } - - private void verifyReadMapping(ActiveRegion region, String... reads) { - Collection wantReads = new ArrayList(Arrays.asList(reads)); - for (SAMRecord read : region.getReads()) { - String regionReadName = read.getReadName(); - Assert.assertTrue(wantReads.contains(regionReadName), "Read " + regionReadName + " assigned to active region " + region); - wantReads.remove(regionReadName); - } - - Assert.assertTrue(wantReads.isEmpty(), "Reads missing in active region " + region); - } - - private Map getActiveRegions(DummyActiveRegionWalker walker, List intervals) { - for (LocusShardDataProvider dataProvider : createDataProviders(walker, intervals, testBAM)) - t.traverse(walker, dataProvider, 0); - - t.endTraversal(walker, 0); - - return walker.mappedActiveRegions; - } - - private Collection toSingleBaseLocs(GenomeLoc interval) { - List bases = new ArrayList(); - if (interval.size() == 1) - bases.add(interval); - else { - for (int location = interval.getStart(); location <= interval.getStop(); location++) - bases.add(genomeLocParser.createGenomeLoc(interval.getContig(), location, location)); - } - - return bases; - } - - private Collection toSingleBaseLocs(List intervals) { - Set bases = new TreeSet(); // for sorting and uniqueness - for (GenomeLoc interval : intervals) - bases.addAll(toSingleBaseLocs(interval)); - - return bases; - } - - private void verifyEqualIntervals(List aIntervals, List bIntervals) { - Collection aBases = toSingleBaseLocs(aIntervals); - Collection bBases = toSingleBaseLocs(bIntervals); - - Assert.assertTrue(aBases.size() == bBases.size(), "Interval lists have a differing number of bases: " + aBases.size() + " vs. " + bBases.size()); - - Iterator aIter = aBases.iterator(); - Iterator bIter = bBases.iterator(); - while (aIter.hasNext() && bIter.hasNext()) { - GenomeLoc aLoc = aIter.next(); - GenomeLoc bLoc = bIter.next(); - Assert.assertTrue(aLoc.equals(bLoc), "Interval locations do not match: " + aLoc + " vs. " + bLoc); - } - } - - // copied from LocusViewTemplate - protected GATKSAMRecord buildSAMRecord(String readName, String contig, int alignmentStart, int alignmentEnd) { - SAMFileHeader header = ArtificialSAMUtils.createDefaultReadGroup(new SAMFileHeader(), "test", "test"); - header.setSequenceDictionary(dictionary); - header.setSortOrder(SAMFileHeader.SortOrder.coordinate); - GATKSAMRecord record = new GATKSAMRecord(header); - - record.setReadName(readName); - record.setReferenceIndex(dictionary.getSequenceIndex(contig)); - record.setAlignmentStart(alignmentStart); - - Cigar cigar = new Cigar(); - int len = alignmentEnd - alignmentStart + 1; - cigar.add(new CigarElement(len, CigarOperator.M)); - record.setCigar(cigar); - record.setReadString(new String(new char[len]).replace("\0", "A")); - record.setBaseQualities(new byte[len]); - - return record; - } - - private List createDataProviders(final Walker walker, List intervals, String bamFile) { - GenomeAnalysisEngine engine = new GenomeAnalysisEngine(); - engine.setGenomeLocParser(genomeLocParser); - t.initialize(engine, walker); - - Collection samFiles = new ArrayList(); - SAMReaderID readerID = new SAMReaderID(new File(bamFile), new Tags()); - samFiles.add(readerID); - - SAMDataSource dataSource = new SAMDataSource(samFiles, new ThreadAllocation(), null, genomeLocParser); - - List providers = new ArrayList(); - for (Shard shard : dataSource.createShardIteratorOverIntervals(new GenomeLocSortedSet(genomeLocParser, intervals), new LocusShardBalancer())) { - for (WindowMaker.WindowMakerIterator window : new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs())) { - providers.add(new LocusShardDataProvider(shard, shard.getReadProperties(), genomeLocParser, window.getLocus(), window, reference, new ArrayList())); - } - } - - return providers; - } -} diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimizedUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java similarity index 99% rename from public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimizedUnitTest.java rename to public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java index 038cd2853..c4dadbcce 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsOptimizedUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java @@ -76,7 +76,7 @@ import java.util.*; * Test the Active Region Traversal Contract * http://iwww.broadinstitute.org/gsa/wiki/index.php/Active_Region_Traversal_Contract */ -public class TraverseActiveRegionsOptimizedUnitTest extends BaseTest { +public class TraverseActiveRegionsUnitTest extends BaseTest { private final static boolean ENFORCE_CONTRACTS = false; private final static boolean DEBUG = false; @@ -131,7 +131,7 @@ public class TraverseActiveRegionsOptimizedUnitTest extends BaseTest { @DataProvider(name = "TraversalEngineProvider") public Object[][] makeTraversals() { final List traversals = new LinkedList(); - traversals.add(new Object[]{new TraverseActiveRegionsOptimized()}); + traversals.add(new Object[]{new TraverseActiveRegions()}); return traversals.toArray(new Object[][]{}); } @@ -537,7 +537,7 @@ public class TraverseActiveRegionsOptimizedUnitTest extends BaseTest { new ValidationExclusion(), new ArrayList(), new ArrayList(), - false, (byte)30, false, t instanceof TraverseActiveRegionsOptimized); + false, (byte)30, false, true); List providers = new ArrayList(); for (Shard shard : dataSource.createShardIteratorOverIntervals(new GenomeLocSortedSet(genomeLocParser, intervals), new LocusShardBalancer())) { From d3baa4b8cac086fb433b2e408e1165713b9ff0b7 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Tue, 15 Jan 2013 11:36:20 -0500 Subject: [PATCH 014/188] Have Haplotype extend the Allele class. This way, we don't need to create a new Allele for every read/Haplotype pair to be placed in the PerReadAlleleLikelihoodMap (very inefficient). Also, now we can easily get the Haplotype associated with the best allele for a given read. --- .../haplotypecaller/HaplotypeCaller.java | 87 ++++++++++++------- .../LikelihoodCalculationEngine.java | 3 +- .../broadinstitute/sting/utils/Haplotype.java | 64 +++++++------- .../variant/variantcontext/Allele.java | 4 +- 4 files changed, 93 insertions(+), 65 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 00db62bff..04da91f65 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -47,7 +47,6 @@ package org.broadinstitute.sting.gatk.walkers.haplotypecaller; import com.google.java.contract.Ensures; -import com.sun.corba.se.impl.logging.UtilSystemException; import net.sf.samtools.*; import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.CommandLineGATK; @@ -155,7 +154,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem protected StingSAMFileWriter bamWriter = null; private SAMFileHeader bamHeader = null; private long uniqueNameCounter = 1; - private final String readGroupId = "ArtificialHaplotype"; + private final static String readGroupId = "ArtificialHaplotype"; /** * The PairHMM implementation to use for genotype likelihood calculations. The various implementations balance a tradeoff of accuracy and runtime. @@ -338,20 +337,8 @@ public class HaplotypeCaller extends ActiveRegionWalker implem likelihoodCalculationEngine = new LikelihoodCalculationEngine( (byte)gcpHMM, DEBUG, pairHMM ); genotypingEngine = new GenotypingEngine( DEBUG, annotationEngine, USE_FILTERED_READ_MAP_FOR_ANNOTATIONS ); - if ( bamWriter != null ) { - // prepare the bam header - bamHeader = new SAMFileHeader(); - bamHeader.setSequenceDictionary(getToolkit().getSAMFileHeader().getSequenceDictionary()); - final List readGroups = new ArrayList(1); - final SAMReadGroupRecord rg = new SAMReadGroupRecord(readGroupId); - rg.setSample("HC"); - rg.setSequencingCenter("BI"); - readGroups.add(rg); - bamHeader.setReadGroups(readGroups); - bamHeader.setSortOrder(SAMFileHeader.SortOrder.coordinate); - bamWriter.writeHeader(bamHeader); - bamWriter.setPresorted(true); - } + if ( bamWriter != null ) + setupBamWriter(); } //--------------------------------------------------------------------------------------------------------------- @@ -461,8 +448,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem if( UG_engine.getUAC().GenotypingMode == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES && activeAllelesToGenotype.isEmpty() ) { return 0; } // No alleles found in this region so nothing to do! finalizeActiveRegion( activeRegion ); // merge overlapping fragments, clip adapter and low qual tails - final Haplotype referenceHaplotype = new Haplotype(activeRegion.getActiveRegionReference(referenceReader)); // Create the reference haplotype which is the bases from the reference that make up the active region - referenceHaplotype.setIsReference(true); + final Haplotype referenceHaplotype = new Haplotype(activeRegion.getActiveRegionReference(referenceReader), true); // Create the reference haplotype which is the bases from the reference that make up the active region final byte[] fullReferenceWithPadding = activeRegion.getFullReference(referenceReader, REFERENCE_PADDING); //int PRUNE_FACTOR = Math.max(MIN_PRUNE_FACTOR, determinePruneFactorFromCoverage( activeRegion )); final ArrayList haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, getPaddedLoc(activeRegion), MIN_PRUNE_FACTOR, activeAllelesToGenotype ); @@ -498,22 +484,19 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } if ( bamWriter != null ) { + // sort the haplotypes in coordinate order and then write them to the bam Collections.sort( haplotypes, new Haplotype.HaplotypePositionComparator() ); final GenomeLoc paddedRefLoc = getPaddedLoc(activeRegion); - for ( Haplotype haplotype : haplotypes ) { - // TODO -- clean up this code - final GATKSAMRecord record = new GATKSAMRecord(bamHeader); - record.setReadBases(haplotype.getBases()); - record.setAlignmentStart(paddedRefLoc.getStart() + haplotype.getAlignmentStartHapwrtRef()); - record.setBaseQualities(Utils.dupBytes((byte) '!', haplotype.getBases().length)); - record.setCigar(haplotype.getCigar()); - record.setMappingQuality(bestHaplotypes.contains(haplotype) ? 60 : 0); - record.setReadName("HC" + uniqueNameCounter++); - record.setReadUnmappedFlag(false); - record.setReferenceIndex(activeRegion.getReferenceLoc().getContigIndex()); - record.setAttribute(SAMTag.RG.toString(), readGroupId); - record.setFlags(16); - bamWriter.addAlignment(record); + for ( Haplotype haplotype : haplotypes ) + writeHaplotype(haplotype, paddedRefLoc, bestHaplotypes.contains(haplotype)); + + // now, output the interesting reads for each sample + for ( final PerReadAlleleLikelihoodMap readAlleleLikelihoodMap : stratifiedReadMap.values() ) { + for ( Map.Entry> entry : readAlleleLikelihoodMap.getLikelihoodReadMap().entrySet() ) { + final Allele bestAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(entry.getValue()); + if ( bestAllele != Allele.NO_CALL ) + writeReadAgainstHaplotype(entry.getKey(), (Haplotype)bestAllele); + } } } @@ -608,6 +591,46 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } return returnMap; + } + + private void setupBamWriter() { + // prepare the bam header + bamHeader = new SAMFileHeader(); + bamHeader.setSequenceDictionary(getToolkit().getSAMFileHeader().getSequenceDictionary()); + bamHeader.setSortOrder(SAMFileHeader.SortOrder.coordinate); + + // include the original read groups plus a new artificial one for the haplotypes + final List readGroups = new ArrayList(getToolkit().getSAMFileHeader().getReadGroups()); + final SAMReadGroupRecord rg = new SAMReadGroupRecord(readGroupId); + rg.setSample("HC"); + rg.setSequencingCenter("BI"); + readGroups.add(rg); + bamHeader.setReadGroups(readGroups); + + bamWriter.writeHeader(bamHeader); + bamWriter.setPresorted(true); + } + + private void writeHaplotype(final Haplotype haplotype, final GenomeLoc paddedRefLoc, final boolean isAmongBestHaplotypes) { + final GATKSAMRecord record = new GATKSAMRecord(bamHeader); + record.setReadBases(haplotype.getBases()); + record.setAlignmentStart(paddedRefLoc.getStart() + haplotype.getAlignmentStartHapwrtRef()); + record.setBaseQualities(Utils.dupBytes((byte) '!', haplotype.getBases().length)); + record.setCigar(haplotype.getCigar()); + record.setMappingQuality(isAmongBestHaplotypes ? 60 : 0); + record.setReadName("HC" + uniqueNameCounter++); + record.setReadUnmappedFlag(false); + record.setReferenceIndex(paddedRefLoc.getContigIndex()); + record.setAttribute(SAMTag.RG.toString(), readGroupId); + record.setFlags(16); + bamWriter.addAlignment(record); + } + + private void writeReadAgainstHaplotype(final GATKSAMRecord read, final Haplotype haplotype) { + + + + } /* diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java index 8b844817d..e05ad85a9 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java @@ -138,6 +138,7 @@ public class LikelihoodCalculationEngine { readQuals[kkk] = ( readQuals[kkk] > (byte) read.getMappingQuality() ? (byte) read.getMappingQuality() : readQuals[kkk] ); // cap base quality by mapping quality //readQuals[kkk] = ( readQuals[kkk] > readInsQuals[kkk] ? readInsQuals[kkk] : readQuals[kkk] ); // cap base quality by base insertion quality, needs to be evaluated //readQuals[kkk] = ( readQuals[kkk] > readDelQuals[kkk] ? readDelQuals[kkk] : readQuals[kkk] ); // cap base quality by base deletion quality, needs to be evaluated + // TODO -- why is Q18 hard-coded here??? readQuals[kkk] = ( readQuals[kkk] < (byte) 18 ? QualityUtils.MIN_USABLE_Q_SCORE : readQuals[kkk] ); } @@ -151,7 +152,7 @@ public class LikelihoodCalculationEngine { final int haplotypeStart = ( previousHaplotypeSeen == null ? 0 : computeFirstDifferingPosition(haplotype.getBases(), previousHaplotypeSeen.getBases()) ); previousHaplotypeSeen = haplotype; - perReadAlleleLikelihoodMap.add(read, Allele.create(haplotype.getBases()), + perReadAlleleLikelihoodMap.add(read, haplotype, pairHMM.computeReadLikelihoodGivenHaplotypeLog10(haplotype.getBases(), read.getReadBases(), readQuals, readInsQuals, readDelQuals, overallGCP, haplotypeStart, jjj == 0)); } diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index 2706f2f99..4830bf053 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -37,59 +37,71 @@ import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.Serializable; import java.util.*; -public class Haplotype { - protected final byte[] bases; +public class Haplotype extends Allele { protected final double[] quals; private GenomeLoc genomeLocation = null; private HashMap eventMap = null; - private boolean isRef = false; private Cigar cigar; private int alignmentStartHapwrtRef; public int leftBreakPoint = 0; public int rightBreakPoint = 0; private Event artificialEvent = null; + /** + * Main constructor + * + * @param bases bases + * @param quals quals + * @param isRef is reference allele? + */ + public Haplotype( final byte[] bases, final double[] quals, final boolean isRef ) { + super(bases.clone(), isRef); + this.quals = quals.clone(); + } + /** * Create a simple consensus sequence with provided bases and a uniform quality over all bases of qual * * @param bases bases * @param qual qual */ - public Haplotype( final byte[] bases, final int qual ) { - this.bases = bases.clone(); + public Haplotype( final byte[] bases, final int qual, final boolean isRef ) { + super(bases.clone(), isRef); quals = new double[bases.length]; Arrays.fill(quals, (double)qual); } + public Haplotype( final byte[] bases, final int qual ) { + this(bases, qual, false); + } + + public Haplotype( final byte[] bases, final boolean isRef ) { + this(bases, 0, isRef); + } + public Haplotype( final byte[] bases, final double[] quals ) { - this.bases = bases.clone(); - this.quals = quals.clone(); + this(bases, quals, false); } public Haplotype( final byte[] bases ) { - this(bases, 0); + this(bases, 0, false); } protected Haplotype( final byte[] bases, final Event artificialEvent ) { - this(bases, 0); + this(bases, 0, false); this.artificialEvent = artificialEvent; } public Haplotype( final byte[] bases, final GenomeLoc loc ) { - this(bases); + this(bases, 0, false); this.genomeLocation = loc; } @Override public boolean equals( Object h ) { - return h instanceof Haplotype && Arrays.equals(bases, ((Haplotype) h).bases); + return h instanceof Haplotype && super.equals(h); } - @Override - public int hashCode() { - return Arrays.hashCode(bases); - } - public HashMap getEventMap() { return eventMap; } @@ -98,17 +110,9 @@ public class Haplotype { this.eventMap = eventMap; } - public boolean isReference() { - return isRef; - } - - public void setIsReference( boolean isRef ) { - this.isRef = isRef; - } - public double getQualitySum() { double s = 0; - for (int k=0; k < bases.length; k++) { + for (int k=0; k < quals.length; k++) { s += quals[k]; } return s; @@ -116,14 +120,14 @@ public class Haplotype { @Override public String toString() { - return new String(bases); + return getDisplayString(); } public double[] getQuals() { return quals.clone(); } public byte[] getBases() { - return bases.clone(); + return super.getBases().clone(); } public long getStartPosition() { @@ -178,13 +182,13 @@ public class Haplotype { public Haplotype insertAllele( final Allele refAllele, final Allele altAllele, final int refInsertLocation, final int genomicInsertLocation ) { // refInsertLocation is in ref haplotype offset coordinates NOT genomic coordinates final int haplotypeInsertLocation = ReadUtils.getReadCoordinateForReferenceCoordinate(alignmentStartHapwrtRef, cigar, refInsertLocation, ReadUtils.ClippingTail.RIGHT_TAIL, true); - if( haplotypeInsertLocation == -1 || haplotypeInsertLocation + refAllele.length() >= bases.length ) { // desired change falls inside deletion so don't bother creating a new haplotype + if( haplotypeInsertLocation == -1 || haplotypeInsertLocation + refAllele.length() >= getBases().length ) { // desired change falls inside deletion so don't bother creating a new haplotype return null; } byte[] newHaplotypeBases = new byte[]{}; - newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(bases, 0, haplotypeInsertLocation)); // bases before the variant + newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(getBases(), 0, haplotypeInsertLocation)); // bases before the variant newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, altAllele.getBases()); // the alt allele of the variant - newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(bases, haplotypeInsertLocation + refAllele.length(), bases.length)); // bases after the variant + newHaplotypeBases = ArrayUtils.addAll(newHaplotypeBases, ArrayUtils.subarray(getBases(), haplotypeInsertLocation + refAllele.length(), getBases().length)); // bases after the variant return new Haplotype(newHaplotypeBases, new Event(refAllele, altAllele, genomicInsertLocation)); } diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java b/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java index 33bca1a8a..0a0b4d0b7 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java @@ -111,7 +111,7 @@ public class Allele implements Comparable { /** A generic static NO_CALL allele for use */ // no public way to create an allele - private Allele(byte[] bases, boolean isRef) { + protected Allele(byte[] bases, boolean isRef) { // null alleles are no longer allowed if ( wouldBeNullAllele(bases) ) { throw new IllegalArgumentException("Null alleles are not supported"); @@ -140,7 +140,7 @@ public class Allele implements Comparable { throw new IllegalArgumentException("Unexpected base in allele bases \'" + new String(bases)+"\'"); } - private Allele(String bases, boolean isRef) { + protected Allele(String bases, boolean isRef) { this(bases.getBytes(), isRef); } From 327169b28360e24c025d98ad6967ff05d798ff2b Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Tue, 15 Jan 2013 12:13:45 -0500 Subject: [PATCH 015/188] Refactor the method that identifies the site overlap type into the type enum class (so it can be used elsewhere potentially). Completed todo item: for sites like (eval) 20 12345 A C 20 12345 A AC (comp) 20 12345 A C 20 12345 A ACCC the records will be matched by the presence of a non-empty intersection of alleles. Any leftover records are then paired with an empty variant context (as though the call was unique). This has one somewhat counterintuitive feature, which is that normally (eval) 20 12345 A AC (comp) 20 12345 A ACCC would be classified as 'ALLELES_DO_NOT_MATCH' (and not counted in genotype tables), in the presence of the SNP, they're counted as EVAL_ONLY and TRUTH_ONLY respectively. + integration test --- .../variantutils/ConcordanceMetrics.java | 40 +++++---- .../variantutils/GenotypeConcordance.java | 86 +++++++++++++++---- .../GenotypeConcordanceIntegrationTest.java | 11 +++ 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java index bb76006bf..8a87c9957 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java @@ -272,22 +272,7 @@ public class ConcordanceMetrics { @Requires({"evalVC != null","truthVC != null"}) private SiteConcordanceType getMatchType(VariantContext evalVC, VariantContext truthVC) { - if ( evalVC.isMonomorphicInSamples() ) - return SiteConcordanceType.TRUTH_ONLY; - if ( truthVC.isMonomorphicInSamples() ) - return SiteConcordanceType.EVAL_ONLY; - - boolean evalSusbsetTruth = VariantContextUtils.allelesAreSubset(evalVC,truthVC); - boolean truthSubsetEval = VariantContextUtils.allelesAreSubset(truthVC,evalVC); - - if ( evalSusbsetTruth && truthSubsetEval ) - return SiteConcordanceType.ALLELES_MATCH; - else if ( evalSusbsetTruth ) - return SiteConcordanceType.EVAL_SUBSET_TRUTH; - else if ( truthSubsetEval ) - return SiteConcordanceType.EVAL_SUPERSET_TRUTH; - - return SiteConcordanceType.ALLELES_DO_NOT_MATCH; + return SiteConcordanceType.getConcordanceType(evalVC,truthVC); } public int[] getSiteConcordance() { @@ -305,6 +290,27 @@ public class ConcordanceMetrics { EVAL_SUBSET_TRUTH, ALLELES_DO_NOT_MATCH, EVAL_ONLY, - TRUTH_ONLY + TRUTH_ONLY; + + public static SiteConcordanceType getConcordanceType(VariantContext eval, VariantContext truth) { + if ( eval.isMonomorphicInSamples() ) + return TRUTH_ONLY; + if ( truth.isMonomorphicInSamples() ) + return EVAL_ONLY; + + boolean evalSubsetTruth = VariantContextUtils.allelesAreSubset(eval,truth); + boolean truthSubsetEval = VariantContextUtils.allelesAreSubset(eval,truth); + + if ( evalSubsetTruth && truthSubsetEval ) + return ALLELES_MATCH; + + if ( evalSubsetTruth ) + return EVAL_SUBSET_TRUTH; + + if ( truthSubsetEval ) + return EVAL_SUPERSET_TRUTH; + + return ALLELES_DO_NOT_MATCH; + } } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 07c9a0d77..0cd1882df 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -64,7 +64,7 @@ import java.util.*; /** * A simple walker for performing genotype concordance calculations between two callsets */ -public class GenotypeConcordance extends RodWalker,ConcordanceMetrics> { +public class GenotypeConcordance extends RodWalker>,ConcordanceMetrics> { @Input(fullName="eval",shortName="eval",doc="The variants and genotypes to evaluate",required=true) RodBinding evalBinding; @@ -81,7 +81,6 @@ public class GenotypeConcordance extends RodWalker evalSamples; List compSamples; - // todo -- integration test coverage // todo -- deal with occurrences like: // Eval: 20 4000 A C // Eval: 20 4000 A AC @@ -89,6 +88,7 @@ public class GenotypeConcordance extends RodWalker map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { - Pair evalCompPair = null; + public List> map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + List> evalCompPair = new ArrayList>(3); if ( tracker != null && ( tracker.getValues(evalBinding,ref.getLocus()).size() > 0 || - tracker.getValues(compBinding,ref.getLocus()).size() > 0 ) ) { + tracker.getValues(compBinding,ref.getLocus()).size() > 0 ) ) { List eval = tracker.getValues(evalBinding,ref.getLocus()); List comp = tracker.getValues(compBinding,ref.getLocus()); if ( eval.size() > 1 || comp.size() > 1 ) { - logger.warn("Eval or Comp Rod at position "+ref.getLocus().toString()+" has multiple records. Site will be skipped."); - return evalCompPair; + logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving."); + evalCompPair = resolveMultipleRecords(eval,comp); + } else { + // if a rod is missing, explicitly create a variant context with 'missing' genotypes. Slow, but correct. + // note that if there is no eval rod there must be a comp rod, and also the reverse + VariantContext evalContext = eval.size() == 1 ? eval.get(0) : createEmptyContext(comp.get(0),evalSamples); + VariantContext compContext = comp.size() == 1 ? comp.get(0) : createEmptyContext(eval.get(0),compSamples); + evalContext = filterGenotypes(evalContext,ignoreFilters); + compContext = filterGenotypes(compContext,ignoreFilters); + evalCompPair.add(new Pair(evalContext,compContext)); } - // if a rod is missing, explicitly create a variant context with 'missing' genotypes. Slow, but correct. - // note that if there is no eval rod there must be a comp rod, and also the reverse - VariantContext evalContext = eval.size() == 1 ? eval.get(0) : createEmptyContext(ref,comp.get(0),evalSamples); - VariantContext compContext = comp.size() == 1 ? comp.get(0) : createEmptyContext(ref,eval.get(0),compSamples); - evalContext = filterGenotypes(evalContext,ignoreFilters); - compContext = filterGenotypes(compContext,ignoreFilters); - evalCompPair = new Pair(evalContext,compContext); } return evalCompPair; } - public ConcordanceMetrics reduce(Pair evalComp, ConcordanceMetrics metrics) { - if ( evalComp != null ) + /** + * The point of this method is to match up pairs of evals and comps by their alternate alleles. Basically multiple records could + * exist for a site such as: + * Eval: 20 4000 A C + * Eval: 20 4000 A AC + * Comp: 20 4000 A C + * So for each eval, loop through the comps. If the eval alleles (non-emptily) intersect the comp alleles, pair them up and remove + * that comp records. Continue until we're out of evals or comps. This is n^2, but should rarely actually happen. + * + * The remaining unpaired records get paird with an empty contexts. So in the example above we'd get a list of: + * 1 - (20,4000,A/C | 20,4000,A/C) + * 2 - (20,4000,A/AC | Empty ) + * @param evalList - list of eval variant contexts + * @param compList - list of comp variant contexts + * @return resolved pairs of the input lists + */ + private List> resolveMultipleRecords(List evalList, List compList) { + List> resolvedPairs = new ArrayList>(evalList.size()+compList.size()); // oversized but w/e + List pairedEval = new ArrayList(evalList.size()); + for ( VariantContext eval : evalList ) { + Set evalAlts = new HashSet(eval.getAlternateAlleles()); + VariantContext pairedComp = null; + for ( VariantContext comp : compList ) { + for ( Allele compAlt : comp.getAlternateAlleles() ) { + if ( evalAlts.contains(compAlt) ) { + // matching alt allele, pair these records + pairedComp = comp; + break; + } + } + } + if ( pairedComp != null ) { + compList.remove(pairedComp); + resolvedPairs.add(new Pair(eval,pairedComp)); + pairedEval.add(eval); + if ( compList.size() < 1 ) + break; + } + } + evalList.removeAll(pairedEval); + for ( VariantContext unpairedEval : evalList ) { + resolvedPairs.add(new Pair(unpairedEval,createEmptyContext(unpairedEval,compSamples))); + } + + for ( VariantContext unpairedComp : compList ) { + resolvedPairs.add(new Pair(createEmptyContext(unpairedComp,evalSamples),unpairedComp)); + } + + return resolvedPairs; + } + + public ConcordanceMetrics reduce(List> evalCompList, ConcordanceMetrics metrics) { + for ( Pair evalComp : evalCompList) metrics.update(evalComp.getFirst(),evalComp.getSecond()); return metrics; } @@ -233,7 +285,7 @@ public class GenotypeConcordance extends RodWalker samples) { + public VariantContext createEmptyContext(VariantContext other, List samples) { VariantContextBuilder builder = new VariantContextBuilder(); // set the alleles to be the same builder.alleles(other.getAlleles()); diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java index d4d8d6f8c..113f098e3 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java @@ -60,4 +60,15 @@ public class GenotypeConcordanceIntegrationTest extends WalkerTest { executeTest("test non-overlapping samples", spec); } + + @Test + public void testMultipleRecordsPerSite() { + WalkerTestSpec spec = new WalkerTestSpec( + baseTestString("GenotypeConcordance.multipleRecordsTest1.eval.vcf","GenotypeConcordance.multipleRecordsTest1.comp.vcf"), + 0, + Arrays.asList("fdf2cac15775c613f596c27247a76570") + ); + + executeTest("test multiple records per site",spec); + } } From 0d282a7750df16b154f87cc83e391188c70e1dab Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 00:12:02 -0500 Subject: [PATCH 017/188] Bam writing from HaplotypeCaller seems to be working on all my test cases. Note that it's a hidden debugging option for now. Please let me know if you notice any bad behavior with it. --- .../haplotypecaller/HaplotypeCaller.java | 60 +++++++++++++++++-- .../LikelihoodCalculationEngine.java | 4 -- .../broadinstitute/sting/utils/Haplotype.java | 8 --- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 04da91f65..4da2e1179 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -484,18 +484,17 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } if ( bamWriter != null ) { - // sort the haplotypes in coordinate order and then write them to the bam - Collections.sort( haplotypes, new Haplotype.HaplotypePositionComparator() ); + // write the haplotypes to the bam final GenomeLoc paddedRefLoc = getPaddedLoc(activeRegion); for ( Haplotype haplotype : haplotypes ) writeHaplotype(haplotype, paddedRefLoc, bestHaplotypes.contains(haplotype)); - // now, output the interesting reads for each sample + // next, output the interesting reads for each sample aligned against the appropriate haplotype for ( final PerReadAlleleLikelihoodMap readAlleleLikelihoodMap : stratifiedReadMap.values() ) { for ( Map.Entry> entry : readAlleleLikelihoodMap.getLikelihoodReadMap().entrySet() ) { final Allele bestAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(entry.getValue()); if ( bestAllele != Allele.NO_CALL ) - writeReadAgainstHaplotype(entry.getKey(), (Haplotype)bestAllele); + writeReadAgainstHaplotype(entry.getKey(), (Haplotype) bestAllele, paddedRefLoc.getStart()); } } } @@ -607,8 +606,8 @@ public class HaplotypeCaller extends ActiveRegionWalker implem readGroups.add(rg); bamHeader.setReadGroups(readGroups); + bamWriter.setPresorted(false); bamWriter.writeHeader(bamHeader); - bamWriter.setPresorted(true); } private void writeHaplotype(final Haplotype haplotype, final GenomeLoc paddedRefLoc, final boolean isAmongBestHaplotypes) { @@ -626,11 +625,60 @@ public class HaplotypeCaller extends ActiveRegionWalker implem bamWriter.addAlignment(record); } - private void writeReadAgainstHaplotype(final GATKSAMRecord read, final Haplotype haplotype) { + private void writeReadAgainstHaplotype(final GATKSAMRecord read, final Haplotype haplotype, final int referenceStart) { + final SWPairwiseAlignment swPairwiseAlignment = new SWPairwiseAlignment(haplotype.getBases(), read.getReadBases(), 5.0, -10.0, -22.0, -1.2); + final int readStartOnHaplotype = swPairwiseAlignment.getAlignmentStart2wrt1(); + final int readStartOnReference = referenceStart + haplotype.getAlignmentStartHapwrtRef() + readStartOnHaplotype; + read.setAlignmentStart(readStartOnReference); + final Cigar cigar = generateReadCigarFromHaplotype(read, readStartOnHaplotype, haplotype.getCigar()); + read.setCigar(cigar); + bamWriter.addAlignment(read); + } + private Cigar generateReadCigarFromHaplotype(final GATKSAMRecord read, final int readStartOnHaplotype, final Cigar haplotypeCigar) { + + int currentReadPos = 0; + int currentHapPos = 0; + final List readCigarElements = new ArrayList(); + + for ( final CigarElement cigarElement : haplotypeCigar.getCigarElements() ) { + + if ( cigarElement.getOperator() == CigarOperator.D ) { + if ( currentReadPos > 0 ) + readCigarElements.add(cigarElement); + } else if ( cigarElement.getOperator() == CigarOperator.M || cigarElement.getOperator() == CigarOperator.I ) { + + final int elementLength = cigarElement.getLength(); + final int nextReadPos = currentReadPos + elementLength; + final int nextHapPos = currentHapPos + elementLength; + + // do we want this element? + if ( currentReadPos > 0 ) { + // do we want the entire element? + if ( nextReadPos < read.getReadLength() ) { + readCigarElements.add(cigarElement); + currentReadPos = nextReadPos; + } + // otherwise, we can finish up and return the cigar + else { + readCigarElements.add(new CigarElement(read.getReadLength() - currentReadPos, cigarElement.getOperator())); + return new Cigar(readCigarElements); + } + } + // do we want part of the element to start? + else if ( currentReadPos == 0 && nextHapPos > readStartOnHaplotype ) { + currentReadPos = Math.min(nextHapPos - readStartOnHaplotype, read.getReadLength()); + readCigarElements.add(new CigarElement(currentReadPos, cigarElement.getOperator())); + } + + currentHapPos = nextHapPos; + } + } + + return new Cigar(readCigarElements); } /* diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java index e05ad85a9..aafdbf126 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java @@ -145,10 +145,6 @@ public class LikelihoodCalculationEngine { for( int jjj = 0; jjj < numHaplotypes; jjj++ ) { final Haplotype haplotype = haplotypes.get(jjj); - // TODO -- need to test against a reference/position with non-standard bases - //if ( !Allele.acceptableAlleleBases(haplotype.getBases(), false) ) - // continue; - final int haplotypeStart = ( previousHaplotypeSeen == null ? 0 : computeFirstDifferingPosition(haplotype.getBases(), previousHaplotypeSeen.getBases()) ); previousHaplotypeSeen = haplotype; diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index 4830bf053..8c40b9972 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -211,14 +211,6 @@ public class Haplotype extends Allele { } } - public static class HaplotypePositionComparator implements Comparator, Serializable { - @Override - public int compare( final Haplotype hap1, final Haplotype hap2 ) { - final int comp = hap1.getAlignmentStartHapwrtRef() - hap2.getAlignmentStartHapwrtRef(); - return comp == 0 ? HaplotypeBaseComparator.compareHaplotypeBases(hap1, hap2) : comp; - } - } - public static LinkedHashMap makeHaplotypeListFromAlleles(final List alleleList, final int startPos, final ReferenceContext ref, From 392b5cbcdfd5200f04d0b26f9e73d16399e17769 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 10:22:43 -0500 Subject: [PATCH 018/188] The CachingIndexedFastaSequenceFile now automatically converts IUPAC bases to Ns and errors out on other non-standard bases. This way walkers won't see anything except the standard bases plus Ns in the reference. Added option to turn off this feature (to maintain backwards compatibility). As part of this commit I cleaned up the BaseUtils code by adding a Base enum and removing all of the static indexes for each of the bases. This uncovered a bug in the way the DepthOfCoverage walker counts deletions (it was counting Ns instead!) that isn't covered by tests. Fortunately that walker is being deprecated soon... --- .../gatk/walkers/annotator/GCContent.java | 4 +- .../walkers/coverage/DepthOfCoverage.java | 2 +- .../coverage/DepthOfCoverageStats.java | 2 +- .../validation/ValidationAmplicons.java | 2 +- .../ConcordanceMetricsUnitTest.java | 48 ++++----- .../gatk/walkers/coverage/CoverageUtils.java | 6 +- .../walkers/coverage/GCContentByInterval.java | 2 +- .../CachingIndexedFastaSequenceFile.java | 44 +++++--- .../sting/utils/pileup/PileupElement.java | 3 +- .../sting/utils/sam/AlignmentUtils.java | 9 +- .../variant/utils/BaseUtils.java | 102 ++++++++++++------ .../variant/utils/BaseUtilsUnitTest.java | 15 +++ .../GenotypeLikelihoodsUnitTest.java | 6 +- 13 files changed, 153 insertions(+), 92 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java index 3bb3d7d5a..2b3290595 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java @@ -95,9 +95,9 @@ public class GCContent extends InfoFieldAnnotation implements ExperimentalAnnota for ( byte base : ref.getBases() ) { int baseIndex = BaseUtils.simpleBaseToBaseIndex(base); - if ( baseIndex == BaseUtils.gIndex || baseIndex == BaseUtils.cIndex ) + if ( baseIndex == BaseUtils.Base.G.ordinal() || baseIndex == BaseUtils.Base.C.ordinal() ) gc++; - else if ( baseIndex == BaseUtils.aIndex || baseIndex == BaseUtils.tIndex ) + else if ( baseIndex == BaseUtils.Base.A.ordinal() || baseIndex == BaseUtils.Base.T.ordinal() ) at++; else ; // ignore diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java index 1e4c55e0d..b10daab58 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java @@ -938,7 +938,7 @@ public class DepthOfCoverage extends LocusWalker { if ( lowerCaseSNPs ) { sequence.append(Character.toLowerCase((char) ref.getBase())); } else { - sequence.append((char) BaseUtils.N); + sequence.append((char) BaseUtils.Base.N.base); } rawSequence.append(Character.toUpperCase((char) ref.getBase())); diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java index 28f128dd3..6db44efd5 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java @@ -111,8 +111,8 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private Pair getData1() { - Allele reference_A = Allele.create(BaseUtils.A,true); - Allele alt_C = Allele.create(BaseUtils.C); + Allele reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_C = Allele.create(BaseUtils.Base.C.base); Genotype sam_1_1_eval = GenotypeBuilder.create("test1_sample1", Arrays.asList(reference_A,reference_A)); Genotype sam_1_2_eval = GenotypeBuilder.create("test1_sample2", Arrays.asList(reference_A,alt_C)); @@ -160,9 +160,9 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private Pair getData2() { - Allele reference_A = Allele.create(BaseUtils.A,true); - Allele alt_C = Allele.create(BaseUtils.C); - Allele alt_T = Allele.create(BaseUtils.T); + Allele reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_C = Allele.create(BaseUtils.Base.C.base); + Allele alt_T = Allele.create(BaseUtils.Base.T.base); Genotype sam_1_1_eval = GenotypeBuilder.create("test1_sample1", Arrays.asList(reference_A,reference_A)); Genotype sam_1_2_eval = GenotypeBuilder.create("test1_sample2", Arrays.asList(reference_A,alt_T)); @@ -213,10 +213,10 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private Pair getData3() { - Allele reference_ACT = Allele.create(new byte[]{BaseUtils.A,BaseUtils.C,BaseUtils.T},true); - Allele alt_AC = Allele.create(new byte[]{BaseUtils.A,BaseUtils.C}); - Allele alt_A = Allele.create(BaseUtils.A); - Allele alt_ATT = Allele.create(new byte[]{BaseUtils.A,BaseUtils.T,BaseUtils.T}); + Allele reference_ACT = Allele.create(new byte[]{BaseUtils.Base.A.base,BaseUtils.Base.C.base,BaseUtils.Base.T.base},true); + Allele alt_AC = Allele.create(new byte[]{BaseUtils.Base.A.base,BaseUtils.Base.C.base}); + Allele alt_A = Allele.create(BaseUtils.Base.A.base); + Allele alt_ATT = Allele.create(new byte[]{BaseUtils.Base.A.base,BaseUtils.Base.T.base,BaseUtils.Base.T.base}); Genotype sam_1_1_eval = GenotypeBuilder.create("test1_sample1", Arrays.asList(reference_ACT,alt_ATT)); Genotype sam_1_2_eval = GenotypeBuilder.create("test1_sample2", Arrays.asList(alt_A,alt_A)); @@ -267,9 +267,9 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private Pair getData4() { - Allele reference_A = Allele.create(BaseUtils.A,true); - Allele alt_C = Allele.create(BaseUtils.C); - Allele alt_T = Allele.create(BaseUtils.T); + Allele reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_C = Allele.create(BaseUtils.Base.C.base); + Allele alt_T = Allele.create(BaseUtils.Base.T.base); Genotype sam_1_1_eval = GenotypeBuilder.create("test1_sample1", Arrays.asList(reference_A,reference_A)); Genotype sam_1_2_eval = GenotypeBuilder.create("test1_sample2", Arrays.asList(Allele.NO_CALL,Allele.NO_CALL)); @@ -316,9 +316,9 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private Pair getData5() { - Allele reference_A = Allele.create(BaseUtils.A,true); - Allele alt_C = Allele.create(BaseUtils.C); - Allele alt_T = Allele.create(BaseUtils.T); + Allele reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_C = Allele.create(BaseUtils.Base.C.base); + Allele alt_T = Allele.create(BaseUtils.Base.T.base); Genotype sam_1_1_eval = GenotypeBuilder.create("test1_sample1", Arrays.asList(reference_A,reference_A)); Genotype sam_1_2_eval = GenotypeBuilder.create("test1_sample2", new ArrayList(0)); @@ -368,8 +368,8 @@ public class ConcordanceMetricsUnitTest extends BaseTest { private List> getData6() { - Allele reference_A = Allele.create(BaseUtils.A,true); - Allele alt_C = Allele.create(BaseUtils.C); + Allele reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_C = Allele.create(BaseUtils.Base.C.base); // site 1 - @@ -396,8 +396,8 @@ public class ConcordanceMetricsUnitTest extends BaseTest { Pair testDataSite1 = new Pair(eval_1_builder.make(),truth_1_builder.make()); - reference_A = Allele.create(BaseUtils.A,true); - Allele alt_T = Allele.create(BaseUtils.T); + reference_A = Allele.create(BaseUtils.Base.A.base,true); + Allele alt_T = Allele.create(BaseUtils.Base.T.base); // site 2 - // sample 1: no-call/hom-ref @@ -421,7 +421,7 @@ public class ConcordanceMetricsUnitTest extends BaseTest { Pair testDataSite2 = new Pair(eval_1_builder.make(),truth_1_builder.make()); - Allele alt_G = Allele.create(BaseUtils.G); + Allele alt_G = Allele.create(BaseUtils.Base.G.base); // site 3 - // sample 1: alleles do not match @@ -605,10 +605,10 @@ public class ConcordanceMetricsUnitTest extends BaseTest { public List> getData7() { - Allele ref1 = Allele.create(BaseUtils.T,true); - Allele alt1 = Allele.create(BaseUtils.C); - Allele alt2 = Allele.create(BaseUtils.G); - Allele alt3 = Allele.create(BaseUtils.A); + Allele ref1 = Allele.create(BaseUtils.Base.T.base,true); + Allele alt1 = Allele.create(BaseUtils.Base.C.base); + Allele alt2 = Allele.create(BaseUtils.Base.G.base); + Allele alt3 = Allele.create(BaseUtils.Base.A.base); GenomeLoc loc1 = genomeLocParser.createGenomeLoc("chr1",1,1); VariantContextBuilder site1Eval = new VariantContextBuilder(); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/CoverageUtils.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/CoverageUtils.java index 573291d06..fe2eee2a2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/CoverageUtils.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/CoverageUtils.java @@ -217,9 +217,9 @@ public class CoverageUtils { private static void updateCounts(int[] counts, PileupElement e) { if ( e.isDeletion() ) { - counts[BaseUtils.DELETION_INDEX] += e.getRepresentativeCount(); - } else if ( BaseUtils.basesAreEqual((byte) 'N', e.getBase()) ) { - counts[BaseUtils.NO_CALL_INDEX] += e.getRepresentativeCount(); + counts[BaseUtils.Base.D.ordinal()] += e.getRepresentativeCount(); + } else if ( BaseUtils.basesAreEqual(BaseUtils.Base.N.base, e.getBase()) ) { + counts[BaseUtils.Base.N.ordinal()] += e.getRepresentativeCount(); } else { try { counts[BaseUtils.simpleBaseToBaseIndex(e.getBase())] += e.getRepresentativeCount(); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java index 9cd1be2d9..668d3fd5f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java @@ -86,7 +86,7 @@ public class GCContentByInterval extends LocusWalker { if (tracker == null) return null; int baseIndex = ref.getBaseIndex(); - return (baseIndex == BaseUtils.gIndex || baseIndex == BaseUtils.cIndex) ? 1L : 0L; + return (baseIndex == BaseUtils.Base.G.ordinal() || baseIndex == BaseUtils.Base.C.ordinal()) ? 1L : 0L; } public Long reduce(Long toAdd, Long runningCount) { diff --git a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java index 3d43d5d4d..88eaa8910 100644 --- a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java +++ b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java @@ -33,6 +33,7 @@ import net.sf.samtools.SAMSequenceRecord; import net.sf.samtools.util.StringUtil; import org.apache.log4j.Priority; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.variant.utils.BaseUtils; import java.io.File; import java.io.FileNotFoundException; @@ -41,9 +42,10 @@ import java.util.Arrays; /** * A caching version of the IndexedFastaSequenceFile that avoids going to disk as often as the raw indexer. * - * Thread-safe! Uses a thread-local cache + * Thread-safe! Uses a thread-local cache. * - * Automatically upper-cases the bases coming in, unless they the flag preserveCase is explicitly set + * Automatically upper-cases the bases coming in, unless the flag preserveCase is explicitly set. + * Automatically converts IUPAC bases to Ns, unless the flag preserveIUPAC is explicitly set. */ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { protected static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(CachingIndexedFastaSequenceFile.class); @@ -64,10 +66,15 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { private final long cacheMissBackup; /** - * If true, we will preserve the case of the original base in the genome, not + * If true, we will preserve the case of the original base in the genome */ private final boolean preserveCase; + /** + * If true, we will preserve the IUPAC bases in the genome + */ + private final boolean preserveIUPAC; + // information about checking efficiency long cacheHits = 0; long cacheMisses = 0; @@ -97,13 +104,15 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * @param index the index of the fasta file, used for efficient random access * @param cacheSize the size in bp of the cache we will use for this reader * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case + * @param preserveIUPAC If true, we will keep the IUPAC bases in the FASTA, otherwise they are converted to Ns */ - public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index, final long cacheSize, final boolean preserveCase) { + public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index, final long cacheSize, final boolean preserveCase, final boolean preserveIUPAC) { super(fasta, index); if ( cacheSize < 0 ) throw new IllegalArgumentException("cacheSize must be > 0"); this.cacheSize = cacheSize; this.cacheMissBackup = Math.max(cacheSize / 1000, 1); this.preserveCase = preserveCase; + this.preserveIUPAC = preserveIUPAC; } /** @@ -122,19 +131,9 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { this.cacheSize = cacheSize; this.cacheMissBackup = Math.max(cacheSize / 1000, 1); this.preserveCase = preserveCase; + preserveIUPAC = false; } -// /** -// * Open the given indexed fasta sequence file. Throw an exception if the file cannot be opened. -// * -// * @param fasta The file to open. -// * @param index Pre-built FastaSequenceIndex, for the case in which one does not exist on disk. -// * @throws java.io.FileNotFoundException If the fasta or any of its supporting files cannot be found. -// */ -// public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index) { -// this(fasta, index, DEFAULT_CACHE_SIZE); -// } - /** * Same as general constructor but allows one to override the default cacheSize * @@ -145,7 +144,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * @param cacheSize the size in bp of the cache we will use for this reader */ public CachingIndexedFastaSequenceFile(final File fasta, final FastaSequenceIndex index, final long cacheSize) { - this(fasta, index, cacheSize, false); + this(fasta, index, cacheSize, false, false); } /** @@ -240,6 +239,15 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { return ! isPreservingCase(); } + /** + * Is this CachingIndexedFastaReader keeping the IUPAC bases in the fasta, or is it turning them into Ns? + * + * @return true if the IUPAC bases coming from this reader are not modified + */ + public boolean isPreservingIUPAC() { + return preserveIUPAC; + } + /** * Gets the subsequence of the contig in the range [start,stop] * @@ -261,8 +269,9 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { cacheMisses++; result = super.getSubsequenceAt(contig, start, stop); if ( ! preserveCase ) StringUtil.toUpperCase(result.getBases()); + if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(result.getBases(), true); } else { - // todo -- potential optimization is to check if contig.name == contig, as this in generally will be true + // todo -- potential optimization is to check if contig.name == contig, as this in general will be true SAMSequenceRecord contigInfo = super.getSequenceDictionary().getSequence(contig); if (stop > contigInfo.getSequenceLength()) @@ -276,6 +285,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { // convert all of the bases in the sequence to upper case if we aren't preserving cases if ( ! preserveCase ) StringUtil.toUpperCase(myCache.seq.getBases()); + if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(myCache.seq.getBases(), true); } else { cacheHits++; } diff --git a/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java b/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java index c0e18f227..5a5358208 100644 --- a/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java +++ b/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java @@ -31,7 +31,6 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -52,7 +51,7 @@ public class PileupElement implements Comparable { private final static EnumSet ON_GENOME_OPERATORS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.D); - public static final byte DELETION_BASE = BaseUtils.D; + public static final byte DELETION_BASE = BaseUtils.Base.D.base; public static final byte DELETION_QUAL = (byte) 16; public static final byte A_FOLLOWED_BY_INSERTION_BASE = (byte) 87; public static final byte C_FOLLOWED_BY_INSERTION_BASE = (byte) 88; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index 0907a0239..b7a813ec2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -31,7 +31,6 @@ import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; @@ -402,13 +401,13 @@ public class AlignmentUtils { switch (ce.getOperator()) { case I: if (alignPos > 0) { - if (alignment[alignPos - 1] == BaseUtils.A) { + if (alignment[alignPos - 1] == BaseUtils.Base.A.base) { alignment[alignPos - 1] = PileupElement.A_FOLLOWED_BY_INSERTION_BASE; - } else if (alignment[alignPos - 1] == BaseUtils.C) { + } else if (alignment[alignPos - 1] == BaseUtils.Base.C.base) { alignment[alignPos - 1] = PileupElement.C_FOLLOWED_BY_INSERTION_BASE; - } else if (alignment[alignPos - 1] == BaseUtils.T) { + } else if (alignment[alignPos - 1] == BaseUtils.Base.T.base) { alignment[alignPos - 1] = PileupElement.T_FOLLOWED_BY_INSERTION_BASE; - } else if (alignment[alignPos - 1] == BaseUtils.G) { + } else if (alignment[alignPos - 1] == BaseUtils.Base.G.base) { alignment[alignPos - 1] = PileupElement.G_FOLLOWED_BY_INSERTION_BASE; } } diff --git a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java index 819041a3e..7a37e8de5 100644 --- a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java @@ -26,6 +26,7 @@ package org.broadinstitute.variant.utils; import net.sf.samtools.util.StringUtil; +import org.broadinstitute.sting.utils.exceptions.UserException; import java.util.Arrays; import java.util.Random; @@ -34,42 +35,66 @@ import java.util.Random; * BaseUtils contains some basic utilities for manipulating nucleotides. */ public class BaseUtils { - public final static byte A = (byte) 'A'; - public final static byte C = (byte) 'C'; - public final static byte G = (byte) 'G'; - public final static byte T = (byte) 'T'; - public final static byte N = (byte) 'N'; - public final static byte D = (byte) 'D'; + public enum Base { + A ((byte)'A'), + C ((byte)'C'), + G ((byte)'G'), + T ((byte)'T'), + N ((byte)'N'), + D ((byte)'D'); - // - // todo -- we need a generalized base abstraction using the Base enum. - // + public byte base; + + private Base(final byte base) { + this.base = base; + } + } + + // todo -- add this to the generalized base abstraction using the Base enum. public final static byte[] BASES = {'A', 'C', 'G', 'T'}; public final static byte[] EXTENDED_BASES = {'A', 'C', 'G', 'T', 'N', 'D'}; static private final int[] baseIndexMap = new int[256]; static { Arrays.fill(baseIndexMap, -1); - baseIndexMap['A'] = 0; - baseIndexMap['a'] = 0; - baseIndexMap['*'] = 0; // the wildcard character counts as an A - baseIndexMap['C'] = 1; - baseIndexMap['c'] = 1; - baseIndexMap['G'] = 2; - baseIndexMap['g'] = 2; - baseIndexMap['T'] = 3; - baseIndexMap['t'] = 3; + baseIndexMap['A'] = Base.A.ordinal(); + baseIndexMap['a'] = Base.A.ordinal(); + baseIndexMap['*'] = Base.A.ordinal(); // the wildcard character counts as an A + baseIndexMap['C'] = Base.C.ordinal(); + baseIndexMap['c'] = Base.C.ordinal(); + baseIndexMap['G'] = Base.G.ordinal(); + baseIndexMap['g'] = Base.G.ordinal(); + baseIndexMap['T'] = Base.T.ordinal(); + baseIndexMap['t'] = Base.T.ordinal(); } - // todo -- fix me (enums?) - public static final byte DELETION_INDEX = 4; - public static final byte NO_CALL_INDEX = 5; // (this is 'N') - - public static final int aIndex = BaseUtils.simpleBaseToBaseIndex((byte) 'A'); - public static final int cIndex = BaseUtils.simpleBaseToBaseIndex((byte) 'C'); - public static final int gIndex = BaseUtils.simpleBaseToBaseIndex((byte) 'G'); - public static final int tIndex = BaseUtils.simpleBaseToBaseIndex((byte) 'T'); + static private final int[] baseIndexWithIupacMap = baseIndexMap.clone(); + static { + baseIndexWithIupacMap['*'] = -1; // the wildcard character is bad + baseIndexWithIupacMap['N'] = Base.N.ordinal(); + baseIndexWithIupacMap['n'] = Base.N.ordinal(); + baseIndexWithIupacMap['R'] = Base.N.ordinal(); + baseIndexWithIupacMap['r'] = Base.N.ordinal(); + baseIndexWithIupacMap['Y'] = Base.N.ordinal(); + baseIndexWithIupacMap['y'] = Base.N.ordinal(); + baseIndexWithIupacMap['M'] = Base.N.ordinal(); + baseIndexWithIupacMap['m'] = Base.N.ordinal(); + baseIndexWithIupacMap['K'] = Base.N.ordinal(); + baseIndexWithIupacMap['k'] = Base.N.ordinal(); + baseIndexWithIupacMap['W'] = Base.N.ordinal(); + baseIndexWithIupacMap['w'] = Base.N.ordinal(); + baseIndexWithIupacMap['S'] = Base.N.ordinal(); + baseIndexWithIupacMap['s'] = Base.N.ordinal(); + baseIndexWithIupacMap['B'] = Base.N.ordinal(); + baseIndexWithIupacMap['b'] = Base.N.ordinal(); + baseIndexWithIupacMap['D'] = Base.N.ordinal(); + baseIndexWithIupacMap['d'] = Base.N.ordinal(); + baseIndexWithIupacMap['H'] = Base.N.ordinal(); + baseIndexWithIupacMap['h'] = Base.N.ordinal(); + baseIndexWithIupacMap['V'] = Base.N.ordinal(); + baseIndexWithIupacMap['v'] = Base.N.ordinal(); + } // Use a fixed random seed to allow for deterministic results when using random bases private static final Random randomNumberGen = new Random(47382911L); @@ -96,10 +121,10 @@ public class BaseUtils { } public static boolean isTransition(byte base1, byte base2) { - int b1 = simpleBaseToBaseIndex(base1); - int b2 = simpleBaseToBaseIndex(base2); - return b1 == 0 && b2 == 2 || b1 == 2 && b2 == 0 || - b1 == 1 && b2 == 3 || b1 == 3 && b2 == 1; + final int b1 = simpleBaseToBaseIndex(base1); + final int b2 = simpleBaseToBaseIndex(base2); + return b1 == Base.A.ordinal() && b2 == Base.G.ordinal() || b1 == Base.G.ordinal() && b2 == Base.A.ordinal() || + b1 == Base.C.ordinal() && b2 == Base.T.ordinal() || b1 == Base.T.ordinal() && b2 == Base.C.ordinal(); } public static boolean isTransversion(byte base1, byte base2) { @@ -141,6 +166,19 @@ public class BaseUtils { return base >= 'A' && base <= 'Z'; } + public static byte[] convertIUPACtoN(final byte[] bases, final boolean errorOnBadReferenceBase) { + final int length = bases.length; + for ( int i = 0; i < length; i++ ) { + final int baseIndex = baseIndexWithIupacMap[bases[i]]; + if ( baseIndex == Base.N.ordinal() ) { + bases[i] = 'N'; + } else if ( errorOnBadReferenceBase && baseIndex == -1 ) { + throw new UserException.BadInput("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'"); + } + } + return bases; + } + /** * Converts a IUPAC nucleotide code to a pair of bases * @@ -231,10 +269,10 @@ public class BaseUtils { switch (base) { case 'd': case 'D': - return DELETION_INDEX; + return Base.D.ordinal(); case 'n': case 'N': - return NO_CALL_INDEX; + return Base.N.ordinal(); default: return simpleBaseToBaseIndex(base); diff --git a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java index 372d13a7a..4f918f718 100644 --- a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java @@ -50,6 +50,21 @@ public class BaseUtilsUnitTest extends BaseTest { Assert.assertTrue(MathUtils.compareDoubles(fraction, expected) == 0); } + @Test + public void testConvertIUPACtoN() { + + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'A'}, false), new byte[]{'A', 'A', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'W', 'A', 'A'}, false), new byte[]{'N', 'A', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'M', 'A'}, false), new byte[]{'A', 'N', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'K'}, false), new byte[]{'A', 'A', 'N'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'M', 'M', 'M'}, false), new byte[]{'N', 'N', 'N'}); + } + + private void checkBytesAreEqual(final byte[] b1, final byte[] b2) { + for ( int i = 0; i < b1.length; i++ ) + Assert.assertEquals(b1[i], b2[i]); + } + @Test public void testTransitionTransversion() { logger.warn("Executing testTransitionTransversion"); diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java index 49720d1f6..03d6f457f 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java @@ -154,9 +154,9 @@ public class GenotypeLikelihoodsUnitTest { public void testGetQualFromLikelihoodsMultiAllelic() { GenotypeLikelihoods gl = GenotypeLikelihoods.fromLog10Likelihoods(triAllelic); - Allele ref = Allele.create(BaseUtils.A,true); - Allele alt1 = Allele.create(BaseUtils.C); - Allele alt2 = Allele.create(BaseUtils.T); + Allele ref = Allele.create(BaseUtils.Base.A.base,true); + Allele alt1 = Allele.create(BaseUtils.Base.C.base); + Allele alt2 = Allele.create(BaseUtils.Base.T.base); List allAlleles = Arrays.asList(ref,alt1,alt2); List gtAlleles = Arrays.asList(alt1,alt2); GenotypeBuilder gtBuilder = new GenotypeBuilder(); From 445735a4a53f22a5ddd214b95f8e0f4eed8bd593 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 11:10:13 -0500 Subject: [PATCH 019/188] There was no reason to be sharing the Haplotype infrastructure between the HaplotypeCaller and the HaplotypeScore annotation since they were really looking for different things. Separated them out, adding efficiencies for the HaplotypeScore version. --- .../walkers/annotator/HaplotypeScore.java | 57 +++++++++++++++---- .../SimpleDeBruijnAssembler.java | 2 +- .../broadinstitute/sting/utils/Haplotype.java | 49 ++-------------- 3 files changed, 52 insertions(+), 56 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java index fe4075117..af6304297 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java @@ -56,7 +56,6 @@ import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.InfoFieldAnnot import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.StandardAnnotation; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.sting.utils.Haplotype; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.variant.vcf.VCFHeaderLineType; @@ -217,14 +216,14 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot final Haplotype haplotype1 = consensusHaplotypeQueue.poll(); List hlist = new ArrayList(); - hlist.add(new Haplotype(haplotype1.getBases(), 60)); + hlist.add(new Haplotype(haplotype1.getBases(), (byte)60)); for (int k = 1; k < haplotypesToCompute; k++) { Haplotype haplotype2 = consensusHaplotypeQueue.poll(); if (haplotype2 == null) { haplotype2 = haplotype1; } // Sometimes only the reference haplotype can be found - hlist.add(new Haplotype(haplotype2.getBases(), 20)); + hlist.add(new Haplotype(haplotype2.getBases(), (byte)20)); } return hlist; } else @@ -236,8 +235,8 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot final byte[] haplotypeBases = new byte[contextSize]; Arrays.fill(haplotypeBases, (byte) REGEXP_WILDCARD); - final double[] baseQualities = new double[contextSize]; - Arrays.fill(baseQualities, 0.0); + final byte[] baseQualities = new byte[contextSize]; + Arrays.fill(baseQualities, (byte)0); byte[] readBases = read.getReadBases(); readBases = AlignmentUtils.readToAlignmentByteArray(read.getCigar(), readBases); // Adjust the read bases based on the Cigar string @@ -267,7 +266,7 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot readQuals[baseOffset] = (byte) 0; } // quals less than 5 are used as codes and don't have actual probabilistic meaning behind them haplotypeBases[i] = readBases[baseOffset]; - baseQualities[i] = (double) readQuals[baseOffset]; + baseQualities[i] = readQuals[baseOffset]; } return new Haplotype(haplotypeBases, baseQualities); @@ -286,10 +285,10 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot final int length = a.length; final byte[] consensusChars = new byte[length]; - final double[] consensusQuals = new double[length]; + final byte[] consensusQuals = new byte[length]; - final double[] qualsA = haplotypeA.getQuals(); - final double[] qualsB = haplotypeB.getQuals(); + final byte[] qualsA = haplotypeA.getQuals(); + final byte[] qualsB = haplotypeB.getQuals(); for (int i = 0; i < length; i++) { chA = a[i]; @@ -300,7 +299,7 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot if ((chA == wc) && (chB == wc)) { consensusChars[i] = wc; - consensusQuals[i] = 0.0; + consensusQuals[i] = 0; } else if ((chA == wc)) { consensusChars[i] = chB; consensusQuals[i] = qualsB[i]; @@ -309,7 +308,7 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot consensusQuals[i] = qualsA[i]; } else { consensusChars[i] = chA; - consensusQuals[i] = qualsA[i] + qualsB[i]; + consensusQuals[i] = (byte)((int)qualsA[i] + (int)qualsB[i]); } } @@ -433,7 +432,6 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot } - public List getKeyNames() { return Arrays.asList("HaplotypeScore"); } @@ -441,4 +439,39 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot public List getDescriptions() { return Arrays.asList(new VCFInfoHeaderLine("HaplotypeScore", 1, VCFHeaderLineType.Float, "Consistency of the site with at most two segregating haplotypes")); } + + private static class Haplotype { + private final byte[] bases; + private final byte[] quals; + private int qualitySum = -1; + + public Haplotype( final byte[] bases, final byte[] quals ) { + this.bases = bases; + this.quals = quals; + } + + public Haplotype( final byte[] bases, final byte qual ) { + this.bases = bases; + quals = new byte[bases.length]; + Arrays.fill(quals, qual); + } + + public double getQualitySum() { + if ( qualitySum == -1 ) { + qualitySum = 0; + for ( final byte qual : quals ) { + qualitySum += (int)qual; + } + } + return qualitySum; + } + + public byte[] getQuals() { + return quals.clone(); + } + + public byte[] getBases() { + return bases.clone(); + } + } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java index e1a94eee7..e16994fa4 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java @@ -338,7 +338,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { for( final DefaultDirectedGraph graph : graphs ) { for ( final KBestPaths.Path path : KBestPaths.getKBestPaths(graph, NUM_BEST_PATHS_PER_KMER_GRAPH) ) { - final Haplotype h = new Haplotype( path.getBases( graph ), path.getScore() ); + final Haplotype h = new Haplotype( path.getBases( graph ) ); if( addHaplotype( h, fullReferenceWithPadding, returnHaplotypes, activeRegionStart, activeRegionStop, false ) ) { // for GGA mode, add the desired allele into the haplotype if it isn't already present diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index 8c40b9972..66aed1173 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -37,8 +37,8 @@ import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.Serializable; import java.util.*; -public class Haplotype extends Allele { - protected final double[] quals; +public class Haplotype extends Allele { + private GenomeLoc genomeLocation = null; private HashMap eventMap = null; private Cigar cigar; @@ -51,49 +51,23 @@ public class Haplotype extends Allele { * Main constructor * * @param bases bases - * @param quals quals * @param isRef is reference allele? */ - public Haplotype( final byte[] bases, final double[] quals, final boolean isRef ) { - super(bases.clone(), isRef); - this.quals = quals.clone(); - } - - /** - * Create a simple consensus sequence with provided bases and a uniform quality over all bases of qual - * - * @param bases bases - * @param qual qual - */ - public Haplotype( final byte[] bases, final int qual, final boolean isRef ) { - super(bases.clone(), isRef); - quals = new double[bases.length]; - Arrays.fill(quals, (double)qual); - } - - public Haplotype( final byte[] bases, final int qual ) { - this(bases, qual, false); - } - public Haplotype( final byte[] bases, final boolean isRef ) { - this(bases, 0, isRef); - } - - public Haplotype( final byte[] bases, final double[] quals ) { - this(bases, quals, false); + super(bases.clone(), isRef); } public Haplotype( final byte[] bases ) { - this(bases, 0, false); + this(bases, false); } protected Haplotype( final byte[] bases, final Event artificialEvent ) { - this(bases, 0, false); + this(bases, false); this.artificialEvent = artificialEvent; } public Haplotype( final byte[] bases, final GenomeLoc loc ) { - this(bases, 0, false); + this(bases, false); this.genomeLocation = loc; } @@ -110,22 +84,11 @@ public class Haplotype extends Allele { this.eventMap = eventMap; } - public double getQualitySum() { - double s = 0; - for (int k=0; k < quals.length; k++) { - s += quals[k]; - } - return s; - } - @Override public String toString() { return getDisplayString(); } - public double[] getQuals() { - return quals.clone(); - } public byte[] getBases() { return super.getBases().clone(); } From 4ffb43079f020e1a1ed3dc2fffc02a1bf660e01d Mon Sep 17 00:00:00 2001 From: Khalid Shakir Date: Wed, 16 Jan 2013 12:43:15 -0500 Subject: [PATCH 020/188] Re-committing the following changes from Dec 18: Refactored interval specific arguments out of GATKArgumentCollection into InvtervalArgumentCollection such that it can be used in other CommandLinePrograms. Updated SelectHeaders to print out full interval arguments. Added RemoteFile.createUrl(Date expiration) to enable creation of presigned URLs for download over http: or file:. --- .../walkers/variantutils/SelectHeaders.java | 51 +++++++++++--- .../IntervalArgumentCollection.java | 70 +++++++++++++++++++ .../sting/gatk/GenomeAnalysisEngine.java | 38 +--------- .../arguments/GATKArgumentCollection.java | 45 +----------- .../sting/utils/interval/IntervalUtils.java | 42 +++++++++++ .../broadinstitute/variant/vcf/VCFHeader.java | 4 ++ .../utils/interval/IntervalUtilsUnitTest.java | 4 +- .../sting/queue/util/RemoteFile.scala | 3 + 8 files changed, 166 insertions(+), 91 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java index 81a17b6ae..38fa060cc 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java @@ -57,6 +57,8 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.gatk.walkers.TreeReducible; import org.broadinstitute.sting.utils.SampleUtils; +import org.broadinstitute.sting.utils.interval.IntervalMergingRule; +import org.broadinstitute.sting.utils.interval.IntervalSetRule; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -180,18 +182,47 @@ public class SelectHeaders extends RodWalker implements TreeRe headerLines = new LinkedHashSet(getSelectedHeaders(headerLines)); // Optionally add in the intervals. - if (includeIntervals && getToolkit().getArguments().intervals != null) { - for (IntervalBinding intervalBinding : getToolkit().getArguments().intervals) { - String source = intervalBinding.getSource(); - if (source == null) - continue; - File file = new File(source); - if (file.exists()) { - headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, FilenameUtils.getBaseName(file.getName()))); - } else { - headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, source)); + if (includeIntervals) { + IntervalArgumentCollection intervalArguments = getToolkit().getArguments().intervalArguments; + if (intervalArguments.intervals != null) { + for (IntervalBinding intervalBinding : intervalArguments.intervals) { + String source = intervalBinding.getSource(); + if (source == null) + continue; + File file = new File(source); + if (file.exists()) { + headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, FilenameUtils.getBaseName(file.getName()))); + } else { + headerLines.add(new VCFHeaderLine(VCFHeader.INTERVALS_KEY, source)); + } } } + + if (intervalArguments.excludeIntervals != null) { + for (IntervalBinding intervalBinding : intervalArguments.excludeIntervals) { + String source = intervalBinding.getSource(); + if (source == null) + continue; + File file = new File(source); + if (file.exists()) { + headerLines.add(new VCFHeaderLine(VCFHeader.EXCLUDE_INTERVALS_KEY, FilenameUtils.getBaseName(file.getName()))); + } else { + headerLines.add(new VCFHeaderLine(VCFHeader.EXCLUDE_INTERVALS_KEY, source)); + } + } + } + + if (intervalArguments.intervalMerging != IntervalMergingRule.ALL) { + headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_MERGING_KEY, String.valueOf(intervalArguments.intervalMerging))); + } + + if (intervalArguments.intervalSetRule != IntervalSetRule.UNION) { + headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_SET_RULE_KEY, String.valueOf(intervalArguments.intervalSetRule))); + } + + if (intervalArguments.intervalPadding != 0) { + headerLines.add(new VCFHeaderLine(VCFHeader.INTERVAL_PADDING_KEY, String.valueOf(intervalArguments.intervalPadding))); + } } TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); diff --git a/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java b/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java new file mode 100644 index 000000000..3f76ae652 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java @@ -0,0 +1,70 @@ +/* +* 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.commandline; + +import org.broad.tribble.Feature; +import org.broadinstitute.sting.utils.interval.IntervalMergingRule; +import org.broadinstitute.sting.utils.interval.IntervalSetRule; + +import java.util.List; + +public class IntervalArgumentCollection { + /** + * Using this option one can instruct the GATK engine to traverse over only part of the genome. This argument can be specified multiple times. + * One may use samtools-style intervals either explicitly (e.g. -L chr1 or -L chr1:100-200) or listed in a file (e.g. -L myFile.intervals). + * Additionally, one may specify a rod file to traverse over the positions for which there is a record in the file (e.g. -L file.vcf). + * To specify the completely unmapped reads in the BAM file (i.e. those without a reference contig) use -L unmapped. + */ + @Input(fullName = "intervals", shortName = "L", doc = "One or more genomic intervals over which to operate. Can be explicitly specified on the command line or in a file (including a rod file)", required = false) + public List> intervals = null; + + /** + * Using this option one can instruct the GATK engine NOT to traverse over certain parts of the genome. This argument can be specified multiple times. + * One may use samtools-style intervals either explicitly (e.g. -XL chr1 or -XL chr1:100-200) or listed in a file (e.g. -XL myFile.intervals). + * Additionally, one may specify a rod file to skip over the positions for which there is a record in the file (e.g. -XL file.vcf). + */ + @Input(fullName = "excludeIntervals", shortName = "XL", doc = "One or more genomic intervals to exclude from processing. Can be explicitly specified on the command line or in a file (including a rod file)", required = false) + public List> excludeIntervals = null; + + /** + * How should the intervals specified by multiple -L or -XL arguments be combined? Using this argument one can, for example, traverse over all of the positions + * for which there is a record in a VCF but just in chromosome 20 (-L chr20 -L file.vcf -isr INTERSECTION). + */ + @Argument(fullName = "interval_set_rule", shortName = "isr", doc = "Indicates the set merging approach the interval parser should use to combine the various -L or -XL inputs", required = false) + public IntervalSetRule intervalSetRule = IntervalSetRule.UNION; + + /** + * Should abutting (but not overlapping) intervals be treated as separate intervals? + */ + @Argument(fullName = "interval_merging", shortName = "im", doc = "Indicates the interval merging rule we should use for abutting intervals", required = false) + public IntervalMergingRule intervalMerging = IntervalMergingRule.ALL; + + /** + * For example, '-L chr1:100' with a padding value of 20 would turn into '-L chr1:80-120'. + */ + @Argument(fullName = "interval_padding", shortName = "ip", doc = "Indicates how many basepairs of padding to include around each of the intervals specified with the -L/--intervals argument", required = false) + public int intervalPadding = 0; +} diff --git a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index f9d6955c0..9b801be7d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -55,7 +55,6 @@ import org.broadinstitute.sting.gatk.samples.SampleDBBuilder; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.classloader.PluginManager; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.interval.IntervalUtils; @@ -361,7 +360,6 @@ public class GenomeAnalysisEngine { * Returns a list of active, initialized read transformers * * @param walker the walker we need to apply read transformers too - * @return a non-null list of read transformers */ public void initializeReadTransformers(final Walker walker) { final List activeTransformers = new ArrayList(); @@ -672,41 +670,7 @@ public class GenomeAnalysisEngine { * Setup the intervals to be processed */ protected void initializeIntervals() { - // return if no interval arguments at all - if ( argCollection.intervals == null && argCollection.excludeIntervals == null ) - return; - - // Note that the use of '-L all' is no longer supported. - - // if include argument isn't given, create new set of all possible intervals - - final Pair includeExcludePair = IntervalUtils.parseIntervalBindingsPair( - this.referenceDataSource, - argCollection.intervals, - argCollection.intervalSetRule, argCollection.intervalMerging, argCollection.intervalPadding, - argCollection.excludeIntervals); - - final GenomeLocSortedSet includeSortedSet = includeExcludePair.getFirst(); - final GenomeLocSortedSet excludeSortedSet = includeExcludePair.getSecond(); - - // if no exclude arguments, can return parseIntervalArguments directly - if ( excludeSortedSet == null ) - intervals = includeSortedSet; - - // otherwise there are exclude arguments => must merge include and exclude GenomeLocSortedSets - else { - intervals = includeSortedSet.subtractRegions(excludeSortedSet); - - // logging messages only printed when exclude (-XL) arguments are given - final long toPruneSize = includeSortedSet.coveredSize(); - final long toExcludeSize = excludeSortedSet.coveredSize(); - final long intervalSize = intervals.coveredSize(); - logger.info(String.format("Initial include intervals span %d loci; exclude intervals span %d loci", toPruneSize, toExcludeSize)); - logger.info(String.format("Excluding %d loci from original intervals (%.2f%% reduction)", - toPruneSize - intervalSize, (toPruneSize - intervalSize) / (0.01 * toPruneSize))); - } - - logger.info(String.format("Processing %d bp from intervals", intervals.coveredSize())); + intervals = IntervalUtils.parseIntervalArguments(this.referenceDataSource, argCollection.intervalArguments); } /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index ab09064dd..62ca38ad2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -26,11 +26,7 @@ package org.broadinstitute.sting.gatk.arguments; import net.sf.samtools.SAMFileReader; -import org.broad.tribble.Feature; -import org.broadinstitute.sting.commandline.Argument; -import org.broadinstitute.sting.commandline.Hidden; -import org.broadinstitute.sting.commandline.Input; -import org.broadinstitute.sting.commandline.IntervalBinding; +import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.gatk.downsampling.DownsamplingMethod; @@ -38,8 +34,6 @@ import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.gatk.samples.PedigreeValidationType; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.sting.utils.interval.IntervalMergingRule; -import org.broadinstitute.sting.utils.interval.IntervalSetRule; import java.io.File; import java.util.ArrayList; @@ -100,41 +94,8 @@ public class GATKArgumentCollection { @Argument(fullName = "read_filter", shortName = "rf", doc = "Specify filtration criteria to apply to each read individually", required = false) public List readFilters = new ArrayList(); - /** - * Using this option one can instruct the GATK engine to traverse over only part of the genome. This argument can be specified multiple times. - * One may use samtools-style intervals either explicitly (e.g. -L chr1 or -L chr1:100-200) or listed in a file (e.g. -L myFile.intervals). - * Additionally, one may specify a rod file to traverse over the positions for which there is a record in the file (e.g. -L file.vcf). - * To specify the completely unmapped reads in the BAM file (i.e. those without a reference contig) use -L unmapped. - */ - @Input(fullName = "intervals", shortName = "L", doc = "One or more genomic intervals over which to operate. Can be explicitly specified on the command line or in a file (including a rod file)", required = false) - public List> intervals = null; - - /** - * Using this option one can instruct the GATK engine NOT to traverse over certain parts of the genome. This argument can be specified multiple times. - * One may use samtools-style intervals either explicitly (e.g. -XL chr1 or -XL chr1:100-200) or listed in a file (e.g. -XL myFile.intervals). - * Additionally, one may specify a rod file to skip over the positions for which there is a record in the file (e.g. -XL file.vcf). - */ - @Input(fullName = "excludeIntervals", shortName = "XL", doc = "One or more genomic intervals to exclude from processing. Can be explicitly specified on the command line or in a file (including a rod file)", required = false) - public List> excludeIntervals = null; - - /** - * How should the intervals specified by multiple -L or -XL arguments be combined? Using this argument one can, for example, traverse over all of the positions - * for which there is a record in a VCF but just in chromosome 20 (-L chr20 -L file.vcf -isr INTERSECTION). - */ - @Argument(fullName = "interval_set_rule", shortName = "isr", doc = "Indicates the set merging approach the interval parser should use to combine the various -L or -XL inputs", required = false) - public IntervalSetRule intervalSetRule = IntervalSetRule.UNION; - - /** - * Should abutting (but not overlapping) intervals be treated as separate intervals? - */ - @Argument(fullName = "interval_merging", shortName = "im", doc = "Indicates the interval merging rule we should use for abutting intervals", required = false) - public IntervalMergingRule intervalMerging = IntervalMergingRule.ALL; - - /** - * For example, '-L chr1:100' with a padding value of 20 would turn into '-L chr1:80-120'. - */ - @Argument(fullName = "interval_padding", shortName = "ip", doc = "Indicates how many basepairs of padding to include around each of the intervals specified with the -L/--intervals argument", required = false) - public int intervalPadding = 0; + @ArgumentCollection + public IntervalArgumentCollection intervalArguments = new IntervalArgumentCollection(); @Input(fullName = "reference_sequence", shortName = "R", doc = "Reference sequence file", required = false) public File referenceFile = null; diff --git a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java index c647a7b80..7374dda14 100644 --- a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java @@ -32,6 +32,7 @@ import net.sf.picard.util.IntervalList; import net.sf.samtools.SAMFileHeader; import org.apache.log4j.Logger; import org.broad.tribble.Feature; +import org.broadinstitute.sting.commandline.IntervalArgumentCollection; import org.broadinstitute.sting.commandline.IntervalBinding; import org.broadinstitute.sting.gatk.datasources.reference.ReferenceDataSource; import org.broadinstitute.sting.utils.GenomeLoc; @@ -534,6 +535,47 @@ public class IntervalUtils { } } + public static GenomeLocSortedSet parseIntervalArguments(final ReferenceDataSource referenceDataSource, IntervalArgumentCollection argCollection) { + GenomeLocSortedSet intervals = null; + + // return if no interval arguments at all + if ( argCollection.intervals == null && argCollection.excludeIntervals == null ) + return intervals; + + // Note that the use of '-L all' is no longer supported. + + // if include argument isn't given, create new set of all possible intervals + + final Pair includeExcludePair = IntervalUtils.parseIntervalBindingsPair( + referenceDataSource, + argCollection.intervals, + argCollection.intervalSetRule, argCollection.intervalMerging, argCollection.intervalPadding, + argCollection.excludeIntervals); + + final GenomeLocSortedSet includeSortedSet = includeExcludePair.getFirst(); + final GenomeLocSortedSet excludeSortedSet = includeExcludePair.getSecond(); + + // if no exclude arguments, can return parseIntervalArguments directly + if ( excludeSortedSet == null ) + intervals = includeSortedSet; + + // otherwise there are exclude arguments => must merge include and exclude GenomeLocSortedSets + else { + intervals = includeSortedSet.subtractRegions(excludeSortedSet); + + // logging messages only printed when exclude (-XL) arguments are given + final long toPruneSize = includeSortedSet.coveredSize(); + final long toExcludeSize = excludeSortedSet.coveredSize(); + final long intervalSize = intervals.coveredSize(); + logger.info(String.format("Initial include intervals span %d loci; exclude intervals span %d loci", toPruneSize, toExcludeSize)); + logger.info(String.format("Excluding %d loci from original intervals (%.2f%% reduction)", + toPruneSize - intervalSize, (toPruneSize - intervalSize) / (0.01 * toPruneSize))); + } + + logger.info(String.format("Processing %d bp from intervals", intervals.coveredSize())); + return intervals; + } + public static Pair parseIntervalBindingsPair( final ReferenceDataSource referenceDataSource, final List> intervals, diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java b/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java index 583a01417..9bdb86a48 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java @@ -73,6 +73,10 @@ public class VCFHeader { public static final String REFERENCE_KEY = "reference"; public static final String CONTIG_KEY = "contig"; public static final String INTERVALS_KEY = "intervals"; + public static final String EXCLUDE_INTERVALS_KEY = "excludeIntervals"; + public static final String INTERVAL_MERGING_KEY = "interval_merging"; + public static final String INTERVAL_SET_RULE_KEY = "interval_set_rule"; + public static final String INTERVAL_PADDING_KEY = "interval_padding"; // were the input samples sorted originally (or are we sorting them)? private boolean samplesWereAlreadySorted = true; diff --git a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalUtilsUnitTest.java index 35f9d4137..2be2745de 100644 --- a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalUtilsUnitTest.java @@ -1068,7 +1068,7 @@ public class IntervalUtilsUnitTest extends BaseTest { List> intervalArgs = new ArrayList>(1); intervalArgs.add(new IntervalBinding(picardIntervalFile.getAbsolutePath())); - IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalSetRule, argCollection.intervalMerging, argCollection.intervalPadding, genomeLocParser); + IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalArguments.intervalSetRule, argCollection.intervalArguments.intervalMerging, argCollection.intervalArguments.intervalPadding, genomeLocParser); } @Test(expectedExceptions=UserException.class, dataProvider="invalidIntervalTestData") @@ -1081,7 +1081,7 @@ public class IntervalUtilsUnitTest extends BaseTest { List> intervalArgs = new ArrayList>(1); intervalArgs.add(new IntervalBinding(gatkIntervalFile.getAbsolutePath())); - IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalSetRule, argCollection.intervalMerging, argCollection.intervalPadding, genomeLocParser); + IntervalUtils.loadIntervals(intervalArgs, argCollection.intervalArguments.intervalSetRule, argCollection.intervalArguments.intervalMerging, argCollection.intervalArguments.intervalPadding, genomeLocParser); } private File createTempFile( String tempFilePrefix, String tempFileExtension, String... lines ) throws Exception { diff --git a/public/scala/src/org/broadinstitute/sting/queue/util/RemoteFile.scala b/public/scala/src/org/broadinstitute/sting/queue/util/RemoteFile.scala index 28be82136..23a99b586 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/util/RemoteFile.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/util/RemoteFile.scala @@ -27,6 +27,8 @@ package org.broadinstitute.sting.queue.util import java.io.File import org.broadinstitute.sting.utils.io.FileExtension +import java.util.Date +import java.net.URL /** * An extension of java.io.File that can be pulled from or pushed to a remote location. @@ -35,5 +37,6 @@ trait RemoteFile extends File with FileExtension { def pullToLocal() def pushToRemote() def deleteRemote() + def createUrl(expiration: Date): URL def remoteDescription: String } From d18dbcbac103c0ce8f0480e04efcdd00a50f3394 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 14:55:33 -0500 Subject: [PATCH 021/188] Added tests for changing IUPAC bases to Ns, for failing on bad ref bases, and for the HaplotypeCaller not failing when running over a region with an IUPAC base. Out of curiosity, why does Picard's IndexedFastaSequenceFile allow one to query for start position 0? When doing so, that base is a line feed (-1 offset to the first base in the contig) which is an illegal base (and which caused me no end of trouble)... --- .../HaplotypeCallerIntegrationTest.java | 9 +++++ .../CachingIndexedFastaSequenceFile.java | 14 +++---- .../variant/utils/BaseUtils.java | 6 ++- ...chingIndexedFastaSequenceFileUnitTest.java | 39 +++++++++++++++++-- 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index d95da6b7f..6183fc411 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -50,6 +50,7 @@ import org.broadinstitute.sting.WalkerTest; import org.testng.annotations.Test; import java.util.Arrays; +import java.util.Collections; public class HaplotypeCallerIntegrationTest extends WalkerTest { final static String REF = b37KGReference; @@ -156,6 +157,14 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { executeTest("HCTestStructuralIndels: ", spec); } + @Test + public void HCTestDoesNotFailOnBadRefBase() { + // don't care about the output - just want to make sure it doesn't fail + final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "NA12878.readsOverBadBase.chr3.bam") + " --no_cmdline_in_header -o /dev/null -L 3:60830000-60840000 --minPruning 3 -stand_call_conf 2 -stand_emit_conf 2"; + final WalkerTestSpec spec = new WalkerTestSpec(base, Collections.emptyList()); + executeTest("HCTestDoesNotFailOnBadRefBase: ", spec); + } + // -------------------------------------------------------------------------------------------------------------- // // testing reduced reads diff --git a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java index 88eaa8910..a749625cd 100644 --- a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java +++ b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java @@ -125,13 +125,13 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * @param cacheSize the size of the cache to use in this CachingIndexedFastaReader, must be >= 0 * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case */ - public CachingIndexedFastaSequenceFile(final File fasta, final long cacheSize, final boolean preserveCase ) throws FileNotFoundException { + public CachingIndexedFastaSequenceFile(final File fasta, final long cacheSize, final boolean preserveCase, final boolean preserveIUPAC) throws FileNotFoundException { super(fasta); if ( cacheSize < 0 ) throw new IllegalArgumentException("cacheSize must be > 0"); this.cacheSize = cacheSize; this.cacheMissBackup = Math.max(cacheSize / 1000, 1); this.preserveCase = preserveCase; - preserveIUPAC = false; + this.preserveIUPAC = preserveIUPAC; } /** @@ -168,7 +168,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * @param preserveCase If true, we will keep the case of the underlying bases in the FASTA, otherwise everything is converted to upper case */ public CachingIndexedFastaSequenceFile(final File fasta, final boolean preserveCase) throws FileNotFoundException { - this(fasta, DEFAULT_CACHE_SIZE, preserveCase); + this(fasta, DEFAULT_CACHE_SIZE, preserveCase, false); } /** @@ -181,7 +181,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * @param cacheSize the size of the cache to use in this CachingIndexedFastaReader, must be >= 0 */ public CachingIndexedFastaSequenceFile(final File fasta, final long cacheSize ) throws FileNotFoundException { - this(fasta, cacheSize, false); + this(fasta, cacheSize, false, false); } /** @@ -261,7 +261,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { * all of the bases in the ReferenceSequence returned by this method will be upper cased. */ @Override - public ReferenceSequence getSubsequenceAt( final String contig, final long start, final long stop ) { + public ReferenceSequence getSubsequenceAt( final String contig, long start, final long stop ) { final ReferenceSequence result; final Cache myCache = cache.get(); @@ -269,7 +269,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { cacheMisses++; result = super.getSubsequenceAt(contig, start, stop); if ( ! preserveCase ) StringUtil.toUpperCase(result.getBases()); - if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(result.getBases(), true); + if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(result.getBases(), true, start < 1); } else { // todo -- potential optimization is to check if contig.name == contig, as this in general will be true SAMSequenceRecord contigInfo = super.getSequenceDictionary().getSequence(contig); @@ -285,7 +285,7 @@ public class CachingIndexedFastaSequenceFile extends IndexedFastaSequenceFile { // convert all of the bases in the sequence to upper case if we aren't preserving cases if ( ! preserveCase ) StringUtil.toUpperCase(myCache.seq.getBases()); - if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(myCache.seq.getBases(), true); + if ( ! preserveIUPAC ) BaseUtils.convertIUPACtoN(myCache.seq.getBases(), true, myCache.start == 0); } else { cacheHits++; } diff --git a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java index 7a37e8de5..a6ac2ca53 100644 --- a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java @@ -166,9 +166,11 @@ public class BaseUtils { return base >= 'A' && base <= 'Z'; } - public static byte[] convertIUPACtoN(final byte[] bases, final boolean errorOnBadReferenceBase) { + public static byte[] convertIUPACtoN(final byte[] bases, final boolean errorOnBadReferenceBase, final boolean ignoreConversionOfFirstByte) { final int length = bases.length; - for ( int i = 0; i < length; i++ ) { + final int start = ignoreConversionOfFirstByte ? 1 : 0; + + for ( int i = start; i < length; i++ ) { final int baseIndex = baseIndexWithIupacMap[bases[i]]; if ( baseIndex == Base.N.ordinal() ) { bases[i] = 'N'; diff --git a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java index c67e52f2e..0c1b5b069 100644 --- a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java @@ -32,8 +32,10 @@ package org.broadinstitute.sting.utils.fasta; import net.sf.picard.reference.IndexedFastaSequenceFile; import net.sf.picard.reference.ReferenceSequence; import net.sf.samtools.SAMSequenceRecord; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Priority; import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.exceptions.UserException; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -49,7 +51,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** - * Basic unit test for GenomeLoc + * Basic unit test for CachingIndexedFastaSequenceFile */ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { private File simpleFasta = new File(publicTestDir + "/exampleFASTA.fasta"); @@ -80,7 +82,7 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { @Test(dataProvider = "fastas", enabled = true && ! DEBUG) public void testCachingIndexedFastaReaderSequential1(File fasta, int cacheSize, int querySize) throws FileNotFoundException { - final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true); + final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false); SAMSequenceRecord contig = caching.getSequenceDictionary().getSequence(0); logger.warn(String.format("Checking contig %s length %d with cache size %d and query size %d", @@ -122,7 +124,7 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { @Test(dataProvider = "fastas", enabled = true && ! DEBUG) public void testCachingIndexedFastaReaderTwoStage(File fasta, int cacheSize, int querySize) throws FileNotFoundException { final IndexedFastaSequenceFile uncached = new IndexedFastaSequenceFile(fasta); - final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true); + final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false); SAMSequenceRecord contig = uncached.getSequenceDictionary().getSequence(0); @@ -167,7 +169,7 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { @Test(dataProvider = "ParallelFastaTest", enabled = true && ! DEBUG, timeOut = 60000) public void testCachingIndexedFastaReaderParallel(final File fasta, final int cacheSize, final int querySize, final int nt) throws FileNotFoundException, InterruptedException { - final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true); + final CachingIndexedFastaSequenceFile caching = new CachingIndexedFastaSequenceFile(fasta, getCacheSize(cacheSize), true, false); logger.warn(String.format("Parallel caching index fasta reader test cacheSize %d querySize %d nt %d", caching.getCacheSize(), querySize, nt)); for ( int iterations = 0; iterations < 1; iterations++ ) { @@ -230,4 +232,33 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { else return new String(reader.getSubsequenceAt(contig, start, stop).getBases()); } + + @Test(enabled = true) + public void testIupacChanges() throws FileNotFoundException, InterruptedException { + final String testFasta = privateTestDir + "iupacFASTA.fasta"; + final CachingIndexedFastaSequenceFile iupacPreserving = new CachingIndexedFastaSequenceFile(new File(testFasta), CachingIndexedFastaSequenceFile.DEFAULT_CACHE_SIZE, false, true); + final CachingIndexedFastaSequenceFile makeNs = new CachingIndexedFastaSequenceFile(new File(testFasta)); + + int preservingNs = 0; + int changingNs = 0; + for ( SAMSequenceRecord contig : iupacPreserving.getSequenceDictionary().getSequences() ) { + final String sPreserving = fetchBaseString(iupacPreserving, contig.getSequenceName(), 0, 15000); + preservingNs += StringUtils.countMatches(sPreserving, "N"); + + final String sChanging = fetchBaseString(makeNs, contig.getSequenceName(), 0, 15000); + changingNs += StringUtils.countMatches(sChanging, "N"); + } + + Assert.assertEquals(changingNs, preservingNs + 4); + } + + @Test(enabled = true, expectedExceptions = {UserException.class}) + public void testFailOnBadBase() throws FileNotFoundException, InterruptedException { + final String testFasta = privateTestDir + "problematicFASTA.fasta"; + final CachingIndexedFastaSequenceFile fasta = new CachingIndexedFastaSequenceFile(new File(testFasta)); + + for ( SAMSequenceRecord contig : fasta.getSequenceDictionary().getSequences() ) { + fetchBaseString(fasta, contig.getSequenceName(), -1, -1); + } + } } From ec1cfe67329c43afe916be4816af3b5af23f27c3 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 15:05:49 -0500 Subject: [PATCH 022/188] Oops, forgot to add 1 of my files --- .../variant/utils/BaseUtilsUnitTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java index 4f918f718..37627204f 100644 --- a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java @@ -53,11 +53,11 @@ public class BaseUtilsUnitTest extends BaseTest { @Test public void testConvertIUPACtoN() { - checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'A'}, false), new byte[]{'A', 'A', 'A'}); - checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'W', 'A', 'A'}, false), new byte[]{'N', 'A', 'A'}); - checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'M', 'A'}, false), new byte[]{'A', 'N', 'A'}); - checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'K'}, false), new byte[]{'A', 'A', 'N'}); - checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'M', 'M', 'M'}, false), new byte[]{'N', 'N', 'N'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'A'}, false, false), new byte[]{'A', 'A', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'W', 'A', 'A'}, false, false), new byte[]{'N', 'A', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'M', 'A'}, false, false), new byte[]{'A', 'N', 'A'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'A', 'A', 'K'}, false, false), new byte[]{'A', 'A', 'N'}); + checkBytesAreEqual(BaseUtils.convertIUPACtoN(new byte[]{'M', 'M', 'M'}, false, false), new byte[]{'N', 'N', 'N'}); } private void checkBytesAreEqual(final byte[] b1, final byte[] b2) { From 4d0e7b50ec967897a5400befb329177bb0256c69 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 15 Jan 2013 16:45:45 -0500 Subject: [PATCH 023/188] ArtificialBAMBuilder utility class for creating streams of GATKSAMRecords with a variety of properties -- Allows us to make a stream of reads or an index BAM file with read having the following properties (coming from n samples, of fixed read length and aligned to the genome with M operator, having N reads per alignment start, skipping N bases between each alignment start, starting at a given alignment start) -- This stream can be handed back to the caller immediately, or written to an indexed BAM file -- Update LocusIteratorByStateUnitTest to use this functionality (which was refactored from LIBS unit tests and ArtificialSAMUtils) --- .../sting/utils/sam/ArtificialBAMBuilder.java | 176 ++++++++++++++++++ .../sting/utils/sam/ArtificialSAMUtils.java | 29 --- .../LocusIteratorByStateUnitTest.java | 22 +-- .../sam/ArtificialBAMBuilderUnitTest.java | 122 ++++++++++++ 4 files changed, 305 insertions(+), 44 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java create mode 100644 public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java new file mode 100644 index 000000000..651d759e0 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java @@ -0,0 +1,176 @@ +/* + * 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.utils.sam; + +import net.sf.samtools.*; +import org.broadinstitute.sting.utils.NGSPlatform; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Easy to use creator of artificial BAM files for testing + * + * Allows us to make a stream of reads or an index BAM file with read having the following properties + * + * - coming from n samples + * - of fixed read length and aligned to the genome with M operator + * - having N reads per alignment start + * - skipping N bases between each alignment start + * - starting at a given alignment start + * + * User: depristo + * Date: 1/15/13 + * Time: 9:22 AM + */ +public class ArtificialBAMBuilder { + public final static int BAM_SHARD_SIZE = 16384; + + final int nReadsPerLocus; + final int nLoci; + + int skipNLoci = 0; + int alignmentStart = 1; + int readLength = 10; + private final ArrayList samples = new ArrayList(); + + final SAMFileWriterFactory factory = new SAMFileWriterFactory(); + { + factory.setCreateIndex(true); + } + + SAMFileHeader header; + + public ArtificialBAMBuilder(int nReadsPerLocus, int nLoci) { + this.nReadsPerLocus = nReadsPerLocus; + this.nLoci = nLoci; + createAndSetHeader(1); + } + + public ArtificialBAMBuilder createAndSetHeader(final int nSamples) { + this.header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000); + samples.clear(); + + for ( int i = 0; i < nSamples; i++ ) { + final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord("rg" + i); + final String sample = "sample" + i; + samples.add(sample); + rg.setSample(sample); + rg.setPlatform(NGSPlatform.ILLUMINA.getDefaultPlatform()); + header.addReadGroup(rg); + } + + return this; + } + + public List getSamples() { + return samples; + } + + /** + * Create a read stream based on the parameters. The cigar string for each + * read will be *M, where * is the length of the read. + * + * Useful for testing things like LocusIteratorBystate + * + * @return a ordered list of reads + */ + public List makeReads() { + final String baseName = "read"; + List reads = new ArrayList(nReadsPerLocus*nLoci); + for ( int locusI = 0; locusI < nLoci; locusI++) { + final int locus = locusI * (skipNLoci + 1); + for ( int readI = 0; readI < nReadsPerLocus; readI++ ) { + for ( final SAMReadGroupRecord rg : header.getReadGroups() ) { + final String readName = String.format("%s.%d.%d.%s", baseName, locus, readI, rg.getId()); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, alignmentStart + locus, readLength); + read.setReadGroup(new GATKSAMReadGroupRecord(rg)); + reads.add(read); + } + } + } + + return reads; + } + + /** + * Make an indexed BAM file contains the reads in the builder, marking it for deleteOnExit() + * @return the BAM file + */ + public File makeTemporarilyBAMFile() { + try { + final File file = File.createTempFile("tempBAM", ".bam"); + file.deleteOnExit(); + return makeBAMFile(file); + } catch ( IOException e ) { + throw new RuntimeException(e); + } + } + + /** + * Write the reads from this builder to output, creating an index as well + * @param output the output BAM file we want to use + * @return + */ + public File makeBAMFile(final File output) { + final SAMFileWriter writer = factory.makeBAMWriter(header, true, output, 0); + for ( final GATKSAMRecord read : makeReads() ) + writer.addAlignment(read); + writer.close(); + return output; + } + + public int getnReadsPerLocus() { return nReadsPerLocus; } + public int getnLoci() { return nLoci; } + public int getSkipNLoci() { return skipNLoci; } + public ArtificialBAMBuilder setSkipNLoci(int skipNLoci) { this.skipNLoci = skipNLoci; return this; } + public int getAlignmentStart() { return alignmentStart; } + public ArtificialBAMBuilder setAlignmentStart(int alignmentStart) { this.alignmentStart = alignmentStart; return this; } + public int getReadLength() { return readLength; } + public ArtificialBAMBuilder setReadLength(int readLength) { this.readLength = readLength; return this; } + public SAMFileHeader getHeader() { return header; } + public ArtificialBAMBuilder setHeader(SAMFileHeader header) { this.header = header; return this; } + + public int getNSamples() { return samples.size(); } + + public int expectedNumberOfReads() { + return nLoci * nReadsPerLocus * header.getReadGroups().size(); + } + + @Override + public String toString() { + return "ArtificialBAMBuilder{" + + "samples=" + samples + + ", readLength=" + readLength + + ", alignmentStart=" + alignmentStart + + ", skipNLoci=" + skipNLoci + + ", nLoci=" + nLoci + + ", nReadsPerLocus=" + nReadsPerLocus + + '}'; + } +} diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java index 4af6555d9..0f5d6a2f7 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java @@ -327,35 +327,6 @@ public class ArtificialSAMUtils { return stack; } - /** - * Create a read stream based on the parameters. The cigar string for each - * read will be *M, where * is the length of the read. - * - * Useful for testing things like LocusIteratorBystate - * - * @return a collection of stackSize reads all sharing the above properties - */ - public static List createReadStream( final int nReadsPerLocus, - final int nLoci, - final SAMFileHeader header, - final int alignmentStart, - final int length ) { - final String baseName = "read"; - List reads = new ArrayList(nReadsPerLocus*nLoci); - for ( int locus = 0; locus < nLoci; locus++ ) { - for ( int readI = 0; readI < nReadsPerLocus; readI++ ) { - for ( final SAMReadGroupRecord rg : header.getReadGroups() ) { - final String readName = String.format("%s.%d.%d.%s", baseName, locus, readI, rg.getId()); - final GATKSAMRecord read = createArtificialRead(header, readName, 0, alignmentStart + locus, length); - read.setReadGroup(new GATKSAMReadGroupRecord(rg)); - reads.add(read); - } - } - } - - return reads; - } - /** * create an iterator containing the specified read piles * diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index 37494903c..2f984165e 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -28,17 +28,16 @@ package org.broadinstitute.sting.utils.locusiterator; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMFileHeader; import net.sf.samtools.SAMReadGroupRecord; -import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.ReadProperties; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.gatk.downsampling.DownsamplingMethod; -import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.NGSPlatform; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; +import org.broadinstitute.sting.utils.sam.ArtificialBAMBuilder; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -447,26 +446,19 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { //logger.warn(String.format("testLIBSKeepSubmittedReads %d %d %d %b %b %b", nReadsPerLocus, nLoci, nSamples, keepReads, grabReadsAfterEachCycle, downsample)); final int readLength = 10; - final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100000); - final List samples = new ArrayList(nSamples); - for ( int i = 0; i < nSamples; i++ ) { - final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord("rg" + i); - final String sample = "sample" + i; - samples.add(sample); - rg.setSample(sample); - rg.setPlatform(NGSPlatform.ILLUMINA.getDefaultPlatform()); - header.addReadGroup(rg); - } - final boolean downsample = downsampleTo != -1; final DownsamplingMethod downsampler = downsample ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) : new DownsamplingMethod(DownsampleType.NONE, null, null, false); - final List reads = ArtificialSAMUtils.createReadStream(nReadsPerLocus, nLoci, header, 1, readLength); + + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(nReadsPerLocus, nLoci); + bamBuilder.createAndSetHeader(nSamples).setReadLength(readLength).setAlignmentStart(1); + + final List reads = bamBuilder.makeReads(); li = new LocusIteratorByState(new FakeCloseableIterator(reads.iterator()), createTestReadProperties(downsampler, keepReads), genomeLocParser, - samples); + bamBuilder.getSamples()); final Set seenSoFar = new HashSet(); final Set keptReads = new HashSet(); diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java new file mode 100644 index 000000000..cf3c97b34 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java @@ -0,0 +1,122 @@ +/* + * 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.utils.sam; + +import net.sf.samtools.SAMFileReader; +import net.sf.samtools.SAMRecord; +import org.apache.commons.collections.IteratorUtils; +import org.broadinstitute.sting.BaseTest; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: depristo + * Date: 1/15/13 + * Time: 3:49 PM + * To change this template use File | Settings | File Templates. + */ +public class ArtificialBAMBuilderUnitTest extends BaseTest { + @DataProvider(name = "CombinatorialARTTilingProvider") + public Object[][] makeCombinatorialARTTilingProvider() { + final List tests = new LinkedList(); + + final List starts = Arrays.asList( + 1, // very start of the chromosome + ArtificialBAMBuilder.BAM_SHARD_SIZE - 100, // right before the shard boundary + ArtificialBAMBuilder.BAM_SHARD_SIZE + 100 // right after the shard boundary + ); + + for ( final int readLength : Arrays.asList(10, 20) ) { + for ( final int skips : Arrays.asList(0, 1, 10) ) { + for ( final int start : starts ) { + for ( final int nSamples : Arrays.asList(1, 2) ) { + for ( final int nReadsPerLocus : Arrays.asList(1, 10) ) { + for ( final int nLoci : Arrays.asList(10, 100, 1000) ) { + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(nReadsPerLocus, nLoci); + bamBuilder.setReadLength(readLength); + bamBuilder.setSkipNLoci(skips); + bamBuilder.setAlignmentStart(start); + bamBuilder.createAndSetHeader(nSamples); + tests.add(new Object[]{bamBuilder, readLength, skips, start, nSamples, nReadsPerLocus, nLoci}); + } + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "CombinatorialARTTilingProvider") + public void testBamProvider(final ArtificialBAMBuilder bamBuilder, int readLength, int skips, int start, int nSamples, int nReadsPerLocus, int nLoci) { + Assert.assertEquals(bamBuilder.getReadLength(), readLength); + Assert.assertEquals(bamBuilder.getSkipNLoci(), skips); + Assert.assertEquals(bamBuilder.getAlignmentStart(), start); + Assert.assertEquals(bamBuilder.getNSamples(), nSamples); + Assert.assertEquals(bamBuilder.getnReadsPerLocus(), nReadsPerLocus); + Assert.assertEquals(bamBuilder.getnLoci(), nLoci); + + final List reads = bamBuilder.makeReads(); + Assert.assertEquals(reads.size(), bamBuilder.expectedNumberOfReads()); + for ( final GATKSAMRecord read : reads ) { + assertGoodRead(read, bamBuilder); + } + + final File bam = bamBuilder.makeTemporarilyBAMFile(); + final SAMFileReader reader = new SAMFileReader(bam); + Assert.assertTrue(reader.hasIndex()); + final Iterator bamIt = reader.iterator(); + int nReadsFromBam = 0; + int lastStart = -1; + while ( bamIt.hasNext() ) { + final SAMRecord read = bamIt.next(); + assertGoodRead(read, bamBuilder); + nReadsFromBam++; + Assert.assertTrue(read.getAlignmentStart() >= lastStart); + lastStart = read.getAlignmentStart(); + } + Assert.assertEquals(nReadsFromBam, bamBuilder.expectedNumberOfReads()); + } + + private void assertGoodRead(final SAMRecord read, final ArtificialBAMBuilder bamBuilder) { + Assert.assertEquals(read.getReadLength(), bamBuilder.getReadLength()); + Assert.assertEquals(read.getReadBases().length, bamBuilder.getReadLength()); + Assert.assertEquals(read.getBaseQualities().length, bamBuilder.getReadLength()); + Assert.assertTrue(read.getAlignmentStart() >= bamBuilder.getAlignmentStart()); + Assert.assertNotNull(read.getReadGroup()); + } +} + + From ddcb33fcf81cd208bc8ad6e23aeb1eb49624ea07 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 16 Jan 2013 12:09:36 -0500 Subject: [PATCH 024/188] Cache result of getLocation() in Shard so we don't performance expensive calculation over and over --- .../sting/gatk/datasources/reads/Shard.java | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/Shard.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/Shard.java index 2c03363ba..5b4c2afda 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/Shard.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/Shard.java @@ -95,7 +95,10 @@ public abstract class Shard implements HasGenomeLocation { */ private final Map fileSpans; - + /** + * Lazy-calculated span of all of the genome locs in this shard + */ + private GenomeLoc spanningLocation = null; /** * Statistics about which reads in this shards were used and which were filtered away. @@ -148,27 +151,34 @@ public abstract class Shard implements HasGenomeLocation { /** * Returns the span of the genomeLocs comprising this shard - * @param - * @return + * @return a GenomeLoc that starts as the first position in getGenomeLocs() and stops at the stop of the last + * position in getGenomeLocs() */ public GenomeLoc getLocation() { - if ( getGenomeLocs() == null ) - return GenomeLoc.WHOLE_GENOME; + if ( spanningLocation == null ) { + if ( getGenomeLocs() == null ) + spanningLocation = GenomeLoc.WHOLE_GENOME; + else if ( getGenomeLocs().size() == 0 ) { + spanningLocation = getGenomeLocs().get(0); + } else { + int start = Integer.MAX_VALUE; + int stop = Integer.MIN_VALUE; + String contig = null; - int start = Integer.MAX_VALUE; - int stop = Integer.MIN_VALUE; - String contig = null; + for ( GenomeLoc loc : getGenomeLocs() ) { + if ( GenomeLoc.isUnmapped(loc) ) + // special case the unmapped region marker, just abort out + return loc; + contig = loc.getContig(); + if ( loc.getStart() < start ) start = loc.getStart(); + if ( loc.getStop() > stop ) stop = loc.getStop(); + } - for ( GenomeLoc loc : getGenomeLocs() ) { - if ( GenomeLoc.isUnmapped(loc) ) - // special case the unmapped region marker, just abort out - return loc; - contig = loc.getContig(); - if ( loc.getStart() < start ) start = loc.getStart(); - if ( loc.getStop() > stop ) stop = loc.getStop(); + spanningLocation = parser.createGenomeLoc(contig, start, stop); + } } - return parser.createGenomeLoc(contig, start, stop); + return spanningLocation; } From 2a42b47e4a19c17ae3dad64a980e856229875295 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 16 Jan 2013 15:29:26 -0500 Subject: [PATCH 025/188] Massive expansion of ActiveRegionTraversal unit tests, resulting in several bugfixes to ART -- UnitTests now include combinational tiling of reads within and spanning shard boundaries -- ART now properly handles shard transitions, and does so efficiently without requiring hash sets or other collections of reads -- Updating HC and CountReadsInActiveRegions integration tests --- .../HaplotypeCallerIntegrationTest.java | 12 +- .../traversals/TraverseActiveRegions.java | 226 +++++++++++++----- .../sting/utils/sam/ArtificialBAMBuilder.java | 39 ++- .../traversals/DummyActiveRegionWalker.java | 104 ++++++++ .../TraverseActiveRegionsUnitTest.java | 207 +++++++++++----- .../LocusIteratorByStateUnitTest.java | 28 ++- .../sam/ArtificialBAMBuilderUnitTest.java | 6 +- 7 files changed, 482 insertions(+), 140 deletions(-) create mode 100644 public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 6183fc411..e86834a4a 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "1e2671557b01ad0497557097282965fc"); + HCTest(CEUTRIO_BAM, "", "b8f7b741445ce6b6ea491c794ce75c17"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "2bd237a7e1e63eebe755dbe7963e430a"); + HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); } @Test(enabled = false) @@ -84,7 +84,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "a938cdd7262968597fc8eb6c1c0a69f1"); + "c679ae7f04bdfda896b5c046d35e043c"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -102,7 +102,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "d590c8d6d5e58d685401b65a23846893"); + "1a034b7eb572e1b6f659d6e5d57b3e76"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "50a26224b9e863ee47a0619eb54a0323"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "29f1125df5ab27cc937a144ae08ac735"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,7 +146,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("4439496472eb1e2f5c91b30ba525be37")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("8b1b8d1bd7feac1503fc4ffa6236cff7")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 03aaf95f2..a7e4d7649 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -25,6 +25,7 @@ package org.broadinstitute.sting.gatk.traversals; +import com.google.java.contract.Requires; import org.apache.log4j.Logger; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.WalkerManager; @@ -47,24 +48,36 @@ import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import java.util.*; /** - * Created with IntelliJ IDEA. + * Implement active region traversal + * * User: depristo * Date: 1/9/13 * Time: 4:45 PM - * To change this template use File | Settings | File Templates. + * + * Live region: + * + * The ART tracks a thing called the live region. The live region is a position on a specific contig + * of the alignment start of the last read we processed during this traversal. Because the + * read stream is sorted, future reads must occurs in the the live region. Therefore the the dead region + * (everything to the left of the live boundary) cannot have any more read data. The live / dead + * regions are used to decide when we can safely call map on active regions, as only active regions + * contained completely within the dead region (including extensions) have a complete set of read data + * in the collected read list. All of the data related to the live region is captured by the local + * variable spanOfLastReadSeen + * */ public class TraverseActiveRegions extends TraversalEngine,LocusShardDataProvider> { + protected final static Logger logger = Logger.getLogger(TraversalEngine.class); protected final static boolean DEBUG = false; // set by the tranversal private int activeRegionExtension = -1; private int maxRegionSize = -1; - /** - * our log, which we want to capture anything from this class - */ - protected final static Logger logger = Logger.getLogger(TraversalEngine.class); - protected final LinkedList workQueue = new LinkedList(); + private final LinkedList workQueue = new LinkedList(); + + private LinkedList myReads = new LinkedList(); + private GenomeLoc spanOfLastReadSeen = null; protected int getActiveRegionExtension() { return activeRegionExtension; @@ -79,6 +92,11 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine myReads = new LinkedList(); - private Shard lastShard = null; + /** + * Did read appear in the last shard? + * + * When we transition across shard boundaries we see duplicate reads because + * each shard contains the reads that *overlap* the shard. So if we just finished + * shard 1-1000 and are now in 1001-2000 we'll see duplicate reads from 1001 + * that overlapped 1-1000. This function tests read to determine if we would have + * seen it before by asking if read.getAlignmentStart() is less than the + * stop position of the last seen read at the start of the traversal. The reason + * we need to use the location of the last read at the start of the traversal + * is that we update the lastRead during the traversal, and we only want to filter + * out reads whose start is before the last read of the previous shard, not the + * current shard. + * + * @param locOfLastReadAtTraversalStart the location of the last read seen at the start of the traversal + * @param read the read we want to test if it's already been seen in the last shard + * @return true if read would have appeared in the last shard, false otherwise + */ + protected boolean appearedInLastShard(final GenomeLoc locOfLastReadAtTraversalStart, final GATKSAMRecord read) { + if ( locOfLastReadAtTraversalStart == null ) + // we're in the first shard, so obviously the answer is no + return false; + else { + // otherwise check to see if the alignment occurred in the previous shard + return read.getAlignmentStart() <= locOfLastReadAtTraversalStart.getStart() + // we're on the same contig + && read.getReferenceIndex() == locOfLastReadAtTraversalStart.getContigIndex(); + } + + } + + // ------------------------------------------------------------------------------------- + // + // Actual traverse function + // + // ------------------------------------------------------------------------------------- + + /** + * Is the current shard on a new contig w.r.t. the previous shard? + * @param currentShard the current shard we are processing + * @return true if the last shard was on a different contig than the current shard + */ + private boolean onNewContig(final Shard currentShard) { + return spanOfLastSeenRead() != null + && spanOfLastSeenRead().getContigIndex() != currentShard.getLocation().getContigIndex(); + } @Override public T traverse( final ActiveRegionWalker walker, final LocusShardDataProvider dataProvider, T sum) { - if ( DEBUG ) logger.warn(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); - - final HashSet maybeDuplicatedReads = new HashSet(); - // TODO -- there's got to be a better way to know this - if ( lastShard != dataProvider.getShard() ) { - maybeDuplicatedReads.addAll(myReads); - logger.info("Crossing shard boundary requires us to check for duplicates against " + maybeDuplicatedReads.size() + " reads"); - if ( DEBUG ) logger.warn("Clearing myReads"); - } - lastShard = dataProvider.getShard(); + logger.debug(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); final LocusView locusView = new AllLocusView(dataProvider); @@ -181,6 +234,12 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); for( final GATKSAMRecord read : reads ) { - notifyOfCurrentPosition(read); - // most of the time maybeDuplicatedReads is empty - // TODO -- I believe that because of the ordering of reads that as soon as we don't find a read in the - // TODO -- potential list of duplicates we can clear the hashset - if ( ! maybeDuplicatedReads.isEmpty() && maybeDuplicatedReads.contains(read) ) { + if ( appearedInLastShard(locOfLastReadAtTraversalStart, read) ) { if ( DEBUG ) logger.warn("Skipping duplicated " + read.getReadName()); } else { if ( DEBUG ) logger.warn("Adding read " + read.getReadName() + " at " + engine.getGenomeLocParser().createGenomeLoc(read) + " from provider " + dataProvider); - myReads.add((GATKSAMRecord)read); + rememberLastReadLocation(read); + myReads.add(read); } } @@ -257,28 +313,87 @@ public class TraverseActiveRegions extends TraversalEngine walker, T sum) { + return processActiveRegions((ActiveRegionWalker)walker, sum, true); } - protected void notifyOfCurrentPosition(final GenomeLoc currentLocation) { - if ( startOfLiveRegion == null ) - startOfLiveRegion = currentLocation; - else - startOfLiveRegion = startOfLiveRegion.max(currentLocation.getStartLocation()); + // ------------------------------------------------------------------------------------- + // + // Functions to manage and interact with the live / dead zone + // + // ------------------------------------------------------------------------------------- + + /** + * Update the live region to reflect that the last read we've seen in the traversal is read + * + * Requires that sequential calls always be provided reads in coordinate sorted order + * + * @param read the last read we've seen during the traversal + */ + protected void rememberLastReadLocation(final GATKSAMRecord read) { + final GenomeLoc currentLocation = engine.getGenomeLocParser().createGenomeLoc(read); + if ( spanOfLastReadSeen == null ) + spanOfLastReadSeen = currentLocation; + else { + if ( currentLocation.isBefore(spanOfLastReadSeen) ) + throw new IllegalStateException("Updating last read seen in the traversal with read " + read + " with span " + currentLocation + " but this occurs before the previously seen read " + spanOfLastReadSeen); + spanOfLastReadSeen = currentLocation; + } } - protected GenomeLoc getStartOfLiveRegion() { - return startOfLiveRegion; + /** + * Get a GenomeLoc indicating the start (heading to the right) of the live ART region. + * @return the left-most position of the live region on the genome + */ + protected GenomeLoc spanOfLastSeenRead() { + return spanOfLastReadSeen; } - protected boolean regionCompletelyWithinDeadZone(final GenomeLoc region, final boolean includeExtension) { - return (region.getStop() < (getStartOfLiveRegion().getStart() - (includeExtension ? getActiveRegionExtension() : 0))) - || ! region.onSameContig(getStartOfLiveRegion()); + /** + * Is the active region completely within the traversal's dead zone? + * + * @param region the region we want to test + * @return true if the extended location of region is completely within the current dead zone, false otherwise + */ + protected boolean regionCompletelyWithinDeadZone(final ActiveRegion region) { + return region.getExtendedLoc().getStop() < spanOfLastSeenRead().getStart() + || ! region.getExtendedLoc().onSameContig(spanOfLastSeenRead()); } + /** + * Is the read dead? That is, can it no longer be in any future active region, and therefore can be discarded? + * + * read: start |--------> stop ------ stop + extension + * region: start |-----------------| end + * + * Since the regions are coming in order, read could potentially be contained in a future interval if + * stop + activeRegionExtension >= end. If, on the other hand, stop + extension is < the end + * of this region, then we can discard it, since any future region could only include reads + * up to end + 1 - extension. + * + * Note that this function doesn't care about the dead zone. We're assuming that by + * actually calling this function with an active region that region is already in the dead zone, + * so checking that the read is in the dead zone doesn't make sense. + * + * @param read the read we're testing + * @param activeRegion the current active region + * @return true if the read is dead, false other + */ + @Requires({"read != null", "activeRegion != null"}) + private boolean readCannotOccurInAnyMoreActiveRegions(final GATKSAMRecord read, final ActiveRegion activeRegion) { + return read.getAlignmentEnd() + getActiveRegionExtension() < activeRegion.getLocation().getStop(); + } + + // ------------------------------------------------------------------------------------- + // + // Functions to process active regions that are ready for map / reduce calls + // + // ------------------------------------------------------------------------------------- + private T processActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { if( walker.activeRegionOutStream != null ) { writeActiveRegionsToStream(walker); @@ -292,11 +407,10 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine walker) { final Iterator liveReads = myReads.iterator(); while ( liveReads.hasNext() ) { @@ -325,7 +430,7 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine walker, T sum) { - return processActiveRegions((ActiveRegionWalker)walker, sum, true); - } } diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java index 651d759e0..f5018db8c 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java @@ -25,7 +25,9 @@ package org.broadinstitute.sting.utils.sam; +import net.sf.picard.reference.IndexedFastaSequenceFile; import net.sf.samtools.*; +import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.NGSPlatform; import java.io.File; @@ -51,6 +53,9 @@ import java.util.List; public class ArtificialBAMBuilder { public final static int BAM_SHARD_SIZE = 16384; + private final IndexedFastaSequenceFile reference; + private final GenomeLocParser parser; + final int nReadsPerLocus; final int nLoci; @@ -66,14 +71,39 @@ public class ArtificialBAMBuilder { SAMFileHeader header; - public ArtificialBAMBuilder(int nReadsPerLocus, int nLoci) { + public ArtificialBAMBuilder(final IndexedFastaSequenceFile reference, int nReadsPerLocus, int nLoci) { this.nReadsPerLocus = nReadsPerLocus; this.nLoci = nLoci; + + this.reference = reference; + this.parser = new GenomeLocParser(reference); createAndSetHeader(1); } + public ArtificialBAMBuilder(int nReadsPerLocus, int nLoci) { + this(ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000).getSequenceDictionary(), nReadsPerLocus, nLoci); + } + + public ArtificialBAMBuilder(final SAMSequenceDictionary dict, int nReadsPerLocus, int nLoci) { + this.nReadsPerLocus = nReadsPerLocus; + this.nLoci = nLoci; + this.reference = null; + this.parser = new GenomeLocParser(dict); + createAndSetHeader(1); + } + + public IndexedFastaSequenceFile getReference() { + return reference; + } + + public GenomeLocParser getGenomeLocParser() { + return parser; + } + public ArtificialBAMBuilder createAndSetHeader(final int nSamples) { - this.header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 1000000); + this.header = new SAMFileHeader(); + header.setSortOrder(SAMFileHeader.SortOrder.coordinate); + header.setSequenceDictionary(parser.getContigs()); samples.clear(); for ( int i = 0; i < nSamples; i++ ) { @@ -156,6 +186,11 @@ public class ArtificialBAMBuilder { public SAMFileHeader getHeader() { return header; } public ArtificialBAMBuilder setHeader(SAMFileHeader header) { this.header = header; return this; } + public int getAlignmentEnd() { + return alignmentStart + nLoci * (skipNLoci + 1) + readLength; + } + + public int getNSamples() { return samples.size(); } public int expectedNumberOfReads() { diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java new file mode 100644 index 000000000..bc1e1d7b0 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java @@ -0,0 +1,104 @@ +/* + * 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.traversals; + +import org.broadinstitute.sting.gatk.contexts.AlignmentContext; +import org.broadinstitute.sting.gatk.contexts.ReferenceContext; +import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; +import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocSortedSet; +import org.broadinstitute.sting.utils.activeregion.ActiveRegion; +import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; + +import java.util.*; + +/** + * ActiveRegionWalker for unit testing + * + * User: depristo + * Date: 1/15/13 + * Time: 1:28 PM + */ +class DummyActiveRegionWalker extends ActiveRegionWalker { + private final double prob; + private EnumSet states = super.desiredReadStates(); + private GenomeLocSortedSet activeRegions = null; + + protected List isActiveCalls = new ArrayList(); + protected Map mappedActiveRegions = new LinkedHashMap(); + + public DummyActiveRegionWalker() { + this(1.0); + } + + public DummyActiveRegionWalker(double constProb) { + this.prob = constProb; + } + + public DummyActiveRegionWalker(EnumSet wantStates) { + this(1.0); + this.states = wantStates; + } + + public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions) { + this(1.0); + this.activeRegions = activeRegions; + } + + public void setStates(EnumSet states) { + this.states = states; + } + + @Override + public EnumSet desiredReadStates() { + return states; + } + + @Override + public ActivityProfileResult isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + isActiveCalls.add(ref.getLocus()); + final double p = activeRegions == null || activeRegions.overlaps(ref.getLocus()) ? prob : 0.0; + return new ActivityProfileResult(ref.getLocus(), p); + } + + @Override + public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) { + mappedActiveRegions.put(activeRegion.getLocation(), activeRegion); + return 0; + } + + @Override + public Integer reduceInit() { + return 0; + } + + @Override + public Integer reduce(Integer value, Integer sum) { + return 0; + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java index c4dadbcce..15d4eec2d 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java @@ -30,33 +30,26 @@ import net.sf.samtools.*; import org.broadinstitute.sting.commandline.Tags; import org.broadinstitute.sting.gatk.arguments.ValidationExclusion; import org.broadinstitute.sting.gatk.datasources.reads.*; -import org.broadinstitute.sting.gatk.downsampling.DownsamplingMethod; import org.broadinstitute.sting.gatk.filters.ReadFilter; import org.broadinstitute.sting.gatk.iterators.ReadTransformer; import org.broadinstitute.sting.gatk.resourcemanagement.ThreadAllocation; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLocSortedSet; +import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; import org.broadinstitute.sting.utils.interval.IntervalMergingRule; import org.broadinstitute.sting.utils.interval.IntervalUtils; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.sam.*; import net.sf.picard.reference.IndexedFastaSequenceFile; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.sting.gatk.contexts.AlignmentContext; -import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.datasources.providers.LocusShardDataProvider; import org.broadinstitute.sting.gatk.datasources.rmd.ReferenceOrderedDataSource; import org.broadinstitute.sting.gatk.executive.WindowMaker; -import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; -import org.broadinstitute.sting.utils.sam.ReadUtils; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -80,54 +73,6 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { private final static boolean ENFORCE_CONTRACTS = false; private final static boolean DEBUG = false; - private class DummyActiveRegionWalker extends ActiveRegionWalker { - private final double prob; - private EnumSet states = super.desiredReadStates(); - - protected List isActiveCalls = new ArrayList(); - protected Map mappedActiveRegions = new HashMap(); - - public DummyActiveRegionWalker() { - this.prob = 1.0; - } - - public DummyActiveRegionWalker(double constProb) { - this.prob = constProb; - } - - public DummyActiveRegionWalker(EnumSet wantStates) { - this.prob = 1.0; - this.states = wantStates; - } - - @Override - public EnumSet desiredReadStates() { - return states; - } - - @Override - public ActivityProfileResult isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { - isActiveCalls.add(ref.getLocus()); - return new ActivityProfileResult(ref.getLocus(), prob); - } - - @Override - public Integer map(ActiveRegion activeRegion, RefMetaDataTracker metaDataTracker) { - mappedActiveRegions.put(activeRegion.getLocation(), activeRegion); - return 0; - } - - @Override - public Integer reduceInit() { - return 0; - } - - @Override - public Integer reduce(Integer value, Integer sum) { - return 0; - } - } - @DataProvider(name = "TraversalEngineProvider") public Object[][] makeTraversals() { final List traversals = new LinkedList(); @@ -297,7 +242,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { } } - @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider") + @Test(enabled = true, dataProvider = "TraversalEngineProvider") public void testPrimaryReadMapping(TraverseActiveRegions t) { DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); @@ -340,7 +285,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { verifyReadMapping(region, "simple20"); } - @Test(enabled = true, dataProvider = "TraversalEngineProvider") + @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider") public void testNonPrimaryReadMapping(TraverseActiveRegions t) { DummyActiveRegionWalker walker = new DummyActiveRegionWalker( EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY)); @@ -456,7 +401,11 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { } private Map getActiveRegions(TraverseActiveRegions t, DummyActiveRegionWalker walker, List intervals) { - for (LocusShardDataProvider dataProvider : createDataProviders(t, walker, intervals, testBAM)) + return getActiveRegions(t, walker, intervals, testBAM); + } + + private Map getActiveRegions(TraverseActiveRegions t, DummyActiveRegionWalker walker, List intervals, final String bam) { + for (LocusShardDataProvider dataProvider : createDataProviders(t, walker, intervals, bam)) t.traverse(walker, dataProvider, 0); t.endTraversal(walker, 0); @@ -516,14 +465,15 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { record.setCigar(cigar); record.setReadString(new String(new char[len]).replace("\0", "A")); record.setBaseQualities(new byte[len]); + record.setReadGroup(new GATKSAMReadGroupRecord(header.getReadGroup("test"))); return record; } - private List createDataProviders(TraverseActiveRegions t, final Walker walker, List intervals, String bamFile) { + private List createDataProviders(TraverseActiveRegions traverseActiveRegions, final Walker walker, List intervals, String bamFile) { GenomeAnalysisEngine engine = new GenomeAnalysisEngine(); engine.setGenomeLocParser(genomeLocParser); - t.initialize(engine, walker); + traverseActiveRegions.initialize(engine, walker); Collection samFiles = new ArrayList(); SAMReaderID readerID = new SAMReaderID(new File(bamFile), new Tags()); @@ -539,13 +489,144 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { new ArrayList(), false, (byte)30, false, true); + final Set samples = SampleUtils.getSAMFileSamples(dataSource.getHeader()); + List providers = new ArrayList(); for (Shard shard : dataSource.createShardIteratorOverIntervals(new GenomeLocSortedSet(genomeLocParser, intervals), new LocusShardBalancer())) { - for (WindowMaker.WindowMakerIterator window : new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs())) { + for (WindowMaker.WindowMakerIterator window : new WindowMaker(shard, genomeLocParser, dataSource.seek(shard), shard.getGenomeLocs(), samples)) { providers.add(new LocusShardDataProvider(shard, shard.getReadProperties(), genomeLocParser, window.getLocus(), window, reference, new ArrayList())); } } return providers; } + + @DataProvider(name = "CombinatorialARTTilingProvider") + public Object[][] makeCombinatorialARTTilingProvider() { + final List tests = new LinkedList(); + + final List starts = Arrays.asList( + 1, // very start of the chromosome + ArtificialBAMBuilder.BAM_SHARD_SIZE - 100, // right before the shard boundary + ArtificialBAMBuilder.BAM_SHARD_SIZE + 100 // right after the shard boundary + ); + + final List> allReadStates = Arrays.asList( + EnumSet.of(ActiveRegionReadState.PRIMARY), + EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY), + EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED) + ); + + final int maxTests = Integer.MAX_VALUE; + int nTests = 0; + for ( final int readLength : Arrays.asList(10, 100) ) { + for ( final int skips : Arrays.asList(0, 1, 10) ) { + for ( final int start : starts ) { + for ( final int nReadsPerLocus : Arrays.asList(1, 2) ) { + for ( final int nLoci : Arrays.asList(1, 1000) ) { + for ( EnumSet readStates : allReadStates ) { + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci); + bamBuilder.setReadLength(readLength); + bamBuilder.setSkipNLoci(skips); + bamBuilder.setAlignmentStart(start); + + for ( final GenomeLocSortedSet activeRegions : enumerateActiveRegions(bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd())) { + nTests++; + if ( nTests < maxTests ) // && nTests == 1238 ) + tests.add(new Object[]{nTests, activeRegions, readStates, bamBuilder}); + } + } + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + private Collection enumerateActiveRegions(final int start, final int stop) { + // should basically cut up entire region into equal sized chunks, of + // size 10, 20, 50, 100, etc, alternating skipping pieces so they are inactive + // Need to make sure we include some edge cases: + final List activeRegions = new LinkedList(); + + for ( final int stepSize : Arrays.asList(11, 29, 53, 97) ) { + for ( final boolean startWithActive : Arrays.asList(true, false) ) { + activeRegions.add(makeActiveRegionMask(start, stop, stepSize, startWithActive)); + } + } + + // active region is the whole interval + activeRegions.add(new GenomeLocSortedSet(genomeLocParser, genomeLocParser.createGenomeLoc("1", start, stop))); + + // active region extends up to the end of the data, but doesn't include start + activeRegions.add(new GenomeLocSortedSet(genomeLocParser, genomeLocParser.createGenomeLoc("1", start+10, stop))); + + return activeRegions; + } + + private GenomeLocSortedSet makeActiveRegionMask(final int start, final int stop, final int stepSize, final boolean startWithActive) { + final GenomeLocSortedSet active = new GenomeLocSortedSet(genomeLocParser); + + boolean includeRegion = startWithActive; + for ( int left = start; left < stop; left += stepSize) { + final int right = left + stepSize; + final GenomeLoc region = genomeLocParser.createGenomeLoc("1", left, right); + if ( includeRegion ) + active.add(region); + includeRegion = ! includeRegion; + } + + return active; + } + + + @Test(enabled = true, dataProvider = "CombinatorialARTTilingProvider") + public void testARTReadsInActiveRegions(final int id, final GenomeLocSortedSet activeRegions, final EnumSet readStates, final ArtificialBAMBuilder bamBuilder) { + logger.warn("Running testARTReadsInActiveRegions id=" + id + " locs " + activeRegions + " against bam " + bamBuilder); + final List intervals = Arrays.asList( + genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd()) + ); + + final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions); + walker.setStates(readStates); + + final TraverseActiveRegions traversal = new TraverseActiveRegions(); + final Map activeRegionsMap = getActiveRegions(traversal, walker, intervals, bamBuilder.makeTemporarilyBAMFile().toString()); + + final Set alreadySeenReads = new HashSet(); // for use with the primary / non-primary + for ( final ActiveRegion region : activeRegionsMap.values() ) { + int nReadsExpectedInRegion = 0; + for ( final GATKSAMRecord read : bamBuilder.makeReads() ) { + final GenomeLoc readLoc = genomeLocParser.createGenomeLoc(read); + final Set readNamesInRegion = readNamesInRegion(region); + + boolean shouldBeInRegion = readStates.contains(ActiveRegionReadState.EXTENDED) + ? region.getExtendedLoc().overlapsP(readLoc) + : region.getLocation().overlapsP(readLoc); + + if ( ! readStates.contains(ActiveRegionReadState.NONPRIMARY) ) { + if ( alreadySeenReads.contains(read.getReadName()) ) + shouldBeInRegion = false; + else if ( shouldBeInRegion ) + alreadySeenReads.add(read.getReadName()); + } + + Assert.assertEquals(readNamesInRegion.contains(read.getReadName()), shouldBeInRegion, "Region " + region + + " failed contains read check: read " + read + " with span " + readLoc + " should be in region is " + shouldBeInRegion + " but I got the opposite"); + + nReadsExpectedInRegion += shouldBeInRegion ? 1 : 0; + } + + Assert.assertEquals(region.size(), nReadsExpectedInRegion, "There are more reads in active region " + region + "than expected"); + } + } + + private Set readNamesInRegion(final ActiveRegion region) { + final Set readNames = new LinkedHashSet(region.getReads().size()); + for ( final SAMRecord read : region.getReads() ) + readNames.add(read.getReadName()); + return readNames; + } } diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index 2f984165e..e5e28e1f6 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -54,6 +54,32 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { private static final boolean DEBUG = false; protected LocusIteratorByState li; + @Test(enabled = true) + public void testUnmappedAndAllIReadsPassThrough() { + final int readLength = 10; + GATKSAMRecord mapped1 = ArtificialSAMUtils.createArtificialRead(header,"mapped1",0,1,readLength); + GATKSAMRecord mapped2 = ArtificialSAMUtils.createArtificialRead(header,"mapped2",0,1,readLength); + GATKSAMRecord unmapped = ArtificialSAMUtils.createArtificialRead(header,"unmapped",0,1,readLength); + GATKSAMRecord allI = ArtificialSAMUtils.createArtificialRead(header,"allI",0,1,readLength); + + unmapped.setReadUnmappedFlag(true); + unmapped.setCigarString("*"); + allI.setCigarString(readLength + "I"); + + List reads = Arrays.asList(mapped1, unmapped, allI, mapped2); + + // create the iterator by state with the fake reads and fake records + li = makeLTBS(reads,createTestReadProperties(DownsamplingMethod.NONE, true)); + + Assert.assertTrue(li.hasNext()); + AlignmentContext context = li.next(); + ReadBackedPileup pileup = context.getBasePileup(); + Assert.assertEquals(pileup.depthOfCoverage(), 2, "Should see only 2 reads in pileup, even with unmapped and all I reads"); + + final List rawReads = li.transferReadsFromAllPreviousPileups(); + Assert.assertEquals(rawReads, reads, "Input and transferred read lists should be the same, and include the unmapped and all I reads"); + } + @Test(enabled = true && ! DEBUG) public void testXandEQOperators() { final byte[] bases1 = new byte[] {'A','A','A','A','A','A','A','A','A','A'}; @@ -451,7 +477,7 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) : new DownsamplingMethod(DownsampleType.NONE, null, null, false); - final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(nReadsPerLocus, nLoci); + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(header.getSequenceDictionary(), nReadsPerLocus, nLoci); bamBuilder.createAndSetHeader(nSamples).setReadLength(readLength).setAlignmentStart(1); final List reads = bamBuilder.makeReads(); diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java index cf3c97b34..2a638eb69 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java @@ -47,8 +47,8 @@ import java.util.List; * To change this template use File | Settings | File Templates. */ public class ArtificialBAMBuilderUnitTest extends BaseTest { - @DataProvider(name = "CombinatorialARTTilingProvider") - public Object[][] makeCombinatorialARTTilingProvider() { + @DataProvider(name = "ArtificialBAMBuilderUnitTestProvider") + public Object[][] makeArtificialBAMBuilderUnitTestProvider() { final List tests = new LinkedList(); final List starts = Arrays.asList( @@ -79,7 +79,7 @@ public class ArtificialBAMBuilderUnitTest extends BaseTest { return tests.toArray(new Object[][]{}); } - @Test(dataProvider = "CombinatorialARTTilingProvider") + @Test(dataProvider = "ArtificialBAMBuilderUnitTestProvider") public void testBamProvider(final ArtificialBAMBuilder bamBuilder, int readLength, int skips, int start, int nSamples, int nReadsPerLocus, int nLoci) { Assert.assertEquals(bamBuilder.getReadLength(), readLength); Assert.assertEquals(bamBuilder.getSkipNLoci(), skips); From 4cf34ee9da6dfa9539b485daeed9f276fb192975 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 15:35:04 -0500 Subject: [PATCH 026/188] Bug fix to FisherStrand: do not let it output INFINITY. This all needs to be unit tested, but that's coming on the horizon. --- .../sting/gatk/walkers/annotator/FisherStrand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java index 167e5df63..fd81103cd 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java @@ -116,8 +116,8 @@ public class FisherStrand extends InfoFieldAnnotation implements StandardAnnotat else if (table1 == null) return annotationForOneTable(pValueForContingencyTable(table2)); else { // take the one with the best (i.e., least significant pvalue) - double pvalue1 = Math.max(pValueForContingencyTable(table1), MIN_PVALUE); - double pvalue2 = Math.max(pValueForContingencyTable(table2), MIN_PVALUE); + double pvalue1 = pValueForContingencyTable(table1); + double pvalue2 = pValueForContingencyTable(table2); return annotationForOneTable(Math.max(pvalue1, pvalue2)); } } @@ -129,7 +129,7 @@ public class FisherStrand extends InfoFieldAnnotation implements StandardAnnotat * @return a hash map from FS -> phred-scaled pValue */ private Map annotationForOneTable(final double pValue) { - final Object value = String.format("%.3f", QualityUtils.phredScaleErrorRate(pValue)); + final Object value = String.format("%.3f", QualityUtils.phredScaleErrorRate(Math.max(pValue, MIN_PVALUE))); // prevent INFINITYs return Collections.singletonMap(FS, value); // Map map = new HashMap(); // map.put(FS, String.format("%.3f", QualityUtils.phredScaleErrorRate(pValue))); From 79bc8180228480f037a122b609b24ff666a7040f Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 16:15:58 -0500 Subject: [PATCH 027/188] Bug fix for VariantsToVCF: old dbSNP files can have '-' as reference base and those records always need to be padded. --- .../sting/gatk/refdata/VariantContextAdaptors.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java index c7edebd81..a77341a5d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java @@ -194,17 +194,18 @@ public class VariantContextAdaptors { return null; // we weren't given enough reference context to create the VariantContext final byte refBaseForIndel = ref.getBases()[index]; + final boolean refBaseIsDash = dbsnp.getNCBIRefBase().equals("-"); boolean addPaddingBase; if ( isSNP(dbsnp) || isMNP(dbsnp) ) addPaddingBase = false; else if ( isIndel(dbsnp) || dbsnp.getVariantType().contains("mixed") ) - addPaddingBase = VariantContextUtils.requiresPaddingBase(stripNullDashes(getAlleleList(dbsnp))); + addPaddingBase = refBaseIsDash || VariantContextUtils.requiresPaddingBase(stripNullDashes(getAlleleList(dbsnp))); else return null; // can't handle anything else Allele refAllele; - if ( dbsnp.getNCBIRefBase().equals("-") ) + if ( refBaseIsDash ) refAllele = Allele.create(refBaseForIndel, true); else if ( ! Allele.acceptableAlleleBases(dbsnp.getNCBIRefBase()) ) return null; From 3c476a92a27db20f80ea94598cdac18e3d31c09c Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 16 Jan 2013 15:56:03 -0500 Subject: [PATCH 028/188] Add dummy functionality (currently throws an error) to allow HC to include unmapped reads during assembly and calling --- .../haplotypecaller/HaplotypeCaller.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 4da2e1179..ce6aa32f4 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -184,6 +184,16 @@ public class HaplotypeCaller extends ActiveRegionWalker implem @Argument(fullName="downsampleRegion", shortName="dr", doc="coverage, per-sample, to downsample each active region to", required = false) protected int DOWNSAMPLE_PER_SAMPLE_PER_REGION = 1000; + /** + * If this flag is provided, the haplotype caller will include unmapped reads in the assembly and calling + * when these reads occur in the region being analyzed. Typically, for paired end analyses, one pair of the + * read can map, but if its pair is too divergent then it may be unmapped and placed next to its mate, taking + * the mates contig and alignment start. If this flag is provided the haplotype caller will see such reads, + * and may make use of them in assembly and calling, where possible. + */ + @Argument(fullName="includeUmappedReads", shortName="unmapped", doc="If provided, unmapped reads with chromosomal coordinates (i.e., those placed to their maps) will be included in the assembly and calling", required = false) + protected boolean includeUnmappedReads = false; + @Argument(fullName="useAllelesTrigger", shortName="allelesTrigger", doc = "If specified, use additional trigger on variants found in an external alleles file", required=false) protected boolean USE_ALLELES_TRIGGER = false; @@ -354,11 +364,20 @@ public class HaplotypeCaller extends ActiveRegionWalker implem // enable non primary and extended reads in the active region @Override public EnumSet desiredReadStates() { - return EnumSet.of( - ActiveRegionReadState.PRIMARY, - ActiveRegionReadState.NONPRIMARY, - ActiveRegionReadState.EXTENDED - ); + if ( includeUnmappedReads ) { + throw new UserException.BadArgumentValue("includeUmappedReads", "is not yet functional"); +// return EnumSet.of( +// ActiveRegionReadState.PRIMARY, +// ActiveRegionReadState.NONPRIMARY, +// ActiveRegionReadState.EXTENDED, +// ActiveRegionReadState.UNMAPPED +// ); + } else + return EnumSet.of( + ActiveRegionReadState.PRIMARY, + ActiveRegionReadState.NONPRIMARY, + ActiveRegionReadState.EXTENDED + ); } @Override From 738c24a3b1efea489a5638eb146107d8533b8878 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 16 Jan 2013 16:25:11 -0500 Subject: [PATCH 029/188] Add tests to ensure that all insertion reads appear in the active region traversal --- .../sting/utils/sam/ArtificialBAMBuilder.java | 18 +++++- .../TraverseActiveRegionsUnitTest.java | 59 ++++++++++++++++++- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java index f5018db8c..ab539c9dc 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java @@ -32,8 +32,7 @@ import org.broadinstitute.sting.utils.NGSPlatform; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * Easy to use creator of artificial BAM files for testing @@ -64,6 +63,8 @@ public class ArtificialBAMBuilder { int readLength = 10; private final ArrayList samples = new ArrayList(); + private LinkedList additionalReads = new LinkedList(); + final SAMFileWriterFactory factory = new SAMFileWriterFactory(); { factory.setCreateIndex(true); @@ -118,6 +119,14 @@ public class ArtificialBAMBuilder { return this; } + public void addReads(final GATKSAMRecord readToAdd) { + additionalReads.add(readToAdd); + } + + public void addReads(final Collection readsToAdd) { + additionalReads.addAll(readsToAdd); + } + public List getSamples() { return samples; } @@ -145,6 +154,11 @@ public class ArtificialBAMBuilder { } } + if ( ! additionalReads.isEmpty() ) { + reads.addAll(additionalReads); + Collections.sort(reads, new SAMRecordCoordinateComparator()); + } + return reads; } diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java index 15d4eec2d..319af5ec5 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java @@ -501,6 +501,12 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { return providers; } + // --------------------------------------------------------------------------------------------------------- + // + // Combinatorial tests to ensure reads are going into the right regions + // + // --------------------------------------------------------------------------------------------------------- + @DataProvider(name = "CombinatorialARTTilingProvider") public Object[][] makeCombinatorialARTTilingProvider() { final List tests = new LinkedList(); @@ -582,7 +588,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { } - @Test(enabled = true, dataProvider = "CombinatorialARTTilingProvider") + @Test(enabled = true && ! DEBUG, dataProvider = "CombinatorialARTTilingProvider") public void testARTReadsInActiveRegions(final int id, final GenomeLocSortedSet activeRegions, final EnumSet readStates, final ArtificialBAMBuilder bamBuilder) { logger.warn("Running testARTReadsInActiveRegions id=" + id + " locs " + activeRegions + " against bam " + bamBuilder); final List intervals = Arrays.asList( @@ -597,10 +603,10 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { final Set alreadySeenReads = new HashSet(); // for use with the primary / non-primary for ( final ActiveRegion region : activeRegionsMap.values() ) { + final Set readNamesInRegion = readNamesInRegion(region); int nReadsExpectedInRegion = 0; for ( final GATKSAMRecord read : bamBuilder.makeReads() ) { final GenomeLoc readLoc = genomeLocParser.createGenomeLoc(read); - final Set readNamesInRegion = readNamesInRegion(region); boolean shouldBeInRegion = readStates.contains(ActiveRegionReadState.EXTENDED) ? region.getExtendedLoc().overlapsP(readLoc) @@ -629,4 +635,53 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { readNames.add(read.getReadName()); return readNames; } + + // --------------------------------------------------------------------------------------------------------- + // + // Make sure all insertion reads are properly included in the active regions + // + // --------------------------------------------------------------------------------------------------------- + + @Test + public void ensureAllInsertionReadsAreInActiveRegions() { + + final int readLength = 10; + final int start = 20; + final int nReadsPerLocus = 10; + final int nLoci = 3; + + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci); + bamBuilder.setReadLength(readLength); + bamBuilder.setAlignmentStart(start); + + // note that the position must be +1 as the read's all I cigar puts the end 1 bp before start, leaving it out of the region + GATKSAMRecord allI = ArtificialSAMUtils.createArtificialRead(bamBuilder.getHeader(),"allI",0,start+1,readLength); + allI.setCigarString(readLength + "I"); + allI.setReadGroup(new GATKSAMReadGroupRecord(bamBuilder.getHeader().getReadGroups().get(0))); + + bamBuilder.addReads(allI); + + final GenomeLocSortedSet activeRegions = new GenomeLocSortedSet(bamBuilder.getGenomeLocParser()); + activeRegions.add(bamBuilder.getGenomeLocParser().createGenomeLoc("1", 10, 30)); + final List intervals = Arrays.asList( + genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd()) + ); + + final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions); + + final TraverseActiveRegions traversal = new TraverseActiveRegions(); + final Map activeRegionsMap = getActiveRegions(traversal, walker, intervals, bamBuilder.makeTemporarilyBAMFile().toString()); + + final ActiveRegion region = activeRegionsMap.values().iterator().next(); + int nReadsExpectedInRegion = 0; + + final Set readNamesInRegion = readNamesInRegion(region); + for ( final GATKSAMRecord read : bamBuilder.makeReads() ) { + Assert.assertTrue(readNamesInRegion.contains(read.getReadName()), + "Region " + region + " should contain read " + read + " with cigar " + read.getCigarString() + " but it wasn't"); + nReadsExpectedInRegion++; + } + + Assert.assertEquals(region.size(), nReadsExpectedInRegion, "There are more reads in active region " + region + "than expected"); + } } From e15d4ad2783a1fd55221ba5297307c8edaddc46f Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Wed, 16 Jan 2013 18:00:23 -0500 Subject: [PATCH 030/188] Addition of moltenize argument for moltenized tabular output. NRD/NRS not moltenized because there are only two columns. --- .../variantutils/GenotypeConcordance.java | 360 +++++++++++++----- 1 file changed, 270 insertions(+), 90 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 0cd1882df..2acff956c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -75,22 +75,43 @@ public class GenotypeConcordance extends RodWalker genotypeFilterExpressionsEval = new ArrayList(); + + @Argument(shortName="gfc", fullName="genotypeFilterExpressionComp", doc="One or more criteria to use to set COMP genotypes to no-call. "+ + "These genotype-level filters are only applied to the COMP rod.", required=false) + public ArrayList genotypeFilterExpressionsComp = new ArrayList(); + + @Argument(shortName="moltenize",fullName="moltenize",doc="Molten rather than tabular output") + public boolean moltenize = false; + @Output PrintStream out; - List evalSamples; - List compSamples; + private List evalSamples; + private List compSamples; + private List evalJexls = null; + private List compJexls = null; - // todo -- deal with occurrences like: - // Eval: 20 4000 A C - // Eval: 20 4000 A AC - // Comp: 20 4000 A C - // currently this results in a warning and skipping - // todo -- extend to multiple eval, multiple comp // todo -- table with "proportion of overlapping sites" (not just eval/comp margins) - // todo -- genotype-level filtering + // todo -- moltenize + public void initialize() { + evalJexls = initializeJexl(genotypeFilterExpressionsEval); + compJexls = initializeJexl(genotypeFilterExpressionsComp); + } + + private List initializeJexl(ArrayList genotypeFilterExpressions) { + ArrayList dummyNames = new ArrayList(genotypeFilterExpressions.size()); + int expCount = 1; + for ( String exp : genotypeFilterExpressions ) { + dummyNames.add(String.format("gfe%d",expCount++)); + } + return VariantContextUtils.initializeMatchExps(dummyNames, genotypeFilterExpressions); + } + public ConcordanceMetrics reduceInit() { Map headerMap = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(evalBinding,compBinding)); VCFHeader evalHeader = headerMap.get(evalBinding.getName()); @@ -110,15 +131,19 @@ public class GenotypeConcordance extends RodWalker eval = tracker.getValues(evalBinding,ref.getLocus()); List comp = tracker.getValues(compBinding,ref.getLocus()); if ( eval.size() > 1 || comp.size() > 1 ) { - logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving."); - evalCompPair = resolveMultipleRecords(eval,comp); + if ( noDuplicateTypes(eval) && noDuplicateTypes(comp) ) { + logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving."); + evalCompPair = resolveMultipleRecords(eval,comp); + } else { + logger.warn("Eval or Comp Rod at position "+ref.getLocus().toString()+" has multiple records of the same type. This locus will be skipped."); + } } else { // if a rod is missing, explicitly create a variant context with 'missing' genotypes. Slow, but correct. // note that if there is no eval rod there must be a comp rod, and also the reverse VariantContext evalContext = eval.size() == 1 ? eval.get(0) : createEmptyContext(comp.get(0),evalSamples); VariantContext compContext = comp.size() == 1 ? comp.get(0) : createEmptyContext(eval.get(0),compSamples); - evalContext = filterGenotypes(evalContext,ignoreFilters); - compContext = filterGenotypes(compContext,ignoreFilters); + evalContext = filterGenotypes(evalContext,ignoreFilters,evalJexls); + compContext = filterGenotypes(compContext,ignoreFilters,compJexls); evalCompPair.add(new Pair(evalContext,compContext)); } } @@ -126,9 +151,21 @@ public class GenotypeConcordance extends RodWalker vcList) { + HashSet types = new HashSet(vcList.size()); + for ( VariantContext vc : vcList ) { + VariantContext.Type type = vc.getType(); + if ( types.contains(type) ) + return false; + types.add(type); + } + + return true; + } + /** - * The point of this method is to match up pairs of evals and comps by their alternate alleles. Basically multiple records could - * exist for a site such as: + * The point of this method is to match up pairs of evals and comps by their type (or alternate alleles for mixed). + * Basically multiple records could exist for a site such as: * Eval: 20 4000 A C * Eval: 20 4000 A AC * Comp: 20 4000 A C @@ -146,14 +183,19 @@ public class GenotypeConcordance extends RodWalker> resolvedPairs = new ArrayList>(evalList.size()+compList.size()); // oversized but w/e List pairedEval = new ArrayList(evalList.size()); for ( VariantContext eval : evalList ) { - Set evalAlts = new HashSet(eval.getAlternateAlleles()); + VariantContext.Type evalType = eval.getType(); + Set evalAlleles = new HashSet(eval.getAlternateAlleles()); VariantContext pairedComp = null; for ( VariantContext comp : compList ) { - for ( Allele compAlt : comp.getAlternateAlleles() ) { - if ( evalAlts.contains(compAlt) ) { - // matching alt allele, pair these records - pairedComp = comp; - break; + if ( evalType.equals(comp.getType()) ) { + pairedComp = comp; + break; + } else if ( eval.isMixed() || comp.isMixed() ) { + for ( Allele compAllele : comp.getAlternateAlleles() ) { + if ( evalAlleles.contains(compAllele) ) { + pairedComp = comp; + break; + } } } } @@ -197,83 +239,202 @@ public class GenotypeConcordance extends RodWalker entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { - ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); - concordanceEvalProportions.set(entry.getKey(),"Sample",entry.getKey()); - concordanceCompProportions.set(entry.getKey(),"Sample",entry.getKey()); - concordanceCounts.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCompProportions.addColumn("Eval_Genotype","%s"); + concordanceCounts.addColumn("Eval_Genotype","%s"); + concordanceEvalProportions.addColumn("Eval_Genotype","%s"); + concordanceSummary.addColumn("Non-Reference_Discrepancy","%.3f"); + + concordanceCompProportions.addColumn("Comp_Genotype","%s"); + concordanceCounts.addColumn("Comp_Genotype","%s"); + concordanceEvalProportions.addColumn("Comp_Genotype","%s"); + concordanceSummary.addColumn("Non-Reference_Sensitivity","%.3f"); + + concordanceCompProportions.addColumn("Proportion","%.3f"); + concordanceCounts.addColumn("Count","%d"); + concordanceEvalProportions.addColumn("Proportion","%.3f"); + + for ( Map.Entry entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { + ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String rowKey = String.format("%s_%s_%s",entry.getKey(),evalType.toString(),compType.toString()); + concordanceCounts.set(rowKey,"Sample",entry.getKey()); + concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCounts.set(rowKey,"Comp_Genotype",evalType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(rowKey,"Count",count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) { + concordanceEvalProportions.set(rowKey,"Sample",entry.getKey()); + concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + } + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) { + concordanceCompProportions.set(rowKey,"Sample",entry.getKey()); + concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + } + String mismatchKey = String.format("%s_%s",entry.getKey(),"Mismatching"); + concordanceCounts.set(mismatchKey,"Sample",entry.getKey()); + concordanceCounts.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCounts.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Sample",entry.getKey()); + concordanceEvalProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(mismatchKey,"Sample",entry.getKey()); + concordanceCompProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(mismatchKey,"Count",table.getnMismatchingAlt()); + } + + String sampleKey = "ALL"; + ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String rowKey = String.format("%s_%s_%s",sampleKey,evalType.toString(),compType.toString()); + concordanceCounts.set(rowKey,"Sample",sampleKey); + concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCounts.set(rowKey,"Comp_Genotype",evalType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(rowKey,"Count",count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) { + concordanceEvalProportions.set(rowKey,"Sample",sampleKey); + concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + } + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) { + concordanceCompProportions.set(rowKey,"Sample",sampleKey); + concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + } + String rowKey = String.format("%s_%s",sampleKey,"Mismatching"); + concordanceCounts.set(rowKey,"Sample",sampleKey); + concordanceCounts.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCounts.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Sample",sampleKey); + concordanceEvalProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(rowKey,"Sample",sampleKey); + concordanceCompProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(rowKey,"Count",table.getnMismatchingAlt()); + + for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { + concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); + concordanceSummary.set(nrsEntry.getKey(),"Non-Reference_Sensitivity",nrsEntry.getValue()); + } + for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { + concordanceSummary.set(nrdEntry.getKey(),"Non-Reference_Discrepancy",nrdEntry.getValue()); + } + concordanceSummary.set("ALL_NRS_NRD","Sample","ALL"); + concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Sensitivity",metrics.getOverallNRS()); + concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Discrepancy",metrics.getOverallNRD()); + + + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.addColumn(type.toString(),"%d"); + } + + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + } + + } else { + concordanceCompProportions.addColumn("Sample","%s"); + concordanceCounts.addColumn("Sample","%s"); + concordanceEvalProportions.addColumn("Sample","%s"); + concordanceSummary.addColumn("Sample","%s"); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String colKey = String.format("%s_%s", evalType.toString(), compType.toString()); + concordanceCounts.addColumn(colKey,"%d"); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) + concordanceEvalProportions.addColumn(colKey,"%.3f"); + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) + concordanceCompProportions.addColumn(colKey,"%.3f"); + } + } + concordanceEvalProportions.addColumn("Mismatching_Alleles","%.3f"); + concordanceCompProportions.addColumn("Mismatching_Alleles","%.3f"); + concordanceCounts.addColumn("Mismatching_Alleles","%d"); + concordanceSummary.addColumn("Non-Reference Sensitivity","%.3f"); + concordanceSummary.addColumn("Non-Reference Discrepancy","%.3f"); + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.addColumn(type.toString(),"%d"); + } + + for ( Map.Entry entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { + ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); + concordanceEvalProportions.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCompProportions.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCounts.set(entry.getKey(),"Sample",entry.getKey()); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(entry.getKey(),colKey,count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) + concordanceEvalProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) + concordanceCompProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + concordanceEvalProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(entry.getKey(),"Mismatching_Alleles",table.getnMismatchingAlt()); + } + + String rowKey = "ALL"; + concordanceCompProportions.set(rowKey,"Sample",rowKey); + concordanceEvalProportions.set(rowKey,"Sample",rowKey); + concordanceCounts.set(rowKey,"Sample",rowKey); + ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); for ( GenotypeType evalType : GenotypeType.values() ) { for ( GenotypeType compType : GenotypeType.values() ) { String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); - int count = table.get(evalType, compType); - concordanceCounts.set(entry.getKey(),colKey,count); + int count = table.get(evalType,compType); + concordanceCounts.set(rowKey,colKey,count); if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) - concordanceEvalProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + concordanceEvalProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) - concordanceCompProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + concordanceCompProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); } } - concordanceEvalProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); - concordanceCompProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); - concordanceCounts.set(entry.getKey(),"Mismatching_Alleles",table.getnMismatchingAlt()); - } + concordanceEvalProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(rowKey,"Mismatching_Alleles",table.getnMismatchingAlt()); - String rowKey = "ALL"; - concordanceCompProportions.set(rowKey,"Sample",rowKey); - concordanceEvalProportions.set(rowKey,"Sample",rowKey); - concordanceCounts.set(rowKey,"Sample",rowKey); - ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); - for ( GenotypeType evalType : GenotypeType.values() ) { - for ( GenotypeType compType : GenotypeType.values() ) { - String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); - int count = table.get(evalType,compType); - concordanceCounts.set(rowKey,colKey,count); - if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) - concordanceEvalProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); - if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) - concordanceCompProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { + concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); + concordanceSummary.set(nrsEntry.getKey(),"Non-Reference Sensitivity",nrsEntry.getValue()); } - } - concordanceEvalProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); - concordanceCompProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); - concordanceCounts.set(rowKey,"Mismatching_Alleles",table.getnMismatchingAlt()); + for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { + concordanceSummary.set(nrdEntry.getKey(),"Non-Reference Discrepancy",nrdEntry.getValue()); + } + concordanceSummary.set("ALL","Sample","ALL"); + concordanceSummary.set("ALL","Non-Reference Sensitivity",metrics.getOverallNRS()); + concordanceSummary.set("ALL","Non-Reference Discrepancy",metrics.getOverallNRD()); - for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { - concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); - concordanceSummary.set(nrsEntry.getKey(),"Non-Reference Sensitivity",nrsEntry.getValue()); - } - for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { - concordanceSummary.set(nrdEntry.getKey(),"Non-Reference Discrepancy",nrdEntry.getValue()); - } - concordanceSummary.set("ALL","Sample","ALL"); - concordanceSummary.set("ALL","Non-Reference Sensitivity",metrics.getOverallNRS()); - concordanceSummary.set("ALL","Non-Reference Discrepancy",metrics.getOverallNRD()); - - for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { - siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + } } report.addTable(concordanceCompProportions); @@ -298,13 +459,32 @@ public class GenotypeConcordance extends RodWalker exps) { // placeholder method for genotype-level filtering. However if the site itself is filtered, // and such filters are not ignored, the genotype-level data should be altered to reflect this + if ( ! context.isFiltered() || ignoreSiteFilter ) { - // todo -- add genotype-level jexl filtering here - return context; + List filteredGenotypes = new ArrayList(context.getNSamples()); + for ( Genotype g : context.getGenotypes() ) { + Map matchMap = VariantContextUtils.match(context, g, exps); + boolean filtered = false; + for ( Boolean b : matchMap.values() ) { + if ( b ) { + filtered = true; + break; + } + } + if ( filtered ) { + filteredGenotypes.add(GenotypeBuilder.create(g.getSampleName(),Arrays.asList(Allele.NO_CALL,Allele.NO_CALL),g.getExtendedAttributes())); + } else { + filteredGenotypes.add(g); + } + } + VariantContextBuilder builder = new VariantContextBuilder(context); + builder.genotypes(filteredGenotypes); + return builder.make(); } + VariantContextBuilder builder = new VariantContextBuilder(); builder.alleles(Arrays.asList(context.getReference())); builder.loc(context.getChr(),context.getStart(),context.getEnd()); From dbb69a1e1088db4c7fcfd9e512b1b9e095a62ba3 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 22:33:16 -0500 Subject: [PATCH 031/188] Need to use ints for quals in HaplotypeScore instead of bytes because of overflow (they are summed when haplotypes are combined) --- .../walkers/annotator/HaplotypeScore.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java index af6304297..3acba48ae 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java @@ -216,14 +216,14 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot final Haplotype haplotype1 = consensusHaplotypeQueue.poll(); List hlist = new ArrayList(); - hlist.add(new Haplotype(haplotype1.getBases(), (byte)60)); + hlist.add(new Haplotype(haplotype1.getBases(), 60)); for (int k = 1; k < haplotypesToCompute; k++) { Haplotype haplotype2 = consensusHaplotypeQueue.poll(); if (haplotype2 == null) { haplotype2 = haplotype1; } // Sometimes only the reference haplotype can be found - hlist.add(new Haplotype(haplotype2.getBases(), (byte)20)); + hlist.add(new Haplotype(haplotype2.getBases(), 20)); } return hlist; } else @@ -285,10 +285,10 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot final int length = a.length; final byte[] consensusChars = new byte[length]; - final byte[] consensusQuals = new byte[length]; + final int[] consensusQuals = new int[length]; - final byte[] qualsA = haplotypeA.getQuals(); - final byte[] qualsB = haplotypeB.getQuals(); + final int[] qualsA = haplotypeA.getQuals(); + final int[] qualsB = haplotypeB.getQuals(); for (int i = 0; i < length; i++) { chA = a[i]; @@ -308,7 +308,7 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot consensusQuals[i] = qualsA[i]; } else { consensusChars[i] = chA; - consensusQuals[i] = (byte)((int)qualsA[i] + (int)qualsB[i]); + consensusQuals[i] = qualsA[i] + qualsB[i]; } } @@ -442,31 +442,38 @@ public class HaplotypeScore extends InfoFieldAnnotation implements StandardAnnot private static class Haplotype { private final byte[] bases; - private final byte[] quals; + private final int[] quals; private int qualitySum = -1; - public Haplotype( final byte[] bases, final byte[] quals ) { + public Haplotype( final byte[] bases, final int[] quals ) { this.bases = bases; this.quals = quals; } - public Haplotype( final byte[] bases, final byte qual ) { + public Haplotype( final byte[] bases, final int qual ) { this.bases = bases; - quals = new byte[bases.length]; + quals = new int[bases.length]; Arrays.fill(quals, qual); } + public Haplotype( final byte[] bases, final byte[] quals ) { + this.bases = bases; + this.quals = new int[quals.length]; + for ( int i = 0 ; i < quals.length; i++ ) + this.quals[i] = (int)quals[i]; + } + public double getQualitySum() { if ( qualitySum == -1 ) { qualitySum = 0; - for ( final byte qual : quals ) { - qualitySum += (int)qual; + for ( final int qual : quals ) { + qualitySum += qual; } } return qualitySum; } - public byte[] getQuals() { + public int[] getQuals() { return quals.clone(); } From a623cca89a7310fe52118529dfd9c9f28698d8e5 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 16 Jan 2013 22:47:58 -0500 Subject: [PATCH 033/188] Bug fix for HaplotypeCaller, as reported on the forum: when reduced reads didn't completely overlap a deletion call, we were incorrectly trying to find the reference position of a base on the read that didn't exist. Added integration test to cover this case. --- .../sting/gatk/walkers/annotator/DepthOfCoverage.java | 2 +- .../gatk/walkers/annotator/DepthPerAlleleBySample.java | 2 +- .../sting/gatk/walkers/annotator/FisherStrand.java | 2 +- .../haplotypecaller/HaplotypeCallerIntegrationTest.java | 8 ++++++++ .../src/org/broadinstitute/sting/utils/sam/ReadUtils.java | 5 +++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthOfCoverage.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthOfCoverage.java index aeec36c18..4adb2ca71 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthOfCoverage.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthOfCoverage.java @@ -99,7 +99,7 @@ public class DepthOfCoverage extends InfoFieldAnnotation implements StandardAnno for (PerReadAlleleLikelihoodMap maps : perReadAlleleLikelihoodMap.values() ) { for (Map.Entry> el : maps.getLikelihoodReadMap().entrySet()) { final GATKSAMRecord read = el.getKey(); - depth += (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinate(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1); + depth += (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1); } } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthPerAlleleBySample.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthPerAlleleBySample.java index a194fe323..5acea12f6 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthPerAlleleBySample.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/DepthPerAlleleBySample.java @@ -144,7 +144,7 @@ public class DepthPerAlleleBySample extends GenotypeAnnotation implements Standa continue; // read is non-informative if (!vc.getAlleles().contains(a)) continue; // sanity check - shouldn't be needed - alleleCounts.put(a, alleleCounts.get(a) + (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinate(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1)); + alleleCounts.put(a, alleleCounts.get(a) + (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1)); } final int[] counts = new int[alleleCounts.size()]; counts[0] = alleleCounts.get(vc.getReference()); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java index fd81103cd..fbd27dfe3 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java @@ -277,7 +277,7 @@ public class FisherStrand extends InfoFieldAnnotation implements StandardAnnotat int column = isFW ? 0 : 1; final GATKSAMRecord read = el.getKey(); - table[row][column] += (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinate(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1); + table[row][column] += (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1); } } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index e86834a4a..03d4216dd 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -178,4 +178,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { Arrays.asList("8a400b0c46f41447fcc35a907e34f384")); executeTest("HC calling on a ReducedRead BAM", spec); } + + @Test + public void testReducedBamWithReadsNotFullySpanningDeletion() { + WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( + "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, + Arrays.asList("0446c11fe2ba68a14f938ebc6e71ded7")); + executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index b43b590df..1488f7269 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -394,6 +394,11 @@ public class ReadUtils { return getReadCoordinateForReferenceCoordinate(read.getSoftStart(), read.getCigar(), refCoord, tail, false); } + public static int getReadCoordinateForReferenceCoordinateUpToEndOfRead(GATKSAMRecord read, int refCoord, ClippingTail tail) { + final int leftmostSafeVariantPosition = Math.max(read.getSoftStart(), refCoord); + return getReadCoordinateForReferenceCoordinate(read.getSoftStart(), read.getCigar(), leftmostSafeVariantPosition, tail, false); + } + public static int getReadCoordinateForReferenceCoordinate(final int alignmentStart, final Cigar cigar, final int refCoord, final ClippingTail tail, final boolean allowGoalNotReached) { Pair result = getReadCoordinateForReferenceCoordinate(alignmentStart, cigar, refCoord, allowGoalNotReached); int readCoord = result.getFirst(); From 953592421b267254b0dc4811522c982bbdd5360d Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Thu, 17 Jan 2013 09:19:21 -0500 Subject: [PATCH 034/188] I think we got out of sync with the HC tests as we were clobbering each other's changes. Only differences here are to some RankSumTest values. --- .../HaplotypeCallerIntegrationTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 03d4216dd..3ceb0df94 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "b8f7b741445ce6b6ea491c794ce75c17"); + HCTest(CEUTRIO_BAM, "", "0e59153c6359d7cb7be44e25ab552790"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); + HCTest(NA12878_BAM, "", "d4b377aed2c8be2ebd81ee5e43b73a93"); } @Test(enabled = false) @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "6c0c441b71848c2eea38ab5e2afe1120"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "14ed8e5be2d2a0bf478d742b4baa5a46"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -124,7 +124,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleSymbolic() { - HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "0761ff5cbf279be467833fa6708bf360"); + HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "76fe5e57ed96541bdfee74782331b061"); } private void HCTestIndelQualityScores(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "29f1125df5ab27cc937a144ae08ac735"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "25981f7706f61d930556fb128cd1e5c5"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,7 +146,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("8b1b8d1bd7feac1503fc4ffa6236cff7")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("4701887e1927814259560d85098b6440")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("8a400b0c46f41447fcc35a907e34f384")); + Arrays.asList("18d047bf8116b56e0c6212e0875eceea")); executeTest("HC calling on a ReducedRead BAM", spec); } From 6db3e473af175328166cf5aea9e0bd94ff9a9e31 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Thu, 17 Jan 2013 10:30:04 -0500 Subject: [PATCH 035/188] Better error message for bad qual --- .../gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java index fc7573f21..8c8de2bad 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java @@ -425,7 +425,7 @@ public class DiploidSNPGenotypeLikelihoods implements Cloneable { byte qual = p.getQual(); if ( qual > SAMUtils.MAX_PHRED_SCORE ) - throw new UserException.MalformedBAM(p.getRead(), String.format("the maximum allowed quality score is %d, but a quality of %d was observed in read %s. Perhaps your BAM incorrectly encodes the quality scores in Sanger format; see http://en.wikipedia.org/wiki/FASTQ_format for more details", SAMUtils.MAX_PHRED_SCORE, qual, p.getRead().getReadName())); + throw new UserException.MisencodedBAM(p.getRead(), "we encountered an extremely high quality score (" + (int)qual + ")"); if ( capBaseQualsAtMappingQual ) qual = (byte)Math.min((int)qual, p.getMappingQual()); if ( (int)qual < minBaseQual ) From 6a903f2c235fd48dd02aa9f1982da9e980046c2e Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 18 Jan 2013 01:21:08 -0500 Subject: [PATCH 036/188] I finally gave up on trying to get the Haplotype/Allele merging to work in the HaplotypeCaller. I've resigned myself instead to create a mapping from Allele to Haplotype. It's cheap so not a big deal, but really shouldn't be necessary. Ryan and I are talking about refactoring for GATK2.5. --- .../haplotypecaller/HaplotypeCaller.java | 7 ++++++- .../LikelihoodCalculationEngine.java | 9 +++++++-- .../HaplotypeCallerIntegrationTest.java | 18 +++++++++--------- .../broadinstitute/sting/utils/Haplotype.java | 9 +++++++-- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index ce6aa32f4..26f2560b7 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -508,12 +508,17 @@ public class HaplotypeCaller extends ActiveRegionWalker implem for ( Haplotype haplotype : haplotypes ) writeHaplotype(haplotype, paddedRefLoc, bestHaplotypes.contains(haplotype)); + // we need to remap the Alleles back to the Haplotypes; inefficient but unfortunately this is a requirement currently + final Map alleleToHaplotypeMap = new HashMap(haplotypes.size()); + for ( final Haplotype haplotype : haplotypes ) + alleleToHaplotypeMap.put(Allele.create(haplotype.getBases()), haplotype); + // next, output the interesting reads for each sample aligned against the appropriate haplotype for ( final PerReadAlleleLikelihoodMap readAlleleLikelihoodMap : stratifiedReadMap.values() ) { for ( Map.Entry> entry : readAlleleLikelihoodMap.getLikelihoodReadMap().entrySet() ) { final Allele bestAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(entry.getValue()); if ( bestAllele != Allele.NO_CALL ) - writeReadAgainstHaplotype(entry.getKey(), (Haplotype) bestAllele, paddedRefLoc.getStart()); + writeReadAgainstHaplotype(entry.getKey(), alleleToHaplotypeMap.get(bestAllele), paddedRefLoc.getStart()); } } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java index aafdbf126..57e071189 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java @@ -124,9 +124,14 @@ public class LikelihoodCalculationEngine { } private PerReadAlleleLikelihoodMap computeReadLikelihoods( final ArrayList haplotypes, final ArrayList reads) { + // first, a little set up to get copies of the Haplotypes that are Alleles (more efficient than creating them each time) + final int numHaplotypes = haplotypes.size(); + final Map alleleVersions = new HashMap(numHaplotypes); + for ( final Haplotype haplotype : haplotypes ) { + alleleVersions.put(haplotype, Allele.create(haplotype.getBases())); + } final PerReadAlleleLikelihoodMap perReadAlleleLikelihoodMap = new PerReadAlleleLikelihoodMap(); - final int numHaplotypes = haplotypes.size(); for( final GATKSAMRecord read : reads ) { final byte[] overallGCP = new byte[read.getReadLength()]; Arrays.fill( overallGCP, constantGCP ); // Is there a way to derive empirical estimates for this from the data? @@ -148,7 +153,7 @@ public class LikelihoodCalculationEngine { final int haplotypeStart = ( previousHaplotypeSeen == null ? 0 : computeFirstDifferingPosition(haplotype.getBases(), previousHaplotypeSeen.getBases()) ); previousHaplotypeSeen = haplotype; - perReadAlleleLikelihoodMap.add(read, haplotype, + perReadAlleleLikelihoodMap.add(read, alleleVersions.get(haplotype), pairHMM.computeReadLikelihoodGivenHaplotypeLog10(haplotype.getBases(), read.getReadBases(), readQuals, readInsQuals, readDelQuals, overallGCP, haplotypeStart, jjj == 0)); } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 3ceb0df94..6c7afd8bb 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "0e59153c6359d7cb7be44e25ab552790"); + HCTest(CEUTRIO_BAM, "", "b8f7b741445ce6b6ea491c794ce75c17"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "d4b377aed2c8be2ebd81ee5e43b73a93"); + HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); } @Test(enabled = false) @@ -102,7 +102,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "1a034b7eb572e1b6f659d6e5d57b3e76"); + "d590c8d6d5e58d685401b65a23846893"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "14ed8e5be2d2a0bf478d742b4baa5a46"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "6c0c441b71848c2eea38ab5e2afe1120"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -124,7 +124,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleSymbolic() { - HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "76fe5e57ed96541bdfee74782331b061"); + HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "0761ff5cbf279be467833fa6708bf360"); } private void HCTestIndelQualityScores(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "25981f7706f61d930556fb128cd1e5c5"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "29f1125df5ab27cc937a144ae08ac735"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,7 +146,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("4701887e1927814259560d85098b6440")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("8b1b8d1bd7feac1503fc4ffa6236cff7")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("18d047bf8116b56e0c6212e0875eceea")); + Arrays.asList("8a400b0c46f41447fcc35a907e34f384")); executeTest("HC calling on a ReducedRead BAM", spec); } @@ -183,7 +183,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void testReducedBamWithReadsNotFullySpanningDeletion() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, - Arrays.asList("0446c11fe2ba68a14f938ebc6e71ded7")); + Arrays.asList("6c22e5d57c4f5b631e3345e721aaca1b")); executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); } } diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index 66aed1173..baab1f5fa 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -73,9 +73,14 @@ public class Haplotype extends Allele { @Override public boolean equals( Object h ) { - return h instanceof Haplotype && super.equals(h); + return h instanceof Haplotype && Arrays.equals(getBases(), ((Haplotype) h).getBases()); } - + + @Override + public int hashCode() { + return Arrays.hashCode(getBases()); + } + public HashMap getEventMap() { return eventMap; } From 39c73a6cf5adf5d0643c93af0c60b354a31e73ad Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 18 Jan 2013 03:35:48 -0500 Subject: [PATCH 037/188] 1. Ryan and I noticed that the FisherStrand annotation was completely busted for indels with reduced reads; fixed. 2. While making the previous fix and unifying FS for SNPs and indels, I noticed that FS was slightly broken in the general case for indels too; fixed. 3. I also fixed a minor bug in the Allele Biased Downsampling code for reduced reads. --- .../AlleleBiasedDownsamplingUtils.java | 11 ++-- .../gatk/walkers/annotator/FisherStrand.java | 53 +++++++++---------- .../UnifiedGenotyperIntegrationTest.java | 12 ++--- .../HaplotypeCallerIntegrationTest.java | 4 +- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java b/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java index a7bb58d0c..ba1da7c87 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java @@ -84,12 +84,13 @@ public class AlleleBiasedDownsamplingUtils { // start by stratifying the reads by the alleles they represent at this position for( final PileupElement pe : pileup ) { // we do not want to remove a reduced read - if ( pe.getRead().isReducedRead() ) + if ( pe.getRead().isReducedRead() ) { reducedReadPileups.add(pe); - - final int baseIndex = BaseUtils.simpleBaseToBaseIndex(pe.getBase()); - if ( baseIndex != -1 ) - alleleStratifiedElements[baseIndex].add(pe); + } else { + final int baseIndex = BaseUtils.simpleBaseToBaseIndex(pe.getBase()); + if ( baseIndex != -1 ) + alleleStratifiedElements[baseIndex].add(pe); + } } // Unfortunately, we need to maintain the original pileup ordering of reads or FragmentUtils will complain later. diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java index fbd27dfe3..ff3d7940f 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/FisherStrand.java @@ -265,24 +265,16 @@ public class FisherStrand extends InfoFieldAnnotation implements StandardAnnotat for (PerReadAlleleLikelihoodMap maps : stratifiedPerReadAlleleLikelihoodMap.values() ) { for (Map.Entry> el : maps.getLikelihoodReadMap().entrySet()) { - final boolean matchesRef = PerReadAlleleLikelihoodMap.getMostLikelyAllele(el.getValue()).equals(ref,true); - final boolean matchesAlt = PerReadAlleleLikelihoodMap.getMostLikelyAllele(el.getValue()).equals(alt,true); - - if ( !matchesRef && !matchesAlt ) - continue; - - boolean isFW = el.getKey().getReadNegativeStrandFlag(); - - int row = matchesRef ? 0 : 1; - int column = isFW ? 0 : 1; - + final Allele mostLikelyAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(el.getValue()); final GATKSAMRecord read = el.getKey(); - table[row][column] += (read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1); + final int representativeCount = read.isReducedRead() ? read.getReducedCount(ReadUtils.getReadCoordinateForReferenceCoordinateUpToEndOfRead(read, vc.getStart(), ReadUtils.ClippingTail.RIGHT_TAIL)) : 1; + updateTable(table, mostLikelyAllele, read, ref, alt, representativeCount); } } return table; } + /** Allocate and fill a 2x2 strand contingency table. In the end, it'll look something like this: * fw rc @@ -299,31 +291,36 @@ public class FisherStrand extends InfoFieldAnnotation implements StandardAnnotat for ( Map.Entry sample : stratifiedContexts.entrySet() ) { for (PileupElement p : sample.getValue().getBasePileup()) { - // ignore reduced reads because they are always on the forward strand! - // TODO -- when het compression is enabled in RR, we somehow need to allow those reads through into the Fisher test - if ( p.getRead().isReducedRead() ) - continue; - if ( ! RankSumTest.isUsableBase(p, false) ) // ignore deletions continue; if ( p.getQual() < minQScoreToConsider || p.getMappingQual() < minQScoreToConsider ) continue; - final Allele base = Allele.create(p.getBase(), false); - final boolean isFW = !p.getRead().getReadNegativeStrandFlag(); - - final boolean matchesRef = ref.equals(base, true); - final boolean matchesAlt = alt.equals(base, true); - if ( matchesRef || matchesAlt ) { - int row = matchesRef ? 0 : 1; - int column = isFW ? 0 : 1; - - table[row][column] += p.getRepresentativeCount(); - } + updateTable(table, Allele.create(p.getBase(), false), p.getRead(), ref, alt, p.getRepresentativeCount()); } } return table; } + + private static void updateTable(final int[][] table, final Allele allele, final GATKSAMRecord read, final Allele ref, final Allele alt, final int representativeCount) { + // ignore reduced reads because they are always on the forward strand! + // TODO -- when het compression is enabled in RR, we somehow need to allow those reads through into the Fisher test + if ( read.isReducedRead() ) + return; + + final boolean matchesRef = allele.equals(ref, true); + final boolean matchesAlt = allele.equals(alt, true); + + if ( matchesRef || matchesAlt ) { + + final boolean isFW = !read.getReadNegativeStrandFlag(); + + int row = matchesRef ? 0 : 1; + int column = isFW ? 0 : 1; + + table[row][column] += representativeCount; + } + } } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java index a84019988..5b5a75d4e 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java @@ -363,7 +363,7 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { " -o %s" + " -L 1:10,000,000-10,500,000", 1, - Arrays.asList("39c7a813fd6ee82d3604f2a868b35b2a")); + Arrays.asList("8231ae37b52b927db9fc1e5c221b0ba0")); executeTest(String.format("test indel calling, multiple technologies"), spec); } @@ -391,13 +391,13 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { public void testMultiSampleIndels1() { WalkerTest.WalkerTestSpec spec1 = new WalkerTest.WalkerTestSpec( baseCommandIndels + " -I " + validationDataLocation + "low_coverage_CEU.chr1.10k-11k.bam -o %s -L 1:10450700-10551000", 1, - Arrays.asList("3d3c5691973a223209a1341272d881be")); + Arrays.asList("a47810de2f6ef8087f4644064a0814bc")); List result = executeTest("test MultiSample Pilot1 CEU indels", spec1).getFirst(); WalkerTest.WalkerTestSpec spec2 = new WalkerTest.WalkerTestSpec( baseCommandIndels + " --genotyping_mode GENOTYPE_GIVEN_ALLELES -alleles " + result.get(0).getAbsolutePath() + " -I " + validationDataLocation + "low_coverage_CEU.chr1.10k-11k.bam -o %s -L 1:10450700-10551000", 1, - Arrays.asList("23b7a37a64065cee53a80495c8717eea")); + Arrays.asList("53b8d2b0fa63c5d1019855e8e0db28f0")); executeTest("test MultiSample Pilot1 CEU indels using GENOTYPE_GIVEN_ALLELES", spec2); } @@ -497,18 +497,18 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { public void testReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T UnifiedGenotyper -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("092e42a712afb660ec79ff11c55933e2")); + Arrays.asList("02175dc9731aed92837ce0db78489fc0")); executeTest("test calling on a ReducedRead BAM", spec); } @Test public void testReducedBamSNPs() { - testReducedCalling("SNP", "c0de74ab8f4f14eb3a2c5d55c200ac5f"); + testReducedCalling("SNP", "fe1af8b30b7f1a267f772b9aaf388f24"); } @Test public void testReducedBamINDELs() { - testReducedCalling("INDEL", "1c9aaf65ffaa12bb766855265a1c3f8e"); + testReducedCalling("INDEL", "a85c110fcac9574a54c7daccb1e2d5ae"); } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 6c7afd8bb..27fe31fa7 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -102,7 +102,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "d590c8d6d5e58d685401b65a23846893"); + "1a034b7eb572e1b6f659d6e5d57b3e76"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -183,7 +183,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void testReducedBamWithReadsNotFullySpanningDeletion() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, - Arrays.asList("6c22e5d57c4f5b631e3345e721aaca1b")); + Arrays.asList("4e8121dd9dc90478f237bd6ae4d19920")); executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); } } From 91030e9afa344b44f6551551f1f5687b48d4e51c Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Fri, 18 Jan 2013 09:49:48 -0500 Subject: [PATCH 038/188] Bugfix: records that get paired up during the resolution of multiple-records-per-site were not going into genotype-level filtering. Caught via testing. Testing for moltenized output, and for genotype-level filtering. This tool is now fully functional. There are three todo items: 1) Docs 2) An additional output table that gives concordance proportions normalized by records in both eval and comp (not just total in eval or total in comp) 3) Code cleanup for table creation (putting a table together the way I do takes -way- too many lines of code) --- .../variantutils/GenotypeConcordance.java | 15 +++---- .../GenotypeConcordanceIntegrationTest.java | 44 +++++++++++++++++++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 2acff956c..e8965dfc8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -94,9 +94,8 @@ public class GenotypeConcordance extends RodWalker evalJexls = null; private List compJexls = null; - // todo -- table with "proportion of overlapping sites" (not just eval/comp margins) - // todo -- moltenize - + // todo -- table with "proportion of overlapping sites" (not just eval/comp margins) [e.g. drop no-calls] + // (this will break all the integration tests of course, due to new formatting) public void initialize() { evalJexls = initializeJexl(genotypeFilterExpressionsEval); @@ -201,7 +200,7 @@ public class GenotypeConcordance extends RodWalker(eval,pairedComp)); + resolvedPairs.add(new Pair(filterGenotypes(eval,ignoreFilters,evalJexls),filterGenotypes(pairedComp,ignoreFilters,compJexls))); pairedEval.add(eval); if ( compList.size() < 1 ) break; @@ -209,11 +208,11 @@ public class GenotypeConcordance extends RodWalker(unpairedEval,createEmptyContext(unpairedEval,compSamples))); + resolvedPairs.add(new Pair(filterGenotypes(unpairedEval,ignoreFilters,evalJexls),createEmptyContext(unpairedEval,compSamples))); } for ( VariantContext unpairedComp : compList ) { - resolvedPairs.add(new Pair(createEmptyContext(unpairedComp,evalSamples),unpairedComp)); + resolvedPairs.add(new Pair(createEmptyContext(unpairedComp,evalSamples),filterGenotypes(unpairedComp,ignoreFilters,compJexls))); } return resolvedPairs; @@ -233,6 +232,7 @@ public class GenotypeConcordance extends RodWalker exps) { - // placeholder method for genotype-level filtering. However if the site itself is filtered, - // and such filters are not ignored, the genotype-level data should be altered to reflect this - if ( ! context.isFiltered() || ignoreSiteFilter ) { List filteredGenotypes = new ArrayList(context.getNSamples()); for ( Genotype g : context.getGenotypes() ) { diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java index 113f098e3..117032ac9 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java @@ -61,6 +61,17 @@ public class GenotypeConcordanceIntegrationTest extends WalkerTest { executeTest("test non-overlapping samples", spec); } + @Test + public void testNonoverlappingSamplesMoltenized() { + WalkerTestSpec spec = new WalkerTestSpec( + baseTestString("GenotypeConcordanceNonOverlapTest_Eval.vcf", "GenotypeConcordanceNonOverlapTest_Comp.vcf"), + 0, + Arrays.asList("") + ); + + executeTest("Test moltenized output",spec); + } + @Test public void testMultipleRecordsPerSite() { WalkerTestSpec spec = new WalkerTestSpec( @@ -71,4 +82,37 @@ public class GenotypeConcordanceIntegrationTest extends WalkerTest { executeTest("test multiple records per site",spec); } + + @Test + public void testGQFilteringEval() { + WalkerTestSpec spec = new WalkerTestSpec( + baseTestString("genotypeConcordanceFilterTest.vcf","genotypeConcordanceFilterTest.vcf") + " -gfe 'GQ<30'", + 0, + Arrays.asList("b7b495ccfa6d50a6be3e095d3f6d3c52") + ); + + executeTest("Test filtering on the EVAL rod",spec); + } + + @Test + public void testFloatFilteringComp() { + WalkerTestSpec spec = new WalkerTestSpec( + baseTestString("genotypeConcordanceFilterTest.vcf","genotypeConcordanceFilterTest.vcf") + " -gfc 'LX<0.50'", + 0, + Arrays.asList("6406b16cde7960b8943edf594303afd6") + ); + + executeTest("Test filtering on the COMP rod", spec); + } + + @Test + public void testCombinedFilters() { + WalkerTestSpec spec = new WalkerTestSpec( + baseTestString("genotypeConcordanceFilterTest.vcf","genotypeConcordanceFilterTest.vcf") + " -gfc 'LX<0.52' -gfe 'DP<5' -gfe 'GQ<37'", + 0, + Arrays.asList("26ffd06215b6177acce0ea9f35d73d31") + ); + + executeTest("Test filtering on both rods",spec); + } } From bf5748a5381c63ad341ebfdaa36bdce21af44f74 Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Fri, 18 Jan 2013 10:25:36 -0500 Subject: [PATCH 040/188] Forgot to actually put in the md5. Also with the new change to record pairing and filtering, the multiple-records integration test changed: the indel records (T/TG | T/TGACA) are matched up (rather than left separate) resulting in properly identifying mismatching alleles, rather than HET-UNAVAILABLE and UNAVAILABLE-HET. Very nice. --- .../variantutils/GenotypeConcordanceIntegrationTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java index 117032ac9..e69d1ee60 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java @@ -64,9 +64,9 @@ public class GenotypeConcordanceIntegrationTest extends WalkerTest { @Test public void testNonoverlappingSamplesMoltenized() { WalkerTestSpec spec = new WalkerTestSpec( - baseTestString("GenotypeConcordanceNonOverlapTest_Eval.vcf", "GenotypeConcordanceNonOverlapTest_Comp.vcf"), + baseTestString("GenotypeConcordanceNonOverlapTest_Eval.vcf", "GenotypeConcordanceNonOverlapTest_Comp.vcf") + " -moltenize", 0, - Arrays.asList("") + Arrays.asList("370141088362d0ab7054be5249c49c11") ); executeTest("Test moltenized output",spec); @@ -77,7 +77,7 @@ public class GenotypeConcordanceIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec( baseTestString("GenotypeConcordance.multipleRecordsTest1.eval.vcf","GenotypeConcordance.multipleRecordsTest1.comp.vcf"), 0, - Arrays.asList("fdf2cac15775c613f596c27247a76570") + Arrays.asList("352d59c4ac0cee5eb8ddbc9404b19ce9") ); executeTest("test multiple records per site",spec); From cac439bc5e81fc3a21882dfaba9894bcb886340f Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 18 Jan 2013 11:17:31 -0500 Subject: [PATCH 041/188] Optimized the Allele Biased Downsampling: now it doesn't re-sort the pileup but just removes reads from the original one. Added a small fix that slightly changed md5s. --- .../AlleleBiasedDownsamplingUtils.java | 128 ++++++------------ .../UnifiedGenotyperIntegrationTest.java | 10 +- .../HaplotypeCallerIntegrationTest.java | 4 +- 3 files changed, 52 insertions(+), 90 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java b/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java index ba1da7c87..02821ab50 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java @@ -47,7 +47,6 @@ package org.broadinstitute.sting.gatk.downsampling; import net.sf.samtools.SAMReadGroupRecord; -import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.pileup.*; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -78,54 +77,46 @@ public class AlleleBiasedDownsamplingUtils { for ( int i = 0; i < 4; i++ ) alleleStratifiedElements[i] = new ArrayList(); - // keep all of the reduced reads - final ArrayList reducedReadPileups = new ArrayList(); - // start by stratifying the reads by the alleles they represent at this position - for( final PileupElement pe : pileup ) { + for ( final PileupElement pe : pileup ) { // we do not want to remove a reduced read - if ( pe.getRead().isReducedRead() ) { - reducedReadPileups.add(pe); - } else { + if ( !pe.getRead().isReducedRead() ) { final int baseIndex = BaseUtils.simpleBaseToBaseIndex(pe.getBase()); if ( baseIndex != -1 ) alleleStratifiedElements[baseIndex].add(pe); } } - // Unfortunately, we need to maintain the original pileup ordering of reads or FragmentUtils will complain later. - int numReadsToRemove = (int)(pileup.getNumberOfElements() * downsamplingFraction); // floor - final TreeSet elementsToKeep = new TreeSet(new Comparator() { - @Override - public int compare(PileupElement element1, PileupElement element2) { - final int difference = element1.getRead().getAlignmentStart() - element2.getRead().getAlignmentStart(); - return difference != 0 ? difference : element1.getRead().getReadName().compareTo(element2.getRead().getReadName()); - } - }); - elementsToKeep.addAll(reducedReadPileups); - // make a listing of allele counts final int[] alleleCounts = new int[4]; for ( int i = 0; i < 4; i++ ) alleleCounts[i] = alleleStratifiedElements[i].size(); // do smart down-sampling + int numReadsToRemove = (int)(pileup.getNumberOfElements() * downsamplingFraction); // floor final int[] targetAlleleCounts = runSmartDownsampling(alleleCounts, numReadsToRemove); + final HashSet readsToRemove = new HashSet(numReadsToRemove); for ( int i = 0; i < 4; i++ ) { final ArrayList alleleList = alleleStratifiedElements[i]; - // if we don't need to remove any reads, keep them all - if ( alleleList.size() <= targetAlleleCounts[i] ) - elementsToKeep.addAll(alleleList); - else - elementsToKeep.addAll(downsampleElements(alleleList, alleleList.size() - targetAlleleCounts[i], log)); + // if we don't need to remove any reads, then don't + if ( alleleList.size() > targetAlleleCounts[i] ) + readsToRemove.addAll(downsampleElements(alleleList, alleleList.size() - targetAlleleCounts[i], log)); } // clean up pointers so memory can be garbage collected if needed for ( int i = 0; i < 4; i++ ) alleleStratifiedElements[i].clear(); - return new ReadBackedPileupImpl(pileup.getLocation(), new ArrayList(elementsToKeep)); + // we need to keep the reads sorted because the FragmentUtils code will expect them in coordinate order and will fail otherwise + final List readsToKeep = new ArrayList(pileup.getNumberOfElements() - numReadsToRemove); + for ( final PileupElement pe : pileup ) { + if ( !readsToRemove.contains(pe) ) { + readsToKeep.add(pe); + } + } + + return new ReadBackedPileupImpl(pileup.getLocation(), new ArrayList(readsToKeep)); } private static int scoreAlleleCounts(final int[] alleleCounts) { @@ -189,37 +180,43 @@ public class AlleleBiasedDownsamplingUtils { } /** - * Performs allele biased down-sampling on a pileup and computes the list of elements to keep + * Performs allele biased down-sampling on a pileup and computes the list of elements to remove * * @param elements original list of records * @param numElementsToRemove the number of records to remove * @param log logging output - * @return the list of pileup elements TO KEEP + * @return the list of pileup elements TO REMOVE */ - private static List downsampleElements(final ArrayList elements, final int numElementsToRemove, final PrintStream log) { - if ( numElementsToRemove == 0 ) - return elements; + private static List downsampleElements(final List elements, final int numElementsToRemove, final PrintStream log) { + ArrayList elementsToRemove = new ArrayList(numElementsToRemove); + // are there no elements to remove? + if ( numElementsToRemove == 0 ) + return elementsToRemove; + + // should we remove all of the elements? final int pileupSize = elements.size(); if ( numElementsToRemove == pileupSize ) { logAllElements(elements, log); - return new ArrayList(0); + elementsToRemove.addAll(elements); + return elementsToRemove; } + // create a bitset describing which elements to remove final BitSet itemsToRemove = new BitSet(pileupSize); for ( Integer selectedIndex : MathUtils.sampleIndicesWithoutReplacement(pileupSize, numElementsToRemove) ) { itemsToRemove.set(selectedIndex); } - ArrayList elementsToKeep = new ArrayList(pileupSize - numElementsToRemove); for ( int i = 0; i < pileupSize; i++ ) { - if ( itemsToRemove.get(i) ) - logRead(elements.get(i).getRead(), log); - else - elementsToKeep.add(elements.get(i)); + if ( itemsToRemove.get(i) ) { + final T element = elements.get(i); + logElement(element, log); + elementsToRemove.add(element); + } } - return elementsToKeep; + return elementsToRemove; } /** @@ -253,65 +250,30 @@ public class AlleleBiasedDownsamplingUtils { final List alleleBin = alleleReadMap.get(alleles.get(i)); if ( alleleBin.size() > targetAlleleCounts[i] ) { - readsToRemove.addAll(downsampleReads(alleleBin, alleleBin.size() - targetAlleleCounts[i], log)); + readsToRemove.addAll(downsampleElements(alleleBin, alleleBin.size() - targetAlleleCounts[i], log)); } } return readsToRemove; } - /** - * Performs allele biased down-sampling on a pileup and computes the list of elements to remove - * - * @param reads original list of records - * @param numElementsToRemove the number of records to remove - * @param log logging output - * @return the list of pileup elements TO REMOVE - */ - private static List downsampleReads(final List reads, final int numElementsToRemove, final PrintStream log) { - final ArrayList readsToRemove = new ArrayList(numElementsToRemove); - - if ( numElementsToRemove == 0 ) - return readsToRemove; - - final int pileupSize = reads.size(); - if ( numElementsToRemove == pileupSize ) { - logAllReads(reads, log); - return reads; - } - - final BitSet itemsToRemove = new BitSet(pileupSize); - for ( Integer selectedIndex : MathUtils.sampleIndicesWithoutReplacement(pileupSize, numElementsToRemove) ) { - itemsToRemove.set(selectedIndex); - } - - for ( int i = 0; i < pileupSize; i++ ) { - if ( itemsToRemove.get(i) ) { - final GATKSAMRecord read = reads.get(i); - readsToRemove.add(read); - logRead(read, log); + private static void logAllElements(final List elements, final PrintStream log) { + if ( log != null ) { + for ( final T obj : elements ) { + logElement(obj, log); } } - - return readsToRemove; } - private static void logAllElements(final List elements, final PrintStream log) { + private static void logElement(final T obj, final PrintStream log) { if ( log != null ) { - for ( final PileupElement p : elements ) - logRead(p.getRead(), log); - } - } - private static void logAllReads(final List reads, final PrintStream log) { - if ( log != null ) { - for ( final GATKSAMRecord read : reads ) - logRead(read, log); - } - } + final GATKSAMRecord read; + if ( obj instanceof PileupElement ) + read = ((PileupElement)obj).getRead(); + else + read = (GATKSAMRecord)obj; - private static void logRead(final SAMRecord read, final PrintStream log) { - if ( log != null ) { final SAMReadGroupRecord readGroup = read.getReadGroup(); log.println(String.format("%s\t%s\t%s\t%s", read.getReadName(), readGroup.getSample(), readGroup.getLibrary(), readGroup.getPlatformUnit())); } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java index 5b5a75d4e..45a42d018 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperIntegrationTest.java @@ -108,7 +108,7 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { public void testMultipleSNPAlleles() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T UnifiedGenotyper -R " + b37KGReference + " --no_cmdline_in_header -glm BOTH --dbsnp " + b37dbSNP129 + " -I " + privateTestDir + "multiallelic.snps.bam -o %s -L " + privateTestDir + "multiallelic.snps.intervals", 1, - Arrays.asList("b41b95aaa2c453c9b75b3b29a9c2718e")); + Arrays.asList("35479a79e1ce7c15493bd77e58cadcaa")); executeTest("test Multiple SNP alleles", spec); } @@ -238,12 +238,12 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { @Test public void testOutputParameterAllConfident() { - testOutputParameters("--output_mode EMIT_ALL_CONFIDENT_SITES", "9dbc9389db39cf9697e93e0bf529314f"); + testOutputParameters("--output_mode EMIT_ALL_CONFIDENT_SITES", "5649f72de04e1391e0f2bb86843d3d72"); } @Test public void testOutputParameterAllSites() { - testOutputParameters("--output_mode EMIT_ALL_SITES", "8b26088a035e579c4afd3b46737291e4"); + testOutputParameters("--output_mode EMIT_ALL_SITES", "cb151bb9e90680b12714d481091ed209"); } private void testOutputParameters(final String args, final String md5) { @@ -497,13 +497,13 @@ public class UnifiedGenotyperIntegrationTest extends WalkerTest { public void testReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T UnifiedGenotyper -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("02175dc9731aed92837ce0db78489fc0")); + Arrays.asList("8b9a9fc2e7150acbe2dac91b4620f304")); executeTest("test calling on a ReducedRead BAM", spec); } @Test public void testReducedBamSNPs() { - testReducedCalling("SNP", "fe1af8b30b7f1a267f772b9aaf388f24"); + testReducedCalling("SNP", "b5991dddbfb59366614ff8819062649f"); } @Test diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 27fe31fa7..939b9873c 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -102,7 +102,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "1a034b7eb572e1b6f659d6e5d57b3e76"); + "d590c8d6d5e58d685401b65a23846893"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -146,7 +146,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("8b1b8d1bd7feac1503fc4ffa6236cff7")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("31db0a2d9eb07f86e0a89f0d97169072")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } From 826c29827be177af7d731bb518eb16d6f690c0ad Mon Sep 17 00:00:00 2001 From: Ami Levy-Moonshine Date: Fri, 18 Jan 2013 15:03:12 -0500 Subject: [PATCH 043/188] change the default VCFs gatherer of the GATK (not just the UG) --- .../gatk/walkers/genotyper/UnifiedGenotyper.java | 2 +- .../extensions/gatk/ArgumentDefinitionField.java | 8 +++++++- .../queue/extensions/gatk/CatVariantsGatherer.scala | 13 ++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java index 758d52e68..d16ece4fd 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java @@ -176,7 +176,7 @@ public class UnifiedGenotyper extends LocusWalker, Unif /** * A raw, unfiltered, highly sensitive callset in VCF format. */ - @Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer") + //@Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer") @Output(doc="File to which variants should be written",required=true) protected VariantContextWriter writer = null; diff --git a/public/java/src/org/broadinstitute/sting/queue/extensions/gatk/ArgumentDefinitionField.java b/public/java/src/org/broadinstitute/sting/queue/extensions/gatk/ArgumentDefinitionField.java index 1bf4c69fc..51cc576aa 100644 --- a/public/java/src/org/broadinstitute/sting/queue/extensions/gatk/ArgumentDefinitionField.java +++ b/public/java/src/org/broadinstitute/sting/queue/extensions/gatk/ArgumentDefinitionField.java @@ -158,12 +158,18 @@ public abstract class ArgumentDefinitionField extends ArgumentField { List fields = new ArrayList(); String gatherClass; + + // one can set the specific gatherer to use by adding @Gather before any output argument. + // For example (used to be part of UG): + // @Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer") + // @Output(doc="File to which variants should be written",required=true) + // protected VariantContextWriter writer = null; if (gatherer != null) gatherClass = gatherer; else if (SAMFileWriter.class.isAssignableFrom(argumentDefinition.argumentType)) gatherClass = "BamGatherFunction"; else if (VariantContextWriter.class.isAssignableFrom(argumentDefinition.argumentType)) - gatherClass = "VcfGatherFunction"; + gatherClass = "CatVariantsGatherer"; // used to be "VcfGatherFunction"; else gatherClass = "org.broadinstitute.sting.queue.function.scattergather.SimpleTextGatherFunction"; diff --git a/public/scala/src/org/broadinstitute/sting/queue/extensions/gatk/CatVariantsGatherer.scala b/public/scala/src/org/broadinstitute/sting/queue/extensions/gatk/CatVariantsGatherer.scala index 848554dfc..30fd4c81f 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/extensions/gatk/CatVariantsGatherer.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/extensions/gatk/CatVariantsGatherer.scala @@ -30,11 +30,13 @@ import org.broadinstitute.sting.queue.function.scattergather.GatherFunction /** - * Created with IntelliJ IDEA. - * User: ami - * Date: 12/11/12 - * Time: 2:04 PM - * To change this template use File | Settings | File Templates. + * + * Currently this is the default gather for VCFs. + * One can set a specific gatherer to use by adding @Gather before any output argument. + * For example (used to be part of UG): + * @Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer") + * @Output(doc="File to which variants should be written",required=true) + * protected VariantContextWriter writer = null; */ class CatVariantsGatherer extends CatVariants with GatherFunction with RetryMemoryLimit{ this.assumeSorted = true @@ -45,6 +47,7 @@ class CatVariantsGatherer extends CatVariants with GatherFunction with RetryMemo this.reference = originalGATK.reference_sequence this.variant = this.gatherParts.zipWithIndex map { case (input, index) => new TaggedFile(input, "input"+index) } this.outputFile = this.originalOutput + this.assumeSorted = true super.freezeFieldValues() } From 7b8b06416553c6b60f4092dd4cd45340de219359 Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Fri, 18 Jan 2013 16:11:53 -0500 Subject: [PATCH 045/188] Last manual license update (hopefully) if everyone updates their git hook accordingly, this will be the last time I have to manually run the script. GSATDG-5 --- .../GenotypeConcordanceIntegrationTest.java | 67 ++++++++++++------- .../IntervalArgumentCollection.java | 6 +- .../sting/gatk/iterators/GATKSAMIterator.java | 46 ++++++------- .../locusiterator/AlignmentStateMachine.java | 46 ++++++------- .../locusiterator/LIBSDownsamplingInfo.java | 46 ++++++------- .../utils/locusiterator/LIBSPerformance.java | 46 ++++++------- .../utils/locusiterator/LocusIterator.java | 25 +++++++ .../PerSampleReadStateManager.java | 46 ++++++------- .../utils/locusiterator/ReadStateManager.java | 46 ++++++------- .../locusiterator/SamplePartitioner.java | 46 ++++++------- .../sting/utils/sam/ArtificialBAMBuilder.java | 46 ++++++------- .../traversals/DummyActiveRegionWalker.java | 46 ++++++------- .../TraverseActiveRegionsUnitTest.java | 46 ++++++------- .../AlignmentStateMachineUnitTest.java | 46 ++++++------- .../utils/locusiterator/LIBS_position.java | 46 ++++++------- .../locusiterator/LocusIteratorBenchmark.java | 46 ++++++------- .../LocusIteratorByStateBaseTest.java | 46 ++++++------- .../PerSampleReadStateManagerUnitTest.java | 46 ++++++------- .../utils/pileup/PileupElementUnitTest.java | 46 ++++++------- .../sam/ArtificialBAMBuilderUnitTest.java | 46 ++++++------- 20 files changed, 463 insertions(+), 417 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java index e69d1ee60..2ebb1d7d8 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordanceIntegrationTest.java @@ -1,27 +1,48 @@ /* - * Copyright (c) 2010. - * - * 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. - */ +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ package org.broadinstitute.sting.gatk.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java b/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java index 3f76ae652..b491c9f3d 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/commandline/IntervalArgumentCollection.java @@ -1,6 +1,6 @@ /* * 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 @@ -9,10 +9,10 @@ * 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 diff --git a/public/java/src/org/broadinstitute/sting/gatk/iterators/GATKSAMIterator.java b/public/java/src/org/broadinstitute/sting/gatk/iterators/GATKSAMIterator.java index 30a520e09..f5f4ec6f6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/iterators/GATKSAMIterator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/iterators/GATKSAMIterator.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.iterators; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java index 50bc9e25b..c4b566582 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachine.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSDownsamplingInfo.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSDownsamplingInfo.java index fc282163e..c7875354f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSDownsamplingInfo.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSDownsamplingInfo.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java index 2d074f420..8069ea29f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LIBSPerformance.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java index f830dcb30..fc114b4f0 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java @@ -1,3 +1,28 @@ +/* +* 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.utils.locusiterator; import net.sf.samtools.util.CloseableIterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java index 3f3bc706f..2caaf9d27 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManager.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java index 09ec3b264..8fbd302a8 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/ReadStateManager.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java index 9bb474e4d..49a8d10aa 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/SamplePartitioner.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java index ab539c9dc..82b5b29cc 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.sam; diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java index bc1e1d7b0..76be54d72 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.traversals; diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java index 319af5ec5..76eac3a8d 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.traversals; diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachineUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachineUnitTest.java index 2f1e95a1f..7cb148b61 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachineUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/AlignmentStateMachineUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LIBS_position.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LIBS_position.java index 31be5a25a..d856805f8 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LIBS_position.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LIBS_position.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorBenchmark.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorBenchmark.java index c0938676e..e52cd46cc 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorBenchmark.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorBenchmark.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateBaseTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateBaseTest.java index 7c8c6108c..1a51440ad 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateBaseTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateBaseTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java index b9f2fb29a..77dd29e60 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/PerSampleReadStateManagerUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.locusiterator; diff --git a/public/java/test/org/broadinstitute/sting/utils/pileup/PileupElementUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/pileup/PileupElementUnitTest.java index a760833f5..888ab7f7f 100644 --- a/public/java/test/org/broadinstitute/sting/utils/pileup/PileupElementUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/pileup/PileupElementUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.pileup; diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java index 2a638eb69..a2aec1b1e 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilderUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.sam; From 7060e01a8e0bcbd20d98f6601c48705ed939be74 Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Tue, 22 Jan 2013 15:14:41 -0500 Subject: [PATCH 050/188] Fix for broken unit test plus some minor changes to comments. Unit tests were broken by my pulling the site status utility function into the enum. Thankfully the unit tests caught my silly duplication of a line. --- .../gatk/walkers/variantutils/ConcordanceMetrics.java | 2 +- .../gatk/walkers/variantutils/GenotypeConcordance.java | 5 +++-- .../walkers/variantutils/ConcordanceMetricsUnitTest.java | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java index 8a87c9957..9d5495351 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java @@ -299,7 +299,7 @@ public class ConcordanceMetrics { return EVAL_ONLY; boolean evalSubsetTruth = VariantContextUtils.allelesAreSubset(eval,truth); - boolean truthSubsetEval = VariantContextUtils.allelesAreSubset(eval,truth); + boolean truthSubsetEval = VariantContextUtils.allelesAreSubset(truth,eval); if ( evalSubsetTruth && truthSubsetEval ) return ALLELES_MATCH; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index e8965dfc8..6902f864e 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -168,8 +168,9 @@ public class GenotypeConcordance extends RodWalker data = getData2(); VariantContext eval = data.getFirst(); VariantContext truth = data.getSecond(); @@ -709,8 +709,13 @@ public class ConcordanceMetricsUnitTest extends BaseTest { List> data = getData7(); + int idx = 0; + int[] expecNotMatch = new int[]{0,0,0,0,0,1,1}; for ( Pair varPair : data ) { metrics.update(varPair.getFirst(),varPair.getSecond()); + Assert.assertEquals(metrics.getOverallSiteConcordance().get(ConcordanceMetrics.SiteConcordanceType.ALLELES_DO_NOT_MATCH),expecNotMatch[idx]); + logger.info(idx); + idx++; } Assert.assertEquals(metrics.getOverallSiteConcordance().get(ConcordanceMetrics.SiteConcordanceType.ALLELES_DO_NOT_MATCH),1); From d33c755aeaafcef933b474fba01c82a0a71dbe7b Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Tue, 22 Jan 2013 15:29:33 -0500 Subject: [PATCH 051/188] Adding docs. --- .../variantutils/GenotypeConcordance.java | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 6902f864e..47e2ea052 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -62,27 +62,75 @@ import java.io.PrintStream; import java.util.*; /** - * A simple walker for performing genotype concordance calculations between two callsets + * A simple walker for performing genotype concordance calculations between two callsets. Outputs a GATK table with + * per-sample and aggregate counts and frequencies, a summary table for NRD/NRS, and a table for site allele overlaps. + * + *

+ * Genotype concordance takes in two callsets (vcfs) and tabulates the number of sites which overlap and share alleles, + * and for each sample, the genotype-by-genotype counts (for instance, the number of sites at which a sample was + * called homozygous reference in the EVAL callset, but homozygous variant in the COMP callset). It outputs these + * counts as well as convenient proportions (such as the proportion of het calls in the EVAL which were called REF in + * the COMP) and metrics (such as NRD and NRS). + * + *

INPUT

+ *

+ * Genotype concordance requires two callsets (as it does a comparison): an EVAL and a COMP callset, specified via + * the -eval and -comp arguments + *

+ * (Optional) Jexl expressions for genotype-level filtering of EVAL or COMP genotypes, specified via the -gfe and + * -cfe arguments, respectively. + * + *

OUTPUT

+ * Genotype Concordance writes a GATK report to the specified (via -o) file, consisting of multiple tables of counts + * and proportions. These tables may be optionally moltenized via the -moltenize argument. + * */ public class GenotypeConcordance extends RodWalker>,ConcordanceMetrics> { + /** + * The callset you want to evaluate, typically this is where you'd put 'unassessed' callsets. + */ @Input(fullName="eval",shortName="eval",doc="The variants and genotypes to evaluate",required=true) RodBinding evalBinding; + /** + * The callset you want to treat as 'truth'. Can also be of unknown quality for the sake of callset comparisons. + */ @Input(fullName="comp",shortName="comp",doc="The variants and genotypes to compare against",required=true) RodBinding compBinding; + /** + * The FILTER field of the eval and comp VCFs will be ignored. If this flag is not included, all FILTER sites will + * be treated as not being present in the VCF. (That is, the genotypes will be assigned UNAVAILABLE, as distinct + * from NO_CALL). + */ @Argument(fullName="ignoreFilters",doc="Filters will be ignored",required=false) boolean ignoreFilters = false; + /** + * A genotype level JEXL expression to apply to eval genotypes. Genotypes filtered in this way will be replaced by NO_CALL. + * For instance: -gfe 'GQ<20' will set to no-call any genotype with genotype quality less than 20. + */ @Argument(shortName="gfe", fullName="genotypeFilterExpressionEval", doc="One or more criteria to use to set EVAL genotypes to no-call. "+ "These genotype-level filters are only applied to the EVAL rod.", required=false) public ArrayList genotypeFilterExpressionsEval = new ArrayList(); + /** + * Identical to -gfe except the filter is applied to genotypes in the comp rod. + */ @Argument(shortName="gfc", fullName="genotypeFilterExpressionComp", doc="One or more criteria to use to set COMP genotypes to no-call. "+ "These genotype-level filters are only applied to the COMP rod.", required=false) public ArrayList genotypeFilterExpressionsComp = new ArrayList(); + /** + * Moltenize the count and proportion tables. Rather than moltenizing per-sample data into a 2x2 table, it is fully + * moltenized into elements. That is, WITHOUT this argument, each row of the table begins with the sample name and + * proceeds directly with counts/proportions of eval/comp counts (for instance HOM_REF/HOM_REF, HOM_REF/NO_CALL). + * + * If the Moltenize argument is given, the output will begin with a sample name, followed by the contrastive genotype + * type (such as HOM_REF/HOM_REF), followed by the count or proportion. This will significantly increase the number of + * rows. + */ @Argument(shortName="moltenize",fullName="moltenize",doc="Molten rather than tabular output") public boolean moltenize = false; From c5e1bb678b9e80fbc331d41328186db8db058c6e Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Tue, 22 Jan 2013 15:18:19 -0700 Subject: [PATCH 052/188] Refrain from pushing symlinks into the repo... not all filesystems treat it correctly --- licensing/private_license.txt | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) mode change 120000 => 100644 licensing/private_license.txt diff --git a/licensing/private_license.txt b/licensing/private_license.txt deleted file mode 120000 index d83474e7a..000000000 --- a/licensing/private_license.txt +++ /dev/null @@ -1 +0,0 @@ -protected_license.txt \ No newline at end of file diff --git a/licensing/private_license.txt b/licensing/private_license.txt new file mode 100644 index 000000000..2f40c5089 --- /dev/null +++ b/licensing/private_license.txt @@ -0,0 +1,43 @@ + By downloading the PROGRAM you agree to the following terms of use: + + BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY + + This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). + + WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and + WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. + NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: + + 1. DEFINITIONS + 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. + + 2. LICENSE + 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. + The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. + 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. + 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. + + 3. OWNERSHIP OF INTELLECTUAL PROPERTY + LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. + Copyright 2012 Broad Institute, Inc. + Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. + LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. + + 4. INDEMNIFICATION + LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. + + 5. NO REPRESENTATIONS OR WARRANTIES + THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. + IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. + + 6. ASSIGNMENT + This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. + + 7. MISCELLANEOUS + 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. + 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. + 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. + 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. + 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. + 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. + 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. From 42b807a5fe806011f8594554e3a4355ecf9c3df8 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 17 Jan 2013 14:51:26 -0500 Subject: [PATCH 055/188] Unit tests for ActivityProfileResult --- .../ActivityProfileResultTest.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java new file mode 100644 index 000000000..d131666fa --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java @@ -0,0 +1,98 @@ +/* + * 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.utils.activeregion; + +import net.sf.picard.reference.ReferenceSequenceFile; +import net.sf.samtools.SAMFileHeader; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.GenomeLocSortedSet; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.sam.ArtificialBAMBuilder; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: depristo + * Date: 1/17/13 + * Time: 2:30 PM + * To change this template use File | Settings | File Templates. + */ +public class ActivityProfileResultTest { + private GenomeLocParser genomeLocParser; + + @BeforeClass + public void init() throws FileNotFoundException { + // sequence + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 100); + genomeLocParser = new GenomeLocParser(header.getSequenceDictionary()); + } + + @DataProvider(name = "ActiveProfileResultProvider") + public Object[][] makeActiveProfileResultProvider() { + final List tests = new LinkedList(); + + final String chr = genomeLocParser.getContigs().getSequence(0).getSequenceName(); + for ( final GenomeLoc loc : Arrays.asList( + genomeLocParser.createGenomeLoc(chr, 10, 10), + genomeLocParser.createGenomeLoc(chr, 100, 100) )) { + for ( final double prob : Arrays.asList(0.0, 0.5, 1.0) ) { + for ( final ActivityProfileResult.ActivityProfileResultState state : ActivityProfileResult.ActivityProfileResultState.values() ) { + for ( final Number value : Arrays.asList(1, 2, 4) ) { + tests.add(new Object[]{ loc, prob, state, value}); + } + } + tests.add(new Object[]{ loc, prob, null, null}); + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "ActiveProfileResultProvider") + public void testActiveProfileResultProvider(GenomeLoc loc, final double prob, ActivityProfileResult.ActivityProfileResultState maybeState, final Number maybeNumber) { + final ActivityProfileResult apr = maybeState == null + ? new ActivityProfileResult(loc, prob) + : new ActivityProfileResult(loc, prob, maybeState, maybeNumber); + + Assert.assertEquals(apr.getLoc(), loc); + Assert.assertNotNull(apr.toString()); + Assert.assertEquals(apr.isActiveProb, prob); + Assert.assertEquals(apr.resultState, maybeState == null ? ActivityProfileResult.ActivityProfileResultState.NONE : maybeState); + Assert.assertEquals(apr.resultValue, maybeState == null ? null : maybeNumber); + } +} From 8d9b0f1bd57d4d569d6ec27e7d372a923e11b9bd Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 17 Jan 2013 17:31:56 -0500 Subject: [PATCH 056/188] Restructure ActivityProfiler into root class ActivityProfile and derived class BandPassActivityProfile -- Required before I jump in an redo the entire activity profile so it's can be run imcrementally -- This restructuring makes the differences between the two functionalities clearer, as almost all of the functionality is in the base class. The only functionality provided by the BandPassActivityProfile is isolated to a finalizeProfile function overloaded from the base class. -- Renamed ActivityProfileResult to ActivityProfileState, as this is a clearer indication of its actual functionality. Almost all of the misc. walker changes are due to this name update -- Code cleanup and docs for TraverseActiveRegions -- Expanded unit tests for ActivityProfile and ActivityProfileState --- .../targets/FindCoveredIntervals.java | 6 +- .../haplotypecaller/HaplotypeCaller.java | 13 +- .../traversals/TraverseActiveRegions.java | 95 +++++---- .../gatk/walkers/ActiveRegionWalker.java | 4 +- .../utils/activeregion/ActivityProfile.java | 183 ++++++++++-------- ...eResult.java => ActivityProfileState.java} | 22 +-- .../activeregion/BandPassActivityProfile.java | 84 ++++++++ .../traversals/DummyActiveRegionWalker.java | 6 +- ...java => ActivityProfileStateUnitTest.java} | 20 +- .../activeregion/ActivityProfileUnitTest.java | 55 ++++-- 10 files changed, 308 insertions(+), 180 deletions(-) rename public/java/src/org/broadinstitute/sting/utils/activeregion/{ActivityProfileResult.java => ActivityProfileState.java} (77%) create mode 100644 public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java rename public/java/test/org/broadinstitute/sting/utils/activeregion/{ActivityProfileResultTest.java => ActivityProfileStateUnitTest.java} (79%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java index 08de5a6aa..74ff77e4b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java @@ -57,7 +57,7 @@ import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.gatk.walkers.PartitionBy; import org.broadinstitute.sting.gatk.walkers.PartitionType; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; @@ -74,12 +74,12 @@ public class FindCoveredIntervals extends ActiveRegionWalker { @Override // Look to see if the region has sufficient coverage - public ActivityProfileResult isActive(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) { + public ActivityProfileState isActive(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context) { int depth = ThresHolder.DEFAULTS.getFilteredCoverage(context.getBasePileup()); // note the linear probability scale - return new ActivityProfileResult(ref.getLocus(), Math.min(depth / coverageThreshold, 1)); + return new ActivityProfileState(ref.getLocus(), Math.min(depth / coverageThreshold, 1)); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 26f2560b7..9bb04421c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -56,7 +56,6 @@ import org.broadinstitute.sting.gatk.arguments.StandardCallerArgumentCollection; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.gatk.filters.BadMateFilter; import org.broadinstitute.sting.gatk.io.StingSAMFileWriter; import org.broadinstitute.sting.gatk.iterators.ReadTransformer; @@ -71,7 +70,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.VariantCallContext; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import org.broadinstitute.sting.utils.clipping.ReadClipper; import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; @@ -382,7 +381,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem @Override @Ensures({"result.isActiveProb >= 0.0", "result.isActiveProb <= 1.0"}) - public ActivityProfileResult isActive( final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context ) { + public ActivityProfileState isActive( final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context ) { if( UG_engine.getUAC().GenotypingMode == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ) { for( final VariantContext vc : tracker.getValues(UG_engine.getUAC().alleles, ref.getLocus()) ) { @@ -391,15 +390,15 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } } if( tracker.getValues(UG_engine.getUAC().alleles, ref.getLocus()).size() > 0 ) { - return new ActivityProfileResult(ref.getLocus(), 1.0); + return new ActivityProfileState(ref.getLocus(), 1.0); } } if( USE_ALLELES_TRIGGER ) { - return new ActivityProfileResult( ref.getLocus(), tracker.getValues(UG_engine.getUAC().alleles, ref.getLocus()).size() > 0 ? 1.0 : 0.0 ); + return new ActivityProfileState( ref.getLocus(), tracker.getValues(UG_engine.getUAC().alleles, ref.getLocus()).size() > 0 ? 1.0 : 0.0 ); } - if( context == null ) { return new ActivityProfileResult(ref.getLocus(), 0.0); } + if( context == null ) { return new ActivityProfileState(ref.getLocus(), 0.0); } final List noCall = new ArrayList(); // used to noCall all genotypes until the exact model is applied noCall.add(Allele.NO_CALL); @@ -436,7 +435,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem final VariantCallContext vcOut = UG_engine_simple_genotyper.calculateGenotypes(new VariantContextBuilder("HCisActive!", context.getContig(), context.getLocation().getStart(), context.getLocation().getStop(), alleles).genotypes(genotypes).make(), GenotypeLikelihoodsCalculationModel.Model.INDEL); final double isActiveProb = vcOut == null ? 0.0 : QualityUtils.qualToProb( vcOut.getPhredScaledQual() ); - return new ActivityProfileResult( ref.getLocus(), isActiveProb, averageHQSoftClips.mean() > 6.0 ? ActivityProfileResult.ActivityProfileResultState.HIGH_QUALITY_SOFT_CLIPS : ActivityProfileResult.ActivityProfileResultState.NONE, averageHQSoftClips.mean() ); + return new ActivityProfileState( ref.getLocus(), isActiveProb, averageHQSoftClips.mean() > 6.0 ? ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS : ActivityProfileState.Type.NONE, averageHQSoftClips.mean() ); } //--------------------------------------------------------------------------------------------------------------- diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index a7e4d7649..de0bfd1f1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -41,7 +41,8 @@ import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActivityProfile; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; +import org.broadinstitute.sting.utils.activeregion.BandPassActivityProfile; import org.broadinstitute.sting.utils.progressmeter.ProgressMeter; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -71,6 +72,7 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine myReads = new LinkedList(); private GenomeLoc spanOfLastReadSeen = null; + @Override + public void initialize(GenomeAnalysisEngine engine, Walker walker, ProgressMeter progressMeter) { + super.initialize(engine, walker, progressMeter); + + final ActiveRegionWalker arWalker = (ActiveRegionWalker)walker; + if ( arWalker.wantsExtendedReads() && ! arWalker.wantsNonPrimaryReads() ) { + throw new IllegalArgumentException("Active region walker " + arWalker + " requested extended events but not " + + "non-primary reads, an inconsistent state. Please modify the walker"); + } + + activeRegionExtension = walker.getClass().getAnnotation(ActiveRegionExtension.class).extension(); + maxRegionSize = walker.getClass().getAnnotation(ActiveRegionExtension.class).maxRegion(); + walkerHasPresetRegions = arWalker.hasPresetActiveRegions(); + } + + // ------------------------------------------------------------------------------------- + // + // Utility functions + // + // ------------------------------------------------------------------------------------- + protected int getActiveRegionExtension() { return activeRegionExtension; } @@ -97,19 +120,6 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine walker, + final LocusShardDataProvider dataProvider, + final LocusView locusView) { + if ( WalkerManager.getWalkerDataSource(walker) != DataSource.REFERENCE_ORDERED_DATA ) + return new ManagingReferenceOrderedView( dataProvider ); + else + return (RodLocusView)locusView; + } + + + // ------------------------------------------------------------------------------------- + // + // Working with ActivityProfiles and Active Regions + // + // ------------------------------------------------------------------------------------- + /** * Take the individual isActive calls and integrate them into contiguous active regions and * add these blocks of work to the work queue @@ -133,28 +159,26 @@ public class TraverseActiveRegions extends TraversalEngine walker, + protected final ActivityProfileState walkerActiveProb(final ActiveRegionWalker walker, final RefMetaDataTracker tracker, final ReferenceContext refContext, final AlignmentContext locus, final GenomeLoc location) { - if ( walker.hasPresetActiveRegions() ) { - return new ActivityProfileResult(location, walker.presetActiveRegions.overlaps(location) ? 1.0 : 0.0); + if ( walkerHasPresetRegions ) { + return new ActivityProfileState(location, walker.presetActiveRegions.overlaps(location) ? 1.0 : 0.0); } else { return walker.isActive( tracker, refContext, locus ); } } - protected ReferenceOrderedView getReferenceOrderedView(final ActiveRegionWalker walker, - final LocusShardDataProvider dataProvider, - final LocusView locusView) { - if ( WalkerManager.getWalkerDataSource(walker) != DataSource.REFERENCE_ORDERED_DATA ) - return new ManagingReferenceOrderedView( dataProvider ); + private ActivityProfile makeNewActivityProfile() { + if ( walkerHasPresetRegions ) + return new ActivityProfile(engine.getGenomeLocParser()); else - return (RodLocusView)locusView; + return new BandPassActivityProfile(engine.getGenomeLocParser()); } /** @@ -171,6 +195,12 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine activeRegions = new LinkedList(); - ActivityProfile profile = new ActivityProfile(engine.getGenomeLocParser(), walker.hasPresetActiveRegions() ); + ActivityProfile profile = makeNewActivityProfile(); ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); @@ -245,9 +269,8 @@ public class TraverseActiveRegions extends TraversalEngine reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); for( final GATKSAMRecord read : reads ) { if ( appearedInLastShard(locOfLastReadAtTraversalStart, read) ) { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index f937c2458..820100f7f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -40,7 +40,7 @@ import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.GenomeLocSortedSet; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import org.broadinstitute.sting.utils.interval.IntervalMergingRule; import org.broadinstitute.sting.utils.interval.IntervalSetRule; import org.broadinstitute.sting.utils.interval.IntervalUtils; @@ -114,7 +114,7 @@ public abstract class ActiveRegionWalker extends Walker= 0.0", "result.isActiveProb <= 1.0"}) - public abstract ActivityProfileResult isActive(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context); + public abstract ActivityProfileState isActive(final RefMetaDataTracker tracker, final ReferenceContext ref, final AlignmentContext context); // Map over the ActiveRegion public abstract MapType map(final ActiveRegion activeRegion, final RefMetaDataTracker metaDataTracker); diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 909d99424..fd05ddd7b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -1,35 +1,34 @@ /* -* 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. -*/ + * 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.utils.activeregion; +import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.commons.lang.ArrayUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.MathUtils; import java.util.ArrayList; import java.util.Collections; @@ -43,36 +42,37 @@ import java.util.List; * @since Date created */ public class ActivityProfile { - final GenomeLocParser parser; - final boolean presetRegions; - GenomeLoc regionStartLoc = null; - GenomeLoc regionStopLoc = null; - final List isActiveList; - private static final int FILTER_SIZE = 80; - private static final double[] GaussianKernel; + private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author - static { - GaussianKernel = new double[2*FILTER_SIZE + 1]; - for( int iii = 0; iii < 2*FILTER_SIZE + 1; iii++ ) { - GaussianKernel[iii] = MathUtils.NormalDistribution(FILTER_SIZE, 55.0, iii); - } + protected final List isActiveList; + protected final GenomeLocParser parser; + + protected GenomeLoc regionStartLoc = null; + protected GenomeLoc regionStopLoc = null; + + public ActivityProfile(final GenomeLocParser parser) { + this(parser, new ArrayList(), null); } - // todo -- add upfront the start and stop of the intervals - // todo -- check that no regions are unexpectedly missing - // todo -- add unit tests - // TODO -- own preset regions - public ActivityProfile(final GenomeLocParser parser, final boolean presetRegions) { - this(parser, presetRegions, new ArrayList(), null); - } - - protected ActivityProfile(final GenomeLocParser parser, final boolean presetRegions, final List isActiveList, final GenomeLoc regionStartLoc) { + protected ActivityProfile(final GenomeLocParser parser, final List isActiveList, final GenomeLoc regionStartLoc) { this.parser = parser; - this.presetRegions = presetRegions; this.isActiveList = isActiveList; this.regionStartLoc = regionStartLoc; } + /** + * Create a profile of the same class as this object containing just the provided isActiveList + * + * Used by clients to create derived activity profiles (such as ones without the starting X + * sites because they've been removed in an ActiveRegion) of the same class. + * + * @param isActiveList the active results list to use in the derived instance + * @return a freshly allocated data set + */ + protected ActivityProfile createDerivedProfile(final List isActiveList) { + return new ActivityProfile(parser, isActiveList, regionStartLoc); + } + @Override public String toString() { return "ActivityProfile{" + @@ -82,14 +82,14 @@ public class ActivityProfile { } /** - * Add the next ActivityProfileResult to this profile. + * Add the next ActivityProfileState to this profile. * * Must be contiguous with the previously added result, or an IllegalArgumentException will be thrown * - * @param result a well-formed ActivityProfileResult result to incorporate into this profile + * @param result a well-formed ActivityProfileState result to incorporate into this profile */ @Requires("result != null") - public void add(final ActivityProfileResult result) { + public void add(final ActivityProfileState result) { final GenomeLoc loc = result.getLoc(); if ( regionStartLoc == null ) { @@ -104,31 +104,67 @@ public class ActivityProfile { isActiveList.add(result); } + /** + * How many profile results are in this profile? + * @return the number of profile results + */ + @Ensures("result >= 0") public int size() { return isActiveList.size(); } + /** + * Is this profile empty? + * @return true if the profile is empty + */ + @Ensures("isEmpty() == (size() == 0)") public boolean isEmpty() { return isActiveList.isEmpty(); } - public boolean hasPresetRegions() { - return presetRegions; + /** + * Get the list of active profile results in this object + * @return a non-null, ordered list of active profile results + */ + @Ensures("result != null") + protected List getActiveList() { + return isActiveList; } /** - * Band pass this ActivityProfile, producing a new profile that's band pass filtered - * @return a new ActivityProfile that's the band-pass filtered version of this profile + * Finalize the probabilities in this activity profile, preparing it for a future + * call to createActiveRegions. This function returns a new profile with cleaned + * up activity estimates. + * + * This code looks at the current list of states, cleans them up, and then returns + * a newly allocated ActivityProfile + * + * @return a newly allocated ActivityProfile based on the current state of this + * profile, but that has been "finalized" as required by the profile implementation */ - public ActivityProfile bandPassFilter() { - final double[] activeProbArray = new double[isActiveList.size()]; + public ActivityProfile finalizeProfile() { int iii = 0; - for( final ActivityProfileResult result : isActiveList ) { + for( final double prob : finalizeProbabilities() ) { + final ActivityProfileState result = isActiveList.get(iii++); + result.isActiveProb = prob; + result.resultState = ActivityProfileState.Type.NONE; + result.resultValue = null; + } + + return createDerivedProfile(isActiveList); + } + + public double[] finalizeProbabilities() { + final double[] activeProbArray = new double[isActiveList.size()]; + + int iii = 0; + for( final ActivityProfileState result : isActiveList ) { activeProbArray[iii++] = result.isActiveProb; } + iii = 0; - for( final ActivityProfileResult result : isActiveList ) { - if( result.resultState.equals(ActivityProfileResult.ActivityProfileResultState.HIGH_QUALITY_SOFT_CLIPS) ) { // special code to deal with the problem that high quality soft clipped bases aren't added to pileups + for( final ActivityProfileState result : isActiveList ) { + if( result.resultState.equals(ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS) ) { // special code to deal with the problem that high quality soft clipped bases aren't added to pileups final int numHQClips = result.resultValue.intValue(); for( int jjj = Math.max(0, iii - numHQClips); jjj < Math.min(activeProbArray.length, iii+numHQClips); jjj++ ) { activeProbArray[jjj] = Math.max(activeProbArray[jjj], activeProbArray[iii]); @@ -137,29 +173,7 @@ public class ActivityProfile { iii++; } - final double[] filteredProbArray; - if( !presetRegions ) { - // if we aren't using preset regions, actually apply the band pass filter for activeProbArray into filteredProbArray - filteredProbArray = new double[activeProbArray.length]; - for( iii = 0; iii < activeProbArray.length; iii++ ) { - final double[] kernel = ArrayUtils.subarray(GaussianKernel, Math.max(FILTER_SIZE-iii, 0), Math.min(GaussianKernel.length,FILTER_SIZE + activeProbArray.length - iii)); - final double[] activeProbSubArray = ArrayUtils.subarray(activeProbArray, Math.max(0,iii - FILTER_SIZE), Math.min(activeProbArray.length,iii + FILTER_SIZE + 1)); - filteredProbArray[iii] = MathUtils.dotProduct(activeProbSubArray, kernel); - } - } else { - // otherwise we simply use the activeProbArray directly - filteredProbArray = activeProbArray; - } - - iii = 0; - for( final double prob : filteredProbArray ) { - final ActivityProfileResult result = isActiveList.get(iii++); - result.isActiveProb = prob; - result.resultState = ActivityProfileResult.ActivityProfileResultState.NONE; - result.resultValue = null; - } - - return new ActivityProfile(parser, presetRegions, isActiveList, regionStartLoc); + return activeProbArray; } /** @@ -168,7 +182,6 @@ public class ActivityProfile { * @return the list of active regions */ public List createActiveRegions( final int activeRegionExtension, final int maxRegionSize ) { - final double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author final ArrayList returnList = new ArrayList(); if( isActiveList.size() == 0 ) { @@ -203,11 +216,11 @@ public class ActivityProfile { * @param activeRegionExtension the amount of margin overlap in the active region * @return a fully initialized ActiveRegion with the above properties */ - private final List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize) { + private List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize) { return createActiveRegion(isActive, curStart, curEnd, activeRegionExtension, maxRegionSize, new ArrayList()); } - private final List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize, final List returnList) { + private List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize, final List returnList) { if( !isActive || curEnd - curStart < maxRegionSize ) { final GenomeLoc loc = parser.createGenomeLoc(regionStartLoc.getContig(), regionStartLoc.getStart() + curStart, regionStartLoc.getStart() + curEnd); returnList.add(new ActiveRegion(loc, isActive, parser, activeRegionExtension)); diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileResult.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java similarity index 77% rename from public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileResult.java rename to public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java index bf2636465..38e89b605 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileResult.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java @@ -34,40 +34,40 @@ import org.broadinstitute.sting.utils.GenomeLoc; * User: rpoplin * Date: 7/27/12 */ -public class ActivityProfileResult { +public class ActivityProfileState { private GenomeLoc loc; public double isActiveProb; - public ActivityProfileResultState resultState; + public Type resultState; public Number resultValue; - public enum ActivityProfileResultState { + public enum Type { NONE, HIGH_QUALITY_SOFT_CLIPS } /** - * Create a new ActivityProfileResult at loc with probability of being active of isActiveProb + * Create a new ActivityProfileState at loc with probability of being active of isActiveProb * * @param loc the position of the result profile (for debugging purposes) * @param isActiveProb the probability of being active (between 0 and 1) */ @Requires({"loc != null", "isActiveProb >= 0.0 && isActiveProb <= 1.0"}) - public ActivityProfileResult( final GenomeLoc loc, final double isActiveProb ) { - this(loc, isActiveProb, ActivityProfileResultState.NONE, null); + public ActivityProfileState(final GenomeLoc loc, final double isActiveProb) { + this(loc, isActiveProb, Type.NONE, null); } /** - * Create a new ActivityProfileResult at loc with probability of being active of isActiveProb that maintains some + * Create a new ActivityProfileState at loc with probability of being active of isActiveProb that maintains some * information about the result state and value (TODO RYAN -- what do these mean?) * * @param loc the position of the result profile (for debugging purposes) * @param isActiveProb the probability of being active (between 0 and 1) */ @Requires({"loc != null", "isActiveProb >= 0.0 && isActiveProb <= 1.0"}) - public ActivityProfileResult( final GenomeLoc loc, final double isActiveProb, final ActivityProfileResultState resultState, final Number resultValue ) { + public ActivityProfileState(final GenomeLoc loc, final double isActiveProb, final Type resultState, final Number resultValue) { // make sure the location of that activity profile is 1 if ( loc.size() != 1 ) - throw new IllegalArgumentException("Location for an ActivityProfileResult must have to size 1 bp but saw " + loc); + throw new IllegalArgumentException("Location for an ActivityProfileState must have to size 1 bp but saw " + loc); this.loc = loc; this.isActiveProb = isActiveProb; @@ -76,7 +76,7 @@ public class ActivityProfileResult { } /** - * Get the genome loc associated with the ActivityProfileResult + * Get the genome loc associated with the ActivityProfileState * @return the location of this result */ @Ensures("result != null") @@ -86,7 +86,7 @@ public class ActivityProfileResult { @Override public String toString() { - return "ActivityProfileResult{" + + return "ActivityProfileState{" + "loc=" + loc + ", isActiveProb=" + isActiveProb + ", resultState=" + resultState + diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java new file mode 100644 index 000000000..cef700419 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -0,0 +1,84 @@ +/* +* 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.utils.activeregion; + +import org.apache.commons.lang.ArrayUtils; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.MathUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author Mark DePristo + * @since 2011 + */ +public class BandPassActivityProfile extends ActivityProfile { + private static final int FILTER_SIZE = 80; + private static final double[] GaussianKernel; + + static { + GaussianKernel = new double[2*FILTER_SIZE + 1]; + for( int iii = 0; iii < 2*FILTER_SIZE + 1; iii++ ) { + GaussianKernel[iii] = MathUtils.NormalDistribution(FILTER_SIZE, 55.0, iii); + } + } + + public BandPassActivityProfile(final GenomeLocParser parser) { + this(parser, new ArrayList(), null); + } + + public BandPassActivityProfile(final GenomeLocParser parser, final List isActiveList, final GenomeLoc regionStartLoc) { + super(parser, isActiveList, regionStartLoc); + } + + @Override + protected ActivityProfile createDerivedProfile(List isActiveList) { + return new BandPassActivityProfile(parser, isActiveList, regionStartLoc); + } + + /** + * Band pass the probabilities in the ActivityProfile, producing a new profile that's band pass filtered + * @return a new double[] that's the band-pass filtered version of this profile + */ + @Override + public double[] finalizeProbabilities() { + final double[] activeProbArray = super.finalizeProbabilities(); + final double[] bandPassProbArray = new double[activeProbArray.length]; + + // apply the band pass filter for activeProbArray into filteredProbArray + for( int iii = 0; iii < activeProbArray.length; iii++ ) { + final double[] kernel = ArrayUtils.subarray(GaussianKernel, Math.max(FILTER_SIZE-iii, 0), Math.min(GaussianKernel.length,FILTER_SIZE + activeProbArray.length - iii)); + final double[] activeProbSubArray = ArrayUtils.subarray(activeProbArray, Math.max(0,iii - FILTER_SIZE), Math.min(activeProbArray.length,iii + FILTER_SIZE + 1)); + bandPassProbArray[iii] = MathUtils.dotProduct(activeProbSubArray, kernel); + } + + return bandPassProbArray; + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java index 76be54d72..f09a4b3e8 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocSortedSet; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileResult; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import java.util.*; @@ -80,10 +80,10 @@ class DummyActiveRegionWalker extends ActiveRegionWalker { } @Override - public ActivityProfileResult isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + public ActivityProfileState isActive(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { isActiveCalls.add(ref.getLocus()); final double p = activeRegions == null || activeRegions.overlaps(ref.getLocus()) ? prob : 0.0; - return new ActivityProfileResult(ref.getLocus(), p); + return new ActivityProfileState(ref.getLocus(), p); } @Override diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java similarity index 79% rename from public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java rename to public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java index d131666fa..019cf82da 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileResultTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java @@ -25,23 +25,17 @@ package org.broadinstitute.sting.utils.activeregion; -import net.sf.picard.reference.ReferenceSequenceFile; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.GenomeLocSortedSet; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.broadinstitute.sting.utils.sam.ArtificialBAMBuilder; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; -import java.util.EnumSet; import java.util.LinkedList; import java.util.List; @@ -52,7 +46,7 @@ import java.util.List; * Time: 2:30 PM * To change this template use File | Settings | File Templates. */ -public class ActivityProfileResultTest { +public class ActivityProfileStateUnitTest { private GenomeLocParser genomeLocParser; @BeforeClass @@ -71,7 +65,7 @@ public class ActivityProfileResultTest { genomeLocParser.createGenomeLoc(chr, 10, 10), genomeLocParser.createGenomeLoc(chr, 100, 100) )) { for ( final double prob : Arrays.asList(0.0, 0.5, 1.0) ) { - for ( final ActivityProfileResult.ActivityProfileResultState state : ActivityProfileResult.ActivityProfileResultState.values() ) { + for ( final ActivityProfileState.Type state : ActivityProfileState.Type.values() ) { for ( final Number value : Arrays.asList(1, 2, 4) ) { tests.add(new Object[]{ loc, prob, state, value}); } @@ -84,15 +78,15 @@ public class ActivityProfileResultTest { } @Test(dataProvider = "ActiveProfileResultProvider") - public void testActiveProfileResultProvider(GenomeLoc loc, final double prob, ActivityProfileResult.ActivityProfileResultState maybeState, final Number maybeNumber) { - final ActivityProfileResult apr = maybeState == null - ? new ActivityProfileResult(loc, prob) - : new ActivityProfileResult(loc, prob, maybeState, maybeNumber); + public void testActiveProfileResultProvider(GenomeLoc loc, final double prob, ActivityProfileState.Type maybeState, final Number maybeNumber) { + final ActivityProfileState apr = maybeState == null + ? new ActivityProfileState(loc, prob) + : new ActivityProfileState(loc, prob, maybeState, maybeNumber); Assert.assertEquals(apr.getLoc(), loc); Assert.assertNotNull(apr.toString()); Assert.assertEquals(apr.isActiveProb, prob); - Assert.assertEquals(apr.resultState, maybeState == null ? ActivityProfileResult.ActivityProfileResultState.NONE : maybeState); + Assert.assertEquals(apr.resultState, maybeState == null ? ActivityProfileState.Type.NONE : maybeState); Assert.assertEquals(apr.resultValue, maybeState == null ? null : maybeNumber); } } diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index ff27037d3..430e0b5c6 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -42,9 +42,7 @@ import org.testng.annotations.Test; import java.io.File; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class ActivityProfileUnitTest extends BaseTest { @@ -70,23 +68,26 @@ public class ActivityProfileUnitTest extends BaseTest { List expectedRegions; int extension = 0; GenomeLoc regionStart = startLoc; + final ProfileType type; - public BasicActivityProfileTestProvider(final List probs, final List expectedRegions) { - super(BasicActivityProfileTestProvider.class); - this.probs = probs; - this.expectedRegions = expectedRegions; - setName(getName()); - } - - public BasicActivityProfileTestProvider(final List probs, boolean startActive, int ... startsAndStops) { + public BasicActivityProfileTestProvider(final ProfileType type, final List probs, boolean startActive, int ... startsAndStops) { super(BasicActivityProfileTestProvider.class); + this.type = type; this.probs = probs; this.expectedRegions = toRegions(startActive, startsAndStops); setName(getName()); } private String getName() { - return String.format("probs=%s expectedRegions=%s", Utils.join(",", probs), Utils.join(",", expectedRegions)); + return String.format("type=%s probs=%s expectedRegions=%s", type, Utils.join(",", probs), Utils.join(",", expectedRegions)); + } + + public ActivityProfile makeProfile() { + switch ( type ) { + case Base: return new ActivityProfile(genomeLocParser); + case BandPass: return new BandPassActivityProfile(genomeLocParser); + default: throw new IllegalStateException(type.toString()); + } } private List toRegions(boolean isActive, int[] startsAndStops) { @@ -103,27 +104,36 @@ public class ActivityProfileUnitTest extends BaseTest { } } + private enum ProfileType { + Base, BandPass + } + @DataProvider(name = "BasicActivityProfileTestProvider") public Object[][] makeQualIntervalTestProvider() { - new BasicActivityProfileTestProvider(Arrays.asList(1.0), true, 0, 1); - new BasicActivityProfileTestProvider(Arrays.asList(1.0, 0.0), true, 0, 1, 2); - new BasicActivityProfileTestProvider(Arrays.asList(0.0, 1.0), false, 0, 1, 2); - new BasicActivityProfileTestProvider(Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); - new BasicActivityProfileTestProvider(Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); + for ( final ProfileType type : ProfileType.values() ) { + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); + } return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class); } @Test(dataProvider = "BasicActivityProfileTestProvider") public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) { - ActivityProfile profile = new ActivityProfile(genomeLocParser, false); + ActivityProfile profile = cfg.makeProfile(); + + Assert.assertTrue(profile.isEmpty()); Assert.assertEquals(profile.parser, genomeLocParser); for ( int i = 0; i < cfg.probs.size(); i++ ) { double p = cfg.probs.get(i); GenomeLoc loc = genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart() + i, cfg.regionStart.getStart() + i); - profile.add(new ActivityProfileResult(loc, p)); + profile.add(new ActivityProfileState(loc, p)); + Assert.assertFalse(profile.isEmpty()); } Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() )); @@ -131,6 +141,11 @@ public class ActivityProfileUnitTest extends BaseTest { assertProbsAreEqual(profile.isActiveList, cfg.probs); assertRegionsAreEqual(profile.createActiveRegions(0, 100), cfg.expectedRegions); + + Assert.assertEquals(profile.createDerivedProfile(profile.isActiveList).getClass(), profile.getClass()); + + final List empty = new LinkedList(); + Assert.assertEquals(profile.createDerivedProfile(empty).size(), 0); } private void assertRegionsAreEqual(List actual, List expected) { @@ -140,7 +155,7 @@ public class ActivityProfileUnitTest extends BaseTest { } } - private void assertProbsAreEqual(List actual, List expected) { + private void assertProbsAreEqual(List actual, List expected) { Assert.assertEquals(actual.size(), expected.size()); for ( int i = 0; i < actual.size(); i++ ) { Assert.assertEquals(actual.get(i).isActiveProb, expected.get(i)); From e050f649fdb838338d76a242f9e62d7ad1e19ebf Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 18 Jan 2013 10:18:04 -0500 Subject: [PATCH 057/188] IncrementalActivityProfile, complete with extensive unit tests -- This is an activity profile compatible with fetching its implied active regions incrementally, as activity profile states are added --- .../utils/activeregion/ActivityProfile.java | 2 +- .../activeregion/ActivityProfileState.java | 12 +- .../IncrementalActivityProfile.java | 373 ++++++++++++++++++ .../IncrementalActivityProfileUnitTest.java | 350 ++++++++++++++++ 4 files changed, 735 insertions(+), 2 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java create mode 100644 public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index fd05ddd7b..8d6012fac 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -61,7 +61,7 @@ public class ActivityProfile { } /** - * Create a profile of the same class as this object containing just the provided isActiveList + * Create a profile of the same class as this object containing just the provided stateList * * Used by clients to create derived activity profiles (such as ones without the starting X * sites because they've been removed in an ActiveRegion) of the same class. diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java index 38e89b605..df21672a9 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; * Date: 7/27/12 */ public class ActivityProfileState { - private GenomeLoc loc; + final private GenomeLoc loc; public double isActiveProb; public Type resultState; public Number resultValue; @@ -75,6 +75,16 @@ public class ActivityProfileState { this.resultValue = resultValue; } + /** + * The offset of state w.r.t. our current region's start location + * @param regionStartLoc the start of the region, as a genome loc + * @return the position of this profile relative to the start of this region + */ + public int getOffset(final GenomeLoc regionStartLoc) { + return getLoc().getStart() - regionStartLoc.getStart(); + } + + /** * Get the genome loc associated with the ActivityProfileState * @return the location of this result diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java new file mode 100644 index 000000000..e71f177f4 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java @@ -0,0 +1,373 @@ +/* + * 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.utils.activeregion; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; + +import java.util.*; + +/** + * Class holding information about per-base activity scores for the + * active region traversal + * + * @author Mark DePristo + * @since Date created + */ +public class IncrementalActivityProfile { + private final static int MAX_PROB_PROPOGATION_DISTANCE = 10; + private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author + + protected final List stateList; + protected final GenomeLocParser parser; + + protected GenomeLoc regionStartLoc = null; + protected GenomeLoc regionStopLoc = null; + + /** + * Create a new empty IncrementalActivityProfile + * @param parser the parser we can use to create genome locs + */ + public IncrementalActivityProfile(final GenomeLocParser parser) { + this(parser, new ArrayList(), null); + } + + /** + * Create a new IncrementalActivityProfile using state list (not copied) and starting at regionStartLoc + * @param parser the parser we can use to create genome locs + */ + @Deprecated + protected IncrementalActivityProfile(final GenomeLocParser parser, final List stateList, final GenomeLoc regionStartLoc) { + this.parser = parser; + this.stateList = stateList; + this.regionStartLoc = regionStartLoc; + } + + /** + * Create a profile of the same class as this object containing just the provided stateList + * + * Used by clients to create derived activity profiles (such as ones without the starting X + * sites because they've been removed in an ActiveRegion) of the same class. + * + * @param isActiveList the active results list to use in the derived instance + * @return a freshly allocated data set + */ + @Deprecated + protected IncrementalActivityProfile createDerivedProfile(final List isActiveList) { + return new IncrementalActivityProfile(parser, isActiveList, regionStartLoc); + } + + @Override + public String toString() { + return "ActivityProfile{" + + "start=" + regionStartLoc + + ", stop=" + regionStopLoc + + '}'; + } + + /** + * How far away can probability mass be moved around in this profile? + * + * This distance puts an upper limit on how far, in bp, we will ever propogate probability max around + * when adding a new ActivityProfileState. For example, if the value of this function is + * 10, and you are looking at a state at bp 5, and we know that no states beyond 5 + 10 will have + * their probability propograted back to that state. + * + * @return a positive integer distance in bp + */ + @Ensures("result >= 0") + public int getMaxProbPropogationDistance() { + return MAX_PROB_PROPOGATION_DISTANCE; + } + + /** + * How many profile results are in this profile? + * @return the number of profile results + */ + @Ensures("result >= 0") + public int size() { + return stateList.size(); + } + + /** + * Is this profile empty? + * @return true if the profile is empty + */ + @Ensures("isEmpty() == (size() == 0)") + public boolean isEmpty() { + return stateList.isEmpty(); + } + + /** + * Get the list of active profile results in this object + * @return a non-null, ordered list of active profile results + */ + @Ensures("result != null") + protected List getStateList() { + return stateList; + } + + /** + * Helper function that gets the genome loc for a site offset from relativeLoc, protecting ourselves from + * falling off the edge of the contig. + * + * @param relativeLoc the location offset is relative to + * @param offset the offset from relativeLoc where we'd like to create a GenomeLoc + * @return a genome loc with relativeLoc.start + offset, if this is on the contig, null otherwise + */ + @Requires("relativeLoc != null") + protected GenomeLoc getLocForOffset(final GenomeLoc relativeLoc, final int offset) { + final int start = relativeLoc.getStart() + offset; + if ( start < 0 || start > getCurrentContigLength() ) { + return null; + } else { + return parser.createGenomeLoc(regionStartLoc.getContig(), start); + } + } + + /** + * Get the length of the current contig + * @return the length in bp + */ + @Requires("regionStartLoc != null") + @Ensures("result > 0") + private int getCurrentContigLength() { + // TODO -- fix performance problem with getContigInfo + return parser.getContigInfo(regionStartLoc.getContig()).getSequenceLength(); + } + + // -------------------------------------------------------------------------------- + // + // routines to add states to a profile + // + // -------------------------------------------------------------------------------- + + /** + * Add the next ActivityProfileState to this profile. + * + * Must be contiguous with the previously added result, or an IllegalArgumentException will be thrown + * + * @param state a well-formed ActivityProfileState result to incorporate into this profile + */ + @Requires("state != null") + public void add(final ActivityProfileState state) { + final GenomeLoc loc = state.getLoc(); + + if ( regionStartLoc == null ) { + regionStartLoc = loc; + regionStopLoc = loc; + } else { + // TODO -- need to figure out where to add loc as the regions will be popping off the front + if ( regionStopLoc.getStart() != loc.getStart() - 1 ) + throw new IllegalArgumentException("Bad add call to ActivityProfile: loc " + loc + " not immediate after last loc " + regionStopLoc ); + regionStopLoc = loc; + } + + final Collection processedStates = processState(state); + for ( final ActivityProfileState processedState : processedStates ) { + incorporateSingleState(processedState); + } + } + + /** + * Incorporate a single activity profile state into the current list of states + * + * If state's position occurs immediately after the last position in this profile, then + * the state is appended to the state list. If it's within the existing states list, + * the prob of stateToAdd is added to its corresponding state in the list. If the + * position would be before the start of this profile, stateToAdd is simply ignored. + * + * @param stateToAdd the state we want to add to the states list + */ + @Requires("stateToAdd != null") + private void incorporateSingleState(final ActivityProfileState stateToAdd) { + final int position = stateToAdd.getOffset(regionStartLoc); + + if ( position > size() ) + // should we allow this? probably not + throw new IllegalArgumentException("Must add state contiguous to existing states"); + + if ( position >= 0 ) { + // ignore states starting before this regions start + if ( position < size() ) { + stateList.get(position).isActiveProb += stateToAdd.isActiveProb; + } else { + if ( position != size() ) throw new IllegalStateException("position == size but it wasn't"); + stateList.add(stateToAdd); + } + } + } + + /** + * Process justAddedState, returning a collection of derived states that actually be added to the stateList + * + * The purpose of this function is to transform justAddedStates, if needed, into a series of atomic states + * that we actually want to track. For example, if state is for soft clips, we transform that single + * state into a list of states that surround the state up to the distance of the soft clip. + * + * Can be overridden by subclasses to transform states in any way + * + * There's no particular contract for the output states, except that they can never refer to states + * beyond the current end of the stateList unless the explictly include preceding states before + * the reference. So for example if the current state list is [1, 2, 3] this function could return + * [1,2,3,4,5] but not [1,2,3,5]. + * + * @param justAddedState the state our client provided to use to add to the list + * @return a list of derived states that should actually be added to this profile's state list + */ + protected Collection processState(final ActivityProfileState justAddedState) { + if ( justAddedState.resultState.equals(ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS) ) { + // special code to deal with the problem that high quality soft clipped bases aren't added to pileups + final List states = new LinkedList(); + final int numHQClips = justAddedState.resultValue.intValue(); + for( int jjj = - numHQClips; jjj <= numHQClips; jjj++ ) { + final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj); + if ( loc != null ) + states.add(new ActivityProfileState(loc, justAddedState.isActiveProb)); + } + + return states; + } else { + return Collections.singletonList(justAddedState); + } + } + + // -------------------------------------------------------------------------------- + // + // routines to get active regions from the profile + // + // -------------------------------------------------------------------------------- + + /** + * Get the next completed active regions from this profile, and remove all states supporting them from this profile + * + * Takes the current profile and finds all of the active / inactive from the start of the profile that are + * ready. By ready we mean unable to have their probability modified any longer by future additions to the + * profile. The regions that are popped off the profile take their states with them, so the start of this + * profile will always be after the end of the last region returned here. + * + * The regions are returned sorted by genomic position. + * + * This function may not return anything in the list, if no regions are ready + * + * No returned region will be larger than maxRegionSize. + * + * @param activeRegionExtension the extension value to provide to the constructed regions + * @param maxRegionSize the maximize size of the returned region + * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the + * stateList. Used to close out the active region when we've hit some kind of end (such + * as the end of the contig) + * @return a non-null list of active regions + */ + @Ensures("result != null") + public List popReadyActiveRegions(final int activeRegionExtension, final int maxRegionSize, final boolean forceConversion) { + if ( activeRegionExtension < 0 ) throw new IllegalArgumentException("activeRegionExtension must be >= 0 but got " + activeRegionExtension); + if ( maxRegionSize < 1 ) throw new IllegalArgumentException("maxRegionSize must be >= 1 but got " + maxRegionSize); + + final LinkedList regions = new LinkedList(); + + while ( true ) { + final ActiveRegion nextRegion = popNextReadyActiveRegion(activeRegionExtension, maxRegionSize, forceConversion); + if ( nextRegion == null ) + return regions; + else { + regions.add(nextRegion); + } + } + } + + /** + * Helper function for popReadyActiveRegions that pops the first ready region off the front of this profile + * + * If a region is returned, modifies the state of this profile so that states used to make the region are + * no longer part of the profile. Associated information (like the region start position) of this profile + * are also updated. + * + * @param activeRegionExtension the extension value to provide to the constructed regions + * @param maxRegionSize the maximize size of the returned region + * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the + * stateList. Used to close out the active region when we've hit some kind of end (such + * as the end of the contig) + * @return a fully formed active region, or null if none can be made + */ + private ActiveRegion popNextReadyActiveRegion(final int activeRegionExtension, final int maxRegionSize, final boolean forceConversion) { + if ( stateList.isEmpty() ) + return null; + + final ActivityProfileState first = stateList.get(0); + final boolean isActiveRegion = first.isActiveProb > ACTIVE_PROB_THRESHOLD; + final int offsetOfNextRegionEnd = findEndOfRegion(isActiveRegion, maxRegionSize, forceConversion); + if ( offsetOfNextRegionEnd == -1 ) + // couldn't find a valid ending offset, so we return null + return null; + + // we need to create the active region, and clip out the states we're extracting from this profile + stateList.subList(0, offsetOfNextRegionEnd + 1).clear(); + + // update the start and stop locations as necessary + if ( stateList.isEmpty() ) { + regionStartLoc = regionStopLoc = null; + } else { + regionStartLoc = stateList.get(0).getLoc(); + } + final GenomeLoc regionLoc = parser.createGenomeLoc(first.getLoc().getContig(), first.getLoc().getStart(), first.getLoc().getStart() + offsetOfNextRegionEnd); + return new ActiveRegion(regionLoc, isActiveRegion, parser, activeRegionExtension); + } + + /** + * Find the end of the current region, returning the index into the element isActive element, or -1 if the region isn't done + * + * The current region is defined from the start of the stateList, looking for elements that have the same isActiveRegion + * flag (i.e., if isActiveRegion is true we are looking for states with isActiveProb > threshold, or alternatively + * for states < threshold). The maximize size of the returned region is maxRegionSize. If forceConversion is + * true, then we'll return the region end even if this isn't safely beyond the max prob propogation distance. + * + * @param isActiveRegion is the region we're looking for an active region or inactive region? + * @param maxRegionSize the maximize size of the returned region + * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the + * stateList. Used to close out the active region when we've hit some kind of end (such + * as the end of the contig) + * @return the index into stateList of the last element of this region, or -1 if it cannot be found + */ + @Ensures({ + "result >= -1", + "result == -1 || result < maxRegionSize", + "! (result == -1 && forceConversion)"}) + private int findEndOfRegion(final boolean isActiveRegion, final int maxRegionSize, final boolean forceConversion) { + int i = 0; + while ( i < stateList.size() && i < maxRegionSize ) { + if ( stateList.get(i).isActiveProb > ACTIVE_PROB_THRESHOLD != isActiveRegion ) { + break; + } + i++; + } + + // we're one past the end, so i must be decremented + return forceConversion || i + getMaxProbPropogationDistance() < stateList.size() ? i - 1 : -1; + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java new file mode 100644 index 000000000..16b9b1877 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java @@ -0,0 +1,350 @@ +/* + * 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.utils.activeregion; + + +// the imports for unit testing. + + +import net.sf.picard.reference.ReferenceSequenceFile; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + + +public class IncrementalActivityProfileUnitTest extends BaseTest { + private GenomeLocParser genomeLocParser; + private GenomeLoc startLoc; + + @BeforeClass + public void init() throws FileNotFoundException { + // sequence + ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference)); + genomeLocParser = new GenomeLocParser(seq); + startLoc = genomeLocParser.createGenomeLoc("chr1", 1, 1, 100); + } + + // -------------------------------------------------------------------------------- + // + // Basic tests Provider + // + // -------------------------------------------------------------------------------- + + private class BasicActivityProfileTestProvider extends TestDataProvider { + List probs; + List expectedRegions; + int extension = 0; + GenomeLoc regionStart = startLoc; + final ProfileType type; + + public BasicActivityProfileTestProvider(final ProfileType type, final List probs, boolean startActive, int ... startsAndStops) { + super(BasicActivityProfileTestProvider.class); + this.type = type; + this.probs = probs; + this.expectedRegions = toRegions(startActive, startsAndStops); + setName(getName()); + } + + private String getName() { + return String.format("type=%s probs=%s expectedRegions=%s", type, Utils.join(",", probs), Utils.join(",", expectedRegions)); + } + + public IncrementalActivityProfile makeProfile() { + switch ( type ) { + case Base: return new IncrementalActivityProfile(genomeLocParser); + case BandPass: //return new BandPassActivityProfile(genomeLocParser); + default: throw new IllegalStateException(type.toString()); + } + } + + private List toRegions(boolean isActive, int[] startsAndStops) { + List l = new ArrayList(); + for ( int i = 0; i < startsAndStops.length - 1; i++) { + int start = regionStart.getStart() + startsAndStops[i]; + int end = regionStart.getStart() + startsAndStops[i+1] - 1; + GenomeLoc activeLoc = genomeLocParser.createGenomeLoc(regionStart.getContig(), start, end); + ActiveRegion r = new ActiveRegion(activeLoc, isActive, genomeLocParser, extension); + l.add(r); + isActive = ! isActive; + } + return l; + } + } + + private enum ProfileType { + Base, BandPass + } + + @DataProvider(name = "BasicActivityProfileTestProvider") + public Object[][] makeQualIntervalTestProvider() { + for ( final ProfileType type : ProfileType.values() ) { + if ( type != ProfileType.BandPass ) { // todo -- re-enable + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); + } + } + + return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class); + } + + @Test(dataProvider = "BasicActivityProfileTestProvider") + public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) { + IncrementalActivityProfile profile = cfg.makeProfile(); + + Assert.assertTrue(profile.isEmpty()); + + Assert.assertEquals(profile.parser, genomeLocParser); + + for ( int i = 0; i < cfg.probs.size(); i++ ) { + double p = cfg.probs.get(i); + GenomeLoc loc = genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart() + i, cfg.regionStart.getStart() + i); + profile.add(new ActivityProfileState(loc, p)); + Assert.assertFalse(profile.isEmpty()); + } + Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() )); + + Assert.assertEquals(profile.size(), cfg.probs.size()); + assertProbsAreEqual(profile.stateList, cfg.probs); + + // TODO -- reanble tests + //assertRegionsAreEqual(profile.createActiveRegions(0, 100), cfg.expectedRegions); + + Assert.assertEquals(profile.createDerivedProfile(profile.stateList).getClass(), profile.getClass()); + + final List empty = new LinkedList(); + Assert.assertEquals(profile.createDerivedProfile(empty).size(), 0); + } + + private void assertRegionsAreEqual(List actual, List expected) { + Assert.assertEquals(actual.size(), expected.size()); + for ( int i = 0; i < actual.size(); i++ ) { + Assert.assertTrue(actual.get(i).equalExceptReads(expected.get(i))); + } + } + + private void assertProbsAreEqual(List actual, List expected) { + Assert.assertEquals(actual.size(), expected.size()); + for ( int i = 0; i < actual.size(); i++ ) { + Assert.assertEquals(actual.get(i).isActiveProb, expected.get(i)); + } + } + + // ------------------------------------------------------------------------------------- + // + // Hardcore tests for adding to the profile and constructing active regions + // + // ------------------------------------------------------------------------------------- + + private static class SizeToStringList extends ArrayList { + @Override public String toString() { return "List[" + size() + "]"; } + } + + @DataProvider(name = "RegionCreationTests") + public Object[][] makeRegionCreationTests() { + final List tests = new LinkedList(); + + final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength(); + for ( int start : Arrays.asList(1, 10, 100, contigLength - 100, contigLength - 10) ) { + for ( int regionSize : Arrays.asList(1, 10, 100, 1000, 10000) ) { + for ( int maxRegionSize : Arrays.asList(10, 50, 200) ) { + for ( final boolean waitUntilEnd : Arrays.asList(false, true) ) { + for ( final boolean forceConversion : Arrays.asList(false, true) ) { + // what do I really want to test here? I'd like to test a few cases: + // -- region is all active (1.0) + // -- region is all inactive (0.0) + // -- cut the interval into 1, 2, 3, 4, 5 ... 10 regions, each with alternating activity values + for ( final boolean startWithActive : Arrays.asList(true, false) ) { + for ( int nParts : Arrays.asList(1, 2, 3, 4, 5, 7, 10, 11, 13) ) { + +// for ( int start : Arrays.asList(1) ) { +// for ( int regionSize : Arrays.asList(100) ) { +// for ( int maxRegionSize : Arrays.asList(10) ) { +// for ( final boolean waitUntilEnd : Arrays.asList(true) ) { +// for ( final boolean forceConversion : Arrays.asList(false) ) { +// for ( final boolean startWithActive : Arrays.asList(true) ) { +// for ( int nParts : Arrays.asList(3) ) { + regionSize = Math.min(regionSize, contigLength - start); + final List regions = makeRegions(regionSize, startWithActive, nParts); + tests.add(new Object[]{ start, regions, maxRegionSize, nParts, forceConversion, waitUntilEnd }); + } + } + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + private List makeRegions(final int totalRegionSize, + final boolean startWithActive, + final int nParts) { + final List regions = new SizeToStringList(); + + boolean isActive = startWithActive; + final int activeRegionSize = Math.max(totalRegionSize / nParts, 1); + for ( int i = 0; i < totalRegionSize; i += activeRegionSize ) { + for ( int j = 0; j < activeRegionSize && j + i < totalRegionSize; j++ ) { + regions.add(isActive); + } + isActive = ! isActive; + } + + return regions; + } + + + @Test(enabled = true, dataProvider = "RegionCreationTests") + public void testRegionCreation(final int start, final List probs, int maxRegionSize, final int nParts, final boolean forceConversion, final boolean waitUntilEnd) { + final IncrementalActivityProfile profile = new IncrementalActivityProfile(genomeLocParser); + Assert.assertNotNull(profile.toString()); + + final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); + final List seenSites = new ArrayList(Collections.nCopies(probs.size(), false)); + ActiveRegion lastRegion = null; + for ( int i = 0; i < probs.size(); i++ ) { + final boolean isActive = probs.get(i); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start); + final ActivityProfileState state = new ActivityProfileState(loc, isActive ? 1.0 : 0.0); + profile.add(state); + Assert.assertNotNull(profile.toString()); + + if ( ! waitUntilEnd ) { + final List regions = profile.popReadyActiveRegions(0, maxRegionSize, false); + lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites); + } + } + + if ( waitUntilEnd || forceConversion ) { + final List regions = profile.popReadyActiveRegions(0, maxRegionSize, forceConversion); + lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites); + } + + for ( int i = 0; i < probs.size(); i++ ) { + if ( forceConversion || (i + maxRegionSize + profile.getMaxProbPropogationDistance() < probs.size())) + // only require a site to be seen if we are forcing conversion or the site is more than maxRegionSize from the end + Assert.assertTrue(seenSites.get(i), "Missed site " + i); + } + + Assert.assertNotNull(profile.toString()); + } + + private ActiveRegion assertGoodRegions(final int start, final List regions, final int maxRegionSize, ActiveRegion lastRegion, final List probs, final List seenSites) { + for ( final ActiveRegion region : regions ) { + Assert.assertTrue(region.getLocation().size() > 0, "Region " + region + " has a bad size"); + Assert.assertTrue(region.getLocation().size() <= maxRegionSize, "Region " + region + " has a bad size: it's big than the max region size " + maxRegionSize); + if ( lastRegion != null ) { + Assert.assertTrue(region.getLocation().getStart() == lastRegion.getLocation().getStop() + 1, "Region " + region + " doesn't start immediately after previous region" + lastRegion); + } + + // check that all active bases are actually active + final int regionOffset = region.getLocation().getStart() - start; + Assert.assertTrue(regionOffset >= 0 && regionOffset < probs.size(), "Region " + region + " has a bad offset w.r.t. start"); + for ( int j = 0; j < region.getLocation().size(); j++ ) { + final int siteOffset = j + regionOffset; + Assert.assertEquals(region.isActive, probs.get(siteOffset).booleanValue()); + Assert.assertFalse(seenSites.get(siteOffset), "Site " + j + " in " + region + " was seen already"); + seenSites.set(siteOffset, true); + } + + lastRegion = region; + } + + return lastRegion; + } + + // ------------------------------------------------------------------------------------- + // + // Hardcore tests for adding to the profile and constructing active regions + // + // ------------------------------------------------------------------------------------- + + @DataProvider(name = "SoftClipsTest") + public Object[][] makeSoftClipsTest() { + final List tests = new LinkedList(); + + final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength(); + for ( int start : Arrays.asList(1, 10, 100, contigLength - 100, contigLength - 10, contigLength - 1) ) { + for ( int precedingSites: Arrays.asList(0, 1, 10) ) { + if ( precedingSites + start < contigLength ) { + for ( int softClipSize : Arrays.asList(1, 2, 10, 100) ) { +// for ( int start : Arrays.asList(10) ) { +// for ( int precedingSites: Arrays.asList(10) ) { +// for ( int softClipSize : Arrays.asList(1) ) { + tests.add(new Object[]{ start, precedingSites, softClipSize }); + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "SoftClipsTest") + public void testSoftClips(final int start, int nPrecedingSites, final int softClipSize) { + final IncrementalActivityProfile profile = new IncrementalActivityProfile(genomeLocParser); + + final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength(); + final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); + for ( int i = 0; i < nPrecedingSites; i++ ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start); + final ActivityProfileState state = new ActivityProfileState(loc, 0.0); + profile.add(state); + } + + final GenomeLoc softClipLoc = genomeLocParser.createGenomeLoc(contig, nPrecedingSites + start); + profile.add(new ActivityProfileState(softClipLoc, 1.0, ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS, softClipSize)); + + if ( nPrecedingSites == 0 ) { + final int profileSize = Math.min(start + softClipSize, contigLength) - start + 1; + Assert.assertEquals(profile.size(), profileSize, "Wrong number of states in the profile"); + } + + for ( int i = 0; i < profile.size(); i++ ) { + final ActivityProfileState state = profile.getStateList().get(i); + final boolean withinSCRange = state.getLoc().distance(softClipLoc) <= softClipSize; + if ( withinSCRange ) { + Assert.assertTrue(state.isActiveProb > 0.0, "active prob should be changed within soft clip size"); + } else { + Assert.assertEquals(state.isActiveProb, 0.0, "active prob shouldn't be changed outside of clip size"); + } + } + } +} \ No newline at end of file From ce160931d5c65cba4e355129b7328c2b56f08ead Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 18 Jan 2013 16:52:49 -0500 Subject: [PATCH 058/188] Optimize creation of reads in ArtificialBAMBuilder -- Now caches the reads so subsequent calls to makeReads() don't reallocate the reads from scratch each time --- .../sting/utils/sam/ArtificialBAMBuilder.java | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java index 82b5b29cc..bf3045c71 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialBAMBuilder.java @@ -62,6 +62,7 @@ public class ArtificialBAMBuilder { int alignmentStart = 1; int readLength = 10; private final ArrayList samples = new ArrayList(); + private List createdReads = null; private LinkedList additionalReads = new LinkedList(); @@ -102,6 +103,7 @@ public class ArtificialBAMBuilder { } public ArtificialBAMBuilder createAndSetHeader(final int nSamples) { + createdReads = null; this.header = new SAMFileHeader(); header.setSortOrder(SAMFileHeader.SortOrder.coordinate); header.setSequenceDictionary(parser.getContigs()); @@ -120,10 +122,12 @@ public class ArtificialBAMBuilder { } public void addReads(final GATKSAMRecord readToAdd) { + createdReads = null; additionalReads.add(readToAdd); } public void addReads(final Collection readsToAdd) { + createdReads = null; additionalReads.addAll(readsToAdd); } @@ -140,26 +144,34 @@ public class ArtificialBAMBuilder { * @return a ordered list of reads */ public List makeReads() { - final String baseName = "read"; - List reads = new ArrayList(nReadsPerLocus*nLoci); - for ( int locusI = 0; locusI < nLoci; locusI++) { - final int locus = locusI * (skipNLoci + 1); - for ( int readI = 0; readI < nReadsPerLocus; readI++ ) { - for ( final SAMReadGroupRecord rg : header.getReadGroups() ) { - final String readName = String.format("%s.%d.%d.%s", baseName, locus, readI, rg.getId()); - final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, alignmentStart + locus, readLength); - read.setReadGroup(new GATKSAMReadGroupRecord(rg)); - reads.add(read); + if ( createdReads == null ) { + final String baseName = "read"; + final LinkedList readGroups = new LinkedList(); + for ( final SAMReadGroupRecord rg : header.getReadGroups()) + readGroups.add(new GATKSAMReadGroupRecord(rg)); + + List reads = new ArrayList(nReadsPerLocus*nLoci); + for ( int locusI = 0; locusI < nLoci; locusI++) { + final int locus = locusI * (skipNLoci + 1); + for ( int readI = 0; readI < nReadsPerLocus; readI++ ) { + for ( final GATKSAMReadGroupRecord rg : readGroups ) { + final String readName = String.format("%s.%d.%d.%s", baseName, locus, readI, rg.getId()); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, readName, 0, alignmentStart + locus, readLength); + read.setReadGroup(rg); + reads.add(read); + } } } + + if ( ! additionalReads.isEmpty() ) { + reads.addAll(additionalReads); + Collections.sort(reads, new SAMRecordCoordinateComparator()); + } + + createdReads = new ArrayList(reads); } - if ( ! additionalReads.isEmpty() ) { - reads.addAll(additionalReads); - Collections.sort(reads, new SAMRecordCoordinateComparator()); - } - - return reads; + return createdReads; } /** @@ -192,13 +204,13 @@ public class ArtificialBAMBuilder { public int getnReadsPerLocus() { return nReadsPerLocus; } public int getnLoci() { return nLoci; } public int getSkipNLoci() { return skipNLoci; } - public ArtificialBAMBuilder setSkipNLoci(int skipNLoci) { this.skipNLoci = skipNLoci; return this; } + public ArtificialBAMBuilder setSkipNLoci(int skipNLoci) { this.skipNLoci = skipNLoci; createdReads = null; return this; } public int getAlignmentStart() { return alignmentStart; } - public ArtificialBAMBuilder setAlignmentStart(int alignmentStart) { this.alignmentStart = alignmentStart; return this; } + public ArtificialBAMBuilder setAlignmentStart(int alignmentStart) { this.alignmentStart = alignmentStart; createdReads = null; return this; } public int getReadLength() { return readLength; } - public ArtificialBAMBuilder setReadLength(int readLength) { this.readLength = readLength; return this; } + public ArtificialBAMBuilder setReadLength(int readLength) { this.readLength = readLength; createdReads = null; return this; } public SAMFileHeader getHeader() { return header; } - public ArtificialBAMBuilder setHeader(SAMFileHeader header) { this.header = header; return this; } + public ArtificialBAMBuilder setHeader(SAMFileHeader header) { this.header = header; createdReads = null; return this; } public int getAlignmentEnd() { return alignmentStart + nLoci * (skipNLoci + 1) + readLength; From eb60235dcd46aef1260cdad111708644aa08d4e5 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 18 Jan 2013 16:57:28 -0500 Subject: [PATCH 059/188] Working version of incremental active region traversals -- The incremental version now processes active regions as soon as they are ready to be processed, instead of waiting until the end of the shard as in the previous version. This means that ART walkers will now take much less memory than previously. On chr20 of NA12878 the majority of regions are processed with as few as 500 reads in memory. Over the whole chr20 only 5K reads were ever held in ART at one time. -- Fixed bug in the way active regions worked with shard boundaries. The new implementation no longer see shard boundaries in any meaningful way, and that uncovered a problem that active regions were always being closed across shard boundaries. This behavior was actually encoded in the unit tests, so those needed to be updated as well. -- Changed the way that preset regions work in ART. The new contract ensures that you get exactly the regions you requested. the isActive function is still called, but its result has no impact on the regions. With this functionality is should be possible to use the HC as a generic assembly by forcing it to operate over very large regions -- Added a few misc. useful functions to IncrementalActivityProfile --- .../traversals/TraverseActiveRegions.java | 240 ++++++++---------- .../gatk/walkers/ActiveRegionWalker.java | 22 +- .../utils/activeregion/ActiveRegion.java | 17 +- .../IncrementalActivityProfile.java | 18 ++ .../traversals/DummyActiveRegionWalker.java | 18 +- .../TraverseActiveRegionsUnitTest.java | 54 ++-- 6 files changed, 176 insertions(+), 193 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index de0bfd1f1..436edbdf1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -32,17 +32,13 @@ import org.broadinstitute.sting.gatk.WalkerManager; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.datasources.providers.*; -import org.broadinstitute.sting.gatk.datasources.reads.Shard; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.activeregion.ActiveRegion; -import org.broadinstitute.sting.utils.activeregion.ActivityProfile; -import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; -import org.broadinstitute.sting.utils.activeregion.BandPassActivityProfile; +import org.broadinstitute.sting.utils.activeregion.*; import org.broadinstitute.sting.utils.progressmeter.ProgressMeter; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -70,6 +66,7 @@ import java.util.*; public class TraverseActiveRegions extends TraversalEngine,LocusShardDataProvider> { protected final static Logger logger = Logger.getLogger(TraversalEngine.class); protected final static boolean DEBUG = false; + protected final static boolean LOG_READ_CARRYING = false; // set by the tranversal private boolean walkerHasPresetRegions = false; @@ -80,6 +77,8 @@ public class TraverseActiveRegions extends TraversalEngine myReads = new LinkedList(); private GenomeLoc spanOfLastReadSeen = null; + private IncrementalActivityProfile activityProfile = null; + int maxReadsInMemory = 0; @Override public void initialize(GenomeAnalysisEngine engine, Walker walker, ProgressMeter progressMeter) { @@ -94,6 +93,14 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine activeRegions) { - if ( profile.isEmpty() ) - throw new IllegalStateException("trying to incorporate an empty active profile " + profile); - - final ActivityProfile finalizedProfile = profile.finalizeProfile(); - activeRegions.addAll(finalizedProfile.createActiveRegions(getActiveRegionExtension(), getMaxRegionSize())); - return makeNewActivityProfile(); - } - - protected final ActivityProfileState walkerActiveProb(final ActiveRegionWalker walker, - final RefMetaDataTracker tracker, final ReferenceContext refContext, - final AlignmentContext locus, final GenomeLoc location) { - if ( walkerHasPresetRegions ) { - return new ActivityProfileState(location, walker.presetActiveRegions.overlaps(location) ? 1.0 : 0.0); - } else { - return walker.isActive( tracker, refContext, locus ); - } - } - - private ActivityProfile makeNewActivityProfile() { - if ( walkerHasPresetRegions ) - return new ActivityProfile(engine.getGenomeLocParser()); - else - return new BandPassActivityProfile(engine.getGenomeLocParser()); - } - - /** - * Write out each active region to the walker activeRegionOutStream - * - * @param walker - */ - protected void writeActiveRegionsToStream( final ActiveRegionWalker walker ) { - // Just want to output the active regions to a file, not actually process them - for( final ActiveRegion activeRegion : workQueue ) { - if( activeRegion.isActive ) { - walker.activeRegionOutStream.println( activeRegion.getLocation() ); - } - } - } - // ------------------------------------------------------------------------------------- // // Actual traverse function @@ -219,7 +170,7 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine walker, final LocusShardDataProvider dataProvider, T sum) { - logger.debug(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); + if ( LOG_READ_CARRYING || logger.isDebugEnabled() ) + logger.info(String.format("TraverseActiveRegions.traverse: Shard is %s", dataProvider)); final LocusView locusView = new AllLocusView(dataProvider); - final LocusReferenceView referenceView = new LocusReferenceView( walker, dataProvider ); - - final List activeRegions = new LinkedList(); - ActivityProfile profile = makeNewActivityProfile(); - - ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); + final ReferenceOrderedView referenceOrderedDataView = getReferenceOrderedView(walker, dataProvider, locusView); // We keep processing while the next reference location is within the interval final GenomeLoc locOfLastReadAtTraversalStart = spanOfLastSeenRead(); - // if we've moved onto a new contig, process all of the active regions - if ( onNewContig(dataProvider.getShard()) ) - sum = processActiveRegions(walker, sum, true); - - GenomeLoc prevLoc = null; while( locusView.hasNext() ) { final AlignmentContext locus = locusView.next(); final GenomeLoc location = locus.getLocation(); @@ -273,9 +205,7 @@ public class TraverseActiveRegions extends TraversalEngine reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); for( final GATKSAMRecord read : reads ) { - if ( appearedInLastShard(locOfLastReadAtTraversalStart, read) ) { - if ( DEBUG ) logger.warn("Skipping duplicated " + read.getReadName()); - } else { + if ( ! appearedInLastShard(locOfLastReadAtTraversalStart, read) ) { if ( DEBUG ) logger.warn("Adding read " + read.getReadName() + " at " + engine.getGenomeLocParser().createGenomeLoc(read) + " from provider " + dataProvider); rememberLastReadLocation(read); myReads.add(read); @@ -286,10 +216,11 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine walker, T sum) { - return processActiveRegions((ActiveRegionWalker)walker, sum, true); + return processActiveRegions((ActiveRegionWalker)walker, sum, true, true); } // ------------------------------------------------------------------------------------- @@ -383,8 +290,15 @@ public class TraverseActiveRegions extends TraversalEngine 0 ) + throw new IllegalStateException("Active region " + region + " on a contig after last seen read " + spanOfLastSeenRead()); + else { + return contigCmp < 0 || region.getExtendedLoc().getStop() < spanOfLastSeenRead().getStart(); + } } /** @@ -408,7 +322,9 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine walker, T sum, final boolean forceRegionsToBeActive) { - if( walker.activeRegionOutStream != null ) { + /** + * Invoke the walker isActive function, and incorporate its result into the activity profile + * + * @param walker the walker we're running + * @param tracker the ref meta data tracker to pass on to the isActive function of walker + * @param refContext the refContext to pass on to the isActive function of walker + * @param locus the AlignmentContext to pass on to the isActive function of walker + */ + private void addIsActiveResult(final ActiveRegionWalker walker, + final RefMetaDataTracker tracker, final ReferenceContext refContext, + final AlignmentContext locus) { + // must be called, even if we won't use the result, to satisfy walker contract + final ActivityProfileState state = walker.isActive( tracker, refContext, locus ); + if ( ! walkerHasPresetRegions ) { + activityProfile.add(state); + } + } + + /** + * Write out each active region to the walker activeRegionOutStream + * + * @param walker + */ + private void writeActiveRegionsToStream( final ActiveRegionWalker walker ) { + // Just want to output the active regions to a file, not actually process them + for( final ActiveRegion activeRegion : workQueue ) { + if( activeRegion.isActive ) { + walker.activeRegionOutStream.println( activeRegion.getLocation() ); + } + } + } + + /** + * Take the individual isActive calls and integrate them into contiguous active regions and + * add these blocks of work to the work queue + * band-pass filter the list of isActive probabilities and turn into active regions + */ + private T processActiveRegions(final ActiveRegionWalker walker, T sum, final boolean flushActivityProfile, final boolean forceAllRegionsToBeActive) { + if ( ! walkerHasPresetRegions ) { + // We don't have preset regions, so we get our regions from the activity profile + final Collection activeRegions = activityProfile.popReadyActiveRegions(getActiveRegionExtension(), getMaxRegionSize(), flushActivityProfile); + workQueue.addAll(activeRegions); + if ( logger.isDebugEnabled() ) logger.debug("Integrated " + activityProfile.size() + " isActive calls into " + activeRegions.size() + " regions." ); + } + + if ( walker.activeRegionOutStream != null ) { writeActiveRegionsToStream(walker); return sum; } else { - return callWalkerMapOnActiveRegions(walker, sum, forceRegionsToBeActive); - } - } - - private T callWalkerMapOnActiveRegions(final ActiveRegionWalker walker, T sum, final boolean forceRegionsToBeActive) { - // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them - // TODO can implement parallel traversal here - while( workQueue.peek() != null ) { - final ActiveRegion activeRegion = workQueue.peek(); - if ( forceRegionsToBeActive || regionCompletelyWithinDeadZone(activeRegion) ) { - if ( DEBUG ) logger.warn("Processing active region " + activeRegion + " dead zone " + spanOfLastSeenRead()); - sum = processActiveRegion( workQueue.remove(), sum, walker ); - } else { - break; + // Since we've traversed sufficiently past this point (or this contig!) in the workQueue we can unload those regions and process them + while( workQueue.peek() != null ) { + final ActiveRegion activeRegion = workQueue.peek(); + if ( forceAllRegionsToBeActive || regionCompletelyWithinDeadZone(activeRegion) ) { + if ( DEBUG ) logger.warn("Processing active region " + activeRegion + " dead zone " + spanOfLastSeenRead()); + sum = processActiveRegion( workQueue.remove(), sum, walker ); + } else { + break; + } } - } - return sum; + return sum; + } } - protected T processActiveRegion(final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker) { + private T processActiveRegion(final ActiveRegion activeRegion, final T sum, final ActiveRegionWalker walker) { final Iterator liveReads = myReads.iterator(); while ( liveReads.hasNext() ) { boolean killed = false; @@ -468,6 +423,11 @@ public class TraverseActiveRegions extends TraversalEngine> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); + + if ( LOG_READ_CARRYING ) + logger.info(String.format("Processing region %20s span=%3d active?=%5b with %4d reads. Overall max reads carried is %s", + activeRegion.getLocation(), activeRegion.getLocation().size(), activeRegion.isActive, activeRegion.size(), maxReadsInMemory)); + final M x = walker.map(activeRegion, null); return walker.reduce( x, sum ); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index 820100f7f..85d7c8293 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -68,11 +68,7 @@ public abstract class ActiveRegionWalker extends Walker> activeRegionBindings = null; - public GenomeLocSortedSet presetActiveRegions = null; - - public boolean hasPresetActiveRegions() { - return presetActiveRegions != null; - } + private GenomeLocSortedSet presetActiveRegions = null; @Override public void initialize() { @@ -91,6 +87,22 @@ public abstract class ActiveRegionWalker extends Walker { - - public ActiveRegionStartLocationComparator() {} - - @Override - public int compare(final ActiveRegion left, final ActiveRegion right) { - return left.getLocation().compareTo(right.getLocation()); - } - } - */ } \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java index e71f177f4..3cbad54e9 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java @@ -123,6 +123,24 @@ public class IncrementalActivityProfile { return stateList.isEmpty(); } + /** + * Get the span of this activity profile, which is from the start of the first state to the stop of the last + * @return a potentially null GenomeLoc. Will be null if this profile is empty + */ + public GenomeLoc getSpan() { + return isEmpty() ? null : regionStartLoc.endpointSpan(regionStopLoc); + } + + @Requires("! isEmpty()") + public int getContigIndex() { + return regionStartLoc.getContigIndex(); + } + + @Requires("! isEmpty()") + public int getStop() { + return regionStopLoc.getStop(); + } + /** * Get the list of active profile results in this object * @return a non-null, ordered list of active profile results diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java index f09a4b3e8..e2cad88a1 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/DummyActiveRegionWalker.java @@ -51,6 +51,7 @@ class DummyActiveRegionWalker extends ActiveRegionWalker { protected List isActiveCalls = new ArrayList(); protected Map mappedActiveRegions = new LinkedHashMap(); + private boolean declareHavingPresetRegions = false; public DummyActiveRegionWalker() { this(1.0); @@ -60,20 +61,31 @@ class DummyActiveRegionWalker extends ActiveRegionWalker { this.prob = constProb; } - public DummyActiveRegionWalker(EnumSet wantStates) { - this(1.0); + public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions, EnumSet wantStates, final boolean declareHavingPresetRegions) { + this(activeRegions, declareHavingPresetRegions); this.states = wantStates; } - public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions) { + public DummyActiveRegionWalker(GenomeLocSortedSet activeRegions, final boolean declareHavingPresetRegions) { this(1.0); this.activeRegions = activeRegions; + this.declareHavingPresetRegions = declareHavingPresetRegions; } public void setStates(EnumSet states) { this.states = states; } + @Override + public boolean hasPresetActiveRegions() { + return declareHavingPresetRegions; + } + + @Override + public GenomeLocSortedSet getPresetActiveRegions() { + return declareHavingPresetRegions ? activeRegions : null; + } + @Override public EnumSet desiredReadStates() { return states; diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java index 76eac3a8d..a574932a7 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegionsUnitTest.java @@ -179,7 +179,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider") public void testActiveRegionCoverage(TraverseActiveRegions t) { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); + DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals), true); Collection activeRegions = getActiveRegions(t, walker, intervals).values(); verifyActiveRegionCoverage(intervals, activeRegions); @@ -242,9 +242,11 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { } } - @Test(enabled = true, dataProvider = "TraversalEngineProvider") + @Test(enabled = true && !DEBUG, dataProvider = "TraversalEngineProvider") public void testPrimaryReadMapping(TraverseActiveRegions t) { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker(); + DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals), + EnumSet.of(ActiveRegionReadState.PRIMARY), + true); // Contract: Each read has the Primary state in a single region (or none) // This is the region of maximum overlap for the read (earlier if tied) @@ -275,20 +277,18 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); verifyReadMapping(region); - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); + region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000)); verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); - verifyReadMapping(region); - region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); verifyReadMapping(region, "simple20"); } @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider") public void testNonPrimaryReadMapping(TraverseActiveRegions t) { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker( - EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY)); + DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals), + EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY), + true); // Contract: Each read has the Primary state in a single region (or none) // This is the region of maximum overlap for the read (earlier if tied) @@ -321,10 +321,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); verifyReadMapping(region, "boundary_equal", "boundary_unequal", "boundary_1_pre", "boundary_1_post"); - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); + region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000)); verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); @@ -333,8 +330,9 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { @Test(enabled = true && ! DEBUG, dataProvider = "TraversalEngineProvider") public void testExtendedReadMapping(TraverseActiveRegions t) { - DummyActiveRegionWalker walker = new DummyActiveRegionWalker( - EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED)); + DummyActiveRegionWalker walker = new DummyActiveRegionWalker(new GenomeLocSortedSet(genomeLocParser, intervals), + EnumSet.of(ActiveRegionReadState.PRIMARY, ActiveRegionReadState.NONPRIMARY, ActiveRegionReadState.EXTENDED), + true); // Contract: Each read has the Primary state in a single region (or none) // This is the region of maximum overlap for the read (earlier if tied) @@ -368,10 +366,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 2000, 2999)); verifyReadMapping(region, "boundary_equal", "boundary_unequal", "extended_and_np", "boundary_1_pre", "boundary_1_post"); - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 14908, 16384)); - verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); - - region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 16385, 16927)); + region = activeRegions.get(genomeLocParser.createGenomeLoc("1", 10000, 20000)); verifyReadMapping(region, "shard_boundary_1_pre", "shard_boundary_1_post", "shard_boundary_equal"); region = activeRegions.get(genomeLocParser.createGenomeLoc("20", 10000, 10100)); @@ -384,6 +379,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { } private void verifyReadMapping(ActiveRegion region, String... reads) { + Assert.assertNotNull(region, "Region was unexpectedly null"); final Set regionReads = new HashSet(); for (SAMRecord read : region.getReads()) { Assert.assertFalse(regionReads.contains(read.getReadName()), "Duplicate reads detected in region " + region + " read " + read.getReadName()); @@ -530,12 +526,11 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { for ( final int start : starts ) { for ( final int nReadsPerLocus : Arrays.asList(1, 2) ) { for ( final int nLoci : Arrays.asList(1, 1000) ) { + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci); + bamBuilder.setReadLength(readLength); + bamBuilder.setSkipNLoci(skips); + bamBuilder.setAlignmentStart(start); for ( EnumSet readStates : allReadStates ) { - final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(reference, nReadsPerLocus, nLoci); - bamBuilder.setReadLength(readLength); - bamBuilder.setSkipNLoci(skips); - bamBuilder.setAlignmentStart(start); - for ( final GenomeLocSortedSet activeRegions : enumerateActiveRegions(bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd())) { nTests++; if ( nTests < maxTests ) // && nTests == 1238 ) @@ -595,7 +590,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd()) ); - final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions); + final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions, false); walker.setStates(readStates); final TraverseActiveRegions traversal = new TraverseActiveRegions(); @@ -619,8 +614,9 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { alreadySeenReads.add(read.getReadName()); } - Assert.assertEquals(readNamesInRegion.contains(read.getReadName()), shouldBeInRegion, "Region " + region + - " failed contains read check: read " + read + " with span " + readLoc + " should be in region is " + shouldBeInRegion + " but I got the opposite"); + String msg = readNamesInRegion.contains(read.getReadName()) == shouldBeInRegion ? "" : "Region " + region + + " failed contains read check: read " + read + " with span " + readLoc + " should be in region is " + shouldBeInRegion + " but I got the opposite"; + Assert.assertEquals(readNamesInRegion.contains(read.getReadName()), shouldBeInRegion, msg); nReadsExpectedInRegion += shouldBeInRegion ? 1 : 0; } @@ -642,7 +638,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { // // --------------------------------------------------------------------------------------------------------- - @Test + @Test(enabled = true && ! DEBUG) public void ensureAllInsertionReadsAreInActiveRegions() { final int readLength = 10; @@ -667,7 +663,7 @@ public class TraverseActiveRegionsUnitTest extends BaseTest { genomeLocParser.createGenomeLoc("1", bamBuilder.getAlignmentStart(), bamBuilder.getAlignmentEnd()) ); - final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions); + final DummyActiveRegionWalker walker = new DummyActiveRegionWalker(activeRegions, false); final TraverseActiveRegions traversal = new TraverseActiveRegions(); final Map activeRegionsMap = getActiveRegions(traversal, walker, intervals, bamBuilder.makeTemporarilyBAMFile().toString()); From 7fd27a5167ca0fd0eda062954565ed19831bc6e9 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 22 Jan 2013 15:40:09 -0500 Subject: [PATCH 060/188] Add band pass filtering activity profile -- Based on the new incremental activity profile -- Unit Tested! Fixed a few bugs with the old band pass filter -- Expand IncrementalActivityProfileUnitTest to test the band pass filter as well for basic properties -- Add new UnitTest for BandPassIncrementalActivityProfile -- Added normalizeFromRealSpace to MathUtils -- Cleanup unused code in new activity profiles --- .../broadinstitute/sting/utils/MathUtils.java | 24 +++ .../BandPassIncrementalActivityProfile.java | 127 +++++++++++++ .../IncrementalActivityProfile.java | 41 ++--- ...assIncrementalActivityProfileUnitTest.java | 167 ++++++++++++++++++ .../IncrementalActivityProfileUnitTest.java | 27 ++- 5 files changed, 345 insertions(+), 41 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java create mode 100644 public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/utils/MathUtils.java b/public/java/src/org/broadinstitute/sting/utils/MathUtils.java index 7462416bc..f1f0ab9b1 100644 --- a/public/java/src/org/broadinstitute/sting/utils/MathUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/MathUtils.java @@ -634,6 +634,30 @@ public class MathUtils { return normalizeFromLog10(array, false); } + /** + * normalizes the real-space probability array. + * + * Does not assume anything about the values in the array, beyond that no elements are below 0. It's ok + * to have values in the array of > 1, or have the sum go above 0. + * + * @param array the array to be normalized + * @return a newly allocated array corresponding the normalized values in array + */ + @Requires("array != null") + @Ensures({"result != null"}) + public static double[] normalizeFromRealSpace(final double[] array) { + if ( array.length == 0 ) + return array; + + final double sum = sum(array); + final double[] normalized = new double[array.length]; + if ( sum < 0.0 || sum > 1.0 ) throw new IllegalArgumentException("Values in probability array sum to a negative number " + sum); + for ( int i = 0; i < array.length; i++ ) { + normalized[i] = array[i] / sum; + } + return normalized; + } + public static int maxElementIndex(final double[] array) { return maxElementIndex(array, array.length); } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java new file mode 100644 index 000000000..805a0b60a --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java @@ -0,0 +1,127 @@ +/* + * 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.utils.activeregion; + +import com.google.java.contract.Ensures; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.MathUtils; + +import java.util.Collection; +import java.util.LinkedList; + +/** + * A band pass filtering version of the activity profile + * + * Applies a band pass filter with a Gaussian kernel to the input state probabilities to smooth + * them out of an interval + * + * @author Mark DePristo + * @since 2011 + */ +public class BandPassIncrementalActivityProfile extends IncrementalActivityProfile { + public static final int DEFAULT_FILTER_SIZE = 80; + + private final int filterSize; + private final double[] GaussianKernel; + + /** + * Create a band pass activity profile with the default band size + * @param parser our genome loc parser + */ + public BandPassIncrementalActivityProfile(final GenomeLocParser parser) { + this(parser, DEFAULT_FILTER_SIZE); + } + + /** + * Create an activity profile that implements a band pass filter on the states + * @param parser our genome loc parser + * @param filterSize the size (in bp) of the band pass filter. The filter size is the number of bp to each + * side that are included in the band. So a filter size of 1 implies that the actual band + * is 3 bp, 1 for the center site and 1 on each size. 2 => 5, etc. + */ + public BandPassIncrementalActivityProfile(final GenomeLocParser parser, final int filterSize) { + super(parser); + + if ( filterSize < 0 ) throw new IllegalArgumentException("Filter size must be greater than or equal to 0 but got " + filterSize); + + // setup the Gaussian kernel for the band pass filter + this.filterSize = filterSize; + final double[] kernel = new double[getBandSize()]; + for( int iii = 0; iii < 2* filterSize + 1; iii++ ) { + kernel[iii] = MathUtils.NormalDistribution(filterSize, 55.0, iii); + } + this.GaussianKernel = MathUtils.normalizeFromRealSpace(kernel); + } + + /** + * Get the size (in bp) of the band pass filter + * @return a positive integer + */ + @Ensures("result >= 1") + public int getBandSize() { + return 2 * filterSize + 1; + } + + /** + * Get the filter size (which is the size of each wing of the band, minus the center point) + * @return a positive integer + */ + @Ensures("result >= 0") + public int getFilteredSize() { + return filterSize; + } + + /** + * Get the kernel of this band pass filter. Do not modify returned result + * @return the kernel used in this band pass filter + */ + @Ensures({"result != null", "result.length == getBandSize()"}) + protected double[] getKernel() { + return GaussianKernel; + } + + /** + * Band pass the probabilities in the ActivityProfile, producing a new profile that's band pass filtered + * @return a new double[] that's the band-pass filtered version of this profile + */ + @Override + protected Collection processState(final ActivityProfileState justAddedState) { + final Collection states = new LinkedList(); + + for ( final ActivityProfileState superState : super.processState(justAddedState) ) { + for( int jjj = -filterSize; jjj <= filterSize; jjj++ ) { + final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj); + if ( loc != null ) { + final double newProb = superState.isActiveProb * GaussianKernel[jjj + filterSize]; + states.add(new ActivityProfileState(loc, newProb)); + } + } + } + + return states; + } +} diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java index 3cbad54e9..1292b3176 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java @@ -51,35 +51,13 @@ public class IncrementalActivityProfile { /** * Create a new empty IncrementalActivityProfile - * @param parser the parser we can use to create genome locs + * @param parser the parser we can use to create genome locs, cannot be null */ public IncrementalActivityProfile(final GenomeLocParser parser) { - this(parser, new ArrayList(), null); - } + if ( parser == null ) throw new IllegalArgumentException("parser cannot be null"); - /** - * Create a new IncrementalActivityProfile using state list (not copied) and starting at regionStartLoc - * @param parser the parser we can use to create genome locs - */ - @Deprecated - protected IncrementalActivityProfile(final GenomeLocParser parser, final List stateList, final GenomeLoc regionStartLoc) { this.parser = parser; - this.stateList = stateList; - this.regionStartLoc = regionStartLoc; - } - - /** - * Create a profile of the same class as this object containing just the provided stateList - * - * Used by clients to create derived activity profiles (such as ones without the starting X - * sites because they've been removed in an ActiveRegion) of the same class. - * - * @param isActiveList the active results list to use in the derived instance - * @return a freshly allocated data set - */ - @Deprecated - protected IncrementalActivityProfile createDerivedProfile(final List isActiveList) { - return new IncrementalActivityProfile(parser, isActiveList, regionStartLoc); + this.stateList = new ArrayList(); } @Override @@ -150,6 +128,19 @@ public class IncrementalActivityProfile { return stateList; } + /** + * Get the probabilities of the states as a single linear array of doubles + * @return a non-null array + */ + @Ensures("result != null") + protected double[] getProbabilitiesAsArray() { + final double[] probs = new double[getStateList().size()]; + int i = 0; + for ( final ActivityProfileState state : getStateList() ) + probs[i++] = state.isActiveProb; + return probs; + } + /** * Helper function that gets the genome loc for a site offset from relativeLoc, protecting ourselves from * falling off the edge of the contig. diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java new file mode 100644 index 000000000..be90353b3 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java @@ -0,0 +1,167 @@ +/* + * 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.utils.activeregion; + + +// the imports for unit testing. + + +import net.sf.picard.reference.ReferenceSequenceFile; +import org.apache.commons.lang.ArrayUtils; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + + +public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { + private GenomeLocParser genomeLocParser; + + @BeforeClass + public void init() throws FileNotFoundException { + // sequence + ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference)); + genomeLocParser = new GenomeLocParser(seq); + } + + @DataProvider(name = "BandPassBasicTest") + public Object[][] makeBandPassTest() { + final List tests = new LinkedList(); + + for ( int start : Arrays.asList(1, 10, 100, 1000) ) { + for ( boolean precedingIsActive : Arrays.asList(true, false) ) { + for ( int precedingSites: Arrays.asList(0, 1, 10, 100) ) { + for ( int bandPassSize : Arrays.asList(0, 1, 10, 100) ) { +// for ( int start : Arrays.asList(10) ) { +// for ( boolean precedingIsActive : Arrays.asList(false) ) { +// for ( int precedingSites: Arrays.asList(0) ) { +// for ( int bandPassSize : Arrays.asList(1) ) { + tests.add(new Object[]{ start, precedingIsActive, precedingSites, bandPassSize }); + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "BandPassBasicTest") + public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize) { + final BandPassIncrementalActivityProfile profile = new BandPassIncrementalActivityProfile(genomeLocParser, bandPassSize); + + final int expectedBandSize = bandPassSize * 2 + 1; + Assert.assertEquals(profile.getBandSize(), expectedBandSize, "Wrong expected band size"); + + final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); + final double precedingProb = precedingIsActive ? 1.0 : 0.0; + for ( int i = 0; i < nPrecedingSites; i++ ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + start); + final ActivityProfileState state = new ActivityProfileState(loc, precedingProb); + profile.add(state); + } + + final GenomeLoc nextLoc = genomeLocParser.createGenomeLoc(contig, nPrecedingSites + start); + profile.add(new ActivityProfileState(nextLoc, 1.0)); + + if ( precedingIsActive == false && nPrecedingSites >= bandPassSize && bandPassSize < start ) { + // we have enough space that all probs fall on the genome + final double[] probs = profile.getProbabilitiesAsArray(); + Assert.assertEquals(MathUtils.sum(probs), 1.0 * (nPrecedingSites * precedingProb + 1), 1e-3, "Activity profile doesn't sum to number of non-zero prob states"); + } + } + + private double[] bandPassInOnePass(final BandPassIncrementalActivityProfile profile, final double[] activeProbArray) { + final double[] bandPassProbArray = new double[activeProbArray.length]; + + // apply the band pass filter for activeProbArray into filteredProbArray + final double[] GaussianKernel = profile.getKernel(); + for( int iii = 0; iii < activeProbArray.length; iii++ ) { + final double[] kernel = ArrayUtils.subarray(GaussianKernel, Math.max(profile.getFilteredSize() - iii, 0), Math.min(GaussianKernel.length, profile.getFilteredSize() + activeProbArray.length - iii)); + final double[] activeProbSubArray = ArrayUtils.subarray(activeProbArray, Math.max(0,iii - profile.getFilteredSize()), Math.min(activeProbArray.length,iii + profile.getFilteredSize() + 1)); + bandPassProbArray[iii] = MathUtils.dotProduct(activeProbSubArray, kernel); + } + + return bandPassProbArray; + } + + @DataProvider(name = "BandPassComposition") + public Object[][] makeBandPassComposition() { + final List tests = new LinkedList(); + + for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassIncrementalActivityProfile.DEFAULT_FILTER_SIZE) ) { + for ( int integrationLength : Arrays.asList(1, 10, 100, 1000) ) { + tests.add(new Object[]{ bandPassSize, integrationLength }); + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "BandPassComposition") + public void testBandPassComposition(final int bandPassSize, final int integrationLength) { + final int start = 1; + final BandPassIncrementalActivityProfile profile = new BandPassIncrementalActivityProfile(genomeLocParser, bandPassSize); + final double[] rawActiveProbs = new double[integrationLength + bandPassSize * 2]; + + // add a buffer so that we can get all of the band pass values + final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); + int pos = start; + int rawProbsOffset = 0; + for ( int i = 0; i < bandPassSize; i++ ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos++); + final ActivityProfileState state = new ActivityProfileState(loc, 0.0); + profile.add(state); + rawActiveProbs[rawProbsOffset++] = 0.0; + rawActiveProbs[rawActiveProbs.length - rawProbsOffset] = 0.0; + } + + for ( int i = 0; i < integrationLength; i++ ) { + final GenomeLoc nextLoc = genomeLocParser.createGenomeLoc(contig, pos++); + profile.add(new ActivityProfileState(nextLoc, 1.0)); + rawActiveProbs[rawProbsOffset++] = 1.0; + + for ( int j = 0; j < profile.size(); j++ ) { + Assert.assertTrue(profile.getStateList().get(j).isActiveProb >= 0.0, "State probability < 0 at " + j); + Assert.assertTrue(profile.getStateList().get(j).isActiveProb <= 1.0 + 1e-3, "State probability > 1 at " + j); + } + } + + final double[] expectedProbs = bandPassInOnePass(profile, rawActiveProbs); + for ( int j = 0; j < profile.size(); j++ ) { + Assert.assertEquals(profile.getStateList().get(j).isActiveProb, expectedProbs[j], "State probability not expected at " + j); + } + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java index 16b9b1877..64065029c 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java @@ -85,7 +85,9 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { public IncrementalActivityProfile makeProfile() { switch ( type ) { case Base: return new IncrementalActivityProfile(genomeLocParser); - case BandPass: //return new BandPassActivityProfile(genomeLocParser); + case BandPass: + // zero size => equivalent to IncrementalActivityProfile + return new BandPassIncrementalActivityProfile(genomeLocParser, 0); default: throw new IllegalStateException(type.toString()); } } @@ -111,13 +113,11 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { @DataProvider(name = "BasicActivityProfileTestProvider") public Object[][] makeQualIntervalTestProvider() { for ( final ProfileType type : ProfileType.values() ) { - if ( type != ProfileType.BandPass ) { // todo -- re-enable - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2); - new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); - } + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); + new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); } return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class); @@ -135,20 +135,15 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { double p = cfg.probs.get(i); GenomeLoc loc = genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart() + i, cfg.regionStart.getStart() + i); profile.add(new ActivityProfileState(loc, p)); - Assert.assertFalse(profile.isEmpty()); + Assert.assertFalse(profile.isEmpty(), "Profile shouldn't be empty after adding a state"); } - Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() )); + Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() ), "Start loc should be the start of the region"); - Assert.assertEquals(profile.size(), cfg.probs.size()); + Assert.assertEquals(profile.size(), cfg.probs.size(), "Should have exactly the number of states we expected to add"); assertProbsAreEqual(profile.stateList, cfg.probs); // TODO -- reanble tests //assertRegionsAreEqual(profile.createActiveRegions(0, 100), cfg.expectedRegions); - - Assert.assertEquals(profile.createDerivedProfile(profile.stateList).getClass(), profile.getClass()); - - final List empty = new LinkedList(); - Assert.assertEquals(profile.createDerivedProfile(empty).size(), 0); } private void assertRegionsAreEqual(List actual, List expected) { From e917f56df8e248dc472f2516a43acb280fbfb3ed Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 22 Jan 2013 16:02:09 -0500 Subject: [PATCH 061/188] Remove old ActivityProfile and old BandPassActivityProfile --- .../utils/activeregion/ActivityProfile.java | 243 ------------------ .../activeregion/BandPassActivityProfile.java | 84 ------ .../activeregion/ActivityProfileUnitTest.java | 166 ------------ 3 files changed, 493 deletions(-) delete mode 100644 public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java delete mode 100644 public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java delete mode 100644 public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java deleted file mode 100644 index 8d6012fac..000000000 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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.utils.activeregion; - -import com.google.java.contract.Ensures; -import com.google.java.contract.Requires; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Class holding information about per-base activity scores for the - * active region traversal - * - * @author Mark DePristo - * @since Date created - */ -public class ActivityProfile { - private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author - - protected final List isActiveList; - protected final GenomeLocParser parser; - - protected GenomeLoc regionStartLoc = null; - protected GenomeLoc regionStopLoc = null; - - public ActivityProfile(final GenomeLocParser parser) { - this(parser, new ArrayList(), null); - } - - protected ActivityProfile(final GenomeLocParser parser, final List isActiveList, final GenomeLoc regionStartLoc) { - this.parser = parser; - this.isActiveList = isActiveList; - this.regionStartLoc = regionStartLoc; - } - - /** - * Create a profile of the same class as this object containing just the provided stateList - * - * Used by clients to create derived activity profiles (such as ones without the starting X - * sites because they've been removed in an ActiveRegion) of the same class. - * - * @param isActiveList the active results list to use in the derived instance - * @return a freshly allocated data set - */ - protected ActivityProfile createDerivedProfile(final List isActiveList) { - return new ActivityProfile(parser, isActiveList, regionStartLoc); - } - - @Override - public String toString() { - return "ActivityProfile{" + - "start=" + regionStartLoc + - ", stop=" + regionStopLoc + - '}'; - } - - /** - * Add the next ActivityProfileState to this profile. - * - * Must be contiguous with the previously added result, or an IllegalArgumentException will be thrown - * - * @param result a well-formed ActivityProfileState result to incorporate into this profile - */ - @Requires("result != null") - public void add(final ActivityProfileState result) { - final GenomeLoc loc = result.getLoc(); - - if ( regionStartLoc == null ) { - regionStartLoc = loc; - regionStopLoc = loc; - } else { - if ( regionStopLoc.getStart() != loc.getStart() - 1 ) - throw new IllegalArgumentException("Bad add call to ActivityProfile: loc " + loc + " not immediate after last loc " + regionStopLoc ); - regionStopLoc = loc; - } - - isActiveList.add(result); - } - - /** - * How many profile results are in this profile? - * @return the number of profile results - */ - @Ensures("result >= 0") - public int size() { - return isActiveList.size(); - } - - /** - * Is this profile empty? - * @return true if the profile is empty - */ - @Ensures("isEmpty() == (size() == 0)") - public boolean isEmpty() { - return isActiveList.isEmpty(); - } - - /** - * Get the list of active profile results in this object - * @return a non-null, ordered list of active profile results - */ - @Ensures("result != null") - protected List getActiveList() { - return isActiveList; - } - - /** - * Finalize the probabilities in this activity profile, preparing it for a future - * call to createActiveRegions. This function returns a new profile with cleaned - * up activity estimates. - * - * This code looks at the current list of states, cleans them up, and then returns - * a newly allocated ActivityProfile - * - * @return a newly allocated ActivityProfile based on the current state of this - * profile, but that has been "finalized" as required by the profile implementation - */ - public ActivityProfile finalizeProfile() { - int iii = 0; - for( final double prob : finalizeProbabilities() ) { - final ActivityProfileState result = isActiveList.get(iii++); - result.isActiveProb = prob; - result.resultState = ActivityProfileState.Type.NONE; - result.resultValue = null; - } - - return createDerivedProfile(isActiveList); - } - - public double[] finalizeProbabilities() { - final double[] activeProbArray = new double[isActiveList.size()]; - - int iii = 0; - for( final ActivityProfileState result : isActiveList ) { - activeProbArray[iii++] = result.isActiveProb; - } - - iii = 0; - for( final ActivityProfileState result : isActiveList ) { - if( result.resultState.equals(ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS) ) { // special code to deal with the problem that high quality soft clipped bases aren't added to pileups - final int numHQClips = result.resultValue.intValue(); - for( int jjj = Math.max(0, iii - numHQClips); jjj < Math.min(activeProbArray.length, iii+numHQClips); jjj++ ) { - activeProbArray[jjj] = Math.max(activeProbArray[jjj], activeProbArray[iii]); - } - } - iii++; - } - - return activeProbArray; - } - - /** - * Partition this profile into active regions - * @param activeRegionExtension the amount of margin overlap in the active region - * @return the list of active regions - */ - public List createActiveRegions( final int activeRegionExtension, final int maxRegionSize ) { - final ArrayList returnList = new ArrayList(); - - if( isActiveList.size() == 0 ) { - // no elements in the active list, just return an empty one - return Collections.emptyList(); - } else if( isActiveList.size() == 1 ) { - // there's a single element, it's either active or inactive - boolean isActive = isActiveList.get(0).isActiveProb > ACTIVE_PROB_THRESHOLD; - returnList.addAll(createActiveRegion(isActive, 0, 0, activeRegionExtension, maxRegionSize)); - } else { - // there are 2+ elements, divide these up into regions - boolean isActive = isActiveList.get(0).isActiveProb > ACTIVE_PROB_THRESHOLD; - int curStart = 0; - for(int iii = 1; iii < isActiveList.size(); iii++ ) { - final boolean thisStatus = isActiveList.get(iii).isActiveProb > ACTIVE_PROB_THRESHOLD; - if( isActive != thisStatus ) { - returnList.addAll(createActiveRegion(isActive, curStart, iii - 1, activeRegionExtension, maxRegionSize)); - isActive = thisStatus; - curStart = iii; - } - } - returnList.addAll(createActiveRegion(isActive, curStart, isActiveList.size() - 1, activeRegionExtension, maxRegionSize)); // close out the current active region - } - return returnList; - } - - /** - * Helper routine to create an active region based on our current start and end offsets - * @param isActive should the region be active? - * @param curStart offset (0-based) from the start of this region - * @param curEnd offset (0-based) from the start of this region - * @param activeRegionExtension the amount of margin overlap in the active region - * @return a fully initialized ActiveRegion with the above properties - */ - private List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize) { - return createActiveRegion(isActive, curStart, curEnd, activeRegionExtension, maxRegionSize, new ArrayList()); - } - - private List createActiveRegion(final boolean isActive, final int curStart, final int curEnd, final int activeRegionExtension, final int maxRegionSize, final List returnList) { - if( !isActive || curEnd - curStart < maxRegionSize ) { - final GenomeLoc loc = parser.createGenomeLoc(regionStartLoc.getContig(), regionStartLoc.getStart() + curStart, regionStartLoc.getStart() + curEnd); - returnList.add(new ActiveRegion(loc, isActive, parser, activeRegionExtension)); - return returnList; - } - // find the best place to break up the large active region - Double minProb = Double.MAX_VALUE; - int cutPoint = -1; - - final int size = curEnd - curStart + 1; - for( int iii = curStart + (int)(size*0.15); iii < curEnd - (int)(size*0.15); iii++ ) { - if( isActiveList.get(iii).isActiveProb < minProb ) { minProb = isActiveList.get(iii).isActiveProb; cutPoint = iii; } - } - final List leftList = createActiveRegion(isActive, curStart, cutPoint, activeRegionExtension, maxRegionSize, new ArrayList()); - final List rightList = createActiveRegion(isActive, cutPoint+1, curEnd, activeRegionExtension, maxRegionSize, new ArrayList()); - returnList.addAll( leftList ); - returnList.addAll( rightList ); - return returnList; - } -} diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java deleted file mode 100644 index cef700419..000000000 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java +++ /dev/null @@ -1,84 +0,0 @@ -/* -* 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.utils.activeregion; - -import org.apache.commons.lang.ArrayUtils; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.MathUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author Mark DePristo - * @since 2011 - */ -public class BandPassActivityProfile extends ActivityProfile { - private static final int FILTER_SIZE = 80; - private static final double[] GaussianKernel; - - static { - GaussianKernel = new double[2*FILTER_SIZE + 1]; - for( int iii = 0; iii < 2*FILTER_SIZE + 1; iii++ ) { - GaussianKernel[iii] = MathUtils.NormalDistribution(FILTER_SIZE, 55.0, iii); - } - } - - public BandPassActivityProfile(final GenomeLocParser parser) { - this(parser, new ArrayList(), null); - } - - public BandPassActivityProfile(final GenomeLocParser parser, final List isActiveList, final GenomeLoc regionStartLoc) { - super(parser, isActiveList, regionStartLoc); - } - - @Override - protected ActivityProfile createDerivedProfile(List isActiveList) { - return new BandPassActivityProfile(parser, isActiveList, regionStartLoc); - } - - /** - * Band pass the probabilities in the ActivityProfile, producing a new profile that's band pass filtered - * @return a new double[] that's the band-pass filtered version of this profile - */ - @Override - public double[] finalizeProbabilities() { - final double[] activeProbArray = super.finalizeProbabilities(); - final double[] bandPassProbArray = new double[activeProbArray.length]; - - // apply the band pass filter for activeProbArray into filteredProbArray - for( int iii = 0; iii < activeProbArray.length; iii++ ) { - final double[] kernel = ArrayUtils.subarray(GaussianKernel, Math.max(FILTER_SIZE-iii, 0), Math.min(GaussianKernel.length,FILTER_SIZE + activeProbArray.length - iii)); - final double[] activeProbSubArray = ArrayUtils.subarray(activeProbArray, Math.max(0,iii - FILTER_SIZE), Math.min(activeProbArray.length,iii + FILTER_SIZE + 1)); - bandPassProbArray[iii] = MathUtils.dotProduct(activeProbSubArray, kernel); - } - - return bandPassProbArray; - } -} diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java deleted file mode 100644 index 430e0b5c6..000000000 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* -* 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.utils.activeregion; - - -// the imports for unit testing. - - -import net.sf.picard.reference.ReferenceSequenceFile; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.*; - - -public class ActivityProfileUnitTest extends BaseTest { - private GenomeLocParser genomeLocParser; - private GenomeLoc startLoc; - - @BeforeClass - public void init() throws FileNotFoundException { - // sequence - ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference)); - genomeLocParser = new GenomeLocParser(seq); - startLoc = genomeLocParser.createGenomeLoc("chr1", 1, 1, 100); - } - - // -------------------------------------------------------------------------------- - // - // Basic tests Provider - // - // -------------------------------------------------------------------------------- - - private class BasicActivityProfileTestProvider extends TestDataProvider { - List probs; - List expectedRegions; - int extension = 0; - GenomeLoc regionStart = startLoc; - final ProfileType type; - - public BasicActivityProfileTestProvider(final ProfileType type, final List probs, boolean startActive, int ... startsAndStops) { - super(BasicActivityProfileTestProvider.class); - this.type = type; - this.probs = probs; - this.expectedRegions = toRegions(startActive, startsAndStops); - setName(getName()); - } - - private String getName() { - return String.format("type=%s probs=%s expectedRegions=%s", type, Utils.join(",", probs), Utils.join(",", expectedRegions)); - } - - public ActivityProfile makeProfile() { - switch ( type ) { - case Base: return new ActivityProfile(genomeLocParser); - case BandPass: return new BandPassActivityProfile(genomeLocParser); - default: throw new IllegalStateException(type.toString()); - } - } - - private List toRegions(boolean isActive, int[] startsAndStops) { - List l = new ArrayList(); - for ( int i = 0; i < startsAndStops.length - 1; i++) { - int start = regionStart.getStart() + startsAndStops[i]; - int end = regionStart.getStart() + startsAndStops[i+1] - 1; - GenomeLoc activeLoc = genomeLocParser.createGenomeLoc(regionStart.getContig(), start, end); - ActiveRegion r = new ActiveRegion(activeLoc, isActive, genomeLocParser, extension); - l.add(r); - isActive = ! isActive; - } - return l; - } - } - - private enum ProfileType { - Base, BandPass - } - - @DataProvider(name = "BasicActivityProfileTestProvider") - public Object[][] makeQualIntervalTestProvider() { - for ( final ProfileType type : ProfileType.values() ) { - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0), true, 0, 1); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0), true, 0, 1, 2); - new BasicActivityProfileTestProvider(type, Arrays.asList(0.0, 1.0), false, 0, 1, 2); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 0.0, 1.0), true, 0, 1, 2, 3); - new BasicActivityProfileTestProvider(type, Arrays.asList(1.0, 1.0, 1.0), true, 0, 3); - } - - return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class); - } - - @Test(dataProvider = "BasicActivityProfileTestProvider") - public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) { - ActivityProfile profile = cfg.makeProfile(); - - Assert.assertTrue(profile.isEmpty()); - - Assert.assertEquals(profile.parser, genomeLocParser); - - for ( int i = 0; i < cfg.probs.size(); i++ ) { - double p = cfg.probs.get(i); - GenomeLoc loc = genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart() + i, cfg.regionStart.getStart() + i); - profile.add(new ActivityProfileState(loc, p)); - Assert.assertFalse(profile.isEmpty()); - } - Assert.assertEquals(profile.regionStartLoc, genomeLocParser.createGenomeLoc(cfg.regionStart.getContig(), cfg.regionStart.getStart(), cfg.regionStart.getStart() )); - - Assert.assertEquals(profile.size(), cfg.probs.size()); - assertProbsAreEqual(profile.isActiveList, cfg.probs); - - assertRegionsAreEqual(profile.createActiveRegions(0, 100), cfg.expectedRegions); - - Assert.assertEquals(profile.createDerivedProfile(profile.isActiveList).getClass(), profile.getClass()); - - final List empty = new LinkedList(); - Assert.assertEquals(profile.createDerivedProfile(empty).size(), 0); - } - - private void assertRegionsAreEqual(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); - for ( int i = 0; i < actual.size(); i++ ) { - Assert.assertTrue(actual.get(i).equalExceptReads(expected.get(i))); - } - } - - private void assertProbsAreEqual(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); - for ( int i = 0; i < actual.size(); i++ ) { - Assert.assertEquals(actual.get(i).isActiveProb, expected.get(i)); - } - } - - // todo -- test extensions -} \ No newline at end of file From 8e8126506b81fccf34a06aec8dcad873f2f28e09 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 09:44:46 -0500 Subject: [PATCH 062/188] Renaming IncrementalActivityProfile to ActivityProfile -- Also adding a work in progress functionality to make it easy to visualize activity profiles and active regions in IGV --- .../traversals/TraverseActiveRegions.java | 12 +++++++++--- .../gatk/walkers/ActiveRegionWalker.java | 2 ++ .../activeregion/ActiveRegionReadState.java | 5 ++--- ...ivityProfile.java => ActivityProfile.java} | 10 +++++----- .../activeregion/ActivityProfileState.java | 3 ++- ...file.java => BandPassActivityProfile.java} | 19 ++++++++++++++++--- ...Test.java => ActivityProfileUnitTest.java} | 18 +++++++++--------- ...a => BandPassActivityProfileUnitTest.java} | 11 +++++------ 8 files changed, 50 insertions(+), 30 deletions(-) rename public/java/src/org/broadinstitute/sting/utils/activeregion/{IncrementalActivityProfile.java => ActivityProfile.java} (98%) rename public/java/src/org/broadinstitute/sting/utils/activeregion/{BandPassIncrementalActivityProfile.java => BandPassActivityProfile.java} (87%) rename public/java/test/org/broadinstitute/sting/utils/activeregion/{IncrementalActivityProfileUnitTest.java => ActivityProfileUnitTest.java} (95%) rename public/java/test/org/broadinstitute/sting/utils/activeregion/{BandPassIncrementalActivityProfileUnitTest.java => BandPassActivityProfileUnitTest.java} (93%) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 436edbdf1..071b4d806 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -77,7 +77,7 @@ public class TraverseActiveRegions extends TraversalEngine myReads = new LinkedList(); private GenomeLoc spanOfLastReadSeen = null; - private IncrementalActivityProfile activityProfile = null; + private ActivityProfile activityProfile = null; int maxReadsInMemory = 0; @Override @@ -94,7 +94,7 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine activeRegions = activityProfile.popReadyActiveRegions(getActiveRegionExtension(), getMaxRegionSize(), flushActivityProfile); workQueue.addAll(activeRegions); - if ( logger.isDebugEnabled() ) logger.debug("Integrated " + activityProfile.size() + " isActive calls into " + activeRegions.size() + " regions." ); + if ( ! activeRegions.isEmpty() && logger.isDebugEnabled() ) logger.debug("Integrated " + activityProfile.size() + " isActive calls into " + activeRegions.size() + " regions." ); } if ( walker.activeRegionOutStream != null ) { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index 85d7c8293..e268bba0d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -61,6 +61,8 @@ import java.util.*; @ReadFilters({UnmappedReadFilter.class, NotPrimaryAlignmentFilter.class, DuplicateReadFilter.class, FailsVendorQualityCheckFilter.class, MappingQualityUnavailableFilter.class}) @RemoveProgramRecords public abstract class ActiveRegionWalker extends Walker { + @Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results bed file", required = false) + public PrintStream activityProfileOutStream = null; @Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this interval list file", required = false) public PrintStream activeRegionOutStream = null; diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegionReadState.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegionReadState.java index d9b458f51..5da88cb6d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegionReadState.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegionReadState.java @@ -26,12 +26,11 @@ package org.broadinstitute.sting.utils.activeregion; /** - * Created with IntelliJ IDEA. + * Describes how a read relates to an assigned ActiveRegion + * * User: thibault * Date: 11/26/12 * Time: 2:35 PM - * - * Describes how a read relates to an assigned ActiveRegion */ public enum ActiveRegionReadState { PRIMARY, // This is the read's primary region diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java similarity index 98% rename from public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java rename to public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 1292b3176..a863d695e 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -39,7 +39,7 @@ import java.util.*; * @author Mark DePristo * @since Date created */ -public class IncrementalActivityProfile { +public class ActivityProfile { private final static int MAX_PROB_PROPOGATION_DISTANCE = 10; private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author @@ -50,10 +50,10 @@ public class IncrementalActivityProfile { protected GenomeLoc regionStopLoc = null; /** - * Create a new empty IncrementalActivityProfile + * Create a new empty ActivityProfile * @param parser the parser we can use to create genome locs, cannot be null */ - public IncrementalActivityProfile(final GenomeLocParser parser) { + public ActivityProfile(final GenomeLocParser parser) { if ( parser == null ) throw new IllegalArgumentException("parser cannot be null"); this.parser = parser; @@ -79,7 +79,7 @@ public class IncrementalActivityProfile { * @return a positive integer distance in bp */ @Ensures("result >= 0") - public int getMaxProbPropogationDistance() { + public int getMaxProbPropagationDistance() { return MAX_PROB_PROPOGATION_DISTANCE; } @@ -377,6 +377,6 @@ public class IncrementalActivityProfile { } // we're one past the end, so i must be decremented - return forceConversion || i + getMaxProbPropogationDistance() < stateList.size() ? i - 1 : -1; + return forceConversion || i + getMaxProbPropagationDistance() < stateList.size() ? i - 1 : -1; } } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java index df21672a9..272596be3 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java @@ -30,7 +30,8 @@ import com.google.java.contract.Requires; import org.broadinstitute.sting.utils.GenomeLoc; /** - * Created with IntelliJ IDEA. + * The state of an active region walker's isActive call at a specific locus in the genome + * * User: rpoplin * Date: 7/27/12 */ diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java similarity index 87% rename from public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java rename to public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java index 805a0b60a..1a8bac086 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -42,7 +42,7 @@ import java.util.LinkedList; * @author Mark DePristo * @since 2011 */ -public class BandPassIncrementalActivityProfile extends IncrementalActivityProfile { +public class BandPassActivityProfile extends ActivityProfile { public static final int DEFAULT_FILTER_SIZE = 80; private final int filterSize; @@ -52,7 +52,7 @@ public class BandPassIncrementalActivityProfile extends IncrementalActivityProfi * Create a band pass activity profile with the default band size * @param parser our genome loc parser */ - public BandPassIncrementalActivityProfile(final GenomeLocParser parser) { + public BandPassActivityProfile(final GenomeLocParser parser) { this(parser, DEFAULT_FILTER_SIZE); } @@ -63,7 +63,7 @@ public class BandPassIncrementalActivityProfile extends IncrementalActivityProfi * side that are included in the band. So a filter size of 1 implies that the actual band * is 3 bp, 1 for the center site and 1 on each size. 2 => 5, etc. */ - public BandPassIncrementalActivityProfile(final GenomeLocParser parser, final int filterSize) { + public BandPassActivityProfile(final GenomeLocParser parser, final int filterSize) { super(parser); if ( filterSize < 0 ) throw new IllegalArgumentException("Filter size must be greater than or equal to 0 but got " + filterSize); @@ -77,6 +77,19 @@ public class BandPassIncrementalActivityProfile extends IncrementalActivityProfi this.GaussianKernel = MathUtils.normalizeFromRealSpace(kernel); } + /** + * Our maximize propagation distance is whatever our parent's is, plus our filter size + * + * Stops the profile from interpreting sites that aren't yet fully determined due to + * propagation of the probabilities. + * + * @return the distance in bp we might move our probabilities around for some site i + */ + @Override + public int getMaxProbPropagationDistance() { + return super.getMaxProbPropagationDistance() + filterSize; + } + /** * Get the size (in bp) of the band pass filter * @return a positive integer diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java similarity index 95% rename from public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index 64065029c..7cfc5ebb7 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/IncrementalActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -45,7 +45,7 @@ import java.io.FileNotFoundException; import java.util.*; -public class IncrementalActivityProfileUnitTest extends BaseTest { +public class ActivityProfileUnitTest extends BaseTest { private GenomeLocParser genomeLocParser; private GenomeLoc startLoc; @@ -82,12 +82,12 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { return String.format("type=%s probs=%s expectedRegions=%s", type, Utils.join(",", probs), Utils.join(",", expectedRegions)); } - public IncrementalActivityProfile makeProfile() { + public ActivityProfile makeProfile() { switch ( type ) { - case Base: return new IncrementalActivityProfile(genomeLocParser); + case Base: return new ActivityProfile(genomeLocParser); case BandPass: - // zero size => equivalent to IncrementalActivityProfile - return new BandPassIncrementalActivityProfile(genomeLocParser, 0); + // zero size => equivalent to ActivityProfile + return new BandPassActivityProfile(genomeLocParser, 0); default: throw new IllegalStateException(type.toString()); } } @@ -125,7 +125,7 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { @Test(dataProvider = "BasicActivityProfileTestProvider") public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) { - IncrementalActivityProfile profile = cfg.makeProfile(); + ActivityProfile profile = cfg.makeProfile(); Assert.assertTrue(profile.isEmpty()); @@ -228,7 +228,7 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { @Test(enabled = true, dataProvider = "RegionCreationTests") public void testRegionCreation(final int start, final List probs, int maxRegionSize, final int nParts, final boolean forceConversion, final boolean waitUntilEnd) { - final IncrementalActivityProfile profile = new IncrementalActivityProfile(genomeLocParser); + final ActivityProfile profile = new ActivityProfile(genomeLocParser); Assert.assertNotNull(profile.toString()); final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); @@ -253,7 +253,7 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { } for ( int i = 0; i < probs.size(); i++ ) { - if ( forceConversion || (i + maxRegionSize + profile.getMaxProbPropogationDistance() < probs.size())) + if ( forceConversion || (i + maxRegionSize + profile.getMaxProbPropagationDistance() < probs.size())) // only require a site to be seen if we are forcing conversion or the site is more than maxRegionSize from the end Assert.assertTrue(seenSites.get(i), "Missed site " + i); } @@ -314,7 +314,7 @@ public class IncrementalActivityProfileUnitTest extends BaseTest { @Test(dataProvider = "SoftClipsTest") public void testSoftClips(final int start, int nPrecedingSites, final int softClipSize) { - final IncrementalActivityProfile profile = new IncrementalActivityProfile(genomeLocParser); + final ActivityProfile profile = new ActivityProfile(genomeLocParser); final int contigLength = genomeLocParser.getContigs().getSequences().get(0).getSequenceLength(); final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java similarity index 93% rename from public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index be90353b3..a2a85f1d0 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassIncrementalActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -35,7 +35,6 @@ import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -47,7 +46,7 @@ import java.io.FileNotFoundException; import java.util.*; -public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { +public class BandPassActivityProfileUnitTest extends BaseTest { private GenomeLocParser genomeLocParser; @BeforeClass @@ -80,7 +79,7 @@ public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { @Test(dataProvider = "BandPassBasicTest") public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize) { - final BandPassIncrementalActivityProfile profile = new BandPassIncrementalActivityProfile(genomeLocParser, bandPassSize); + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize); final int expectedBandSize = bandPassSize * 2 + 1; Assert.assertEquals(profile.getBandSize(), expectedBandSize, "Wrong expected band size"); @@ -103,7 +102,7 @@ public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { } } - private double[] bandPassInOnePass(final BandPassIncrementalActivityProfile profile, final double[] activeProbArray) { + private double[] bandPassInOnePass(final BandPassActivityProfile profile, final double[] activeProbArray) { final double[] bandPassProbArray = new double[activeProbArray.length]; // apply the band pass filter for activeProbArray into filteredProbArray @@ -121,7 +120,7 @@ public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { public Object[][] makeBandPassComposition() { final List tests = new LinkedList(); - for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassIncrementalActivityProfile.DEFAULT_FILTER_SIZE) ) { + for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassActivityProfile.DEFAULT_FILTER_SIZE) ) { for ( int integrationLength : Arrays.asList(1, 10, 100, 1000) ) { tests.add(new Object[]{ bandPassSize, integrationLength }); } @@ -133,7 +132,7 @@ public class BandPassIncrementalActivityProfileUnitTest extends BaseTest { @Test( dataProvider = "BandPassComposition") public void testBandPassComposition(final int bandPassSize, final int integrationLength) { final int start = 1; - final BandPassIncrementalActivityProfile profile = new BandPassIncrementalActivityProfile(genomeLocParser, bandPassSize); + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize); final double[] rawActiveProbs = new double[integrationLength + bandPassSize * 2]; // add a buffer so that we can get all of the band pass values From 8026199e4cfc2cb7dba2b8f9129b7060a7a86ef9 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 09:47:22 -0500 Subject: [PATCH 063/188] Updating md5s for CountReadsInActiveRegions and HaplotypeCaller to reflect new activity profile mechanics -- In this process I discovered a few missed sites in the old code. The new approach actually produces better HC results than the previous version. --- .../HaplotypeCallerIntegrationTest.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 939b9873c..41f9ab680 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "b8f7b741445ce6b6ea491c794ce75c17"); + HCTest(CEUTRIO_BAM, "", "c142bc73447c72286ca48f4a4966d9b6"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "a2c63f6e6e51a01019bdbd23125bdb15"); + HCTest(NA12878_BAM, "", "d172eb9447015ea50220c6947be145ea"); } @Test(enabled = false) @@ -84,7 +84,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "c679ae7f04bdfda896b5c046d35e043c"); + "2c56ffc3b7fbbf154ae9ca355780a78f"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -96,13 +96,13 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAComplex() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:119673-119823 -L 20:121408-121538", - "8730a9ebaeecae913dca2fb5a0d4e946"); + "66bd513d25b691a5b0c5084924b4a308"); } @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "d590c8d6d5e58d685401b65a23846893"); + "d0fcbfa2ccce0ca4a2e81f31dc43d79d"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "6c0c441b71848c2eea38ab5e2afe1120"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "7e8a6ed62f866fc47c92af0e255ca180"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "29f1125df5ab27cc937a144ae08ac735"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "602aabbbe710ac90b16e474c869e8a86"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,14 +146,14 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("31db0a2d9eb07f86e0a89f0d97169072")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("c23b589be3072027ff2da93067dbf549")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @Test public void HCTestStructuralIndels() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "AFR.structural.indels.bam") + " --no_cmdline_in_header -o %s -minPruning 6 -L 20:8187565-8187800 -L 20:18670537-18670730"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("add0f4f51969b7caeea99005a7ba1aa4")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("a612fe84dd7f80c4ad2d20d27fc6744e")); executeTest("HCTestStructuralIndels: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("8a400b0c46f41447fcc35a907e34f384")); + Arrays.asList("0cb9132967fa9811e04f528be9f686dc")); executeTest("HC calling on a ReducedRead BAM", spec); } @@ -183,7 +183,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void testReducedBamWithReadsNotFullySpanningDeletion() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, - Arrays.asList("4e8121dd9dc90478f237bd6ae4d19920")); + Arrays.asList("36a90309dde1a325c274388e302ffaa5")); executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); } } From 09edc6baebe835cce54a9d77caac4406d9c43dd3 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 13:44:40 -0500 Subject: [PATCH 064/188] TraverseActiveRegions now writes out very nice active region and activity profile IGV formatted files --- .../traversals/TraverseActiveRegions.java | 169 +++++++++++++----- .../gatk/walkers/ActiveRegionWalker.java | 20 ++- .../utils/activeregion/ActiveRegion.java | 7 +- .../utils/activeregion/ActivityProfile.java | 6 +- 4 files changed, 156 insertions(+), 46 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 071b4d806..ac1c751ca 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -25,6 +25,7 @@ package org.broadinstitute.sting.gatk.traversals; +import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import org.apache.log4j.Logger; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; @@ -38,10 +39,12 @@ import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.activeregion.*; import org.broadinstitute.sting.utils.progressmeter.ProgressMeter; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import java.io.PrintStream; import java.util.*; /** @@ -79,26 +82,35 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine 0" + }) + private void printIGVFormatHeader(final PrintStream out, final String graphType, final String ... columns ) { + out.printf("#track graphType=%s%n", graphType); + out.printf("Chromosome\tStart\tEnd\tFeature\t%s%n", Utils.join("\t", columns)); + + } + + /** + * Helper function to write out a IGV formatted line to out, at loc, with values + * + * http://www.broadinstitute.org/software/igv/IGV + * + * @param out a non-null PrintStream where we'll write our line + * @param loc the location of values + * @param featureName string name of this feature (see IGV format) + * @param values the floating point values to associate with loc and feature name in out + */ + @Requires({ + "out != null", + "loc != null", + "values.length > 0" + }) + private void printIGVFormatRow(final PrintStream out, final GenomeLoc loc, final String featureName, final double ... values) { + // note that start and stop are 0 based, but the stop is exclusive so we don't subtract 1 + out.printf("%s\t%d\t%d\t%s", loc.getContig(), loc.getStart() - 1, loc.getStop(), featureName); + for ( final double value : values ) + out.print(String.format("\t%.3f", value)); + out.println(); + } + + /** + * Write out activity profile information, if requested by the walker + * + * @param states the states in the current activity profile + */ + @Requires("states != null") + private void writeActivityProfile(final List states) { + if ( walker.activityProfileOutStream != null ) { + initializeOutputStreamsIfNecessary(); + for ( final ActivityProfileState state : states ) { + printIGVFormatRow(walker.activityProfileOutStream, state.getLoc(), "state", state.isActiveProb); + } + } + } + + /** + * Write out each active region to the walker activeRegionOutStream + * + * @param region the region we're currently operating on + */ + @Requires("region != null") + private void writeActiveRegion(final ActiveRegion region) { + if( walker.activeRegionOutStream != null ) { + initializeOutputStreamsIfNecessary(); + printIGVFormatRow(walker.activeRegionOutStream, region.getLocation().getStartLocation(), + "end-marker", 0.0); + printIGVFormatRow(walker.activeRegionOutStream, region.getLocation(), + "size=" + region.getLocation().size(), region.isActive ? 1.0 : -1.0); + } + } + + // ------------------------------------------------------------------------------------- // // Functions to process active regions that are ready for map / reduce calls @@ -349,26 +459,6 @@ public class TraverseActiveRegions extends TraversalEngine walker ) { - // Just want to output the active regions to a file, not actually process them - for( final ActiveRegion activeRegion : workQueue ) { - if( activeRegion.isActive ) { - walker.activeRegionOutStream.println( activeRegion.getLocation() ); - } - } } /** @@ -384,23 +474,20 @@ public class TraverseActiveRegions extends TraversalEngine walker) { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index e268bba0d..24e512a7b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -61,10 +61,26 @@ import java.util.*; @ReadFilters({UnmappedReadFilter.class, NotPrimaryAlignmentFilter.class, DuplicateReadFilter.class, FailsVendorQualityCheckFilter.class, MappingQualityUnavailableFilter.class}) @RemoveProgramRecords public abstract class ActiveRegionWalker extends Walker { - @Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results bed file", required = false) + /** + * If provided, this walker will write out its activity profile (per bp probabilities of being active) + * to this file in the IGV formatted TAB deliminated output: + * + * http://www.broadinstitute.org/software/igv/IGV + * + * Intended to make debugging the activity profile calculations easier + */ + @Output(fullName="activityProfileOut", shortName="APO", doc="Output the raw activity profile results in IGV format", required = false) public PrintStream activityProfileOutStream = null; - @Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this interval list file", required = false) + /** + * If provided, this walker will write out its active and inactive regions + * to this file in the IGV formatted TAB deliminated output: + * + * http://www.broadinstitute.org/software/igv/IGV + * + * Intended to make debugging the active region calculations easier + */ + @Output(fullName="activeRegionOut", shortName="ARO", doc="Output the active region to this IGV formatted file", required = false) public PrintStream activeRegionOutStream = null; @Input(fullName="activeRegionIn", shortName="AR", doc="Use this interval list file as the active regions to process", required = false) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java index 8f04c09cb..66485c8cf 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import java.util.ArrayList; +import java.util.List; /** * Created by IntelliJ IDEA. @@ -44,6 +45,7 @@ import java.util.ArrayList; public class ActiveRegion implements HasGenomeLocation { private final ArrayList reads = new ArrayList(); + private final List supportingStates; private final GenomeLoc activeRegionLoc; private final GenomeLoc extendedLoc; private final int extension; @@ -51,8 +53,9 @@ public class ActiveRegion implements HasGenomeLocation { private final GenomeLocParser genomeLocParser; public final boolean isActive; - public ActiveRegion( final GenomeLoc activeRegionLoc, final boolean isActive, final GenomeLocParser genomeLocParser, final int extension ) { + public ActiveRegion( final GenomeLoc activeRegionLoc, final List supportingStates, final boolean isActive, final GenomeLocParser genomeLocParser, final int extension ) { this.activeRegionLoc = activeRegionLoc; + this.supportingStates = new ArrayList(supportingStates); this.isActive = isActive; this.genomeLocParser = genomeLocParser; this.extension = extension; @@ -112,6 +115,8 @@ public class ActiveRegion implements HasGenomeLocation { public GenomeLoc getExtendedLoc() { return extendedLoc; } public GenomeLoc getReferenceLoc() { return fullExtentReferenceLoc; } + public List getSupportingStates() { return supportingStates; } + public int getExtension() { return extension; } public int size() { return reads.size(); } public void clearReads() { reads.clear(); } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index a863d695e..ab9095106 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -336,7 +336,9 @@ public class ActivityProfile { return null; // we need to create the active region, and clip out the states we're extracting from this profile - stateList.subList(0, offsetOfNextRegionEnd + 1).clear(); + final List sub = stateList.subList(0, offsetOfNextRegionEnd + 1); + final List supportingStates = new ArrayList(sub); + sub.clear(); // update the start and stop locations as necessary if ( stateList.isEmpty() ) { @@ -345,7 +347,7 @@ public class ActivityProfile { regionStartLoc = stateList.get(0).getLoc(); } final GenomeLoc regionLoc = parser.createGenomeLoc(first.getLoc().getContig(), first.getLoc().getStart(), first.getLoc().getStart() + offsetOfNextRegionEnd); - return new ActiveRegion(regionLoc, isActiveRegion, parser, activeRegionExtension); + return new ActiveRegion(regionLoc, supportingStates, isActiveRegion, parser, activeRegionExtension); } /** From ee8039bf2559d7257f8c9ddc6724aef8fffea058 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 13:51:58 -0500 Subject: [PATCH 065/188] Fix trivial call in unit test --- .../sting/utils/activeregion/ActivityProfileUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index 7cfc5ebb7..311d43206 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -98,7 +98,7 @@ public class ActivityProfileUnitTest extends BaseTest { int start = regionStart.getStart() + startsAndStops[i]; int end = regionStart.getStart() + startsAndStops[i+1] - 1; GenomeLoc activeLoc = genomeLocParser.createGenomeLoc(regionStart.getContig(), start, end); - ActiveRegion r = new ActiveRegion(activeLoc, isActive, genomeLocParser, extension); + ActiveRegion r = new ActiveRegion(activeLoc, null, isActive, genomeLocParser, extension); l.add(r); isActive = ! isActive; } From 7fcfa4668cad4dd9d6ecf9b9c44b65850dfbfbf1 Mon Sep 17 00:00:00 2001 From: Chris Hartl Date: Wed, 23 Jan 2013 14:47:23 -0500 Subject: [PATCH 070/188] Since GenotypeConcordance is now a standalone walker, remove the old GenotypeConcordance evaluation module and the associated integration tests. --- .../evaluators/GenotypeConcordance.java | 273 ------------------ .../VariantEvalIntegrationTest.java | 16 - 2 files changed, 289 deletions(-) delete mode 100644 protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/GenotypeConcordance.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/GenotypeConcordance.java deleted file mode 100644 index bc38a63f7..000000000 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/GenotypeConcordance.java +++ /dev/null @@ -1,273 +0,0 @@ -/* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. -*/ - -package org.broadinstitute.sting.gatk.walkers.varianteval.evaluators; - -import org.apache.log4j.Logger; -import org.broadinstitute.sting.gatk.contexts.AlignmentContext; -import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.varianteval.util.Analysis; -import org.broadinstitute.sting.gatk.walkers.varianteval.util.Molten; -import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.variant.variantcontext.Genotype; -import org.broadinstitute.variant.variantcontext.GenotypeType; -import org.broadinstitute.variant.variantcontext.VariantContext; - -import java.util.*; - -/* - * Copyright (c) 2010 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. - */ - -/** - * a table of sample names to genotype concordance figures - */ -@Analysis(name = "Genotype Concordance Detailed", description = "Determine the genotype concordance between the genotypes in difference tracks, and concordance statistics") -public class GenotypeConcordance extends VariantEvaluator { - protected final static Logger logger = Logger.getLogger(GenotypeConcordance.class); - - @Molten(variableFormat = "%s", valueFormat = "%s") - public final Map map = new TreeMap(); - - // concordance counts - private final long[][] truthByCalledGenotypeCounts; - - /** - * Initialize this object - */ - public GenotypeConcordance() { - final int nGenotypeTypes = GenotypeType.values().length; - truthByCalledGenotypeCounts = new long[nGenotypeTypes][nGenotypeTypes]; - } - - @Override - public int getComparisonOrder() { - return 2; - } - - @Override - public void update2(VariantContext eval, VariantContext validation, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { - // sanity check that we at least have either eval or validation data - if ( (validation != null && !validation.hasGenotypes()) || eval == null && !isValidVC(validation)) { - return; - } else { - final boolean validationIsValidVC = isValidVC(validation); - - // determine concordance for eval data - if (eval != null) { - for (final Genotype g : eval.getGenotypes() ) { - final String sample = g.getSampleName(); - final GenotypeType called = g.getType(); - final GenotypeType truth; - - if (!validationIsValidVC || !validation.hasGenotype(sample)) { - truth = GenotypeType.NO_CALL; - } else { - truth = validation.getGenotype(sample).getType(); - } - - incrValue(truth, called); - } - } - - // otherwise, mark no-calls for all samples - else { - final GenotypeType called = GenotypeType.NO_CALL; - - for (final Genotype g : validation.getGenotypes()) { - final GenotypeType truth = g.getType(); - incrValue(truth, called); - - // print out interesting sites - /* - if ( PRINT_INTERESTING_SITES && super.getVEWalker().gcLog != null ) { - if ( (truth == GenotypeType.HOM_VAR || truth == GenotypeType.HET) && called == GenotypeType.NO_CALL ) { - super.getVEWalker().gcLog.printf("%s FN %s%n", group, validation); - } - if ( (called == GenotypeType.HOM_VAR || called == GenotypeType.HET) && truth == GenotypeType.HOM_REF ) { - super.getVEWalker().gcLog.printf("%s FP %s%n", group, validation); - } - } - */ - } - } - } - } - - private static boolean isValidVC(final VariantContext vc) { - return (vc != null && !vc.isFiltered()); - } - - /** - * increment the specified value - * @param truth the truth type - * @param called the called type - */ - private void incrValue(final GenotypeType truth, final GenotypeType called) { - truthByCalledGenotypeCounts[truth.ordinal()][called.ordinal()]++; - } - - private long count(final GenotypeType truth, final GenotypeType called) { - return truthByCalledGenotypeCounts[truth.ordinal()][called.ordinal()]; - } - - private long count(final EnumSet truth, final GenotypeType called) { - return count(truth, EnumSet.of(called)); - } - - private long count(final GenotypeType truth, final EnumSet called) { - return count(EnumSet.of(truth), called); - } - - private long count(final EnumSet truth, final EnumSet called) { - long sum = 0; - for ( final GenotypeType truth1 : truth ) { - for ( final GenotypeType called1 : called ) { - sum += count(truth1, called1); - } - } - return sum; - } - - private long countDiag( final EnumSet d1 ) { - long sum = 0; - - for(final GenotypeType e1 : d1 ) { - sum += truthByCalledGenotypeCounts[e1.ordinal()][e1.ordinal()]; - } - - return sum; - } - - @Override - public void finalizeEvaluation() { - final EnumSet allVariantGenotypes = EnumSet.of(GenotypeType.HOM_VAR, GenotypeType.HET); - final EnumSet allCalledGenotypes = EnumSet.of(GenotypeType.HOM_VAR, GenotypeType.HET, GenotypeType.HOM_REF); - final EnumSet allGenotypes = EnumSet.allOf(GenotypeType.class); - - // exact values of the table - for ( final GenotypeType truth : GenotypeType.values() ) { - for ( final GenotypeType called : GenotypeType.values() ) { - final String field = String.format("n_true_%s_called_%s", truth, called); - final Long value = count(truth, called); - map.put(field, value.toString()); - } - } - - // counts of called genotypes - for ( final GenotypeType called : GenotypeType.values() ) { - final String field = String.format("total_called_%s", called); - final Long value = count(allGenotypes, called); - map.put(field, value.toString()); - } - - // counts of true genotypes - for ( final GenotypeType truth : GenotypeType.values() ) { - final String field = String.format("total_true_%s", truth); - final Long value = count(truth, allGenotypes); - map.put(field, value.toString()); - } - - for ( final GenotypeType genotype : GenotypeType.values() ) { - final String field = String.format("percent_%s_called_%s", genotype, genotype); - long numer = count(genotype, genotype); - long denom = count(EnumSet.of(genotype), allGenotypes); - map.put(field, Utils.formattedPercent(numer, denom)); - } - - { - // % non-ref called as non-ref - // MAD: this is known as the non-reference sensitivity (# non-ref according to comp found in eval / # non-ref in comp) - final String field = "percent_non_reference_sensitivity"; - long numer = count(allVariantGenotypes, allVariantGenotypes); - long denom = count(allVariantGenotypes, allGenotypes); - map.put(field, Utils.formattedPercent(numer, denom)); - } - - { - // overall genotype concordance of sites called in eval track - // MAD: this is the tradition genotype concordance - final String field = "percent_overall_genotype_concordance"; - long numer = countDiag(allCalledGenotypes); - long denom = count(allCalledGenotypes, allCalledGenotypes); - map.put(field, Utils.formattedPercent(numer, denom)); - } - - { - // overall genotype concordance of sites called non-ref in eval track - // MAD: this is the non-reference discrepancy rate - final String field = "percent_non_reference_discrepancy_rate"; - long homrefConcords = count(GenotypeType.HOM_REF, GenotypeType.HOM_REF); - long allNoHomRef = count(allCalledGenotypes, allCalledGenotypes) - homrefConcords; - long numer = allNoHomRef - countDiag(allVariantGenotypes); - long denom = count(allCalledGenotypes, allCalledGenotypes) - homrefConcords; - map.put(field, Utils.formattedPercent(numer, denom)); - } - } -} - diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalIntegrationTest.java index 748a16db9..d695f2d13 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalIntegrationTest.java @@ -334,16 +334,6 @@ public class VariantEvalIntegrationTest extends WalkerTest { executeTestParallel("testSelect1", spec); } - @Test - public void testVEGenotypeConcordance() { - String vcfFile = "GenotypeConcordanceEval.vcf"; - - WalkerTestSpec spec = new WalkerTestSpec(cmdRoot + " -ST CpG --eval:VCF3 " + validationDataLocation + vcfFile + " --comp:VCF3 " + validationDataLocation + "GenotypeConcordanceComp.vcf -noEV -EV GenotypeConcordance -o %s", - 1, - Arrays.asList("810d55b67de592f6375d9dfb282145ef")); - executeTestParallel("testVEGenotypeConcordance" + vcfFile, spec); - } - @Test public void testVEMendelianViolationEvaluator() { String vcfFile = "/MendelianViolationEval.vcf"; @@ -355,12 +345,6 @@ public class VariantEvalIntegrationTest extends WalkerTest { executeTestParallel("testVEMendelianViolationEvaluator" + vcfFile, spec); } - @Test - public void testCompVsEvalAC() { - String extraArgs = "-T VariantEval -R "+b36KGReference+" -o %s -ST CpG -EV GenotypeConcordance --eval:evalYRI,VCF3 " + validationDataLocation + "yri.trio.gatk.ug.very.few.lines.vcf --comp:compYRI,VCF3 " + validationDataLocation + "yri.trio.gatk.fake.genotypes.ac.test.vcf"; - WalkerTestSpec spec = new WalkerTestSpec(extraArgs,1,Arrays.asList("659a15cc842f0310106fa595a26da71d")); - executeTestParallel("testCompVsEvalAC",spec); - } private static String withSelect(String cmd, String select, String name) { return String.format("%s -select '%s' -selectName %s", cmd, select, name); From 643a508564fc8345a79bf49df42e7fc04661182b Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Wed, 23 Jan 2013 20:53:36 -0700 Subject: [PATCH 072/188] Added atlassian intellij plugin file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 927caf98d..6e2c2f224 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ dist/ dump/ lib/ out/ +/atlassian-ide-plugin.xml From 6790e103e00704640effc7710e1c0f819a2e8104 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Thu, 24 Jan 2013 11:42:49 -0500 Subject: [PATCH 078/188] Moving lots of walkers back from protected to public (along with several of the VA annotations). Let's see whether Mauricio's automatic git hook really works! --- .../sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java | 0 .../sting/gatk/walkers/annotator/AlleleBalance.java | 0 .../sting/gatk/walkers/annotator/AlleleBalanceBySample.java | 0 .../sting/gatk/walkers/annotator/AverageAltAlleleLength.java | 0 .../broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java | 0 .../org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java | 0 .../sting/gatk/walkers/annotator/MappingQualityZeroBySample.java | 0 .../sting/gatk/walkers/annotator/MappingQualityZeroFraction.java | 0 .../broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java | 0 .../org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java | 0 .../sting/gatk/walkers/annotator/TechnologyComposition.java | 0 .../sting/gatk/walkers/annotator/VariantAnnotator.java | 0 .../sting/gatk/walkers/annotator/VariantAnnotatorEngine.java | 0 .../walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java | 0 .../walkers/annotator/interfaces/AnnotationInterfaceManager.java | 0 .../sting/gatk/walkers/annotator/interfaces/AnnotationType.java | 0 .../gatk/walkers/annotator/interfaces/AnnotatorCompatible.java | 0 .../gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java | 0 .../gatk/walkers/annotator/interfaces/GenotypeAnnotation.java | 0 .../gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java | 0 .../gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java | 0 .../gatk/walkers/annotator/interfaces/StandardAnnotation.java | 0 .../walkers/annotator/interfaces/VariantAnnotatorAnnotation.java | 0 .../walkers/annotator/interfaces/WorkInProgressAnnotation.java | 0 .../sting/gatk/walkers/beagle/BeagleOutputToVCF.java | 0 .../sting/gatk/walkers/beagle/ProduceBeagleInput.java | 0 .../sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java | 0 .../sting/gatk/walkers/coverage/DepthOfCoverage.java | 0 .../sting/gatk/walkers/coverage/DepthOfCoverageStats.java | 0 .../sting/gatk/walkers/diffengine/BAMDiffableReader.java | 0 .../sting/gatk/walkers/diffengine/GATKReportDiffableReader.java | 0 .../sting/gatk/walkers/diffengine/VCFDiffableReader.java | 0 .../sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java | 0 .../sting/gatk/walkers/fasta/FastaReferenceMaker.java | 0 .../broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java | 0 .../broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java | 0 .../sting/gatk/walkers/filters/FiltrationContext.java | 0 .../sting/gatk/walkers/filters/FiltrationContextWindow.java | 0 .../sting/gatk/walkers/filters/VariantFiltration.java | 0 .../sting/gatk/walkers/validation/ValidationAmplicons.java | 0 .../sting/gatk/walkers/varianteval/VariantEval.java | 0 .../sting/gatk/walkers/varianteval/VariantEvalReportWriter.java | 0 .../sting/gatk/walkers/varianteval/evaluators/CompOverlap.java | 0 .../sting/gatk/walkers/varianteval/evaluators/CountVariants.java | 0 .../gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java | 0 .../sting/gatk/walkers/varianteval/evaluators/IndelSummary.java | 0 .../varianteval/evaluators/MendelianViolationEvaluator.java | 0 .../gatk/walkers/varianteval/evaluators/MultiallelicSummary.java | 0 .../gatk/walkers/varianteval/evaluators/PrintMissingComp.java | 0 .../sting/gatk/walkers/varianteval/evaluators/StandardEval.java | 0 .../walkers/varianteval/evaluators/ThetaVariantEvaluator.java | 0 .../gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java | 0 .../gatk/walkers/varianteval/evaluators/ValidationReport.java | 0 .../gatk/walkers/varianteval/evaluators/VariantEvaluator.java | 0 .../sting/gatk/walkers/varianteval/evaluators/VariantSummary.java | 0 .../gatk/walkers/varianteval/stratifications/AlleleCount.java | 0 .../gatk/walkers/varianteval/stratifications/AlleleFrequency.java | 0 .../sting/gatk/walkers/varianteval/stratifications/CompRod.java | 0 .../sting/gatk/walkers/varianteval/stratifications/Contig.java | 0 .../sting/gatk/walkers/varianteval/stratifications/CpG.java | 0 .../gatk/walkers/varianteval/stratifications/Degeneracy.java | 0 .../varianteval/stratifications/DynamicStratification.java | 0 .../sting/gatk/walkers/varianteval/stratifications/EvalRod.java | 0 .../sting/gatk/walkers/varianteval/stratifications/Filter.java | 0 .../gatk/walkers/varianteval/stratifications/FunctionalClass.java | 0 .../sting/gatk/walkers/varianteval/stratifications/IndelSize.java | 0 .../varianteval/stratifications/IntervalStratification.java | 0 .../gatk/walkers/varianteval/stratifications/JexlExpression.java | 0 .../sting/gatk/walkers/varianteval/stratifications/Novelty.java | 0 .../gatk/walkers/varianteval/stratifications/OneBPIndel.java | 0 .../varianteval/stratifications/RequiredStratification.java | 0 .../sting/gatk/walkers/varianteval/stratifications/Sample.java | 0 .../varianteval/stratifications/StandardStratification.java | 0 .../gatk/walkers/varianteval/stratifications/TandemRepeat.java | 0 .../walkers/varianteval/stratifications/VariantStratifier.java | 0 .../gatk/walkers/varianteval/stratifications/VariantType.java | 0 .../walkers/varianteval/stratifications/manager/StratNode.java | 0 .../varianteval/stratifications/manager/StratNodeIterator.java | 0 .../stratifications/manager/StratificationManager.java | 0 .../walkers/varianteval/stratifications/manager/Stratifier.java | 0 .../sting/gatk/walkers/varianteval/util/Analysis.java | 0 .../gatk/walkers/varianteval/util/AnalysisModuleScanner.java | 0 .../sting/gatk/walkers/varianteval/util/DataPoint.java | 0 .../sting/gatk/walkers/varianteval/util/EvaluationContext.java | 0 .../sting/gatk/walkers/varianteval/util/Molten.java | 0 .../gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java | 0 .../sting/gatk/walkers/varianteval/util/VariantEvalUtils.java | 0 .../gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java | 0 .../sting/gatk/walkers/variantutils/ConcordanceMetrics.java | 0 .../sting/gatk/walkers/variantutils/FilterLiftedVariants.java | 0 .../sting/gatk/walkers/variantutils/GenotypeConcordance.java | 0 .../sting/gatk/walkers/variantutils/LeftAlignVariants.java | 0 .../sting/gatk/walkers/variantutils/LiftoverVariants.java | 0 .../sting/gatk/walkers/variantutils/RandomlySplitVariants.java | 0 .../sting/gatk/walkers/variantutils/SelectHeaders.java | 0 .../sting/gatk/walkers/variantutils/ValidateVariants.java | 0 .../gatk/walkers/variantutils/VariantValidationAssessor.java | 0 .../sting/gatk/walkers/variantutils/VariantsToBinaryPed.java | 0 .../sting/gatk/walkers/variantutils/VariantsToTable.java | 0 .../sting/gatk/walkers/variantutils/VariantsToVCF.java | 0 .../sting/utils/genotyper/PerReadAlleleLikelihoodMap.java | 0 101 files changed, 0 insertions(+), 0 deletions(-) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java (100%) rename {protected => public}/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java (100%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java b/public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java rename to public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java diff --git a/protected/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java similarity index 100% rename from protected/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java rename to public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java From cd91e365f4a4f0dfb75a2455e80dc3447f676e22 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 14:13:21 -0500 Subject: [PATCH 080/188] Optimize getCurrentContigLength and getLocForOffset in ActivityProfile --- .../sting/utils/activeregion/ActivityProfile.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index ab9095106..80484e12f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -49,6 +49,12 @@ public class ActivityProfile { protected GenomeLoc regionStartLoc = null; protected GenomeLoc regionStopLoc = null; + /** + * A cached value of the regionStartLoc contig length, to make calls to + * getCurrentContigLength efficient + */ + protected int contigLength = -1; + /** * Create a new empty ActivityProfile * @param parser the parser we can use to create genome locs, cannot be null @@ -155,7 +161,7 @@ public class ActivityProfile { if ( start < 0 || start > getCurrentContigLength() ) { return null; } else { - return parser.createGenomeLoc(regionStartLoc.getContig(), start); + return parser.createGenomeLoc(regionStartLoc.getContig(), regionStartLoc.getContigIndex(), start, start); } } @@ -166,8 +172,7 @@ public class ActivityProfile { @Requires("regionStartLoc != null") @Ensures("result > 0") private int getCurrentContigLength() { - // TODO -- fix performance problem with getContigInfo - return parser.getContigInfo(regionStartLoc.getContig()).getSequenceLength(); + return contigLength; } // -------------------------------------------------------------------------------- @@ -190,6 +195,7 @@ public class ActivityProfile { if ( regionStartLoc == null ) { regionStartLoc = loc; regionStopLoc = loc; + contigLength = parser.getContigInfo(regionStartLoc.getContig()).getSequenceLength(); } else { // TODO -- need to figure out where to add loc as the regions will be popping off the front if ( regionStopLoc.getStart() != loc.getStart() - 1 ) From 9e43a2028d3f172782b648ebf56b6a4bf14d4025 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 14:50:14 -0500 Subject: [PATCH 081/188] Making band pass filter size, sigma, active region max size and extension all accessible from the command line --- .../traversals/TraverseActiveRegions.java | 9 ++++++--- .../gatk/walkers/ActiveRegionExtension.java | 16 +++++++++++++++ .../gatk/walkers/ActiveRegionWalker.java | 20 ++++++++++++++++--- .../broadinstitute/sting/utils/MathUtils.java | 2 +- .../activeregion/BandPassActivityProfile.java | 19 +++++++++++++++--- .../BandPassActivityProfileUnitTest.java | 12 +++++++---- 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index ac1c751ca..21971e189 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -102,11 +102,14 @@ public class TraverseActiveRegions extends TraversalEngine extends Walker> activeRegionBindings = null; + @Advanced + @Argument(fullName="activeRegionExtension", shortName="activeRegionExtension", doc="The active region extension; if not provided defaults to Walker annotated default", required = false) + public Integer activeRegionExtension = null; + + @Advanced + @Argument(fullName="activeRegionMaxSize", shortName="activeRegionMaxSize", doc="The active region maximum size; if not provided defaults to Walker annotated default", required = false) + public Integer activeRegionMaxSize = null; + + @Advanced + @Argument(fullName="bandPassFilterSize", shortName="bandPassFilterSize", doc="The filter size of band pass filter; if not provided defaults to Walker annotated default", required = false) + public Integer bandPassFilterSize = null; + + @Advanced + @Argument(fullName="bandPassSigma", shortName="bandPassSigma", doc="The sigma of the band pass filter Gaussian kernel; if not provided defaults to Walker annotated default", required = false) + public Double bandPassSigma = null; + private GenomeLocSortedSet presetActiveRegions = null; @Override diff --git a/public/java/src/org/broadinstitute/sting/utils/MathUtils.java b/public/java/src/org/broadinstitute/sting/utils/MathUtils.java index f1f0ab9b1..0c3ed87c0 100644 --- a/public/java/src/org/broadinstitute/sting/utils/MathUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/MathUtils.java @@ -651,7 +651,7 @@ public class MathUtils { final double sum = sum(array); final double[] normalized = new double[array.length]; - if ( sum < 0.0 || sum > 1.0 ) throw new IllegalArgumentException("Values in probability array sum to a negative number " + sum); + if ( sum < 0.0 ) throw new IllegalArgumentException("Values in probability array sum to a negative number " + sum); for ( int i = 0; i < array.length; i++ ) { normalized[i] = array[i] / sum; } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java index 1a8bac086..5c6389c26 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -44,8 +44,10 @@ import java.util.LinkedList; */ public class BandPassActivityProfile extends ActivityProfile { public static final int DEFAULT_FILTER_SIZE = 80; + public static final double DEFAULT_SIGMA = 55.0; private final int filterSize; + private final double sigma; private final double[] GaussianKernel; /** @@ -53,7 +55,7 @@ public class BandPassActivityProfile extends ActivityProfile { * @param parser our genome loc parser */ public BandPassActivityProfile(final GenomeLocParser parser) { - this(parser, DEFAULT_FILTER_SIZE); + this(parser, DEFAULT_FILTER_SIZE, DEFAULT_SIGMA); } /** @@ -63,16 +65,18 @@ public class BandPassActivityProfile extends ActivityProfile { * side that are included in the band. So a filter size of 1 implies that the actual band * is 3 bp, 1 for the center site and 1 on each size. 2 => 5, etc. */ - public BandPassActivityProfile(final GenomeLocParser parser, final int filterSize) { + public BandPassActivityProfile(final GenomeLocParser parser, final int filterSize, final double sigma) { super(parser); if ( filterSize < 0 ) throw new IllegalArgumentException("Filter size must be greater than or equal to 0 but got " + filterSize); + if ( sigma < 0 ) throw new IllegalArgumentException("Sigma must be greater than or equal to 0 but got " + sigma); // setup the Gaussian kernel for the band pass filter this.filterSize = filterSize; + this.sigma = sigma; final double[] kernel = new double[getBandSize()]; for( int iii = 0; iii < 2* filterSize + 1; iii++ ) { - kernel[iii] = MathUtils.NormalDistribution(filterSize, 55.0, iii); + kernel[iii] = MathUtils.NormalDistribution(filterSize, sigma, iii); } this.GaussianKernel = MathUtils.normalizeFromRealSpace(kernel); } @@ -108,6 +112,15 @@ public class BandPassActivityProfile extends ActivityProfile { return filterSize; } + /** + * Get the Gaussian kernel sigma value + * @return a positive double + */ + @Ensures("result >= 0") + public double getSigma() { + return sigma; + } + /** * Get the kernel of this band pass filter. Do not modify returned result * @return the kernel used in this band pass filter diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index a2a85f1d0..0a71bad14 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -64,11 +64,13 @@ public class BandPassActivityProfileUnitTest extends BaseTest { for ( boolean precedingIsActive : Arrays.asList(true, false) ) { for ( int precedingSites: Arrays.asList(0, 1, 10, 100) ) { for ( int bandPassSize : Arrays.asList(0, 1, 10, 100) ) { + for ( double sigma : Arrays.asList(1.0, 2.0, BandPassActivityProfile.DEFAULT_SIGMA) ) { // for ( int start : Arrays.asList(10) ) { // for ( boolean precedingIsActive : Arrays.asList(false) ) { // for ( int precedingSites: Arrays.asList(0) ) { // for ( int bandPassSize : Arrays.asList(1) ) { - tests.add(new Object[]{ start, precedingIsActive, precedingSites, bandPassSize }); + tests.add(new Object[]{ start, precedingIsActive, precedingSites, bandPassSize, sigma }); + } } } } @@ -78,10 +80,12 @@ public class BandPassActivityProfileUnitTest extends BaseTest { } @Test(dataProvider = "BandPassBasicTest") - public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize) { - final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize); + public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize, final double sigma) { + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, sigma); final int expectedBandSize = bandPassSize * 2 + 1; + Assert.assertEquals(profile.getFilteredSize(), bandPassSize, "Wrong filter size"); + Assert.assertEquals(profile.getSigma(), sigma, "Wrong sigma"); Assert.assertEquals(profile.getBandSize(), expectedBandSize, "Wrong expected band size"); final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); @@ -132,7 +136,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { @Test( dataProvider = "BandPassComposition") public void testBandPassComposition(final int bandPassSize, final int integrationLength) { final int start = 1; - final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize); + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, BandPassActivityProfile.DEFAULT_SIGMA); final double[] rawActiveProbs = new double[integrationLength + bandPassSize * 2]; // add a buffer so that we can get all of the band pass values From 0c94e3d96e0a6c1251bb814fbbd18e9a93511d57 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 15:41:56 -0500 Subject: [PATCH 082/188] Adaptively compute the band pass filter from the sigma, up to a maximum size of 50 bp -- Previously we allowed band pass filter size to be specified along with the sigma. But now that sigma is controllable from walkers and from the command line, we instead compute the filter size given the kernel from the sigma, including all kernel points with p > 1e-5 in the kernel. This means that if you use a smaller kernel you get a small band size and therefore faster ART -- Update, as discussed with Ryan, the sigma and band size to 17 bp for HC (default ART wide) and max band size of 50 bp --- .../traversals/TraverseActiveRegions.java | 3 +- .../gatk/walkers/ActiveRegionExtension.java | 8 --- .../gatk/walkers/ActiveRegionWalker.java | 4 -- .../activeregion/BandPassActivityProfile.java | 52 +++++++++++------- .../activeregion/ActivityProfileUnitTest.java | 4 +- .../BandPassActivityProfileUnitTest.java | 53 ++++++++++++++++++- 6 files changed, 87 insertions(+), 37 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 21971e189..52ac783a9 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -105,11 +105,10 @@ public class TraverseActiveRegions extends TraversalEngine extends Walker 5, etc. + * @param maxFilterSize the maximum size of the band pass filter we are allowed to create, regardless of sigma + * @param sigma the variance of the Gaussian kernel for this band pass filter */ - public BandPassActivityProfile(final GenomeLocParser parser, final int filterSize, final double sigma) { + public BandPassActivityProfile(final GenomeLocParser parser, final int maxFilterSize, final double sigma) { + this(parser, maxFilterSize, sigma, true); + } + + public BandPassActivityProfile(final GenomeLocParser parser, final int maxFilterSize, final double sigma, final boolean adaptiveFilterSize) { super(parser); - if ( filterSize < 0 ) throw new IllegalArgumentException("Filter size must be greater than or equal to 0 but got " + filterSize); if ( sigma < 0 ) throw new IllegalArgumentException("Sigma must be greater than or equal to 0 but got " + sigma); // setup the Gaussian kernel for the band pass filter - this.filterSize = filterSize; this.sigma = sigma; - final double[] kernel = new double[getBandSize()]; - for( int iii = 0; iii < 2* filterSize + 1; iii++ ) { + final double[] fullKernel = makeKernel(maxFilterSize, sigma); + this.filterSize = adaptiveFilterSize ? determineFilterSize(fullKernel, MIN_PROB_TO_KEEP_IN_FILTER) : maxFilterSize; + this.GaussianKernel = makeKernel(this.filterSize, sigma); + } + + protected static int determineFilterSize(final double[] kernel, final double minProbToKeepInFilter) { + final int middle = (kernel.length - 1) / 2; + int filterEnd = middle; + while ( filterEnd > 0 ) { + if ( kernel[filterEnd - 1] < minProbToKeepInFilter ) { + break; + } + filterEnd--; + } + return middle - filterEnd; + } + + protected static double[] makeKernel(final int filterSize, final double sigma) { + final int bandSize = 2 * filterSize + 1; + final double[] kernel = new double[bandSize]; + for( int iii = 0; iii < bandSize; iii++ ) { kernel[iii] = MathUtils.NormalDistribution(filterSize, sigma, iii); } - this.GaussianKernel = MathUtils.normalizeFromRealSpace(kernel); + return MathUtils.normalizeFromRealSpace(kernel); } /** diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index 311d43206..bce1722cd 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -87,7 +87,7 @@ public class ActivityProfileUnitTest extends BaseTest { case Base: return new ActivityProfile(genomeLocParser); case BandPass: // zero size => equivalent to ActivityProfile - return new BandPassActivityProfile(genomeLocParser, 0); + return new BandPassActivityProfile(genomeLocParser, 0, 0.01, false); default: throw new IllegalStateException(type.toString()); } } @@ -98,7 +98,7 @@ public class ActivityProfileUnitTest extends BaseTest { int start = regionStart.getStart() + startsAndStops[i]; int end = regionStart.getStart() + startsAndStops[i+1] - 1; GenomeLoc activeLoc = genomeLocParser.createGenomeLoc(regionStart.getContig(), start, end); - ActiveRegion r = new ActiveRegion(activeLoc, null, isActive, genomeLocParser, extension); + ActiveRegion r = new ActiveRegion(activeLoc, Collections.emptyList(), isActive, genomeLocParser, extension); l.add(r); isActive = ! isActive; } diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index 0a71bad14..ff1c9bdef 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -81,7 +81,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { @Test(dataProvider = "BandPassBasicTest") public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize, final double sigma) { - final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, sigma); + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, sigma, false); final int expectedBandSize = bandPassSize * 2 + 1; Assert.assertEquals(profile.getFilteredSize(), bandPassSize, "Wrong filter size"); @@ -124,7 +124,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { public Object[][] makeBandPassComposition() { final List tests = new LinkedList(); - for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassActivityProfile.DEFAULT_FILTER_SIZE) ) { + for ( int bandPassSize : Arrays.asList(0, 1, 10, 100, BandPassActivityProfile.MAX_FILTER_SIZE) ) { for ( int integrationLength : Arrays.asList(1, 10, 100, 1000) ) { tests.add(new Object[]{ bandPassSize, integrationLength }); } @@ -167,4 +167,53 @@ public class BandPassActivityProfileUnitTest extends BaseTest { Assert.assertEquals(profile.getStateList().get(j).isActiveProb, expectedProbs[j], "State probability not expected at " + j); } } + + // ------------------------------------------------------------------------------------ + // + // Code to test the creation of the kernels + // + // ------------------------------------------------------------------------------------ + + /** + + kernel <- function(sd, pThres) { + raw = dnorm(-80:81, mean=0, sd=sd) + norm = raw / sum(raw) + bad = norm < pThres + paste(norm[! bad], collapse=", ") + } + + print(kernel(0.01, 1e-5)) + print(kernel(1, 1e-5)) + print(kernel(5, 1e-5)) + print(kernel(17, 1e-5)) + + * @return + */ + + @DataProvider(name = "KernelCreation") + public Object[][] makeKernelCreation() { + final List tests = new LinkedList(); + + tests.add(new Object[]{ 0.01, 1000, new double[]{1.0}}); + tests.add(new Object[]{ 1.0, 1000, new double[]{0.0001338302, 0.004431848, 0.053990966, 0.241970723, 0.398942278, 0.241970723, 0.053990966, 0.004431848, 0.0001338302}}); + tests.add(new Object[]{ 1.0, 0, new double[]{1.0}}); + tests.add(new Object[]{ 1.0, 1, new double[]{0.2740686, 0.4518628, 0.2740686}}); + tests.add(new Object[]{ 1.0, 2, new double[]{0.05448868, 0.24420134, 0.40261995, 0.24420134, 0.05448868}}); + tests.add(new Object[]{ 1.0, 1000, new double[]{0.0001338302, 0.004431848, 0.053990966, 0.241970723, 0.398942278, 0.241970723, 0.053990966, 0.004431848, 0.0001338302}}); + tests.add(new Object[]{ 5.0, 1000, new double[]{1.1788613551308e-05, 2.67660451529771e-05, 5.83893851582921e-05, 0.000122380386022754, 0.000246443833694604, 0.000476817640292968, 0.000886369682387602, 0.00158309031659599, 0.00271659384673712, 0.00447890605896858, 0.00709491856924629, 0.0107981933026376, 0.0157900316601788, 0.0221841669358911, 0.029945493127149, 0.0388372109966426, 0.0483941449038287, 0.0579383105522965, 0.0666449205783599, 0.0736540280606647, 0.0782085387950912, 0.0797884560802865, 0.0782085387950912, 0.0736540280606647, 0.0666449205783599, 0.0579383105522965, 0.0483941449038287, 0.0388372109966426, 0.029945493127149, 0.0221841669358911, 0.0157900316601788, 0.0107981933026376, 0.00709491856924629, 0.00447890605896858, 0.00271659384673712, 0.00158309031659599, 0.000886369682387602, 0.000476817640292968, 0.000246443833694604, 0.000122380386022754, 5.83893851582921e-05, 2.67660451529771e-05, 1.1788613551308e-05}}); + tests.add(new Object[]{17.0, 1000, new double[]{1.25162575710745e-05, 1.57001772728555e-05, 1.96260034693739e-05, 2.44487374842009e-05, 3.03513668801384e-05, 3.75489089511911e-05, 4.62928204154855e-05, 5.68757597480354e-05, 6.96366758708924e-05, 8.49661819944029e-05, 0.000103312156275406, 0.000125185491708561, 0.000151165896477646, 0.000181907623161359, 0.000218144981137171, 0.000260697461819069, 0.000310474281706066, 0.000368478124457557, 0.000435807841336874, 0.00051365985048857, 0.000603327960854364, 0.000706201337376934, 0.000823760321812988, 0.000957569829285965, 0.00110927005589186, 0.00128056425833231, 0.00147320340358764, 0.00168896753568649, 0.00192964376796036, 0.00219700088266432, 0.00249276060490197, 0.00281856571330067, 0.00317594525418154, 0.00356627723683793, 0.00399074930220799, 0.00445031797242299, 0.00494566720070898, 0.00547716704583487, 0.00604483338842317, 0.00664828968356621, 0.00728673180099395, 0.00795889703644795, 0.00866303838230695, 0.00939690511889675, 0.0101577307281371, 0.010942229037054, 0.0117465993701676, 0.0125665413280325, 0.0133972796167302, 0.0142335991336574, 0.0150698902735454, 0.0159002041614507, 0.0167183172536454, 0.0175178044808441, 0.0182921198494897, 0.0190346831745763, 0.0197389714002676, 0.020398612780527, 0.0210074820484496, 0.0215597946062309, 0.0220501977225941, 0.022473856734247, 0.0228265343139947, 0.0231046609899767, 0.0233053952756892, 0.0234266719946158, 0.0234672376502799, 0.0234266719946158, 0.0233053952756892, 0.0231046609899767, 0.0228265343139947, 0.022473856734247, 0.0220501977225941, 0.0215597946062309, 0.0210074820484496, 0.020398612780527, 0.0197389714002676, 0.0190346831745763, 0.0182921198494897, 0.0175178044808441, 0.0167183172536454, 0.0159002041614507, 0.0150698902735454, 0.0142335991336574, 0.0133972796167302, 0.0125665413280325, 0.0117465993701676, 0.010942229037054, 0.0101577307281371, 0.00939690511889675, 0.00866303838230695, 0.00795889703644795, 0.00728673180099395, 0.00664828968356621, 0.00604483338842317, 0.00547716704583487, 0.00494566720070898, 0.00445031797242299, 0.00399074930220799, 0.00356627723683793, 0.00317594525418154, 0.00281856571330067, 0.00249276060490197, 0.00219700088266432, 0.00192964376796036, 0.00168896753568649, 0.00147320340358764, 0.00128056425833231, 0.00110927005589186, 0.000957569829285965, 0.000823760321812988, 0.000706201337376934, 0.000603327960854364, 0.00051365985048857, 0.000435807841336874, 0.000368478124457557, 0.000310474281706066, 0.000260697461819069, 0.000218144981137171, 0.000181907623161359, 0.000151165896477646, 0.000125185491708561, 0.000103312156275406, 8.49661819944029e-05, 6.96366758708924e-05, 5.68757597480354e-05, 4.62928204154855e-05, 3.75489089511911e-05, 3.03513668801384e-05, 2.44487374842009e-05, 1.96260034693739e-05, 1.57001772728555e-05, 1.25162575710745e-05}}); + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "KernelCreation") + public void testKernelCreation(final double sigma, final int maxSize, final double[] expectedKernel) { + final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, maxSize, sigma, true); + + final double[] kernel = profile.getKernel(); + Assert.assertEquals(kernel.length, expectedKernel.length); + for ( int i = 0; i < kernel.length; i++ ) + Assert.assertEquals(kernel[i], expectedKernel[i], 1e-3, "Kernels not equal at " + i); + } } From c96b64973ab7b943fb489ac7513ad35bae4a2bbf Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 23 Jan 2013 15:52:00 -0500 Subject: [PATCH 083/188] Soft clip probability propagation is capped by the MAX_PROB_PROPAGATION_DISTANCE, which is 50 bp --- .../sting/utils/activeregion/ActivityProfile.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 80484e12f..16cb2fd84 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -40,7 +40,7 @@ import java.util.*; * @since Date created */ public class ActivityProfile { - private final static int MAX_PROB_PROPOGATION_DISTANCE = 10; + private final static int MAX_PROB_PROPOGATION_DISTANCE = 50; private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author protected final List stateList; @@ -259,7 +259,8 @@ public class ActivityProfile { if ( justAddedState.resultState.equals(ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS) ) { // special code to deal with the problem that high quality soft clipped bases aren't added to pileups final List states = new LinkedList(); - final int numHQClips = justAddedState.resultValue.intValue(); + // add no more than the max prob propagation distance num HQ clips + final int numHQClips = Math.min(justAddedState.resultValue.intValue(), getMaxProbPropagationDistance()); for( int jjj = - numHQClips; jjj <= numHQClips; jjj++ ) { final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj); if ( loc != null ) From 592f90aaefdb46315862db069e57e4397bb558cc Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 24 Jan 2013 11:28:02 -0500 Subject: [PATCH 084/188] ActivityProfile now cuts intelligently at the best local minimum when in a larger than max size active region -- This new algorithm is essential to properly handle activity profiles that have many large active regions generated from lots of dense variant events. The new algorithm passes unit tests and passes visualize visual inspection of both running on 1000G and NA12878 -- Misc. commenting of the code -- Updated ActiveRegionExtension to include a min active region size -- Renamed ActiveRegionExtension to ActiveRegionTraversalParameters, as it carries more than just the traversal extension now --- .../targets/FindCoveredIntervals.java | 4 +- .../haplotypecaller/HaplotypeCaller.java | 2 +- .../traversals/TraverseActiveRegions.java | 14 +- ...a => ActiveRegionTraversalParameters.java} | 36 +++- .../gatk/walkers/ActiveRegionWalker.java | 4 +- .../utils/activeregion/ActivityProfile.java | 82 +++++++-- .../activeregion/ActivityProfileState.java | 5 +- .../activeregion/ActivityProfileUnitTest.java | 170 +++++++++++++++++- 8 files changed, 283 insertions(+), 34 deletions(-) rename public/java/src/org/broadinstitute/sting/gatk/walkers/{ActiveRegionExtension.java => ActiveRegionTraversalParameters.java} (54%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java index 74ff77e4b..3712a8e51 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java @@ -52,7 +52,7 @@ import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; +import org.broadinstitute.sting.gatk.walkers.ActiveRegionTraversalParameters; import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.gatk.walkers.PartitionBy; import org.broadinstitute.sting.gatk.walkers.PartitionType; @@ -64,7 +64,7 @@ import java.io.PrintStream; @DocumentedGATKFeature( groupName = "BAM Processing and Analysis Tools", extraDocs = {CommandLineGATK.class} ) @PartitionBy(PartitionType.CONTIG) -@ActiveRegionExtension(extension = 0, maxRegion = 50000) +@ActiveRegionTraversalParameters(extension = 0, maxRegion = 50000) public class FindCoveredIntervals extends ActiveRegionWalker { @Output(required = true) private PrintStream out; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 9bb04421c..a3d764141 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -131,7 +131,7 @@ import java.util.*; @DocumentedGATKFeature( groupName = "Variant Discovery Tools", extraDocs = {CommandLineGATK.class} ) @PartitionBy(PartitionType.LOCUS) @BAQMode(ApplicationTime = ReadTransformer.ApplicationTime.FORBIDDEN) -@ActiveRegionExtension(extension=65, maxRegion=300) +@ActiveRegionTraversalParameters(extension=65, maxRegion=300) //@Downsample(by= DownsampleType.BY_SAMPLE, toCoverage=5) public class HaplotypeCaller extends ActiveRegionWalker implements AnnotatorCompatible { diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 52ac783a9..bff696f13 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -34,7 +34,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.datasources.providers.*; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.gatk.walkers.ActiveRegionExtension; +import org.broadinstitute.sting.gatk.walkers.ActiveRegionTraversalParameters; import org.broadinstitute.sting.gatk.walkers.ActiveRegionWalker; import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.Walker; @@ -75,6 +75,7 @@ public class TraverseActiveRegions extends TraversalEngine workQueue = new LinkedList(); @@ -102,9 +103,10 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine extends TraversalEngine walker, T sum, final boolean flushActivityProfile, final boolean forceAllRegionsToBeActive) { if ( ! walkerHasPresetRegions ) { // We don't have preset regions, so we get our regions from the activity profile - final Collection activeRegions = activityProfile.popReadyActiveRegions(getActiveRegionExtension(), getMaxRegionSize(), flushActivityProfile); + final Collection activeRegions = activityProfile.popReadyActiveRegions(getActiveRegionExtension(), getMinRegionSize(), getMaxRegionSize(), flushActivityProfile); workQueue.addAll(activeRegions); if ( ! activeRegions.isEmpty() && logger.isDebugEnabled() ) logger.debug("Integrated " + activityProfile.size() + " isActive calls into " + activeRegions.size() + " regions." ); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionExtension.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionTraversalParameters.java similarity index 54% rename from public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionExtension.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionTraversalParameters.java index 72c409f62..cdb45db7b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionExtension.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionTraversalParameters.java @@ -33,7 +33,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Describes the size of the buffer region that is added to each active region when pulling in covered reads. + * Describes the parameters that this walker requires of the active region traversal + * * User: rpoplin * Date: 1/18/12 */ @@ -41,13 +42,40 @@ import java.lang.annotation.RetentionPolicy; @Inherited @Retention(RetentionPolicy.RUNTIME) -public @interface ActiveRegionExtension { +public @interface ActiveRegionTraversalParameters { + /** + * How far to either side of the active region itself should we include reads? + * + * That is, if the active region is 10 bp wide, and extension is 5, ART will provide + * the walker with active regions 10 bp, with 5 bp of extension on either side, and + * all reads that cover the 20 bp of the region + extension. + * + * @return the size of the active region extension we'd like + */ public int extension() default 0; + + /** + * The minimum number of bp for an active region, when we need to chop it up into pieces because + * it's become too big. This only comes into effect when there's literally no good place to chop + * that does make the region smaller than this value. + * + * @return the min size in bp of regions + */ + public int minRegion() default 50; + + /** + * The maximum size in bp of active regions wanted by this walker + * + * Active regions larger than this value are automatically cut up by ART into smaller + * regions of size <= this value. + * + * @return the max size in bp of regions + */ public int maxRegion() default 1500; /** - * The sigma value for the Gaussian kernel of the band pass filter - * @return + * The variance value for the Gaussian kernel of the band pass filter employed by ART + * @return the breadth of the band pass gaussian kernel we want for our traversal */ public double bandPassSigma() default BandPassActivityProfile.DEFAULT_SIGMA; } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index 92504e3ba..e14e50b1a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -55,7 +55,7 @@ import java.util.*; @By(DataSource.READS) @Requires({DataSource.READS, DataSource.REFERENCE}) @PartitionBy(PartitionType.READ) -@ActiveRegionExtension(extension=50,maxRegion=1500) +@ActiveRegionTraversalParameters(extension=50,maxRegion=1500) @ReadFilters({UnmappedReadFilter.class, NotPrimaryAlignmentFilter.class, DuplicateReadFilter.class, FailsVendorQualityCheckFilter.class, MappingQualityUnavailableFilter.class}) @RemoveProgramRecords public abstract class ActiveRegionWalker extends Walker { @@ -160,7 +160,7 @@ public abstract class ActiveRegionWalker extends Walker allIntervals = new ArrayList(); for( final GenomeLoc interval : intervals.toList() ) { final int start = Math.max( 1, interval.getStart() - activeRegionExtension ); diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 16cb2fd84..f265f9d60 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -41,7 +41,7 @@ import java.util.*; */ public class ActivityProfile { private final static int MAX_PROB_PROPOGATION_DISTANCE = 50; - private final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author + protected final static double ACTIVE_PROB_THRESHOLD = 0.002; // TODO: needs to be set-able by the walker author protected final List stateList; protected final GenomeLocParser parser; @@ -197,7 +197,6 @@ public class ActivityProfile { regionStopLoc = loc; contigLength = parser.getContigInfo(regionStartLoc.getContig()).getSequenceLength(); } else { - // TODO -- need to figure out where to add loc as the regions will be popping off the front if ( regionStopLoc.getStart() != loc.getStart() - 1 ) throw new IllegalArgumentException("Bad add call to ActivityProfile: loc " + loc + " not immediate after last loc " + regionStopLoc ); regionStopLoc = loc; @@ -294,6 +293,7 @@ public class ActivityProfile { * No returned region will be larger than maxRegionSize. * * @param activeRegionExtension the extension value to provide to the constructed regions + * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large * @param maxRegionSize the maximize size of the returned region * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the * stateList. Used to close out the active region when we've hit some kind of end (such @@ -301,14 +301,15 @@ public class ActivityProfile { * @return a non-null list of active regions */ @Ensures("result != null") - public List popReadyActiveRegions(final int activeRegionExtension, final int maxRegionSize, final boolean forceConversion) { + public List popReadyActiveRegions(final int activeRegionExtension, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) { if ( activeRegionExtension < 0 ) throw new IllegalArgumentException("activeRegionExtension must be >= 0 but got " + activeRegionExtension); + if ( minRegionSize < 1 ) throw new IllegalArgumentException("minRegionSize must be >= 1 but got " + minRegionSize); if ( maxRegionSize < 1 ) throw new IllegalArgumentException("maxRegionSize must be >= 1 but got " + maxRegionSize); final LinkedList regions = new LinkedList(); while ( true ) { - final ActiveRegion nextRegion = popNextReadyActiveRegion(activeRegionExtension, maxRegionSize, forceConversion); + final ActiveRegion nextRegion = popNextReadyActiveRegion(activeRegionExtension, minRegionSize, maxRegionSize, forceConversion); if ( nextRegion == null ) return regions; else { @@ -325,19 +326,20 @@ public class ActivityProfile { * are also updated. * * @param activeRegionExtension the extension value to provide to the constructed regions + * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large * @param maxRegionSize the maximize size of the returned region * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the * stateList. Used to close out the active region when we've hit some kind of end (such * as the end of the contig) * @return a fully formed active region, or null if none can be made */ - private ActiveRegion popNextReadyActiveRegion(final int activeRegionExtension, final int maxRegionSize, final boolean forceConversion) { + private ActiveRegion popNextReadyActiveRegion(final int activeRegionExtension, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) { if ( stateList.isEmpty() ) return null; final ActivityProfileState first = stateList.get(0); final boolean isActiveRegion = first.isActiveProb > ACTIVE_PROB_THRESHOLD; - final int offsetOfNextRegionEnd = findEndOfRegion(isActiveRegion, maxRegionSize, forceConversion); + final int offsetOfNextRegionEnd = findEndOfRegion(isActiveRegion, minRegionSize, maxRegionSize, forceConversion); if ( offsetOfNextRegionEnd == -1 ) // couldn't find a valid ending offset, so we return null return null; @@ -363,9 +365,14 @@ public class ActivityProfile { * The current region is defined from the start of the stateList, looking for elements that have the same isActiveRegion * flag (i.e., if isActiveRegion is true we are looking for states with isActiveProb > threshold, or alternatively * for states < threshold). The maximize size of the returned region is maxRegionSize. If forceConversion is - * true, then we'll return the region end even if this isn't safely beyond the max prob propogation distance. + * true, then we'll return the region end even if this isn't safely beyond the max prob propagation distance. + * + * Note that if isActiveRegion is true, and we can construct a active region > maxRegionSize in bp, we + * find the further local minimum within that max region, and cut the region there, under the constraint + * that the resulting region must be at least minRegionSize in bp. * * @param isActiveRegion is the region we're looking for an active region or inactive region? + * @param minRegionSize the minimum region size, in the case where we have to cut up regions that are too large * @param maxRegionSize the maximize size of the returned region * @param forceConversion if true, we'll return a region whose end isn't sufficiently far from the end of the * stateList. Used to close out the active region when we've hit some kind of end (such @@ -376,16 +383,65 @@ public class ActivityProfile { "result >= -1", "result == -1 || result < maxRegionSize", "! (result == -1 && forceConversion)"}) - private int findEndOfRegion(final boolean isActiveRegion, final int maxRegionSize, final boolean forceConversion) { - int i = 0; - while ( i < stateList.size() && i < maxRegionSize ) { - if ( stateList.get(i).isActiveProb > ACTIVE_PROB_THRESHOLD != isActiveRegion ) { + private int findEndOfRegion(final boolean isActiveRegion, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) { + final int nStates = stateList.size(); + int endOfActiveRegion = 0; + while ( endOfActiveRegion < nStates && endOfActiveRegion < maxRegionSize ) { + if ( getProb(endOfActiveRegion) > ACTIVE_PROB_THRESHOLD != isActiveRegion ) { break; } - i++; + endOfActiveRegion++; + } + + if ( isActiveRegion && endOfActiveRegion == maxRegionSize ) { + // we've run to the end of the region, let's find a good place to cut + int minI = endOfActiveRegion - 1; + double minP = Double.MAX_VALUE; + for ( int i = minI; i >= minRegionSize - 1; i-- ) { + double cur = getProb(i); + if ( cur < minP && isMinimum(i) ) { + minP = cur; + minI = i; + } + } + + endOfActiveRegion = minI + 1; } // we're one past the end, so i must be decremented - return forceConversion || i + getMaxProbPropagationDistance() < stateList.size() ? i - 1 : -1; + return forceConversion || endOfActiveRegion + getMaxProbPropagationDistance() < stateList.size() ? endOfActiveRegion - 1 : -1; + } + + /** + * Helper function to get the probability of the state at offset index + * @param index a valid offset into the state list + * @return the isActiveProb of the state at index + */ + @Requires({"index >= 0", "index < stateList.size()"}) + private double getProb(final int index) { + return stateList.get(index).isActiveProb; + } + + /** + * Is the probability at index in a local minimum? + * + * Checks that the probability at index is <= both the probabilities to either side. + * Returns false if index is at the end or the start of the state list. + * + * @param index the index of the state we want to test + * @return true if prob at state is a minimum, false otherwise + */ + @Requires({"index >= 0", "index < stateList.size()"}) + private boolean isMinimum(final int index) { + if ( index == stateList.size() - 1 ) + // we cannot be at a minimum if the current position is the last in the state list + return false; + else if ( index < 1 ) + // we cannot be at a minimum if the current position is the first or second + return false; + else { + final double indexP = getProb(index); + return indexP <= getProb(index+1) && indexP < getProb(index-1); + } } } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java index 272596be3..5bba7db17 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java @@ -59,7 +59,10 @@ public class ActivityProfileState { /** * Create a new ActivityProfileState at loc with probability of being active of isActiveProb that maintains some - * information about the result state and value (TODO RYAN -- what do these mean?) + * information about the result state and value + * + * The only state value in use is HIGH_QUALITY_SOFT_CLIPS, and here the value is interpreted as the number + * of bp affected by the soft clips. * * @param loc the position of the result profile (for debugging purposes) * @param isActiveProb the probability of being active (between 0 and 1) diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index bce1722cd..f6246b137 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -33,6 +33,7 @@ import net.sf.picard.reference.ReferenceSequenceFile; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.testng.Assert; @@ -46,6 +47,7 @@ import java.util.*; public class ActivityProfileUnitTest extends BaseTest { + private final static boolean DEBUG = false; private GenomeLocParser genomeLocParser; private GenomeLoc startLoc; @@ -123,7 +125,7 @@ public class ActivityProfileUnitTest extends BaseTest { return BasicActivityProfileTestProvider.getTests(BasicActivityProfileTestProvider.class); } - @Test(dataProvider = "BasicActivityProfileTestProvider") + @Test(enabled = ! DEBUG, dataProvider = "BasicActivityProfileTestProvider") public void testBasicActivityProfile(BasicActivityProfileTestProvider cfg) { ActivityProfile profile = cfg.makeProfile(); @@ -226,7 +228,7 @@ public class ActivityProfileUnitTest extends BaseTest { } - @Test(enabled = true, dataProvider = "RegionCreationTests") + @Test(enabled = !DEBUG, dataProvider = "RegionCreationTests") public void testRegionCreation(final int start, final List probs, int maxRegionSize, final int nParts, final boolean forceConversion, final boolean waitUntilEnd) { final ActivityProfile profile = new ActivityProfile(genomeLocParser); Assert.assertNotNull(profile.toString()); @@ -242,13 +244,13 @@ public class ActivityProfileUnitTest extends BaseTest { Assert.assertNotNull(profile.toString()); if ( ! waitUntilEnd ) { - final List regions = profile.popReadyActiveRegions(0, maxRegionSize, false); + final List regions = profile.popReadyActiveRegions(0, 1, maxRegionSize, false); lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites); } } if ( waitUntilEnd || forceConversion ) { - final List regions = profile.popReadyActiveRegions(0, maxRegionSize, forceConversion); + final List regions = profile.popReadyActiveRegions(0, 1, maxRegionSize, forceConversion); lastRegion = assertGoodRegions(start, regions, maxRegionSize, lastRegion, probs, seenSites); } @@ -312,7 +314,7 @@ public class ActivityProfileUnitTest extends BaseTest { return tests.toArray(new Object[][]{}); } - @Test(dataProvider = "SoftClipsTest") + @Test(enabled = ! DEBUG, dataProvider = "SoftClipsTest") public void testSoftClips(final int start, int nPrecedingSites, final int softClipSize) { final ActivityProfile profile = new ActivityProfile(genomeLocParser); @@ -327,14 +329,15 @@ public class ActivityProfileUnitTest extends BaseTest { final GenomeLoc softClipLoc = genomeLocParser.createGenomeLoc(contig, nPrecedingSites + start); profile.add(new ActivityProfileState(softClipLoc, 1.0, ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS, softClipSize)); + final int actualNumOfSoftClips = Math.min(softClipSize, profile.getMaxProbPropagationDistance()); if ( nPrecedingSites == 0 ) { - final int profileSize = Math.min(start + softClipSize, contigLength) - start + 1; + final int profileSize = Math.min(start + actualNumOfSoftClips, contigLength) - start + 1; Assert.assertEquals(profile.size(), profileSize, "Wrong number of states in the profile"); } for ( int i = 0; i < profile.size(); i++ ) { final ActivityProfileState state = profile.getStateList().get(i); - final boolean withinSCRange = state.getLoc().distance(softClipLoc) <= softClipSize; + final boolean withinSCRange = state.getLoc().distance(softClipLoc) <= actualNumOfSoftClips; if ( withinSCRange ) { Assert.assertTrue(state.isActiveProb > 0.0, "active prob should be changed within soft clip size"); } else { @@ -342,4 +345,157 @@ public class ActivityProfileUnitTest extends BaseTest { } } } + + // ------------------------------------------------------------------------------------- + // + // Tests to ensure we cut large active regions in the right place + // + // ------------------------------------------------------------------------------------- + + private void addProb(final List l, final double v) { + l.add(v); + } + + @DataProvider(name = "ActiveRegionCutTests") + public Object[][] makeActiveRegionCutTests() { + final List tests = new LinkedList(); + +// for ( final int activeRegionSize : Arrays.asList(30) ) { +// for ( final int minRegionSize : Arrays.asList(5) ) { + for ( final int activeRegionSize : Arrays.asList(10, 12, 20, 30, 40) ) { + for ( final int minRegionSize : Arrays.asList(1, 5, 10) ) { + final int maxRegionSize = activeRegionSize * 2 / 3; + if ( minRegionSize >= maxRegionSize ) continue; + { // test flat activity profile + final List probs = Collections.nCopies(activeRegionSize, 1.0); + tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs}); + } + + { // test point profile is properly handled + for ( int end = 1; end < activeRegionSize; end++ ) { + final List probs = Collections.nCopies(end, 1.0); + tests.add(new Object[]{minRegionSize, maxRegionSize, Math.min(end, maxRegionSize), probs}); + } + } + + { // test increasing activity profile + final List probs = new ArrayList(activeRegionSize); + for ( int i = 0; i < activeRegionSize; i++ ) { + addProb(probs, (1.0*(i+1))/ activeRegionSize); + } + tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs}); + } + + { // test decreasing activity profile + final List probs = new ArrayList(activeRegionSize); + for ( int i = 0; i < activeRegionSize; i++ ) { + addProb(probs, 1 - (1.0*(i+1))/ activeRegionSize); + } + tests.add(new Object[]{minRegionSize, maxRegionSize, maxRegionSize, probs}); + } + + { // test two peaks +// for ( final double rootSigma : Arrays.asList(2.0) ) { +// int maxPeak1 = 9; { +// int maxPeak2 = 16; { + for ( final double rootSigma : Arrays.asList(1.0, 2.0, 3.0) ) { + for ( int maxPeak1 = 0; maxPeak1 < activeRegionSize / 2; maxPeak1++ ) { + for ( int maxPeak2 = activeRegionSize / 2 + 1; maxPeak2 < activeRegionSize; maxPeak2++ ) { + final double[] gauss1 = makeGaussian(maxPeak1, activeRegionSize, rootSigma); + final double[] gauss2 = makeGaussian(maxPeak2, activeRegionSize, rootSigma+1); + final List probs = new ArrayList(activeRegionSize); + for ( int i = 0; i < activeRegionSize; i++ ) { + addProb(probs, gauss1[i] + gauss2[i]); + } + final int cutSite = findCutSiteForTwoMaxPeaks(probs, minRegionSize); + if ( cutSite != -1 && cutSite < maxRegionSize ) + tests.add(new Object[]{minRegionSize, maxRegionSize, Math.max(cutSite, minRegionSize), probs}); + } + } + } + } + + { // test that the lowest of two minima is taken + // looks like a bunch of 1s, 0.5, some 1.0s, 0.75, some more 1s +// int firstMin = 0; { +// int secondMin = 4; { + for ( int firstMin = 1; firstMin < activeRegionSize; firstMin++ ) { + for ( int secondMin = firstMin + 1; secondMin < activeRegionSize; secondMin++ ) { + final List probs = new ArrayList(Collections.nCopies(activeRegionSize, 1.0)); + probs.set(firstMin, 0.5); + probs.set(secondMin, 0.75); + final int expectedCut; + if ( firstMin + 1 < minRegionSize ) { + if ( firstMin == secondMin - 1 ) // edge case for non-min at minRegionSize + expectedCut = maxRegionSize; + else + expectedCut = secondMin + 1 > maxRegionSize ? maxRegionSize : ( secondMin + 1 < minRegionSize ? maxRegionSize : secondMin + 1); + } else if ( firstMin + 1 > maxRegionSize ) + expectedCut = maxRegionSize; + else { + expectedCut = firstMin + 1; + } + + Math.min(firstMin + 1, maxRegionSize); + tests.add(new Object[]{minRegionSize, maxRegionSize, expectedCut, probs}); + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + private double[] makeGaussian(final int mean, final int range, final double sigma) { + final double[] gauss = new double[range]; + for( int iii = 0; iii < range; iii++ ) { + gauss[iii] = MathUtils.NormalDistribution(mean, sigma, iii) + ActivityProfile.ACTIVE_PROB_THRESHOLD; + } + return gauss; + } + + private int findCutSiteForTwoMaxPeaks(final List probs, final int minRegionSize) { + for ( int i = probs.size() - 2; i > minRegionSize; i-- ) { + double prev = probs.get(i - 1); + double next = probs.get(i + 1); + double cur = probs.get(i); + if ( cur < next && cur < prev ) + return i + 1; + } + + return -1; + } + + +// private int findCutSite(final List probs) { +// for ( int i = probs.size() - 2; i > 0; i-- ) { +// double prev = probs.get(i + 1); +// double next = probs.get(i-1); +// double cur = probs.get(i); +// if ( cur < next && cur < prev ) +// return i + 1; +// } +// +// return -1; +// } + + @Test(dataProvider = "ActiveRegionCutTests") + public void testActiveRegionCutTests(final int minRegionSize, final int maxRegionSize, final int expectedRegionSize, final List probs) { + final ActivityProfile profile = new ActivityProfile(genomeLocParser); + + final String contig = genomeLocParser.getContigs().getSequences().get(0).getSequenceName(); + for ( int i = 0; i <= maxRegionSize + profile.getMaxProbPropagationDistance(); i++ ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, i + 1); + final double prob = i < probs.size() ? probs.get(i) : 0.0; + final ActivityProfileState state = new ActivityProfileState(loc, prob); + profile.add(state); + } + + final List regions = profile.popReadyActiveRegions(0, minRegionSize, maxRegionSize, false); + Assert.assertTrue(regions.size() >= 1, "Should only be one regions for this test"); + final ActiveRegion region = regions.get(0); + Assert.assertEquals(region.getLocation().getStart(), 1, "Region should start at 1"); + Assert.assertEquals(region.getLocation().size(), expectedRegionSize, "Incorrect region size; cut must have been incorrect"); + } } \ No newline at end of file From c7a29b1d390d690899198526c0205411a91c54d7 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 24 Jan 2013 13:47:16 -0500 Subject: [PATCH 085/188] Fixed NPE in ActiveRegionUnitTest by allowing null supporting states in ActiveRegion --- .../sting/utils/activeregion/ActiveRegion.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java index 66485c8cf..575e94b99 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -54,8 +55,12 @@ public class ActiveRegion implements HasGenomeLocation { public final boolean isActive; public ActiveRegion( final GenomeLoc activeRegionLoc, final List supportingStates, final boolean isActive, final GenomeLocParser genomeLocParser, final int extension ) { + if ( activeRegionLoc == null ) throw new IllegalArgumentException("activeRegionLoc cannot be null"); + if ( genomeLocParser == null ) throw new IllegalArgumentException("genomeLocParser cannot be null"); + if ( extension < 0 ) throw new IllegalArgumentException("extension cannot be < 0 but got " + extension); + this.activeRegionLoc = activeRegionLoc; - this.supportingStates = new ArrayList(supportingStates); + this.supportingStates = supportingStates == null ? Collections.emptyList() : new ArrayList(supportingStates); this.isActive = isActive; this.genomeLocParser = genomeLocParser; this.extension = extension; From 6dd0e1ddd6afb559d892d211fdca9acfa3909201 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 25 Jan 2013 09:42:04 -0500 Subject: [PATCH 086/188] Pulled out the --regenotype functionality from SelectVariants into its own tool: RegenotypeVariants. This allows us to move SelectVariants into the public suite of tools now. --- .../variantutils/RegenotypeVariants.java | 185 ++++++++++++++++++ .../RegenotypeVariantsIntegrationTest.java | 69 +++++++ .../SelectVariantsIntegrationTest.java | 26 --- .../walkers/variantutils/SelectVariants.java | 44 +---- 4 files changed, 255 insertions(+), 69 deletions(-) create mode 100644 protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariantsIntegrationTest.java rename {protected => public}/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java (93%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java new file mode 100644 index 000000000..c8fc27e6a --- /dev/null +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java @@ -0,0 +1,185 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.variantutils; + +import org.broadinstitute.sting.commandline.*; +import org.broadinstitute.sting.gatk.CommandLineGATK; +import org.broadinstitute.sting.gatk.arguments.StandardVariantContextInputArgumentCollection; +import org.broadinstitute.sting.gatk.contexts.AlignmentContext; +import org.broadinstitute.sting.gatk.contexts.ReferenceContext; +import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; +import org.broadinstitute.sting.gatk.walkers.RodWalker; +import org.broadinstitute.sting.gatk.walkers.TreeReducible; +import org.broadinstitute.sting.gatk.walkers.genotyper.GenotypeLikelihoodsCalculationModel; +import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedArgumentCollection; +import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyper; +import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; +import org.broadinstitute.sting.utils.SampleUtils; +import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; +import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.variantcontext.*; +import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; +import org.broadinstitute.variant.vcf.*; + +import java.util.*; + +/** + * Regenotypes the variants from a VCF. VCF records must contain PLs or GLs. + * + *

+ * This tool triggers re-genotyping of the samples through the Exact Allele Frequency calculation model. Note that this is truly the + * mathematically correct way to select samples from a larger set (especially when calls were generated from low coverage sequencing data); + * using the hard genotypes to select (i.e. the default mode of SelectVariants) can lead to false positives when errors are confused for + * variants in the original genotyping. This functionality used to comprise the --regenotype option in SelectVariants but we pulled it out + * into its own tool for technical purposes. + * + *

Input

+ *

+ * A variant set to regenotype. + *

+ * + *

Output

+ *

+ * A re-genotyped VCF. + *

+ * + *

Examples

+ *
+ * java -Xmx2g -jar GenomeAnalysisTK.jar \
+ *   -R ref.fasta \
+ *   -T RegenotypeVariants \
+ *   --variant input.vcf \
+ *   -o output.vcf
+ * 
+ * + */ +@DocumentedGATKFeature( groupName = "Variant Evaluation and Manipulation Tools", extraDocs = {CommandLineGATK.class} ) +public class RegenotypeVariants extends RodWalker implements TreeReducible { + + @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); + + @Output(doc="File to which variants should be written",required=true) + protected VariantContextWriter vcfWriter = null; + + private UnifiedGenotyperEngine UG_engine = null; + + public void initialize() { + final UnifiedArgumentCollection UAC = new UnifiedArgumentCollection(); + UAC.GLmodel = GenotypeLikelihoodsCalculationModel.Model.BOTH; + UAC.OutputMode = UnifiedGenotyperEngine.OUTPUT_MODE.EMIT_ALL_SITES; + UAC.GenotypingMode = GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES; + + String trackName = variantCollection.variants.getName(); + Set samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName)); + UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); + + final Set hInfo = new HashSet(); + hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(trackName))); + hInfo.addAll(UnifiedGenotyper.getHeaderInfo(UAC, null, null)); + + vcfWriter.writeHeader(new VCFHeader(hInfo, samples)); + } + + /** + * Subset VC record if necessary and emit the modified record (provided it satisfies criteria for printing) + * + * @param tracker the ROD tracker + * @param ref reference information + * @param context alignment info + * @return 1 if the record was printed to the output file, 0 if otherwise + */ + @Override + public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + if ( tracker == null ) + return 0; + + Collection vcs = tracker.getValues(variantCollection.variants, context.getLocation()); + + if ( vcs == null || vcs.size() == 0) { + return 0; + } + + for (VariantContext vc : vcs) { + + if ( vc.isPolymorphicInSamples() && hasPLs(vc) ) { + synchronized (UG_engine) { + final VariantContextBuilder builder = new VariantContextBuilder(UG_engine.calculateGenotypes(vc)).filters(vc.getFiltersMaybeNull()); + VariantContextUtils.calculateChromosomeCounts(builder, false); + vc = builder.make(); + } + } + + vcfWriter.add(vc); + } + + return 1; + } + + private boolean hasPLs(final VariantContext vc) { + for ( Genotype g : vc.getGenotypes() ) { + if ( g.hasLikelihoods() ) + return true; + } + return false; + } + + @Override + public Integer reduceInit() { return 0; } + + @Override + public Integer reduce(Integer value, Integer sum) { return value + sum; } + + @Override + public Integer treeReduce(Integer lhs, Integer rhs) { + return lhs + rhs; + } + + public void onTraversalDone(Integer result) { + logger.info(result + " records processed."); + } +} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariantsIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariantsIntegrationTest.java new file mode 100644 index 000000000..2fe50ff68 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariantsIntegrationTest.java @@ -0,0 +1,69 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.variantutils; + +import org.broadinstitute.sting.WalkerTest; +import org.broadinstitute.sting.utils.exceptions.UserException; +import org.testng.annotations.Test; + +import java.util.Arrays; + +public class RegenotypeVariantsIntegrationTest extends WalkerTest { + + @Test + public void testRegenotype() { + String testFile = privateTestDir + "combine.3.NA12892.vcf"; + + WalkerTestSpec spec = new WalkerTestSpec( + "-T RegenotypeVariants -R " + b36KGReference + " --variant " + testFile + " -o %s --no_cmdline_in_header", + 1, + Arrays.asList("46ff472fc7ef6734ad01170028d5924a") + ); + + executeTest("testRegenotype--" + testFile, spec); + } +} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariantsIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariantsIntegrationTest.java index aeb8d9318..c97f0bf02 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariantsIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariantsIntegrationTest.java @@ -229,19 +229,6 @@ public class SelectVariantsIntegrationTest extends WalkerTest { executeTest("testUsingDbsnpName--" + testFile, spec); } - @Test - public void testRegenotype() { - String testFile = privateTestDir + "combine.3.vcf"; - - WalkerTestSpec spec = new WalkerTestSpec( - "-T SelectVariants -R " + b36KGReference + " -regenotype -sn NA12892 --variant " + testFile + " -o %s --no_cmdline_in_header", - 1, - Arrays.asList("46ff472fc7ef6734ad01170028d5924a") - ); - - executeTest("testRegenotype--" + testFile, spec); - } - @Test public void testRemoveMLE() { String testFile = privateTestDir + "vcfexample.withMLE.vcf"; @@ -255,19 +242,6 @@ public class SelectVariantsIntegrationTest extends WalkerTest { executeTest("testRemoveMLE--" + testFile, spec); } - @Test - public void testRemoveMLEAndRegenotype() { - String testFile = privateTestDir + "vcfexample.withMLE.vcf"; - - WalkerTestSpec spec = new WalkerTestSpec( - "-T SelectVariants -R " + b36KGReference + " -regenotype -sn NA12892 --variant " + testFile + " -o %s --no_cmdline_in_header", - 1, - Arrays.asList("46ff472fc7ef6734ad01170028d5924a") - ); - - executeTest("testRemoveMLEAndRegenotype--" + testFile, spec); - } - @Test public void testMultipleRecordsAtOnePosition() { String testFile = privateTestDir + "selectVariants.onePosition.vcf"; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java similarity index 93% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java rename to public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java index ebad1e2ed..f79946a2e 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java @@ -56,15 +56,9 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.gatk.walkers.TreeReducible; import org.broadinstitute.sting.gatk.walkers.annotator.ChromosomeCountConstants; -import org.broadinstitute.sting.gatk.walkers.annotator.ChromosomeCounts; -import org.broadinstitute.sting.gatk.walkers.genotyper.GenotypeLikelihoodsCalculationModel; -import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedArgumentCollection; -import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyper; -import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; import org.broadinstitute.sting.utils.MendelianViolation; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -260,17 +254,6 @@ public class SelectVariants extends RodWalker implements TreeR @Argument(fullName="excludeFiltered", shortName="ef", doc="Don't include filtered loci in the analysis", required=false) protected boolean EXCLUDE_FILTERED = false; - /** - * This argument triggers re-genotyping of the selected samples through the Exact calculation model. Note that this is truly the - * mathematically correct way to select samples (especially when calls were generated from low coverage sequencing data); using the - * hard genotypes to select (i.e. the default mode of SelectVariants) can lead to false positives when errors are confused for variants - * in the original genotyping. We decided not to set the --regenotype option as the default though as the output can be unexpected if - * a user is strictly comparing against the original genotypes (GTs) in the file. - */ - @Argument(fullName="regenotype", shortName="regenotype", doc="re-genotype the selected samples based on their GLs (or PLs)", required=false) - protected Boolean REGENOTYPE = false; - private UnifiedGenotyperEngine UG_engine = null; - /** * When this argument is used, we can choose to include only multiallelic or biallelic sites, depending on how many alleles are listed in the ALT column of a vcf. * For example, a multiallelic record such as: @@ -471,15 +454,6 @@ public class SelectVariants extends RodWalker implements TreeR SELECT_RANDOM_FRACTION = fractionRandom > 0; if (SELECT_RANDOM_FRACTION) logger.info("Selecting approximately " + 100.0*fractionRandom + "% of the variants at random from the variant track"); - if ( REGENOTYPE ) { - final UnifiedArgumentCollection UAC = new UnifiedArgumentCollection(); - UAC.GLmodel = GenotypeLikelihoodsCalculationModel.Model.BOTH; - UAC.OutputMode = UnifiedGenotyperEngine.OUTPUT_MODE.EMIT_ALL_SITES; - UAC.GenotypingMode = GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES; - UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); - headerLines.addAll(UnifiedGenotyper.getHeaderInfo(UAC, null, null)); - } - /** load in the IDs file to a hashset for matching */ if ( rsIDFile != null ) { IDsToKeep = new HashSet(); @@ -557,14 +531,6 @@ public class SelectVariants extends RodWalker implements TreeR VariantContext sub = subsetRecord(vc, EXCLUDE_NON_VARIANTS); - if ( REGENOTYPE && sub.isPolymorphicInSamples() && hasPLs(sub) ) { - synchronized (UG_engine) { - final VariantContextBuilder builder = new VariantContextBuilder(UG_engine.calculateGenotypes(sub)).filters(sub.getFiltersMaybeNull()); - addAnnotations(builder, sub); - sub = builder.make(); - } - } - if ( (!EXCLUDE_NON_VARIANTS || sub.isPolymorphicInSamples()) && (!EXCLUDE_FILTERED || !sub.isFiltered()) ) { boolean failedJexlMatch = false; for ( VariantContextUtils.JexlVCMatchExp jexl : jexls ) { @@ -596,19 +562,11 @@ public class SelectVariants extends RodWalker implements TreeR return false; } - private boolean hasPLs(final VariantContext vc) { - for ( Genotype g : vc.getGenotypes() ) { - if ( g.hasLikelihoods() ) - return true; - } - return false; - } - /** * Checks if vc has a variant call for (at least one of) the samples. * @param vc the variant rod VariantContext. Here, the variant is the dataset you're looking for discordances to (e.g. HapMap) * @param compVCs the comparison VariantContext (discordance - * @return + * @return true if is discordant */ private boolean isDiscordant (VariantContext vc, Collection compVCs) { if (vc == null) From f7b80116d6ea5c17d134a17972385709d9237ec2 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 25 Jan 2013 10:52:02 -0500 Subject: [PATCH 087/188] Don't let users play with the different exact model implementations. --- .../StandardCallerArgumentCollection.java | 14 +++++++------- .../walkers/genotyper/afcalc/AFCalcFactory.java | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/arguments/StandardCallerArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/arguments/StandardCallerArgumentCollection.java index bb31b410e..3a1532bb1 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/arguments/StandardCallerArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/arguments/StandardCallerArgumentCollection.java @@ -109,13 +109,6 @@ public class StandardCallerArgumentCollection { @Argument(fullName = "max_alternate_alleles", shortName = "maxAltAlleles", doc = "Maximum number of alternate alleles to genotype", required = false) public int MAX_ALTERNATE_ALLELES = 6; - /** - * Controls the model used to calculate the probability that a site is variant plus the various sample genotypes in the data at a given locus. - */ - @Advanced - @Argument(fullName = "p_nonref_model", shortName = "pnrm", doc = "Non-reference probability calculation model to employ", required = false) - public AFCalcFactory.Calculation AFmodel = AFCalcFactory.Calculation.getDefaultModel(); - /** * If this fraction is greater is than zero, the caller will aggressively attempt to remove contamination through biased down-sampling of reads. * Basically, it will ignore the contamination fraction of reads for each alternate allele. So if the pileup contains N total bases, then we @@ -125,6 +118,13 @@ public class StandardCallerArgumentCollection { public double CONTAMINATION_FRACTION = DEFAULT_CONTAMINATION_FRACTION; public static final double DEFAULT_CONTAMINATION_FRACTION = 0.05; + /** + * Controls the model used to calculate the probability that a site is variant plus the various sample genotypes in the data at a given locus. + */ + @Hidden + @Argument(fullName = "p_nonref_model", shortName = "pnrm", doc = "Non-reference probability calculation model to employ", required = false) + public AFCalcFactory.Calculation AFmodel = AFCalcFactory.Calculation.getDefaultModel(); + @Hidden @Argument(fullName = "logRemovedReadsFromContaminationFiltering", shortName="contaminationLog", required=false) public PrintStream contaminationLog = null; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcFactory.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcFactory.java index 131c1284f..d4bb3cab3 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcFactory.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcFactory.java @@ -70,7 +70,7 @@ public class AFCalcFactory { * the needs of the request (i.e., considering ploidy). */ public enum Calculation { - /** expt. implementation -- for testing only */ + /** default implementation */ EXACT_INDEPENDENT(IndependentAllelesDiploidExactAFCalc.class, 2, -1), /** reference implementation of multi-allelic EXACT model. Extremely slow for many alternate alleles */ From 008b6175770074289bb27dd7cb50d5bdca8e3a98 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 10:13:12 -0500 Subject: [PATCH 088/188] Cleanup the getLIBS function in LocusIterator -- Now throws an UnsupportedOperationException in the base class. Only LocusView implements this function and actually returns the LIBS --- .../gatk/datasources/providers/LocusView.java | 8 +++++++- .../sting/utils/locusiterator/LocusIterator.java | 15 ++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java index f77819426..3ff6e34fb 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java @@ -214,7 +214,13 @@ public abstract class LocusView extends LocusIterator implements View { return locus.containsP(location); } - // TODO -- remove me + /** + * {@inheritDoc} + * + * Since this class has an actual LIBS, so this function will never throw an exception + * + * @return the LocusIteratorByState used by this view to get pileups + */ @Override public LocusIteratorByState getLIBS() { return loci.getLIBS(); diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java index fc114b4f0..1243b2893 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIterator.java @@ -34,11 +34,6 @@ import java.util.Iterator; * Iterator that traverses a SAM File, accumulating information on a per-locus basis */ public abstract class LocusIterator implements Iterable, CloseableIterator { - // ----------------------------------------------------------------------------------------------------------------- - // - // constructors and other basic operations - // - // ----------------------------------------------------------------------------------------------------------------- public Iterator iterator() { return this; } @@ -50,9 +45,15 @@ public abstract class LocusIterator implements Iterable, Close public abstract boolean hasNext(); public abstract AlignmentContext next(); - // TODO -- remove me when ART testing is done + /** + * Get, if possible, the underlying LocusIteratorByState from this LocusIterator. + * + * @throws UnsupportedOperationException if we don't support this operation + * + * @return a non-null locus iterator by state + */ public LocusIteratorByState getLIBS() { - return null; + throw new UnsupportedOperationException("This locus iterator does not support getting the underlying LocusIteratorByState"); } public void remove() { From 3f95f39be379e20019e360c6076ee4da3342848e Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 11:06:47 -0500 Subject: [PATCH 089/188] Updating HC md5s for new cutting algorithm and default band pass filter parameters --- .../HaplotypeCallerIntegrationTest.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 41f9ab680..97b9ce746 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "c142bc73447c72286ca48f4a4966d9b6"); + HCTest(CEUTRIO_BAM, "", "11290b619bc79b629cf29b8f428254ce"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "d172eb9447015ea50220c6947be145ea"); + HCTest(NA12878_BAM, "", "897abb2b4f98e9e460f373f9e0db5033"); } @Test(enabled = false) @@ -84,7 +84,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "2c56ffc3b7fbbf154ae9ca355780a78f"); + "efc2cae94069a1d6ee5fdcc7afeaa0ed"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -96,13 +96,13 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAComplex() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:119673-119823 -L 20:121408-121538", - "66bd513d25b691a5b0c5084924b4a308"); + "01f42c311fc3ce4f07ef86f8c01facfb"); } @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "d0fcbfa2ccce0ca4a2e81f31dc43d79d"); + "4c117c84d1abeade1dee3f7b52a4a585"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "7e8a6ed62f866fc47c92af0e255ca180"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "939847eb7bbafc798916acffdb1b5697"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -124,7 +124,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleSymbolic() { - HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "0761ff5cbf279be467833fa6708bf360"); + HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "25806874242973f00fb6f2a320ed4d9c"); } private void HCTestIndelQualityScores(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "602aabbbe710ac90b16e474c869e8a86"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "c50b06d56cf3d0ef53e73a4973207949"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,14 +146,14 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("c23b589be3072027ff2da93067dbf549")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("ae2470e294d99ff2b825281b84730c72")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @Test public void HCTestStructuralIndels() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "AFR.structural.indels.bam") + " --no_cmdline_in_header -o %s -minPruning 6 -L 20:8187565-8187800 -L 20:18670537-18670730"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("a612fe84dd7f80c4ad2d20d27fc6744e")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("6f18ae64bf466476d780a083dcb5fc43")); executeTest("HCTestStructuralIndels: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("0cb9132967fa9811e04f528be9f686dc")); + Arrays.asList("ecdb8e30ec5dd91efc179ab6732499f9")); executeTest("HC calling on a ReducedRead BAM", spec); } From eaf6279d48d77b149fcf8ac4e8e8429c9aea9559 Mon Sep 17 00:00:00 2001 From: Ami Levy-Moonshine Date: Fri, 25 Jan 2013 11:47:30 -0500 Subject: [PATCH 090/188] adding RBP to the general calling pipeline and few other small changes to it (to make it run with the current bundel file names --- .../variant/variantcontext/VariantContextUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index b07040748..0a848fba1 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -878,6 +878,7 @@ public class VariantContextUtils { } private static void mergeGenotypes(GenotypesContext mergedGenotypes, VariantContext oneVC, AlleleMapper alleleMapping, boolean uniqifySamples) { + //TODO: should we add a check for cases when the genotypeMergeOption is REQUIRE_UNIQUE for ( Genotype g : oneVC.getGenotypes() ) { String name = mergedSampleName(oneVC.getSource(), g.getSampleName(), uniqifySamples); if ( ! mergedGenotypes.containsSample(name) ) { From c58e02a3bd106dd9ee59cee08d60ae8ab647a20d Mon Sep 17 00:00:00 2001 From: Khalid Shakir Date: Fri, 25 Jan 2013 14:16:39 -0500 Subject: [PATCH 091/188] Added a QFunction.jobLocalDir for optionally tracking a node local directory that may have faster intermediate storage, with SGF ensuring that if the directory happens to be on the same machine that it get's a clone specific sub-directory to avoid collisions. --- .../sting/queue/function/QFunction.scala | 18 ++++++++++++++-- .../ScatterGatherableFunction.scala | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/public/scala/src/org/broadinstitute/sting/queue/function/QFunction.scala b/public/scala/src/org/broadinstitute/sting/queue/function/QFunction.scala index 1b54231f3..81c76dd29 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/function/QFunction.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/function/QFunction.scala @@ -59,9 +59,17 @@ trait QFunction extends Logging with QJobReport { /** Directory to run the command in. */ var commandDirectory: File = new File(".") - /** Temporary directory to write any files */ + /** Temporary directory to write any files. Must be network accessible. */ var jobTempDir: File = null + /** + * Local path available on all machines to store LOCAL temporary files. Not an @Input, + * nor an @Output. Currently only used for local intermediate files for composite jobs. + * Needs to be an annotated field so that it's mutated during cloning. + */ + @Argument(doc="Local path available on all machines to store LOCAL temporary files.") + var jobLocalDir: File = _ + /** Order the function was added to the graph. */ var addOrder: Seq[Int] = Nil @@ -97,6 +105,7 @@ trait QFunction extends Logging with QJobReport { function.qSettings = this.qSettings function.commandDirectory = this.commandDirectory function.jobTempDir = this.jobTempDir + function.jobLocalDir = this.jobLocalDir function.addOrder = this.addOrder function.jobPriority = this.jobPriority function.jobRestartable = this.jobRestartable @@ -232,6 +241,7 @@ trait QFunction extends Logging with QJobReport { var dirs = Set.empty[File] dirs += commandDirectory dirs += jobTempDir + dirs += jobLocalDir dirs += jobOutputFile.getParentFile if (jobErrorFile != null) dirs += jobErrorFile.getParentFile @@ -370,11 +380,15 @@ trait QFunction extends Logging with QJobReport { if (jobTempDir == null) jobTempDir = qSettings.tempDirectory + if (jobLocalDir == null) + jobLocalDir = jobTempDir + if (jobPriority.isEmpty) jobPriority = qSettings.jobPriority - // Do not set the temp dir relative to the command directory + // Do not set the temp and local dir relative to the command directory jobTempDir = IOUtils.absolute(jobTempDir) + jobLocalDir = IOUtils.absolute(jobLocalDir) absoluteCommandDirectory() } diff --git a/public/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterGatherableFunction.scala b/public/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterGatherableFunction.scala index 66fdf0f8f..67138eb75 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterGatherableFunction.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterGatherableFunction.scala @@ -109,7 +109,7 @@ trait ScatterGatherableFunction extends CommandLineFunction { this.copySettingsTo(scatterFunction) scatterFunction.originalFunction = this scatterFunction.originalInputs = inputFiles - scatterFunction.commandDirectory = this.scatterGatherTempDir("scatter") + scatterFunction.commandDirectory = this.scatterGatherCommandDir("scatter") scatterFunction.jobOutputFile = new File("scatter.out") scatterFunction.addOrder = this.addOrder :+ 1 scatterFunction.isIntermediate = true @@ -154,7 +154,7 @@ trait ScatterGatherableFunction extends CommandLineFunction { this.copySettingsTo(gatherFunction) gatherFunction.originalFunction = this gatherFunction.originalOutput = gatherOutput - gatherFunction.commandDirectory = this.scatterGatherTempDir("gather-" + gatherField.field.getName) + gatherFunction.commandDirectory = this.scatterGatherCommandDir("gather-" + gatherField.field.getName) gatherFunction.jobOutputFile = new File("gather-" + gatherOutput.getName + ".out") gatherFunction.addOrder = this.addOrder :+ gatherAddOrder @@ -178,10 +178,14 @@ trait ScatterGatherableFunction extends CommandLineFunction { cloneFunction.analysisName = this.analysisName cloneFunction.cloneIndex = i cloneFunction.cloneCount = numClones - cloneFunction.commandDirectory = this.scatterGatherTempDir(dirFormat.format(i)) + cloneFunction.commandDirectory = this.scatterGatherCommandDir(dirFormat.format(i)) cloneFunction.jobOutputFile = if (IOUtils.isSpecialFile(this.jobOutputFile)) this.jobOutputFile else new File(this.jobOutputFile.getName) if (this.jobErrorFile != null) cloneFunction.jobErrorFile = if (IOUtils.isSpecialFile(this.jobErrorFile)) this.jobErrorFile else new File(this.jobErrorFile.getName) + // jic the "local" dir is actually on the network, create different sub local directories for each clone. + // This might be better handled with a hook that allows clones to create unique file names. Right now no hook + // like freezeFieldValues exists for specifying per cloneFunction fields. + cloneFunction.jobLocalDir = this.scatterGatherLocalDir(dirFormat.format(i)) cloneFunction.addOrder = this.addOrder :+ (i+1) cloneFunction.isIntermediate = true @@ -350,7 +354,7 @@ trait ScatterGatherableFunction extends CommandLineFunction { this.copySettingsTo(gatherLogFunction) gatherLogFunction.logs = functions.map(logFile).filter(_ != null) gatherLogFunction.jobOutputFile = logFile(this) - gatherLogFunction.commandDirectory = this.scatterGatherTempDir() + gatherLogFunction.commandDirectory = this.scatterGatherCommandDir() gatherLogFunction.addOrder = this.addOrder :+ addOrder gatherLogFunction.isIntermediate = false gatherLogFunction @@ -361,5 +365,12 @@ trait ScatterGatherableFunction extends CommandLineFunction { * @param subDir directory under the scatter gather directory. * @return temporary directory under this scatter gather directory. */ - private def scatterGatherTempDir(subDir: String = "") = IOUtils.absolute(this.scatterGatherDirectory, this.jobName + "-sg/" + subDir) + private def scatterGatherCommandDir(subDir: String = "") = IOUtils.absolute(this.scatterGatherDirectory, this.jobName + "-sg/" + subDir) + + /** + * Returns a sub directory under this job local directory. + * @param subDir directory under the job local directory. + * @return absolute path to a directory under the original job local directory. + */ + private def scatterGatherLocalDir(subDir: String = "") = IOUtils.absolute(this.jobLocalDir, this.jobName + "-sg/" + subDir) } From b4447cdca2fb6c791f5fbea93e898e96a8b5d0d2 Mon Sep 17 00:00:00 2001 From: Ami Levy-Moonshine Date: Fri, 25 Jan 2013 15:49:51 -0500 Subject: [PATCH 092/188] In cases where one uses VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE we used to verify that the samples names are unique in VariantContextUtils.simpleMerge for each VCs. It couse to a bug that was reported on the forum (when a VCs had 2 VC from the same sample). Now we will check it only in CombineVariants.init using the headers. A new function was added to SamplesUtils with unitTests in CVunitTest.java. --- .../variantutils/CombineVariantsUnitTest.java | 51 ++++++++++++++++++- .../walkers/variantutils/CombineVariants.java | 6 +++ .../sting/utils/SampleUtils.java | 19 +++++++ .../variantcontext/VariantContextUtils.java | 32 ++++++------ .../VariantContextUtilsUnitTest.java | 19 +++---- 5 files changed, 100 insertions(+), 27 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java index 1fb056c78..46bd5af3c 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java @@ -48,14 +48,14 @@ package org.broadinstitute.sting.gatk.walkers.variantutils; import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.PositionalBufferedStream; +import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.variant.vcf.*; import org.testng.Assert; import org.testng.annotations.Test; import java.io.StringBufferInputStream; -import java.util.ArrayList; -import java.util.Set; +import java.util.*; /** * test out pieces of the combine variants code @@ -76,6 +76,33 @@ public class CombineVariantsUnitTest { "##FORMAT=\n"+ "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\n"; + public static String VCF4headerStringsWithSamplesName = + "##fileformat=VCFv4.0\n" + + "##filedate=2010-06-21\n"+ + "##reference=NCBI36\n"+ + "##INFO=\n"+ + "##INFO=\n"+ + "##INFO=\n"+ + "##FILTER=\n"+ + "##FORMAT=\n"+ + "##FORMAT=\n"+ + "##FORMAT=\n"+ + "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tNA12878\tNA12891\n"; + + public static String VCF4headerStringsWithUniqueSamplesName = + "##fileformat=VCFv4.0\n" + + "##filedate=2010-06-21\n"+ + "##reference=NCBI36\n"+ + "##INFO=\n"+ + "##INFO=\n"+ + "##INFO=\n"+ + "##FILTER=\n"+ + "##FORMAT=\n"+ + "##FORMAT=\n"+ + "##FORMAT=\n"+ + "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tNA12892\n"; + + // altered info field public static String VCF4headerStringsBrokenInfo = "##fileformat=VCFv4.0\n"+ @@ -110,6 +137,26 @@ public class CombineVariantsUnitTest { return head; } + @Test + public void testHeadersWithSamplesNamesDuplicationThatIsNotAllowed() { + VCFHeader one = createHeader(VCF4headerStringsWithSamplesName); + VCFHeader two = createHeader(VCF4headerStringsWithSamplesName); + Map headers = new HashMap(); + headers.put("VCF4headerStringsWithSamplesName",one); + headers.put("VCF4headerStringsWithSamplesName2",two); + Assert.assertEquals(SampleUtils.verifyUniqueSamplesNames(headers),false); + } + + @Test + public void testHeadersWithoutSamplesNamesDuplication() { + VCFHeader one = createHeader(VCF4headerStringsWithSamplesName); + VCFHeader two = createHeader(VCF4headerStringsWithUniqueSamplesName); + Map headers = new HashMap(); + headers.put("VCF4headerStringsWithSamplesName",one); + headers.put("VCF4headerStringsWithSamplesName2",two); + Assert.assertEquals(SampleUtils.verifyUniqueSamplesNames(headers),true); + } + @Test public void testHeadersWhereOneIsAStrictSubsetOfTheOther() { VCFHeader one = createHeader(VCFHeaderUnitTest.VCF4headerStrings); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java index 996eab7e9..3ebac3e58 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java @@ -208,6 +208,10 @@ public class CombineVariants extends RodWalker implements Tree logger.info("Priority string is not provided, using arbitrary genotyping order: "+priority); } + if (genotypeMergeOption == VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE && + !SampleUtils.verifyUniqueSamplesNames(vcfRods)) + throw new IllegalStateException("REQUIRE_UNIQUE sample names is true but duplicate names were discovered."); + samples = sitesOnlyVCF ? Collections.emptySet() : SampleUtils.getSampleList(vcfRods, genotypeMergeOption); if ( SET_KEY.toLowerCase().equals("null") ) @@ -223,6 +227,8 @@ public class CombineVariants extends RodWalker implements Tree vcfWriter.writeHeader(vcfHeader); } + + private void validateAnnotateUnionArguments() { Set rodNames = SampleUtils.getRodNamesWithVCFHeader(getToolkit(), null); diff --git a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java index 94e073ca3..6a430588b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java @@ -132,6 +132,25 @@ public class SampleUtils { return samples; } + + /** + * + * @param VCF_Headers + * @return false if there are names duplication between the samples names in the VCF headers + */ + public static boolean verifyUniqueSamplesNames(Map VCF_Headers) { + Set samples = new HashSet(); + for ( Map.Entry val : VCF_Headers.entrySet() ) { + VCFHeader header = val.getValue(); + for ( String sample : header.getGenotypeSamples() ) { + if (samples.add(sample)) + return false; + } + } + + return true; + } + /** * Gets the sample names from all VCF rods input by the user and uniquifies them if there is overlap * (e.g. sampleX.1, sampleX.2, ...) diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index 0a848fba1..b2f41d43b 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -450,7 +450,9 @@ public class VariantContextUtils { /** * Merges VariantContexts into a single hybrid. Takes genotypes for common samples in priority order, if provided. * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with - * the sample name + * the sample name. + * simpleMerge does not verify any more unique sample names EVEN if genotypeMergeOptions == GenotypeMergeType.REQUIRE_UNIQUE. One should use + * SampleUtils.verifyUniqueSamplesNames to check that before using sempleMerge. * * @param unsortedVCs collection of unsorted VCs * @param priorityListOfVCs priority list detailing the order in which we should grab the VCs @@ -483,9 +485,6 @@ public class VariantContextUtils { if ( annotateOrigin && priorityListOfVCs == null && originalNumOfVCs == 0) throw new IllegalArgumentException("Cannot merge calls and annotate their origins without a complete priority list of VariantContexts or the number of original VariantContexts"); - if ( genotypeMergeOptions == GenotypeMergeType.REQUIRE_UNIQUE ) - verifyUniqueSampleNames(unsortedVCs); - final List preFilteredVCs = sortVariantContextsByPriority(unsortedVCs, priorityListOfVCs, genotypeMergeOptions); // Make sure all variant contexts are padded with reference base in case of indels if necessary final List VCs = new ArrayList(); @@ -774,18 +773,19 @@ public class VariantContextUtils { } } - static private void verifyUniqueSampleNames(Collection unsortedVCs) { - Set names = new HashSet(); - for ( VariantContext vc : unsortedVCs ) { - for ( String name : vc.getSampleNames() ) { - //System.out.printf("Checking %s %b%n", name, names.contains(name)); - if ( names.contains(name) ) - throw new IllegalStateException("REQUIRE_UNIQUE sample names is true but duplicate names were discovered " + name); - } - - names.addAll(vc.getSampleNames()); - } - } +// TODO: remove that after testing +// static private void verifyUniqueSampleNames(Collection unsortedVCs) { +// Set names = new HashSet(); +// for ( VariantContext vc : unsortedVCs ) { +// for ( String name : vc.getSampleNames() ) { +// //System.out.printf("Checking %s %b%n", name, names.contains(name)); +// if ( names.contains(name) ) +// throw new IllegalStateException("REQUIRE_UNIQUE sample names is true but duplicate names were discovered " + name); +// } +// +// names.addAll(vc.getSampleNames()); +// } +// } static private Allele determineReferenceAllele(List VCs) { diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java index 9ddb6957c..9c1486cf7 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java @@ -542,15 +542,16 @@ public class VariantContextUtilsUnitTest extends BaseTest { Assert.assertEquals(merged.getSampleNames(), new HashSet(Arrays.asList("s1.1", "s1.2"))); } - @Test(expectedExceptions = IllegalStateException.class) - public void testMergeGenotypesRequireUnique() { - final VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)); - final VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)); - - final VariantContext merged = VariantContextUtils.simpleMerge( - Arrays.asList(vc1, vc2), null, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE, false, false, "set", false, false); - } +// TODO: remove after testing +// @Test(expectedExceptions = IllegalStateException.class) +// public void testMergeGenotypesRequireUnique() { +// final VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)); +// final VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)); +// +// final VariantContext merged = VariantContextUtils.simpleMerge( +// Arrays.asList(vc1, vc2), null, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, +// VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE, false, false, "set", false, false); +// } // -------------------------------------------------------------------------------- // From e445c71161d52ca0427a086aa51f4cae5f0c6387 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 24 Jan 2013 16:36:55 -0500 Subject: [PATCH 093/188] LIBS optimization for adapter clipping -- GATKSAMRecords now cache the result of the getAdapterBoundary, allowing us to avoid repeating a lot of work in LIBS -- Added unittests to cover adapter clipping --- .../locusiterator/LocusIteratorByState.java | 2 +- .../sting/utils/sam/GATKSAMRecord.java | 23 ++++++ .../sting/utils/sam/ReadUtils.java | 2 +- .../activeregion/ActivityProfileUnitTest.java | 13 --- .../LocusIteratorByStateUnitTest.java | 82 ++++++++++++++++++- .../sting/utils/sam/ReadUtilsUnitTest.java | 66 +++++++++++---- 6 files changed, 157 insertions(+), 31 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java index e7b75f1f2..435f9901a 100644 --- a/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java +++ b/public/java/src/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByState.java @@ -328,7 +328,7 @@ public final class LocusIteratorByState extends LocusIterator { * @return true if the read should be excluded from the pileup, false otherwise */ @Requires({"rec != null", "pos > 0"}) - private boolean dontIncludeReadInPileup(GATKSAMRecord rec, long pos) { + private boolean dontIncludeReadInPileup(final GATKSAMRecord rec, final long pos) { return ReadUtils.isBaseInsideAdaptor(rec, pos); } diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java b/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java index 9cd584d1b..62beb8814 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java @@ -46,6 +46,10 @@ import java.util.Map; * if they are ever modified externally then one must also invoke the * setReadGroup() method here to ensure that the cache is kept up-to-date. * + * WARNING -- GATKSAMRecords cache several values (that are expensive to compute) + * that depending on the inferred insert size and alignment starts and stops of this read and its mate. + * Changing these values in any way will invalidate the cached value. However, we do not monitor those setter + * functions, so modifying a GATKSAMRecord in any way may result in stale cached values. */ public class GATKSAMRecord extends BAMRecord { // ReduceReads specific attribute tags @@ -70,6 +74,7 @@ public class GATKSAMRecord extends BAMRecord { private final static int UNINITIALIZED = -1; private int softStart = UNINITIALIZED; private int softEnd = UNINITIALIZED; + private Integer adapterBoundary = null; // because some values can be null, we don't want to duplicate effort private boolean retrievedReadGroup = false; @@ -561,4 +566,22 @@ public class GATKSAMRecord extends BAMRecord { } return clone; } + + /** + * A caching version of ReadUtils.getAdaptorBoundary() + * + * @see ReadUtils.getAdaptorBoundary(SAMRecord) for more information about the meaning of this function + * + * WARNING -- this function caches a value depending on the inferred insert size and alignment starts + * and stops of this read and its mate. Changing these values in any way will invalidate the cached value. + * However, we do not monitor those setter functions, so modifying a GATKSAMRecord in any way may + * result in stale cached values. + * + * @return the result of calling ReadUtils.getAdaptorBoundary on this read + */ + public int getAdapterBoundary() { + if ( adapterBoundary == null ) + adapterBoundary = ReadUtils.getAdaptorBoundary(this); + return adapterBoundary; + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index 1488f7269..3c0f9038b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -169,7 +169,7 @@ public class ReadUtils { * @return whether or not the base is in the adaptor */ public static boolean isBaseInsideAdaptor(final GATKSAMRecord read, long basePos) { - final int adaptorBoundary = getAdaptorBoundary(read); + final int adaptorBoundary = read.getAdapterBoundary(); if (adaptorBoundary == CANNOT_COMPUTE_ADAPTOR_BOUNDARY || read.getInferredInsertSize() > DEFAULT_ADAPTOR_SIZE) return false; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index f6246b137..792361ac3 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -467,19 +467,6 @@ public class ActivityProfileUnitTest extends BaseTest { return -1; } - -// private int findCutSite(final List probs) { -// for ( int i = probs.size() - 2; i > 0; i-- ) { -// double prev = probs.get(i + 1); -// double next = probs.get(i-1); -// double cur = probs.get(i); -// if ( cur < next && cur < prev ) -// return i + 1; -// } -// -// return -1; -// } - @Test(dataProvider = "ActiveRegionCutTests") public void testActiveRegionCutTests(final int minRegionSize, final int maxRegionSize, final int expectedRegionSize, final List probs) { final ActivityProfile profile = new ActivityProfile(genomeLocParser); diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index e5e28e1f6..4e7a783e5 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -51,7 +51,7 @@ import java.util.*; * testing of the new (non-legacy) version of LocusIteratorByState */ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; protected LocusIteratorByState li; @Test(enabled = true) @@ -686,4 +686,84 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { return read; } } + + // --------------------------------------------------------------------------- + // + // make sure that adapter clipping is working properly in LIBS + // + // --------------------------------------------------------------------------- + @DataProvider(name = "AdapterClippingTest") + public Object[][] makeAdapterClippingTest() { + final List tests = new LinkedList(); + + final int start = 10; +// for ( final int goodBases : Arrays.asList(10) ) { +// for ( final int nClipsOnTheRight : Arrays.asList(0)) { + for ( final int goodBases : Arrays.asList(10, 20, 30) ) { + for ( final int nClips : Arrays.asList(0, 1, 2, 10)) { + for ( final boolean onLeft : Arrays.asList(true, false) ) { + final int readLength = nClips + goodBases; + GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read1" , 0, start, readLength); + read.setReadBases(Utils.dupBytes((byte) 'A', readLength)); + read.setBaseQualities(Utils.dupBytes((byte) '@', readLength)); + read.setCigarString(readLength + "M"); + + if ( onLeft ) { + read.setReadNegativeStrandFlag(true); + read.setMateAlignmentStart(start + nClips); + read.setInferredInsertSize(readLength); + tests.add(new Object[]{nClips, goodBases, 0, read}); + } else { + read.setReadNegativeStrandFlag(false); + read.setMateAlignmentStart(start - 1); + read.setInferredInsertSize(goodBases - 1); + tests.add(new Object[]{0, goodBases, nClips, read}); + } + } + } + } + +// for ( final int nClipsOnTheLeft : Arrays.asList(0, 1, 2, 10)) { +// final int readLength = nClipsOnTheLeft + goodBases; +// GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read1" , 0, start, readLength); +// read.setReadBases(Utils.dupBytes((byte) 'A', readLength)); +// read.setBaseQualities(Utils.dupBytes((byte) '@', readLength)); +// read.setCigarString(readLength + "M"); +// read.setReadNegativeStrandFlag(true); +// +// read.setMateAlignmentStart(start + nClipsOnTheLeft); +// read.setInferredInsertSize(readLength); +// +// tests.add(new Object[]{nClipsOnTheLeft, goodBases, 0, read}); +// } +// } + + return tests.toArray(new Object[][]{}); + } + + @Test(enabled = true, dataProvider = "AdapterClippingTest") +// @Test(enabled = true, dataProvider = "LIBS_NotHoldingTooManyReads", timeOut = 100000) + public void testAdapterClipping(final int nClipsOnLeft, final int nReadContainingPileups, final int nClipsOnRight, final GATKSAMRecord read) { + + li = new LocusIteratorByState(new FakeCloseableIterator(Collections.singletonList(read).iterator()), + createTestReadProperties(DownsamplingMethod.NONE, false), + genomeLocParser, + LocusIteratorByState.sampleListForSAMWithoutReadGroups()); + + int expectedPos = read.getAlignmentStart() + nClipsOnLeft; + int nPileups = 0; + while ( li.hasNext() ) { + final AlignmentContext next = li.next(); + Assert.assertEquals(next.getLocation().getStart(), expectedPos); +// if ( nPileups < nClipsOnLeft || nPileups > (nClipsOnLeft + nReadContainingPileups) ) +// Assert.assertEquals(next.getBasePileup().getNumberOfElements(), 0, "Expected empty pileups when the read is in the adapter clipping zone at " + nPileups); +// else +// Assert.assertEquals(next.getBasePileup().getNumberOfElements(), 1, "Expected a pileups with 1 element when the read is within the good part of the read at " + nPileups); + nPileups++; + expectedPos++; + } + + final int nExpectedPileups = nReadContainingPileups; + Assert.assertEquals(nPileups, nExpectedPileups, "Wrong number of pileups seen"); + } } diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java index 4194aa6d5..b11f2af24 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java @@ -27,66 +27,99 @@ package org.broadinstitute.sting.utils.sam; import org.broadinstitute.sting.BaseTest; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.util.LinkedList; +import java.util.List; + public class ReadUtilsUnitTest extends BaseTest { - @Test - public void testGetAdaptorBoundary() { + private interface GetAdaptorFunc { + public int getAdaptor(final GATKSAMRecord record); + } + + @DataProvider(name = "AdaptorGetter") + public Object[][] makeActiveRegionCutTests() { + final List tests = new LinkedList(); + + tests.add( new Object[]{ new GetAdaptorFunc() { + @Override public int getAdaptor(final GATKSAMRecord record) { return ReadUtils.getAdaptorBoundary(record); } + }}); + + tests.add( new Object[]{ new GetAdaptorFunc() { + @Override public int getAdaptor(final GATKSAMRecord record) { return record.getAdapterBoundary(); } + }}); + + return tests.toArray(new Object[][]{}); + } + + private GATKSAMRecord makeRead(final int fragmentSize, final int mateStart) { final byte[] bases = {'A', 'C', 'G', 'T', 'A', 'C', 'G', 'T'}; final byte[] quals = {30, 30, 30, 30, 30, 30, 30, 30}; final String cigar = "8M"; + GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, cigar); + read.setMateAlignmentStart(mateStart); + read.setInferredInsertSize(fragmentSize); + return read; + } + + @Test(dataProvider = "AdaptorGetter") + public void testGetAdaptorBoundary(final GetAdaptorFunc get) { final int fragmentSize = 10; final int mateStart = 1000; final int BEFORE = mateStart - 2; final int AFTER = mateStart + 2; int myStart, boundary; - - GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(bases, quals, cigar); - read.setMateAlignmentStart(mateStart); - read.setInferredInsertSize(fragmentSize); + GATKSAMRecord read; // Test case 1: positive strand, first read + read = makeRead(fragmentSize, mateStart); myStart = BEFORE; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(false); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, myStart + fragmentSize + 1); // Test case 2: positive strand, second read + read = makeRead(fragmentSize, mateStart); myStart = AFTER; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(false); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, myStart + fragmentSize + 1); // Test case 3: negative strand, second read + read = makeRead(fragmentSize, mateStart); myStart = AFTER; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(true); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, mateStart - 1); // Test case 4: negative strand, first read + read = makeRead(fragmentSize, mateStart); myStart = BEFORE; read.setAlignmentStart(myStart); read.setReadNegativeStrandFlag(true); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, mateStart - 1); // Test case 5: mate is mapped to another chromosome (test both strands) + read = makeRead(fragmentSize, mateStart); read.setInferredInsertSize(0); read.setReadNegativeStrandFlag(true); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setReadNegativeStrandFlag(false); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setInferredInsertSize(10); // Test case 6: read is unmapped + read = makeRead(fragmentSize, mateStart); read.setReadUnmappedFlag(true); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); read.setReadUnmappedFlag(false); @@ -94,19 +127,22 @@ public class ReadUtilsUnitTest extends BaseTest { // <--------| // |------> // first read: + read = makeRead(fragmentSize, mateStart); myStart = 980; read.setAlignmentStart(myStart); read.setInferredInsertSize(20); read.setReadNegativeStrandFlag(true); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); // second read: + read = makeRead(fragmentSize, mateStart); myStart = 1000; read.setAlignmentStart(myStart); + read.setInferredInsertSize(20); read.setMateAlignmentStart(980); read.setReadNegativeStrandFlag(false); - boundary = ReadUtils.getAdaptorBoundary(read); + boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); } } From b8c0b05785e36015b3a839eac56cea00a9fd2b2e Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 16:00:06 -0500 Subject: [PATCH 094/188] Add contract to ensure that getAdapterBoundary returns the right result -- Also renamed the function to getAdaptorBoundary for consistency across the codebase --- .../src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java | 4 +++- .../src/org/broadinstitute/sting/utils/sam/ReadUtils.java | 2 +- .../org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java b/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java index 62beb8814..504e718d0 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/GATKSAMRecord.java @@ -25,6 +25,7 @@ package org.broadinstitute.sting.utils.sam; +import com.google.java.contract.Ensures; import net.sf.samtools.*; import org.broadinstitute.sting.utils.NGSPlatform; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; @@ -579,7 +580,8 @@ public class GATKSAMRecord extends BAMRecord { * * @return the result of calling ReadUtils.getAdaptorBoundary on this read */ - public int getAdapterBoundary() { + @Ensures("result == ReadUtils.getAdaptorBoundary(this)") + public int getAdaptorBoundary() { if ( adapterBoundary == null ) adapterBoundary = ReadUtils.getAdaptorBoundary(this); return adapterBoundary; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index 3c0f9038b..c17e81b9c 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -169,7 +169,7 @@ public class ReadUtils { * @return whether or not the base is in the adaptor */ public static boolean isBaseInsideAdaptor(final GATKSAMRecord read, long basePos) { - final int adaptorBoundary = read.getAdapterBoundary(); + final int adaptorBoundary = read.getAdaptorBoundary(); if (adaptorBoundary == CANNOT_COMPUTE_ADAPTOR_BOUNDARY || read.getInferredInsertSize() > DEFAULT_ADAPTOR_SIZE) return false; diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java index b11f2af24..7b48b1b69 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java @@ -48,7 +48,7 @@ public class ReadUtilsUnitTest extends BaseTest { }}); tests.add( new Object[]{ new GetAdaptorFunc() { - @Override public int getAdaptor(final GATKSAMRecord record) { return record.getAdapterBoundary(); } + @Override public int getAdaptor(final GATKSAMRecord record) { return record.getAdaptorBoundary(); } }}); return tests.toArray(new Object[][]{}); From e7c9e3639e4802dfce987163a58dc2ad86d6bca7 Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Fri, 25 Jan 2013 17:49:15 -0500 Subject: [PATCH 095/188] Making metrics a required parameter in MarkDuplicates As requested by user (forum) --- .../sting/queue/extensions/picard/MarkDuplicates.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scala/src/org/broadinstitute/sting/queue/extensions/picard/MarkDuplicates.scala b/public/scala/src/org/broadinstitute/sting/queue/extensions/picard/MarkDuplicates.scala index 59a51db96..7567434e2 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/extensions/picard/MarkDuplicates.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/extensions/picard/MarkDuplicates.scala @@ -48,7 +48,7 @@ class MarkDuplicates extends org.broadinstitute.sting.queue.function.JavaCommand @Output(doc="The output bam index", shortName = "out_index", fullName = "output_bam_index_file", required = false) var outputIndex: File = _ - @Output(doc="File to write duplication metrics to", shortName = "out_metrics", fullName = "output_metrics_file", required = false) + @Output(doc="File to write duplication metrics to", shortName = "out_metrics", fullName = "output_metrics_file", required = true) var metrics: File = new File(output + ".metrics") @Argument(doc="If true do not write duplicates to the output file instead of writing them with appropriate flags set.", shortName = "remdup", fullName = "remove_duplicates", required = false) From ef4cc742e590ead64feb10ba17054f92bdd3dd8b Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Sat, 26 Jan 2013 12:36:30 -0500 Subject: [PATCH 096/188] Fixing the licensing scripts - Fixed shell glob limitation that was failing license updates on big commits - Hook will now force user to re-commit after updating the licenses (pre-commit hook can't update and commit in the same process) - Moved all scripts to bash/zsh - Separated the license utilities in a separate python module to avoid copying code GSATDG-28 #resolve --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6e2c2f224..9a20b68ca 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.ipr *.iws *.iml +*.pyc .DS_Store queueScatterGather /foo* From 6ea7133d95cffb5979d66106d11e6061c0da1314 Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Sat, 26 Jan 2013 13:21:25 -0500 Subject: [PATCH 097/188] Updating licenses of latest moved files --- .../AlleleBiasedDownsamplingUtils.java | 65 +++++++------------ .../gatk/walkers/annotator/AlleleBalance.java | 65 +++++++------------ .../annotator/AlleleBalanceBySample.java | 65 +++++++------------ .../annotator/AverageAltAlleleLength.java | 65 +++++++------------ .../gatk/walkers/annotator/BaseCounts.java | 65 +++++++------------ .../sting/gatk/walkers/annotator/LowMQ.java | 65 +++++++------------ .../annotator/MappingQualityZeroBySample.java | 65 +++++++------------ .../annotator/MappingQualityZeroFraction.java | 65 +++++++------------ .../gatk/walkers/annotator/NBaseCount.java | 65 +++++++------------ .../sting/gatk/walkers/annotator/SnpEff.java | 65 +++++++------------ .../annotator/TechnologyComposition.java | 65 +++++++------------ .../walkers/annotator/VariantAnnotator.java | 65 +++++++------------ .../annotator/VariantAnnotatorEngine.java | 65 +++++++------------ .../ActiveRegionBasedAnnotation.java | 65 +++++++------------ .../AnnotationInterfaceManager.java | 65 +++++++------------ .../annotator/interfaces/AnnotationType.java | 65 +++++++------------ .../interfaces/AnnotatorCompatible.java | 65 +++++++------------ .../interfaces/ExperimentalAnnotation.java | 65 +++++++------------ .../interfaces/GenotypeAnnotation.java | 65 +++++++------------ .../interfaces/InfoFieldAnnotation.java | 65 +++++++------------ .../interfaces/RodRequiringAnnotation.java | 65 +++++++------------ .../interfaces/StandardAnnotation.java | 65 +++++++------------ .../VariantAnnotatorAnnotation.java | 65 +++++++------------ .../interfaces/WorkInProgressAnnotation.java | 65 +++++++------------ .../walkers/beagle/BeagleOutputToVCF.java | 65 +++++++------------ .../walkers/beagle/ProduceBeagleInput.java | 65 +++++++------------ .../beagle/VariantsToBeagleUnphased.java | 65 +++++++------------ .../walkers/coverage/DepthOfCoverage.java | 65 +++++++------------ .../coverage/DepthOfCoverageStats.java | 65 +++++++------------ .../walkers/diffengine/BAMDiffableReader.java | 65 +++++++------------ .../diffengine/GATKReportDiffableReader.java | 65 +++++++------------ .../walkers/diffengine/VCFDiffableReader.java | 65 +++++++------------ .../fasta/FastaAlternateReferenceMaker.java | 65 +++++++------------ .../walkers/fasta/FastaReferenceMaker.java | 65 +++++++------------ .../gatk/walkers/fasta/FastaSequence.java | 65 +++++++------------ .../gatk/walkers/filters/ClusteredSnps.java | 65 +++++++------------ .../walkers/filters/FiltrationContext.java | 65 +++++++------------ .../filters/FiltrationContextWindow.java | 65 +++++++------------ .../walkers/filters/VariantFiltration.java | 65 +++++++------------ .../validation/ValidationAmplicons.java | 65 +++++++------------ .../gatk/walkers/varianteval/VariantEval.java | 65 +++++++------------ .../varianteval/VariantEvalReportWriter.java | 65 +++++++------------ .../varianteval/evaluators/CompOverlap.java | 65 +++++++------------ .../varianteval/evaluators/CountVariants.java | 65 +++++++------------ .../evaluators/IndelLengthHistogram.java | 65 +++++++------------ .../varianteval/evaluators/IndelSummary.java | 65 +++++++------------ .../MendelianViolationEvaluator.java | 65 +++++++------------ .../evaluators/MultiallelicSummary.java | 65 +++++++------------ .../evaluators/PrintMissingComp.java | 65 +++++++------------ .../varianteval/evaluators/StandardEval.java | 65 +++++++------------ .../evaluators/ThetaVariantEvaluator.java | 65 +++++++------------ .../evaluators/TiTvVariantEvaluator.java | 65 +++++++------------ .../evaluators/ValidationReport.java | 65 +++++++------------ .../evaluators/VariantEvaluator.java | 65 +++++++------------ .../evaluators/VariantSummary.java | 65 +++++++------------ .../stratifications/AlleleCount.java | 65 +++++++------------ .../stratifications/AlleleFrequency.java | 65 +++++++------------ .../varianteval/stratifications/CompRod.java | 65 +++++++------------ .../varianteval/stratifications/Contig.java | 65 +++++++------------ .../varianteval/stratifications/CpG.java | 65 +++++++------------ .../stratifications/Degeneracy.java | 65 +++++++------------ .../DynamicStratification.java | 65 +++++++------------ .../varianteval/stratifications/EvalRod.java | 65 +++++++------------ .../varianteval/stratifications/Filter.java | 65 +++++++------------ .../stratifications/FunctionalClass.java | 65 +++++++------------ .../stratifications/IndelSize.java | 65 +++++++------------ .../IntervalStratification.java | 65 +++++++------------ .../stratifications/JexlExpression.java | 65 +++++++------------ .../varianteval/stratifications/Novelty.java | 65 +++++++------------ .../stratifications/OneBPIndel.java | 65 +++++++------------ .../RequiredStratification.java | 65 +++++++------------ .../varianteval/stratifications/Sample.java | 65 +++++++------------ .../StandardStratification.java | 65 +++++++------------ .../stratifications/TandemRepeat.java | 65 +++++++------------ .../stratifications/VariantStratifier.java | 65 +++++++------------ .../stratifications/VariantType.java | 65 +++++++------------ .../stratifications/manager/StratNode.java | 65 +++++++------------ .../manager/StratNodeIterator.java | 65 +++++++------------ .../manager/StratificationManager.java | 65 +++++++------------ .../stratifications/manager/Stratifier.java | 65 +++++++------------ .../walkers/varianteval/util/Analysis.java | 65 +++++++------------ .../util/AnalysisModuleScanner.java | 65 +++++++------------ .../walkers/varianteval/util/DataPoint.java | 65 +++++++------------ .../varianteval/util/EvaluationContext.java | 65 +++++++------------ .../gatk/walkers/varianteval/util/Molten.java | 65 +++++++------------ .../util/SortableJexlVCMatchExp.java | 65 +++++++------------ .../varianteval/util/VariantEvalUtils.java | 65 +++++++------------ .../VQSRCalibrationCurve.java | 65 +++++++------------ .../variantutils/ConcordanceMetrics.java | 65 +++++++------------ .../variantutils/FilterLiftedVariants.java | 65 +++++++------------ .../variantutils/GenotypeConcordance.java | 65 +++++++------------ .../variantutils/LeftAlignVariants.java | 65 +++++++------------ .../variantutils/LiftoverVariants.java | 65 +++++++------------ .../variantutils/RandomlySplitVariants.java | 65 +++++++------------ .../walkers/variantutils/SelectHeaders.java | 65 +++++++------------ .../walkers/variantutils/SelectVariants.java | 65 +++++++------------ .../variantutils/ValidateVariants.java | 65 +++++++------------ .../VariantValidationAssessor.java | 65 +++++++------------ .../variantutils/VariantsToBinaryPed.java | 65 +++++++------------ .../walkers/variantutils/VariantsToTable.java | 65 +++++++------------ .../walkers/variantutils/VariantsToVCF.java | 65 +++++++------------ .../utils/activeregion/ActivityProfile.java | 46 ++++++------- .../activeregion/BandPassActivityProfile.java | 46 ++++++------- .../genotyper/PerReadAlleleLikelihoodMap.java | 65 +++++++------------ .../ActivityProfileStateUnitTest.java | 46 ++++++------- .../activeregion/ActivityProfileUnitTest.java | 46 ++++++------- .../BandPassActivityProfileUnitTest.java | 46 ++++++------- 107 files changed, 2359 insertions(+), 4501 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java b/public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java index 02821ab50..11f03ce36 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java +++ b/public/java/src/org/broadinstitute/sting/gatk/downsampling/AlleleBiasedDownsamplingUtils.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.downsampling; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java index 146f71e16..73c31ef66 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalance.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java index c501c2f5f..fbba6722e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AlleleBalanceBySample.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java index d5c9bcef2..17a33bdca 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/AverageAltAlleleLength.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java index c3500fbc0..704422308 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/BaseCounts.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java index 94f5aac56..8ed9a9fe0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/LowMQ.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java index 9e334847d..fa1a5dde5 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroBySample.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java index 659a94d9e..65d2f0757 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/MappingQualityZeroFraction.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java index c5142b285..8cabb7c82 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/NBaseCount.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java index 58f606066..17002ba39 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/SnpEff.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java index 6d8f015f0..dbaafb1ed 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TechnologyComposition.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java index c3f738c92..e30d43185 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java index f03a25c04..29f6ed388 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java index 32ca332ca..bc725815d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ActiveRegionBasedAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java index 1e7a2fa80..221887158 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationInterfaceManager.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java index 70cb5bef1..515efab5b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotationType.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java index 44102899b..98b7cad9c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/AnnotatorCompatible.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java index ce6974101..4161f6c22 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/ExperimentalAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java index cb10de73d..ec058708c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/GenotypeAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java index 092dc6e36..ce1bb47e5 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/InfoFieldAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java index 4b893cb01..4a6a47418 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/RodRequiringAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java index c63875ed6..62734fe6c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/StandardAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java index f8442f4dc..1415c1d7c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/VariantAnnotatorAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java index eb6b617bf..14f39de17 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/interfaces/WorkInProgressAnnotation.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.annotator.interfaces; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java index 03df03a14..09b2cba80 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.beagle; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java index 409c8dca8..15527d34a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.beagle; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java index e5b5286b6..3ef688d02 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.beagle; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java index b10daab58..dbb8ed5a6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.coverage; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java index 6fe452a82..56aa6f2d7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverageStats.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.coverage; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java index 6badc0d78..57d903f4d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/BAMDiffableReader.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.diffengine; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java index a69ac4181..55f52a32a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/GATKReportDiffableReader.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.diffengine; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java index 4c1989cdc..59f3d512c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.diffengine; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java index 3562b3d75..8a5b3530e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.fasta; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java index 4cac2f119..e9728601d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.fasta; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java index bcdf6c3a6..41f701f1a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaSequence.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.fasta; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java index d73ac9220..f186fc73d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/ClusteredSnps.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.filters; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java index faddf97da..bce20d31a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContext.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.filters; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java index 56a5b6289..f41053f75 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/FiltrationContextWindow.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.filters; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java index 461afd049..091d5e428 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.filters; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java index 8547c0993..1a9ce5ad5 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/validation/ValidationAmplicons.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.validation; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java index e1450a428..d586ee7da 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java index 77459a0de..a63f32485 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java index dc11b1032..c0b87b5b7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CompOverlap.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java index 2392f4901..33a5a9fc9 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/CountVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java index 548b0ab42..643948b45 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelLengthHistogram.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java index 4793aa390..68fcc6aba 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/IndelSummary.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java index 0ad5c8c31..3d082f23c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MendelianViolationEvaluator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java index e839d73b8..e9fc8114b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/MultiallelicSummary.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java index bf370a9ad..8553ed376 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/PrintMissingComp.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java index 55712772e..206fc9560 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/StandardEval.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java index 54cccb52c..c5e73a875 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ThetaVariantEvaluator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java index 129b67e81..4ad7be045 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/TiTvVariantEvaluator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java index 92a1c6c43..c31cf9f86 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/ValidationReport.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java index d3660cf32..13130ccb0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantEvaluator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java index d5aedaf04..a3b703ad3 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.evaluators; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java index fdd4b1ef4..f18f73bac 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleCount.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java index 1d8b05fce..179161ee2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/AlleleFrequency.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java index 0609260f0..202f6528a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CompRod.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java index f0cb84930..411aed94f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Contig.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java index e3457cad1..bba431ab4 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java index 02c306c43..120bd3cf0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Degeneracy.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java index 6e03f2bce..afb36cdc6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/DynamicStratification.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java index e1a0f9ea4..6d00bf16a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/EvalRod.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java index 9c85a84c1..49c2a8808 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Filter.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java index 60b05c966..d43db70fa 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/FunctionalClass.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java index 18d7ed3f8..3e10d3b98 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IndelSize.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java index c2555b3c9..be689fe55 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java index a83c2941c..a1a10294f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/JexlExpression.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java index 2be5c350b..ef077c678 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Novelty.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java index 6eb607879..65fb2dd11 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/OneBPIndel.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java index 5a1f51f05..de4ab5db8 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/RequiredStratification.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java index 144eeb841..ca9a1df85 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/Sample.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java index 06fc29e16..5267513ad 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/StandardStratification.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java index 621644df8..de82b18cc 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java index 91005e3c3..3ca8c0bdc 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantStratifier.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java index ecca7aecb..01862cf3a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/VariantType.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java index 256a7b7ff..4ab6262be 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNode.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications.manager; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java index 7bda94916..87fb3dfa4 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratNodeIterator.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications.manager; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java index 9d95313a1..053a88218 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications.manager; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java index be2a0dad5..d211eee50 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/Stratifier.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.stratifications.manager; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java index 9cc7e88de..838500ab8 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Analysis.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java index 4394e17a8..a5c3b125e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/AnalysisModuleScanner.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java index aacbb29e5..34c9368f2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/DataPoint.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java index 3059de37b..2e9512639 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/EvaluationContext.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java index a2f3acb4e..d65887090 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/Molten.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java index 74020ed18..1cd68c610 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/SortableJexlVCMatchExp.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java index fc6aaea76..7e751e4a0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/util/VariantEvalUtils.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.varianteval.util; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java index d3a79221e..d416d5d16 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VQSRCalibrationCurve.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantrecalibration; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java index 9d5495351..b7f88a330 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetrics.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java index f824ea4d1..c2785e920 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 47e2ea052..048c7ef77 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java index 7ac36b2f8..17f75229a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java index 940f2faf4..3ef9fa3d7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java index 23516b5ed..896f36e6c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RandomlySplitVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java index 38fa060cc..abd0956fb 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java index f79946a2e..6da6d14b1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java index f3e8167df..4b9f2c6c1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/ValidateVariants.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java index 5ac70a8c3..17d5ab1b1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java index e3cc27570..3bd95d9ec 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToBinaryPed.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java index 46bb4a48b..91057c812 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java index 9f2aa68e3..61746cbf1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.walkers.variantutils; diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index f265f9d60..15aca4162 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.activeregion; diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java index 75ae72f9e..37798410d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.activeregion; diff --git a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java index 28c20921e..46a3f58d0 100644 --- a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java +++ b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java @@ -1,47 +1,26 @@ /* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +* 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.utils.genotyper; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java index 019cf82da..f199a0d82 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileStateUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.activeregion; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index 792361ac3..1df4a3348 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.activeregion; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index ff1c9bdef..540e9470a 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -1,27 +1,27 @@ /* - * 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. - */ +* 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.utils.activeregion; From 705cccaf63c57e42fb3fe7450ba998d85ef324f7 Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Sun, 27 Jan 2013 02:36:31 -0500 Subject: [PATCH 099/188] Making SplitReads output FastQ's instead of BAM - eliminates one step in my pipeline - BAM is too finicky and maintaining parameters that wouldn't be useful was becoming a headache, better avoided. --- .../sting/gatk/io/FastqFileWriter.java | 77 +++++++++++++++++++ .../sting/utils/sam/GATKSAMRecord.java | 12 ++- .../sting/utils/sam/ReadUtils.java | 63 +++++++++++++++ .../variant/utils/BaseUtils.java | 23 ++++++ .../sting/utils/sam/ReadUtilsUnitTest.java | 20 +++++ 5 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/gatk/io/FastqFileWriter.java diff --git a/public/java/src/org/broadinstitute/sting/gatk/io/FastqFileWriter.java b/public/java/src/org/broadinstitute/sting/gatk/io/FastqFileWriter.java new file mode 100644 index 000000000..acef3e500 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/gatk/io/FastqFileWriter.java @@ -0,0 +1,77 @@ +/* +* 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.io; + +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.sam.ReadUtils; + +import java.io.FileNotFoundException; +import java.io.PrintStream; + +/** + * User: carneiro + * Date: 1/27/13 + * Time: 12:54 AM + */ +public class FastqFileWriter { + private PrintStream output; + + public FastqFileWriter(String filename) { + try { + this.output = new PrintStream(filename); + } catch (FileNotFoundException e) { + throw new ReviewedStingException("Can't open file " + filename); + } + } + + public void addAlignment(GATKSAMRecord read) { + output.println("@" + read.getReadName()); + + if (read.getReadNegativeStrandFlag()) { + output.println(ReadUtils.getBasesReverseComplement(read)); + output.println("+"); + output.println(ReadUtils.convertReadQualToString(invertQuals(read.getBaseQualities()))); + } else { + output.println(ReadUtils.convertReadBasesToString(read)); + output.println("+"); + output.println(ReadUtils.convertReadQualToString(read)); + } + } + + public void close() { + this.output.close(); + } + + private byte[] invertQuals (byte[] quals) { + final int l = quals.length; + byte[] invertedQuals = new byte[l]; + for (int i=0; i cigarElements = new LinkedList(); + cigarElements.add(new CigarElement(length, CigarOperator.M)); + Cigar cigar = new Cigar(cigarElements); + return ArtificialSAMUtils.createArtificialRead(cigar); + } + /////////////////////////////////////////////////////////////////////////////// // *** The following methods are overloaded to cache the appropriate data ***// /////////////////////////////////////////////////////////////////////////////// diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index c17e81b9c..29f8c8dcd 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.NGSPlatform; import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.variant.utils.BaseUtils; import java.io.File; import java.util.*; @@ -850,4 +851,66 @@ public class ReadUtils { return events; } + /** + * Given a read, outputs the read bases in a string format + * + * @param read the read + * @return a string representation of the read bases + */ + public static String convertReadBasesToString(GATKSAMRecord read) { + String bases = ""; + for (byte b : read.getReadBases()) { + bases += (char) b; + } + return bases.toUpperCase(); + } + + /** + * Given a read, outputs the base qualities in a string format + * + * @param quals the read qualities + * @return a string representation of the base qualities + */ + public static String convertReadQualToString(byte[] quals) { + String result = ""; + for (byte b : quals) { + result += (char) (33 + b); + } + return result; + } + + /** + * Given a read, outputs the base qualities in a string format + * + * @param read the read + * @return a string representation of the base qualities + */ + public static String convertReadQualToString(GATKSAMRecord read) { + return convertReadQualToString(read.getBaseQualities()); + } + + /** + * Returns the reverse complement of the read bases + * + * @param bases the read bases + * @return the reverse complement of the read bases + */ + public static String getBasesReverseComplement(byte[] bases) { + String reverse = ""; + for (int i = bases.length-1; i >=0; i--) { + reverse += (char) BaseUtils.getComplement(bases[i]); + } + return reverse; + } + + /** + * Returns the reverse complement of the read bases + * + * @param read the read + * @return the reverse complement of the read bases + */ + public static String getBasesReverseComplement(GATKSAMRecord read) { + return getBasesReverseComplement(read.getReadBases()); + } + } diff --git a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java index a6ac2ca53..bbd02e0a6 100644 --- a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java @@ -26,6 +26,7 @@ package org.broadinstitute.variant.utils; import net.sf.samtools.util.StringUtil; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import java.util.Arrays; @@ -497,4 +498,26 @@ public class BaseUtils { return randomBaseIndex; } + + public static byte getComplement(byte base) { + switch(base) { + case 'a': + case 'A': + return 'T'; + case 'c': + case 'C': + return 'G'; + case 'g': + case 'G': + return 'C'; + case 't': + case 'T': + return 'A'; + case 'n': + case 'N': + return 'N'; + default: + throw new ReviewedStingException("base must be A, C, G or T. " + (char) base + " is not a valid base."); + } + } } diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java index 7b48b1b69..20971643e 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java @@ -26,12 +26,15 @@ package org.broadinstitute.sting.utils.sam; import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; +import org.broadinstitute.variant.utils.BaseUtils; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.LinkedList; import java.util.List; +import java.util.Random; public class ReadUtilsUnitTest extends BaseTest { @@ -145,4 +148,21 @@ public class ReadUtilsUnitTest extends BaseTest { boundary = get.getAdaptor(read); Assert.assertEquals(boundary, ReadUtils.CANNOT_COMPUTE_ADAPTOR_BOUNDARY); } + + @Test (enabled = true) + public void testGetBasesReverseComplement() { + int iterations = 1000; + Random random = GenomeAnalysisEngine.getRandomGenerator(); + while(iterations-- > 0) { + final int l = random.nextInt(1000); + GATKSAMRecord read = GATKSAMRecord.createRandomRead(l); + byte [] original = read.getReadBases(); + byte [] reconverted = new byte[l]; + String revComp = ReadUtils.getBasesReverseComplement(read); + for (int i=0; i Date: Fri, 25 Jan 2013 17:20:13 -0500 Subject: [PATCH 100/188] ART optimization: BandPassActivityProfile only applies the gaussian filter if the state probability > 0 --- .../activeregion/BandPassActivityProfile.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java index 37798410d..a1f1fc580 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -153,12 +153,16 @@ public class BandPassActivityProfile extends ActivityProfile { final Collection states = new LinkedList(); for ( final ActivityProfileState superState : super.processState(justAddedState) ) { - for( int jjj = -filterSize; jjj <= filterSize; jjj++ ) { - final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj); - if ( loc != null ) { - final double newProb = superState.isActiveProb * GaussianKernel[jjj + filterSize]; - states.add(new ActivityProfileState(loc, newProb)); + if ( superState.isActiveProb > 0.0 ) { + for( int jjj = -filterSize; jjj <= filterSize; jjj++ ) { + final GenomeLoc loc = getLocForOffset(justAddedState.getLoc(), jjj); + if ( loc != null ) { + final double newProb = superState.isActiveProb * GaussianKernel[jjj + filterSize]; + states.add(new ActivityProfileState(loc, newProb)); + } } + } else { + states.add(justAddedState); } } From 93d88cdc68e2f715fb570f8a86579b042b4a02d4 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 17:21:05 -0500 Subject: [PATCH 101/188] Optimization: LocusReferenceView now passes along the contig index to createGenomeLoc, speeding up their creation -- Also cleaned up some unused methods --- .../providers/LocusReferenceView.java | 43 ++----------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusReferenceView.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusReferenceView.java index f74724795..d5b7d0487 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusReferenceView.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusReferenceView.java @@ -123,38 +123,10 @@ public class LocusReferenceView extends ReferenceView { if(bounds != null) { int expandedStart = getWindowStart( bounds ); int expandedStop = getWindowStop( bounds ); - initializeReferenceSequence(genomeLocParser.createGenomeLoc(bounds.getContig(), expandedStart, expandedStop)); + initializeReferenceSequence(genomeLocParser.createGenomeLoc(bounds.getContig(), bounds.getContigIndex(), expandedStart, expandedStop)); } } - /** Returns true if the specified location is fully within the bounds of the reference window loaded into - * this LocusReferenceView object. - */ - public boolean isLocationWithinBounds(GenomeLoc loc) { - return bounds.containsP(loc); - } - - /** Ensures that specified location is within the bounds of the reference window loaded into this - * LocusReferenceView object. If the location loc is within the current bounds (or if it is null), then nothing is done. - * Otherwise, the bounds are expanded on either side, as needed, to accomodate the location, and the reference seuqence for the - * new bounds is reloaded (can be costly!). If loc spans beyond the current contig, the expansion is performed - * to the start/stop of that contig only. - * @param loc - */ - public void expandBoundsToAccomodateLoc(GenomeLoc loc) { - if ( bounds==null || loc==null) return; // can bounds be null actually??? - if ( isLocationWithinBounds(loc) ) return; - if ( loc.getContigIndex() != bounds.getContigIndex() ) - throw new ReviewedStingException("Illegal attempt to expand reference view bounds to accommodate location on a different contig."); - - bounds = genomeLocParser.createGenomeLoc(bounds.getContig(), - Math.min(bounds.getStart(),loc.getStart()), - Math.max(bounds.getStop(),loc.getStop())); - int expandedStart = getWindowStart( bounds ); - int expandedStop = getWindowStop( bounds ); - initializeReferenceSequence(genomeLocParser.createGenomeLoc(bounds.getContig(), expandedStart, expandedStop)); - } - /** * Initialize the bounds of this shard, trimming the bounds so that they match the reference. * @param provider Provider covering the appropriate locus. @@ -210,7 +182,8 @@ public class LocusReferenceView extends ReferenceView { public ReferenceContext getReferenceContext( GenomeLoc genomeLoc ) { //validateLocation( genomeLoc ); - GenomeLoc window = genomeLocParser.createGenomeLoc( genomeLoc.getContig(), getWindowStart(genomeLoc), getWindowStop(genomeLoc) ); + GenomeLoc window = genomeLocParser.createGenomeLoc( genomeLoc.getContig(), bounds.getContigIndex(), + getWindowStart(genomeLoc), getWindowStop(genomeLoc) ); int refStart = -1; if (bounds != null) { @@ -237,16 +210,6 @@ public class LocusReferenceView extends ReferenceView { return super.getReferenceBases(genomeLoc); } - /** - * Validates that the genomeLoc is one base wide and is in the reference sequence. - * @param genomeLoc location to verify. - */ - private void validateLocation( GenomeLoc genomeLoc ) throws InvalidPositionException { - if( bounds != null && !bounds.containsP(genomeLoc) ) - throw new InvalidPositionException( - String.format("Requested position %s not within interval %s", genomeLoc, bounds)); - } - /** * Gets the start of the expanded window, bounded if necessary by the contig. * @param locus The locus to expand. From 804caf7a45505f9be1c041dd42241ede1d7022c5 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 17:23:15 -0500 Subject: [PATCH 102/188] HaplotypeCaller Optimization: return a inactive (p = 0.0) activity if the context has no bases in the pileup -- Allows us to avoid doing a lot of misc. work to set up the genotype when we don't have any data to genotype. Valuable in the case where we are passing through large regions without any data --- .../sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index a3d764141..8b3eb9f1b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -398,7 +398,9 @@ public class HaplotypeCaller extends ActiveRegionWalker implem return new ActivityProfileState( ref.getLocus(), tracker.getValues(UG_engine.getUAC().alleles, ref.getLocus()).size() > 0 ? 1.0 : 0.0 ); } - if( context == null ) { return new ActivityProfileState(ref.getLocus(), 0.0); } + if( context == null || context.getBasePileup().isEmpty() ) + // if we don't have any data, just abort early + return new ActivityProfileState(ref.getLocus(), 0.0); final List noCall = new ArrayList(); // used to noCall all genotypes until the exact model is applied noCall.add(Allele.NO_CALL); From 0fb238b61e767fc32a93cc9f89ff67c86a279f86 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 25 Jan 2013 17:25:42 -0500 Subject: [PATCH 103/188] TraverseActiveRegions Optimizations and Bugfixes: make sure to record position of current locus to discharge active regions when there's no data -- Now records the position of the current locus, as well as that of the last read. Necessary when passing through regions with no reads. The previous version would keep accumulating empty active regions, and never discharge them until end of traversal (if there was no reads in the future) or until a read was finally found -- Protected a call to logger.debug with if ( logger.isDebugEnabled()) to avoid a lot of overhead in writing unseen debugger logging information --- .../traversals/TraverseActiveRegions.java | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index bff696f13..6933b45a7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -68,7 +68,6 @@ import java.util.*; */ public class TraverseActiveRegions extends TraversalEngine,LocusShardDataProvider> { protected final static Logger logger = Logger.getLogger(TraversalEngine.class); - protected final static boolean DEBUG = false; protected final static boolean LOG_READ_CARRYING = false; // set by the tranversal @@ -221,12 +220,13 @@ public class TraverseActiveRegions extends TraversalEngine reads = locusView.getLIBS().transferReadsFromAllPreviousPileups(); for( final GATKSAMRecord read : reads ) { if ( ! appearedInLastShard(locOfLastReadAtTraversalStart, read) ) { - if ( DEBUG ) logger.warn("Adding read " + read.getReadName() + " at " + engine.getGenomeLocParser().createGenomeLoc(read) + " from provider " + dataProvider); rememberLastReadLocation(read); myReads.add(read); } @@ -295,6 +295,26 @@ public class TraverseActiveRegions extends TraversalEngine extends TraversalEngine extends TraversalEngine extends TraversalEngine> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); + if ( logger.isDebugEnabled() ) { + logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); + } if ( LOG_READ_CARRYING ) logger.info(String.format("Processing region %20s span=%3d active?=%5b with %4d reads. Overall max reads carried is %s", From 72b2e77eed3295b8ef09b512a464bf2d2e6cafc4 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 26 Jan 2013 15:23:40 -0500 Subject: [PATCH 104/188] Linearize the findEndOfRegion algorithm in ActivityProfile, radically improving its performance -- Previous algorithm was O(N^2) -- #resolve GSA-723 https://jira.broadinstitute.org/browse/GSA-723 --- .../utils/activeregion/ActivityProfile.java | 99 +++++++++++++++---- 1 file changed, 79 insertions(+), 20 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 15aca4162..14a8e6dcb 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -49,6 +49,14 @@ public class ActivityProfile { protected GenomeLoc regionStartLoc = null; protected GenomeLoc regionStopLoc = null; + /** + * Optimization variable. Keeps track of the right-most state we looked at in our + * last unsuccessful call to findEndOfRegion. This variable allows us to + * avoid an O(N^2) algorithm to find the end of the current region in the profile. It + * must be reset to 0 when a region is popped off the stack. + */ + int startSearchForEndOfRegionHere = 0; + /** * A cached value of the regionStartLoc contig length, to make calls to * getCurrentContigLength efficient @@ -77,10 +85,10 @@ public class ActivityProfile { /** * How far away can probability mass be moved around in this profile? * - * This distance puts an upper limit on how far, in bp, we will ever propogate probability max around + * This distance puts an upper limit on how far, in bp, we will ever propagate probability max around * when adding a new ActivityProfileState. For example, if the value of this function is * 10, and you are looking at a state at bp 5, and we know that no states beyond 5 + 10 will have - * their probability propograted back to that state. + * their probability propagated back to that state. * * @return a positive integer distance in bp */ @@ -344,6 +352,9 @@ public class ActivityProfile { // couldn't find a valid ending offset, so we return null return null; + // reset the start site of findEndOfRegion to the first element + startSearchForEndOfRegionHere = 0; + // we need to create the active region, and clip out the states we're extracting from this profile final List sub = stateList.subList(0, offsetOfNextRegionEnd + 1); final List supportingStates = new ArrayList(sub); @@ -384,8 +395,72 @@ public class ActivityProfile { "result == -1 || result < maxRegionSize", "! (result == -1 && forceConversion)"}) private int findEndOfRegion(final boolean isActiveRegion, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) { + int endOfActiveRegion = findFirstActivityBoundary(isActiveRegion, maxRegionSize, startSearchForEndOfRegionHere); + startSearchForEndOfRegionHere = Math.max(endOfActiveRegion - getMaxProbPropagationDistance(), 0); + + if ( isActiveRegion && endOfActiveRegion == maxRegionSize ) + // we've run to the end of the region, let's find a good place to cut + endOfActiveRegion = findBestCutSite(endOfActiveRegion, minRegionSize); + + // we're one past the end, so i must be decremented + return forceConversion || endOfActiveRegion + getMaxProbPropagationDistance() < stateList.size() + ? endOfActiveRegion - 1 + : -1; + } + + /** + * Find the the local minimum within 0 - endOfActiveRegion where we should divide region + * + * This algorithm finds the global minimum probability state within the region [minRegionSize, endOfActiveRegion) + * (exclusive of endOfActiveRegion), and returns the state index of that state. + * that it + * + * @param endOfActiveRegion the last state of the current active region (exclusive) + * @param minRegionSize the minimum of the left-most region, after cutting + * @return the index of state after the cut site (just like endOfActiveRegion) + */ + @Requires({"endOfActiveRegion >= minRegionSize", "minRegionSize >= 0"}) + @Ensures({"result >= minRegionSize", "result <= endOfActiveRegion"}) + private int findBestCutSite(final int endOfActiveRegion, final int minRegionSize) { + int minI = endOfActiveRegion - 1; + double minP = Double.MAX_VALUE; + + for ( int i = minI; i >= minRegionSize - 1; i-- ) { + double cur = getProb(i); + if ( cur < minP && isMinimum(i) ) { + minP = cur; + minI = i; + } + } + + return minI + 1; + } + + /** + * Find the first index into the state list where the state is considered ! isActiveRegion + * + * Note that each state has a probability of being active, and this function thresholds that + * value on ACTIVE_PROB_THRESHOLD, coloring each state as active or inactive. Finds the + * largest contiguous stretch of states starting at startSearchAt with the same isActive + * state as isActiveRegion. If the entire state list has the same isActive value, then returns + * maxRegionSize + * + * @param isActiveRegion are we looking for a stretch of active states, or inactive ones? + * @param maxRegionSize don't look for a boundary that would yield a region of size > maxRegionSize + * @param startSearchAt start looking not at 0 but rather at this offset into the state list. This + * parameter allows us to remember where we looked before across calls, so that + * we don't keep searching from 0 -> 1, then 0 -> 2, then 0 -> 3 on each subsequent + * call to this function. Use with caution, as an incorrect value could result in + * skipping a true boundary + * @return the index of the first state in the state list with isActive value != isActiveRegion, or maxRegionSize + * if no such element exists + */ + @Requires({"maxRegionSize > 0", "startSearchAt >= 0", "startSearchAt <= maxRegionSize", "startSearchAt <= stateList.size()"}) + @Ensures({"result >= 0", "result <= stateList.size()"}) + private int findFirstActivityBoundary(final boolean isActiveRegion, final int maxRegionSize, final int startSearchAt) { final int nStates = stateList.size(); - int endOfActiveRegion = 0; + int endOfActiveRegion = startSearchAt; + while ( endOfActiveRegion < nStates && endOfActiveRegion < maxRegionSize ) { if ( getProb(endOfActiveRegion) > ACTIVE_PROB_THRESHOLD != isActiveRegion ) { break; @@ -393,23 +468,7 @@ public class ActivityProfile { endOfActiveRegion++; } - if ( isActiveRegion && endOfActiveRegion == maxRegionSize ) { - // we've run to the end of the region, let's find a good place to cut - int minI = endOfActiveRegion - 1; - double minP = Double.MAX_VALUE; - for ( int i = minI; i >= minRegionSize - 1; i-- ) { - double cur = getProb(i); - if ( cur < minP && isMinimum(i) ) { - minP = cur; - minI = i; - } - } - - endOfActiveRegion = minI + 1; - } - - // we're one past the end, so i must be decremented - return forceConversion || endOfActiveRegion + getMaxProbPropagationDistance() < stateList.size() ? endOfActiveRegion - 1 : -1; + return endOfActiveRegion; } /** From c97a361b5d3d3d3d213c9081e84d96778e046cf0 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 27 Jan 2013 13:39:35 -0500 Subject: [PATCH 105/188] Added realistic BandPassFilterUnitTest that ensures quality results for 1000G phase I VCF and NA12878 VCF -- Helped ID more bugs in the ActivityProfile, necessitating a new algorithm for popping off active regions. This new algorithm requires that at least maxRegionSize + prob. propagation distance states have been examined. This ensures that the incremental results are the same as you get reading in an entire profile and running getRegions on the full profile -- TODO is to remove incremental search start algorithm, as this is no longer necessary, and nicely eliminates a state variable I was always uncomfortable with --- .../utils/activeregion/ActivityProfile.java | 11 +- .../activeregion/ActivityProfileState.java | 2 + .../activeregion/BandPassActivityProfile.java | 8 ++ .../BandPassActivityProfileUnitTest.java | 110 +++++++++++++++++- .../VariantContextTestProvider.java | 4 +- 5 files changed, 126 insertions(+), 9 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index 14a8e6dcb..ae181463b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -395,6 +395,13 @@ public class ActivityProfile { "result == -1 || result < maxRegionSize", "! (result == -1 && forceConversion)"}) private int findEndOfRegion(final boolean isActiveRegion, final int minRegionSize, final int maxRegionSize, final boolean forceConversion) { + if ( ! forceConversion && stateList.size() < maxRegionSize + getMaxProbPropagationDistance() ) { + // we really haven't finalized at the probability mass that might affect our decision, so keep + // waiting until we do before we try to make any decisions + return -1; + } + + // TODO -- don't need startSearchForEndOfRegionHere with the above check int endOfActiveRegion = findFirstActivityBoundary(isActiveRegion, maxRegionSize, startSearchForEndOfRegionHere); startSearchForEndOfRegionHere = Math.max(endOfActiveRegion - getMaxProbPropagationDistance(), 0); @@ -403,9 +410,7 @@ public class ActivityProfile { endOfActiveRegion = findBestCutSite(endOfActiveRegion, minRegionSize); // we're one past the end, so i must be decremented - return forceConversion || endOfActiveRegion + getMaxProbPropagationDistance() < stateList.size() - ? endOfActiveRegion - 1 - : -1; + return endOfActiveRegion - 1; } /** diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java index 5bba7db17..309405be0 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfileState.java @@ -72,6 +72,8 @@ public class ActivityProfileState { // make sure the location of that activity profile is 1 if ( loc.size() != 1 ) throw new IllegalArgumentException("Location for an ActivityProfileState must have to size 1 bp but saw " + loc); + if ( resultValue != null && resultValue.doubleValue() < 0 ) + throw new IllegalArgumentException("Result value isn't null and its < 0, which is illegal: " + resultValue); this.loc = loc; this.isActiveProb = isActiveProb; diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java index a1f1fc580..abbc74df4 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfile.java @@ -52,6 +52,14 @@ public class BandPassActivityProfile extends ActivityProfile { private final double sigma; private final double[] GaussianKernel; + /** + * Create a new BandPassActivityProfile with default sigma and file sizes + * @param parser our genome loc parser + */ + public BandPassActivityProfile(final GenomeLocParser parser) { + this(parser, MAX_FILTER_SIZE, DEFAULT_SIGMA, true); + } + /** * Create an activity profile that implements a band pass filter on the states * @param parser our genome loc parser diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index 540e9470a..2c7d78169 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -35,7 +35,12 @@ import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.variant.variantcontext.VariantContext; +import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; +import org.broadinstitute.variant.vcf.VCFCodec; +import org.broadinstitute.variant.vcf.VCFHeader; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -47,12 +52,13 @@ import java.util.*; public class BandPassActivityProfileUnitTest extends BaseTest { + private final static boolean DEBUG = false; private GenomeLocParser genomeLocParser; @BeforeClass public void init() throws FileNotFoundException { // sequence - ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(hg18Reference)); + ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); genomeLocParser = new GenomeLocParser(seq); } @@ -79,7 +85,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { return tests.toArray(new Object[][]{}); } - @Test(dataProvider = "BandPassBasicTest") + @Test(enabled = ! DEBUG, dataProvider = "BandPassBasicTest") public void testBandPass(final int start, final boolean precedingIsActive, final int nPrecedingSites, final int bandPassSize, final double sigma) { final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, sigma, false); @@ -133,7 +139,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { return tests.toArray(new Object[][]{}); } - @Test( dataProvider = "BandPassComposition") + @Test( enabled = ! DEBUG, dataProvider = "BandPassComposition") public void testBandPassComposition(final int bandPassSize, final int integrationLength) { final int start = 1; final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, bandPassSize, BandPassActivityProfile.DEFAULT_SIGMA); @@ -207,7 +213,7 @@ public class BandPassActivityProfileUnitTest extends BaseTest { return tests.toArray(new Object[][]{}); } - @Test( dataProvider = "KernelCreation") + @Test( enabled = ! DEBUG, dataProvider = "KernelCreation") public void testKernelCreation(final double sigma, final int maxSize, final double[] expectedKernel) { final BandPassActivityProfile profile = new BandPassActivityProfile(genomeLocParser, maxSize, sigma, true); @@ -216,4 +222,100 @@ public class BandPassActivityProfileUnitTest extends BaseTest { for ( int i = 0; i < kernel.length; i++ ) Assert.assertEquals(kernel[i], expectedKernel[i], 1e-3, "Kernels not equal at " + i); } + + // ------------------------------------------------------------------------------------ + // + // Large-scale test, reading in 1000G Phase I chr20 calls and making sure that + // the regions returned are the same if you run on the entire profile vs. doing it + // incremental + // + // ------------------------------------------------------------------------------------ + + @DataProvider(name = "VCFProfile") + public Object[][] makeVCFProfile() { + final List tests = new LinkedList(); + + //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 61000}); + //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 100000}); + //tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 1000000}); + tests.add(new Object[]{ privateTestDir + "ALL.chr20.phase1_release_v3.20101123.snps_indels_svs.sites.vcf", "20", 60470, 1000000}); + tests.add(new Object[]{ privateTestDir + "NA12878.WGS.b37.chr20.firstMB.vcf", "20", 1, 1000000}); + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "VCFProfile") + public void testVCFProfile(final String path, final String contig, final int start, final int end) throws Exception { + final int extension = 50; + final int minRegionSize = 50; + final int maxRegionSize = 300; + + final File file = new File(path); + final VCFCodec codec = new VCFCodec(); + final Pair> reader = VariantContextTestProvider.readAllVCs(file, codec); + + final List incRegions = new ArrayList(); + final BandPassActivityProfile incProfile = new BandPassActivityProfile(genomeLocParser); + final BandPassActivityProfile fullProfile = new BandPassActivityProfile(genomeLocParser); + int pos = start; + for ( final VariantContext vc : reader.getSecond() ) { + if ( vc == null ) continue; + while ( pos < vc.getStart() ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos); + //logger.warn("Adding 0.0 at " + loc + " because vc.getStart is " + vc.getStart()); + incProfile.add(new ActivityProfileState(loc, 0.0)); + fullProfile.add(new ActivityProfileState(loc, 0.0)); + pos++; + } + if ( vc.getStart() >= start && vc.getEnd() <= end ) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos); + //logger.warn("Adding 1.0 at " + loc); + ActivityProfileState.Type type = ActivityProfileState.Type.NONE; + Number value = null; + if ( vc.isBiallelic() && vc.isIndel() ) { + type = ActivityProfileState.Type.HIGH_QUALITY_SOFT_CLIPS; + value = Math.abs(vc.getIndelLengths().get(0)); + } + final ActivityProfileState state = new ActivityProfileState(loc, 1.0, type, value); + incProfile.add(state); + fullProfile.add(state); + pos++; + } + + incRegions.addAll(incProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, false)); + + if ( vc.getStart() > end ) + break; + } + + incRegions.addAll(incProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, true)); + + final List fullRegions = fullProfile.popReadyActiveRegions(extension, minRegionSize, maxRegionSize, true); + assertGoodRegions(fullRegions, start, end, maxRegionSize); + assertGoodRegions(incRegions, start, end, maxRegionSize); + + Assert.assertEquals(incRegions.size(), fullRegions.size(), "incremental and full region sizes aren't the same"); + for ( int i = 0; i < fullRegions.size(); i++ ) { + final ActiveRegion incRegion = incRegions.get(i); + final ActiveRegion fullRegion = fullRegions.get(i); + Assert.assertTrue(incRegion.equalExceptReads(fullRegion), "Full and incremental regions are not equal: full = " + fullRegion + " inc = " + incRegion); + } + } + + private void assertGoodRegions(final List regions, final int start, final int end, final int maxRegionSize) { + int lastPosSeen = start - 1; + for ( int regionI = 0; regionI < regions.size(); regionI++ ) { + final ActiveRegion region = regions.get(regionI); + Assert.assertEquals(region.getLocation().getStart(), lastPosSeen + 1, "discontinuous with previous region. lastPosSeen " + lastPosSeen + " but region is " + region); + Assert.assertTrue(region.getLocation().size() <= maxRegionSize, "Region is too big: " + region); + lastPosSeen = region.getLocation().getStop(); + + for ( final ActivityProfileState state : region.getSupportingStates() ) { + Assert.assertEquals(state.isActiveProb > ActivityProfile.ACTIVE_PROB_THRESHOLD, region.isActive, + "Region is active=" + region.isActive + " but contains a state " + state + " with prob " + + state.isActiveProb + " not within expected values given threshold for activity of " + + ActivityProfile.ACTIVE_PROB_THRESHOLD); + } + } + } } diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java index 0a2dc384e..f489806f6 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java @@ -688,7 +688,7 @@ public class VariantContextTestProvider { * @return * @throws IOException */ - private final static Pair> readAllVCs( final File source, final FeatureCodec codec ) throws IOException { + public final static Pair> readAllVCs( final File source, final FeatureCodec codec ) throws IOException { // read in the features PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); FeatureCodecHeader header = codec.readHeader(pbs); @@ -701,7 +701,7 @@ public class VariantContextTestProvider { return new Pair>(vcfHeader, new VCIterable(pbs, codec, vcfHeader)); } - private static class VCIterable implements Iterable, Iterator { + public static class VCIterable implements Iterable, Iterator { final PositionalBufferedStream pbs; final FeatureCodec codec; final VCFHeader header; From 14d8afe413e608c83f194ad40d00b2e3399de699 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 27 Jan 2013 13:51:53 -0500 Subject: [PATCH 106/188] Remove startSearchAt state variable from ActivityProfile -- New algorithm will only try to create an active region if there's at least maxREgionSize + propagation distance states in the list. When that's true, we are guaranteed to actually find a region. So this algorithm is not only truly correct but as super fast, as we only ever do the search for the end of the region when we will certainly find one, and actually generate a region. --- .../utils/activeregion/ActiveRegion.java | 1 - .../utils/activeregion/ActivityProfile.java | 28 ++++--------------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java index 575e94b99..194f61933 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java @@ -125,7 +125,6 @@ public class ActiveRegion implements HasGenomeLocation { public int getExtension() { return extension; } public int size() { return reads.size(); } public void clearReads() { reads.clear(); } - public void remove( final GATKSAMRecord read ) { reads.remove( read ); } public void removeAll( final ArrayList readsToRemove ) { reads.removeAll( readsToRemove ); } public boolean equalExceptReads(final ActiveRegion other) { diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java index ae181463b..ff4673717 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActivityProfile.java @@ -49,14 +49,6 @@ public class ActivityProfile { protected GenomeLoc regionStartLoc = null; protected GenomeLoc regionStopLoc = null; - /** - * Optimization variable. Keeps track of the right-most state we looked at in our - * last unsuccessful call to findEndOfRegion. This variable allows us to - * avoid an O(N^2) algorithm to find the end of the current region in the profile. It - * must be reset to 0 when a region is popped off the stack. - */ - int startSearchForEndOfRegionHere = 0; - /** * A cached value of the regionStartLoc contig length, to make calls to * getCurrentContigLength efficient @@ -352,9 +344,6 @@ public class ActivityProfile { // couldn't find a valid ending offset, so we return null return null; - // reset the start site of findEndOfRegion to the first element - startSearchForEndOfRegionHere = 0; - // we need to create the active region, and clip out the states we're extracting from this profile final List sub = stateList.subList(0, offsetOfNextRegionEnd + 1); final List supportingStates = new ArrayList(sub); @@ -401,9 +390,7 @@ public class ActivityProfile { return -1; } - // TODO -- don't need startSearchForEndOfRegionHere with the above check - int endOfActiveRegion = findFirstActivityBoundary(isActiveRegion, maxRegionSize, startSearchForEndOfRegionHere); - startSearchForEndOfRegionHere = Math.max(endOfActiveRegion - getMaxProbPropagationDistance(), 0); + int endOfActiveRegion = findFirstActivityBoundary(isActiveRegion, maxRegionSize); if ( isActiveRegion && endOfActiveRegion == maxRegionSize ) // we've run to the end of the region, let's find a good place to cut @@ -446,25 +433,20 @@ public class ActivityProfile { * * Note that each state has a probability of being active, and this function thresholds that * value on ACTIVE_PROB_THRESHOLD, coloring each state as active or inactive. Finds the - * largest contiguous stretch of states starting at startSearchAt with the same isActive + * largest contiguous stretch of states starting at the first state (index 0) with the same isActive * state as isActiveRegion. If the entire state list has the same isActive value, then returns * maxRegionSize * * @param isActiveRegion are we looking for a stretch of active states, or inactive ones? * @param maxRegionSize don't look for a boundary that would yield a region of size > maxRegionSize - * @param startSearchAt start looking not at 0 but rather at this offset into the state list. This - * parameter allows us to remember where we looked before across calls, so that - * we don't keep searching from 0 -> 1, then 0 -> 2, then 0 -> 3 on each subsequent - * call to this function. Use with caution, as an incorrect value could result in - * skipping a true boundary * @return the index of the first state in the state list with isActive value != isActiveRegion, or maxRegionSize * if no such element exists */ - @Requires({"maxRegionSize > 0", "startSearchAt >= 0", "startSearchAt <= maxRegionSize", "startSearchAt <= stateList.size()"}) + @Requires({"maxRegionSize > 0"}) @Ensures({"result >= 0", "result <= stateList.size()"}) - private int findFirstActivityBoundary(final boolean isActiveRegion, final int maxRegionSize, final int startSearchAt) { + private int findFirstActivityBoundary(final boolean isActiveRegion, final int maxRegionSize) { final int nStates = stateList.size(); - int endOfActiveRegion = startSearchAt; + int endOfActiveRegion = 0; while ( endOfActiveRegion < nStates && endOfActiveRegion < maxRegionSize ) { if ( getProb(endOfActiveRegion) > ACTIVE_PROB_THRESHOLD != isActiveRegion ) { From 63913d516f35be9cfecce9dd8b8fdc8b5137c592 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sun, 27 Jan 2013 16:52:45 -0500 Subject: [PATCH 108/188] Add join call to Progress meter unit test so we actually know the daemon thread has finished --- .../utils/progressmeter/ProgressMeterDaemonUnitTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/java/test/org/broadinstitute/sting/utils/progressmeter/ProgressMeterDaemonUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/progressmeter/ProgressMeterDaemonUnitTest.java index 4de24bc15..c33c1976b 100644 --- a/public/java/test/org/broadinstitute/sting/utils/progressmeter/ProgressMeterDaemonUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/progressmeter/ProgressMeterDaemonUnitTest.java @@ -84,7 +84,7 @@ public class ProgressMeterDaemonUnitTest extends BaseTest { } @Test(dataProvider = "PollingData", invocationCount = 10, successPercentage = 90) - public void testMe(final long poll, final int ticks) throws InterruptedException { + public void testProgressMeterDaemon(final long poll, final int ticks) throws InterruptedException { final TestingProgressMeter meter = new TestingProgressMeter(poll); final ProgressMeterDaemon daemon = meter.getProgressMeterDaemon(); Assert.assertTrue(daemon.isDaemon()); @@ -96,6 +96,9 @@ public class ProgressMeterDaemonUnitTest extends BaseTest { daemon.done(); Assert.assertTrue(daemon.isDone()); + // wait for the thread to actually finish + daemon.join(); + Assert.assertTrue(meter.progressCalls.size() >= 1, "Expected at least one progress update call from daemon thread, but only got " + meter.progressCalls.size() + " with exact calls " + meter.progressCalls); From 1aee8f205e83bd30f4bee1a2201924a11dcc24f5 Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Sun, 27 Jan 2013 16:48:44 -0500 Subject: [PATCH 109/188] Tool to calculate per base coverage distribution GSATDG-29 #resolve --- .../targets/BaseCoverageDistribution.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java new file mode 100644 index 000000000..a12008eb4 --- /dev/null +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java @@ -0,0 +1,101 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.diagnostics.targets; + +import org.broadinstitute.sting.commandline.Output; +import org.broadinstitute.sting.gatk.contexts.AlignmentContext; +import org.broadinstitute.sting.gatk.contexts.ReferenceContext; +import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; +import org.broadinstitute.sting.gatk.report.GATKReport; +import org.broadinstitute.sting.gatk.walkers.LocusWalker; + +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; + +/** + * User: carneiro + * Date: 1/27/13 + * Time: 11:16 AM + */ +public class BaseCoverageDistribution extends LocusWalker> { + @Output(required = true) + private PrintStream out; + + @Override + public boolean includeReadsWithDeletionAtLoci() { + return true; + } + + @Override + public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + return context.getBasePileup().getReads().size(); // I want the reads instead of the base pileup because I want to count deletions. + } + + @Override + public Map reduceInit() { + return new HashMap(10000); + } + + @Override + public Map reduce(Integer value, Map sum) { + Long curr = sum.get(value); + if (curr == null) + curr = 0L; + sum.put(value, curr + 1); + return sum; + } + + @Override + public void onTraversalDone(Map result) { + GATKReport report = GATKReport.newSimpleReport("BaseCoverageDistribution", "Coverage", "Count"); + for (Map.Entry entry : result.entrySet()) { + report.addRow(entry.getKey(), entry.getValue()); + } + report.print(out); + } +} From 3744d1a5961ab117b2f67b6cc7c4f7bd2184591a Mon Sep 17 00:00:00 2001 From: David Roazen Date: Mon, 28 Jan 2013 01:19:44 -0500 Subject: [PATCH 111/188] Collapse the downsampling fork in the GATK engine With LegacyLocusIteratorByState deleted, the legacy downsampling implementation was already non-functional. This commit removes all remaining code in the engine belonging to the legacy implementation. --- .../sting/gatk/GenomeAnalysisEngine.java | 18 +- .../sting/gatk/WalkerManager.java | 10 +- .../arguments/GATKArgumentCollection.java | 6 +- .../gatk/datasources/providers/LocusView.java | 8 - .../gatk/datasources/reads/BAMScheduler.java | 9 +- .../reads/LegacyReadShardBalancer.java | 130 ------------ .../gatk/datasources/reads/SAMDataSource.java | 128 ++---------- .../gatk/downsampling/DownsamplingMethod.java | 73 +++---- .../sting/gatk/executive/WindowMaker.java | 3 - .../iterators/LegacyDownsampleIterator.java | 77 ------- .../utils/LegacyReservoirDownsampler.java | 153 -------------- .../reads/DownsamplerBenchmark.java | 2 +- .../reads/ReadShardBalancerUnitTest.java | 28 +-- .../traversals/TraverseReadsUnitTest.java | 7 +- .../LegacyReservoirDownsamplerUnitTest.java | 191 ------------------ .../LocusIteratorByStateUnitTest.java | 8 +- 16 files changed, 78 insertions(+), 773 deletions(-) delete mode 100644 public/java/src/org/broadinstitute/sting/gatk/datasources/reads/LegacyReadShardBalancer.java delete mode 100644 public/java/src/org/broadinstitute/sting/gatk/iterators/LegacyDownsampleIterator.java delete mode 100644 public/java/src/org/broadinstitute/sting/utils/LegacyReservoirDownsampler.java delete mode 100644 public/java/test/org/broadinstitute/sting/utils/LegacyReservoirDownsamplerUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index 9b801be7d..389b1371a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -434,12 +434,9 @@ public class GenomeAnalysisEngine { protected DownsamplingMethod getDownsamplingMethod() { GATKArgumentCollection argCollection = this.getArguments(); - // Legacy downsampler can only be selected via the command line, not via walker annotations - boolean useLegacyDownsampler = argCollection.useLegacyDownsampler; - DownsamplingMethod commandLineMethod = argCollection.getDownsamplingMethod(); - DownsamplingMethod walkerMethod = WalkerManager.getDownsamplingMethod(walker, useLegacyDownsampler); - DownsamplingMethod defaultMethod = DownsamplingMethod.getDefaultDownsamplingMethod(walker, useLegacyDownsampler); + DownsamplingMethod walkerMethod = WalkerManager.getDownsamplingMethod(walker); + DownsamplingMethod defaultMethod = DownsamplingMethod.getDefaultDownsamplingMethod(walker); DownsamplingMethod method = commandLineMethod != null ? commandLineMethod : (walkerMethod != null ? walkerMethod : defaultMethod); method.checkCompatibilityWithWalker(walker); @@ -572,15 +569,10 @@ public class GenomeAnalysisEngine { throw new UserException.CommandLineException("Pairs traversal cannot be used in conjunction with intervals."); } - // Use the legacy ReadShardBalancer if legacy downsampling is enabled - ShardBalancer readShardBalancer = downsamplingMethod != null && downsamplingMethod.useLegacyDownsampler ? - new LegacyReadShardBalancer() : - new ReadShardBalancer(); - if(intervals == null) - return readsDataSource.createShardIteratorOverAllReads(readShardBalancer); + return readsDataSource.createShardIteratorOverAllReads(new ReadShardBalancer()); else - return readsDataSource.createShardIteratorOverIntervals(intervals, readShardBalancer); + return readsDataSource.createShardIteratorOverIntervals(intervals, new ReadShardBalancer()); } else throw new ReviewedStingException("Unable to determine walker type for walker " + walker.getClass().getName()); @@ -793,7 +785,7 @@ public class GenomeAnalysisEngine { DownsamplingMethod downsamplingMethod = getDownsamplingMethod(); // Synchronize the method back into the collection so that it shows up when - // interrogating for the downsample method during command line recreation. + // interrogating for the downsampling method during command line recreation. setDownsamplingMethod(downsamplingMethod); logger.info(downsamplingMethod); diff --git a/public/java/src/org/broadinstitute/sting/gatk/WalkerManager.java b/public/java/src/org/broadinstitute/sting/gatk/WalkerManager.java index 62c2cdd13..6dfb2c2a5 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/WalkerManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/WalkerManager.java @@ -306,11 +306,10 @@ public class WalkerManager extends PluginManager { * downsampling method is specified on the command-line, the command-line version will * be used instead. * @param walker The walker to interrogate. - * @param useLegacyDownsampler If true, use the legacy downsampling implementation * @return The downsampling method, as specified by the walker. Null if none exists. */ - public static DownsamplingMethod getDownsamplingMethod(Walker walker, boolean useLegacyDownsampler) { - return getDownsamplingMethod(walker.getClass(), useLegacyDownsampler); + public static DownsamplingMethod getDownsamplingMethod( Walker walker ) { + return getDownsamplingMethod(walker.getClass()); } /** @@ -318,10 +317,9 @@ public class WalkerManager extends PluginManager { * downsampling method is specified on the command-line, the command-line version will * be used instead. * @param walkerClass The class of the walker to interrogate. - * @param useLegacyDownsampler If true, use the legacy downsampling implementation * @return The downsampling method, as specified by the walker. Null if none exists. */ - public static DownsamplingMethod getDownsamplingMethod(Class walkerClass, boolean useLegacyDownsampler) { + public static DownsamplingMethod getDownsamplingMethod( Class walkerClass ) { DownsamplingMethod downsamplingMethod = null; if( walkerClass.isAnnotationPresent(Downsample.class) ) { @@ -329,7 +327,7 @@ public class WalkerManager extends PluginManager { DownsampleType type = downsampleParameters.by(); Integer toCoverage = downsampleParameters.toCoverage() >= 0 ? downsampleParameters.toCoverage() : null; Double toFraction = downsampleParameters.toFraction() >= 0.0d ? downsampleParameters.toFraction() : null; - downsamplingMethod = new DownsamplingMethod(type,toCoverage,toFraction,useLegacyDownsampler); + downsamplingMethod = new DownsamplingMethod(type, toCoverage, toFraction); } return downsamplingMethod; diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index 62ca38ad2..9cd88001c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -126,9 +126,6 @@ public class GATKArgumentCollection { @Argument(fullName = "downsample_to_coverage", shortName = "dcov", doc = "Coverage [integer] to downsample to at any given locus; note that downsampled reads are randomly selected from all possible reads at a locus. For non-locus-based traversals (eg., ReadWalkers), this sets the maximum number of reads at each alignment start position.", required = false) public Integer downsampleCoverage = null; - @Argument(fullName = "use_legacy_downsampler", shortName = "use_legacy_downsampler", doc = "Use the legacy downsampling implementation instead of the newer, less-tested implementation", required = false) - public boolean useLegacyDownsampler = false; - /** * Gets the downsampling method explicitly specified by the user. If the user didn't specify * a default downsampling mechanism, return the default. @@ -138,7 +135,7 @@ public class GATKArgumentCollection { if ( downsamplingType == null && downsampleFraction == null && downsampleCoverage == null ) return null; - return new DownsamplingMethod(downsamplingType, downsampleCoverage, downsampleFraction, useLegacyDownsampler); + return new DownsamplingMethod(downsamplingType, downsampleCoverage, downsampleFraction); } /** @@ -152,7 +149,6 @@ public class GATKArgumentCollection { downsamplingType = method.type; downsampleCoverage = method.toCoverage; downsampleFraction = method.toFraction; - useLegacyDownsampler = method.useLegacyDownsampler; } // -------------------------------------------------------------------------------------------------------------- diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java index 3ff6e34fb..6b3661baa 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/LocusView.java @@ -162,14 +162,6 @@ public abstract class LocusView extends LocusIterator implements View { // Cache the current and apply filtering. AlignmentContext current = nextLocus; - // The old ALL_READS downsampling implementation -- use only if legacy downsampling was requested: - if ( sourceInfo.getDownsamplingMethod().useLegacyDownsampler && - sourceInfo.getDownsamplingMethod().type == DownsampleType.ALL_READS && - sourceInfo.getDownsamplingMethod().toCoverage != null ) { - - current.downsampleToCoverage(sourceInfo.getDownsamplingMethod().toCoverage); - } - // Indicate that the next operation will need to advance. nextLocus = null; diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BAMScheduler.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BAMScheduler.java index 0b41f15c0..8d7cfbaa7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BAMScheduler.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BAMScheduler.java @@ -133,14 +133,7 @@ public class BAMScheduler implements Iterator { Map currentPosition; - // Only use the deprecated SAMDataSource.getCurrentPosition() if we're not using experimental downsampling - // TODO: clean this up once the experimental downsampling engine fork collapses - if ( dataSource.getReadsInfo().getDownsamplingMethod() != null && dataSource.getReadsInfo().getDownsamplingMethod().useLegacyDownsampler ) { - currentPosition = dataSource.getCurrentPosition(); - } - else { - currentPosition = dataSource.getInitialReaderPositions(); - } + currentPosition = dataSource.getInitialReaderPositions(); for(SAMReaderID reader: dataSource.getReaderIDs()) filePointer.addFileSpans(reader,createSpanToEndOfFile(currentPosition.get(reader).getGATKChunks().get(0).getChunkStart())); diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/LegacyReadShardBalancer.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/LegacyReadShardBalancer.java deleted file mode 100644 index 510398157..000000000 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/LegacyReadShardBalancer.java +++ /dev/null @@ -1,130 +0,0 @@ -/* -* 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.reads; - -import net.sf.samtools.GATKBAMFileSpan; -import net.sf.samtools.SAMFileSpan; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; - -/** - * Divide up large file pointers containing reads into more manageable subcomponents. - * - * TODO: delete this class once the experimental downsampling engine fork collapses - */ -public class LegacyReadShardBalancer extends ShardBalancer { - /** - * Convert iterators of file pointers into balanced iterators of shards. - * @return An iterator over balanced shards. - */ - public Iterator iterator() { - return new Iterator() { - /** - * The cached shard to be returned next. Prefetched in the peekable iterator style. - */ - private Shard nextShard = null; - - /** - * The file pointer currently being processed. - */ - private FilePointer currentFilePointer; - - /** - * Ending position of the last shard in the file. - */ - private Map position = readsDataSource.getCurrentPosition(); - - { - if(filePointers.hasNext()) - currentFilePointer = filePointers.next(); - advance(); - } - - public boolean hasNext() { - return nextShard != null; - } - - public Shard next() { - if(!hasNext()) - throw new NoSuchElementException("No next read shard available"); - Shard currentShard = nextShard; - advance(); - return currentShard; - } - - public void remove() { - throw new UnsupportedOperationException("Unable to remove from shard balancing iterator"); - } - - private void advance() { - Map shardPosition; - nextShard = null; - - Map selectedReaders = new HashMap(); - while(selectedReaders.size() == 0 && currentFilePointer != null) { - shardPosition = currentFilePointer.fileSpans; - - for(SAMReaderID id: shardPosition.keySet()) { - SAMFileSpan fileSpan = new GATKBAMFileSpan(shardPosition.get(id).removeContentsBefore(position.get(id))); - selectedReaders.put(id,fileSpan); - } - - if(!isEmpty(selectedReaders)) { - Shard shard = new ReadShard(parser,readsDataSource,selectedReaders,currentFilePointer.locations,currentFilePointer.isRegionUnmapped); - readsDataSource.fillShard(shard); - - if(!shard.isBufferEmpty()) { - nextShard = shard; - break; - } - } - - selectedReaders.clear(); - currentFilePointer = filePointers.hasNext() ? filePointers.next() : null; - } - - position = readsDataSource.getCurrentPosition(); - } - - /** - * Detects whether the list of file spans contain any read data. - * @param selectedSpans Mapping of readers to file spans. - * @return True if file spans are completely empty; false otherwise. - */ - private boolean isEmpty(Map selectedSpans) { - for(SAMFileSpan fileSpan: selectedSpans.values()) { - if(!fileSpan.isEmpty()) - return false; - } - return true; - } - }; - } - -} diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java index c9a3b0df0..d52e55d6d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java @@ -97,13 +97,6 @@ public class SAMDataSource { */ private final Map bamIndices = new HashMap(); - /** - * How far along is each reader? - * - * TODO: delete this once the experimental downsampling engine fork collapses - */ - private final Map readerPositions = new HashMap(); - /** * The merged header. */ @@ -298,8 +291,6 @@ public class SAMDataSource { this.sortOrder = sortOrder; } - initializeReaderPositions(readers); - mergedHeader = readers.getMergedHeader(); hasReadGroupCollisions = readers.hasReadGroupCollisions(); @@ -387,17 +378,6 @@ public class SAMDataSource { return resourcePool.getReaderID(read.getFileSource().getReader()); } - /** - * Retrieves the current position within the BAM file. - * @return A mapping of reader to current position. - * - * TODO: delete this once the experimental downsampling engine fork collapses - */ - @Deprecated - public Map getCurrentPosition() { - return readerPositions; - } - /** * Gets the merged header from the SAM file. * @return The merged header. @@ -475,67 +455,6 @@ public class SAMDataSource { } } - /** - * Legacy method to fill the given buffering shard with reads. - * - * Shard.fill() is used instead of this method unless legacy downsampling is enabled - * - * TODO: delete this method once the experimental downsampling engine fork collapses - * - * @param shard Shard to fill. - */ - @Deprecated - public void fillShard(Shard shard) { - if(!shard.buffersReads()) - throw new ReviewedStingException("Attempting to fill a non-buffering shard."); - - SAMReaders readers = resourcePool.getAvailableReaders(); - // Cache the most recently viewed read so that we can check whether we've reached the end of a pair. - SAMRecord read = null; - - Map positionUpdates = new IdentityHashMap(); - - CloseableIterator iterator = getIterator(readers,shard,sortOrder == SAMFileHeader.SortOrder.coordinate); - while(!shard.isBufferFull() && iterator.hasNext()) { - final SAMRecord nextRead = iterator.next(); - if ( read == null || (nextRead.getReferenceIndex().equals(read.getReferenceIndex())) ) { - // only add reads to the shard if they are on the same contig - read = nextRead; - shard.addRead(read); - noteFilePositionUpdate(positionUpdates,read); - } else { - break; - } - } - - // If the reads are sorted in queryname order, ensure that all reads - // having the same queryname become part of the same shard. - if(sortOrder == SAMFileHeader.SortOrder.queryname) { - while(iterator.hasNext()) { - SAMRecord nextRead = iterator.next(); - if(read == null || !read.getReadName().equals(nextRead.getReadName())) - break; - shard.addRead(nextRead); - noteFilePositionUpdate(positionUpdates,nextRead); - } - } - - iterator.close(); - - // Make the updates specified by the reader. - for(Map.Entry positionUpdate: positionUpdates.entrySet()) - readerPositions.put(readers.getReaderID(positionUpdate.getKey()),positionUpdate.getValue()); - } - - /* - * TODO: delete this method once the experimental downsampling engine fork collapses - */ - @Deprecated - private void noteFilePositionUpdate(Map positionMapping, SAMRecord read) { - GATKBAMFileSpan endChunk = new GATKBAMFileSpan(read.getFileSource().getFilePointer().getContentsFollowing()); - positionMapping.put(read.getFileSource().getReader(),endChunk); - } - public StingSAMIterator seek(Shard shard) { if(shard.buffersReads()) { return shard.iterator(); @@ -559,19 +478,6 @@ public class SAMDataSource { throw new ReviewedStingException("Unable to find id for reader associated with read " + read.getReadName()); } - /** - * Initialize the current reader positions - * - * TODO: delete this once the experimental downsampling engine fork collapses - * - * @param readers - */ - @Deprecated - private void initializeReaderPositions(SAMReaders readers) { - for(SAMReaderID id: getReaderIDs()) - readerPositions.put(id,new GATKBAMFileSpan(readers.getReader(id).getFilePointerSpanningReads())); - } - /** * Get the initial reader positions across all BAM files * @@ -646,7 +552,6 @@ public class SAMDataSource { enableVerification, readProperties.useOriginalBaseQualities(), new ReleasingIterator(readers,StingSAMIteratorAdapter.adapt(mergingIterator)), - readProperties.getDownsamplingMethod().toFraction, readProperties.getValidationExclusionList().contains(ValidationExclusion.TYPE.NO_READ_ORDER_VERIFICATION), readProperties.getSupplementalFilters(), readProperties.getReadTransformers(), @@ -704,7 +609,6 @@ public class SAMDataSource { * @param enableVerification Verify the order of reads. * @param useOriginalBaseQualities True if original base qualities should be used. * @param wrappedIterator the raw data source. - * @param downsamplingFraction whether and how much to downsample the reads themselves (not at a locus). * @param noValidationOfReadOrder Another trigger for the verifying iterator? TODO: look into this. * @param supplementalFilters additional filters to apply to the reads. * @param defaultBaseQualities if the reads have incomplete quality scores, set them all to defaultBaseQuality. @@ -715,7 +619,6 @@ public class SAMDataSource { boolean enableVerification, boolean useOriginalBaseQualities, StingSAMIterator wrappedIterator, - Double downsamplingFraction, Boolean noValidationOfReadOrder, Collection supplementalFilters, List readTransformers, @@ -727,30 +630,25 @@ public class SAMDataSource { // * (otherwise we will process something that we may end up throwing away) * // // ************************************************************************************************ // + // Filters: wrappedIterator = StingSAMIteratorAdapter.adapt(new CountingFilteringIterator(readMetrics,wrappedIterator,supplementalFilters)); - // If we're using the new downsampling implementation, apply downsampling iterators at this - // point in the read stream for most (but not all) cases - if ( ! readProperties.getDownsamplingMethod().useLegacyDownsampler ) { + // Downsampling: - // For locus traversals where we're downsampling to coverage by sample, assume that the downsamplers - // will be invoked downstream from us in LocusIteratorByState. This improves performance by avoiding - // splitting/re-assembly of the read stream at this stage, and also allows for partial downsampling - // of individual reads. - boolean assumeDownstreamLIBSDownsampling = isLocusBasedTraversal && - readProperties.getDownsamplingMethod().type == DownsampleType.BY_SAMPLE && - readProperties.getDownsamplingMethod().toCoverage != null; + // For locus traversals where we're downsampling to coverage by sample, assume that the downsamplers + // will be invoked downstream from us in LocusIteratorByState. This improves performance by avoiding + // splitting/re-assembly of the read stream at this stage, and also allows for partial downsampling + // of individual reads. + boolean assumeDownstreamLIBSDownsampling = isLocusBasedTraversal && + readProperties.getDownsamplingMethod().type == DownsampleType.BY_SAMPLE && + readProperties.getDownsamplingMethod().toCoverage != null; - if ( ! assumeDownstreamLIBSDownsampling ) { - wrappedIterator = applyDownsamplingIterator(wrappedIterator); - } + // Apply downsampling iterators here only in cases where we know that LocusIteratorByState won't be + // doing any downsampling downstream of us + if ( ! assumeDownstreamLIBSDownsampling ) { + wrappedIterator = applyDownsamplingIterator(wrappedIterator); } - // Use the old fractional downsampler only if we're using legacy downsampling: - // TODO: remove this statement (and associated classes) once the downsampling engine fork collapses - if ( readProperties.getDownsamplingMethod().useLegacyDownsampler && downsamplingFraction != null ) - wrappedIterator = new LegacyDownsampleIterator(wrappedIterator, downsamplingFraction); - // unless they've said not to validate read ordering (!noValidationOfReadOrder) and we've enabled verification, // verify the read ordering by applying a sort order iterator if (!noValidationOfReadOrder && enableVerification) diff --git a/public/java/src/org/broadinstitute/sting/gatk/downsampling/DownsamplingMethod.java b/public/java/src/org/broadinstitute/sting/gatk/downsampling/DownsamplingMethod.java index bc32f9188..5aa27608d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/downsampling/DownsamplingMethod.java +++ b/public/java/src/org/broadinstitute/sting/gatk/downsampling/DownsamplingMethod.java @@ -50,35 +50,43 @@ public class DownsamplingMethod { */ public final Double toFraction; - /** - * Use the legacy downsampling implementation instead of the newer implementation? - */ - public final boolean useLegacyDownsampler; - /** * Expresses no downsampling applied at all. */ - public static final DownsamplingMethod NONE = new DownsamplingMethod(DownsampleType.NONE,null,null,false); + public static final DownsamplingMethod NONE = new DownsamplingMethod(DownsampleType.NONE, null, null); /** * Default type to use if no type is specified */ - public static DownsampleType DEFAULT_DOWNSAMPLING_TYPE = DownsampleType.BY_SAMPLE; + public static final DownsampleType DEFAULT_DOWNSAMPLING_TYPE = DownsampleType.BY_SAMPLE; /** * Default target coverage for locus-based traversals */ - public static int DEFAULT_LOCUS_BASED_TRAVERSAL_DOWNSAMPLING_COVERAGE = 1000; + public static final int DEFAULT_LOCUS_TRAVERSAL_DOWNSAMPLING_COVERAGE = 1000; - public DownsamplingMethod( DownsampleType type, Integer toCoverage, Double toFraction, boolean useLegacyDownsampler ) { + /** + * Default downsampling method for locus-based traversals + */ + public static final DownsamplingMethod DEFAULT_LOCUS_TRAVERSAL_DOWNSAMPLING_METHOD = + new DownsamplingMethod(DEFAULT_DOWNSAMPLING_TYPE, DEFAULT_LOCUS_TRAVERSAL_DOWNSAMPLING_COVERAGE, null); + + /** + * Default downsampling method for read-based traversals + */ + public static final DownsamplingMethod DEFAULT_READ_TRAVERSAL_DOWNSAMPLING_METHOD = NONE; + + + public DownsamplingMethod( DownsampleType type, Integer toCoverage, Double toFraction ) { this.type = type != null ? type : DEFAULT_DOWNSAMPLING_TYPE; - this.toCoverage = toCoverage; - this.toFraction = toFraction; - this.useLegacyDownsampler = useLegacyDownsampler; if ( type == DownsampleType.NONE ) { - toCoverage = null; - toFraction = null; + this.toCoverage = null; + this.toFraction = null; + } + else { + this.toCoverage = toCoverage; + this.toFraction = toFraction; } validate(); @@ -87,34 +95,28 @@ public class DownsamplingMethod { private void validate() { // Can't leave toFraction and toCoverage null unless type is NONE if ( type != DownsampleType.NONE && toFraction == null && toCoverage == null ) - throw new UserException.CommandLineException("Must specify either toFraction or toCoverage when downsampling."); + throw new UserException("Must specify either toFraction or toCoverage when downsampling."); // Fraction and coverage cannot both be specified. if ( toFraction != null && toCoverage != null ) - throw new UserException.CommandLineException("Downsampling coverage and fraction are both specified. Please choose only one."); + throw new UserException("Downsampling coverage and fraction are both specified. Please choose only one."); // toCoverage must be > 0 when specified if ( toCoverage != null && toCoverage <= 0 ) { - throw new UserException.CommandLineException("toCoverage must be > 0 when downsampling to coverage"); + throw new UserException("toCoverage must be > 0 when downsampling to coverage"); } // toFraction must be >= 0.0 and <= 1.0 when specified if ( toFraction != null && (toFraction < 0.0 || toFraction > 1.0) ) { - throw new UserException.CommandLineException("toFraction must be >= 0.0 and <= 1.0 when downsampling to a fraction of reads"); + throw new UserException("toFraction must be >= 0.0 and <= 1.0 when downsampling to a fraction of reads"); } } public void checkCompatibilityWithWalker( Walker walker ) { boolean isLocusTraversal = walker instanceof LocusWalker || walker instanceof ActiveRegionWalker; - if ( ! isLocusTraversal && useLegacyDownsampler && toCoverage != null ) { - throw new UserException.CommandLineException("Downsampling to coverage for read-based traversals (eg., ReadWalkers) is not supported in the legacy downsampling implementation. " + - "The newer downsampling implementation does not have this limitation."); - } - - if ( isLocusTraversal && ! useLegacyDownsampler && type == DownsampleType.ALL_READS && toCoverage != null ) { - throw new UserException.CommandLineException("Downsampling to coverage with the ALL_READS method for locus-based traversals (eg., LocusWalkers) is not yet supported in the new downsampling implementation (though it is supported for ReadWalkers). " + - "You can run with --use_legacy_downsampler for a broken and poorly-maintained implementation of ALL_READS to-coverage downsampling, but this is not recommended."); + if ( isLocusTraversal && type == DownsampleType.ALL_READS && toCoverage != null ) { + throw new UserException("Downsampling to coverage with the ALL_READS method for locus-based traversals (eg., LocusWalkers) is not currently supported (though it is supported for ReadWalkers)."); } } @@ -128,31 +130,22 @@ public class DownsamplingMethod { builder.append(String.format("Method: %s, ", type)); if ( toCoverage != null ) { - builder.append(String.format("Target Coverage: %d, ", toCoverage)); + builder.append(String.format("Target Coverage: %d", toCoverage)); } else { - builder.append(String.format("Target Fraction: %.2f, ", toFraction)); - } - - if ( useLegacyDownsampler ) { - builder.append("Using the legacy downsampling implementation"); - } - else { - builder.append("Using the new downsampling implementation"); + builder.append(String.format("Target Fraction: %.2f", toFraction)); } } return builder.toString(); } - public static DownsamplingMethod getDefaultDownsamplingMethod( Walker walker, boolean useLegacyDownsampler ) { + public static DownsamplingMethod getDefaultDownsamplingMethod( Walker walker ) { if ( walker instanceof LocusWalker || walker instanceof ActiveRegionWalker ) { - return new DownsamplingMethod(DEFAULT_DOWNSAMPLING_TYPE, DEFAULT_LOCUS_BASED_TRAVERSAL_DOWNSAMPLING_COVERAGE, - null, useLegacyDownsampler); + return DEFAULT_LOCUS_TRAVERSAL_DOWNSAMPLING_METHOD; } else { - // Downsampling is off by default for non-locus-based traversals - return new DownsamplingMethod(DownsampleType.NONE, null, null, useLegacyDownsampler); + return DEFAULT_READ_TRAVERSAL_DOWNSAMPLING_METHOD; } } } diff --git a/public/java/src/org/broadinstitute/sting/gatk/executive/WindowMaker.java b/public/java/src/org/broadinstitute/sting/gatk/executive/WindowMaker.java index f587442d7..e9a2b56c2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/executive/WindowMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/executive/WindowMaker.java @@ -111,9 +111,6 @@ public class WindowMaker implements Iterable, I this.sourceInfo = shard.getReadProperties(); this.readIterator = new GATKSAMIterator(iterator); - // Use the legacy version of LocusIteratorByState if legacy downsampling was requested: - if ( sourceInfo.getDownsamplingMethod().useLegacyDownsampler ) - throw new IllegalArgumentException("legacy downsampler no longer supported in the window maker"); this.libs = new LocusIteratorByState(readIterator,sourceInfo,genomeLocParser,sampleNames); this.sourceIterator = new PeekableIterator(libs); diff --git a/public/java/src/org/broadinstitute/sting/gatk/iterators/LegacyDownsampleIterator.java b/public/java/src/org/broadinstitute/sting/gatk/iterators/LegacyDownsampleIterator.java deleted file mode 100644 index d0992149e..000000000 --- a/public/java/src/org/broadinstitute/sting/gatk/iterators/LegacyDownsampleIterator.java +++ /dev/null @@ -1,77 +0,0 @@ -/* -* 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.iterators; - -import net.sf.samtools.SAMRecord; -import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; - -import java.util.Iterator; - - -public class LegacyDownsampleIterator implements StingSAMIterator { - - StingSAMIterator it; - int cutoff; - SAMRecord next; - - public LegacyDownsampleIterator(StingSAMIterator it, double fraction) { - this.it = it; - cutoff = (int)(fraction * 10000); - next = getNextRecord(); - } - - public boolean hasNext() { - return next != null; - } - - public SAMRecord next() { - SAMRecord result = next; - next = getNextRecord(); - return result; - } - - public void remove() { - throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!"); - } - - private SAMRecord getNextRecord() { - while ( true ) { - if ( !it.hasNext() ) - return null; - SAMRecord rec = it.next(); - if ( GenomeAnalysisEngine.getRandomGenerator().nextInt(10000) < cutoff ) - return rec; - } - } - - public void close() { - it.close(); - } - - public Iterator iterator() { - return this; - } -} \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/utils/LegacyReservoirDownsampler.java b/public/java/src/org/broadinstitute/sting/utils/LegacyReservoirDownsampler.java deleted file mode 100644 index 2d590dd80..000000000 --- a/public/java/src/org/broadinstitute/sting/utils/LegacyReservoirDownsampler.java +++ /dev/null @@ -1,153 +0,0 @@ -/* -* 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.utils; - -import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -/** - * THIS IMPLEMENTATION IS BROKEN AND WILL BE REMOVED ONCE THE DOWNSAMPLING ENGINE FORK COLLAPSES - * - * Randomly downsample from a stream of elements. This algorithm is a direct, - * naive implementation of reservoir downsampling as described in "Random Downsampling - * with a Reservoir" (Vitter 1985). At time of writing, this paper is located here: - * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.138.784&rep=rep1&type=pdf - - * @author mhanna - * @version 0.1 - */ -public class LegacyReservoirDownsampler { - /** - * The reservoir of elements tracked by this downsampler. - */ - private final ArrayList reservoir; - - /** - * What is the maximum number of reads that can be returned in a single batch. - */ - private final int maxElements; - - /** - * Create a new downsampler with the given source iterator and given comparator. - * @param maxElements What is the maximum number of reads that can be returned in any call of this - */ - public LegacyReservoirDownsampler(final int maxElements) { - if(maxElements < 0) - throw new ReviewedStingException("Unable to work with an negative size collection of elements"); - this.reservoir = new ArrayList(maxElements); - this.maxElements = maxElements; - } - - /** - * Returns the eliminated element. - * @param element Eliminated element; null if no element has been eliminated. - * @return - */ - public T add(T element) { - if(maxElements <= 0) - return element; - else if(reservoir.size() < maxElements) { - reservoir.add(element); - return null; - } - else { - // Get a uniformly distributed int. If the chosen slot lives within the partition, replace the entry in that slot with the newest entry. - int slot = GenomeAnalysisEngine.getRandomGenerator().nextInt(maxElements); - if(slot >= 0 && slot < maxElements) { - T displaced = reservoir.get(slot); - reservoir.set(slot,element); - return displaced; - } - else - return element; - } - } - - public boolean addAll(Collection elements) { - boolean added = false; - for(T element: elements) - added |= (add(element) != null); - return added; - } - - /** - * Returns the contents of this reservoir, downsampled to the given value. Note that the return value - * @return The downsampled contents of this reservoir. - */ - public Collection getDownsampledContents() { - return reservoir; - } - - public void clear() { - reservoir.clear(); - } - - public boolean isEmpty() { - return reservoir.isEmpty(); - } - - public int size() { - return reservoir.size(); - } - - public Iterator iterator() { - return reservoir.iterator(); - } - - public boolean contains(Object o) { - return reservoir.contains(o); - } - - public boolean containsAll(Collection elements) { - return reservoir.containsAll(elements); - } - - public boolean retainAll(Collection elements) { - return reservoir.retainAll(elements); - } - - public boolean remove(Object o) { - return reservoir.remove(o); - } - - public boolean removeAll(Collection elements) { - return reservoir.removeAll(elements); - } - - public Object[] toArray() { - Object[] contents = new Object[reservoir.size()]; - reservoir.toArray(contents); - return contents; - } - - public T[] toArray(T[] array) { - return reservoir.toArray(array); - } -} diff --git a/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/DownsamplerBenchmark.java b/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/DownsamplerBenchmark.java index d960177d9..00389be97 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/DownsamplerBenchmark.java +++ b/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/DownsamplerBenchmark.java @@ -86,7 +86,7 @@ public class DownsamplerBenchmark extends ReadProcessingBenchmark { }, PER_SAMPLE { @Override - DownsamplingMethod create() { return DownsamplingMethod.getDefaultDownsamplingMethod(new CountLoci(), false); } + DownsamplingMethod create() { return DownsamplingMethod.getDefaultDownsamplingMethod(new CountLoci()); } }; abstract DownsamplingMethod create(); } diff --git a/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/ReadShardBalancerUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/ReadShardBalancerUnitTest.java index 049e8d6bb..40ec42ef1 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/ReadShardBalancerUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/datasources/reads/ReadShardBalancerUnitTest.java @@ -52,7 +52,7 @@ public class ReadShardBalancerUnitTest extends BaseTest { * Tests to ensure that ReadShardBalancer works as expected and does not place shard boundaries * at inappropriate places, such as within an alignment start position */ - private static class ExperimentalReadShardBalancerTest extends TestDataProvider { + private static class ReadShardBalancerTest extends TestDataProvider { private int numContigs; private int numStacksPerContig; private int stackSize; @@ -63,19 +63,19 @@ public class ReadShardBalancerUnitTest extends BaseTest { private SAMFileHeader header; private SAMReaderID testBAM; - public ExperimentalReadShardBalancerTest( int numContigs, - int numStacksPerContig, - int stackSize, - int numUnmappedReads, - int downsamplingTargetCoverage ) { - super(ExperimentalReadShardBalancerTest.class); + public ReadShardBalancerTest( int numContigs, + int numStacksPerContig, + int stackSize, + int numUnmappedReads, + int downsamplingTargetCoverage ) { + super(ReadShardBalancerTest.class); this.numContigs = numContigs; this.numStacksPerContig = numStacksPerContig; this.stackSize = stackSize; this.numUnmappedReads = numUnmappedReads; - this.downsamplingMethod = new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsamplingTargetCoverage, null, false); + this.downsamplingMethod = new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsamplingTargetCoverage, null); this.expectedReadCount = Math.min(stackSize, downsamplingTargetCoverage) * numStacksPerContig * numContigs + numUnmappedReads; setName(String.format("%s: numContigs=%d numStacksPerContig=%d stackSize=%d numUnmappedReads=%d downsamplingTargetCoverage=%d", @@ -176,8 +176,8 @@ public class ReadShardBalancerUnitTest extends BaseTest { } } - @DataProvider(name = "ExperimentalReadShardBalancerTestDataProvider") - public Object[][] createExperimentalReadShardBalancerTests() { + @DataProvider(name = "ReadShardBalancerTestDataProvider") + public Object[][] createReadShardBalancerTests() { for ( int numContigs = 1; numContigs <= 3; numContigs++ ) { for ( int numStacksPerContig : Arrays.asList(1, 2, 4) ) { // Use crucial read shard boundary values as the stack sizes @@ -185,18 +185,18 @@ public class ReadShardBalancerUnitTest extends BaseTest { for ( int numUnmappedReads : Arrays.asList(0, ReadShard.DEFAULT_MAX_READS / 2, ReadShard.DEFAULT_MAX_READS * 2) ) { // The first value will result in no downsampling at all, the others in some downsampling for ( int downsamplingTargetCoverage : Arrays.asList(ReadShard.DEFAULT_MAX_READS * 10, ReadShard.DEFAULT_MAX_READS, ReadShard.DEFAULT_MAX_READS / 2) ) { - new ExperimentalReadShardBalancerTest(numContigs, numStacksPerContig, stackSize, numUnmappedReads, downsamplingTargetCoverage); + new ReadShardBalancerTest(numContigs, numStacksPerContig, stackSize, numUnmappedReads, downsamplingTargetCoverage); } } } } } - return ExperimentalReadShardBalancerTest.getTests(ExperimentalReadShardBalancerTest.class); + return ReadShardBalancerTest.getTests(ReadShardBalancerTest.class); } - @Test(dataProvider = "ExperimentalReadShardBalancerTestDataProvider") - public void runExperimentalReadShardBalancerTest( ExperimentalReadShardBalancerTest test ) { + @Test(dataProvider = "ReadShardBalancerTestDataProvider") + public void runReadShardBalancerTest( ReadShardBalancerTest test ) { logger.warn("Running test: " + test); test.run(); diff --git a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseReadsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseReadsUnitTest.java index 4328e3047..8bc373fe8 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseReadsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/traversals/TraverseReadsUnitTest.java @@ -31,10 +31,7 @@ import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.commandline.Tags; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.datasources.providers.ReadShardDataProvider; -import org.broadinstitute.sting.gatk.datasources.reads.LegacyReadShardBalancer; -import org.broadinstitute.sting.gatk.datasources.reads.SAMDataSource; -import org.broadinstitute.sting.gatk.datasources.reads.SAMReaderID; -import org.broadinstitute.sting.gatk.datasources.reads.Shard; +import org.broadinstitute.sting.gatk.datasources.reads.*; import org.broadinstitute.sting.gatk.resourcemanagement.ThreadAllocation; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.gatk.walkers.qc.CountReads; @@ -139,7 +136,7 @@ public class TraverseReadsUnitTest extends BaseTest { @Test public void testUnmappedReadCount() { SAMDataSource dataSource = new SAMDataSource(bamList,new ThreadAllocation(),null,genomeLocParser); - Iterable shardStrategy = dataSource.createShardIteratorOverAllReads(new LegacyReadShardBalancer()); + Iterable shardStrategy = dataSource.createShardIteratorOverAllReads(new ReadShardBalancer()); countReadWalker.initialize(); Object accumulator = countReadWalker.reduceInit(); diff --git a/public/java/test/org/broadinstitute/sting/utils/LegacyReservoirDownsamplerUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/LegacyReservoirDownsamplerUnitTest.java deleted file mode 100644 index bdcd4f600..000000000 --- a/public/java/test/org/broadinstitute/sting/utils/LegacyReservoirDownsamplerUnitTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/* -* 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.utils; - -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; -import net.sf.samtools.SAMRecord; -import net.sf.samtools.SAMFileHeader; - -import java.util.*; - -/** - * Basic tests to prove the integrity of the reservoir downsampler. - * At the moment, always run tests on SAM records as that's the task - * for which the downsampler was conceived. - * - * @author mhanna - * @version 0.1 - */ -public class LegacyReservoirDownsamplerUnitTest { - private static final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1,1,200); - - - @Test - public void testEmptyIterator() { - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(1); - Assert.assertTrue(downsampler.isEmpty(),"Downsampler is not empty but should be."); - } - - @Test - public void testOneElementWithPoolSizeOne() { - List reads = Collections.singletonList(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(1); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - Collection batchedReads = downsampler.getDownsampledContents(); - Assert.assertEquals(batchedReads.size(), 1, "Downsampler is returning the wrong number of reads"); - Assert.assertSame(batchedReads.iterator().next(), reads.get(0), "Downsampler is returning an incorrect read"); - } - - @Test - public void testOneElementWithPoolSizeGreaterThanOne() { - List reads = Collections.singletonList(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(5); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - Collection batchedReads = downsampler.getDownsampledContents(); - Assert.assertEquals(batchedReads.size(), 1, "Downsampler is returning the wrong number of reads"); - Assert.assertSame(batchedReads.iterator().next(), reads.get(0), "Downsampler is returning an incorrect read"); - - } - - @Test - public void testPoolFilledPartially() { - List reads = new ArrayList(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(5); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - List batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 3, "Downsampler is returning the wrong number of reads"); - - Assert.assertSame(batchedReads.get(0), reads.get(0), "Downsampler read 1 is incorrect"); - Assert.assertSame(batchedReads.get(1), reads.get(1), "Downsampler read 2 is incorrect"); - Assert.assertSame(batchedReads.get(2), reads.get(2), "Downsampler read 3 is incorrect"); - } - - @Test - public void testPoolFilledExactly() { - List reads = new ArrayList(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read4",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read5",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(5); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - List batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 5, "Downsampler is returning the wrong number of reads"); - Assert.assertSame(batchedReads.iterator().next(), reads.get(0), "Downsampler is returning an incorrect read"); - - Assert.assertSame(batchedReads.get(0), reads.get(0), "Downsampler read 1 is incorrect"); - Assert.assertSame(batchedReads.get(1), reads.get(1), "Downsampler read 2 is incorrect"); - Assert.assertSame(batchedReads.get(2), reads.get(2), "Downsampler read 3 is incorrect"); - Assert.assertSame(batchedReads.get(3), reads.get(3), "Downsampler read 4 is incorrect"); - Assert.assertSame(batchedReads.get(4), reads.get(4), "Downsampler read 5 is incorrect"); - } - - @Test - public void testLargerPileWithZeroElementPool() { - List reads = new ArrayList(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(0); - downsampler.addAll(reads); - - Assert.assertTrue(downsampler.isEmpty(),"Downsampler isn't empty but should be"); - List batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 0, "Downsampler is returning the wrong number of reads"); - } - - @Test - public void testLargerPileWithSingleElementPool() { - List reads = new ArrayList(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read2",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read3",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read4",0,1,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read5",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(1); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - List batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 1, "Downsampler is returning the wrong number of reads"); - Assert.assertTrue(reads.contains(batchedReads.get(0)),"Downsampler is returning a bad read."); - } - - @Test - public void testFillingAcrossLoci() { - List reads = new ArrayList(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read1",0,1,76)); - LegacyReservoirDownsampler downsampler = new LegacyReservoirDownsampler(5); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - List batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 1, "Downsampler is returning the wrong number of reads"); - Assert.assertEquals(batchedReads.get(0), reads.get(0), "Downsampler is returning an incorrect read."); - - reads.clear(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read2",0,2,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read3",0,2,76)); - - downsampler.clear(); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 2, "Downsampler is returning the wrong number of reads"); - Assert.assertEquals(batchedReads.get(0), reads.get(0), "Downsampler is returning an incorrect read."); - Assert.assertEquals(batchedReads.get(1), reads.get(1), "Downsampler is returning an incorrect read."); - - reads.clear(); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read4",0,3,76)); - reads.add(ArtificialSAMUtils.createArtificialRead(header,"read5",0,3,76)); - - downsampler.clear(); - downsampler.addAll(reads); - - Assert.assertFalse(downsampler.isEmpty(),"Downsampler is empty but shouldn't be"); - batchedReads = new ArrayList(downsampler.getDownsampledContents()); - Assert.assertEquals(batchedReads.size(), 2, "Downsampler is returning the wrong number of reads"); - Assert.assertEquals(batchedReads.get(0), reads.get(0), "Downsampler is returning an incorrect read."); - Assert.assertEquals(batchedReads.get(1), reads.get(1), "Downsampler is returning an incorrect read."); - } - -} diff --git a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java index 4e7a783e5..eb7e61ed8 100644 --- a/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/locusiterator/LocusIteratorByStateUnitTest.java @@ -474,8 +474,8 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { final boolean downsample = downsampleTo != -1; final DownsamplingMethod downsampler = downsample - ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) - : new DownsamplingMethod(DownsampleType.NONE, null, null, false); + ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null) + : new DownsamplingMethod(DownsampleType.NONE, null, null); final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(header.getSequenceDictionary(), nReadsPerLocus, nLoci); bamBuilder.createAndSetHeader(nSamples).setReadLength(readLength).setAlignmentStart(1); @@ -635,8 +635,8 @@ public class LocusIteratorByStateUnitTest extends LocusIteratorByStateBaseTest { final boolean downsample = downsampleTo != -1; final DownsamplingMethod downsampler = downsample - ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null, false) - : new DownsamplingMethod(DownsampleType.NONE, null, null, false); + ? new DownsamplingMethod(DownsampleType.BY_SAMPLE, downsampleTo, null) + : new DownsamplingMethod(DownsampleType.NONE, null, null); // final List reads = ArtificialSAMUtils.createReadStream(nReadsPerLocus, nLoci, header, 1, readLength); From 1599c9a20e3c25faa899f496d76f7344c38e1e9b Mon Sep 17 00:00:00 2001 From: David Roazen Date: Mon, 28 Jan 2013 02:40:18 -0500 Subject: [PATCH 112/188] Remove the ability to package GATK/Queue Lite from the build system Still need to reconfigure Bamboo to open-source protected, but this can be done during the 2.4 release freeze. --- build.xml | 27 ---------------- public/packages/GenomeAnalysisTKLite.xml | 39 ----------------------- public/packages/QueueLite.xml | 40 ------------------------ 3 files changed, 106 deletions(-) delete mode 100644 public/packages/GenomeAnalysisTKLite.xml delete mode 100644 public/packages/QueueLite.xml diff --git a/build.xml b/build.xml index 2dfff0cc2..e92e41c10 100644 --- a/build.xml +++ b/build.xml @@ -873,10 +873,6 @@ - - - - @@ -885,10 +881,6 @@ - - - - @@ -939,15 +931,10 @@ - - - - - @@ -956,13 +943,8 @@ - - - - - @@ -1006,14 +988,10 @@ - - - - @@ -1363,13 +1341,8 @@ - - - - - diff --git a/public/packages/GenomeAnalysisTKLite.xml b/public/packages/GenomeAnalysisTKLite.xml deleted file mode 100644 index b2f73434c..000000000 --- a/public/packages/GenomeAnalysisTKLite.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/public/packages/QueueLite.xml b/public/packages/QueueLite.xml deleted file mode 100644 index 0ead68fb0..000000000 --- a/public/packages/QueueLite.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - From f63f27aa13250afd9730d192b2ce362dd6a11f14 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Tue, 8 Jan 2013 14:45:50 -0500 Subject: [PATCH 113/188] org.broadinstitute.variant refactor, part 2 -removed sting dependencies from test classes -removed org.apache.log4j dependency -misc cleanup --- .../gatk/walkers/annotator/RankSumTest.java | 2 +- .../annotator/TandemRepeatAnnotator.java | 6 +- .../gatk/walkers/bqsr/BaseRecalibrator.java | 2 +- .../reducereads/MultiSampleCompressor.java | 2 +- .../reducereads/SingleSampleCompressor.java | 2 +- .../reducereads/SlidingWindow.java | 2 +- .../genotyper/ConsensusAlleleCounter.java | 2 +- .../GeneralPloidyGenotypeLikelihoods.java | 2 +- ...dyGenotypeLikelihoodsCalculationModel.java | 2 +- .../genotyper/UnifiedArgumentCollection.java | 4 +- .../walkers/genotyper/UnifiedGenotyper.java | 4 +- .../genotyper/UnifiedGenotyperEngine.java | 7 +- .../genotyper/afcalc/DiploidExactAFCalc.java | 5 +- .../walkers/genotyper/afcalc/ExactAFCalc.java | 4 +- .../afcalc/GeneralPloidyExactAFCalc.java | 5 +- .../afcalc/OriginalDiploidExactAFCalc.java | 2 +- .../haplotypecaller/GenotypingEngine.java | 3 +- .../haplotypecaller/HaplotypeCaller.java | 5 +- .../gatk/walkers/indels/IndelRealigner.java | 2 +- .../validation/GenotypeAndValidate.java | 2 +- .../variantutils/RegenotypeVariants.java | 3 +- .../utils/recalibration/RecalDatumNode.java | 2 +- .../sting/utils/recalibration/RecalUtils.java | 2 +- .../recalibration/RecalibrationReport.java | 2 +- .../covariates/RepeatLengthCovariate.java | 4 +- ...eralPloidyGenotypeLikelihoodsUnitTest.java | 2 +- .../afcalc/AFCalcPerformanceUnitTest.java | 2 +- .../StratificationManagerUnitTest.java | 2 +- .../variantutils/CombineVariantsUnitTest.java | 6 +- .../ConcordanceMetricsUnitTest.java | 8 +- .../sting/commandline/ParsingEngine.java | 2 +- .../providers/RODMetaDataContainer.java | 2 +- .../sting/gatk/executive/Accumulator.java | 2 +- .../gatk/refdata/tracks/RMDTrackBuilder.java | 2 +- .../sting/gatk/walkers/Walker.java | 2 +- .../walkers/coverage/DepthOfCoverage.java | 2 +- .../walkers/coverage/GCContentByInterval.java | 2 +- .../diagnostics/CoveredByNSamplesSites.java | 5 - .../fasta/FastaAlternateReferenceMaker.java | 2 +- .../walkers/fasta/FastaReferenceMaker.java | 3 +- .../sting/gatk/walkers/qc/CountIntervals.java | 2 +- .../sting/gatk/walkers/qc/CountRODs.java | 2 +- .../sting/gatk/walkers/qc/CountRODsByRef.java | 2 +- .../gatk/walkers/qc/CountTerminusEvent.java | 2 +- .../gatk/walkers/readutils/ClipReads.java | 2 +- .../gatk/walkers/varianteval/VariantEval.java | 3 +- .../varianteval/VariantEvalReportWriter.java | 2 +- .../stratifications/TandemRepeat.java | 4 +- .../manager/StratificationManager.java | 3 +- .../walkers/variantutils/CombineVariants.java | 2 +- .../variantutils/GenotypeConcordance.java | 2 +- .../walkers/variantutils/SelectHeaders.java | 2 +- .../walkers/variantutils/SelectVariants.java | 2 +- .../sting/tools/CatVariants.java | 2 +- .../sting/utils/MannWhitneyU.java | 2 +- .../sting/utils/SWPairwiseAlignment.java | 52 +- .../sting/utils/SampleUtils.java | 2 +- .../broadinstitute/sting/utils/baq/BAQ.java | 2 +- .../sting/utils/duplicates/DupUtils.java | 2 +- .../sting/utils/fragments/FragmentUtils.java | 2 +- .../help/GenericDocumentationHandler.java | 2 +- .../sting/utils/interval/IntervalUtils.java | 2 +- .../sting/utils/sam/ReadUtils.java | 2 +- .../sting/utils/variant/GATKVCFUtils.java | 30 +- .../variant/GATKVariantContextUtils.java | 431 ----------------- .../variant/bcf2/BCF2Codec.java | 8 +- .../variant/bcf2/BCF2Decoder.java | 10 +- .../bcf2/BCF2GenotypeFieldDecoders.java | 2 - .../bcf2/BCF2LazyGenotypesDecoder.java | 5 - .../utils/{Utils.java => GeneralUtils.java} | 102 +++- .../collections => variant/utils}/Pair.java | 2 +- .../variantcontext/GenotypeLikelihoods.java | 6 +- .../variantcontext/VariantContext.java | 11 +- .../variantcontext/VariantContextUtils.java | 445 +++++++++++++++++- .../variantcontext/VariantJEXLContext.java | 4 +- .../writer/BCF2FieldWriterManager.java | 7 +- .../variantcontext/writer/BCF2Writer.java | 9 +- .../variant/vcf/AbstractVCFCodec.java | 14 +- .../variant/vcf/VCFCompoundHeaderLine.java | 7 +- .../broadinstitute/variant/vcf/VCFHeader.java | 21 +- .../variant/vcf/VCFStandardHeaderLines.java | 15 +- .../broadinstitute/variant/vcf/VCFUtils.java | 52 +- .../org/broadinstitute/sting/WalkerTest.java | 2 +- .../sting/utils/MWUnitTest.java | 4 +- .../BandPassActivityProfileUnitTest.java | 2 +- .../utils/variant}/VCFIntegrationTest.java | 3 +- .../variant}/VariantContextBenchmark.java | 6 +- .../variant/VariantBaseTest.java | 141 ++++++ .../bcf2/BCF2EncoderDecoderUnitTest.java | 9 +- .../variant/bcf2/BCF2UtilsUnitTest.java | 10 +- .../variant/utils/BaseUtilsUnitTest.java | 13 +- .../variantcontext/AlleleUnitTest.java | 3 +- .../GenotypeLikelihoodsUnitTest.java | 10 +- .../variantcontext/GenotypeUnitTest.java | 4 +- .../GenotypesContextUnitTest.java | 8 +- .../VariantContextTestProvider.java | 31 +- .../VariantContextUnitTest.java | 39 +- .../VariantContextUtilsUnitTest.java | 26 +- .../VariantJEXLContextUnitTest.java | 26 +- .../writer/VCFWriterUnitTest.java | 23 +- .../writer/VariantContextWritersUnitTest.java | 9 +- .../variant/vcf/IndexFactoryUnitTest.java | 15 +- .../variant/vcf/VCFHeaderUnitTest.java | 13 +- .../vcf/VCFStandardHeaderLinesUnitTest.java | 4 +- 104 files changed, 979 insertions(+), 825 deletions(-) rename public/java/src/org/broadinstitute/variant/utils/{Utils.java => GeneralUtils.java} (64%) rename public/java/src/org/broadinstitute/{sting/utils/collections => variant/utils}/Pair.java (98%) rename public/java/test/org/broadinstitute/{variant/vcf => sting/utils/variant}/VCFIntegrationTest.java (98%) rename public/java/test/org/broadinstitute/{variant/variantcontext => sting/utils/variant}/VariantContextBenchmark.java (99%) create mode 100644 public/java/test/org/broadinstitute/variant/VariantBaseTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java index ec107512a..6f965227c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java @@ -57,7 +57,7 @@ import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.sting.utils.MannWhitneyU; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.variant.vcf.VCFHeaderLine; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.Allele; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java index 2ec53133d..a6b713551 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java @@ -53,11 +53,11 @@ import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompa import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.InfoFieldAnnotation; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.StandardAnnotation; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeaderLineCount; import org.broadinstitute.variant.vcf.VCFHeaderLineType; import org.broadinstitute.variant.vcf.VCFInfoHeaderLine; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import java.util.Arrays; @@ -79,7 +79,7 @@ public class TandemRepeatAnnotator extends InfoFieldAnnotation implements Standa if ( !vc.isIndel()) return null; - Pair,byte[]> result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, ref.getForwardBases()); + Pair,byte[]> result = VariantContextUtils.getNumTandemRepeatUnits(vc, ref.getForwardBases()); if (result == null) return null; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java index 76e4374d1..d6c5e82f6 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java @@ -63,7 +63,7 @@ import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java index 6818669df..50d741f13 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; import net.sf.samtools.SAMFileHeader; import org.apache.log4j.Logger; import org.broadinstitute.sting.utils.SampleUtils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java index 036d2782a..5b08e99a0 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java index 58282e216..e91120f1c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java @@ -52,7 +52,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.gatk.downsampling.ReservoirDownsampler; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.recalibration.EventType; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java index 2257adf6a..90904ab29 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java @@ -53,7 +53,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java index cf144a735..6a5fbce39 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.ExactACcounts; import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.ExactACset; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.variant.vcf.VCFConstants; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java index 3e0437edb..23804bb23 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java @@ -56,7 +56,7 @@ import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.variant.vcf.VCFConstants; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.*; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java index a7f90ebec..e97c92309 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java @@ -49,8 +49,8 @@ package org.broadinstitute.sting.gatk.walkers.genotyper; import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.arguments.StandardCallerArgumentCollection; import org.broadinstitute.sting.utils.pairhmm.PairHMM; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.VariantContext; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; public class UnifiedArgumentCollection extends StandardCallerArgumentCollection { @@ -172,7 +172,7 @@ public class UnifiedArgumentCollection extends StandardCallerArgumentCollection Sample ploidy - equivalent to number of chromosomes per pool. In pooled experiments this should be = # of samples in pool * individual sample ploidy */ @Argument(shortName="ploidy", fullName="sample_ploidy", doc="Plody (number of chromosomes) per sample. For pooled data, set to (Number of samples in each pool * Sample Ploidy).", required=false) - public int samplePloidy = GATKVariantContextUtils.DEFAULT_PLOIDY; + public int samplePloidy = VariantContextUtils.DEFAULT_PLOIDY; @Hidden @Argument(shortName="minqs", fullName="min_quality_score", doc="Min quality score to consider. Smaller numbers process faster. Default: Q1.", required=false) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java index d16ece4fd..46ac10d90 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java @@ -61,7 +61,7 @@ import org.broadinstitute.sting.gatk.walkers.annotator.VariantAnnotatorEngine; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompatible; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -304,7 +304,7 @@ public class UnifiedGenotyper extends LocusWalker, Unif headerInfo.add(new VCFInfoHeaderLine(UnifiedGenotyperEngine.NUMBER_OF_DISCOVERED_ALLELES_KEY, 1, VCFHeaderLineType.Integer, "Number of alternate alleles discovered (but not necessarily genotyped) at this site")); // add the pool values for each genotype - if (UAC.samplePloidy != GATKVariantContextUtils.DEFAULT_PLOIDY) { + if (UAC.samplePloidy != VariantContextUtils.DEFAULT_PLOIDY) { headerInfo.add(new VCFFormatHeaderLine(VCFConstants.MLE_PER_SAMPLE_ALLELE_COUNT_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Integer, "Maximum likelihood expectation (MLE) for the alternate allele count, in the same order as listed, for each individual sample")); headerInfo.add(new VCFFormatHeaderLine(VCFConstants.MLE_PER_SAMPLE_ALLELE_FRACTION_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Float, "Maximum likelihood expectation (MLE) for the alternate allele fraction, in the same order as listed, for each individual sample")); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java index 8f6097661..b1aaf8190 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java @@ -61,7 +61,6 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.AFCalcResult; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.classloader.PluginManager; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -135,7 +134,7 @@ public class UnifiedGenotyperEngine { // --------------------------------------------------------------------------------------------------------- @Requires({"toolkit != null", "UAC != null"}) public UnifiedGenotyperEngine(GenomeAnalysisEngine toolkit, UnifiedArgumentCollection UAC) { - this(toolkit, UAC, Logger.getLogger(UnifiedGenotyperEngine.class), null, null, SampleUtils.getSAMFileSamples(toolkit.getSAMFileHeader()), GATKVariantContextUtils.DEFAULT_PLOIDY); + this(toolkit, UAC, Logger.getLogger(UnifiedGenotyperEngine.class), null, null, SampleUtils.getSAMFileSamples(toolkit.getSAMFileHeader()), VariantContextUtils.DEFAULT_PLOIDY); } @Requires({"toolkit != null", "UAC != null", "logger != null", "samples != null && samples.size() > 0","ploidy>0"}) @@ -526,7 +525,7 @@ public class UnifiedGenotyperEngine { // if we are subsetting alleles (either because there were too many or because some were not polymorphic) // then we may need to trim the alleles (because the original VariantContext may have had to pad at the end). if ( myAlleles.size() != vc.getAlleles().size() && !limitedContext ) // limitedContext callers need to handle allele trimming on their own to keep their perReadAlleleLikelihoodMap alleles in sync - vcCall = GATKVariantContextUtils.reverseTrimAlleles(vcCall); + vcCall = VariantContextUtils.reverseTrimAlleles(vcCall); if ( annotationEngine != null && !limitedContext ) { // limitedContext callers need to handle annotations on their own by calling their own annotationEngine // Note: we want to use the *unfiltered* and *unBAQed* context for the annotations @@ -663,7 +662,7 @@ public class UnifiedGenotyperEngine { private void determineGLModelsToUse() { String modelPrefix = ""; - if ( !UAC.GLmodel.name().contains(GPSTRING) && UAC.samplePloidy != GATKVariantContextUtils.DEFAULT_PLOIDY ) + if ( !UAC.GLmodel.name().contains(GPSTRING) && UAC.samplePloidy != VariantContextUtils.DEFAULT_PLOIDY ) modelPrefix = GPSTRING; if ( UAC.GLmodel.name().toUpperCase().contains("BOTH") ) { diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java index 170b6e250..68f57a300 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java @@ -47,7 +47,6 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.*; import java.util.*; @@ -106,7 +105,7 @@ public abstract class DiploidExactAFCalc extends ExactAFCalc { alleles.add(vc.getReference()); alleles.addAll(chooseMostLikelyAlternateAlleles(vc, getMaxAltAlleles())); builder.alleles(alleles); - builder.genotypes(GATKVariantContextUtils.subsetDiploidAlleles(vc, alleles, false)); + builder.genotypes(VariantContextUtils.subsetDiploidAlleles(vc, alleles, false)); return builder.make(); } else { return vc; @@ -352,6 +351,6 @@ public abstract class DiploidExactAFCalc extends ExactAFCalc { final List allelesToUse, final boolean assignGenotypes, final int ploidy) { - return GATKVariantContextUtils.subsetDiploidAlleles(vc, allelesToUse, assignGenotypes); + return VariantContextUtils.subsetDiploidAlleles(vc, allelesToUse, assignGenotypes); } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java index 3d28db159..cf6b67afd 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java @@ -47,10 +47,10 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.Genotype; import org.broadinstitute.variant.variantcontext.GenotypesContext; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.ArrayList; @@ -92,7 +92,7 @@ abstract class ExactAFCalc extends AFCalc { if ( sample.hasLikelihoods() ) { double[] gls = sample.getLikelihoods().getAsVector(); - if ( MathUtils.sum(gls) < GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) + if ( MathUtils.sum(gls) < VariantContextUtils.SUM_GL_THRESH_NOCALL ) genotypeLikelihoods.add(gls); } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java index f8c364e82..1e1652c68 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java @@ -48,7 +48,6 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.gatk.walkers.genotyper.GeneralPloidyGenotypeLikelihoods; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.variant.variantcontext.*; @@ -554,7 +553,7 @@ public class GeneralPloidyExactAFCalc extends ExactAFCalc { } // if there is no mass on the (new) likelihoods, then just no-call the sample - if ( MathUtils.sum(newLikelihoods) > GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) { + if ( MathUtils.sum(newLikelihoods) > VariantContextUtils.SUM_GL_THRESH_NOCALL ) { newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); } else { @@ -566,7 +565,7 @@ public class GeneralPloidyExactAFCalc extends ExactAFCalc { gb.PL(newLikelihoods); // if we weren't asked to assign a genotype, then just no-call the sample - if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) + if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > VariantContextUtils.SUM_GL_THRESH_NOCALL ) gb.alleles(NO_CALL_ALLELES); else assignGenotype(gb, newLikelihoods, allelesToUse, ploidy); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java index 325d3b722..92305fe4b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java @@ -47,7 +47,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.VariantContext; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java index 27e921432..fa15eccdf 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java @@ -57,7 +57,6 @@ import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.*; @@ -204,7 +203,7 @@ public class GenotypingEngine { VariantContext annotatedCall = annotationEngine.annotateContext(stratifiedReadMap, call); if( annotatedCall.getAlleles().size() != mergedVC.getAlleles().size() ) { // some alleles were removed so reverseTrimming might be necessary! - annotatedCall = GATKVariantContextUtils.reverseTrimAlleles(annotatedCall); + annotatedCall = VariantContextUtils.reverseTrimAlleles(annotatedCall); } returnCalls.add( annotatedCall ); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 8b3eb9f1b..455809a17 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -72,7 +72,6 @@ import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; @@ -298,7 +297,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem samplesList.addAll( samples ); // initialize the UnifiedGenotyper Engine which is used to call into the exact model final UnifiedArgumentCollection UAC = new UnifiedArgumentCollection( SCAC ); // this adapter is used so that the full set of unused UG arguments aren't exposed to the HC user - UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); + UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); // create a UAC but with the exactCallsLog = null, so we only output the log for the HC caller itself, if requested UnifiedArgumentCollection simpleUAC = new UnifiedArgumentCollection(UAC); @@ -308,7 +307,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem simpleUAC.STANDARD_CONFIDENCE_FOR_EMITTING = Math.min( 4.0, UAC.STANDARD_CONFIDENCE_FOR_EMITTING ); // low values used for isActive determination only, default/user-specified values used for actual calling simpleUAC.CONTAMINATION_FRACTION = 0.0; simpleUAC.exactCallsLog = null; - UG_engine_simple_genotyper = new UnifiedGenotyperEngine(getToolkit(), simpleUAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); + UG_engine_simple_genotyper = new UnifiedGenotyperEngine(getToolkit(), simpleUAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); // initialize the output VCF header annotationEngine = new VariantAnnotatorEngine(Arrays.asList(annotationClassesToUse), annotationsToUse, annotationsToExclude, this, getToolkit()); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java index 851703648..1865cadea 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java @@ -63,7 +63,7 @@ import org.broadinstitute.sting.gatk.walkers.BAQMode; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java index 33187f79a..927e1e607 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java @@ -328,7 +328,7 @@ public class GenotypeAndValidate extends RodWalker header = GATKVCFUtils.getVCFHeadersFromRodPrefix(getToolkit(), alleles.getName()); samples = SampleUtils.getSampleList(header, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); - Set headerLines = VCFUtils.smartMergeHeaders(header.values(), logger); + Set headerLines = VCFUtils.smartMergeHeaders(header.values(), true); headerLines.add(new VCFHeaderLine("source", "GenotypeAndValidate")); vcfWriter.writeHeader(new VCFHeader(headerLines, samples)); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java index c8fc27e6a..74ab8f073 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java @@ -61,7 +61,6 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.broadinstitute.variant.vcf.*; @@ -116,7 +115,7 @@ public class RegenotypeVariants extends RodWalker implements T String trackName = variantCollection.variants.getName(); Set samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName)); - UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); + UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); final Set hInfo = new HashSet(); hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(trackName))); diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java index 637d9fb2d..9122c9ab6 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java @@ -51,7 +51,7 @@ import com.google.java.contract.Requires; import org.apache.commons.math.MathException; import org.apache.commons.math.stat.inference.ChiSquareTestImpl; import org.apache.log4j.Logger; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.Collection; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java index 4cde2916d..e8fc713f1 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java @@ -58,7 +58,7 @@ import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.PluginManager; import org.broadinstitute.sting.utils.collections.NestedIntegerArray; import org.broadinstitute.sting.utils.collections.NestedHashMap; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.DynamicClassResolutionException; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java index 3ecc41109..3fdbd63bd 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.report.GATKReportTable; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.collections.NestedIntegerArray; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.recalibration.covariates.Covariate; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java index 6586782b8..638d9fb93 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.utils.recalibration.covariates; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.recalibration.ReadCovariates; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.Arrays; @@ -73,7 +73,7 @@ public class RepeatLengthCovariate implements ExperimentalCovariate { int maxRL = 0; for (int str = 1; str <= 8; str++) { if (i + str <= readBytes.length) { - maxRL = Math.max(maxRL, GATKVariantContextUtils.findNumberofRepetitions( + maxRL = Math.max(maxRL, VariantContextUtils.findNumberofRepetitions( Arrays.copyOfRange(readBytes, i, i + str), Arrays.copyOfRange(readBytes, i, readBytes.length) )); diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java index 14dedebc4..08d333f8b 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java @@ -52,7 +52,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.*; import org.testng.Assert; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java index 8deddc357..291489984 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.VariantContext; import org.testng.Assert; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java index aabcd374d..f144f9b59 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java @@ -52,7 +52,7 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manage import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java index 46bd5af3c..31ed3dcc8 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java @@ -164,7 +164,7 @@ public class CombineVariantsUnitTest { ArrayList headers = new ArrayList(); headers.add(one); headers.add(two); - Set lines = VCFUtils.smartMergeHeaders(headers, null); + Set lines = VCFUtils.smartMergeHeaders(headers, false); Assert.assertEquals(lines.size(), VCFHeaderUnitTest.VCF4headerStringCount); } @@ -175,7 +175,7 @@ public class CombineVariantsUnitTest { ArrayList headers = new ArrayList(); headers.add(one); headers.add(two); - Set lines = VCFUtils.smartMergeHeaders(headers, null); + Set lines = VCFUtils.smartMergeHeaders(headers, false); Assert.assertEquals(lines.size(), VCFHeaderUnitTest.VCF4headerStringCount); } @@ -186,7 +186,7 @@ public class CombineVariantsUnitTest { ArrayList headers = new ArrayList(); headers.add(one); headers.add(two); - Set lines = VCFUtils.smartMergeHeaders(headers, null); + Set lines = VCFUtils.smartMergeHeaders(headers, false); Assert.assertEquals(lines.size(), VCFHeaderUnitTest.VCF4headerStringCount); } } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java index 0fff41d52..300dd633d 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java @@ -46,20 +46,16 @@ package org.broadinstitute.sting.gatk.walkers.variantutils; -import com.sun.org.apache.xpath.internal.operations.Gt; import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.gatk.walkers.variantutils.ConcordanceMetrics; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.Genotype; import org.broadinstitute.variant.variantcontext.GenotypeBuilder; import org.broadinstitute.variant.variantcontext.GenotypeType; -import org.broadinstitute.variant.variantcontext.GenotypesContext; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextBuilder; import org.broadinstitute.variant.vcf.VCFCodec; @@ -67,7 +63,6 @@ import org.broadinstitute.variant.vcf.VCFHeader; import org.testng.annotations.Test; import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.PositionalBufferedStream; -import org.broadinstitute.variant.vcf.*; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -75,7 +70,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.StringBufferInputStream; import java.util.ArrayList; -import java.util.Set; import java.util.Arrays; import java.util.List; import net.sf.picard.reference.ReferenceSequenceFile; diff --git a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java index 5e863f4f7..071bd2cad 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java +++ b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java @@ -31,7 +31,7 @@ import org.apache.log4j.Logger; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.JVMUtils; import org.broadinstitute.sting.utils.classloader.PluginManager; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.ApplicationDetails; diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java index e078e678b..b7c824360 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java @@ -26,7 +26,7 @@ package org.broadinstitute.sting.gatk.datasources.providers; import org.broadinstitute.sting.gatk.refdata.utils.GATKFeature; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java b/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java index d0ba0fa21..ea83aab53 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java @@ -31,7 +31,7 @@ import org.broadinstitute.sting.gatk.datasources.providers.ShardDataProvider; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocSortedSet; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.ArrayList; diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java index c5f87d625..ec51b2f53 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java @@ -40,7 +40,7 @@ import org.broadinstitute.sting.gatk.arguments.ValidationExclusion; import org.broadinstitute.sting.gatk.refdata.utils.RMDTriplet; import org.broadinstitute.sting.gatk.refdata.utils.RMDTriplet.RMDStorageType; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.file.FSLockWithShared; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java index 522414c00..979cc2fbf 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.gatk.samples.Sample; import org.broadinstitute.sting.gatk.samples.SampleDB; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.recalibration.BQSRMode; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java index dbb8ed5a6..383b22295 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java @@ -46,7 +46,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.codecs.refseq.RefSeqCodec; import org.broadinstitute.sting.utils.codecs.refseq.RefSeqFeature; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java index 668d3fd5f..77a4af1cd 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java index 0ad6e9d3b..a5a8edb0c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java @@ -26,7 +26,6 @@ package org.broadinstitute.sting.gatk.walkers.diagnostics; -import ca.mcgill.mcb.pcingola.interval.Intron; import org.broadinstitute.sting.commandline.Argument; import org.broadinstitute.sting.commandline.ArgumentCollection; import org.broadinstitute.sting.commandline.Output; @@ -36,17 +35,13 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; -import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.variant.variantcontext.Genotype; import org.broadinstitute.variant.variantcontext.GenotypesContext; import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.*; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; /** * print intervals file with all the variant sites that have "most" ( >= 90% by default) of the samples with "good" (>= 10 by default)coverage ("most" and "good" can be set in the command line). diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java index 8a5b3530e..ac6d82375 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.VariantContext; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java index e9728601d..d12ad3183 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java @@ -32,9 +32,8 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; -import org.broadinstitute.sting.gatk.walkers.WalkerName; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java index 0423c6f0a..82247d160 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java @@ -36,7 +36,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java index a0f943f7e..be1e264c6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java @@ -43,7 +43,7 @@ import org.broadinstitute.sting.gatk.walkers.TreeReducible; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.collections.ExpandingArrayList; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java index 77490be93..7135bffce 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; import org.broadinstitute.sting.utils.collections.ExpandingArrayList; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.util.Collections; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java index cabc2f467..4e05033ec 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.gatk.walkers.Requires; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java index fe2b75464..6b2c0f75c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java @@ -45,7 +45,7 @@ import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.clipping.ClippingOp; import org.broadinstitute.sting.utils.clipping.ClippingRepresentation; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java index d586ee7da..9f758706e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java @@ -49,7 +49,6 @@ import org.broadinstitute.sting.gatk.walkers.varianteval.util.VariantEvalUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -198,7 +197,7 @@ public class VariantEval extends RodWalker implements TreeRedu protected double MENDELIAN_VIOLATION_QUAL_THRESHOLD = 50; @Argument(shortName="ploidy", fullName="samplePloidy", doc="Per-sample ploidy (number of chromosomes per sample)", required=false) - protected int ploidy = GATKVariantContextUtils.DEFAULT_PLOIDY; + protected int ploidy = VariantContextUtils.DEFAULT_PLOIDY; @Argument(fullName="ancestralAlignments", shortName="aa", doc="Fasta file with ancestral alleles", required=false) private File ancestralAlignmentsFile = null; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java index a63f32485..5c16c7385 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java @@ -34,7 +34,7 @@ import org.broadinstitute.sting.gatk.walkers.varianteval.util.Analysis; import org.broadinstitute.sting.gatk.walkers.varianteval.util.AnalysisModuleScanner; import org.broadinstitute.sting.gatk.walkers.varianteval.util.DataPoint; import org.broadinstitute.sting.gatk.walkers.varianteval.util.EvaluationContext; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java index de82b18cc..5ef414b00 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java @@ -27,8 +27,8 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.VariantContext; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.Arrays; import java.util.List; @@ -51,7 +51,7 @@ public class TandemRepeat extends VariantStratifier { public List getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) { if ( eval == null || ! eval.isIndel() ) return ALL; - else if ( GATKVariantContextUtils.isTandemRepeat(eval, ref.getForwardBases()) ) { + else if ( VariantContextUtils.isTandemRepeat(eval, ref.getForwardBases()) ) { print("REPEAT", eval, ref); return REPEAT; } else { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java index 053a88218..d792e4c67 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java @@ -27,9 +27,8 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manage import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.broadinstitute.sting.gatk.walkers.varianteval.util.EvaluationContext; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java index 3ebac3e58..c54a57385 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java @@ -217,7 +217,7 @@ public class CombineVariants extends RodWalker implements Tree if ( SET_KEY.toLowerCase().equals("null") ) SET_KEY = null; - Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), logger); + Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true); if ( SET_KEY != null ) headerLines.add(new VCFInfoHeaderLine(SET_KEY, 1, VCFHeaderLineType.String, "Source VCF for the merged record in CombineVariants")); if ( !ASSUME_IDENTICAL_SAMPLES ) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 048c7ef77..8d5e7c2b8 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -32,7 +32,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.report.GATKReport; import org.broadinstitute.sting.gatk.report.GATKReportTable; import org.broadinstitute.sting.gatk.walkers.RodWalker; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.vcf.VCFHeader; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java index abd0956fb..e94a771d3 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java @@ -153,7 +153,7 @@ public class SelectHeaders extends RodWalker implements TreeRe List rodNames = Arrays.asList(variantCollection.variants.getName()); Map vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), rodNames); - Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), logger); + Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true); headerLines.add(new VCFHeaderLine(VCFHeader.SOURCE_KEY, "SelectHeaders")); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java index 6da6d14b1..dfe604a7d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java @@ -400,7 +400,7 @@ public class SelectVariants extends RodWalker implements TreeR } // Initialize VCF header - Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), logger); + Set headerLines = VCFUtils.smartMergeHeaders(vcfRods.values(), true); headerLines.add(new VCFHeaderLine("source", "SelectVariants")); if (KEEP_ORIGINAL_CHR_COUNTS) { diff --git a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java index 1feb4e009..07a90bb11 100644 --- a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java +++ b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java @@ -36,9 +36,9 @@ import org.broadinstitute.sting.commandline.Input; import org.broadinstitute.sting.commandline.Output; import org.broadinstitute.sting.commandline.CommandLineProgram; import org.broadinstitute.variant.bcf2.BCF2Codec; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.vcf.VCFCodec; import org.broadinstitute.variant.vcf.VCFHeader; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.writer.Options; diff --git a/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java b/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java index 74009682a..05468c6c2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java +++ b/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java @@ -33,7 +33,7 @@ import org.apache.commons.math.MathException; import org.apache.commons.math.distribution.NormalDistribution; import org.apache.commons.math.distribution.NormalDistributionImpl; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.StingException; import java.io.Serializable; diff --git a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java index 7bd937af9..b316d1117 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java +++ b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java @@ -1,34 +1,34 @@ -/* -* 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. -*/ - +/* +* 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.utils; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.StingException; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java index 6a430588b..4e98897cf 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java @@ -29,8 +29,8 @@ import net.sf.samtools.SAMFileHeader; import net.sf.samtools.SAMReadGroupRecord; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.vcf.VCFHeader; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.text.ListFileUtils; import org.broadinstitute.sting.utils.text.XReadLines; import org.broadinstitute.variant.variantcontext.VariantContextUtils; diff --git a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java index 8c7bce6ac..794caa315 100644 --- a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java +++ b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java @@ -32,7 +32,7 @@ import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import net.sf.samtools.SAMUtils; import org.apache.log4j.Logger; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.sam.ReadUtils; diff --git a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java index 39f5b06c6..1072fb1b7 100644 --- a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java @@ -29,7 +29,7 @@ import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.QualityUtils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java index 76ccede62..00dd037db 100644 --- a/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java @@ -30,7 +30,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.utils.recalibration.EventType; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java index bb0dc670b..099554a2c 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java @@ -37,7 +37,7 @@ import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.refdata.tracks.FeatureManager; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.JVMUtils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; diff --git a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java index 7374dda14..403e166c5 100644 --- a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java @@ -39,7 +39,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.GenomeLocSortedSet; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.text.XReadLines; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index 29f8c8dcd..46eceefd5 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -32,7 +32,7 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.NGSPlatform; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.variant.utils.BaseUtils; diff --git a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java index 8602a2bd3..b2069c7ee 100644 --- a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java @@ -31,7 +31,7 @@ import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.sting.commandline.RodBinding; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.datasources.rmd.ReferenceOrderedDataSource; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.vcf.*; @@ -147,32 +147,4 @@ public class GATKVCFUtils { return VCFUtils.withUpdatedContigs(header, engine.getArguments().referenceFile, engine.getMasterSequenceDictionary()); } - /** - * Read all of the VCF records from source into memory, returning the header and the VariantContexts - * - * @param source the file to read, must be in VCF4 format - * @return - * @throws java.io.IOException - */ - public static Pair> readVCF(final File source) throws IOException { - // read in the features - final List vcs = new ArrayList(); - final VCFCodec codec = new VCFCodec(); - PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); - FeatureCodecHeader header = codec.readHeader(pbs); - pbs.close(); - - pbs = new PositionalBufferedStream(new FileInputStream(source)); - pbs.skip(header.getHeaderEnd()); - - final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue(); - - while ( ! pbs.isDone() ) { - final VariantContext vc = codec.decode(pbs); - if ( vc != null ) - vcs.add(vc); - } - - return new Pair>(vcfHeader, vcs); - } } \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java index 8accb1643..82241ad55 100644 --- a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java @@ -25,22 +25,12 @@ package org.broadinstitute.sting.utils.variant; -import com.google.java.contract.Requires; -import org.apache.commons.lang.ArrayUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.*; -import java.util.*; - public class GATKVariantContextUtils { - public static final int DEFAULT_PLOIDY = 2; - public static final double SUM_GL_THRESH_NOCALL = -0.1; // if sum(gl) is bigger than this threshold, we treat GL's as non-informative and will force a no-call. - private static final List NO_CALL_ALLELES = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL); - /** * create a genome location, given a variant context * @param genomeLocParser parser @@ -51,425 +41,4 @@ public class GATKVariantContextUtils { return genomeLocParser.createGenomeLoc(vc.getChr(), vc.getStart(), vc.getEnd(), true); } - /** - * Returns true iff VC is an non-complex indel where every allele represents an expansion or - * contraction of a series of identical bases in the reference. - * - * For example, suppose the ref bases are CTCTCTGA, which includes a 3x repeat of CTCTCT - * - * If VC = -/CT, then this function returns true because the CT insertion matches exactly the - * upcoming reference. - * If VC = -/CTA then this function returns false because the CTA isn't a perfect match - * - * Now consider deletions: - * - * If VC = CT/- then again the same logic applies and this returns true - * The case of CTA/- makes no sense because it doesn't actually match the reference bases. - * - * The logic of this function is pretty simple. Take all of the non-null alleles in VC. For - * each insertion allele of n bases, check if that allele matches the next n reference bases. - * For each deletion allele of n bases, check if this matches the reference bases at n - 2 n, - * as it must necessarily match the first n bases. If this test returns true for all - * alleles you are a tandem repeat, otherwise you are not. - * - * @param vc - * @param refBasesStartingAtVCWithPad not this is assumed to include the PADDED reference - * @return - */ - @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) - public static boolean isTandemRepeat(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { - final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); - if ( ! vc.isIndel() ) // only indels are tandem repeats - return false; - - final Allele ref = vc.getReference(); - - for ( final Allele allele : vc.getAlternateAlleles() ) { - if ( ! isRepeatAllele(ref, allele, refBasesStartingAtVCWithoutPad) ) - return false; - } - - // we've passed all of the tests, so we are a repeat - return true; - } - - /** - * - * @param vc - * @param refBasesStartingAtVCWithPad - * @return - */ - @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) - public static Pair,byte[]> getNumTandemRepeatUnits(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { - final boolean VERBOSE = false; - final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); - if ( ! vc.isIndel() ) // only indels are tandem repeats - return null; - - final Allele refAllele = vc.getReference(); - final byte[] refAlleleBases = Arrays.copyOfRange(refAllele.getBases(), 1, refAllele.length()); - - byte[] repeatUnit = null; - final ArrayList lengths = new ArrayList(); - - for ( final Allele allele : vc.getAlternateAlleles() ) { - Pair result = getNumTandemRepeatUnits(refAlleleBases, Arrays.copyOfRange(allele.getBases(), 1, allele.length()), refBasesStartingAtVCWithoutPad.getBytes()); - - final int[] repetitionCount = result.first; - // repetition count = 0 means allele is not a tandem expansion of context - if (repetitionCount[0] == 0 || repetitionCount[1] == 0) - return null; - - if (lengths.size() == 0) { - lengths.add(repetitionCount[0]); // add ref allele length only once - } - lengths.add(repetitionCount[1]); // add this alt allele's length - - repeatUnit = result.second; - if (VERBOSE) { - System.out.println("RefContext:"+refBasesStartingAtVCWithoutPad); - System.out.println("Ref:"+refAllele.toString()+" Count:" + String.valueOf(repetitionCount[0])); - System.out.println("Allele:"+allele.toString()+" Count:" + String.valueOf(repetitionCount[1])); - System.out.println("RU:"+new String(repeatUnit)); - } - } - - return new Pair, byte[]>(lengths,repeatUnit); - } - - protected static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { - /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units. - Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)5. - */ - - byte[] longB; - // find first repeat unit based on either ref or alt, whichever is longer - if (altBases.length > refBases.length) - longB = altBases; - else - longB = refBases; - - // see if non-null allele (either ref or alt, whichever is longer) can be decomposed into several identical tandem units - // for example, -*,CACA needs to first be decomposed into (CA)2 - final int repeatUnitLength = findRepeatedSubstring(longB); - final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength); - - final int[] repetitionCount = new int[2]; -// repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext)); -// repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext)); - int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases); - repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext))-repetitionsInRef; - repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext))-repetitionsInRef; - - return new Pair(repetitionCount, repeatUnit); - - } - - /** - * Find out if a string can be represented as a tandem number of substrings. - * For example ACTACT is a 2-tandem of ACT, - * but ACTACA is not. - * - * @param bases String to be tested - * @return Length of repeat unit, if string can be represented as tandem of substring (if it can't - * be represented as one, it will be just the length of the input string) - */ - public static int findRepeatedSubstring(byte[] bases) { - - int repLength; - for (repLength=1; repLength <=bases.length; repLength++) { - final byte[] candidateRepeatUnit = Arrays.copyOf(bases,repLength); - boolean allBasesMatch = true; - for (int start = repLength; start < bases.length; start += repLength ) { - // check that remaining of string is exactly equal to repeat unit - final byte[] basePiece = Arrays.copyOfRange(bases,start,start+candidateRepeatUnit.length); - if (!Arrays.equals(candidateRepeatUnit, basePiece)) { - allBasesMatch = false; - break; - } - } - if (allBasesMatch) - return repLength; - } - - return repLength; - } - - /** - * Helper routine that finds number of repetitions a string consists of. - * For example, for string ATAT and repeat unit AT, number of repetitions = 2 - * @param repeatUnit Substring - * @param testString String to test - * @return Number of repetitions (0 if testString is not a concatenation of n repeatUnit's - */ - public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString) { - int numRepeats = 0; - for (int start = 0; start < testString.length; start += repeatUnit.length) { - int end = start + repeatUnit.length; - byte[] unit = Arrays.copyOfRange(testString,start, end); - if(Arrays.equals(unit,repeatUnit)) - numRepeats++; - else - return numRepeats; - } - return numRepeats; - } - - /** - * Helper function for isTandemRepeat that checks that allele matches somewhere on the reference - * @param ref - * @param alt - * @param refBasesStartingAtVCWithoutPad - * @return - */ - protected static boolean isRepeatAllele(final Allele ref, final Allele alt, final String refBasesStartingAtVCWithoutPad) { - if ( ! Allele.oneIsPrefixOfOther(ref, alt) ) - return false; // we require one allele be a prefix of another - - if ( ref.length() > alt.length() ) { // we are a deletion - return basesAreRepeated(ref.getBaseString(), alt.getBaseString(), refBasesStartingAtVCWithoutPad, 2); - } else { // we are an insertion - return basesAreRepeated(alt.getBaseString(), ref.getBaseString(), refBasesStartingAtVCWithoutPad, 1); - } - } - - protected static boolean basesAreRepeated(final String l, final String s, final String ref, final int minNumberOfMatches) { - final String potentialRepeat = l.substring(s.length()); // skip s bases - - for ( int i = 0; i < minNumberOfMatches; i++) { - final int start = i * potentialRepeat.length(); - final int end = (i+1) * potentialRepeat.length(); - if ( ref.length() < end ) - return false; // we ran out of bases to test - final String refSub = ref.substring(start, end); - if ( ! refSub.equals(potentialRepeat) ) - return false; // repeat didn't match, fail - } - - return true; // we passed all tests, we matched - } - - /** - * Assign genotypes (GTs) to the samples in the Variant Context greedily based on the PLs - * - * @param vc variant context with genotype likelihoods - * @return genotypes context - */ - public static GenotypesContext assignDiploidGenotypes(final VariantContext vc) { - return subsetDiploidAlleles(vc, vc.getAlleles(), true); - } - - /** - * Split variant context into its biallelic components if there are more than 2 alleles - * - * For VC has A/B/C alleles, returns A/B and A/C contexts. - * Genotypes are all no-calls now (it's not possible to fix them easily) - * Alleles are right trimmed to satisfy VCF conventions - * - * If vc is biallelic or non-variant it is just returned - * - * Chromosome counts are updated (but they are by definition 0) - * - * @param vc a potentially multi-allelic variant context - * @return a list of bi-allelic (or monomorphic) variant context - */ - public static List splitVariantContextToBiallelics(final VariantContext vc) { - if ( ! vc.isVariant() || vc.isBiallelic() ) - // non variant or biallelics already satisfy the contract - return Collections.singletonList(vc); - else { - final List biallelics = new LinkedList(); - - for ( final Allele alt : vc.getAlternateAlleles() ) { - VariantContextBuilder builder = new VariantContextBuilder(vc); - final List alleles = Arrays.asList(vc.getReference(), alt); - builder.alleles(alleles); - builder.genotypes(subsetDiploidAlleles(vc, alleles, false)); - VariantContextUtils.calculateChromosomeCounts(builder, true); - biallelics.add(reverseTrimAlleles(builder.make())); - } - - return biallelics; - } - } - - /** - * subset the Variant Context to the specific set of alleles passed in (pruning the PLs appropriately) - * - * @param vc variant context with genotype likelihoods - * @param allelesToUse which alleles from the vc are okay to use; *** must be in the same relative order as those in the original VC *** - * @param assignGenotypes true if we should update the genotypes based on the (subsetted) PLs - * @return genotypes - */ - public static GenotypesContext subsetDiploidAlleles(final VariantContext vc, - final List allelesToUse, - final boolean assignGenotypes) { - - // the genotypes with PLs - final GenotypesContext oldGTs = vc.getGenotypes(); - - // samples - final List sampleIndices = oldGTs.getSampleNamesOrderedByName(); - - // the new genotypes to create - final GenotypesContext newGTs = GenotypesContext.create(); - - // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward - final int numOriginalAltAlleles = vc.getAlternateAlleles().size(); - final int numNewAltAlleles = allelesToUse.size() - 1; - - // which PLs should be carried forward? - ArrayList likelihoodIndexesToUse = null; - - // an optimization: if we are supposed to use all (or none in the case of a ref call) of the alleles, - // then we can keep the PLs as is; otherwise, we determine which ones to keep - if ( numNewAltAlleles != numOriginalAltAlleles && numNewAltAlleles > 0 ) { - likelihoodIndexesToUse = new ArrayList(30); - - final boolean[] altAlleleIndexToUse = new boolean[numOriginalAltAlleles]; - for ( int i = 0; i < numOriginalAltAlleles; i++ ) { - if ( allelesToUse.contains(vc.getAlternateAllele(i)) ) - altAlleleIndexToUse[i] = true; - } - - // numLikelihoods takes total # of alleles. Use default # of chromosomes (ploidy) = 2 - final int numLikelihoods = GenotypeLikelihoods.numLikelihoods(1 + numOriginalAltAlleles, DEFAULT_PLOIDY); - for ( int PLindex = 0; PLindex < numLikelihoods; PLindex++ ) { - final GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); - // consider this entry only if both of the alleles are good - if ( (alleles.alleleIndex1 == 0 || altAlleleIndexToUse[alleles.alleleIndex1 - 1]) && (alleles.alleleIndex2 == 0 || altAlleleIndexToUse[alleles.alleleIndex2 - 1]) ) - likelihoodIndexesToUse.add(PLindex); - } - } - - // create the new genotypes - for ( int k = 0; k < oldGTs.size(); k++ ) { - final Genotype g = oldGTs.get(sampleIndices.get(k)); - if ( !g.hasLikelihoods() ) { - newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); - continue; - } - - // create the new likelihoods array from the alleles we are allowed to use - final double[] originalLikelihoods = g.getLikelihoods().getAsVector(); - double[] newLikelihoods; - if ( likelihoodIndexesToUse == null ) { - newLikelihoods = originalLikelihoods; - } else { - newLikelihoods = new double[likelihoodIndexesToUse.size()]; - int newIndex = 0; - for ( int oldIndex : likelihoodIndexesToUse ) - newLikelihoods[newIndex++] = originalLikelihoods[oldIndex]; - - // might need to re-normalize - newLikelihoods = MathUtils.normalizeFromLog10(newLikelihoods, false, true); - } - - // if there is no mass on the (new) likelihoods, then just no-call the sample - if ( MathUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { - newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); - } - else { - final GenotypeBuilder gb = new GenotypeBuilder(g); - - if ( numNewAltAlleles == 0 ) - gb.noPL(); - else - gb.PL(newLikelihoods); - - // if we weren't asked to assign a genotype, then just no-call the sample - if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { - gb.alleles(NO_CALL_ALLELES); - } - else { - // find the genotype with maximum likelihoods - int PLindex = numNewAltAlleles == 0 ? 0 : MathUtils.maxElementIndex(newLikelihoods); - GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); - - gb.alleles(Arrays.asList(allelesToUse.get(alleles.alleleIndex1), allelesToUse.get(alleles.alleleIndex2))); - if ( numNewAltAlleles != 0 ) gb.log10PError(GenotypeLikelihoods.getGQLog10FromLikelihoods(PLindex, newLikelihoods)); - } - newGTs.add(gb.make()); - } - } - - return newGTs; - } - - public static VariantContext reverseTrimAlleles( final VariantContext inputVC ) { - - // see whether we need to trim common reference base from all alleles - final int trimExtent = computeReverseClipping(inputVC.getAlleles(), inputVC.getReference().getDisplayString().getBytes(), 0, false); - if ( trimExtent <= 0 || inputVC.getAlleles().size() <= 1 ) - return inputVC; - - final List alleles = new ArrayList(); - final GenotypesContext genotypes = GenotypesContext.create(); - final Map originalToTrimmedAlleleMap = new HashMap(); - - for (final Allele a : inputVC.getAlleles()) { - if (a.isSymbolic()) { - alleles.add(a); - originalToTrimmedAlleleMap.put(a, a); - } else { - // get bases for current allele and create a new one with trimmed bases - final byte[] newBases = Arrays.copyOfRange(a.getBases(), 0, a.length()-trimExtent); - final Allele trimmedAllele = Allele.create(newBases, a.isReference()); - alleles.add(trimmedAllele); - originalToTrimmedAlleleMap.put(a, trimmedAllele); - } - } - - // now we can recreate new genotypes with trimmed alleles - for ( final Genotype genotype : inputVC.getGenotypes() ) { - final List originalAlleles = genotype.getAlleles(); - final List trimmedAlleles = new ArrayList(); - for ( final Allele a : originalAlleles ) { - if ( a.isCalled() ) - trimmedAlleles.add(originalToTrimmedAlleleMap.get(a)); - else - trimmedAlleles.add(Allele.NO_CALL); - } - genotypes.add(new GenotypeBuilder(genotype).alleles(trimmedAlleles).make()); - } - - return new VariantContextBuilder(inputVC).stop(inputVC.getStart() + alleles.get(0).length() - 1).alleles(alleles).genotypes(genotypes).make(); - } - - public static int computeReverseClipping(final List unclippedAlleles, - final byte[] ref, - final int forwardClipping, - final boolean allowFullClip) { - int clipping = 0; - boolean stillClipping = true; - - while ( stillClipping ) { - for ( final Allele a : unclippedAlleles ) { - if ( a.isSymbolic() ) - continue; - - // we need to ensure that we don't reverse clip out all of the bases from an allele because we then will have the wrong - // position set for the VariantContext (although it's okay to forward clip it all out, because the position will be fine). - if ( a.length() - clipping == 0 ) - return clipping - (allowFullClip ? 0 : 1); - - if ( a.length() - clipping <= forwardClipping || a.length() - forwardClipping == 0 ) { - stillClipping = false; - } - else if ( ref.length == clipping ) { - if ( allowFullClip ) - stillClipping = false; - else - return -1; - } - else if ( a.getBases()[a.length()-clipping-1] != ref[ref.length-clipping-1] ) { - stillClipping = false; - } - } - if ( stillClipping ) - clipping++; - } - - return clipping; - } } diff --git a/public/java/src/org/broadinstitute/variant/bcf2/BCF2Codec.java b/public/java/src/org/broadinstitute/variant/bcf2/BCF2Codec.java index 2dcd775c0..098b2a5b0 100644 --- a/public/java/src/org/broadinstitute/variant/bcf2/BCF2Codec.java +++ b/public/java/src/org/broadinstitute/variant/bcf2/BCF2Codec.java @@ -27,13 +27,13 @@ package org.broadinstitute.variant.bcf2; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; import org.broad.tribble.Feature; import org.broad.tribble.FeatureCodec; import org.broad.tribble.FeatureCodecHeader; import org.broad.tribble.TribbleException; import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.PositionalBufferedStream; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.variant.variantcontext.*; @@ -50,8 +50,6 @@ import java.util.Map; * Decode BCF2 files */ public final class BCF2Codec implements FeatureCodec { - final protected static Logger logger = Logger.getLogger(BCF2Codec.class); - private final static int ALLOWED_MAJOR_VERSION = 2; private final static int MIN_MINOR_VERSION = 1; @@ -149,7 +147,9 @@ public final class BCF2Codec implements FeatureCodec { if ( bcfVersion.getMinorVersion() < MIN_MINOR_VERSION ) error("BCF2Codec can only process BCF2 files with minor version >= " + MIN_MINOR_VERSION + " but this file has minor version " + bcfVersion.getMinorVersion()); - logger.debug("Parsing data stream with BCF version " + bcfVersion); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("Parsing data stream with BCF version " + bcfVersion); + } final int headerSizeInBytes = BCF2Type.INT32.read(inputStream); diff --git a/public/java/src/org/broadinstitute/variant/bcf2/BCF2Decoder.java b/public/java/src/org/broadinstitute/variant/bcf2/BCF2Decoder.java index c3a1b5f15..b9970706b 100644 --- a/public/java/src/org/broadinstitute/variant/bcf2/BCF2Decoder.java +++ b/public/java/src/org/broadinstitute/variant/bcf2/BCF2Decoder.java @@ -27,9 +27,8 @@ package org.broadinstitute.variant.bcf2; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; -import org.broad.tribble.FeatureCodec; import org.broad.tribble.TribbleException; +import org.broadinstitute.variant.utils.GeneralUtils; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -38,8 +37,6 @@ import java.util.ArrayList; import java.util.Arrays; public final class BCF2Decoder { - final protected static Logger logger = Logger.getLogger(FeatureCodec.class); - byte[] recordBytes = null; ByteArrayInputStream recordStream = null; @@ -343,8 +340,9 @@ public final class BCF2Decoder { bytesRead += read1; } - if ( nReadAttempts > 1 ) // TODO -- remove me - logger.warn("Required multiple read attempts to actually get the entire BCF2 block, unexpected behavior"); + if ( GeneralUtils.DEBUG_MODE_ENABLED && nReadAttempts > 1 ) { // TODO -- remove me + System.err.println("Required multiple read attempts to actually get the entire BCF2 block, unexpected behavior"); + } validateReadBytes(bytesRead, nReadAttempts, blockSizeInBytes); } catch ( IOException e ) { diff --git a/public/java/src/org/broadinstitute/variant/bcf2/BCF2GenotypeFieldDecoders.java b/public/java/src/org/broadinstitute/variant/bcf2/BCF2GenotypeFieldDecoders.java index 1b624a1b8..87d676526 100644 --- a/public/java/src/org/broadinstitute/variant/bcf2/BCF2GenotypeFieldDecoders.java +++ b/public/java/src/org/broadinstitute/variant/bcf2/BCF2GenotypeFieldDecoders.java @@ -27,7 +27,6 @@ package org.broadinstitute.variant.bcf2; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.variant.variantcontext.Allele; @@ -46,7 +45,6 @@ import java.util.*; * @since 6/12 */ public class BCF2GenotypeFieldDecoders { - final protected static Logger logger = Logger.getLogger(BCF2GenotypeFieldDecoders.class); private final static boolean ENABLE_FASTPATH_GT = true; private final static int MIN_SAMPLES_FOR_FASTPATH_GENOTYPES = 0; // TODO -- update to reasonable number diff --git a/public/java/src/org/broadinstitute/variant/bcf2/BCF2LazyGenotypesDecoder.java b/public/java/src/org/broadinstitute/variant/bcf2/BCF2LazyGenotypesDecoder.java index bcd8e41d8..ffbfe81e6 100644 --- a/public/java/src/org/broadinstitute/variant/bcf2/BCF2LazyGenotypesDecoder.java +++ b/public/java/src/org/broadinstitute/variant/bcf2/BCF2LazyGenotypesDecoder.java @@ -26,7 +26,6 @@ package org.broadinstitute.variant.bcf2; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; import org.broad.tribble.TribbleException; import org.broadinstitute.variant.variantcontext.*; @@ -40,8 +39,6 @@ import java.util.*; * @since 5/12 */ public class BCF2LazyGenotypesDecoder implements LazyGenotypesContext.LazyParser { - final protected static Logger logger = Logger.getLogger(BCF2LazyGenotypesDecoder.class); - // the essential information for us to use to decode the genotypes data // initialized when this lazy decoder is created, as we know all of this from the BCF2Codec // and its stored here again for code cleanliness @@ -63,8 +60,6 @@ public class BCF2LazyGenotypesDecoder implements LazyGenotypesContext.LazyParser @Override public LazyGenotypesContext.LazyData parse(final Object data) { -// if ( logger.isDebugEnabled() ) -// logger.debug("Decoding BCF genotypes for " + nSamples + " samples with " + nFields + " fields each"); try { // load our byte[] data into the decoder diff --git a/public/java/src/org/broadinstitute/variant/utils/Utils.java b/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java similarity index 64% rename from public/java/src/org/broadinstitute/variant/utils/Utils.java rename to public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java index e61ce2ef3..79014a0eb 100644 --- a/public/java/src/org/broadinstitute/variant/utils/Utils.java +++ b/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java @@ -25,10 +25,18 @@ package org.broadinstitute.variant.utils; -import java.util.Collection; -import java.util.Iterator; +import java.util.*; -public class Utils { +/** + * Constants and utility methods used throughout the VCF/BCF/VariantContext classes + */ +public class GeneralUtils { + + /** + * Setting this to true causes the VCF/BCF/VariantContext classes to emit debugging information + * to standard error + */ + public static final boolean DEBUG_MODE_ENABLED = false; /** * The smallest log10 value we'll emit from normalizeFromLog10 and other functions @@ -66,7 +74,6 @@ public class Utils { } } - /** * normalizes the log10-based array. ASSUMES THAT ALL ARRAY ENTRIES ARE <= 0 (<= 1 IN REAL-SPACE). * @@ -134,10 +141,21 @@ public class Utils { return normalized; } + public static double sum(double[] values) { + double s = 0.0; + for (double v : values) + s += v; + return s; + } + public static double arrayMax(final double[] array) { return array[maxElementIndex(array, array.length)]; } + public static int maxElementIndex(final double[] array) { + return maxElementIndex(array, array.length); + } + public static int maxElementIndex(final double[] array, final int endIndex) { if (array == null || array.length == 0) throw new IllegalArgumentException("Array cannot be null!"); @@ -150,6 +168,82 @@ public class Utils { return maxI; } + + public static List cons(final T elt, final List l) { + List l2 = new ArrayList(); + l2.add(elt); + if (l != null) l2.addAll(l); + return l2; + } + + /** + * Make all combinations of N size of objects + * + * if objects = [A, B, C] + * if N = 1 => [[A], [B], [C]] + * if N = 2 => [[A, A], [B, A], [C, A], [A, B], [B, B], [C, B], [A, C], [B, C], [C, C]] + * + * @param objects + * @param n + * @param + * @param withReplacement if false, the resulting permutations will only contain unique objects from objects + * @return + */ + public static List> makePermutations(final List objects, final int n, final boolean withReplacement) { + final List> combinations = new ArrayList>(); + + if ( n <= 0 ) + ; + else if ( n == 1 ) { + for ( final T o : objects ) + combinations.add(Collections.singletonList(o)); + } else { + final List> sub = makePermutations(objects, n - 1, withReplacement); + for ( List subI : sub ) { + for ( final T a : objects ) { + if ( withReplacement || ! subI.contains(a) ) + combinations.add(cons(a, subI)); + } + } + } + + return combinations; + } + + /** + * Compares double values for equality (within 1e-6), or inequality. + * + * @param a the first double value + * @param b the second double value + * @return -1 if a is greater than b, 0 if a is equal to be within 1e-6, 1 if b is greater than a. + */ + public static byte compareDoubles(double a, double b) { + return compareDoubles(a, b, 1e-6); + } + + /** + * Compares double values for equality (within epsilon), or inequality. + * + * @param a the first double value + * @param b the second double value + * @param epsilon the precision within which two double values will be considered equal + * @return -1 if a is greater than b, 0 if a is equal to be within epsilon, 1 if b is greater than a. + */ + public static byte compareDoubles(double a, double b, double epsilon) { + if (Math.abs(a - b) < epsilon) { + return 0; + } + if (a > b) { + return -1; + } + return 1; + } + + static public final List reverse(final List l) { + final List newL = new ArrayList(l); + Collections.reverse(newL); + return newL; + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/collections/Pair.java b/public/java/src/org/broadinstitute/variant/utils/Pair.java similarity index 98% rename from public/java/src/org/broadinstitute/sting/utils/collections/Pair.java rename to public/java/src/org/broadinstitute/variant/utils/Pair.java index 4c00331a9..858d5fbd7 100644 --- a/public/java/src/org/broadinstitute/sting/utils/collections/Pair.java +++ b/public/java/src/org/broadinstitute/variant/utils/Pair.java @@ -23,7 +23,7 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.sting.utils.collections; +package org.broadinstitute.variant.utils; public class Pair { diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/GenotypeLikelihoods.java b/public/java/src/org/broadinstitute/variant/variantcontext/GenotypeLikelihoods.java index 7d804fd1b..1f6da6ecc 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/GenotypeLikelihoods.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/GenotypeLikelihoods.java @@ -28,7 +28,7 @@ package org.broadinstitute.variant.variantcontext; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import org.broad.tribble.TribbleException; -import org.broadinstitute.variant.utils.Utils; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.VCFConstants; import java.util.Arrays; @@ -155,7 +155,7 @@ public class GenotypeLikelihoods { //Returns null in case of missing likelihoods public EnumMap getAsMap(boolean normalizeFromLog10){ //Make sure that the log10likelihoods are set - double[] likelihoods = normalizeFromLog10 ? Utils.normalizeFromLog10(getAsVector()) : getAsVector(); + double[] likelihoods = normalizeFromLog10 ? GeneralUtils.normalizeFromLog10(getAsVector()) : getAsVector(); if(likelihoods == null) return null; EnumMap likelihoodsMap = new EnumMap(GenotypeType.class); @@ -215,7 +215,7 @@ public class GenotypeLikelihoods { if (qual < 0) { // QUAL can be negative if the chosen genotype is not the most likely one individually. // In this case, we compute the actual genotype probability and QUAL is the likelihood of it not being the chosen one - double[] normalized = Utils.normalizeFromLog10(likelihoods); + double[] normalized = GeneralUtils.normalizeFromLog10(likelihoods); double chosenGenotype = normalized[iOfChoosenGenotype]; return Math.log10(1.0 - chosenGenotype); } else { diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java index 003877088..05edee153 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java @@ -25,10 +25,10 @@ package org.broadinstitute.variant.variantcontext; -import org.apache.log4j.Logger; import org.broad.tribble.Feature; import org.broad.tribble.TribbleException; import org.broad.tribble.util.ParsingUtils; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; import java.util.*; @@ -202,7 +202,6 @@ import java.util.*; public class VariantContext implements Feature { // to enable tribble integration private final static boolean WARN_ABOUT_BAD_END = true; private final static int MAX_ALLELE_SIZE_FOR_NON_SV = 150; - final protected static Logger logger = Logger.getLogger(VariantContext.class); private boolean fullyDecoded = false; protected CommonInfo commonInfo = null; public final static double NO_LOG10_PERROR = CommonInfo.NO_LOG10_PERROR; @@ -1176,10 +1175,12 @@ public class VariantContext implements Feature { // to enable tribble integratio final String message = "Badly formed variant context at location " + getChr() + ":" + getStart() + "; getEnd() was " + getEnd() + " but this VariantContext contains an END key with value " + end; - if ( WARN_ABOUT_BAD_END ) - logger.warn(message); - else + if ( GeneralUtils.DEBUG_MODE_ENABLED && WARN_ABOUT_BAD_END ) { + System.err.println(message); + } + else { throw new TribbleException(message); + } } } else { final long length = (stop - start) + 1; diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index b2f41d43b..fb97d41ff 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -29,24 +29,27 @@ import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import org.apache.commons.jexl2.Expression; import org.apache.commons.jexl2.JexlEngine; -import org.apache.log4j.Logger; +import org.apache.commons.lang.ArrayUtils; import org.broad.tribble.TribbleException; import org.broad.tribble.util.popgen.HardyWeinbergCalculation; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Utils; +import org.broadinstitute.variant.utils.GeneralUtils; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.vcf.*; import java.io.Serializable; import java.util.*; public class VariantContextUtils { - private static Logger logger = Logger.getLogger(VariantContextUtils.class); public final static String MERGE_INTERSECTION = "Intersection"; public final static String MERGE_FILTER_IN_ALL = "FilteredInAll"; public final static String MERGE_REF_IN_ALL = "ReferenceInAll"; public final static String MERGE_FILTER_PREFIX = "filterIn"; + public static final int DEFAULT_PLOIDY = 2; + public static final double SUM_GL_THRESH_NOCALL = -0.1; // if sum(gl) is bigger than this threshold, we treat GL's as non-informative and will force a no-call. private static Set MISSING_KEYS_WARNED_ABOUT = new HashSet(); + private static final List NO_CALL_ALLELES = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL); final public static JexlEngine engine = new JexlEngine(); private final static boolean ASSUME_MISSING_FIELDS_ARE_STRINGS = false; @@ -166,7 +169,8 @@ public class VariantContextUtils { if ( ASSUME_MISSING_FIELDS_ARE_STRINGS ) { if ( ! MISSING_KEYS_WARNED_ABOUT.contains(field) ) { MISSING_KEYS_WARNED_ABOUT.add(field); - logger.warn("Field " + field + " missing from VCF header, assuming it is an unbounded string type"); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) + System.err.println("Field " + field + " missing from VCF header, assuming it is an unbounded string type"); } return new VCFInfoHeaderLine(field, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Auto-generated string header for " + field); } @@ -176,6 +180,428 @@ public class VariantContextUtils { return metaData; } + /** + * Returns true iff VC is an non-complex indel where every allele represents an expansion or + * contraction of a series of identical bases in the reference. + * + * For example, suppose the ref bases are CTCTCTGA, which includes a 3x repeat of CTCTCT + * + * If VC = -/CT, then this function returns true because the CT insertion matches exactly the + * upcoming reference. + * If VC = -/CTA then this function returns false because the CTA isn't a perfect match + * + * Now consider deletions: + * + * If VC = CT/- then again the same logic applies and this returns true + * The case of CTA/- makes no sense because it doesn't actually match the reference bases. + * + * The logic of this function is pretty simple. Take all of the non-null alleles in VC. For + * each insertion allele of n bases, check if that allele matches the next n reference bases. + * For each deletion allele of n bases, check if this matches the reference bases at n - 2 n, + * as it must necessarily match the first n bases. If this test returns true for all + * alleles you are a tandem repeat, otherwise you are not. + * + * @param vc + * @param refBasesStartingAtVCWithPad not this is assumed to include the PADDED reference + * @return + */ + @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) + public static boolean isTandemRepeat(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { + final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); + if ( ! vc.isIndel() ) // only indels are tandem repeats + return false; + + final Allele ref = vc.getReference(); + + for ( final Allele allele : vc.getAlternateAlleles() ) { + if ( ! isRepeatAllele(ref, allele, refBasesStartingAtVCWithoutPad) ) + return false; + } + + // we've passed all of the tests, so we are a repeat + return true; + } + + /** + * + * @param vc + * @param refBasesStartingAtVCWithPad + * @return + */ + @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) + public static Pair,byte[]> getNumTandemRepeatUnits(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { + final boolean VERBOSE = false; + final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); + if ( ! vc.isIndel() ) // only indels are tandem repeats + return null; + + final Allele refAllele = vc.getReference(); + final byte[] refAlleleBases = Arrays.copyOfRange(refAllele.getBases(), 1, refAllele.length()); + + byte[] repeatUnit = null; + final ArrayList lengths = new ArrayList(); + + for ( final Allele allele : vc.getAlternateAlleles() ) { + Pair result = getNumTandemRepeatUnits(refAlleleBases, Arrays.copyOfRange(allele.getBases(), 1, allele.length()), refBasesStartingAtVCWithoutPad.getBytes()); + + final int[] repetitionCount = result.first; + // repetition count = 0 means allele is not a tandem expansion of context + if (repetitionCount[0] == 0 || repetitionCount[1] == 0) + return null; + + if (lengths.size() == 0) { + lengths.add(repetitionCount[0]); // add ref allele length only once + } + lengths.add(repetitionCount[1]); // add this alt allele's length + + repeatUnit = result.second; + if (VERBOSE) { + System.out.println("RefContext:"+refBasesStartingAtVCWithoutPad); + System.out.println("Ref:"+refAllele.toString()+" Count:" + String.valueOf(repetitionCount[0])); + System.out.println("Allele:"+allele.toString()+" Count:" + String.valueOf(repetitionCount[1])); + System.out.println("RU:"+new String(repeatUnit)); + } + } + + return new Pair, byte[]>(lengths,repeatUnit); + } + + protected static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { + /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units. + Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)5. + */ + + byte[] longB; + // find first repeat unit based on either ref or alt, whichever is longer + if (altBases.length > refBases.length) + longB = altBases; + else + longB = refBases; + + // see if non-null allele (either ref or alt, whichever is longer) can be decomposed into several identical tandem units + // for example, -*,CACA needs to first be decomposed into (CA)2 + final int repeatUnitLength = findRepeatedSubstring(longB); + final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength); + + final int[] repetitionCount = new int[2]; +// repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext)); +// repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext)); + int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases); + repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext))-repetitionsInRef; + repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext))-repetitionsInRef; + + return new Pair(repetitionCount, repeatUnit); + + } + + /** + * Find out if a string can be represented as a tandem number of substrings. + * For example ACTACT is a 2-tandem of ACT, + * but ACTACA is not. + * + * @param bases String to be tested + * @return Length of repeat unit, if string can be represented as tandem of substring (if it can't + * be represented as one, it will be just the length of the input string) + */ + public static int findRepeatedSubstring(byte[] bases) { + + int repLength; + for (repLength=1; repLength <=bases.length; repLength++) { + final byte[] candidateRepeatUnit = Arrays.copyOf(bases,repLength); + boolean allBasesMatch = true; + for (int start = repLength; start < bases.length; start += repLength ) { + // check that remaining of string is exactly equal to repeat unit + final byte[] basePiece = Arrays.copyOfRange(bases,start,start+candidateRepeatUnit.length); + if (!Arrays.equals(candidateRepeatUnit, basePiece)) { + allBasesMatch = false; + break; + } + } + if (allBasesMatch) + return repLength; + } + + return repLength; + } + + /** + * Helper routine that finds number of repetitions a string consists of. + * For example, for string ATAT and repeat unit AT, number of repetitions = 2 + * @param repeatUnit Substring + * @param testString String to test + * @return Number of repetitions (0 if testString is not a concatenation of n repeatUnit's + */ + public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString) { + int numRepeats = 0; + for (int start = 0; start < testString.length; start += repeatUnit.length) { + int end = start + repeatUnit.length; + byte[] unit = Arrays.copyOfRange(testString,start, end); + if(Arrays.equals(unit,repeatUnit)) + numRepeats++; + else + return numRepeats; + } + return numRepeats; + } + + /** + * Helper function for isTandemRepeat that checks that allele matches somewhere on the reference + * @param ref + * @param alt + * @param refBasesStartingAtVCWithoutPad + * @return + */ + protected static boolean isRepeatAllele(final Allele ref, final Allele alt, final String refBasesStartingAtVCWithoutPad) { + if ( ! Allele.oneIsPrefixOfOther(ref, alt) ) + return false; // we require one allele be a prefix of another + + if ( ref.length() > alt.length() ) { // we are a deletion + return basesAreRepeated(ref.getBaseString(), alt.getBaseString(), refBasesStartingAtVCWithoutPad, 2); + } else { // we are an insertion + return basesAreRepeated(alt.getBaseString(), ref.getBaseString(), refBasesStartingAtVCWithoutPad, 1); + } + } + + protected static boolean basesAreRepeated(final String l, final String s, final String ref, final int minNumberOfMatches) { + final String potentialRepeat = l.substring(s.length()); // skip s bases + + for ( int i = 0; i < minNumberOfMatches; i++) { + final int start = i * potentialRepeat.length(); + final int end = (i+1) * potentialRepeat.length(); + if ( ref.length() < end ) + return false; // we ran out of bases to test + final String refSub = ref.substring(start, end); + if ( ! refSub.equals(potentialRepeat) ) + return false; // repeat didn't match, fail + } + + return true; // we passed all tests, we matched + } + + /** + * Assign genotypes (GTs) to the samples in the Variant Context greedily based on the PLs + * + * @param vc variant context with genotype likelihoods + * @return genotypes context + */ + public static GenotypesContext assignDiploidGenotypes(final VariantContext vc) { + return subsetDiploidAlleles(vc, vc.getAlleles(), true); + } + + /** + * Split variant context into its biallelic components if there are more than 2 alleles + * + * For VC has A/B/C alleles, returns A/B and A/C contexts. + * Genotypes are all no-calls now (it's not possible to fix them easily) + * Alleles are right trimmed to satisfy VCF conventions + * + * If vc is biallelic or non-variant it is just returned + * + * Chromosome counts are updated (but they are by definition 0) + * + * @param vc a potentially multi-allelic variant context + * @return a list of bi-allelic (or monomorphic) variant context + */ + public static List splitVariantContextToBiallelics(final VariantContext vc) { + if ( ! vc.isVariant() || vc.isBiallelic() ) + // non variant or biallelics already satisfy the contract + return Collections.singletonList(vc); + else { + final List biallelics = new LinkedList(); + + for ( final Allele alt : vc.getAlternateAlleles() ) { + VariantContextBuilder builder = new VariantContextBuilder(vc); + final List alleles = Arrays.asList(vc.getReference(), alt); + builder.alleles(alleles); + builder.genotypes(subsetDiploidAlleles(vc, alleles, false)); + calculateChromosomeCounts(builder, true); + biallelics.add(reverseTrimAlleles(builder.make())); + } + + return biallelics; + } + } + + /** + * subset the Variant Context to the specific set of alleles passed in (pruning the PLs appropriately) + * + * @param vc variant context with genotype likelihoods + * @param allelesToUse which alleles from the vc are okay to use; *** must be in the same relative order as those in the original VC *** + * @param assignGenotypes true if we should update the genotypes based on the (subsetted) PLs + * @return genotypes + */ + public static GenotypesContext subsetDiploidAlleles(final VariantContext vc, + final List allelesToUse, + final boolean assignGenotypes) { + + // the genotypes with PLs + final GenotypesContext oldGTs = vc.getGenotypes(); + + // samples + final List sampleIndices = oldGTs.getSampleNamesOrderedByName(); + + // the new genotypes to create + final GenotypesContext newGTs = GenotypesContext.create(); + + // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward + final int numOriginalAltAlleles = vc.getAlternateAlleles().size(); + final int numNewAltAlleles = allelesToUse.size() - 1; + + // which PLs should be carried forward? + ArrayList likelihoodIndexesToUse = null; + + // an optimization: if we are supposed to use all (or none in the case of a ref call) of the alleles, + // then we can keep the PLs as is; otherwise, we determine which ones to keep + if ( numNewAltAlleles != numOriginalAltAlleles && numNewAltAlleles > 0 ) { + likelihoodIndexesToUse = new ArrayList(30); + + final boolean[] altAlleleIndexToUse = new boolean[numOriginalAltAlleles]; + for ( int i = 0; i < numOriginalAltAlleles; i++ ) { + if ( allelesToUse.contains(vc.getAlternateAllele(i)) ) + altAlleleIndexToUse[i] = true; + } + + // numLikelihoods takes total # of alleles. Use default # of chromosomes (ploidy) = 2 + final int numLikelihoods = GenotypeLikelihoods.numLikelihoods(1 + numOriginalAltAlleles, DEFAULT_PLOIDY); + for ( int PLindex = 0; PLindex < numLikelihoods; PLindex++ ) { + final GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); + // consider this entry only if both of the alleles are good + if ( (alleles.alleleIndex1 == 0 || altAlleleIndexToUse[alleles.alleleIndex1 - 1]) && (alleles.alleleIndex2 == 0 || altAlleleIndexToUse[alleles.alleleIndex2 - 1]) ) + likelihoodIndexesToUse.add(PLindex); + } + } + + // create the new genotypes + for ( int k = 0; k < oldGTs.size(); k++ ) { + final Genotype g = oldGTs.get(sampleIndices.get(k)); + if ( !g.hasLikelihoods() ) { + newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); + continue; + } + + // create the new likelihoods array from the alleles we are allowed to use + final double[] originalLikelihoods = g.getLikelihoods().getAsVector(); + double[] newLikelihoods; + if ( likelihoodIndexesToUse == null ) { + newLikelihoods = originalLikelihoods; + } else { + newLikelihoods = new double[likelihoodIndexesToUse.size()]; + int newIndex = 0; + for ( int oldIndex : likelihoodIndexesToUse ) + newLikelihoods[newIndex++] = originalLikelihoods[oldIndex]; + + // might need to re-normalize + newLikelihoods = GeneralUtils.normalizeFromLog10(newLikelihoods, false, true); + } + + // if there is no mass on the (new) likelihoods, then just no-call the sample + if ( GeneralUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { + newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); + } + else { + final GenotypeBuilder gb = new GenotypeBuilder(g); + + if ( numNewAltAlleles == 0 ) + gb.noPL(); + else + gb.PL(newLikelihoods); + + // if we weren't asked to assign a genotype, then just no-call the sample + if ( !assignGenotypes || GeneralUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { + gb.alleles(NO_CALL_ALLELES); + } + else { + // find the genotype with maximum likelihoods + int PLindex = numNewAltAlleles == 0 ? 0 : GeneralUtils.maxElementIndex(newLikelihoods); + GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); + + gb.alleles(Arrays.asList(allelesToUse.get(alleles.alleleIndex1), allelesToUse.get(alleles.alleleIndex2))); + if ( numNewAltAlleles != 0 ) gb.log10PError(GenotypeLikelihoods.getGQLog10FromLikelihoods(PLindex, newLikelihoods)); + } + newGTs.add(gb.make()); + } + } + + return newGTs; + } + + public static VariantContext reverseTrimAlleles( final VariantContext inputVC ) { + + // see whether we need to trim common reference base from all alleles + final int trimExtent = computeReverseClipping(inputVC.getAlleles(), inputVC.getReference().getDisplayString().getBytes(), 0, false); + if ( trimExtent <= 0 || inputVC.getAlleles().size() <= 1 ) + return inputVC; + + final List alleles = new ArrayList(); + final GenotypesContext genotypes = GenotypesContext.create(); + final Map originalToTrimmedAlleleMap = new HashMap(); + + for (final Allele a : inputVC.getAlleles()) { + if (a.isSymbolic()) { + alleles.add(a); + originalToTrimmedAlleleMap.put(a, a); + } else { + // get bases for current allele and create a new one with trimmed bases + final byte[] newBases = Arrays.copyOfRange(a.getBases(), 0, a.length()-trimExtent); + final Allele trimmedAllele = Allele.create(newBases, a.isReference()); + alleles.add(trimmedAllele); + originalToTrimmedAlleleMap.put(a, trimmedAllele); + } + } + + // now we can recreate new genotypes with trimmed alleles + for ( final Genotype genotype : inputVC.getGenotypes() ) { + final List originalAlleles = genotype.getAlleles(); + final List trimmedAlleles = new ArrayList(); + for ( final Allele a : originalAlleles ) { + if ( a.isCalled() ) + trimmedAlleles.add(originalToTrimmedAlleleMap.get(a)); + else + trimmedAlleles.add(Allele.NO_CALL); + } + genotypes.add(new GenotypeBuilder(genotype).alleles(trimmedAlleles).make()); + } + + return new VariantContextBuilder(inputVC).stop(inputVC.getStart() + alleles.get(0).length() - 1).alleles(alleles).genotypes(genotypes).make(); + } + + public static int computeReverseClipping(final List unclippedAlleles, + final byte[] ref, + final int forwardClipping, + final boolean allowFullClip) { + int clipping = 0; + boolean stillClipping = true; + + while ( stillClipping ) { + for ( final Allele a : unclippedAlleles ) { + if ( a.isSymbolic() ) + continue; + + // we need to ensure that we don't reverse clip out all of the bases from an allele because we then will have the wrong + // position set for the VariantContext (although it's okay to forward clip it all out, because the position will be fine). + if ( a.length() - clipping == 0 ) + return clipping - (allowFullClip ? 0 : 1); + + if ( a.length() - clipping <= forwardClipping || a.length() - forwardClipping == 0 ) { + stillClipping = false; + } + else if ( ref.length == clipping ) { + if ( allowFullClip ) + stillClipping = false; + else + return -1; + } + else if ( a.getBases()[a.length()-clipping-1] != ref[ref.length-clipping-1] ) { + stillClipping = false; + } + } + if ( stillClipping ) + clipping++; + } + + return clipping; + } + /** * A simple but common wrapper for matching VariantContext objects using JEXL expressions */ @@ -602,9 +1028,10 @@ public class VariantContextUtils { if (vc.alleles.size() == 1) continue; if ( hasPLIncompatibleAlleles(alleles, vc.alleles)) { - if ( ! genotypes.isEmpty() ) - logger.debug(String.format("Stripping PLs at %s:%d-%d due to incompatible alleles merged=%s vs. single=%s", - vc.getChr(), vc.getStart(), vc.getEnd(), alleles, vc.alleles)); + if ( GeneralUtils.DEBUG_MODE_ENABLED && ! genotypes.isEmpty() ) { + System.err.println(String.format("Stripping PLs at %s:%d-%d due to incompatible alleles merged=%s vs. single=%s", + vc.getChr(), vc.getStart(), vc.getEnd(), alleles, vc.alleles)); + } genotypes = stripPLsAndAD(genotypes); // this will remove stale AC,AF attributed from vc calculateChromosomeCounts(vc, attributes, true); @@ -635,7 +1062,7 @@ public class VariantContextUtils { for ( final VariantContext vc : VCs ) if ( vc.isVariant() ) s.add( vc.isFiltered() ? MERGE_FILTER_PREFIX + vc.getSource() : vc.getSource() ); - setValue = Utils.join("-", s); + setValue = GeneralUtils.join("-", s); } if ( setKey != null ) { @@ -649,7 +1076,7 @@ public class VariantContextUtils { if ( depth > 0 ) attributes.put(VCFConstants.DEPTH_KEY, String.valueOf(depth)); - final String ID = rsIDs.isEmpty() ? VCFConstants.EMPTY_ID_FIELD : Utils.join(",", rsIDs); + final String ID = rsIDs.isEmpty() ? VCFConstants.EMPTY_ID_FIELD : GeneralUtils.join(",", rsIDs); final VariantContextBuilder builder = new VariantContextBuilder().source(name).id(ID); builder.loc(longestVC.getChr(), longestVC.getStart(), longestVC.getEnd()); diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantJEXLContext.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantJEXLContext.java index 2df3e3227..efdd54b57 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantJEXLContext.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantJEXLContext.java @@ -27,7 +27,7 @@ package org.broadinstitute.variant.variantcontext; import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.MapContext; -import org.broadinstitute.variant.utils.Utils; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.VCFConstants; import java.util.Collection; @@ -168,7 +168,7 @@ class JEXLMap implements Map { infoMap.put("QUAL", String.valueOf(vc.getPhredScaledQual())); // add alleles - infoMap.put("ALLELES", Utils.join(";", vc.getAlleles())); + infoMap.put("ALLELES", GeneralUtils.join(";", vc.getAlleles())); infoMap.put("N_ALLELES", String.valueOf(vc.getNAlleles())); // add attributes diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2FieldWriterManager.java b/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2FieldWriterManager.java index c80f83855..a3cbc5bf3 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2FieldWriterManager.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2FieldWriterManager.java @@ -27,7 +27,7 @@ package org.broadinstitute.variant.variantcontext.writer; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; import java.util.HashMap; @@ -40,7 +40,6 @@ import java.util.Map; * @since 06/12 */ public class BCF2FieldWriterManager { - final protected static Logger logger = Logger.getLogger(BCF2FieldWriterManager.class); final Map siteWriters = new HashMap(); final Map genotypesWriters = new HashMap(); final IntGenotypeFieldAccessors intGenotypeFieldAccessors = new IntGenotypeFieldAccessors(); @@ -98,8 +97,8 @@ public class BCF2FieldWriterManager { final boolean createGenotypesEncoders ) { if ( createGenotypesEncoders && intGenotypeFieldAccessors.getAccessor(line.getID()) != null ) { - if ( line.getType() != VCFHeaderLineType.Integer ) - logger.warn("Warning: field " + line.getID() + " expected to encode an integer but saw " + line.getType() + " for record " + line); + if ( GeneralUtils.DEBUG_MODE_ENABLED && line.getType() != VCFHeaderLineType.Integer ) + System.err.println("Warning: field " + line.getID() + " expected to encode an integer but saw " + line.getType() + " for record " + line); return new BCF2FieldEncoder.IntArray(line, dict); } else if ( createGenotypesEncoders && line.getID().equals(VCFConstants.GENOTYPE_KEY) ) { return new BCF2FieldEncoder.GenericInts(line, dict); diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2Writer.java b/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2Writer.java index e01a39cfb..c24ffec48 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2Writer.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/writer/BCF2Writer.java @@ -28,11 +28,11 @@ package org.broadinstitute.variant.variantcontext.writer; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.samtools.SAMSequenceDictionary; -import org.apache.log4j.Logger; import org.broadinstitute.variant.bcf2.BCF2Codec; import org.broadinstitute.variant.bcf2.BCF2Type; import org.broadinstitute.variant.bcf2.BCF2Utils; import org.broadinstitute.variant.bcf2.BCFVersion; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.variant.vcf.VCFContigHeaderLine; import org.broadinstitute.variant.vcf.VCFHeader; @@ -89,7 +89,6 @@ class BCF2Writer extends IndexingVariantContextWriter { public static final int MAJOR_VERSION = 2; public static final int MINOR_VERSION = 1; - final protected static Logger logger = Logger.getLogger(BCF2Writer.class); final private static boolean ALLOW_MISSING_CONTIG_LINES = false; private final OutputStream outputStream; // Note: do not flush until completely done writing, to avoid issues with eventual BGZF support @@ -129,7 +128,9 @@ class BCF2Writer extends IndexingVariantContextWriter { // create the config offsets map if ( header.getContigLines().isEmpty() ) { if ( ALLOW_MISSING_CONTIG_LINES ) { - logger.warn("No contig dictionary found in header, falling back to reference sequence dictionary"); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("No contig dictionary found in header, falling back to reference sequence dictionary"); + } createContigDictionary(VCFUtils.makeContigHeaderLines(getRefDict(), null)); } else { throw new IllegalStateException("Cannot write BCF2 file with missing contig lines"); @@ -275,10 +276,8 @@ class BCF2Writer extends IndexingVariantContextWriter { if ( lgc.getUnparsedGenotypeData() instanceof BCF2Codec.LazyData && canSafelyWriteRawGenotypesBytes((BCF2Codec.LazyData) lgc.getUnparsedGenotypeData())) { - //logger.info("Passing on raw BCF2 genotypes data"); return (BCF2Codec.LazyData)lgc.getUnparsedGenotypeData(); } else { - //logger.info("Decoding raw BCF2 genotypes data"); lgc.decode(); // WARNING -- required to avoid keeping around bad lazy data for too long } } diff --git a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java index 8ad79364b..11d152e65 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java +++ b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java @@ -25,7 +25,6 @@ package org.broadinstitute.variant.vcf; -import org.apache.log4j.Logger; import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; import org.broad.tribble.NameAwareCodec; @@ -33,6 +32,7 @@ import org.broad.tribble.TribbleException; import org.broad.tribble.readers.LineReader; import org.broad.tribble.util.BlockCompressedInputStream; import org.broad.tribble.util.ParsingUtils; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.variantcontext.*; import java.io.FileInputStream; @@ -46,7 +46,6 @@ import java.util.zip.GZIPInputStream; public abstract class AbstractVCFCodec extends AsciiFeatureCodec implements NameAwareCodec { public final static int MAX_ALLELE_SIZE_BEFORE_WARNING = (int)Math.pow(2, 20); - protected final static Logger log = Logger.getLogger(AbstractVCFCodec.class); protected final static int NUM_STANDARD_FIELDS = 8; // INFO is the 8th column // we have to store the list of strings that make up the header until they're needed @@ -397,9 +396,9 @@ public abstract class AbstractVCFCodec extends AsciiFeatureCodec key = infoFieldArray[i]; final VCFInfoHeaderLine headerLine = header.getInfoHeaderLine(key); if ( headerLine != null && headerLine.getType() != VCFHeaderLineType.Flag ) { - if ( ! warnedAboutNoEqualsForNonFlag ) { - log.warn("Found info key " + key + " without a = value, but the header says the field is of type " - + headerLine.getType() + " but this construct is only value for FLAG type fields"); + if ( GeneralUtils.DEBUG_MODE_ENABLED && ! warnedAboutNoEqualsForNonFlag ) { + System.err.println("Found info key " + key + " without a = value, but the header says the field is of type " + + headerLine.getType() + " but this construct is only value for FLAG type fields"); warnedAboutNoEqualsForNonFlag = true; } @@ -517,8 +516,9 @@ public abstract class AbstractVCFCodec extends AsciiFeatureCodec if ( allele == null || allele.length() == 0 ) generateException("Empty alleles are not permitted in VCF records", lineNo); - if ( MAX_ALLELE_SIZE_BEFORE_WARNING != -1 && allele.length() > MAX_ALLELE_SIZE_BEFORE_WARNING ) - log.warn(String.format("Allele detected with length %d exceeding max size %d at approximately line %d, likely resulting in degraded VCF processing performance", allele.length(), MAX_ALLELE_SIZE_BEFORE_WARNING, lineNo)); + if ( GeneralUtils.DEBUG_MODE_ENABLED && MAX_ALLELE_SIZE_BEFORE_WARNING != -1 && allele.length() > MAX_ALLELE_SIZE_BEFORE_WARNING ) { + System.err.println(String.format("Allele detected with length %d exceeding max size %d at approximately line %d, likely resulting in degraded VCF processing performance", allele.length(), MAX_ALLELE_SIZE_BEFORE_WARNING, lineNo)); + } if ( isSymbolicAllele(allele) ) { if ( isRef ) { diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFCompoundHeaderLine.java b/public/java/src/org/broadinstitute/variant/vcf/VCFCompoundHeaderLine.java index 7aa378642..3fc790f80 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFCompoundHeaderLine.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFCompoundHeaderLine.java @@ -25,8 +25,8 @@ package org.broadinstitute.variant.vcf; -import org.apache.log4j.Logger; import org.broad.tribble.TribbleException; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.variantcontext.GenotypeLikelihoods; import org.broadinstitute.variant.variantcontext.VariantContext; @@ -38,7 +38,6 @@ import java.util.Map; * a base class for compound header lines, which include info lines and format lines (so far) */ public abstract class VCFCompoundHeaderLine extends VCFHeaderLine implements VCFIDHeaderLine { - final protected static Logger logger = Logger.getLogger(VCFHeader.class); public enum SupportedHeaderLineType { INFO(true), FORMAT(false); @@ -197,7 +196,9 @@ public abstract class VCFCompoundHeaderLine extends VCFHeaderLine implements VCF if ( type == VCFHeaderLineType.Flag && count != 0 ) { count = 0; - logger.warn("FLAG fields must have a count value of 0, but saw " + count + " for header line " + getID() + ". Changing it to 0 inside the code"); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("FLAG fields must have a count value of 0, but saw " + count + " for header line " + getID() + ". Changing it to 0 inside the code"); + } } } diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java b/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java index 9bdb86a48..9d4c4d576 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFHeader.java @@ -25,9 +25,9 @@ package org.broadinstitute.variant.vcf; -import org.apache.log4j.Logger; import org.broad.tribble.TribbleException; import org.broad.tribble.util.ParsingUtils; +import org.broadinstitute.variant.utils.GeneralUtils; import java.util.*; @@ -45,7 +45,6 @@ import java.util.*; * A class representing the VCF header */ public class VCFHeader { - final protected static Logger logger = Logger.getLogger(VCFHeader.class); // the mandatory header fields public enum HEADER_FIELDS { @@ -238,9 +237,11 @@ public class VCFHeader { } if ( hasFormatLine(VCFConstants.GENOTYPE_LIKELIHOODS_KEY) && ! hasFormatLine(VCFConstants.GENOTYPE_PL_KEY) ) { - logger.warn("Found " + VCFConstants.GENOTYPE_LIKELIHOODS_KEY + " format, but no " - + VCFConstants.GENOTYPE_PL_KEY + " field. We now only manage PL fields internally" - + " automatically adding a corresponding PL field to your VCF header"); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("Found " + VCFConstants.GENOTYPE_LIKELIHOODS_KEY + " format, but no " + + VCFConstants.GENOTYPE_PL_KEY + " field. We now only manage PL fields internally" + + " automatically adding a corresponding PL field to your VCF header"); + } addMetaDataLine(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_PL_KEY, VCFHeaderLineCount.G, VCFHeaderLineType.Integer, "Normalized, Phred-scaled likelihoods for genotypes as defined in the VCF specification")); } } @@ -254,10 +255,14 @@ public class VCFHeader { */ private final void addMetaDataMapBinding(final Map map, T line) { final String key = line.getID(); - if ( map.containsKey(key) ) - logger.debug("Found duplicate VCF header lines for " + key + "; keeping the first only" ); - else + if ( map.containsKey(key) ) { + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("Found duplicate VCF header lines for " + key + "; keeping the first only" ); + } + } + else { map.put(key, line); + } } /** diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFStandardHeaderLines.java b/public/java/src/org/broadinstitute/variant/vcf/VCFStandardHeaderLines.java index b6f982193..d289c679e 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFStandardHeaderLines.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFStandardHeaderLines.java @@ -27,8 +27,8 @@ package org.broadinstitute.variant.vcf; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.apache.log4j.Logger; import org.broad.tribble.TribbleException; +import org.broadinstitute.variant.utils.GeneralUtils; import java.util.*; @@ -46,7 +46,6 @@ public class VCFStandardHeaderLines { * Enabling this causes us to repair header lines even if only their descriptions differ */ private final static boolean REPAIR_BAD_DESCRIPTIONS = false; - protected final static Logger logger = Logger.getLogger(VCFStandardHeaderLines.class); private static Standards formatStandards = new Standards(); private static Standards infoStandards = new Standards(); @@ -216,11 +215,13 @@ public class VCFStandardHeaderLines { final boolean needsRepair = badCountType || badCount || badType || (REPAIR_BAD_DESCRIPTIONS && badDesc); if ( needsRepair ) { - logger.warn("Repairing standard header line for field " + line.getID() + " because" - + (badCountType ? " -- count types disagree; header has " + line.getCountType() + " but standard is " + standard.getCountType() : "") - + (badType ? " -- type disagree; header has " + line.getType() + " but standard is " + standard.getType() : "") - + (badCount ? " -- counts disagree; header has " + line.getCount() + " but standard is " + standard.getCount() : "") - + (badDesc ? " -- descriptions disagree; header has '" + line.getDescription() + "' but standard is '" + standard.getDescription() + "'": "")); + if ( GeneralUtils.DEBUG_MODE_ENABLED ) { + System.err.println("Repairing standard header line for field " + line.getID() + " because" + + (badCountType ? " -- count types disagree; header has " + line.getCountType() + " but standard is " + standard.getCountType() : "") + + (badType ? " -- type disagree; header has " + line.getType() + " but standard is " + standard.getType() : "") + + (badCount ? " -- counts disagree; header has " + line.getCount() + " but standard is " + standard.getCount() : "") + + (badDesc ? " -- descriptions disagree; header has '" + line.getDescription() + "' but standard is '" + standard.getDescription() + "'": "")); + } return standard; } else return line; diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java b/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java index f7d4c5b45..db2d47609 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java @@ -28,17 +28,22 @@ package org.broadinstitute.variant.vcf; import net.sf.samtools.SAMSequenceDictionary; import net.sf.samtools.SAMSequenceRecord; import org.apache.commons.io.FilenameUtils; -import org.apache.log4j.Logger; +import org.broad.tribble.FeatureCodecHeader; +import org.broad.tribble.readers.PositionalBufferedStream; +import org.broadinstitute.variant.utils.GeneralUtils; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.*; public class VCFUtils { - public static Set smartMergeHeaders(Collection headers, Logger logger) throws IllegalStateException { + public static Set smartMergeHeaders(Collection headers, boolean emitWarnings) throws IllegalStateException { HashMap map = new HashMap(); // from KEY.NAME -> line - HeaderConflictWarner conflictWarner = new HeaderConflictWarner(logger); + HeaderConflictWarner conflictWarner = new HeaderConflictWarner(emitWarnings); // todo -- needs to remove all version headers from sources and add its own VCF version line for ( VCFHeader source : headers ) { @@ -193,19 +198,48 @@ public class VCFUtils { return assembly; } - /** Only displays a warning if a logger is provided and an identical warning hasn't been already issued */ + /** + * Read all of the VCF records from source into memory, returning the header and the VariantContexts + * + * @param source the file to read, must be in VCF4 format + * @return + * @throws java.io.IOException + */ + public static Pair> readVCF(final File source) throws IOException { + // read in the features + final List vcs = new ArrayList(); + final VCFCodec codec = new VCFCodec(); + PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); + FeatureCodecHeader header = codec.readHeader(pbs); + pbs.close(); + + pbs = new PositionalBufferedStream(new FileInputStream(source)); + pbs.skip(header.getHeaderEnd()); + + final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue(); + + while ( ! pbs.isDone() ) { + final VariantContext vc = codec.decode(pbs); + if ( vc != null ) + vcs.add(vc); + } + + return new Pair>(vcfHeader, vcs); + } + + /** Only displays a warning if warnings are enabled and an identical warning hasn't been already issued */ private static final class HeaderConflictWarner { - Logger logger; + boolean emitWarnings; Set alreadyIssued = new HashSet(); - private HeaderConflictWarner(final Logger logger) { - this.logger = logger; + private HeaderConflictWarner( final boolean emitWarnings ) { + this.emitWarnings = emitWarnings; } public void warn(final VCFHeaderLine line, final String msg) { - if ( logger != null && ! alreadyIssued.contains(line.getKey()) ) { + if ( GeneralUtils.DEBUG_MODE_ENABLED && emitWarnings && ! alreadyIssued.contains(line.getKey()) ) { alreadyIssued.add(line.getKey()); - logger.warn(msg); + System.err.println(msg); } } } diff --git a/public/java/test/org/broadinstitute/sting/WalkerTest.java b/public/java/test/org/broadinstitute/sting/WalkerTest.java index 9e4612de5..6c0a18f1d 100644 --- a/public/java/test/org/broadinstitute/sting/WalkerTest.java +++ b/public/java/test/org/broadinstitute/sting/WalkerTest.java @@ -35,8 +35,8 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.variant.bcf2.BCF2Utils; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.vcf.VCFCodec; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; diff --git a/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java index c81043f90..a56045165 100644 --- a/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java @@ -25,11 +25,9 @@ package org.broadinstitute.sting.utils; -import cern.jet.math.Arithmetic; import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; -import org.jgrapht.alg.StrongConnectivityInspector; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.testng.Assert; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index 2c7d78169..35fa47ede 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -35,8 +35,8 @@ import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; import org.broadinstitute.variant.vcf.VCFCodec; diff --git a/public/java/test/org/broadinstitute/variant/vcf/VCFIntegrationTest.java b/public/java/test/org/broadinstitute/sting/utils/variant/VCFIntegrationTest.java similarity index 98% rename from public/java/test/org/broadinstitute/variant/vcf/VCFIntegrationTest.java rename to public/java/test/org/broadinstitute/sting/utils/variant/VCFIntegrationTest.java index 2d36f09c2..f4cef7730 100644 --- a/public/java/test/org/broadinstitute/variant/vcf/VCFIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/variant/VCFIntegrationTest.java @@ -23,10 +23,9 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.vcf; +package org.broadinstitute.sting.utils.variant; import org.broadinstitute.sting.WalkerTest; -import org.broadinstitute.sting.utils.exceptions.UserException; import org.testng.annotations.Test; import java.io.File; diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextBenchmark.java b/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java similarity index 99% rename from public/java/test/org/broadinstitute/variant/variantcontext/VariantContextBenchmark.java rename to public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java index 34abe372f..8a6d2138e 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextBenchmark.java +++ b/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java @@ -23,13 +23,13 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.variantcontext; +package org.broadinstitute.sting.utils.variant; import com.google.caliper.Param; import com.google.caliper.SimpleBenchmark; import org.broad.tribble.Feature; import org.broad.tribble.FeatureCodec; -import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.vcf.VCFCodec; import java.util.ArrayList; @@ -73,8 +73,6 @@ public class VariantContextBenchmark extends SimpleBenchmark { MERGE } - private GenomeLocParser b37GenomeLocParser; - @Override protected void setUp() { // TODO -- update for new tribble interface // try { diff --git a/public/java/test/org/broadinstitute/variant/VariantBaseTest.java b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java new file mode 100644 index 000000000..be70b22e6 --- /dev/null +++ b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java @@ -0,0 +1,141 @@ +package org.broadinstitute.variant; + +import org.testng.Assert; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +/** + * Base class for test classes within org.broadinstitute.variant + */ +public class VariantBaseTest { + + public static final String hg19Reference = "/seq/references/Homo_sapiens_assembly19/v1/Homo_sapiens_assembly19.fasta"; + public static final String b37KGReference = "/humgen/1kg/reference/human_g1k_v37.fasta"; + + // TODO: change this to an appropriate value once the move to the Picard repo takes place + public static final String variantTestDataRoot = new File("private/testdata/").getAbsolutePath() + "/"; + + /** + * Simple generic utility class to creating TestNG data providers: + * + * 1: inherit this class, as in + * + * private class SummarizeDifferenceTest extends TestDataProvider { + * public SummarizeDifferenceTest() { + * super(SummarizeDifferenceTest.class); + * } + * ... + * } + * + * Provide a reference to your class to the TestDataProvider constructor. + * + * 2: Create instances of your subclass. Return from it the call to getTests, providing + * the class type of your test + * + * @DataProvider(name = "summaries" + * public Object[][] createSummaries() { + * new SummarizeDifferenceTest().addDiff("A", "A").addSummary("A:2"); + * new SummarizeDifferenceTest().addDiff("A", "B").addSummary("A:1", "B:1"); + * return SummarizeDifferenceTest.getTests(SummarizeDifferenceTest.class); + * } + * + * This class magically tracks created objects of this + */ + public static class TestDataProvider { + private static final Map> tests = new HashMap>(); + protected String name; + + /** + * Create a new TestDataProvider instance bound to the class variable C + * @param c + */ + public TestDataProvider(Class c, String name) { + if ( ! tests.containsKey(c) ) + tests.put(c, new ArrayList()); + tests.get(c).add(this); + this.name = name; + } + + public TestDataProvider(Class c) { + this(c, ""); + } + + public void setName(final String name) { + this.name = name; + } + + /** + * Return all of the data providers in the form expected by TestNG of type class C + * @param c + * @return + */ + public static Object[][] getTests(Class c) { + List params2 = new ArrayList(); + for ( Object x : tests.get(c) ) params2.add(new Object[]{x}); + return params2.toArray(new Object[][]{}); + } + + @Override + public String toString() { + return "TestDataProvider("+name+")"; + } + } + + /** + * Creates a temp file that will be deleted on exit after tests are complete. + * @param name Prefix of the file. + * @param extension Extension to concat to the end of the file. + * @return A file in the temporary directory starting with name, ending with extension, which will be deleted after the program exits. + */ + public static File createTempFile(String name, String extension) { + try { + File file = File.createTempFile(name, extension); + file.deleteOnExit(); + return file; + } catch (IOException ex) { + throw new RuntimeException("Cannot create temp file: " + ex.getMessage(), ex); + } + } + + private static final double DEFAULT_FLOAT_TOLERANCE = 1e-1; + + public static final void assertEqualsDoubleSmart(final Object actual, final Double expected) { + Assert.assertTrue(actual instanceof Double, "Not a double"); + assertEqualsDoubleSmart((double)(Double)actual, (double)expected); + } + + public static final void assertEqualsDoubleSmart(final Object actual, final Double expected, final double tolerance) { + Assert.assertTrue(actual instanceof Double, "Not a double"); + assertEqualsDoubleSmart((double)(Double)actual, (double)expected, tolerance); + } + + public static final void assertEqualsDoubleSmart(final double actual, final double expected) { + assertEqualsDoubleSmart(actual, expected, DEFAULT_FLOAT_TOLERANCE); + } + + public static final void assertEqualsSet(final Set actual, final Set expected, final String info) { + final Set actualSet = new HashSet(actual); + final Set expectedSet = new HashSet(expected); + Assert.assertTrue(actualSet.equals(expectedSet), info); // note this is necessary due to testng bug for set comps + } + + public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance) { + assertEqualsDoubleSmart(actual, expected, tolerance, null); + } + + public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance, final String message) { + if ( Double.isNaN(expected) ) // NaN == NaN => false unfortunately + Assert.assertTrue(Double.isNaN(actual), "expected is nan, actual is not"); + else if ( Double.isInfinite(expected) ) // NaN == NaN => false unfortunately + Assert.assertTrue(Double.isInfinite(actual), "expected is infinite, actual is not"); + else { + final double delta = Math.abs(actual - expected); + final double ratio = Math.abs(actual / expected - 1.0); + Assert.assertTrue(delta < tolerance || ratio < tolerance, "expected = " + expected + " actual = " + actual + + " not within tolerance " + tolerance + + (message == null ? "" : "message: " + message)); + } + } +} diff --git a/public/java/test/org/broadinstitute/variant/bcf2/BCF2EncoderDecoderUnitTest.java b/public/java/test/org/broadinstitute/variant/bcf2/BCF2EncoderDecoderUnitTest.java index 35c4eacfb..8f3a216b7 100644 --- a/public/java/test/org/broadinstitute/variant/bcf2/BCF2EncoderDecoderUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/bcf2/BCF2EncoderDecoderUnitTest.java @@ -25,12 +25,9 @@ package org.broadinstitute.variant.bcf2; - // the imports for unit testing. - - import org.apache.commons.lang.ArrayUtils; -import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.variantcontext.writer.BCF2Encoder; import org.testng.Assert; import org.testng.annotations.BeforeSuite; @@ -47,7 +44,7 @@ import java.util.Collections; import java.util.List; -public class BCF2EncoderDecoderUnitTest extends BaseTest { +public class BCF2EncoderDecoderUnitTest extends VariantBaseTest { private final double FLOAT_TOLERANCE = 1e-6; final List primitives = new ArrayList(); final List basicTypes = new ArrayList(); @@ -561,7 +558,7 @@ public class BCF2EncoderDecoderUnitTest extends BaseTest { final double valueFloat = (Double)tv.value; final double decodedFloat = (Double)decoded; - BaseTest.assertEqualsDoubleSmart(decodedFloat, valueFloat, FLOAT_TOLERANCE); + VariantBaseTest.assertEqualsDoubleSmart(decodedFloat, valueFloat, FLOAT_TOLERANCE); } else Assert.assertEquals(decoded, tv.value); } diff --git a/public/java/test/org/broadinstitute/variant/bcf2/BCF2UtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/bcf2/BCF2UtilsUnitTest.java index 6d854f080..5d01a458b 100644 --- a/public/java/test/org/broadinstitute/variant/bcf2/BCF2UtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/bcf2/BCF2UtilsUnitTest.java @@ -25,8 +25,8 @@ package org.broadinstitute.variant.bcf2; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.variant.VariantBaseTest; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; import java.util.*; @@ -37,7 +37,7 @@ import org.testng.annotations.Test; /** * Tests for BCF2Utils */ -public final class BCF2UtilsUnitTest extends BaseTest { +public final class BCF2UtilsUnitTest extends VariantBaseTest { @DataProvider(name = "CollapseExpandTest") public Object[][] makeCollapseExpandTest() { List tests = new ArrayList(); @@ -87,7 +87,7 @@ public final class BCF2UtilsUnitTest extends BaseTest { final List empty = Collections.emptyList(); final List> permutations = extrasToTake == 0 ? Collections.singletonList(empty) - : Utils.makePermutations(extraLines, extrasToTake, false); + : GeneralUtils.makePermutations(extraLines, extrasToTake, false); for ( final List permutation : permutations ) { for ( int i = -1; i < inputLines.size(); i++ ) { final List allLines = new ArrayList(inputLines); @@ -113,7 +113,7 @@ public final class BCF2UtilsUnitTest extends BaseTest { final List> permutations = testSamples.isEmpty() ? Collections.singletonList(testSamples) - : Utils.makePermutations(testSamples, testSamples.size(), false); + : GeneralUtils.makePermutations(testSamples, testSamples.size(), false); for ( final List testSamplesPermutation : permutations ) { final VCFHeader testHeaderWithSamples = new VCFHeader(inputHeader.getMetaDataInInputOrder(), testSamplesPermutation); final boolean expectedConsistent = testSamples.equals(inSamples); diff --git a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java index 37627204f..738fa28e2 100644 --- a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java @@ -25,21 +25,18 @@ package org.broadinstitute.variant.utils; -import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.variant.VariantBaseTest; import org.testng.Assert; -import org.broadinstitute.sting.BaseTest; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; -public class BaseUtilsUnitTest extends BaseTest { +public class BaseUtilsUnitTest extends VariantBaseTest { @BeforeClass public void init() { } @Test public void testMostFrequentBaseFraction() { - logger.warn("Executing testMostFrequentBaseFraction"); - compareFrequentBaseFractionToExpected("AAAAA", 1.0); compareFrequentBaseFractionToExpected("ACCG", 0.5); compareFrequentBaseFractionToExpected("ACCCCTTTTG", 4.0/10.0); @@ -47,7 +44,7 @@ public class BaseUtilsUnitTest extends BaseTest { private void compareFrequentBaseFractionToExpected(String sequence, double expected) { double fraction = BaseUtils.mostFrequentBaseFraction(sequence.getBytes()); - Assert.assertTrue(MathUtils.compareDoubles(fraction, expected) == 0); + Assert.assertTrue(GeneralUtils.compareDoubles(fraction, expected) == 0); } @Test @@ -67,8 +64,6 @@ public class BaseUtilsUnitTest extends BaseTest { @Test public void testTransitionTransversion() { - logger.warn("Executing testTransitionTransversion"); - Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION ); Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION ); Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'G' ) == BaseUtils.BaseSubstitutionType.TRANSITION ); @@ -94,8 +89,6 @@ public class BaseUtilsUnitTest extends BaseTest { @Test public void testReverseComplementString() { - logger.warn("Executing testReverseComplementString"); - compareRCStringToExpected("ACGGT", "ACCGT"); compareRCStringToExpected("TCGTATATCTCGCTATATATATATAGCTCTAGTATA", "TATACTAGAGCTATATATATATAGCGAGATATACGA"); compareRCStringToExpected("AAAN", "NTTT"); diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/AlleleUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/AlleleUnitTest.java index f1dff7ab1..7fa652f2f 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/AlleleUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/AlleleUnitTest.java @@ -28,6 +28,7 @@ package org.broadinstitute.variant.variantcontext; // the imports for unit testing. +import org.broadinstitute.variant.VariantBaseTest; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; @@ -44,7 +45,7 @@ import org.testng.annotations.Test; /** * Basic unit test for RecalData */ -public class AlleleUnitTest { +public class AlleleUnitTest extends VariantBaseTest { Allele ARef, A, T, ATIns, ATCIns, NoCall; @BeforeSuite diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java index 03d6f457f..fb180c476 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java @@ -30,9 +30,9 @@ package org.broadinstitute.variant.variantcontext; import org.broad.tribble.TribbleException; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.exceptions.UserException; +import org.broadinstitute.variant.utils.GeneralUtils; import org.testng.Assert; import org.testng.annotations.Test; @@ -44,7 +44,7 @@ import java.util.List; /** * Basic unit test for Genotype likelihoods objects */ -public class GenotypeLikelihoodsUnitTest { +public class GenotypeLikelihoodsUnitTest extends VariantBaseTest { double [] v = new double[]{-10.5, -1.25, -5.11}; final static String vGLString = "-10.50,-1.25,-5.11"; final static String vPLString = "93,0,39"; @@ -88,7 +88,7 @@ public class GenotypeLikelihoodsUnitTest { //Linear scale glMap = gl.getAsMap(true); - double [] vl = MathUtils.normalizeFromLog10(v); + double [] vl = GeneralUtils.normalizeFromLog10(v); Assert.assertEquals(vl[GenotypeType.HOM_REF.ordinal()-1],glMap.get(GenotypeType.HOM_REF)); Assert.assertEquals(vl[GenotypeType.HET.ordinal()-1],glMap.get(GenotypeType.HET)); Assert.assertEquals(vl[GenotypeType.HOM_VAR.ordinal()-1],glMap.get(GenotypeType.HOM_VAR)); @@ -118,7 +118,7 @@ public class GenotypeLikelihoodsUnitTest { //GQ for the best guess genotype Assert.assertEquals(gl.getLog10GQ(GenotypeType.HET),-3.9); - double[] test = MathUtils.normalizeFromLog10(gl.getAsVector()); + double[] test = GeneralUtils.normalizeFromLog10(gl.getAsVector()); //GQ for the other genotypes Assert.assertEquals(gl.getLog10GQ(GenotypeType.HOM_REF), Math.log10(1.0 - test[GenotypeType.HOM_REF.ordinal()-1])); diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeUnitTest.java index 2148b555e..8d0d2af90 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeUnitTest.java @@ -29,13 +29,13 @@ package org.broadinstitute.variant.variantcontext; // the imports for unit testing. -import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.variant.VariantBaseTest; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -public class GenotypeUnitTest extends BaseTest { +public class GenotypeUnitTest extends VariantBaseTest { Allele A, Aref, T; @BeforeSuite diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypesContextUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypesContextUnitTest.java index a7e7fe357..1618ad1f2 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypesContextUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypesContextUnitTest.java @@ -30,8 +30,8 @@ package org.broadinstitute.variant.variantcontext; import org.broad.tribble.util.ParsingUtils; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.variant.VariantBaseTest; +import org.broadinstitute.variant.utils.GeneralUtils; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.DataProvider; @@ -40,7 +40,7 @@ import org.testng.annotations.Test; import java.util.*; -public class GenotypesContextUnitTest extends BaseTest { +public class GenotypesContextUnitTest extends VariantBaseTest { Allele Aref, C, T; Genotype AA, AT, TT, AC, CT, CC, MISSING; List allGenotypes; @@ -128,7 +128,7 @@ public class GenotypesContextUnitTest extends BaseTest { // sorted new GenotypesContextProvider(maker, samples); // unsorted - new GenotypesContextProvider(maker, Utils.reverse(samples)); + new GenotypesContextProvider(maker, GeneralUtils.reverse(samples)); } } diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java index f489806f6..d739e4aa5 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java @@ -25,15 +25,14 @@ package org.broadinstitute.variant.variantcontext; -import org.apache.log4j.Logger; import org.broad.tribble.FeatureCodec; import org.broad.tribble.FeatureCodecHeader; import org.broad.tribble.readers.PositionalBufferedStream; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.bcf2.BCF2Codec; +import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; -import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.writer.Options; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.testng.Assert; @@ -50,8 +49,6 @@ import java.util.*; * @since Date created */ public class VariantContextTestProvider { - final protected static Logger logger = Logger.getLogger(VariantContextTestProvider.class); - final private static boolean ENABLE_GENOTYPE_TESTS = true; final private static boolean ENABLE_A_AND_G_TESTS = true; final private static boolean ENABLE_VARARRAY_TESTS = true; @@ -68,12 +65,12 @@ public class VariantContextTestProvider { private final static List testSourceVCFs = new ArrayList(); static { - testSourceVCFs.add(new File(BaseTest.privateTestDir + "ILLUMINA.wex.broad_phase2_baseline.20111114.both.exome.genotypes.1000.vcf")); - testSourceVCFs.add(new File(BaseTest.privateTestDir + "ex2.vcf")); - testSourceVCFs.add(new File(BaseTest.privateTestDir + "dbsnp_135.b37.1000.vcf")); + testSourceVCFs.add(new File(VariantBaseTest.variantTestDataRoot + "ILLUMINA.wex.broad_phase2_baseline.20111114.both.exome.genotypes.1000.vcf")); + testSourceVCFs.add(new File(VariantBaseTest.variantTestDataRoot + "ex2.vcf")); + testSourceVCFs.add(new File(VariantBaseTest.variantTestDataRoot + "dbsnp_135.b37.1000.vcf")); if ( ENABLE_SYMBOLIC_ALLELE_TESTS ) { - testSourceVCFs.add(new File(BaseTest.privateTestDir + "diagnosis_targets_testfile.vcf")); - testSourceVCFs.add(new File(BaseTest.privateTestDir + "VQSR.mixedTest.recal")); + testSourceVCFs.add(new File(VariantBaseTest.variantTestDataRoot + "diagnosis_targets_testfile.vcf")); + testSourceVCFs.add(new File(VariantBaseTest.variantTestDataRoot + "VQSR.mixedTest.recal")); } } @@ -156,12 +153,10 @@ public class VariantContextTestProvider { Pair> x = readAllVCs( file, codec ); List fullyDecoded = new ArrayList(); - logger.warn("Reading records from " + file); for ( final VariantContext raw : x.getSecond() ) { if ( raw != null ) fullyDecoded.add(raw.fullyDecode(x.getFirst(), false)); } - logger.warn("Done reading " + file); TEST_DATAs.add(new VariantContextTestData(x.getFirst(), fullyDecoded)); } @@ -788,12 +783,12 @@ public class VariantContextTestProvider { assertAttributesEquals(actual.getAttributes(), expected.getAttributes()); Assert.assertEquals(actual.filtersWereApplied(), expected.filtersWereApplied(), "filtersWereApplied"); Assert.assertEquals(actual.isFiltered(), expected.isFiltered(), "isFiltered"); - BaseTest.assertEqualsSet(actual.getFilters(), expected.getFilters(), "filters"); - BaseTest.assertEqualsDoubleSmart(actual.getPhredScaledQual(), expected.getPhredScaledQual()); + VariantBaseTest.assertEqualsSet(actual.getFilters(), expected.getFilters(), "filters"); + VariantBaseTest.assertEqualsDoubleSmart(actual.getPhredScaledQual(), expected.getPhredScaledQual()); Assert.assertEquals(actual.hasGenotypes(), expected.hasGenotypes(), "hasGenotypes"); if ( expected.hasGenotypes() ) { - BaseTest.assertEqualsSet(actual.getSampleNames(), expected.getSampleNames(), "sample names set"); + VariantBaseTest.assertEqualsSet(actual.getSampleNames(), expected.getSampleNames(), "sample names set"); Assert.assertEquals(actual.getSampleNamesOrderedByName(), expected.getSampleNamesOrderedByName(), "sample names"); final Set samples = expected.getSampleNames(); for ( final String sample : samples ) { @@ -879,7 +874,7 @@ public class VariantContextTestProvider { private static void assertAttributeEquals(final String key, final Object actual, final Object expected) { if ( expected instanceof Double ) { // must be very tolerant because doubles are being rounded to 2 sig figs - BaseTest.assertEqualsDoubleSmart(actual, (Double)expected, 1e-2); + VariantBaseTest.assertEqualsDoubleSmart(actual, (Double)expected, 1e-2); } else Assert.assertEquals(actual, expected, "Attribute " + key); } @@ -935,7 +930,7 @@ public class VariantContextTestProvider { } private static List> makeAllGenotypes(final List alleles, final int highestPloidy) { - return Utils.makePermutations(alleles, highestPloidy, true); + return GeneralUtils.makePermutations(alleles, highestPloidy, true); } public static void assertEquals(final VCFHeader actual, final VCFHeader expected) { diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java index d34e6396d..d09800760 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java @@ -29,9 +29,8 @@ package org.broadinstitute.variant.variantcontext; // the imports for unit testing. -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.collections.Pair; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.VariantBaseTest; +import org.broadinstitute.variant.utils.Pair; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -41,7 +40,7 @@ import org.testng.Assert; import java.util.*; -public class VariantContextUnitTest extends BaseTest { +public class VariantContextUnitTest extends VariantBaseTest { Allele A, Aref, C, T, Tref; Allele del, delRef, ATC, ATCref; @@ -500,30 +499,30 @@ public class VariantContextUnitTest extends BaseTest { Pair,byte[]> result; byte[] refBytes = "TATCATCATCGGA".getBytes(); - Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes()),4); - Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes()),0); - Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes()),1); - Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes()),1); - Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes()),2); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes()),4); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes()),0); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes()),1); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes()),1); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes()),2); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACAC".getBytes()),7); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACA".getBytes()),2); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CATGCATG".getBytes()),4); - Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AATAATA".getBytes()),7); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CACACAC".getBytes()),7); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CACACA".getBytes()),2); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CATGCATG".getBytes()),4); + Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("AATAATA".getBytes()),7); // A*,ATC, context = ATC ATC ATC : (ATC)3 -> (ATC)4 VariantContext vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStop, Arrays.asList(nullR,atc)).make(); - result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); Assert.assertEquals(result.getFirst().toArray()[0],3); Assert.assertEquals(result.getFirst().toArray()[1],4); Assert.assertEquals(result.getSecond().length,3); // ATC*,A,ATCATC vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+3, Arrays.asList(Allele.create("AATC", true),nullA,atcatc)).make(); - result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); Assert.assertEquals(result.getFirst().toArray()[0],3); Assert.assertEquals(result.getFirst().toArray()[1],2); Assert.assertEquals(result.getFirst().toArray()[2],4); @@ -532,7 +531,7 @@ public class VariantContextUnitTest extends BaseTest { // simple non-tandem deletion: CCCC*, - refBytes = "TCCCCCCCCATG".getBytes(); vc = new VariantContextBuilder("foo", delLoc, 10, 14, Arrays.asList(ccccR,nullA)).make(); - result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); Assert.assertEquals(result.getFirst().toArray()[0],8); Assert.assertEquals(result.getFirst().toArray()[1],4); Assert.assertEquals(result.getSecond().length,1); @@ -540,7 +539,7 @@ public class VariantContextUnitTest extends BaseTest { // CCCC*,CC,-,CCCCCC, context = CCC: (C)7 -> (C)5,(C)3,(C)9 refBytes = "TCCCCCCCAGAGAGAG".getBytes(); vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(ccccR,cc, nullA,cccccc)).make(); - result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); Assert.assertEquals(result.getFirst().toArray()[0],7); Assert.assertEquals(result.getFirst().toArray()[1],5); Assert.assertEquals(result.getFirst().toArray()[2],3); @@ -550,7 +549,7 @@ public class VariantContextUnitTest extends BaseTest { // GAGA*,-,GAGAGAGA refBytes = "TGAGAGAGAGATTT".getBytes(); vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(gagaR, nullA,gagagaga)).make(); - result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); Assert.assertEquals(result.getFirst().toArray()[0],5); Assert.assertEquals(result.getFirst().toArray()[1],3); Assert.assertEquals(result.getFirst().toArray()[2],7); diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java index 9c1486cf7..9b24f64e7 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java @@ -26,12 +26,8 @@ package org.broadinstitute.variant.variantcontext; import net.sf.picard.reference.IndexedFastaSequenceFile; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.VariantBaseTest; +import org.broadinstitute.variant.utils.GeneralUtils; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.DataProvider; @@ -41,19 +37,17 @@ import java.io.File; import java.io.FileNotFoundException; import java.util.*; -public class VariantContextUtilsUnitTest extends BaseTest { +public class VariantContextUtilsUnitTest extends VariantBaseTest { Allele Aref, T, C, G, Cref, ATC, ATCATC; - private GenomeLocParser genomeLocParser; @BeforeSuite public void setup() { final File referenceFile = new File(b37KGReference); try { - IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(referenceFile); - genomeLocParser = new GenomeLocParser(seq); + IndexedFastaSequenceFile seq = new IndexedFastaSequenceFile(referenceFile); } catch(FileNotFoundException ex) { - throw new UserException.CouldNotReadInputFile(referenceFile,ex); + throw new RuntimeException(referenceFile.getAbsolutePath(),ex); } // alleles @@ -658,7 +652,7 @@ public class VariantContextUtilsUnitTest extends BaseTest { public void testRepeatDetectorTest(RepeatDetectorTest cfg) { // test alleles are equal - Assert.assertEquals(GATKVariantContextUtils.isTandemRepeat(cfg.vc, cfg.ref.getBytes()), cfg.isTrueRepeat); + Assert.assertEquals(VariantContextUtils.isTandemRepeat(cfg.vc, cfg.ref.getBytes()), cfg.isTrueRepeat); } // -------------------------------------------------------------------------------- @@ -704,7 +698,7 @@ public class VariantContextUtilsUnitTest extends BaseTest { @Test(dataProvider = "ReverseClippingPositionTestProvider") public void testReverseClippingPositionTestProvider(ReverseClippingPositionTestProvider cfg) { - int result = GATKVariantContextUtils.computeReverseClipping(cfg.alleles, cfg.ref.getBytes(), 0, false); + int result = VariantContextUtils.computeReverseClipping(cfg.alleles, cfg.ref.getBytes(), 0, false); Assert.assertEquals(result, cfg.expectedClip); } @@ -782,7 +776,7 @@ public class VariantContextUtilsUnitTest extends BaseTest { @Test(dataProvider = "SplitBiallelics") public void testSplitBiallelicsNoGenotypes(final VariantContext vc, final List expectedBiallelics) { - final List biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vc); + final List biallelics = VariantContextUtils.splitVariantContextToBiallelics(vc); Assert.assertEquals(biallelics.size(), expectedBiallelics.size()); for ( int i = 0; i < biallelics.size(); i++ ) { final VariantContext actual = biallelics.get(i); @@ -796,14 +790,14 @@ public class VariantContextUtilsUnitTest extends BaseTest { final List genotypes = new ArrayList(); int sampleI = 0; - for ( final List alleles : Utils.makePermutations(vc.getAlleles(), 2, true) ) { + for ( final List alleles : GeneralUtils.makePermutations(vc.getAlleles(), 2, true) ) { genotypes.add(GenotypeBuilder.create("sample" + sampleI++, alleles)); } genotypes.add(GenotypeBuilder.createMissing("missing", 2)); final VariantContext vcWithGenotypes = new VariantContextBuilder(vc).genotypes(genotypes).make(); - final List biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vcWithGenotypes); + final List biallelics = VariantContextUtils.splitVariantContextToBiallelics(vcWithGenotypes); for ( int i = 0; i < biallelics.size(); i++ ) { final VariantContext actual = biallelics.get(i); Assert.assertEquals(actual.getNSamples(), vcWithGenotypes.getNSamples()); // not dropping any samples diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantJEXLContextUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantJEXLContextUnitTest.java index f2213e088..8d2569771 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantJEXLContextUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantJEXLContextUnitTest.java @@ -25,13 +25,8 @@ package org.broadinstitute.variant.variantcontext; -import net.sf.samtools.SAMFileHeader; +import org.broadinstitute.variant.VariantBaseTest; import org.testng.Assert; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; - import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -49,8 +44,7 @@ import java.util.Map; * * Test out parts of the VariantJEXLContext */ -public class VariantJEXLContextUnitTest extends BaseTest { - +public class VariantJEXLContextUnitTest extends VariantBaseTest { private static String expression = "QUAL > 500.0"; private static VariantContextUtils.JexlVCMatchExp exp; @@ -60,27 +54,15 @@ public class VariantJEXLContextUnitTest extends BaseTest { Allele ATC, ATCref; // A [ref] / T at 10 - GenomeLoc snpLoc; // - / ATC [ref] from 20-23 - private static int startingChr = 1; - private static int endingChr = 2; - private static int readCount = 100; - private static int DEFAULT_READ_LENGTH = ArtificialSAMUtils.DEFAULT_READ_LENGTH; - static SAMFileHeader header; - - private static GenomeLocParser genomeLocParser; - @BeforeClass public void beforeClass() { - header = ArtificialSAMUtils.createArtificialSamHeader(( endingChr - startingChr ) + 1, startingChr, readCount + DEFAULT_READ_LENGTH); - genomeLocParser = new GenomeLocParser(header.getSequenceDictionary()); try { exp = new VariantContextUtils.JexlVCMatchExp("name", VariantContextUtils.engine.createExpression(expression)); } catch (Exception e) { Assert.fail("Unable to create expression" + e.getMessage()); } - snpLoc = genomeLocParser.createGenomeLoc("chr1", 10, 10, true); } @BeforeMethod @@ -142,9 +124,7 @@ public class VariantJEXLContextUnitTest extends BaseTest { private JEXLMap getVarContext() { List alleles = Arrays.asList(Aref, T); - VariantContext vc = new VariantContextBuilder("test", snpLoc.getContig(), snpLoc.getStart(), snpLoc.getStop(), alleles).make(); + VariantContext vc = new VariantContextBuilder("test", "chr1", 10, 10, alleles).make(); return new JEXLMap(Arrays.asList(exp),vc); } - - } diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/writer/VCFWriterUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/writer/VCFWriterUnitTest.java index 79258e844..bbfac11cb 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/writer/VCFWriterUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/writer/VCFWriterUnitTest.java @@ -29,16 +29,11 @@ import net.sf.picard.reference.IndexedFastaSequenceFile; import org.broad.tribble.AbstractFeatureReader; import org.broad.tribble.FeatureReader; import org.broad.tribble.Tribble; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.vcf.VCFCodec; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.variant.vcf.VCFHeaderLine; import org.broadinstitute.variant.vcf.VCFHeaderVersion; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.variant.variantcontext.*; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -58,22 +53,20 @@ import java.util.*; *

* This class tests out the ability of the VCF writer to correctly write VCF files */ -public class VCFWriterUnitTest extends BaseTest { +public class VCFWriterUnitTest extends VariantBaseTest { private Set metaData = new HashSet(); private Set additionalColumns = new HashSet(); private File fakeVCFFile = new File("FAKEVCFFILEFORTESTING.vcf"); - private GenomeLocParser genomeLocParser; private IndexedFastaSequenceFile seq; @BeforeClass public void beforeTests() { - File referenceFile = new File(hg18Reference); + File referenceFile = new File(hg19Reference); try { - seq = new CachingIndexedFastaSequenceFile(referenceFile); - genomeLocParser = new GenomeLocParser(seq); + seq = new IndexedFastaSequenceFile(referenceFile); } catch(FileNotFoundException ex) { - throw new UserException.CouldNotReadInputFile(referenceFile,ex); + throw new RuntimeException(referenceFile.getAbsolutePath(), ex); } } @@ -108,7 +101,7 @@ public class VCFWriterUnitTest extends BaseTest { fakeVCFFile.delete(); } catch (IOException e ) { - throw new ReviewedStingException(e.getMessage()); + throw new RuntimeException(e.getMessage()); } } @@ -133,8 +126,6 @@ public class VCFWriterUnitTest extends BaseTest { * @return a VCFRecord */ private VariantContext createVC(VCFHeader header) { - - GenomeLoc loc = genomeLocParser.createGenomeLoc("chr1",1); List alleles = new ArrayList(); Set filters = null; Map attributes = new HashMap(); @@ -148,7 +139,7 @@ public class VCFWriterUnitTest extends BaseTest { Genotype gt = new GenotypeBuilder(name,alleles.subList(1,2)).GQ(0).attribute("BB", "1").phased(true).make(); genotypes.add(gt); } - return new VariantContextBuilder("RANDOM", loc.getContig(), loc.getStart(), loc.getStop(), alleles) + return new VariantContextBuilder("RANDOM", "chr1", 1, 1, alleles) .genotypes(genotypes).attributes(attributes).make(); } diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/writer/VariantContextWritersUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/writer/VariantContextWritersUnitTest.java index 023f48928..9e6541bfa 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/writer/VariantContextWritersUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/writer/VariantContextWritersUnitTest.java @@ -32,11 +32,10 @@ package org.broadinstitute.variant.variantcontext.writer; import net.sf.picard.reference.IndexedFastaSequenceFile; import net.sf.samtools.SAMSequenceDictionary; import org.broad.tribble.FeatureCodec; -import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.bcf2.BCF2Codec; import org.broadinstitute.variant.vcf.VCFCodec; import org.broadinstitute.variant.vcf.VCFHeader; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; import org.testng.annotations.BeforeSuite; @@ -50,15 +49,13 @@ import java.util.EnumSet; import java.util.List; -public class VariantContextWritersUnitTest extends BaseTest { +public class VariantContextWritersUnitTest extends VariantBaseTest { private SAMSequenceDictionary dictionary; @BeforeSuite public void before() throws IOException { final File source = new File(b37KGReference); - //final File source = new File("/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta"); - IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(source); - //IndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + IndexedFastaSequenceFile seq = new IndexedFastaSequenceFile(source); dictionary = seq.getSequenceDictionary(); VariantContextTestProvider.initializeTests(); } diff --git a/public/java/test/org/broadinstitute/variant/vcf/IndexFactoryUnitTest.java b/public/java/test/org/broadinstitute/variant/vcf/IndexFactoryUnitTest.java index b0b07d148..6292baae3 100644 --- a/public/java/test/org/broadinstitute/variant/vcf/IndexFactoryUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/vcf/IndexFactoryUnitTest.java @@ -25,15 +25,14 @@ package org.broadinstitute.variant.vcf; +import net.sf.picard.reference.IndexedFastaSequenceFile; import net.sf.samtools.SAMSequenceDictionary; import org.broad.tribble.AbstractFeatureReader; import org.broad.tribble.CloseableTribbleIterator; import org.broad.tribble.Tribble; import org.broad.tribble.index.Index; import org.broad.tribble.index.IndexFactory; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.writer.Options; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; @@ -50,10 +49,10 @@ import java.util.EnumSet; /** * tests out the various functions in the index factory class */ -public class IndexFactoryUnitTest extends BaseTest { +public class IndexFactoryUnitTest extends VariantBaseTest { - File inputFile = new File(privateTestDir + "HiSeq.10000.vcf"); - File outputFile = new File(privateTestDir + "onTheFlyOutputTest.vcf"); + File inputFile = new File(variantTestDataRoot + "HiSeq.10000.vcf"); + File outputFile = new File(variantTestDataRoot + "onTheFlyOutputTest.vcf"); File outputFileIndex = Tribble.indexFile(outputFile); private SAMSequenceDictionary dict; @@ -61,10 +60,10 @@ public class IndexFactoryUnitTest extends BaseTest { @BeforeTest public void setup() { try { - dict = new CachingIndexedFastaSequenceFile(new File(b37KGReference)).getSequenceDictionary(); + dict = new IndexedFastaSequenceFile(new File(b37KGReference)).getSequenceDictionary(); } catch(FileNotFoundException ex) { - throw new UserException.CouldNotReadInputFile(b37KGReference,ex); + throw new RuntimeException(b37KGReference,ex); } } diff --git a/public/java/test/org/broadinstitute/variant/vcf/VCFHeaderUnitTest.java b/public/java/test/org/broadinstitute/variant/vcf/VCFHeaderUnitTest.java index d7d3c8d6c..7d6b11953 100644 --- a/public/java/test/org/broadinstitute/variant/vcf/VCFHeaderUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/vcf/VCFHeaderUnitTest.java @@ -27,9 +27,8 @@ package org.broadinstitute.variant.vcf; import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.PositionalBufferedStream; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.variant.VariantBaseTest; import org.testng.Assert; -import org.broadinstitute.sting.BaseTest; import org.testng.annotations.Test; @@ -45,7 +44,7 @@ import java.security.NoSuchAlgorithmException; * Time: 3:32:08 PM * To change this template use File | Settings | File Templates. */ -public class VCFHeaderUnitTest extends BaseTest { +public class VCFHeaderUnitTest extends VariantBaseTest { private VCFHeader createHeader(String headerStr) { VCFCodec codec = new VCFCodec(); @@ -80,13 +79,13 @@ public class VCFHeaderUnitTest extends BaseTest { try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { - throw new ReviewedStingException("Unable to find MD5 digest"); + throw new RuntimeException("Unable to find MD5 digest"); } InputStream is; try { is = new FileInputStream(file); } catch (FileNotFoundException e) { - throw new ReviewedStingException("Unable to open file " + file); + throw new RuntimeException("Unable to open file " + file); } byte[] buffer = new byte[8192]; int read; @@ -100,14 +99,14 @@ public class VCFHeaderUnitTest extends BaseTest { } catch (IOException e) { - throw new ReviewedStingException("Unable to process file for MD5", e); + throw new RuntimeException("Unable to process file for MD5", e); } finally { try { is.close(); } catch (IOException e) { - throw new ReviewedStingException("Unable to close input stream for MD5 calculation", e); + throw new RuntimeException("Unable to close input stream for MD5 calculation", e); } } } diff --git a/public/java/test/org/broadinstitute/variant/vcf/VCFStandardHeaderLinesUnitTest.java b/public/java/test/org/broadinstitute/variant/vcf/VCFStandardHeaderLinesUnitTest.java index b77191051..02090c9cd 100644 --- a/public/java/test/org/broadinstitute/variant/vcf/VCFStandardHeaderLinesUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/vcf/VCFStandardHeaderLinesUnitTest.java @@ -25,7 +25,7 @@ package org.broadinstitute.variant.vcf; -import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.variant.VariantBaseTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.testng.Assert; @@ -41,7 +41,7 @@ import java.util.List; * Time: 3:32:08 PM * To change this template use File | Settings | File Templates. */ -public class VCFStandardHeaderLinesUnitTest extends BaseTest { +public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest { @DataProvider(name = "getStandardLines") public Object[][] makeGetStandardLines() { List tests = new ArrayList(); From aab160372a63bcca13c8e8740f0351a3cf5b164a Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Mon, 28 Jan 2013 11:26:01 -0500 Subject: [PATCH 114/188] No need to sort the BQSR tables by default. --- .../broadinstitute/sting/utils/recalibration/RecalUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java index e8fc713f1..34aa5abc7 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java @@ -310,7 +310,7 @@ public class RecalUtils { if(sortByCols) { reportTable = new GATKReportTable("RecalTable" + reportTableIndex++, "", columnNames.size(), GATKReportTable.TableSortingWay.SORT_BY_COLUMN); } else { - reportTable = new GATKReportTable("RecalTable" + reportTableIndex++, "", columnNames.size()); + reportTable = new GATKReportTable("RecalTable" + reportTableIndex++, "", columnNames.size(), GATKReportTable.TableSortingWay.DO_NOT_SORT); } for (final Pair columnName : columnNames) reportTable.addColumn(columnName.getFirst(), columnName.getSecond()); From 8777e02aa5d31a1679239891789324f21fdfe50c Mon Sep 17 00:00:00 2001 From: Tad Jordan Date: Mon, 28 Jan 2013 11:33:49 -0500 Subject: [PATCH 115/188] R issue in Queue fixed. GSA-721 --- .../broadinstitute/sting/utils/R/RScriptExecutor.java | 10 ++++++---- .../broadinstitute/sting/utils/R/RScriptLibrary.java | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/R/RScriptExecutor.java b/public/java/src/org/broadinstitute/sting/utils/R/RScriptExecutor.java index 0d6450c8f..04205350f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/R/RScriptExecutor.java +++ b/public/java/src/org/broadinstitute/sting/utils/R/RScriptExecutor.java @@ -110,15 +110,17 @@ public class RScriptExecutor { List tempFiles = new ArrayList(); try { - File tempLibDir = IOUtils.tempDir("Rlib.", ""); - tempFiles.add(tempLibDir); + File tempLibSourceDir = IOUtils.tempDir("RlibSources.", ""); + File tempLibInstallationDir = IOUtils.tempDir("Rlib.", ""); + tempFiles.add(tempLibSourceDir); + tempFiles.add(tempLibInstallationDir); - StringBuilder expression = new StringBuilder("tempLibDir = '").append(tempLibDir).append("';"); + StringBuilder expression = new StringBuilder("tempLibDir = '").append(tempLibInstallationDir).append("';"); if (this.libraries.size() > 0) { List tempLibraryPaths = new ArrayList(); for (RScriptLibrary library: this.libraries) { - File tempLibrary = library.writeTemp(); + File tempLibrary = library.writeLibrary(tempLibSourceDir); tempFiles.add(tempLibrary); tempLibraryPaths.add(tempLibrary.getAbsolutePath()); } diff --git a/public/java/src/org/broadinstitute/sting/utils/R/RScriptLibrary.java b/public/java/src/org/broadinstitute/sting/utils/R/RScriptLibrary.java index 685979d83..93110ccdc 100644 --- a/public/java/src/org/broadinstitute/sting/utils/R/RScriptLibrary.java +++ b/public/java/src/org/broadinstitute/sting/utils/R/RScriptLibrary.java @@ -57,4 +57,10 @@ public enum RScriptLibrary { public File writeTemp() { return IOUtils.writeTempResource(new Resource(getResourcePath(), RScriptLibrary.class)); } + + public File writeLibrary(File tempDir) { + File libraryFile = new File(tempDir, getLibraryName()); + IOUtils.writeResource(new Resource(getResourcePath(), RScriptLibrary.class), libraryFile); + return libraryFile; + } } From d665a8ba0caf7a5a5da592ca6a1e52571c8a5d59 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Mon, 28 Jan 2013 15:56:33 -0500 Subject: [PATCH 116/188] The Bayesian calculation of Qemp in the BQSR is now hierarchical. This fixes issues in which the covariate bins were very sparse and the prior estimate being used was the original quality score. This resulted in large correction factors for each covariate which breaks the equation. There is also now a new option, qlobalQScorePrior, which can be used to ignore the given (very high) quality scores and instead use this value as the prior. --- .../recalibration/BQSRReadTransformer.java | 2 +- .../recalibration/BaseRecalibration.java | 58 ++++++++++--------- .../sting/utils/recalibration/RecalDatum.java | 46 +++++++++++---- .../arguments/GATKArgumentCollection.java | 3 + .../utils/recalibration/BQSRArgumentSet.java | 8 +++ 5 files changed, 80 insertions(+), 37 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BQSRReadTransformer.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BQSRReadTransformer.java index f6e63deec..c85072fa2 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BQSRReadTransformer.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BQSRReadTransformer.java @@ -67,7 +67,7 @@ public class BQSRReadTransformer extends ReadTransformer { this.enabled = engine.hasBQSRArgumentSet(); if ( enabled ) { final BQSRArgumentSet args = engine.getBQSRArgumentSet(); - this.bqsr = new BaseRecalibration(args.getRecalFile(), args.getQuantizationLevels(), args.shouldDisableIndelQuals(), args.getPreserveQscoresLessThan(), args.shouldEmitOriginalQuals()); + this.bqsr = new BaseRecalibration(args.getRecalFile(), args.getQuantizationLevels(), args.shouldDisableIndelQuals(), args.getPreserveQscoresLessThan(), args.shouldEmitOriginalQuals(), args.getGlobalQScorePrior()); } final BQSRMode mode = WalkerManager.getWalkerAnnotation(walker, BQSRMode.class); return mode.ApplicationTime(); diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index 828f91c6f..6852cc40f 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -75,12 +75,12 @@ public class BaseRecalibration { private final boolean disableIndelQuals; private final int preserveQLessThan; + private final double globalQScorePrior; private final boolean emitOriginalQuals; private final NestedIntegerArray globalDeltaQs; private final NestedIntegerArray deltaQReporteds; - /** * Constructor using a GATK Report file * @@ -89,7 +89,7 @@ public class BaseRecalibration { * @param disableIndelQuals if true, do not emit base indel qualities * @param preserveQLessThan preserve quality scores less than this value */ - public BaseRecalibration(final File RECAL_FILE, final int quantizationLevels, final boolean disableIndelQuals, final int preserveQLessThan, final boolean emitOriginalQuals) { + public BaseRecalibration(final File RECAL_FILE, final int quantizationLevels, final boolean disableIndelQuals, final int preserveQLessThan, final boolean emitOriginalQuals, final double globalQScorePrior) { RecalibrationReport recalibrationReport = new RecalibrationReport(RECAL_FILE); recalibrationTables = recalibrationReport.getRecalibrationTables(); @@ -102,6 +102,7 @@ public class BaseRecalibration { this.disableIndelQuals = disableIndelQuals; this.preserveQLessThan = preserveQLessThan; + this.globalQScorePrior = globalQScorePrior; this.emitOriginalQuals = emitOriginalQuals; logger.info("Calculating cached tables..."); @@ -112,13 +113,16 @@ public class BaseRecalibration { // be done upfront, on initialization of this BaseRecalibration structure // final NestedIntegerArray byReadGroupTable = recalibrationTables.getReadGroupTable(); - globalDeltaQs = new NestedIntegerArray( byReadGroupTable.getDimensions() ); + final NestedIntegerArray byQualTable = recalibrationTables.getQualityScoreTable(); + + globalDeltaQs = new NestedIntegerArray( byQualTable.getDimensions() ); logger.info("Calculating global delta Q table..."); - for ( NestedIntegerArray.Leaf leaf : byReadGroupTable.getAllLeaves() ) { + for ( NestedIntegerArray.Leaf leaf : byQualTable.getAllLeaves() ) { final int rgKey = leaf.keys[0]; - final int eventIndex = leaf.keys[1]; - final double globalDeltaQ = calculateGlobalDeltaQ(rgKey, EventType.eventFrom(eventIndex)); - globalDeltaQs.put(globalDeltaQ, rgKey, eventIndex); + final int qual = leaf.keys[1]; + final int eventIndex = leaf.keys[2]; + final double globalDeltaQ = calculateGlobalDeltaQ(rgKey, EventType.eventFrom(eventIndex), (byte) qual); + globalDeltaQs.put(globalDeltaQ, rgKey, qual, eventIndex); } @@ -127,7 +131,6 @@ public class BaseRecalibration { // into a matrix indexed by rgGroup, qual, and event type. // the code below actually creates this cache with a NestedIntegerArray calling into the actual // calculateDeltaQReported code. - final NestedIntegerArray byQualTable = recalibrationTables.getQualityScoreTable(); deltaQReporteds = new NestedIntegerArray( byQualTable.getDimensions() ); logger.info("Calculating delta Q reported table..."); for ( NestedIntegerArray.Leaf leaf : byQualTable.getAllLeaves() ) { @@ -135,7 +138,7 @@ public class BaseRecalibration { final int qual = leaf.keys[1]; final int eventIndex = leaf.keys[2]; final EventType event = EventType.eventFrom(eventIndex); - final double globalDeltaQ = getGlobalDeltaQ(rgKey, event); + final double globalDeltaQ = getGlobalDeltaQ(rgKey, event, (byte)qual); final double deltaQReported = calculateDeltaQReported(rgKey, qual, event, globalDeltaQ, (byte)qual); deltaQReporteds.put(deltaQReported, rgKey, qual, eventIndex); } @@ -188,17 +191,17 @@ public class BaseRecalibration { // the rg key is constant over the whole read, the global deltaQ is too final int rgKey = fullReadKeySet[0][0]; - final double globalDeltaQ = getGlobalDeltaQ(rgKey, errorModel); for (int offset = 0; offset < readLength; offset++) { // recalibrate all bases in the read final byte origQual = quals[offset]; + final double globalDeltaQ = getGlobalDeltaQ(rgKey, errorModel, origQual); // only recalibrate usable qualities (the original quality will come from the instrument -- reported quality) if ( origQual >= preserveQLessThan ) { // get the keyset for this base using the error model final int[] keySet = fullReadKeySet[offset]; - final double deltaQReported = getDeltaQReported(keySet[0], keySet[1], errorModel, globalDeltaQ); - final double deltaQCovariates = calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, globalDeltaQ, deltaQReported, origQual); + final double deltaQReported = getDeltaQReported(keySet[0], keySet[1], errorModel, globalDeltaQ, origQual); + final double deltaQCovariates = calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, deltaQReported, globalDeltaQ, origQual); // calculate the recalibrated qual using the BQSR formula double recalibratedQualDouble = origQual + globalDeltaQ + deltaQReported + deltaQCovariates; @@ -218,11 +221,12 @@ public class BaseRecalibration { } } - private double getGlobalDeltaQ(final int rgKey, final EventType errorModel) { - final Double cached = globalDeltaQs.get(rgKey, errorModel.ordinal()); + private double getGlobalDeltaQ(final int rgKey, final EventType errorModel, final byte qualFromRead) { + + final Double cached = globalDeltaQs.get(rgKey, (int) qualFromRead, errorModel.ordinal()); if ( TEST_CACHING ) { - final double calcd = calculateGlobalDeltaQ(rgKey, errorModel); + final double calcd = calculateGlobalDeltaQ(rgKey, errorModel, qualFromRead); if ( calcd != cached ) throw new IllegalStateException("calculated " + calcd + " and cached " + cached + " global delta q not equal at " + rgKey + " / " + errorModel); } @@ -230,7 +234,8 @@ public class BaseRecalibration { return cachedWithDefault(cached); } - private double getDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ) { + private double getDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ, final byte origQual) { + final Double cached = deltaQReporteds.get(rgKey, qualKey, errorModel.ordinal()); if ( TEST_CACHING ) { @@ -240,6 +245,7 @@ public class BaseRecalibration { } return cachedWithDefault(cached); + } /** @@ -258,14 +264,14 @@ public class BaseRecalibration { * @param errorModel the event type * @return global delta Q */ - private double calculateGlobalDeltaQ(final int rgKey, final EventType errorModel) { + private double calculateGlobalDeltaQ(final int rgKey, final EventType errorModel, final byte qualFromRead) { double result = 0.0; final RecalDatum empiricalQualRG = recalibrationTables.getReadGroupTable().get(rgKey, errorModel.ordinal()); if (empiricalQualRG != null) { - final double globalDeltaQEmpirical = empiricalQualRG.getEmpiricalQuality(); - final double aggregrateQReported = empiricalQualRG.getEstimatedQReported(); + final double aggregrateQReported = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : qualFromRead ); + final double globalDeltaQEmpirical = empiricalQualRG.getEmpiricalQuality( aggregrateQReported ); result = globalDeltaQEmpirical - aggregrateQReported; } @@ -277,14 +283,14 @@ public class BaseRecalibration { final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(rgKey, qualKey, errorModel.ordinal()); if (empiricalQualQS != null) { - final double deltaQReportedEmpirical = empiricalQualQS.getEmpiricalQuality(); - result = deltaQReportedEmpirical - qualFromRead - globalDeltaQ; + final double deltaQReportedEmpirical = empiricalQualQS.getEmpiricalQuality( qualFromRead + globalDeltaQ ); + result = deltaQReportedEmpirical - ( qualFromRead + globalDeltaQ ); } return result; } - private double calculateDeltaQCovariates(final RecalibrationTables recalibrationTables, final int[] key, final EventType errorModel, final double globalDeltaQ, final double deltaQReported, final byte qualFromRead) { + private double calculateDeltaQCovariates(final RecalibrationTables recalibrationTables, final int[] key, final EventType errorModel, final double deltaQReported, final double globalDeltaQ, final byte qualFromRead) { double result = 0.0; // for all optional covariates @@ -294,7 +300,7 @@ public class BaseRecalibration { result += calculateDeltaQCovariate(recalibrationTables.getTable(i), key[0], key[1], key[i], errorModel, - globalDeltaQ, deltaQReported, qualFromRead); + deltaQReported, globalDeltaQ, qualFromRead); } return result; @@ -305,13 +311,13 @@ public class BaseRecalibration { final int qualKey, final int tableKey, final EventType errorModel, - final double globalDeltaQ, final double deltaQReported, + final double globalDeltaQ, final byte qualFromRead) { final RecalDatum empiricalQualCO = table.get(rgKey, qualKey, tableKey, errorModel.ordinal()); if (empiricalQualCO != null) { - final double deltaQCovariateEmpirical = empiricalQualCO.getEmpiricalQuality(); - return deltaQCovariateEmpirical - qualFromRead - (globalDeltaQ + deltaQReported); + final double deltaQCovariateEmpirical = empiricalQualCO.getEmpiricalQuality( deltaQReported + globalDeltaQ + qualFromRead ); + return deltaQCovariateEmpirical - ( deltaQReported + globalDeltaQ + qualFromRead ); } else { return 0.0; } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java index 9430caaac..743c56ee5 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java @@ -78,6 +78,9 @@ import org.apache.commons.math.optimization.fitting.GaussianFunction; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; +import java.util.HashMap; +import java.util.Map; + /** * An individual piece of recalibration data. Each bin counts up the number of observations and the number @@ -111,6 +114,11 @@ public class RecalDatum { */ private double empiricalQuality; + /** + * the empirical quality for datums that have been collapsed together (by read group and reported quality, for example) + */ + private Map empiricalQualityMap; + /** * number of bases seen in total */ @@ -148,6 +156,7 @@ public class RecalDatum { numMismatches = _numMismatches; estimatedQReported = reportedQuality; empiricalQuality = UNINITIALIZED; + empiricalQualityMap = new HashMap(); } /** @@ -159,6 +168,7 @@ public class RecalDatum { this.numMismatches = copy.getNumMismatches(); this.estimatedQReported = copy.estimatedQReported; this.empiricalQuality = copy.empiricalQuality; + empiricalQualityMap = copy.empiricalQualityMap; } /** @@ -172,6 +182,7 @@ public class RecalDatum { increment(other.getNumObservations(), other.getNumMismatches()); estimatedQReported = -10 * Math.log10(sumErrors / getNumObservations()); empiricalQuality = UNINITIALIZED; + empiricalQualityMap = new HashMap(); } public synchronized void setEstimatedQReported(final double estimatedQReported) { @@ -314,22 +325,37 @@ public class RecalDatum { return getNumObservations() * QualityUtils.qualToErrorProb(estimatedQReported); } + /** + * Calculate empirical quality score from mismatches, observations, and the given conditional prior (expensive operation) + */ + public double getEmpiricalQuality(final double conditionalPriorQ) { + + final int priorQKey = MathUtils.fastRound(conditionalPriorQ); + Double returnQ = empiricalQualityMap.get(priorQKey); + + if( returnQ == null ) { + // smoothing is one error and one non-error observation + final long mismatches = (long)(getNumMismatches() + 0.5) + SMOOTHING_CONSTANT; + final long observations = getNumObservations() + SMOOTHING_CONSTANT + SMOOTHING_CONSTANT; + + final double empiricalQual = RecalDatum.bayesianEstimateOfEmpiricalQuality(observations, mismatches, conditionalPriorQ); + + // This is the old and busted point estimate approach: + //final double empiricalQual = -10 * Math.log10(getEmpiricalErrorRate()); + + returnQ = Math.min(empiricalQual, (double) QualityUtils.MAX_RECALIBRATED_Q_SCORE); + empiricalQualityMap.put( priorQKey, returnQ ); + } + return returnQ; + } + /** * Calculate and cache the empirical quality score from mismatches and observations (expensive operation) */ @Requires("empiricalQuality == UNINITIALIZED") @Ensures("empiricalQuality != UNINITIALIZED") private synchronized void calcEmpiricalQuality() { - - // smoothing is one error and one non-error observation - final long mismatches = (long)(getNumMismatches() + 0.5) + SMOOTHING_CONSTANT; - final long observations = getNumObservations() + SMOOTHING_CONSTANT + SMOOTHING_CONSTANT; - - final double empiricalQual = RecalDatum.bayesianEstimateOfEmpiricalQuality(observations, mismatches, getEstimatedQReported()); - - // This is the old and busted point estimate approach: - //final double empiricalQual = -10 * Math.log10(getEmpiricalErrorRate()); - + final double empiricalQual = getEmpiricalQuality(getEstimatedQReported()); empiricalQuality = Math.min(empiricalQual, (double) QualityUtils.MAX_RECALIBRATED_Q_SCORE); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index 9cd88001c..6520947d4 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -241,6 +241,9 @@ public class GATKArgumentCollection { @Argument(fullName = "preserve_qscores_less_than", shortName = "preserveQ", doc = "Bases with quality scores less than this threshold won't be recalibrated (with -BQSR)", required = false) public int PRESERVE_QSCORES_LESS_THAN = QualityUtils.MIN_USABLE_Q_SCORE; + @Argument(fullName = "qlobalQScorePrior", shortName = "qlobalQScorePrior", doc = "The global Qscore Bayesian prior to use in the BQSR. If specified, this value will be used as the prior for all mismatch quality scores instead of the actual reported quality score", required = false) + public double globalQScorePrior = -1.0; + // -------------------------------------------------------------------------------------------------------------- // // Other utility arguments diff --git a/public/java/src/org/broadinstitute/sting/utils/recalibration/BQSRArgumentSet.java b/public/java/src/org/broadinstitute/sting/utils/recalibration/BQSRArgumentSet.java index dbf70f4ce..600700484 100644 --- a/public/java/src/org/broadinstitute/sting/utils/recalibration/BQSRArgumentSet.java +++ b/public/java/src/org/broadinstitute/sting/utils/recalibration/BQSRArgumentSet.java @@ -36,6 +36,7 @@ public class BQSRArgumentSet { private boolean disableIndelQuals; private boolean emitOriginalQuals; private int PRESERVE_QSCORES_LESS_THAN; + private double globalQScorePrior; public BQSRArgumentSet(final GATKArgumentCollection args) { this.BQSR_RECAL_FILE = args.BQSR_RECAL_FILE; @@ -43,6 +44,7 @@ public class BQSRArgumentSet { this.disableIndelQuals = args.disableIndelQuals; this.emitOriginalQuals = args.emitOriginalQuals; this.PRESERVE_QSCORES_LESS_THAN = args.PRESERVE_QSCORES_LESS_THAN; + this.globalQScorePrior = args.globalQScorePrior; } public File getRecalFile() { return BQSR_RECAL_FILE; } @@ -55,6 +57,8 @@ public class BQSRArgumentSet { public int getPreserveQscoresLessThan() { return PRESERVE_QSCORES_LESS_THAN; } + public double getGlobalQScorePrior() { return globalQScorePrior; } + public void setRecalFile(final File BQSR_RECAL_FILE) { this.BQSR_RECAL_FILE = BQSR_RECAL_FILE; } @@ -74,4 +78,8 @@ public class BQSRArgumentSet { public void setPreserveQscoresLessThan(final int PRESERVE_QSCORES_LESS_THAN) { this.PRESERVE_QSCORES_LESS_THAN = PRESERVE_QSCORES_LESS_THAN; } + + public void setGlobalQScorePrior(final double globalQScorePrior) { + this.globalQScorePrior = globalQScorePrior; + } } From c103623cf69b272706da0b3748c3be6a2425c4fb Mon Sep 17 00:00:00 2001 From: Ami Levy-Moonshine Date: Mon, 28 Jan 2013 19:04:39 -0500 Subject: [PATCH 118/188] bug fix in my new function at SampleUtils.java --- .../java/src/org/broadinstitute/sting/utils/SampleUtils.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java index 6a430588b..6e4904585 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java @@ -143,8 +143,11 @@ public class SampleUtils { for ( Map.Entry val : VCF_Headers.entrySet() ) { VCFHeader header = val.getValue(); for ( String sample : header.getGenotypeSamples() ) { - if (samples.add(sample)) + if (samples.contains(sample)){ + return false; + } + samples.add(sample); } } From 5995f01a016a16be9568c28f30ba77bc59218dd1 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Mon, 28 Jan 2013 19:55:46 -0500 Subject: [PATCH 119/188] Big intermediate commit (mostly so that I don't have to go again through merge/rebase hell) in expanding BQSR capabilities. Far from done yet: a) Add option to stratify CalibrateGenotypeLikelihoods by repeat - will add integration test in next push. b) Simulator to produce BAM files with given error profile - for now only given SNP/indel error rate can be given. A bad context can be specified and if such context is present then error rate is increased to given value. c) Rewrote RepeatLength covariate to do the right thing - not fully working yet, work in progress. d) Additional experimental covariates to log repeat unit and combined repeat unit+length. Needs code refactoring/testing --- .../gatk/walkers/bqsr/BaseRecalibrator.java | 6 +- .../sting/utils/recalibration/RecalUtils.java | 2 +- .../covariates/RepeatLengthCovariate.java | 239 ++++++++++++-- .../RepeatUnitAndLengthCovariate.java | 295 ++++++++++++++++++ .../covariates/RepeatUnitCovariate.java | 288 +++++++++++++++++ .../RepeatLengthCovariateUnitTest.java | 216 +++++++++++++ .../variantcontext/VariantContextUtils.java | 37 ++- .../VariantContextUnitTest.java | 10 +- 8 files changed, 1046 insertions(+), 47 deletions(-) create mode 100644 protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java create mode 100644 protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java create mode 100644 protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java index d6c5e82f6..002bdc39f 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java @@ -280,7 +280,7 @@ public class BaseRecalibrator extends ReadWalker implements NanoSche * @param hasEvents a vector a vectors of 0 (no event) and 1 (has event) * @return the total number of events across all hasEvent arrays */ - private int nEvents(final int[]... hasEvents) { + protected static int nEvents(final int[]... hasEvents) { int n = 0; for ( final int[] hasEvent : hasEvents ) { n += MathUtils.sum(hasEvent); @@ -302,7 +302,7 @@ public class BaseRecalibrator extends ReadWalker implements NanoSche return ReadUtils.isSOLiDRead(read) && RAC.SOLID_RECAL_MODE != RecalUtils.SOLID_RECAL_MODE.DO_NOTHING && !RecalUtils.isColorSpaceConsistent(read, offset); } - protected boolean[] calculateKnownSites( final GATKSAMRecord read, final List features ) { + protected static boolean[] calculateKnownSites( final GATKSAMRecord read, final List features ) { final int readLength = read.getReadBases().length; final boolean[] knownSites = new boolean[readLength]; Arrays.fill(knownSites, false); @@ -464,7 +464,7 @@ public class BaseRecalibrator extends ReadWalker implements NanoSche * @return a BAQ-style non-null byte[] counting NO_BAQ_UNCERTAINTY values * // TODO -- could be optimized avoiding this function entirely by using this inline if the calculation code above */ - private byte[] flatBAQArray(final GATKSAMRecord read) { + protected static byte[] flatBAQArray(final GATKSAMRecord read) { final byte[] baq = new byte[read.getReadLength()]; Arrays.fill(baq, NO_BAQ_UNCERTAINTY); return baq; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java index 34aa5abc7..e44f2e06e 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java @@ -477,7 +477,7 @@ public class RecalUtils { } } - private static List generateValuesFromKeys(final List keys, final Covariate[] covariates, final Map covariateNameMap) { + protected static List generateValuesFromKeys(final List keys, final Covariate[] covariates, final Map covariateNameMap) { final List values = new ArrayList(4); values.add(covariates[RecalibrationTables.TableType.READ_GROUP_TABLE.ordinal()].formatKey((Integer)keys.get(0))); final int covariateIndex = (Integer)keys.get(1); diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java index 638d9fb93..b6266a543 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java @@ -46,63 +46,248 @@ package org.broadinstitute.sting.utils.recalibration.covariates; +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.recalibration.ReadCovariates; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.Arrays; - -/** - * Created with IntelliJ IDEA. - * User: rpoplin - * Date: 11/3/12 - */ +import java.util.HashMap; +import java.util.Map; +import java.util.Set; public class RepeatLengthCovariate implements ExperimentalCovariate { final int MAX_REPEAT_LENGTH = 20; + final int MAX_STR_UNIT_LENGTH = 1; // =1 will restrict effectively to detecting homopolymer runs + public final boolean RECORD_REPUNIT_WITH_REPLENGTH = false; + private final HashMap repeatLookupTable = new HashMap(); + private final HashMap repeatReverseLookupTable = new HashMap(); + private int nextId = 0; // Initialize any member variables using the command-line arguments passed to the walkers @Override - public void initialize(final RecalibrationArgumentCollection RAC) {} + public void initialize(final RecalibrationArgumentCollection RAC) { + } @Override public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { - byte[] readBytes = read.getReadBases(); - for (int i = 0; i < readBytes.length; i++) { - int maxRL = 0; - for (int str = 1; str <= 8; str++) { - if (i + str <= readBytes.length) { - maxRL = Math.max(maxRL, VariantContextUtils.findNumberofRepetitions( - Arrays.copyOfRange(readBytes, i, i + str), - Arrays.copyOfRange(readBytes, i, readBytes.length) - )); + // store the original bases and then write Ns over low quality ones + final byte[] originalBases = read.getReadBases().clone(); + + final boolean negativeStrand = read.getReadNegativeStrandFlag(); + byte[] bases = read.getReadBases(); + if (negativeStrand) + bases = BaseUtils.simpleReverseComplement(bases); + + // don't record reads with N's + if (!BaseUtils.isAllRegularBases(bases)) + return; + + for (int i = 0; i < bases.length; i++) { + final Pair res = findTandemRepeatUnits(bases, i); + // merge repeat unit and repeat length to get covariate value + final String repeatID = repeatFromUnitAndLength(res.first, res.second); + final int key = keyForRepeat(repeatID); + + final int readOffset = (negativeStrand ? bases.length - i - 1 : i); + values.addCovariate(key, key, key, readOffset); + } + + // put the original bases back in + read.setReadBases(originalBases); + + } + + private Pair findTandemRepeatUnits(byte[] readBases, int offset) { + int maxBW = 0; + byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+1-str < 0) + break; + + // get backward repeat unit and # repeats + byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); + maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); + if (maxBW > 1) { + bestBWRepeatUnit = backwardRepeatUnit.clone(); + break; + } + } + byte[] bestRepeatUnit = bestBWRepeatUnit; + int maxRL = maxBW; + + if (offset < readBases.length-1) { + byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; + int maxFW = 0; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+str+1 > readBases.length) + break; + + // get forward repeat unit and # repeats + byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); + maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); + if (maxFW > 1) { + bestFWRepeatUnit = forwardRepeatUnit.clone(); + break; } } - if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } - values.addCovariate(maxRL, maxRL, maxRL, i); - } - } + // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components + if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { + maxRL = maxBW + maxFW; + bestRepeatUnit = bestFWRepeatUnit; // arbitrary + } + else { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; - // Used to get the covariate's value from input csv file during on-the-fly recalibration + } +/* if (maxFW > maxBW) { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + } + else if (maxFW < maxBW) { + maxRL = maxBW; + bestRepeatUnit = bestBWRepeatUnit; + } */ + /* else { + // maxFW = maxBW but repeat units different: not in a tandem repeat. + maxRL = 1; + bestRepeatUnit = bestBWRepeatUnit; // arbitrary + } */ + + } + + + + if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } + return new Pair(bestRepeatUnit, maxRL); + + } @Override public final Object getValue(final String str) { - return Byte.parseByte(str); + return str; } @Override - public String formatKey(final int key) { - return String.format("%d", key); + public synchronized String formatKey(final int key) { + // This method is synchronized so that we don't attempt to do a get() + // from the reverse lookup table while that table is being updated + return repeatReverseLookupTable.get(key); } @Override public int keyFromValue(final Object value) { - return (value instanceof String) ? Integer.parseInt((String) value) : (Integer) value; + return keyForRepeat((String) value); + } + + /** + * Get the mapping from read group names to integer key values for all read groups in this covariate + * @return a set of mappings from read group names -> integer key values + */ + public Set> getKeyMap() { + return repeatLookupTable.entrySet(); + } + + @Requires({"repeatLength>=0", "repeatFromUnitAndLength != null"}) + @Ensures("result != null") + private String repeatFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { + if (RECORD_REPUNIT_WITH_REPLENGTH) + return new String(repeatFromUnitAndLength) + String.format("%d",repeatLength); + else + return String.format("%d",repeatLength); + } + + private int keyForRepeat(final String repeatID) { + // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), + // synchronize only the table updates. + + // Before entering the synchronized block, check to see if this read group is not in our tables. + // If it's not, either we will have to insert it, OR another thread will insert it first. + // This preliminary check avoids doing any synchronization most of the time. + if ( ! repeatLookupTable.containsKey(repeatID) ) { + + synchronized ( this ) { + + // Now we need to make sure the key is STILL not there, since another thread may have come along + // and inserted it while we were waiting to enter this synchronized block! + if ( ! repeatLookupTable.containsKey(repeatID) ) { + repeatLookupTable.put(repeatID, nextId); + repeatReverseLookupTable.put(nextId, repeatID); + nextId++; + } + } + } + + return repeatLookupTable.get(repeatID); + } + + + /** + * Splits repeat unit and num repetitions from covariate value. + * For example, if value if "ATG4" it returns (ATG,4) + * @param value Covariate value + * @return Split pair + */ + @Requires("value != null") + @Ensures({"result.first != null","result.second>=0"}) + public static Pair getRUandNRfromCovariate(final String value) { + + int k = 0; + for ( k=0; k < value.length(); k++ ) { + if (!BaseUtils.isRegularBase(value.getBytes()[k])) + break; + } + Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal + if (k == value.length() || nr <= 0) + throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); + + return new Pair(value.substring(0,k), nr); + } + + /** + * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). + * For example, (AGC),3 returns AGCAGCAGC + * @param repeatUnit Tandem repeat unit + * @param numRepeats Number of repeats + * @return Expanded String + */ + @Requires({"numRepeats > 0","repeatUnit != null"}) + @Ensures("result != null") + public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { + final StringBuilder sb = new StringBuilder(); + + for (int i=0; i < numRepeats; i++) + sb.append(repeatUnit); + + return sb.toString(); + } + + // version given covariate key + public static String getBasesFromRUandNR(final String covariateValue) { + Pair pair = getRUandNRfromCovariate(covariateValue); + return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); } @Override - public int maximumKeyValue() { - return MAX_REPEAT_LENGTH + 1; + public synchronized int maximumKeyValue() { + // Synchronized so that we don't query table size while the tables are being updated + //return repeatLookupTable.size() - 1; + // max possible values of covariate: for repeat unit, length is up to MAX_STR_UNIT_LENGTH, + // so we have 4^MAX_STR_UNIT_LENGTH * MAX_REPEAT_LENGTH possible values + if (RECORD_REPUNIT_WITH_REPLENGTH) + return (1<<(2*MAX_STR_UNIT_LENGTH)) * MAX_REPEAT_LENGTH +1; + else + return (1+MAX_REPEAT_LENGTH); } } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java new file mode 100644 index 000000000..36c5d57d3 --- /dev/null +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java @@ -0,0 +1,295 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.utils.recalibration.covariates; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; +import org.broadinstitute.sting.utils.recalibration.ReadCovariates; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +public class RepeatUnitAndLengthCovariate implements ExperimentalCovariate { + final int MAX_REPEAT_LENGTH = 20; + final int MAX_STR_UNIT_LENGTH = 8; + public final boolean RECORD_REPUNIT_WITH_REPLENGTH = true; + private final HashMap repeatLookupTable = new HashMap(); + private final HashMap repeatReverseLookupTable = new HashMap(); + private int nextId = 0; + + // Initialize any member variables using the command-line arguments passed to the walkers + @Override + public void initialize(final RecalibrationArgumentCollection RAC) { + } + + @Override + public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { + // store the original bases and then write Ns over low quality ones + final byte[] originalBases = read.getReadBases().clone(); + + final boolean negativeStrand = read.getReadNegativeStrandFlag(); + byte[] bases = read.getReadBases(); + if (negativeStrand) + bases = BaseUtils.simpleReverseComplement(bases); + + // don't record reads with N's + if (!BaseUtils.isAllRegularBases(bases)) + return; + + for (int i = 0; i < bases.length; i++) { + final Pair res = findTandemRepeatUnits(bases, i); + // merge repeat unit and repeat length to get covariate value + final String repeatID = repeatFromUnitAndLength(res.first, res.second); + final int key = keyForRepeat(repeatID); + + final int readOffset = (negativeStrand ? bases.length - i - 1 : i); + values.addCovariate(key, key, key, readOffset); + } + + // put the original bases back in + read.setReadBases(originalBases); + + } + + private Pair findTandemRepeatUnits(byte[] readBases, int offset) { + int maxBW = 0; + byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+1-str < 0) + break; + + // get backward repeat unit and # repeats + byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); + maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); + if (maxBW > 1) { + bestBWRepeatUnit = backwardRepeatUnit.clone(); + break; + } + } + byte[] bestRepeatUnit = bestBWRepeatUnit; + int maxRL = maxBW; + + if (offset < readBases.length-1) { + byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; + int maxFW = 0; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+str+1 > readBases.length) + break; + + // get forward repeat unit and # repeats + byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); + maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); + if (maxFW > 1) { + bestFWRepeatUnit = forwardRepeatUnit.clone(); + break; + } + } + // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components + if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { + maxRL = maxBW + maxFW; + bestRepeatUnit = bestFWRepeatUnit; // arbitrary + } + else { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + + } +/* if (maxFW > maxBW) { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + } + else if (maxFW < maxBW) { + maxRL = maxBW; + bestRepeatUnit = bestBWRepeatUnit; + } */ + /* else { + // maxFW = maxBW but repeat units different: not in a tandem repeat. + maxRL = 1; + bestRepeatUnit = bestBWRepeatUnit; // arbitrary + } */ + + } + + + + if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } + return new Pair(bestRepeatUnit, maxRL); + + } + @Override + public final Object getValue(final String str) { + return str; + } + + @Override + public synchronized String formatKey(final int key) { + // This method is synchronized so that we don't attempt to do a get() + // from the reverse lookup table while that table is being updated + return repeatReverseLookupTable.get(key); + } + + @Override + public int keyFromValue(final Object value) { + return keyForRepeat((String) value); + } + + /** + * Get the mapping from read group names to integer key values for all read groups in this covariate + * @return a set of mappings from read group names -> integer key values + */ + public Set> getKeyMap() { + return repeatLookupTable.entrySet(); + } + + @Requires({"repeatLength>=0", "repeatFromUnitAndLength != null"}) + @Ensures("result != null") + private String repeatFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { + if (RECORD_REPUNIT_WITH_REPLENGTH) + return new String(repeatFromUnitAndLength) + String.format("%d",repeatLength); + else + return String.format("%d",repeatLength); + } + + private int keyForRepeat(final String repeatID) { + // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), + // synchronize only the table updates. + + // Before entering the synchronized block, check to see if this read group is not in our tables. + // If it's not, either we will have to insert it, OR another thread will insert it first. + // This preliminary check avoids doing any synchronization most of the time. + if ( ! repeatLookupTable.containsKey(repeatID) ) { + + synchronized ( this ) { + + // Now we need to make sure the key is STILL not there, since another thread may have come along + // and inserted it while we were waiting to enter this synchronized block! + if ( ! repeatLookupTable.containsKey(repeatID) ) { + repeatLookupTable.put(repeatID, nextId); + repeatReverseLookupTable.put(nextId, repeatID); + nextId++; + } + } + } + + return repeatLookupTable.get(repeatID); + } + + + /** + * Splits repeat unit and num repetitions from covariate value. + * For example, if value if "ATG4" it returns (ATG,4) + * @param value Covariate value + * @return Split pair + */ + @Requires("value != null") + @Ensures({"result.first != null","result.second>=0"}) + public static Pair getRUandNRfromCovariate(final String value) { + + int k = 0; + for ( k=0; k < value.length(); k++ ) { + if (!BaseUtils.isRegularBase(value.getBytes()[k])) + break; + } + Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal + if (k == value.length() || nr <= 0) + throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); + + return new Pair(value.substring(0,k), nr); + } + + /** + * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). + * For example, (AGC),3 returns AGCAGCAGC + * @param repeatUnit Tandem repeat unit + * @param numRepeats Number of repeats + * @return Expanded String + */ + @Requires({"numRepeats > 0","repeatUnit != null"}) + @Ensures("result != null") + public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { + final StringBuilder sb = new StringBuilder(); + + for (int i=0; i < numRepeats; i++) + sb.append(repeatUnit); + + return sb.toString(); + } + + // version given covariate key + public static String getBasesFromRUandNR(final String covariateValue) { + Pair pair = getRUandNRfromCovariate(covariateValue); + return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); + } + + @Override + public synchronized int maximumKeyValue() { + // Synchronized so that we don't query table size while the tables are being updated + //return repeatLookupTable.size() - 1; + // max possible values of covariate: for repeat unit, length is up to MAX_STR_UNIT_LENGTH, + // so we have 4^MAX_STR_UNIT_LENGTH * MAX_REPEAT_LENGTH possible values + if (RECORD_REPUNIT_WITH_REPLENGTH) + return (1<<(2*MAX_STR_UNIT_LENGTH)) * MAX_REPEAT_LENGTH +1; + else + return (1+MAX_REPEAT_LENGTH); + } + +} diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java new file mode 100644 index 000000000..9e98e741e --- /dev/null +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java @@ -0,0 +1,288 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.utils.recalibration.covariates; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; +import org.broadinstitute.sting.utils.recalibration.ReadCovariates; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Created with IntelliJ IDEA. + * User: rpoplin + * Date: 11/3/12 + */ + +public class RepeatUnitCovariate implements ExperimentalCovariate { + final int MAX_REPEAT_LENGTH = 20; + final int MAX_STR_UNIT_LENGTH = 8; + private final HashMap repeatLookupTable = new HashMap(); + private final HashMap repeatReverseLookupTable = new HashMap(); + private int nextId = 0; + + // Initialize any member variables using the command-line arguments passed to the walkers + @Override + public void initialize(final RecalibrationArgumentCollection RAC) { + } + + @Override + public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { + // store the original bases and then write Ns over low quality ones + final byte[] originalBases = read.getReadBases().clone(); + + final boolean negativeStrand = read.getReadNegativeStrandFlag(); + byte[] bases = read.getReadBases(); + if (negativeStrand) + bases = BaseUtils.simpleReverseComplement(bases); + + // don't record reads with N's + if (!BaseUtils.isAllRegularBases(bases)) + return; + + for (int i = 0; i < bases.length; i++) { + final Pair res = findTandemRepeatUnits(bases, i); + // to merge repeat unit and repeat length to get covariate value: + //final String repeatID = repeatFromUnitAndLength(res.first, res.second); + final String repeatID = new String(res.first); + final int key = keyForRepeat(repeatID); + + final int readOffset = (negativeStrand ? bases.length - i - 1 : i); + values.addCovariate(key, key, key, readOffset); + } + + // put the original bases back in + read.setReadBases(originalBases); + + } + + private Pair findTandemRepeatUnits(byte[] readBases, int offset) { + int maxBW = 0; + byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+1-str < 0) + break; + + // get backward repeat unit and # repeats + byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); + maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); + if (maxBW > 1) { + bestBWRepeatUnit = backwardRepeatUnit.clone(); + break; + } + } + byte[] bestRepeatUnit = bestBWRepeatUnit; + int maxRL = maxBW; + + if (offset < readBases.length-1) { + byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; + int maxFW = 0; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+str+1 > readBases.length) + break; + + // get forward repeat unit and # repeats + byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); + maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); + if (maxFW > 1) { + bestFWRepeatUnit = forwardRepeatUnit.clone(); + break; + } + } + // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components + if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { + maxRL = maxBW + maxFW; + bestRepeatUnit = bestFWRepeatUnit; // arbitrary + } + else { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + + } +/* if (maxFW > maxBW) { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + } + else if (maxFW < maxBW) { + maxRL = maxBW; + bestRepeatUnit = bestBWRepeatUnit; + } */ + /* else { + // maxFW = maxBW but repeat units different: not in a tandem repeat. + maxRL = 1; + bestRepeatUnit = bestBWRepeatUnit; // arbitrary + } */ + + } + + + + if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } + return new Pair(bestRepeatUnit, maxRL); + + } + @Override + public final Object getValue(final String str) { + return str; + } + + @Override + public synchronized String formatKey(final int key) { + // This method is synchronized so that we don't attempt to do a get() + // from the reverse lookup table while that table is being updated + return repeatReverseLookupTable.get(key); + } + + @Override + public int keyFromValue(final Object value) { + return keyForRepeat((String) value); + } + + /** + * Get the mapping from read group names to integer key values for all read groups in this covariate + * @return a set of mappings from read group names -> integer key values + */ + public Set> getKeyMap() { + return repeatLookupTable.entrySet(); + } + + private int keyForRepeat(final String repeatID) { + // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), + // synchronize only the table updates. + + // Before entering the synchronized block, check to see if this read group is not in our tables. + // If it's not, either we will have to insert it, OR another thread will insert it first. + // This preliminary check avoids doing any synchronization most of the time. + if ( ! repeatLookupTable.containsKey(repeatID) ) { + + synchronized ( this ) { + + // Now we need to make sure the key is STILL not there, since another thread may have come along + // and inserted it while we were waiting to enter this synchronized block! + if ( ! repeatLookupTable.containsKey(repeatID) ) { + repeatLookupTable.put(repeatID, nextId); + repeatReverseLookupTable.put(nextId, repeatID); + nextId++; + } + } + } + + return repeatLookupTable.get(repeatID); + } + + + /** + * Splits repeat unit and num repetitions from covariate value. + * For example, if value if "ATG4" it returns (ATG,4) + * @param value Covariate value + * @return Split pair + */ + @Requires("value != null") + @Ensures({"result.first != null","result.second>=0"}) + public static Pair getRUandNRfromCovariate(final String value) { + + int k = 0; + for ( k=0; k < value.length(); k++ ) { + if (!BaseUtils.isRegularBase(value.getBytes()[k])) + break; + } + Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal + if (k == value.length() || nr <= 0) + throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); + + return new Pair(value.substring(0,k), nr); + } + + /** + * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). + * For example, (AGC),3 returns AGCAGCAGC + * @param repeatUnit Tandem repeat unit + * @param numRepeats Number of repeats + * @return Expanded String + */ + @Requires({"numRepeats > 0","repeatUnit != null"}) + @Ensures("result != null") + public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { + final StringBuilder sb = new StringBuilder(); + + for (int i=0; i < numRepeats; i++) + sb.append(repeatUnit); + + return sb.toString(); + } + + // version given covariate key + public static String getBasesFromRUandNR(final String covariateValue) { + Pair pair = getRUandNRfromCovariate(covariateValue); + return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); + } + + @Override + public synchronized int maximumKeyValue() { + // Synchronized so that we don't query table size while the tables are being updated + //return repeatLookupTable.size() - 1; + // max possible values of covariate: for repeat unit, length is up to MAX_STR_UNIT_LENGTH, + // so we have 4^MAX_STR_UNIT_LENGTH * MAX_REPEAT_LENGTH possible values + return (1<<(2*MAX_STR_UNIT_LENGTH)) +1; + } + + +} diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java new file mode 100644 index 000000000..6880c9d23 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java @@ -0,0 +1,216 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ +package org.broadinstitute.sting.utils.recalibration; + +import com.google.java.contract.Requires; +import net.sf.samtools.SAMFileHeader; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; +import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.sting.utils.recalibration.EventType; +import org.broadinstitute.sting.utils.recalibration.ReadCovariates; +import org.broadinstitute.sting.utils.recalibration.covariates.ReadGroupCovariate; +import org.broadinstitute.sting.utils.recalibration.covariates.RepeatLengthCovariate; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.variant.utils.BaseUtils; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Random; + +public class RepeatLengthCovariateUnitTest { + + RepeatLengthCovariate covariate; + RecalibrationArgumentCollection RAC; + + + + @BeforeClass + public void init() { + RAC = new RecalibrationArgumentCollection(); + covariate = new RepeatLengthCovariate(); + covariate.initialize(RAC); + } + + + @Test(enabled = true) + public void testFindNumberOfRepetitions() { + // First, test logic to compute number of repetitions of a substring on a given string. + int result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), true); + Assert.assertEquals(2,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), true); + Assert.assertEquals(4,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), true); + Assert.assertEquals(4,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), true); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), true); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), true); + Assert.assertEquals(1,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), true); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), true); + Assert.assertEquals(0,result); + // Same tests but looking backward on string + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), false); + Assert.assertEquals(2,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), false); + Assert.assertEquals(4,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), false); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), false); + Assert.assertEquals(4,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), false); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), false); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), false); + Assert.assertEquals(0,result); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), false); + Assert.assertEquals(3,result); + + // test logic to get repeat unit and number of repeats from covariate value + final String[] repUnits = new String[]{"AG","CCG","TCCA","T"}; + for (String ru : repUnits) { + for (int k=1; k < 10; k++) { + Pair pair = RepeatLengthCovariate.getRUandNRfromCovariate(String.format("%s%d",ru,k)); + Assert.assertEquals(pair.second.intValue(),k); + Assert.assertEquals(pair.first,ru); + } + } + + } + + /** + * Build synthetic reads with random content made up of tandem repeats, record computed Repeat Unit and # repeats and see if + * they match with read context + */ + @Test(enabled = true) + public void testManyObservations() { + final int NUM_UNITS = 10; + final int MAX_REPEAT_UNIT_LENGTH = 6; + final int MAX_NUM_REPETITIONS = 5; + final int NUM_TEST_CASES = 1; + + Random random = new Random(); + + for (int r = 0; r < NUM_TEST_CASES; r++) { + final StringBuilder sb = new StringBuilder(); + // for each unit, generate a repeat unit at random with given random length + final ArrayList repeatUnits = new ArrayList(); + final ArrayList numsRepetitions = new ArrayList(); + for (int n=0; n < NUM_UNITS; n++) { + final int repLength = 1+random.nextInt(MAX_REPEAT_UNIT_LENGTH); + final String repeatUnit = getRandomBases(repLength); + final int numRepetitions = 1+random.nextInt(MAX_NUM_REPETITIONS); + + // log for comparison with covariate + numsRepetitions.add(numRepetitions); + repeatUnits.add(repeatUnit); + + for (int k=0; k < numRepetitions; k++) + sb.append(repeatUnit); + + } + + // final String readBases = sb.toString(); + final String readBases = "TTTTTTTTAATGGGGGAGGGAGGGAGACTTACTTACTTACTTACTTATCGGAATCGGATATATAACGGCTTTCTTCTTCCCCCCA"; + System.out.println(readBases); + + final byte[] readQuals = new byte[readBases.length()]; + Arrays.fill(readQuals,(byte)30); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(readBases.getBytes(),readQuals,readBases.length()+"M"); + + final ReadCovariates values = new ReadCovariates(read.getReadLength(),1); + covariate.recordValues( read, values); + final int fullReadKeySet[][] = values.getKeySet(EventType.BASE_SUBSTITUTION); + for (int offset = 0; offset < readBases.length(); offset++) { // recalibrate all bases in the read + final int[] keySet = fullReadKeySet[offset]; + final String val = covariate.formatKey(keySet[0]); + System.out.format("offset %d:%s\n", offset, val); +// final String repeatString = RepeatLengthCovariate.getBasesFromRUandNR(val); +// final String partialRead = readBases.substring(0,offset+1); + // Assert.assertTrue(partialRead.endsWith(repeatString)); + } + //values. + int k=0; + + + } + + + + + + + } + + /** + * Returns random bases of given length + * @param length required length + * @return given random string + */ + @Requires("length > 0") + String getRandomBases(final int length) { + byte[] bases = new byte[length]; + Random ran = new Random(); + for (int i=0; i < length; i++ ) { + int idx = ran.nextInt(4); + bases[i] = BaseUtils.baseIndexToSimpleBase(idx); + } + return new String(bases); + } + + +} diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index fb97d41ff..a6378951e 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -266,9 +266,9 @@ public class VariantContextUtils { return new Pair, byte[]>(lengths,repeatUnit); } - protected static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { + public static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units. - Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)5. + Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)2. */ byte[] longB; @@ -284,11 +284,10 @@ public class VariantContextUtils { final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength); final int[] repetitionCount = new int[2]; -// repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext)); -// repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext)); - int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases); - repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext))-repetitionsInRef; - repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext))-repetitionsInRef; + // look for repetitions forward on the ref bases (i.e. starting at beginning of ref bases) + int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases, true); + repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext), true)-repetitionsInRef; + repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext), true)-repetitionsInRef; return new Pair(repetitionCount, repeatUnit); @@ -329,17 +328,33 @@ public class VariantContextUtils { * For example, for string ATAT and repeat unit AT, number of repetitions = 2 * @param repeatUnit Substring * @param testString String to test + * @oaram lookForward Look for repetitions forward (at beginning of string) or backward (at end of string) * @return Number of repetitions (0 if testString is not a concatenation of n repeatUnit's */ - public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString) { + public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString, boolean lookForward) { int numRepeats = 0; - for (int start = 0; start < testString.length; start += repeatUnit.length) { + if (lookForward) { + // look forward on the test string + for (int start = 0; start < testString.length; start += repeatUnit.length) { + int end = start + repeatUnit.length; + byte[] unit = Arrays.copyOfRange(testString,start, end); + if(Arrays.equals(unit,repeatUnit)) + numRepeats++; + else + break; + } + return numRepeats; + } + + // look backward. For example, if repeatUnit = AT and testString = GATAT, number of repeat units is still 2 + // look forward on the test string + for (int start = testString.length - repeatUnit.length; start >= 0; start -= repeatUnit.length) { int end = start + repeatUnit.length; byte[] unit = Arrays.copyOfRange(testString,start, end); if(Arrays.equals(unit,repeatUnit)) numRepeats++; else - return numRepeats; + break; } return numRepeats; } @@ -369,7 +384,7 @@ public class VariantContextUtils { final int start = i * potentialRepeat.length(); final int end = (i+1) * potentialRepeat.length(); if ( ref.length() < end ) - return false; // we ran out of bases to test + return false; // we ran out of bases to test final String refSub = ref.substring(start, end); if ( ! refSub.equals(potentialRepeat) ) return false; // repeat didn't match, fail diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java index d09800760..25e9878ae 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java @@ -499,11 +499,11 @@ public class VariantContextUnitTest extends VariantBaseTest { Pair,byte[]> result; byte[] refBytes = "TATCATCATCGGA".getBytes(); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes()),4); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes()),0); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes()),1); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes()),1); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes()),2); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes(), true),4); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes(), true),0); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes(), true),1); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes(), true),1); + Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes(), true),2); Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3); Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1); From ff799cc79a6b17d4cd5c6baacc6a8d919d1c377f Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Mon, 28 Jan 2013 20:04:25 -0500 Subject: [PATCH 120/188] Fixed bad merge --- .../RepeatLengthCovariateUnitTest.java | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java index 6880c9d23..d08276147 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java @@ -49,16 +49,13 @@ import com.google.java.contract.Requires; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; -import org.broadinstitute.sting.utils.collections.Pair; -import org.broadinstitute.sting.utils.recalibration.EventType; -import org.broadinstitute.sting.utils.recalibration.ReadCovariates; -import org.broadinstitute.sting.utils.recalibration.covariates.ReadGroupCovariate; import org.broadinstitute.sting.utils.recalibration.covariates.RepeatLengthCovariate; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -86,38 +83,38 @@ public class RepeatLengthCovariateUnitTest { @Test(enabled = true) public void testFindNumberOfRepetitions() { // First, test logic to compute number of repetitions of a substring on a given string. - int result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), true); + int result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACAC".getBytes(), true); Assert.assertEquals(2,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), true); Assert.assertEquals(4,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), true); Assert.assertEquals(4,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), true); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), true); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), true); Assert.assertEquals(1,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), true); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), true); + result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), true); Assert.assertEquals(0,result); // Same tests but looking backward on string - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), false); Assert.assertEquals(2,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), false); Assert.assertEquals(4,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), false); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), false); Assert.assertEquals(4,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), false); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), false); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), false); Assert.assertEquals(0,result); - result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), false); + result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), false); Assert.assertEquals(3,result); // test logic to get repeat unit and number of repeats from covariate value From 1f254d29df1c249de917a85ae5c8a756742f9697 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Mon, 28 Jan 2013 22:16:43 -0500 Subject: [PATCH 121/188] Don't set the empirical quality when reading in the recal table because then we won't be using the new quality estimates for the prior since the value is cached. --- .../recalibration/BaseRecalibration.java | 60 +++++++++---------- .../sting/utils/recalibration/RecalDatum.java | 58 ++++++------------ .../recalibration/RecalibrationReport.java | 4 +- 3 files changed, 51 insertions(+), 71 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index 6852cc40f..ba18f5c96 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -81,9 +81,10 @@ public class BaseRecalibration { private final NestedIntegerArray globalDeltaQs; private final NestedIntegerArray deltaQReporteds; + /** * Constructor using a GATK Report file - * + * * @param RECAL_FILE a GATK Report file containing the recalibration information * @param quantizationLevels number of bins to quantize the quality scores * @param disableIndelQuals if true, do not emit base indel qualities @@ -113,16 +114,13 @@ public class BaseRecalibration { // be done upfront, on initialization of this BaseRecalibration structure // final NestedIntegerArray byReadGroupTable = recalibrationTables.getReadGroupTable(); - final NestedIntegerArray byQualTable = recalibrationTables.getQualityScoreTable(); - - globalDeltaQs = new NestedIntegerArray( byQualTable.getDimensions() ); + globalDeltaQs = new NestedIntegerArray( byReadGroupTable.getDimensions() ); logger.info("Calculating global delta Q table..."); - for ( NestedIntegerArray.Leaf leaf : byQualTable.getAllLeaves() ) { + for ( NestedIntegerArray.Leaf leaf : byReadGroupTable.getAllLeaves() ) { final int rgKey = leaf.keys[0]; - final int qual = leaf.keys[1]; - final int eventIndex = leaf.keys[2]; - final double globalDeltaQ = calculateGlobalDeltaQ(rgKey, EventType.eventFrom(eventIndex), (byte) qual); - globalDeltaQs.put(globalDeltaQ, rgKey, qual, eventIndex); + final int eventIndex = leaf.keys[1]; + final double globalDeltaQ = calculateGlobalDeltaQ(rgKey, EventType.eventFrom(eventIndex)); + globalDeltaQs.put(globalDeltaQ, rgKey, eventIndex); } @@ -131,6 +129,7 @@ public class BaseRecalibration { // into a matrix indexed by rgGroup, qual, and event type. // the code below actually creates this cache with a NestedIntegerArray calling into the actual // calculateDeltaQReported code. + final NestedIntegerArray byQualTable = recalibrationTables.getQualityScoreTable(); deltaQReporteds = new NestedIntegerArray( byQualTable.getDimensions() ); logger.info("Calculating delta Q reported table..."); for ( NestedIntegerArray.Leaf leaf : byQualTable.getAllLeaves() ) { @@ -138,7 +137,7 @@ public class BaseRecalibration { final int qual = leaf.keys[1]; final int eventIndex = leaf.keys[2]; final EventType event = EventType.eventFrom(eventIndex); - final double globalDeltaQ = getGlobalDeltaQ(rgKey, event, (byte)qual); + final double globalDeltaQ = getGlobalDeltaQ(rgKey, event); final double deltaQReported = calculateDeltaQReported(rgKey, qual, event, globalDeltaQ, (byte)qual); deltaQReporteds.put(deltaQReported, rgKey, qual, eventIndex); } @@ -191,17 +190,17 @@ public class BaseRecalibration { // the rg key is constant over the whole read, the global deltaQ is too final int rgKey = fullReadKeySet[0][0]; + final double globalDeltaQ = getGlobalDeltaQ(rgKey, errorModel); for (int offset = 0; offset < readLength; offset++) { // recalibrate all bases in the read final byte origQual = quals[offset]; - final double globalDeltaQ = getGlobalDeltaQ(rgKey, errorModel, origQual); // only recalibrate usable qualities (the original quality will come from the instrument -- reported quality) if ( origQual >= preserveQLessThan ) { // get the keyset for this base using the error model final int[] keySet = fullReadKeySet[offset]; - final double deltaQReported = getDeltaQReported(keySet[0], keySet[1], errorModel, globalDeltaQ, origQual); - final double deltaQCovariates = calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, deltaQReported, globalDeltaQ, origQual); + final double deltaQReported = getDeltaQReported(keySet[0], keySet[1], errorModel, globalDeltaQ); + final double deltaQCovariates = calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, globalDeltaQ, deltaQReported, origQual); // calculate the recalibrated qual using the BQSR formula double recalibratedQualDouble = origQual + globalDeltaQ + deltaQReported + deltaQCovariates; @@ -213,6 +212,10 @@ public class BaseRecalibration { final byte recalibratedQualityScore = quantizationInfo.getQuantizedQuals().get(recalibratedQual); quals[offset] = recalibratedQualityScore; + if( quals[offset] > QualityUtils.MAX_REASONABLE_Q_SCORE ) { + System.out.println("A"); + //calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, globalDeltaQ, deltaQReported, origQual); + } } } @@ -221,12 +224,11 @@ public class BaseRecalibration { } } - private double getGlobalDeltaQ(final int rgKey, final EventType errorModel, final byte qualFromRead) { - - final Double cached = globalDeltaQs.get(rgKey, (int) qualFromRead, errorModel.ordinal()); + private double getGlobalDeltaQ(final int rgKey, final EventType errorModel) { + final Double cached = globalDeltaQs.get(rgKey, errorModel.ordinal()); if ( TEST_CACHING ) { - final double calcd = calculateGlobalDeltaQ(rgKey, errorModel, qualFromRead); + final double calcd = calculateGlobalDeltaQ(rgKey, errorModel); if ( calcd != cached ) throw new IllegalStateException("calculated " + calcd + " and cached " + cached + " global delta q not equal at " + rgKey + " / " + errorModel); } @@ -234,8 +236,7 @@ public class BaseRecalibration { return cachedWithDefault(cached); } - private double getDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ, final byte origQual) { - + private double getDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ) { final Double cached = deltaQReporteds.get(rgKey, qualKey, errorModel.ordinal()); if ( TEST_CACHING ) { @@ -245,7 +246,6 @@ public class BaseRecalibration { } return cachedWithDefault(cached); - } /** @@ -264,14 +264,14 @@ public class BaseRecalibration { * @param errorModel the event type * @return global delta Q */ - private double calculateGlobalDeltaQ(final int rgKey, final EventType errorModel, final byte qualFromRead) { + private double calculateGlobalDeltaQ(final int rgKey, final EventType errorModel) { double result = 0.0; final RecalDatum empiricalQualRG = recalibrationTables.getReadGroupTable().get(rgKey, errorModel.ordinal()); if (empiricalQualRG != null) { - final double aggregrateQReported = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : qualFromRead ); - final double globalDeltaQEmpirical = empiricalQualRG.getEmpiricalQuality( aggregrateQReported ); + final double aggregrateQReported = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : empiricalQualRG.getEstimatedQReported() ); + final double globalDeltaQEmpirical = empiricalQualRG.getEmpiricalQuality(aggregrateQReported); result = globalDeltaQEmpirical - aggregrateQReported; } @@ -283,14 +283,14 @@ public class BaseRecalibration { final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(rgKey, qualKey, errorModel.ordinal()); if (empiricalQualQS != null) { - final double deltaQReportedEmpirical = empiricalQualQS.getEmpiricalQuality( qualFromRead + globalDeltaQ ); - result = deltaQReportedEmpirical - ( qualFromRead + globalDeltaQ ); + final double deltaQReportedEmpirical = empiricalQualQS.getEmpiricalQuality(globalDeltaQ + qualFromRead); + result = deltaQReportedEmpirical - (globalDeltaQ + qualFromRead); } return result; } - private double calculateDeltaQCovariates(final RecalibrationTables recalibrationTables, final int[] key, final EventType errorModel, final double deltaQReported, final double globalDeltaQ, final byte qualFromRead) { + private double calculateDeltaQCovariates(final RecalibrationTables recalibrationTables, final int[] key, final EventType errorModel, final double globalDeltaQ, final double deltaQReported, final byte qualFromRead) { double result = 0.0; // for all optional covariates @@ -300,7 +300,7 @@ public class BaseRecalibration { result += calculateDeltaQCovariate(recalibrationTables.getTable(i), key[0], key[1], key[i], errorModel, - deltaQReported, globalDeltaQ, qualFromRead); + globalDeltaQ, deltaQReported, qualFromRead); } return result; @@ -311,13 +311,13 @@ public class BaseRecalibration { final int qualKey, final int tableKey, final EventType errorModel, - final double deltaQReported, final double globalDeltaQ, + final double deltaQReported, final byte qualFromRead) { final RecalDatum empiricalQualCO = table.get(rgKey, qualKey, tableKey, errorModel.ordinal()); if (empiricalQualCO != null) { - final double deltaQCovariateEmpirical = empiricalQualCO.getEmpiricalQuality( deltaQReported + globalDeltaQ + qualFromRead ); - return deltaQCovariateEmpirical - ( deltaQReported + globalDeltaQ + qualFromRead ); + final double deltaQCovariateEmpirical = empiricalQualCO.getEmpiricalQuality(deltaQReported + globalDeltaQ + qualFromRead); + return deltaQCovariateEmpirical - (deltaQReported + globalDeltaQ + qualFromRead); } else { return 0.0; } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java index 743c56ee5..67794c248 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java @@ -77,9 +77,7 @@ import com.google.java.contract.Requires; import org.apache.commons.math.optimization.fitting.GaussianFunction; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; - -import java.util.HashMap; -import java.util.Map; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; /** @@ -114,11 +112,6 @@ public class RecalDatum { */ private double empiricalQuality; - /** - * the empirical quality for datums that have been collapsed together (by read group and reported quality, for example) - */ - private Map empiricalQualityMap; - /** * number of bases seen in total */ @@ -156,7 +149,6 @@ public class RecalDatum { numMismatches = _numMismatches; estimatedQReported = reportedQuality; empiricalQuality = UNINITIALIZED; - empiricalQualityMap = new HashMap(); } /** @@ -168,7 +160,6 @@ public class RecalDatum { this.numMismatches = copy.getNumMismatches(); this.estimatedQReported = copy.estimatedQReported; this.empiricalQuality = copy.empiricalQuality; - empiricalQualityMap = copy.empiricalQualityMap; } /** @@ -182,7 +173,6 @@ public class RecalDatum { increment(other.getNumObservations(), other.getNumMismatches()); estimatedQReported = -10 * Math.log10(sumErrors / getNumObservations()); empiricalQuality = UNINITIALIZED; - empiricalQualityMap = new HashMap(); } public synchronized void setEstimatedQReported(final double estimatedQReported) { @@ -232,8 +222,13 @@ public class RecalDatum { } public final double getEmpiricalQuality() { - if (empiricalQuality == UNINITIALIZED) - calcEmpiricalQuality(); + return getEmpiricalQuality(getEstimatedQReported()); + } + + public final double getEmpiricalQuality(final double conditionalPrior) { + if (empiricalQuality == UNINITIALIZED) { + calcEmpiricalQuality(conditionalPrior); + } return empiricalQuality; } @@ -325,37 +320,22 @@ public class RecalDatum { return getNumObservations() * QualityUtils.qualToErrorProb(estimatedQReported); } - /** - * Calculate empirical quality score from mismatches, observations, and the given conditional prior (expensive operation) - */ - public double getEmpiricalQuality(final double conditionalPriorQ) { - - final int priorQKey = MathUtils.fastRound(conditionalPriorQ); - Double returnQ = empiricalQualityMap.get(priorQKey); - - if( returnQ == null ) { - // smoothing is one error and one non-error observation - final long mismatches = (long)(getNumMismatches() + 0.5) + SMOOTHING_CONSTANT; - final long observations = getNumObservations() + SMOOTHING_CONSTANT + SMOOTHING_CONSTANT; - - final double empiricalQual = RecalDatum.bayesianEstimateOfEmpiricalQuality(observations, mismatches, conditionalPriorQ); - - // This is the old and busted point estimate approach: - //final double empiricalQual = -10 * Math.log10(getEmpiricalErrorRate()); - - returnQ = Math.min(empiricalQual, (double) QualityUtils.MAX_RECALIBRATED_Q_SCORE); - empiricalQualityMap.put( priorQKey, returnQ ); - } - return returnQ; - } - /** * Calculate and cache the empirical quality score from mismatches and observations (expensive operation) */ @Requires("empiricalQuality == UNINITIALIZED") @Ensures("empiricalQuality != UNINITIALIZED") - private synchronized void calcEmpiricalQuality() { - final double empiricalQual = getEmpiricalQuality(getEstimatedQReported()); + private synchronized void calcEmpiricalQuality(final double conditionalPrior) { + + // smoothing is one error and one non-error observation + final long mismatches = (long)(getNumMismatches() + 0.5) + SMOOTHING_CONSTANT; + final long observations = getNumObservations() + SMOOTHING_CONSTANT + SMOOTHING_CONSTANT; + + final double empiricalQual = RecalDatum.bayesianEstimateOfEmpiricalQuality(observations, mismatches, conditionalPrior); + + // This is the old and busted point estimate approach: + //final double empiricalQual = -10 * Math.log10(getEmpiricalErrorRate()); + empiricalQuality = Math.min(empiricalQual, (double) QualityUtils.MAX_RECALIBRATED_Q_SCORE); } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java index 3fdbd63bd..bf8f00ca4 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java @@ -246,7 +246,7 @@ public class RecalibrationReport { private RecalDatum getRecalDatum(final GATKReportTable reportTable, final int row, final boolean hasEstimatedQReportedColumn) { final long nObservations = asLong(reportTable.get(row, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME)); final double nErrors = asDouble(reportTable.get(row, RecalUtils.NUMBER_ERRORS_COLUMN_NAME)); - final double empiricalQuality = asDouble(reportTable.get(row, RecalUtils.EMPIRICAL_QUALITY_COLUMN_NAME)); + //final double empiricalQuality = asDouble(reportTable.get(row, RecalUtils.EMPIRICAL_QUALITY_COLUMN_NAME)); // the estimatedQreported column only exists in the ReadGroup table final double estimatedQReported = hasEstimatedQReportedColumn ? @@ -255,7 +255,7 @@ public class RecalibrationReport { final RecalDatum datum = new RecalDatum(nObservations, nErrors, (byte)1); datum.setEstimatedQReported(estimatedQReported); - datum.setEmpiricalQuality(empiricalQuality); + //datum.setEmpiricalQuality(empiricalQuality); return datum; } From e9c3a0acdf2f7669138f1849643baa2ddf2d45ef Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Mon, 28 Jan 2013 22:18:58 -0500 Subject: [PATCH 122/188] fix typo --- .../sting/gatk/arguments/GATKArgumentCollection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index 6520947d4..b4d6051d9 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -241,7 +241,7 @@ public class GATKArgumentCollection { @Argument(fullName = "preserve_qscores_less_than", shortName = "preserveQ", doc = "Bases with quality scores less than this threshold won't be recalibrated (with -BQSR)", required = false) public int PRESERVE_QSCORES_LESS_THAN = QualityUtils.MIN_USABLE_Q_SCORE; - @Argument(fullName = "qlobalQScorePrior", shortName = "qlobalQScorePrior", doc = "The global Qscore Bayesian prior to use in the BQSR. If specified, this value will be used as the prior for all mismatch quality scores instead of the actual reported quality score", required = false) + @Argument(fullName = "globalQScorePrior", shortName = "globalQScorePrior", doc = "The global Qscore Bayesian prior to use in the BQSR. If specified, this value will be used as the prior for all mismatch quality scores instead of the actual reported quality score", required = false) public double globalQScorePrior = -1.0; // -------------------------------------------------------------------------------------------------------------- From 35543b9cbab7ff489b2eb8fb3bdbf518f9e3cf0d Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Tue, 29 Jan 2013 09:47:57 -0500 Subject: [PATCH 123/188] updating BQSR integration test values for the PR half of BQSR. --- .../sting/utils/recalibration/BaseRecalibration.java | 4 ---- .../sting/utils/recalibration/RecalDatum.java | 2 +- .../sting/utils/recalibration/RecalibrationReport.java | 2 +- .../sting/gatk/walkers/bqsr/BQSRIntegrationTest.java | 8 ++++---- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index ba18f5c96..1f4e92ad7 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -212,10 +212,6 @@ public class BaseRecalibration { final byte recalibratedQualityScore = quantizationInfo.getQuantizedQuals().get(recalibratedQual); quals[offset] = recalibratedQualityScore; - if( quals[offset] > QualityUtils.MAX_REASONABLE_Q_SCORE ) { - System.out.println("A"); - //calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, globalDeltaQ, deltaQReported, origQual); - } } } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java index 67794c248..0b4441439 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java @@ -225,7 +225,7 @@ public class RecalDatum { return getEmpiricalQuality(getEstimatedQReported()); } - public final double getEmpiricalQuality(final double conditionalPrior) { + public synchronized final double getEmpiricalQuality(final double conditionalPrior) { if (empiricalQuality == UNINITIALIZED) { calcEmpiricalQuality(conditionalPrior); } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java index bf8f00ca4..e3ab16639 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java @@ -255,7 +255,7 @@ public class RecalibrationReport { final RecalDatum datum = new RecalDatum(nObservations, nErrors, (byte)1); datum.setEstimatedQReported(estimatedQReported); - //datum.setEmpiricalQuality(empiricalQuality); + //datum.setEmpiricalQuality(empiricalQuality); // don't set the value here because we will want to recompute with a different conditional Q score prior value return datum; } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java index b8a409d2f..254bfd92c 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java @@ -188,12 +188,12 @@ public class BQSRIntegrationTest extends WalkerTest { public Object[][] createPRTestData() { List tests = new ArrayList(); - tests.add(new Object[]{1, new PRTest(" -qq -1", "5226c06237b213b9e9b25a32ed92d09a")}); - tests.add(new Object[]{1, new PRTest(" -qq 6", "b592a5c62b952a012e18adb898ea9c33")}); - tests.add(new Object[]{1, new PRTest(" -DIQ", "8977bea0c57b808e65e9505eb648cdf7")}); + tests.add(new Object[]{1, new PRTest(" -qq -1", "64622d37e234e57cf472068a00b4ec89")}); + tests.add(new Object[]{1, new PRTest(" -qq 6", "735270581d1ee836f3f99d68ecbd5f24")}); + tests.add(new Object[]{1, new PRTest(" -DIQ", "1e3b0a11f246a238ac4c06b084142715")}); for ( final int nct : Arrays.asList(1, 2, 4) ) { - tests.add(new Object[]{nct, new PRTest("", "ab2f209ab98ad3432e208cbd524a4c4a")}); + tests.add(new Object[]{nct, new PRTest("", "39ecde2c2ba4a7c109e65372618a419a")}); } return tests.toArray(new Object[][]{}); From c11197e3617af59ba14bf6b3b729ebbc78ce65b1 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Tue, 29 Jan 2013 10:10:24 -0500 Subject: [PATCH 124/188] Refactored repeat covariates to eliminate duplicated code - now all inherit from basic RepeatCovariate abstract class. Comprehensive unit tests coming... --- .../covariates/RepeatCovariate.java | 281 ++++++++++++++++++ .../covariates/RepeatLengthCovariate.java | 232 +-------------- .../RepeatUnitAndLengthCovariate.java | 221 +------------- .../covariates/RepeatUnitCovariate.java | 207 +------------ 4 files changed, 292 insertions(+), 649 deletions(-) create mode 100644 protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java new file mode 100644 index 000000000..d500a8ef9 --- /dev/null +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -0,0 +1,281 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.utils.recalibration.covariates; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; +import org.broadinstitute.sting.utils.recalibration.ReadCovariates; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.variant.variantcontext.VariantContextUtils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public abstract class RepeatCovariate implements ExperimentalCovariate { + final int MAX_REPEAT_LENGTH = 20; + final int MAX_STR_UNIT_LENGTH = 8; + private final HashMap repeatLookupTable = new HashMap(); + private final HashMap repeatReverseLookupTable = new HashMap(); + private int nextId = 0; + + // Initialize any member variables using the command-line arguments passed to the walkers + @Override + public void initialize(final RecalibrationArgumentCollection RAC) { + } + + @Override + public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { + // store the original bases and then write Ns over low quality ones + final byte[] originalBases = read.getReadBases().clone(); + + final boolean negativeStrand = read.getReadNegativeStrandFlag(); + byte[] bases = read.getReadBases(); + if (negativeStrand) + bases = BaseUtils.simpleReverseComplement(bases); + + // don't record reads with N's + if (!BaseUtils.isAllRegularBases(bases)) + return; + + for (int i = 0; i < bases.length; i++) { + final Pair res = findTandemRepeatUnits(bases, i); + // to merge repeat unit and repeat length to get covariate value: + final String repeatID = getCovariateValueFromUnitAndLength(res.first, res.second); + final int key = keyForRepeat(repeatID); + + final int readOffset = (negativeStrand ? bases.length - i - 1 : i); + values.addCovariate(key, key, key, readOffset); + } + + // put the original bases back in + read.setReadBases(originalBases); + + } + + private Pair findTandemRepeatUnits(byte[] readBases, int offset) { + int maxBW = 0; + byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+1-str < 0) + break; + + // get backward repeat unit and # repeats + byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str + 1, offset + 1); + maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); + if (maxBW > 1) { + bestBWRepeatUnit = backwardRepeatUnit.clone(); + break; + } + } + byte[] bestRepeatUnit = bestBWRepeatUnit; + int maxRL = maxBW; + + if (offset < readBases.length-1) { + byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; + int maxFW = 0; + for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { + // fix repeat unit length + //edge case: if candidate tandem repeat unit falls beyond edge of read, skip + if (offset+str+1 > readBases.length) + break; + + // get forward repeat unit and # repeats + byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); + maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); + if (maxFW > 1) { + bestFWRepeatUnit = forwardRepeatUnit.clone(); + break; + } + } + // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components + if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { + maxRL = maxBW + maxFW; + bestRepeatUnit = bestFWRepeatUnit; // arbitrary + } + else { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + + } +/* if (maxFW > maxBW) { + // tandem repeat starting forward from current offset + maxRL = maxFW; + bestRepeatUnit = bestFWRepeatUnit; + } + else if (maxFW < maxBW) { + maxRL = maxBW; + bestRepeatUnit = bestBWRepeatUnit; + } */ + /* else { + // maxFW = maxBW but repeat units different: not in a tandem repeat. + maxRL = 1; + bestRepeatUnit = bestBWRepeatUnit; // arbitrary + } */ + + } + + + + if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } + return new Pair(bestRepeatUnit, maxRL); + + } + @Override + public final Object getValue(final String str) { + return str; + } + + @Override + public synchronized String formatKey(final int key) { + // This method is synchronized so that we don't attempt to do a get() + // from the reverse lookup table while that table is being updated + return repeatReverseLookupTable.get(key); + } + + @Requires({"repeatLength>=0", "repeatFromUnitAndLength != null"}) + @Ensures("result != null") + protected abstract String getCovariateValueFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength); + + + @Override + public int keyFromValue(final Object value) { + return keyForRepeat((String) value); + } + + /** + * Get the mapping from read group names to integer key values for all read groups in this covariate + * @return a set of mappings from read group names -> integer key values + */ + public Set> getKeyMap() { + return repeatLookupTable.entrySet(); + } + + private int keyForRepeat(final String repeatID) { + // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), + // synchronize only the table updates. + + // Before entering the synchronized block, check to see if this read group is not in our tables. + // If it's not, either we will have to insert it, OR another thread will insert it first. + // This preliminary check avoids doing any synchronization most of the time. + if ( ! repeatLookupTable.containsKey(repeatID) ) { + + synchronized ( this ) { + + // Now we need to make sure the key is STILL not there, since another thread may have come along + // and inserted it while we were waiting to enter this synchronized block! + if ( ! repeatLookupTable.containsKey(repeatID) ) { + repeatLookupTable.put(repeatID, nextId); + repeatReverseLookupTable.put(nextId, repeatID); + nextId++; + } + } + } + + return repeatLookupTable.get(repeatID); + } + + + /** + * Splits repeat unit and num repetitions from covariate value. + * For example, if value if "ATG4" it returns (ATG,4) + * @param value Covariate value + * @return Split pair + */ + @Requires("value != null") + @Ensures({"result.first != null","result.second>=0"}) + public static Pair getRUandNRfromCovariate(final String value) { + + int k = 0; + for ( k=0; k < value.length(); k++ ) { + if (!BaseUtils.isRegularBase(value.getBytes()[k])) + break; + } + Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal + if (k == value.length() || nr <= 0) + throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); + + return new Pair(value.substring(0,k), nr); + } + + /** + * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). + * For example, (AGC),3 returns AGCAGCAGC + * @param repeatUnit Tandem repeat unit + * @param numRepeats Number of repeats + * @return Expanded String + */ + @Requires({"numRepeats > 0","repeatUnit != null"}) + @Ensures("result != null") + public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { + final StringBuilder sb = new StringBuilder(); + + for (int i=0; i < numRepeats; i++) + sb.append(repeatUnit); + + return sb.toString(); + } + + // version given covariate key + public static String getBasesFromRUandNR(final String covariateValue) { + Pair pair = getRUandNRfromCovariate(covariateValue); + return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); + } + + @Override + public abstract int maximumKeyValue(); + + + +} diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java index b6266a543..48f3d4b60 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatLengthCovariate.java @@ -48,234 +48,13 @@ package org.broadinstitute.sting.utils.recalibration.covariates; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; -import org.broadinstitute.sting.utils.recalibration.ReadCovariates; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class RepeatLengthCovariate implements ExperimentalCovariate { - final int MAX_REPEAT_LENGTH = 20; - final int MAX_STR_UNIT_LENGTH = 1; // =1 will restrict effectively to detecting homopolymer runs - public final boolean RECORD_REPUNIT_WITH_REPLENGTH = false; - private final HashMap repeatLookupTable = new HashMap(); - private final HashMap repeatReverseLookupTable = new HashMap(); - private int nextId = 0; - - // Initialize any member variables using the command-line arguments passed to the walkers - @Override - public void initialize(final RecalibrationArgumentCollection RAC) { - } - - @Override - public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { - // store the original bases and then write Ns over low quality ones - final byte[] originalBases = read.getReadBases().clone(); - - final boolean negativeStrand = read.getReadNegativeStrandFlag(); - byte[] bases = read.getReadBases(); - if (negativeStrand) - bases = BaseUtils.simpleReverseComplement(bases); - - // don't record reads with N's - if (!BaseUtils.isAllRegularBases(bases)) - return; - - for (int i = 0; i < bases.length; i++) { - final Pair res = findTandemRepeatUnits(bases, i); - // merge repeat unit and repeat length to get covariate value - final String repeatID = repeatFromUnitAndLength(res.first, res.second); - final int key = keyForRepeat(repeatID); - - final int readOffset = (negativeStrand ? bases.length - i - 1 : i); - values.addCovariate(key, key, key, readOffset); - } - - // put the original bases back in - read.setReadBases(originalBases); - - } - - private Pair findTandemRepeatUnits(byte[] readBases, int offset) { - int maxBW = 0; - byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+1-str < 0) - break; - - // get backward repeat unit and # repeats - byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); - maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); - if (maxBW > 1) { - bestBWRepeatUnit = backwardRepeatUnit.clone(); - break; - } - } - byte[] bestRepeatUnit = bestBWRepeatUnit; - int maxRL = maxBW; - - if (offset < readBases.length-1) { - byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; - int maxFW = 0; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+str+1 > readBases.length) - break; - - // get forward repeat unit and # repeats - byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); - maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); - if (maxFW > 1) { - bestFWRepeatUnit = forwardRepeatUnit.clone(); - break; - } - } - // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components - if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { - maxRL = maxBW + maxFW; - bestRepeatUnit = bestFWRepeatUnit; // arbitrary - } - else { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - - } -/* if (maxFW > maxBW) { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - } - else if (maxFW < maxBW) { - maxRL = maxBW; - bestRepeatUnit = bestBWRepeatUnit; - } */ - /* else { - // maxFW = maxBW but repeat units different: not in a tandem repeat. - maxRL = 1; - bestRepeatUnit = bestBWRepeatUnit; // arbitrary - } */ - - } - - - - if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } - return new Pair(bestRepeatUnit, maxRL); - - } - @Override - public final Object getValue(final String str) { - return str; - } - - @Override - public synchronized String formatKey(final int key) { - // This method is synchronized so that we don't attempt to do a get() - // from the reverse lookup table while that table is being updated - return repeatReverseLookupTable.get(key); - } - - @Override - public int keyFromValue(final Object value) { - return keyForRepeat((String) value); - } - - /** - * Get the mapping from read group names to integer key values for all read groups in this covariate - * @return a set of mappings from read group names -> integer key values - */ - public Set> getKeyMap() { - return repeatLookupTable.entrySet(); - } +public class RepeatLengthCovariate extends RepeatCovariate { @Requires({"repeatLength>=0", "repeatFromUnitAndLength != null"}) @Ensures("result != null") - private String repeatFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { - if (RECORD_REPUNIT_WITH_REPLENGTH) - return new String(repeatFromUnitAndLength) + String.format("%d",repeatLength); - else - return String.format("%d",repeatLength); - } - - private int keyForRepeat(final String repeatID) { - // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), - // synchronize only the table updates. - - // Before entering the synchronized block, check to see if this read group is not in our tables. - // If it's not, either we will have to insert it, OR another thread will insert it first. - // This preliminary check avoids doing any synchronization most of the time. - if ( ! repeatLookupTable.containsKey(repeatID) ) { - - synchronized ( this ) { - - // Now we need to make sure the key is STILL not there, since another thread may have come along - // and inserted it while we were waiting to enter this synchronized block! - if ( ! repeatLookupTable.containsKey(repeatID) ) { - repeatLookupTable.put(repeatID, nextId); - repeatReverseLookupTable.put(nextId, repeatID); - nextId++; - } - } - } - - return repeatLookupTable.get(repeatID); - } - - - /** - * Splits repeat unit and num repetitions from covariate value. - * For example, if value if "ATG4" it returns (ATG,4) - * @param value Covariate value - * @return Split pair - */ - @Requires("value != null") - @Ensures({"result.first != null","result.second>=0"}) - public static Pair getRUandNRfromCovariate(final String value) { - - int k = 0; - for ( k=0; k < value.length(); k++ ) { - if (!BaseUtils.isRegularBase(value.getBytes()[k])) - break; - } - Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal - if (k == value.length() || nr <= 0) - throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); - - return new Pair(value.substring(0,k), nr); - } - - /** - * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). - * For example, (AGC),3 returns AGCAGCAGC - * @param repeatUnit Tandem repeat unit - * @param numRepeats Number of repeats - * @return Expanded String - */ - @Requires({"numRepeats > 0","repeatUnit != null"}) - @Ensures("result != null") - public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { - final StringBuilder sb = new StringBuilder(); - - for (int i=0; i < numRepeats; i++) - sb.append(repeatUnit); - - return sb.toString(); - } - - // version given covariate key - public static String getBasesFromRUandNR(final String covariateValue) { - Pair pair = getRUandNRfromCovariate(covariateValue); - return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); + protected String getCovariateValueFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { + return String.format("%d",repeatLength); } @Override @@ -284,10 +63,7 @@ public class RepeatLengthCovariate implements ExperimentalCovariate { //return repeatLookupTable.size() - 1; // max possible values of covariate: for repeat unit, length is up to MAX_STR_UNIT_LENGTH, // so we have 4^MAX_STR_UNIT_LENGTH * MAX_REPEAT_LENGTH possible values - if (RECORD_REPUNIT_WITH_REPLENGTH) - return (1<<(2*MAX_STR_UNIT_LENGTH)) * MAX_REPEAT_LENGTH +1; - else - return (1+MAX_REPEAT_LENGTH); + return (1+MAX_REPEAT_LENGTH); } } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java index 36c5d57d3..5822b9e05 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java @@ -62,222 +62,12 @@ import java.util.Map; import java.util.Set; -public class RepeatUnitAndLengthCovariate implements ExperimentalCovariate { - final int MAX_REPEAT_LENGTH = 20; - final int MAX_STR_UNIT_LENGTH = 8; - public final boolean RECORD_REPUNIT_WITH_REPLENGTH = true; - private final HashMap repeatLookupTable = new HashMap(); - private final HashMap repeatReverseLookupTable = new HashMap(); - private int nextId = 0; - - // Initialize any member variables using the command-line arguments passed to the walkers - @Override - public void initialize(final RecalibrationArgumentCollection RAC) { - } - - @Override - public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { - // store the original bases and then write Ns over low quality ones - final byte[] originalBases = read.getReadBases().clone(); - - final boolean negativeStrand = read.getReadNegativeStrandFlag(); - byte[] bases = read.getReadBases(); - if (negativeStrand) - bases = BaseUtils.simpleReverseComplement(bases); - - // don't record reads with N's - if (!BaseUtils.isAllRegularBases(bases)) - return; - - for (int i = 0; i < bases.length; i++) { - final Pair res = findTandemRepeatUnits(bases, i); - // merge repeat unit and repeat length to get covariate value - final String repeatID = repeatFromUnitAndLength(res.first, res.second); - final int key = keyForRepeat(repeatID); - - final int readOffset = (negativeStrand ? bases.length - i - 1 : i); - values.addCovariate(key, key, key, readOffset); - } - - // put the original bases back in - read.setReadBases(originalBases); - - } - - private Pair findTandemRepeatUnits(byte[] readBases, int offset) { - int maxBW = 0; - byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+1-str < 0) - break; - - // get backward repeat unit and # repeats - byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); - maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); - if (maxBW > 1) { - bestBWRepeatUnit = backwardRepeatUnit.clone(); - break; - } - } - byte[] bestRepeatUnit = bestBWRepeatUnit; - int maxRL = maxBW; - - if (offset < readBases.length-1) { - byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; - int maxFW = 0; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+str+1 > readBases.length) - break; - - // get forward repeat unit and # repeats - byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); - maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); - if (maxFW > 1) { - bestFWRepeatUnit = forwardRepeatUnit.clone(); - break; - } - } - // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components - if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { - maxRL = maxBW + maxFW; - bestRepeatUnit = bestFWRepeatUnit; // arbitrary - } - else { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - - } -/* if (maxFW > maxBW) { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - } - else if (maxFW < maxBW) { - maxRL = maxBW; - bestRepeatUnit = bestBWRepeatUnit; - } */ - /* else { - // maxFW = maxBW but repeat units different: not in a tandem repeat. - maxRL = 1; - bestRepeatUnit = bestBWRepeatUnit; // arbitrary - } */ - - } - - - - if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } - return new Pair(bestRepeatUnit, maxRL); - - } - @Override - public final Object getValue(final String str) { - return str; - } - - @Override - public synchronized String formatKey(final int key) { - // This method is synchronized so that we don't attempt to do a get() - // from the reverse lookup table while that table is being updated - return repeatReverseLookupTable.get(key); - } - - @Override - public int keyFromValue(final Object value) { - return keyForRepeat((String) value); - } - - /** - * Get the mapping from read group names to integer key values for all read groups in this covariate - * @return a set of mappings from read group names -> integer key values - */ - public Set> getKeyMap() { - return repeatLookupTable.entrySet(); - } +public class RepeatUnitAndLengthCovariate extends RepeatCovariate { @Requires({"repeatLength>=0", "repeatFromUnitAndLength != null"}) @Ensures("result != null") - private String repeatFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { - if (RECORD_REPUNIT_WITH_REPLENGTH) - return new String(repeatFromUnitAndLength) + String.format("%d",repeatLength); - else - return String.format("%d",repeatLength); - } - - private int keyForRepeat(final String repeatID) { - // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), - // synchronize only the table updates. - - // Before entering the synchronized block, check to see if this read group is not in our tables. - // If it's not, either we will have to insert it, OR another thread will insert it first. - // This preliminary check avoids doing any synchronization most of the time. - if ( ! repeatLookupTable.containsKey(repeatID) ) { - - synchronized ( this ) { - - // Now we need to make sure the key is STILL not there, since another thread may have come along - // and inserted it while we were waiting to enter this synchronized block! - if ( ! repeatLookupTable.containsKey(repeatID) ) { - repeatLookupTable.put(repeatID, nextId); - repeatReverseLookupTable.put(nextId, repeatID); - nextId++; - } - } - } - - return repeatLookupTable.get(repeatID); - } - - - /** - * Splits repeat unit and num repetitions from covariate value. - * For example, if value if "ATG4" it returns (ATG,4) - * @param value Covariate value - * @return Split pair - */ - @Requires("value != null") - @Ensures({"result.first != null","result.second>=0"}) - public static Pair getRUandNRfromCovariate(final String value) { - - int k = 0; - for ( k=0; k < value.length(); k++ ) { - if (!BaseUtils.isRegularBase(value.getBytes()[k])) - break; - } - Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal - if (k == value.length() || nr <= 0) - throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); - - return new Pair(value.substring(0,k), nr); - } - - /** - * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). - * For example, (AGC),3 returns AGCAGCAGC - * @param repeatUnit Tandem repeat unit - * @param numRepeats Number of repeats - * @return Expanded String - */ - @Requires({"numRepeats > 0","repeatUnit != null"}) - @Ensures("result != null") - public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { - final StringBuilder sb = new StringBuilder(); - - for (int i=0; i < numRepeats; i++) - sb.append(repeatUnit); - - return sb.toString(); - } - - // version given covariate key - public static String getBasesFromRUandNR(final String covariateValue) { - Pair pair = getRUandNRfromCovariate(covariateValue); - return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); + protected String getCovariateValueFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { + return new String(repeatFromUnitAndLength) + String.format("%d",repeatLength); } @Override @@ -286,10 +76,7 @@ public class RepeatUnitAndLengthCovariate implements ExperimentalCovariate { //return repeatLookupTable.size() - 1; // max possible values of covariate: for repeat unit, length is up to MAX_STR_UNIT_LENGTH, // so we have 4^MAX_STR_UNIT_LENGTH * MAX_REPEAT_LENGTH possible values - if (RECORD_REPUNIT_WITH_REPLENGTH) - return (1<<(2*MAX_STR_UNIT_LENGTH)) * MAX_REPEAT_LENGTH +1; - else - return (1+MAX_REPEAT_LENGTH); + return (1<<(2*MAX_STR_UNIT_LENGTH)) * MAX_REPEAT_LENGTH +1; } } diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java index 9e98e741e..ed843310d 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java @@ -66,214 +66,13 @@ import java.util.Set; * Date: 11/3/12 */ -public class RepeatUnitCovariate implements ExperimentalCovariate { - final int MAX_REPEAT_LENGTH = 20; - final int MAX_STR_UNIT_LENGTH = 8; - private final HashMap repeatLookupTable = new HashMap(); - private final HashMap repeatReverseLookupTable = new HashMap(); - private int nextId = 0; +public class RepeatUnitCovariate extends RepeatCovariate { - // Initialize any member variables using the command-line arguments passed to the walkers - @Override - public void initialize(final RecalibrationArgumentCollection RAC) { - } - - @Override - public void recordValues(final GATKSAMRecord read, final ReadCovariates values) { - // store the original bases and then write Ns over low quality ones - final byte[] originalBases = read.getReadBases().clone(); - - final boolean negativeStrand = read.getReadNegativeStrandFlag(); - byte[] bases = read.getReadBases(); - if (negativeStrand) - bases = BaseUtils.simpleReverseComplement(bases); - - // don't record reads with N's - if (!BaseUtils.isAllRegularBases(bases)) - return; - - for (int i = 0; i < bases.length; i++) { - final Pair res = findTandemRepeatUnits(bases, i); - // to merge repeat unit and repeat length to get covariate value: - //final String repeatID = repeatFromUnitAndLength(res.first, res.second); - final String repeatID = new String(res.first); - final int key = keyForRepeat(repeatID); - - final int readOffset = (negativeStrand ? bases.length - i - 1 : i); - values.addCovariate(key, key, key, readOffset); - } - - // put the original bases back in - read.setReadBases(originalBases); + protected String getCovariateValueFromUnitAndLength(final byte[] repeatFromUnitAndLength, final int repeatLength) { + return new String(repeatFromUnitAndLength); } - private Pair findTandemRepeatUnits(byte[] readBases, int offset) { - int maxBW = 0; - byte[] bestBWRepeatUnit = new byte[]{readBases[offset]}; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+1-str < 0) - break; - - // get backward repeat unit and # repeats - byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str+1, offset+1); - maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit,Arrays.copyOfRange(readBases, 0, offset+1), false); - if (maxBW > 1) { - bestBWRepeatUnit = backwardRepeatUnit.clone(); - break; - } - } - byte[] bestRepeatUnit = bestBWRepeatUnit; - int maxRL = maxBW; - - if (offset < readBases.length-1) { - byte[] bestFWRepeatUnit = new byte[]{readBases[offset+1]}; - int maxFW = 0; - for (int str = 1; str <= MAX_STR_UNIT_LENGTH; str++) { - // fix repeat unit length - //edge case: if candidate tandem repeat unit falls beyond edge of read, skip - if (offset+str+1 > readBases.length) - break; - - // get forward repeat unit and # repeats - byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); - maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); - if (maxFW > 1) { - bestFWRepeatUnit = forwardRepeatUnit.clone(); - break; - } - } - // if FW repeat unit = BW repeat unit it means we're in the middle of a tandem repeat - add FW and BW components - if (Arrays.equals(bestFWRepeatUnit, bestBWRepeatUnit)) { - maxRL = maxBW + maxFW; - bestRepeatUnit = bestFWRepeatUnit; // arbitrary - } - else { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - - } -/* if (maxFW > maxBW) { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - } - else if (maxFW < maxBW) { - maxRL = maxBW; - bestRepeatUnit = bestBWRepeatUnit; - } */ - /* else { - // maxFW = maxBW but repeat units different: not in a tandem repeat. - maxRL = 1; - bestRepeatUnit = bestBWRepeatUnit; // arbitrary - } */ - - } - - - - if(maxRL > MAX_REPEAT_LENGTH) { maxRL = MAX_REPEAT_LENGTH; } - return new Pair(bestRepeatUnit, maxRL); - - } - @Override - public final Object getValue(final String str) { - return str; - } - - @Override - public synchronized String formatKey(final int key) { - // This method is synchronized so that we don't attempt to do a get() - // from the reverse lookup table while that table is being updated - return repeatReverseLookupTable.get(key); - } - - @Override - public int keyFromValue(final Object value) { - return keyForRepeat((String) value); - } - - /** - * Get the mapping from read group names to integer key values for all read groups in this covariate - * @return a set of mappings from read group names -> integer key values - */ - public Set> getKeyMap() { - return repeatLookupTable.entrySet(); - } - - private int keyForRepeat(final String repeatID) { - // Rather than synchronize this entire method (which would be VERY expensive for walkers like the BQSR), - // synchronize only the table updates. - - // Before entering the synchronized block, check to see if this read group is not in our tables. - // If it's not, either we will have to insert it, OR another thread will insert it first. - // This preliminary check avoids doing any synchronization most of the time. - if ( ! repeatLookupTable.containsKey(repeatID) ) { - - synchronized ( this ) { - - // Now we need to make sure the key is STILL not there, since another thread may have come along - // and inserted it while we were waiting to enter this synchronized block! - if ( ! repeatLookupTable.containsKey(repeatID) ) { - repeatLookupTable.put(repeatID, nextId); - repeatReverseLookupTable.put(nextId, repeatID); - nextId++; - } - } - } - - return repeatLookupTable.get(repeatID); - } - - - /** - * Splits repeat unit and num repetitions from covariate value. - * For example, if value if "ATG4" it returns (ATG,4) - * @param value Covariate value - * @return Split pair - */ - @Requires("value != null") - @Ensures({"result.first != null","result.second>=0"}) - public static Pair getRUandNRfromCovariate(final String value) { - - int k = 0; - for ( k=0; k < value.length(); k++ ) { - if (!BaseUtils.isRegularBase(value.getBytes()[k])) - break; - } - Integer nr = Integer.valueOf(value.substring(k,value.length())); // will throw NumberFormatException if format illegal - if (k == value.length() || nr <= 0) - throw new IllegalStateException("Covariate is not of form (Repeat Unit) + Integer"); - - return new Pair(value.substring(0,k), nr); - } - - /** - * Gets bases from tandem repeat representation (Repeat Unit),(Number of Repeats). - * For example, (AGC),3 returns AGCAGCAGC - * @param repeatUnit Tandem repeat unit - * @param numRepeats Number of repeats - * @return Expanded String - */ - @Requires({"numRepeats > 0","repeatUnit != null"}) - @Ensures("result != null") - public static String getBasesFromRUandNR(final String repeatUnit, final int numRepeats) { - final StringBuilder sb = new StringBuilder(); - - for (int i=0; i < numRepeats; i++) - sb.append(repeatUnit); - - return sb.toString(); - } - - // version given covariate key - public static String getBasesFromRUandNR(final String covariateValue) { - Pair pair = getRUandNRfromCovariate(covariateValue); - return getBasesFromRUandNR(pair.getFirst(), pair.getSecond()); - } @Override public synchronized int maximumKeyValue() { From 1d5b29e764662424993a62a1c86bd7aa78759704 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Tue, 29 Jan 2013 15:23:02 -0500 Subject: [PATCH 125/188] Unit tests for repeat covariates: generate 100 random reads consisting of tandem repeat units of random content and size, and check that covariates match expected values at all positions in reads. Fixed corner case where value of covariate at border between 2 tandem repeats of different length/content wasn't consistent --- .../covariates/RepeatCovariate.java | 28 +++---- ...est.java => RepeatCovariatesUnitTest.java} | 77 +++++++++++++------ 2 files changed, 63 insertions(+), 42 deletions(-) rename protected/java/test/org/broadinstitute/sting/utils/recalibration/{RepeatLengthCovariateUnitTest.java => RepeatCovariatesUnitTest.java} (81%) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java index d500a8ef9..a836fbb5e 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -61,8 +61,8 @@ import java.util.Map; import java.util.Set; public abstract class RepeatCovariate implements ExperimentalCovariate { - final int MAX_REPEAT_LENGTH = 20; - final int MAX_STR_UNIT_LENGTH = 8; + public static final int MAX_REPEAT_LENGTH = 20; + public static final int MAX_STR_UNIT_LENGTH = 8; private final HashMap repeatLookupTable = new HashMap(); private final HashMap repeatReverseLookupTable = new HashMap(); private int nextId = 0; @@ -144,25 +144,17 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { bestRepeatUnit = bestFWRepeatUnit; // arbitrary } else { - // tandem repeat starting forward from current offset - maxRL = maxFW; + // tandem repeat starting forward from current offset. + // It could be the case that best BW unit was differnet from FW unit, but that BW still contains FW unit. + // For example, TTCTT(C) CCC - at (C) place, best BW unit is (TTC)2, best FW unit is (C)3. + // but correct representation at that place might be (C)4. + // Hence, if the FW and BW units don't match, check if BW unit can still be a part of FW unit and add + // representations to total + maxBW = VariantContextUtils.findNumberofRepetitions(bestFWRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); + maxRL = maxFW + maxBW; bestRepeatUnit = bestFWRepeatUnit; } -/* if (maxFW > maxBW) { - // tandem repeat starting forward from current offset - maxRL = maxFW; - bestRepeatUnit = bestFWRepeatUnit; - } - else if (maxFW < maxBW) { - maxRL = maxBW; - bestRepeatUnit = bestBWRepeatUnit; - } */ - /* else { - // maxFW = maxBW but repeat units different: not in a tandem repeat. - maxRL = 1; - bestRepeatUnit = bestBWRepeatUnit; // arbitrary - } */ } diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java similarity index 81% rename from protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java rename to protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java index d08276147..e4311a534 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatLengthCovariateUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java @@ -49,7 +49,7 @@ import com.google.java.contract.Requires; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; -import org.broadinstitute.sting.utils.recalibration.covariates.RepeatLengthCovariate; +import org.broadinstitute.sting.utils.recalibration.covariates.*; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -65,9 +65,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Random; -public class RepeatLengthCovariateUnitTest { +public class RepeatCovariatesUnitTest { - RepeatLengthCovariate covariate; + RepeatLengthCovariate rlCovariate; + RepeatUnitCovariate ruCovariate; + RepeatUnitAndLengthCovariate rurlCovariate; RecalibrationArgumentCollection RAC; @@ -75,8 +77,12 @@ public class RepeatLengthCovariateUnitTest { @BeforeClass public void init() { RAC = new RecalibrationArgumentCollection(); - covariate = new RepeatLengthCovariate(); - covariate.initialize(RAC); + rlCovariate = new RepeatLengthCovariate(); + ruCovariate = new RepeatUnitCovariate(); + rurlCovariate = new RepeatUnitAndLengthCovariate(); + rlCovariate.initialize(RAC); + ruCovariate.initialize(RAC); + rurlCovariate.initialize(RAC); } @@ -136,9 +142,9 @@ public class RepeatLengthCovariateUnitTest { @Test(enabled = true) public void testManyObservations() { final int NUM_UNITS = 10; - final int MAX_REPEAT_UNIT_LENGTH = 6; - final int MAX_NUM_REPETITIONS = 5; - final int NUM_TEST_CASES = 1; + final int MAX_REPEAT_UNIT_LENGTH = RepeatCovariate.MAX_STR_UNIT_LENGTH; + final int MAX_NUM_REPETITIONS = RepeatCovariate.MAX_REPEAT_LENGTH; + final int NUM_TEST_CASES = 100; Random random = new Random(); @@ -161,29 +167,52 @@ public class RepeatLengthCovariateUnitTest { } - // final String readBases = sb.toString(); - final String readBases = "TTTTTTTTAATGGGGGAGGGAGGGAGACTTACTTACTTACTTACTTATCGGAATCGGATATATAACGGCTTTCTTCTTCCCCCCA"; + final String readBases = sb.toString(); System.out.println(readBases); + final int readLength = readBases.length(); - final byte[] readQuals = new byte[readBases.length()]; + final byte[] readQuals = new byte[readLength]; Arrays.fill(readQuals,(byte)30); - final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(readBases.getBytes(),readQuals,readBases.length()+"M"); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(readBases.getBytes(),readQuals,readLength+"M"); + + Covariate[] requestedCovariates = new Covariate[3]; + requestedCovariates[0] = rlCovariate; + requestedCovariates[1] = ruCovariate; + requestedCovariates[2] = rurlCovariate; + ReadCovariates rc = RecalUtils.computeCovariates(read, requestedCovariates); + + // check that the length is correct + Assert.assertEquals(rc.getMismatchesKeySet().length, readLength); + Assert.assertEquals(rc.getInsertionsKeySet().length, readLength); + Assert.assertEquals(rc.getDeletionsKeySet().length, readLength); - final ReadCovariates values = new ReadCovariates(read.getReadLength(),1); - covariate.recordValues( read, values); - final int fullReadKeySet[][] = values.getKeySet(EventType.BASE_SUBSTITUTION); for (int offset = 0; offset < readBases.length(); offset++) { // recalibrate all bases in the read - final int[] keySet = fullReadKeySet[offset]; - final String val = covariate.formatKey(keySet[0]); - System.out.format("offset %d:%s\n", offset, val); -// final String repeatString = RepeatLengthCovariate.getBasesFromRUandNR(val); -// final String partialRead = readBases.substring(0,offset+1); - // Assert.assertTrue(partialRead.endsWith(repeatString)); - } - //values. - int k=0; + // check RepeatLength + final String rlValM = rlCovariate.formatKey(rc.getMismatchesKeySet(offset)[0]); + final String rlValI = rlCovariate.formatKey(rc.getInsertionsKeySet(offset)[0]); + final String rlValD = rlCovariate.formatKey(rc.getDeletionsKeySet(offset)[0]); + // check RepeatUnit + final String ruValM = ruCovariate.formatKey(rc.getMismatchesKeySet(offset)[1]); + final String ruValI = ruCovariate.formatKey(rc.getInsertionsKeySet(offset)[1]); + final String ruValD = ruCovariate.formatKey(rc.getDeletionsKeySet(offset)[1]); + // check RepeatUnitAndLength + final String rurlValM = rurlCovariate.formatKey(rc.getMismatchesKeySet(offset)[2]); + final String rurlValI = rurlCovariate.formatKey(rc.getInsertionsKeySet(offset)[2]); + final String rurlValD = rurlCovariate.formatKey(rc.getDeletionsKeySet(offset)[2]); + // check all 3 values are identical + Assert.assertEquals(rlValD,rlValI); + Assert.assertEquals(rlValM,rlValI); + Assert.assertEquals(ruValD,ruValI); + Assert.assertEquals(ruValM,ruValI); + Assert.assertEquals(rurlValD,rurlValI); + Assert.assertEquals(rurlValM,rurlValI); + int fw = VariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(offset+1,readLength).getBytes(),true); + int bw = VariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(0,offset+1).getBytes(),false); + Assert.assertEquals(Math.min(fw+bw,RepeatCovariate.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); + } + } From cba89e98ad4879e66fc9bac9d5a102276b0517cb Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Tue, 29 Jan 2013 15:50:46 -0500 Subject: [PATCH 126/188] Refactoring the Bayesian empirical quality estimates to be in a single unit-testable function. --- .../recalibration/BaseRecalibration.java | 163 +++--------------- 1 file changed, 20 insertions(+), 143 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index 1f4e92ad7..c8d460308 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -57,6 +57,8 @@ import org.broadinstitute.sting.utils.recalibration.covariates.Covariate; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * Utility methods to facilitate on-the-fly base quality score recalibration. @@ -78,10 +80,6 @@ public class BaseRecalibration { private final double globalQScorePrior; private final boolean emitOriginalQuals; - private final NestedIntegerArray globalDeltaQs; - private final NestedIntegerArray deltaQReporteds; - - /** * Constructor using a GATK Report file * @@ -105,44 +103,6 @@ public class BaseRecalibration { this.preserveQLessThan = preserveQLessThan; this.globalQScorePrior = globalQScorePrior; this.emitOriginalQuals = emitOriginalQuals; - - logger.info("Calculating cached tables..."); - - // - // Create a NestedIntegerArray that maps from rgKey x errorModel -> double, - // where the double is the result of this calculation. The entire calculation can - // be done upfront, on initialization of this BaseRecalibration structure - // - final NestedIntegerArray byReadGroupTable = recalibrationTables.getReadGroupTable(); - globalDeltaQs = new NestedIntegerArray( byReadGroupTable.getDimensions() ); - logger.info("Calculating global delta Q table..."); - for ( NestedIntegerArray.Leaf leaf : byReadGroupTable.getAllLeaves() ) { - final int rgKey = leaf.keys[0]; - final int eventIndex = leaf.keys[1]; - final double globalDeltaQ = calculateGlobalDeltaQ(rgKey, EventType.eventFrom(eventIndex)); - globalDeltaQs.put(globalDeltaQ, rgKey, eventIndex); - } - - - // The calculation of the deltaQ report is constant. key[0] and key[1] are the read group and qual, respectively - // and globalDeltaQ is a constant for the read group. So technically the delta Q reported is simply a lookup - // into a matrix indexed by rgGroup, qual, and event type. - // the code below actually creates this cache with a NestedIntegerArray calling into the actual - // calculateDeltaQReported code. - final NestedIntegerArray byQualTable = recalibrationTables.getQualityScoreTable(); - deltaQReporteds = new NestedIntegerArray( byQualTable.getDimensions() ); - logger.info("Calculating delta Q reported table..."); - for ( NestedIntegerArray.Leaf leaf : byQualTable.getAllLeaves() ) { - final int rgKey = leaf.keys[0]; - final int qual = leaf.keys[1]; - final int eventIndex = leaf.keys[2]; - final EventType event = EventType.eventFrom(eventIndex); - final double globalDeltaQ = getGlobalDeltaQ(rgKey, event); - final double deltaQReported = calculateDeltaQReported(rgKey, qual, event, globalDeltaQ, (byte)qual); - deltaQReporteds.put(deltaQReported, rgKey, qual, eventIndex); - } - - logger.info("done calculating cache"); } /** @@ -189,8 +149,8 @@ public class BaseRecalibration { // the rg key is constant over the whole read, the global deltaQ is too final int rgKey = fullReadKeySet[0][0]; - - final double globalDeltaQ = getGlobalDeltaQ(rgKey, errorModel); + final RecalDatum empiricalQualRG = recalibrationTables.getReadGroupTable().get(rgKey, errorModel.ordinal()); + final double epsilon = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : empiricalQualRG.getEstimatedQReported() ); for (int offset = 0; offset < readLength; offset++) { // recalibrate all bases in the read final byte origQual = quals[offset]; @@ -199,11 +159,16 @@ public class BaseRecalibration { if ( origQual >= preserveQLessThan ) { // get the keyset for this base using the error model final int[] keySet = fullReadKeySet[offset]; - final double deltaQReported = getDeltaQReported(keySet[0], keySet[1], errorModel, globalDeltaQ); - final double deltaQCovariates = calculateDeltaQCovariates(recalibrationTables, keySet, errorModel, globalDeltaQ, deltaQReported, origQual); + final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(keySet[0], keySet[1], errorModel.ordinal()); + final List empiricalQualCovs = new ArrayList(); + for (int i = 2; i < requestedCovariates.length; i++) { + if (keySet[i] < 0) { + continue; + } + empiricalQualCovs.add(recalibrationTables.getTable(i).get(keySet[0], keySet[1], keySet[i], errorModel.ordinal())); + } - // calculate the recalibrated qual using the BQSR formula - double recalibratedQualDouble = origQual + globalDeltaQ + deltaQReported + deltaQCovariates; + double recalibratedQualDouble = hierarchicalBayesianQualityEstimate( epsilon, empiricalQualRG, empiricalQualQS, empiricalQualCovs ); // recalibrated quality is bound between 1 and MAX_QUAL final byte recalibratedQual = QualityUtils.boundQual(MathUtils.fastRound(recalibratedQualDouble), QualityUtils.MAX_RECALIBRATED_Q_SCORE); @@ -220,102 +185,14 @@ public class BaseRecalibration { } } - private double getGlobalDeltaQ(final int rgKey, final EventType errorModel) { - final Double cached = globalDeltaQs.get(rgKey, errorModel.ordinal()); - - if ( TEST_CACHING ) { - final double calcd = calculateGlobalDeltaQ(rgKey, errorModel); - if ( calcd != cached ) - throw new IllegalStateException("calculated " + calcd + " and cached " + cached + " global delta q not equal at " + rgKey + " / " + errorModel); + protected double hierarchicalBayesianQualityEstimate( final double epsilon, final RecalDatum empiricalQualRG, final RecalDatum empiricalQualQS, final List empiricalQualCovs ) { + final double globalDeltaQ = ( empiricalQualRG == null ? 0.0 : empiricalQualRG.getEmpiricalQuality(epsilon) - epsilon ); + final double deltaQReported = ( empiricalQualQS == null ? 0.0 : empiricalQualQS.getEmpiricalQuality(globalDeltaQ + epsilon) - (globalDeltaQ + epsilon) ); + double deltaQCovariates = 0.0; + for( final RecalDatum empiricalQualCov : empiricalQualCovs ) { + deltaQCovariates += ( empiricalQualCov == null ? 0.0 : empiricalQualCov.getEmpiricalQuality(deltaQReported + globalDeltaQ + epsilon) - (deltaQReported + globalDeltaQ + epsilon) ); } - return cachedWithDefault(cached); - } - - private double getDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ) { - final Double cached = deltaQReporteds.get(rgKey, qualKey, errorModel.ordinal()); - - if ( TEST_CACHING ) { - final double calcd = calculateDeltaQReported(rgKey, qualKey, errorModel, globalDeltaQ, (byte)qualKey); - if ( calcd != cached ) - throw new IllegalStateException("calculated " + calcd + " and cached " + cached + " global delta q not equal at " + rgKey + " / " + qualKey + " / " + errorModel); - } - - return cachedWithDefault(cached); - } - - /** - * @param d a Double (that may be null) that is the result of a delta Q calculation - * @return a double == d if d != null, or 0.0 if it is - */ - private double cachedWithDefault(final Double d) { - return d == null ? 0.0 : d; - } - - /** - * Note that this calculation is a constant for each rgKey and errorModel. We need only - * compute this value once for all data. - * - * @param rgKey read group key - * @param errorModel the event type - * @return global delta Q - */ - private double calculateGlobalDeltaQ(final int rgKey, final EventType errorModel) { - double result = 0.0; - - final RecalDatum empiricalQualRG = recalibrationTables.getReadGroupTable().get(rgKey, errorModel.ordinal()); - - if (empiricalQualRG != null) { - final double aggregrateQReported = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : empiricalQualRG.getEstimatedQReported() ); - final double globalDeltaQEmpirical = empiricalQualRG.getEmpiricalQuality(aggregrateQReported); - result = globalDeltaQEmpirical - aggregrateQReported; - } - - return result; - } - - private double calculateDeltaQReported(final int rgKey, final int qualKey, final EventType errorModel, final double globalDeltaQ, final byte qualFromRead) { - double result = 0.0; - - final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(rgKey, qualKey, errorModel.ordinal()); - if (empiricalQualQS != null) { - final double deltaQReportedEmpirical = empiricalQualQS.getEmpiricalQuality(globalDeltaQ + qualFromRead); - result = deltaQReportedEmpirical - (globalDeltaQ + qualFromRead); - } - - return result; - } - - private double calculateDeltaQCovariates(final RecalibrationTables recalibrationTables, final int[] key, final EventType errorModel, final double globalDeltaQ, final double deltaQReported, final byte qualFromRead) { - double result = 0.0; - - // for all optional covariates - for (int i = 2; i < requestedCovariates.length; i++) { - if (key[i] < 0) - continue; - - result += calculateDeltaQCovariate(recalibrationTables.getTable(i), - key[0], key[1], key[i], errorModel, - globalDeltaQ, deltaQReported, qualFromRead); - } - - return result; - } - - private double calculateDeltaQCovariate(final NestedIntegerArray table, - final int rgKey, - final int qualKey, - final int tableKey, - final EventType errorModel, - final double globalDeltaQ, - final double deltaQReported, - final byte qualFromRead) { - final RecalDatum empiricalQualCO = table.get(rgKey, qualKey, tableKey, errorModel.ordinal()); - if (empiricalQualCO != null) { - final double deltaQCovariateEmpirical = empiricalQualCO.getEmpiricalQuality(deltaQReported + globalDeltaQ + qualFromRead); - return deltaQCovariateEmpirical - (deltaQReported + globalDeltaQ + qualFromRead); - } else { - return 0.0; - } + return epsilon + globalDeltaQ + deltaQReported + deltaQCovariates; } } From e4ec899a879503f2e56d836d5b8cbe1b18ffc370 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Tue, 29 Jan 2013 15:51:07 -0500 Subject: [PATCH 127/188] First pass at adding unit tests for the RR framework: I have added 3 tests and all 3 uncovered RR bugs! One of the fixes was critical: SlidingWindow was not converting between global and relative positions correctly. Besides not being correct, it was resulting in a massive slow down of the RR traversal. That fix definitely breaks at least one of the integration tests, but it's not worth changing md5s now because I'll be changing things all over RR for the next few days, so I am going to let that test fail indefinitely until I can confirm general correctness of the tool. --- .../reducereads/HeaderElement.java | 8 +- .../reducereads/SimpleGenomeLoc.java | 31 ++- .../reducereads/SlidingWindow.java | 42 +++- .../reducereads/HeaderElementUnitTest.java | 134 +++++++++++ .../reducereads/SimpleGenomeLocUnitTest.java | 106 ++++++++ .../reducereads/SlidingWindowUnitTest.java | 227 ++++++++++++++++++ 6 files changed, 521 insertions(+), 27 deletions(-) create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElementUnitTest.java create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElement.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElement.java index 1e7805fce..13d3d1b4c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElement.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElement.java @@ -244,7 +244,7 @@ public class HeaderElement { * * @return whether or not the HeaderElement is variant due to excess insertions */ - private boolean isVariantFromMismatches(double minVariantProportion) { + protected boolean isVariantFromMismatches(double minVariantProportion) { BaseIndex mostCommon = consensusBaseCounts.baseIndexWithMostProbabilityWithoutIndels(); double mostCommonProportion = consensusBaseCounts.baseCountProportionWithoutIndels(mostCommon); return mostCommonProportion != 0.0 && mostCommonProportion < (1 - minVariantProportion); @@ -256,11 +256,11 @@ public class HeaderElement { * * @return true if we had more soft clipped bases contributing to this site than matches/mismatches. */ - private boolean isVariantFromSoftClips() { - return nSoftClippedBases >= (consensusBaseCounts.totalCount() - nSoftClippedBases); + protected boolean isVariantFromSoftClips() { + return nSoftClippedBases > 0 && nSoftClippedBases >= (consensusBaseCounts.totalCount() - nSoftClippedBases); } - private boolean basePassesFilters(byte baseQual, int minBaseQual, int baseMappingQuality, int minMappingQual) { + protected boolean basePassesFilters(byte baseQual, int minBaseQual, int baseMappingQuality, int minMappingQual) { return baseQual >= minBaseQual && baseMappingQuality >= minMappingQual; } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java index a3ebb132f..85a1f8df1 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java @@ -78,6 +78,13 @@ public class SimpleGenomeLoc extends GenomeLoc { return finished; } + /** + * Merges 2 *contiguous* locs into 1 + * + * @param a SimpleGenomeLoc #1 + * @param b SimpleGenomeLoc #2 + * @return one merged loc + */ @Requires("a != null && b != null") public static SimpleGenomeLoc merge(SimpleGenomeLoc a, SimpleGenomeLoc b) throws ReviewedStingException { if(GenomeLoc.isUnmapped(a) || GenomeLoc.isUnmapped(b)) { @@ -88,7 +95,6 @@ public class SimpleGenomeLoc extends GenomeLoc { throw new ReviewedStingException("The two genome locs need to be contiguous"); } - return new SimpleGenomeLoc(a.getContig(), a.contigIndex, Math.min(a.getStart(), b.getStart()), Math.max(a.getStop(), b.getStop()), @@ -101,19 +107,22 @@ public class SimpleGenomeLoc extends GenomeLoc { * @param sortedLocs a sorted list of contiguous locs * @return one merged loc */ + @Requires("sortedLocs != null") public static SimpleGenomeLoc merge(SortedSet sortedLocs) { - SimpleGenomeLoc previousLoc = null; - for (SimpleGenomeLoc loc : sortedLocs) { - if (loc.isUnmapped()) { + SimpleGenomeLoc result = null; + + for ( SimpleGenomeLoc loc : sortedLocs ) { + if ( loc.isUnmapped() ) throw new ReviewedStingException("Tried to merge unmapped genome locs"); - } - if (previousLoc != null && !previousLoc.contiguousP(loc)) { + + if ( result == null ) + result = loc; + else if ( !result.contiguousP(loc) ) throw new ReviewedStingException("The genome locs need to be contiguous"); - } - previousLoc = loc; + else + result = merge(result, loc); } - SimpleGenomeLoc firstLoc = sortedLocs.first(); - SimpleGenomeLoc lastLoc = sortedLocs.last(); - return merge(firstLoc, lastLoc); + + return result; } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java index e91120f1c..57a11f640 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java @@ -46,6 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; +import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; @@ -135,6 +136,15 @@ public class SlidingWindow { return header.isEmpty() ? -1 : header.peek().getLocation(); } + // for testing only + protected SlidingWindow(final String contig, final int contigIndex, final int startLocation) { + this.contig = contig; + this.contigIndex = contigIndex; + nContigs = 1; + this.windowHeader = new LinkedList(); + windowHeader.addFirst(new HeaderElement(startLocation)); + this.readsInWindow = new TreeSet(); + } public SlidingWindow(String contig, int contigIndex, int contextSize, SAMFileHeader samHeader, GATKSAMReadGroupRecord readGroupAttribute, int windowNumber, final double minAltProportionToTriggerVariant, final double minIndelProportionToTriggerVariant, int minBaseQual, int minMappingQuality, int downsampleCoverage, final ReduceReads.DownsampleStrategy downsampleStrategy, boolean hasIndelQualities, int nContigs, boolean allowPolyploidReduction) { this.contextSize = contextSize; @@ -193,14 +203,17 @@ public class SlidingWindow { } /** - * returns the next complete or incomplete variant region between 'from' (inclusive) and 'to' (exclusive) + * Returns the next complete (or incomplete if closeLastRegion is true) variant region between 'from' (inclusive) and 'to' (exclusive) + * but converted to global coordinates. * - * @param from beginning window header index of the search window (inclusive) - * @param to end window header index of the search window (exclusive) + * @param from beginning window header index of the search window (inclusive); note that this uses local coordinates + * @param to end window header index of the search window (exclusive); note that this uses local coordinates * @param variantSite boolean array with true marking variant regions - * @return null if nothing is variant, start/stop if there is a complete variant region, start/-1 if there is an incomplete variant region. + * @param closeLastRegion if the last index is variant (so it's an incomplete region), should we close (and return as an interval) the location or ignore it? + * @return null if nothing is variant, start/stop if there is a complete variant region, start/-1 if there is an incomplete variant region. All coordinates returned are global. */ - private SimpleGenomeLoc findNextVariantRegion(int from, int to, boolean[] variantSite, boolean forceClose) { + @Requires({"from >= 0", "from <= to", "to <= variantSite.length"}) + private SimpleGenomeLoc findNextVariantRegion(int from, int to, boolean[] variantSite, boolean closeLastRegion) { boolean foundStart = false; final int windowHeaderStart = getStartLocation(windowHeader); int variantRegionStartIndex = 0; @@ -215,22 +228,27 @@ public class SlidingWindow { } final int refStart = windowHeaderStart + variantRegionStartIndex; final int refStop = windowHeaderStart + to - 1; - return (foundStart && forceClose) ? new SimpleGenomeLoc(contig, contigIndex, refStart, refStop, true) : null; + return (foundStart && closeLastRegion) ? new SimpleGenomeLoc(contig, contigIndex, refStart, refStop, true) : null; } /** * Creates a list with all the complete and incomplete variant regions within 'from' (inclusive) and 'to' (exclusive) * - * @param from beginning window header index of the search window (inclusive) - * @param to end window header index of the search window (exclusive) + * @param from beginning window header index of the search window (inclusive); note that this uses local coordinates + * @param to end window header index of the search window (exclusive); note that this uses local coordinates * @param variantSite boolean array with true marking variant regions - * @return a list with start/stops of variant regions following findNextVariantRegion description + * @return a list with start/stops of variant regions following findNextVariantRegion description in global coordinates */ - private CompressionStash findVariantRegions(int from, int to, boolean[] variantSite, boolean forceClose) { + @Requires({"from >= 0", "from <= to", "to <= variantSite.length"}) + @Ensures("result != null") + protected CompressionStash findVariantRegions(int from, int to, boolean[] variantSite, boolean closeLastRegion) { + final int windowHeaderStart = getStartLocation(windowHeader); + CompressionStash regions = new CompressionStash(); int index = from; while(index < to) { - SimpleGenomeLoc result = findNextVariantRegion(index, to, variantSite, forceClose); + // returns results in global coordinates + SimpleGenomeLoc result = findNextVariantRegion(index, to, variantSite, closeLastRegion); if (result == null) break; @@ -238,7 +256,7 @@ public class SlidingWindow { if (!result.isFinished()) break; - index = result.getStop() + 1; + index = result.getStop() - windowHeaderStart + 1; // go back to local coordinates } return regions; } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElementUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElementUnitTest.java new file mode 100644 index 000000000..b6af954a0 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/HeaderElementUnitTest.java @@ -0,0 +1,134 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.compression.reducereads; + + +import org.broadinstitute.sting.BaseTest; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +public class HeaderElementUnitTest extends BaseTest { + + private class HETest { + public byte base, baseQual, insQual, delQual; + public int MQ; + public boolean isClip; + + private HETest(final byte base, final byte baseQual, final byte insQual, final byte delQual, final int MQ, final boolean isClip) { + this.base = base; + this.baseQual = baseQual; + this.insQual = insQual; + this.delQual = delQual; + this.MQ = MQ; + this.isClip = isClip; + } + } + + private static final byte byteA = (byte)'A'; + private static final byte byte10 = (byte)10; + private static final byte byte20 = (byte)20; + private static final int minBaseQual = 20; + private static final int minMappingQual = 20; + + @DataProvider(name = "data") + public Object[][] createData() { + List tests = new ArrayList(); + + tests.add(new Object[]{new HETest(byteA, byte20, byte20, byte20, 20, false)}); + tests.add(new Object[]{new HETest(byteA, byte10, byte20, byte20, 20, false)}); + tests.add(new Object[]{new HETest(byteA, byte20, byte20, byte20, 10, false)}); + tests.add(new Object[]{new HETest(byteA, byte20, byte20, byte20, 20, true)}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "data", enabled = true) + public void testHE(HETest test) { + + HeaderElement headerElement = new HeaderElement(1000, 0); + + // first test that if we add and then remove it, we have no data + headerElement.addBase(test.base, test.baseQual, test.insQual, test.delQual, test.MQ, minBaseQual, minMappingQual, test.isClip); + headerElement.addInsertionToTheRight(); + headerElement.removeBase(test.base, test.baseQual, test.insQual, test.delQual, test.MQ, minBaseQual, minMappingQual, test.isClip); + headerElement.removeInsertionToTheRight(); + testHeaderIsEmpty(headerElement); + + // now, test that the data was added as expected + for ( int i = 0; i < 10; i++ ) + headerElement.addBase(test.base, test.baseQual, test.insQual, test.delQual, test.MQ, minBaseQual, minMappingQual, test.isClip); + testHeaderData(headerElement, test); + + // test the insertion adding functionality + for ( int i = 0; i < 10; i++ ) + headerElement.addInsertionToTheRight(); + Assert.assertEquals(headerElement.numInsertionsToTheRight(), 10); + } + + private void testHeaderIsEmpty(final HeaderElement headerElement) { + Assert.assertFalse(headerElement.hasConsensusData()); + Assert.assertFalse(headerElement.hasFilteredData()); + Assert.assertFalse(headerElement.hasInsertionToTheRight()); + Assert.assertTrue(headerElement.isEmpty()); + Assert.assertEquals(headerElement.getRMS(), 0.0); + } + + private void testHeaderData(final HeaderElement headerElement, final HETest test) { + Assert.assertEquals(headerElement.getRMS(), (double)test.MQ); + Assert.assertEquals(headerElement.isVariantFromSoftClips(), test.isClip); + Assert.assertFalse(headerElement.isEmpty()); + Assert.assertFalse(headerElement.hasInsertionToTheRight()); + Assert.assertEquals(headerElement.hasConsensusData(), headerElement.basePassesFilters(test.baseQual, minBaseQual, test.MQ, minMappingQual)); + Assert.assertEquals(headerElement.hasFilteredData(), !headerElement.basePassesFilters(test.baseQual, minBaseQual, test.MQ, minMappingQual)); + Assert.assertFalse(headerElement.isVariantFromMismatches(0.05)); + Assert.assertEquals(headerElement.isVariant(0.05, 0.05), test.isClip); + } +} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java new file mode 100644 index 000000000..cbac7e3c1 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java @@ -0,0 +1,106 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.compression.reducereads; + + +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.*; + +public class SimpleGenomeLocUnitTest extends BaseTest { + + private static final SimpleGenomeLoc loc1 = new SimpleGenomeLoc("1", 0, 10, 20, false); + private static final SimpleGenomeLoc loc2 = new SimpleGenomeLoc("1", 0, 21, 30, false); + private static final SimpleGenomeLoc loc3 = new SimpleGenomeLoc("1", 0, 31, 40, false); + + private class SGLTest { + public List locs; + + private SGLTest(final List locs) { + this.locs = locs; + } + } + + @DataProvider(name = "SGLtest") + public Object[][] createFindVariantRegionsData() { + List tests = new ArrayList(); + + tests.add(new Object[]{new SGLTest(Arrays.asList(loc1))}); + tests.add(new Object[]{new SGLTest(Arrays.asList(loc1, loc2))}); + tests.add(new Object[]{new SGLTest(Arrays.asList(loc1, loc2, loc3))}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "SGLtest", enabled = true) + public void testSimpleGenomeLoc(SGLTest test) { + testMerge(test.locs); + } + + @Test(expectedExceptions = ReviewedStingException.class) + public void testNotContiguousLocs() { + final List locs = new ArrayList(1); + locs.add(loc1); + locs.add(loc3); + testMerge(locs); + } + + private void testMerge(final List locs) { + SimpleGenomeLoc result1 = locs.get(0); + for ( int i = 1; i < locs.size(); i++ ) + result1 = SimpleGenomeLoc.merge(result1, locs.get(i)); + + SimpleGenomeLoc result2 = SimpleGenomeLoc.merge(new TreeSet(locs)); + Assert.assertEquals(result1, result2); + Assert.assertEquals(result1.getStart(), locs.get(0).getStart()); + Assert.assertEquals(result1.getStop(), locs.get(locs.size() - 1).getStop()); + } +} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java new file mode 100644 index 000000000..cfb8c53b4 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java @@ -0,0 +1,227 @@ +/* +* 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.walkers.compression.reducereads; + +import net.sf.samtools.SAMFileHeader; +import net.sf.samtools.SAMReadGroupRecord; +import net.sf.samtools.SAMRecord; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.broadinstitute.sting.utils.sam.ArtificialSingleSampleReadStream; +import org.broadinstitute.sting.utils.sam.ArtificialSingleSampleReadStreamAnalyzer; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SlidingWindowUnitTest extends BaseTest { + + ////////////////////////////////////////////////////////////////////////////////////// + //// This section tests the findVariantRegions() method and related functionality //// + ////////////////////////////////////////////////////////////////////////////////////// + + private static final int variantRegionLength = 1000; + private static final int globalStartPosition = 1000000; + private static final SimpleGenomeLoc loc90to95 = new SimpleGenomeLoc("1", 0, 1000090, 1000095, false); + private static final SimpleGenomeLoc loc96to99 = new SimpleGenomeLoc("1", 0, 1000096, 1000099, false); + private static final SimpleGenomeLoc loc100to110 = new SimpleGenomeLoc("1", 0, 1000100, 1000110, false); + private static final SimpleGenomeLoc loc999 = new SimpleGenomeLoc("1", 0, 1000999, 1000999, false); + + private class FindVariantRegionsTest { + public List locs, expectedResult; + public boolean[] variantRegionBitset; + + private FindVariantRegionsTest(final List locs) { + this.locs = locs; + this.expectedResult = locs; + variantRegionBitset = createBitset(locs); + } + + private FindVariantRegionsTest(final List locs, final List expectedResult) { + this.locs = locs; + this.expectedResult = expectedResult; + variantRegionBitset = createBitset(locs); + } + } + + private static boolean[] createBitset(final List locs) { + boolean[] variantRegionBitset = new boolean[variantRegionLength]; + for ( SimpleGenomeLoc loc : locs ) { + final int stop = loc.getStop() - globalStartPosition; + for ( int i = loc.getStart() - globalStartPosition; i <= stop; i++ ) + variantRegionBitset[i] = true; + } + return variantRegionBitset; + } + + @DataProvider(name = "findVariantRegions") + public Object[][] createFindVariantRegionsData() { + List tests = new ArrayList(); + + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc100to110))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc96to99, loc100to110), Arrays.asList(new SimpleGenomeLoc("1", 0, 1000090, 1000110, false)))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc999))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc999))}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "findVariantRegions", enabled = true) + public void testFindVariantRegions(FindVariantRegionsTest test) { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); + final CompressionStash locs = slidingWindow.findVariantRegions(0, variantRegionLength, test.variantRegionBitset, true); + int index = 0; + for ( final SimpleGenomeLoc loc : locs ) { + Assert.assertTrue(loc.equals(test.expectedResult.get(index++))); + } + } + + @Test(enabled = true) + public void testNoClosingRegions() { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); + final CompressionStash locs = slidingWindow.findVariantRegions(0, variantRegionLength, createBitset(Arrays.asList(loc90to95, loc999)), false); + Assert.assertEquals(locs.size(), 1); + Assert.assertEquals(locs.iterator().next(), loc90to95); + } + + + + + + + + + + + + + + /* + + private static class DownsamplingReadsIteratorTest extends TestDataProvider { + private DownsamplingReadsIterator downsamplingIter; + private int targetCoverage; + private ArtificialSingleSampleReadStream stream; + private ArtificialSingleSampleReadStreamAnalyzer streamAnalyzer; + + public DownsamplingReadsIteratorTest( ArtificialSingleSampleReadStream stream, int targetCoverage ) { + super(DownsamplingReadsIteratorTest.class); + + this.stream = stream; + this.targetCoverage = targetCoverage; + + setName(String.format("%s: targetCoverage=%d numContigs=%d stacksPerContig=%d readsPerStack=%d-%d distanceBetweenStacks=%d-%d readLength=%d-%d unmappedReads=%d", + getClass().getSimpleName(), + targetCoverage, + stream.getNumContigs(), + stream.getNumStacksPerContig(), + stream.getMinReadsPerStack(), + stream.getMaxReadsPerStack(), + stream.getMinDistanceBetweenStacks(), + stream.getMaxDistanceBetweenStacks(), + stream.getMinReadLength(), + stream.getMaxReadLength(), + stream.getNumUnmappedReads())); + } + + public void run() { + streamAnalyzer = new PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer(stream, targetCoverage); + downsamplingIter = new DownsamplingReadsIterator(stream.getStingSAMIterator(), new SimplePositionalDownsampler(targetCoverage)); + + streamAnalyzer.analyze(downsamplingIter); + + // Check whether the observed properties of the downsampled stream are what they should be + streamAnalyzer.validate(); + + // Allow memory used by this test to be reclaimed + stream = null; + streamAnalyzer = null; + downsamplingIter = null; + } + } + + @DataProvider(name = "DownsamplingReadsIteratorTestDataProvider") + public Object[][] createDownsamplingReadsIteratorTests() { + SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(5, 1, 10000); + String readGroupID = "testReadGroup"; + SAMReadGroupRecord readGroup = new SAMReadGroupRecord(readGroupID); + readGroup.setSample("testSample"); + header.addReadGroup(readGroup); + + // Values that don't vary across tests + int targetCoverage = 10; + int minReadLength = 50; + int maxReadLength = 100; + int minDistanceBetweenStacks = 1; + int maxDistanceBetweenStacks = maxReadLength + 1; + + GenomeAnalysisEngine.resetRandomGenerator(); + + // brute force testing! + for ( int numContigs : Arrays.asList(1, 2, 5) ) { + for ( int stacksPerContig : Arrays.asList(1, 2, 10) ) { + for ( int minReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) { + for ( int maxReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) { + for ( int numUnmappedReads : Arrays.asList(0, 1, targetCoverage, targetCoverage * 2) ) { + // Only interested in sane read stream configurations here + if ( minReadsPerStack <= maxReadsPerStack ) { + new DownsamplingReadsIteratorTest(new ArtificialSingleSampleReadStream(header, + readGroupID, + numContigs, + stacksPerContig, + minReadsPerStack, + maxReadsPerStack, + minDistanceBetweenStacks, + maxDistanceBetweenStacks, + minReadLength, + maxReadLength, + numUnmappedReads), + targetCoverage); + } + } + } + } + } + } + + return DownsamplingReadsIteratorTest.getTests(DownsamplingReadsIteratorTest.class); + } + + @Test(dataProvider = "DownsamplingReadsIteratorTestDataProvider") + public void runDownsamplingReadsIteratorTest( DownsamplingReadsIteratorTest test ) { + logger.warn("Running test: " + test); + + GenomeAnalysisEngine.resetRandomGenerator(); + test.run(); + } + + */ +} From 4aaef495c6f6b1ee9a52877aa78ca94f14d80c49 Mon Sep 17 00:00:00 2001 From: Ami Levy-Moonshine Date: Tue, 29 Jan 2013 16:33:12 -0500 Subject: [PATCH 128/188] correct the help message --- public/java/src/org/broadinstitute/sting/tools/CatVariants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java index 07a90bb11..93246fd6f 100644 --- a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java +++ b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java @@ -51,7 +51,7 @@ import java.util.*; /** * - * Usage: java -cp dist/GenomeAnalysisTK.jar org.broadinstitute.sting.tools.AppendVariants [sorted (optional)]"); + * Usage: java -cp dist/GenomeAnalysisTK.jar org.broadinstitute.sting.tools.CatVariants [sorted (optional)]"); * The input files can be of type: VCF (ends in .vcf or .VCF)"); * BCF2 (ends in .bcf or .BCF)"); * Output file must be vcf or bcf file (.vcf or .bcf)"); From a536e1da848fa8407557f0f850c78475255e9e8f Mon Sep 17 00:00:00 2001 From: David Roazen Date: Tue, 29 Jan 2013 13:57:39 -0500 Subject: [PATCH 130/188] Move some VCF/VariantContext methods back to the GATK based on feedback -Moved some of the more specialized / complex VariantContext and VCF utility methods back to the GATK. -Due to this re-shuffling, was able to return things like the Pair class back to the GATK as well. --- .../gatk/walkers/annotator/RankSumTest.java | 2 +- .../annotator/TandemRepeatAnnotator.java | 6 +- .../gatk/walkers/bqsr/BaseRecalibrator.java | 2 +- .../reducereads/MultiSampleCompressor.java | 2 +- .../reducereads/SingleSampleCompressor.java | 2 +- .../reducereads/SlidingWindow.java | 2 +- .../genotyper/ConsensusAlleleCounter.java | 5 +- .../GeneralPloidyGenotypeLikelihoods.java | 2 +- ...dyGenotypeLikelihoodsCalculationModel.java | 2 +- .../genotyper/UnifiedArgumentCollection.java | 4 +- .../walkers/genotyper/UnifiedGenotyper.java | 4 +- .../genotyper/UnifiedGenotyperEngine.java | 7 +- .../genotyper/afcalc/DiploidExactAFCalc.java | 5 +- .../walkers/genotyper/afcalc/ExactAFCalc.java | 4 +- .../afcalc/GeneralPloidyExactAFCalc.java | 5 +- .../afcalc/OriginalDiploidExactAFCalc.java | 2 +- .../haplotypecaller/GenotypingEngine.java | 5 +- .../haplotypecaller/HaplotypeCaller.java | 5 +- .../gatk/walkers/indels/IndelRealigner.java | 2 +- .../walkers/phasing/PhaseByTransmission.java | 3 +- .../validation/GenotypeAndValidate.java | 4 +- .../ValidationSiteSelector.java | 4 +- .../variantutils/RegenotypeVariants.java | 3 +- .../utils/recalibration/RecalDatumNode.java | 2 +- .../sting/utils/recalibration/RecalUtils.java | 2 +- .../recalibration/RecalibrationReport.java | 2 +- .../covariates/RepeatCovariate.java | 10 +- .../RepeatUnitAndLengthCovariate.java | 12 - .../covariates/RepeatUnitCovariate.java | 14 - ...eralPloidyGenotypeLikelihoodsUnitTest.java | 2 +- .../afcalc/AFCalcPerformanceUnitTest.java | 2 +- .../StratificationManagerUnitTest.java | 2 +- .../ConcordanceMetricsUnitTest.java | 2 +- .../RepeatCovariatesUnitTest.java | 44 +- .../sting/commandline/ParsingEngine.java | 2 +- .../providers/RODMetaDataContainer.java | 2 +- .../sting/gatk/executive/Accumulator.java | 2 +- .../gatk/refdata/VariantContextAdaptors.java | 3 +- .../gatk/refdata/tracks/RMDTrackBuilder.java | 2 +- .../sting/gatk/walkers/Walker.java | 2 +- .../annotator/VariantAnnotatorEngine.java | 3 +- .../walkers/coverage/DepthOfCoverage.java | 2 +- .../walkers/coverage/GCContentByInterval.java | 2 +- .../fasta/FastaAlternateReferenceMaker.java | 2 +- .../walkers/fasta/FastaReferenceMaker.java | 2 +- .../sting/gatk/walkers/qc/CountIntervals.java | 2 +- .../sting/gatk/walkers/qc/CountRODs.java | 2 +- .../sting/gatk/walkers/qc/CountRODsByRef.java | 2 +- .../gatk/walkers/qc/CountTerminusEvent.java | 2 +- .../gatk/walkers/readutils/ClipReads.java | 2 +- .../gatk/walkers/varianteval/VariantEval.java | 5 +- .../varianteval/VariantEvalReportWriter.java | 2 +- .../stratifications/TandemRepeat.java | 4 +- .../manager/StratificationManager.java | 2 +- .../walkers/variantutils/CombineVariants.java | 23 +- .../variantutils/GenotypeConcordance.java | 2 +- .../walkers/variantutils/SelectHeaders.java | 4 +- .../walkers/variantutils/SelectVariants.java | 5 +- .../VariantValidationAssessor.java | 4 +- .../walkers/variantutils/VariantsToTable.java | 3 +- .../walkers/variantutils/VariantsToVCF.java | 2 +- .../sting/tools/CatVariants.java | 2 +- .../sting/utils/MannWhitneyU.java | 2 +- .../sting/utils/SWPairwiseAlignment.java | 2 +- .../sting/utils/SampleUtils.java | 10 +- .../broadinstitute/sting/utils/baq/BAQ.java | 2 +- .../utils/collections}/Pair.java | 2 +- .../sting/utils/duplicates/DupUtils.java | 2 +- .../sting/utils/fragments/FragmentUtils.java | 2 +- .../help/GenericDocumentationHandler.java | 2 +- .../sting/utils/interval/IntervalUtils.java | 2 +- .../sting/utils/sam/ReadUtils.java | 2 +- .../sting/utils/variant/GATKVCFUtils.java | 47 +- .../variant/GATKVariantContextUtils.java | 948 ++++++++++++++++++ .../variant/utils/BaseUtils.java | 6 +- .../variant/utils/GeneralUtils.java | 7 - .../variant/variantcontext/CommonInfo.java | 2 +- .../variantcontext/VariantContextUtils.java | 940 +---------------- .../broadinstitute/variant/vcf/VCFUtils.java | 50 - .../org/broadinstitute/sting/WalkerTest.java | 2 +- .../sting/utils/MWUnitTest.java | 2 +- .../BandPassActivityProfileUnitTest.java | 6 +- .../GATKVariantContextUtilsUnitTest.java} | 332 +++--- .../variant/VariantContextBenchmark.java | 6 +- .../variant/VariantBaseTest.java | 25 + .../VariantContextTestProvider.java | 51 +- .../VariantContextUnitTest.java | 74 -- 87 files changed, 1408 insertions(+), 1386 deletions(-) rename public/java/src/org/broadinstitute/{variant/utils => sting/utils/collections}/Pair.java (98%) rename public/java/test/org/broadinstitute/{variant/variantcontext/VariantContextUtilsUnitTest.java => sting/utils/variant/GATKVariantContextUtilsUnitTest.java} (79%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java index 6f965227c..ec107512a 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/RankSumTest.java @@ -57,7 +57,7 @@ import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.sting.utils.MannWhitneyU; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.variant.vcf.VCFHeaderLine; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.Allele; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java index a6b713551..2e0e759c2 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/TandemRepeatAnnotator.java @@ -53,8 +53,8 @@ import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompa import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.InfoFieldAnnotation; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.StandardAnnotation; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.vcf.VCFHeaderLineCount; import org.broadinstitute.variant.vcf.VCFHeaderLineType; import org.broadinstitute.variant.vcf.VCFInfoHeaderLine; @@ -79,7 +79,7 @@ public class TandemRepeatAnnotator extends InfoFieldAnnotation implements Standa if ( !vc.isIndel()) return null; - Pair,byte[]> result = VariantContextUtils.getNumTandemRepeatUnits(vc, ref.getForwardBases()); + Pair,byte[]> result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, ref.getForwardBases()); if (result == null) return null; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java index 002bdc39f..2df5fefa8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java @@ -63,7 +63,7 @@ import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java index 50d741f13..6818669df 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/MultiSampleCompressor.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; import net.sf.samtools.SAMFileHeader; import org.apache.log4j.Logger; import org.broadinstitute.sting.utils.SampleUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java index 5b08e99a0..036d2782a 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SingleSampleCompressor.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java index 57a11f640..7ce606f20 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java @@ -53,7 +53,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.gatk.downsampling.ReservoirDownsampler; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.recalibration.EventType; import org.broadinstitute.sting.utils.sam.AlignmentStartWithNoTiesComparator; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java index 90904ab29..ddf47805f 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/ConsensusAlleleCounter.java @@ -53,7 +53,8 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; @@ -288,7 +289,7 @@ public class ConsensusAlleleCounter { if (vcs.isEmpty()) return Collections.emptyList(); // nothing else to do, no alleles passed minimum count criterion - final VariantContext mergedVC = VariantContextUtils.simpleMerge(vcs, null, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, VariantContextUtils.GenotypeMergeType.UNSORTED, false, false, null, false, false); + final VariantContext mergedVC = GATKVariantContextUtils.simpleMerge(vcs, null, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, GATKVariantContextUtils.GenotypeMergeType.UNSORTED, false, false, null, false, false); return mergedVC.getAlleles(); } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java index 6a5fbce39..cf144a735 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoods.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.ExactACcounts; import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.ExactACset; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.variant.vcf.VCFConstants; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java index 23804bb23..3e0437edb 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsCalculationModel.java @@ -56,7 +56,7 @@ import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.variant.vcf.VCFConstants; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.*; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java index e97c92309..a7f90ebec 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedArgumentCollection.java @@ -49,8 +49,8 @@ package org.broadinstitute.sting.gatk.walkers.genotyper; import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.arguments.StandardCallerArgumentCollection; import org.broadinstitute.sting.utils.pairhmm.PairHMM; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.VariantContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; public class UnifiedArgumentCollection extends StandardCallerArgumentCollection { @@ -172,7 +172,7 @@ public class UnifiedArgumentCollection extends StandardCallerArgumentCollection Sample ploidy - equivalent to number of chromosomes per pool. In pooled experiments this should be = # of samples in pool * individual sample ploidy */ @Argument(shortName="ploidy", fullName="sample_ploidy", doc="Plody (number of chromosomes) per sample. For pooled data, set to (Number of samples in each pool * Sample Ploidy).", required=false) - public int samplePloidy = VariantContextUtils.DEFAULT_PLOIDY; + public int samplePloidy = GATKVariantContextUtils.DEFAULT_PLOIDY; @Hidden @Argument(shortName="minqs", fullName="min_quality_score", doc="Min quality score to consider. Smaller numbers process faster. Default: Q1.", required=false) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java index 46ac10d90..d16ece4fd 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java @@ -61,7 +61,7 @@ import org.broadinstitute.sting.gatk.walkers.annotator.VariantAnnotatorEngine; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompatible; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -304,7 +304,7 @@ public class UnifiedGenotyper extends LocusWalker, Unif headerInfo.add(new VCFInfoHeaderLine(UnifiedGenotyperEngine.NUMBER_OF_DISCOVERED_ALLELES_KEY, 1, VCFHeaderLineType.Integer, "Number of alternate alleles discovered (but not necessarily genotyped) at this site")); // add the pool values for each genotype - if (UAC.samplePloidy != VariantContextUtils.DEFAULT_PLOIDY) { + if (UAC.samplePloidy != GATKVariantContextUtils.DEFAULT_PLOIDY) { headerInfo.add(new VCFFormatHeaderLine(VCFConstants.MLE_PER_SAMPLE_ALLELE_COUNT_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Integer, "Maximum likelihood expectation (MLE) for the alternate allele count, in the same order as listed, for each individual sample")); headerInfo.add(new VCFFormatHeaderLine(VCFConstants.MLE_PER_SAMPLE_ALLELE_FRACTION_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Float, "Maximum likelihood expectation (MLE) for the alternate allele fraction, in the same order as listed, for each individual sample")); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java index b1aaf8190..8f6097661 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java @@ -61,6 +61,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.AFCalcResult; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.classloader.PluginManager; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -134,7 +135,7 @@ public class UnifiedGenotyperEngine { // --------------------------------------------------------------------------------------------------------- @Requires({"toolkit != null", "UAC != null"}) public UnifiedGenotyperEngine(GenomeAnalysisEngine toolkit, UnifiedArgumentCollection UAC) { - this(toolkit, UAC, Logger.getLogger(UnifiedGenotyperEngine.class), null, null, SampleUtils.getSAMFileSamples(toolkit.getSAMFileHeader()), VariantContextUtils.DEFAULT_PLOIDY); + this(toolkit, UAC, Logger.getLogger(UnifiedGenotyperEngine.class), null, null, SampleUtils.getSAMFileSamples(toolkit.getSAMFileHeader()), GATKVariantContextUtils.DEFAULT_PLOIDY); } @Requires({"toolkit != null", "UAC != null", "logger != null", "samples != null && samples.size() > 0","ploidy>0"}) @@ -525,7 +526,7 @@ public class UnifiedGenotyperEngine { // if we are subsetting alleles (either because there were too many or because some were not polymorphic) // then we may need to trim the alleles (because the original VariantContext may have had to pad at the end). if ( myAlleles.size() != vc.getAlleles().size() && !limitedContext ) // limitedContext callers need to handle allele trimming on their own to keep their perReadAlleleLikelihoodMap alleles in sync - vcCall = VariantContextUtils.reverseTrimAlleles(vcCall); + vcCall = GATKVariantContextUtils.reverseTrimAlleles(vcCall); if ( annotationEngine != null && !limitedContext ) { // limitedContext callers need to handle annotations on their own by calling their own annotationEngine // Note: we want to use the *unfiltered* and *unBAQed* context for the annotations @@ -662,7 +663,7 @@ public class UnifiedGenotyperEngine { private void determineGLModelsToUse() { String modelPrefix = ""; - if ( !UAC.GLmodel.name().contains(GPSTRING) && UAC.samplePloidy != VariantContextUtils.DEFAULT_PLOIDY ) + if ( !UAC.GLmodel.name().contains(GPSTRING) && UAC.samplePloidy != GATKVariantContextUtils.DEFAULT_PLOIDY ) modelPrefix = GPSTRING; if ( UAC.GLmodel.name().toUpperCase().contains("BOTH") ) { diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java index 68f57a300..170b6e250 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/DiploidExactAFCalc.java @@ -47,6 +47,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.*; import java.util.*; @@ -105,7 +106,7 @@ public abstract class DiploidExactAFCalc extends ExactAFCalc { alleles.add(vc.getReference()); alleles.addAll(chooseMostLikelyAlternateAlleles(vc, getMaxAltAlleles())); builder.alleles(alleles); - builder.genotypes(VariantContextUtils.subsetDiploidAlleles(vc, alleles, false)); + builder.genotypes(GATKVariantContextUtils.subsetDiploidAlleles(vc, alleles, false)); return builder.make(); } else { return vc; @@ -351,6 +352,6 @@ public abstract class DiploidExactAFCalc extends ExactAFCalc { final List allelesToUse, final boolean assignGenotypes, final int ploidy) { - return VariantContextUtils.subsetDiploidAlleles(vc, allelesToUse, assignGenotypes); + return GATKVariantContextUtils.subsetDiploidAlleles(vc, allelesToUse, assignGenotypes); } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java index cf6b67afd..3d28db159 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/ExactAFCalc.java @@ -47,10 +47,10 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.Genotype; import org.broadinstitute.variant.variantcontext.GenotypesContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.ArrayList; @@ -92,7 +92,7 @@ abstract class ExactAFCalc extends AFCalc { if ( sample.hasLikelihoods() ) { double[] gls = sample.getLikelihoods().getAsVector(); - if ( MathUtils.sum(gls) < VariantContextUtils.SUM_GL_THRESH_NOCALL ) + if ( MathUtils.sum(gls) < GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) genotypeLikelihoods.add(gls); } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java index 1e1652c68..f8c364e82 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/GeneralPloidyExactAFCalc.java @@ -48,6 +48,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.gatk.walkers.genotyper.GeneralPloidyGenotypeLikelihoods; import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.variant.variantcontext.*; @@ -553,7 +554,7 @@ public class GeneralPloidyExactAFCalc extends ExactAFCalc { } // if there is no mass on the (new) likelihoods, then just no-call the sample - if ( MathUtils.sum(newLikelihoods) > VariantContextUtils.SUM_GL_THRESH_NOCALL ) { + if ( MathUtils.sum(newLikelihoods) > GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) { newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); } else { @@ -565,7 +566,7 @@ public class GeneralPloidyExactAFCalc extends ExactAFCalc { gb.PL(newLikelihoods); // if we weren't asked to assign a genotype, then just no-call the sample - if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > VariantContextUtils.SUM_GL_THRESH_NOCALL ) + if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > GATKVariantContextUtils.SUM_GL_THRESH_NOCALL ) gb.alleles(NO_CALL_ALLELES); else assignGenotype(gb, newLikelihoods, allelesToUse, ploidy); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java index 92305fe4b..325d3b722 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/OriginalDiploidExactAFCalc.java @@ -47,7 +47,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.VariantContext; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java index fa15eccdf..9aeffe966 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java @@ -57,6 +57,7 @@ import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.*; @@ -173,7 +174,7 @@ public class GenotypingEngine { validatePriorityList( priorityList, eventsAtThisLoc ); // Merge the event to find a common reference representation - final VariantContext mergedVC = VariantContextUtils.simpleMerge(eventsAtThisLoc, priorityList, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, VariantContextUtils.GenotypeMergeType.PRIORITIZE, false, false, null, false, false); + final VariantContext mergedVC = GATKVariantContextUtils.simpleMerge(eventsAtThisLoc, priorityList, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, false, false, null, false, false); if( mergedVC == null ) { continue; } if( eventsAtThisLoc.size() != mergedVC.getAlternateAlleles().size() ) { @@ -203,7 +204,7 @@ public class GenotypingEngine { VariantContext annotatedCall = annotationEngine.annotateContext(stratifiedReadMap, call); if( annotatedCall.getAlleles().size() != mergedVC.getAlleles().size() ) { // some alleles were removed so reverseTrimming might be necessary! - annotatedCall = VariantContextUtils.reverseTrimAlleles(annotatedCall); + annotatedCall = GATKVariantContextUtils.reverseTrimAlleles(annotatedCall); } returnCalls.add( annotatedCall ); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 455809a17..8b3eb9f1b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -72,6 +72,7 @@ import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.sting.utils.activeregion.ActiveRegionReadState; import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; import org.broadinstitute.sting.utils.clipping.ReadClipper; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; @@ -297,7 +298,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem samplesList.addAll( samples ); // initialize the UnifiedGenotyper Engine which is used to call into the exact model final UnifiedArgumentCollection UAC = new UnifiedArgumentCollection( SCAC ); // this adapter is used so that the full set of unused UG arguments aren't exposed to the HC user - UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); + UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); // create a UAC but with the exactCallsLog = null, so we only output the log for the HC caller itself, if requested UnifiedArgumentCollection simpleUAC = new UnifiedArgumentCollection(UAC); @@ -307,7 +308,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem simpleUAC.STANDARD_CONFIDENCE_FOR_EMITTING = Math.min( 4.0, UAC.STANDARD_CONFIDENCE_FOR_EMITTING ); // low values used for isActive determination only, default/user-specified values used for actual calling simpleUAC.CONTAMINATION_FRACTION = 0.0; simpleUAC.exactCallsLog = null; - UG_engine_simple_genotyper = new UnifiedGenotyperEngine(getToolkit(), simpleUAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); + UG_engine_simple_genotyper = new UnifiedGenotyperEngine(getToolkit(), simpleUAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); // initialize the output VCF header annotationEngine = new VariantAnnotatorEngine(Arrays.asList(annotationClassesToUse), annotationsToUse, annotationsToExclude, this, getToolkit()); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java index 1865cadea..851703648 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java @@ -63,7 +63,7 @@ import org.broadinstitute.sting.gatk.walkers.BAQMode; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java index 4510dfe55..80c49ff19 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java @@ -59,6 +59,7 @@ import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; @@ -444,7 +445,7 @@ public class PhaseByTransmission extends RodWalker, HashMa ArrayList rodNames = new ArrayList(); rodNames.add(variantCollection.variants.getName()); Map vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), rodNames); - Set vcfSamples = SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); + Set vcfSamples = SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); //Get the trios from the families passed as ped setTrios(); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java index 927e1e607..f0efb3cd9 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/GenotypeAndValidate.java @@ -58,12 +58,12 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; import org.broadinstitute.sting.gatk.walkers.genotyper.VariantCallContext; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.variant.vcf.VCFHeaderLine; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextBuilder; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.broadinstitute.variant.vcf.VCFUtils; @@ -327,7 +327,7 @@ public class GenotypeAndValidate extends RodWalker header = GATKVCFUtils.getVCFHeadersFromRodPrefix(getToolkit(), alleles.getName()); - samples = SampleUtils.getSampleList(header, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); + samples = SampleUtils.getSampleList(header, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); Set headerLines = VCFUtils.smartMergeHeaders(header.values(), true); headerLines.add(new VCFHeaderLine("source", "GenotypeAndValidate")); vcfWriter.writeHeader(new VCFHeader(headerLines, samples)); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/validationsiteselector/ValidationSiteSelector.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/validationsiteselector/ValidationSiteSelector.java index dcd7cd67b..ce44f546d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/validationsiteselector/ValidationSiteSelector.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/validation/validationsiteselector/ValidationSiteSelector.java @@ -54,12 +54,12 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.SampleUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.variant.vcf.VCFHeaderLine; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.VariantContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import java.io.File; @@ -227,7 +227,7 @@ public class ValidationSiteSelector extends RodWalker { public void initialize() { // Get list of samples to include in the output Map vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit()); - TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); + TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); Collection samplesFromFile = SampleUtils.getSamplesFromFiles(sampleFiles); Collection samplesFromExpressions = SampleUtils.matchSamplesExpressions(vcfSamples, sampleExpressions); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java index 74ab8f073..c8fc27e6a 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/RegenotypeVariants.java @@ -61,6 +61,7 @@ import org.broadinstitute.sting.gatk.walkers.genotyper.UnifiedGenotyperEngine; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.broadinstitute.variant.vcf.*; @@ -115,7 +116,7 @@ public class RegenotypeVariants extends RodWalker implements T String trackName = variantCollection.variants.getName(); Set samples = SampleUtils.getSampleListWithVCFHeader(getToolkit(), Arrays.asList(trackName)); - UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, VariantContextUtils.DEFAULT_PLOIDY); + UG_engine = new UnifiedGenotyperEngine(getToolkit(), UAC, logger, null, null, samples, GATKVariantContextUtils.DEFAULT_PLOIDY); final Set hInfo = new HashSet(); hInfo.addAll(GATKVCFUtils.getHeaderFields(getToolkit(), Arrays.asList(trackName))); diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java index 9122c9ab6..637d9fb2d 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java @@ -51,7 +51,7 @@ import com.google.java.contract.Requires; import org.apache.commons.math.MathException; import org.apache.commons.math.stat.inference.ChiSquareTestImpl; import org.apache.log4j.Logger; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.Collection; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java index e44f2e06e..699f26c5e 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalUtils.java @@ -58,7 +58,7 @@ import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.PluginManager; import org.broadinstitute.sting.utils.collections.NestedIntegerArray; import org.broadinstitute.sting.utils.collections.NestedHashMap; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.DynamicClassResolutionException; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java index e3ab16639..2f9a38972 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.report.GATKReportTable; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.collections.NestedIntegerArray; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.recalibration.covariates.Covariate; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java index a836fbb5e..546bd6ac8 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -51,9 +51,9 @@ import com.google.java.contract.Requires; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.recalibration.ReadCovariates; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; +import org.broadinstitute.sting.utils.collections.Pair; import java.util.Arrays; import java.util.HashMap; @@ -112,7 +112,7 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { // get backward repeat unit and # repeats byte[] backwardRepeatUnit = Arrays.copyOfRange(readBases, offset - str + 1, offset + 1); - maxBW = VariantContextUtils.findNumberofRepetitions(backwardRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); + maxBW = GATKVariantContextUtils.findNumberofRepetitions(backwardRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); if (maxBW > 1) { bestBWRepeatUnit = backwardRepeatUnit.clone(); break; @@ -132,7 +132,7 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { // get forward repeat unit and # repeats byte[] forwardRepeatUnit = Arrays.copyOfRange(readBases, offset +1, offset+str+1); - maxFW = VariantContextUtils.findNumberofRepetitions(forwardRepeatUnit,Arrays.copyOfRange(readBases, offset+1, readBases.length), true); + maxFW = GATKVariantContextUtils.findNumberofRepetitions(forwardRepeatUnit, Arrays.copyOfRange(readBases, offset + 1, readBases.length), true); if (maxFW > 1) { bestFWRepeatUnit = forwardRepeatUnit.clone(); break; @@ -150,7 +150,7 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { // but correct representation at that place might be (C)4. // Hence, if the FW and BW units don't match, check if BW unit can still be a part of FW unit and add // representations to total - maxBW = VariantContextUtils.findNumberofRepetitions(bestFWRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); + maxBW = GATKVariantContextUtils.findNumberofRepetitions(bestFWRepeatUnit, Arrays.copyOfRange(readBases, 0, offset + 1), false); maxRL = maxFW + maxBW; bestRepeatUnit = bestFWRepeatUnit; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java index 5822b9e05..c4fdaad8b 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitAndLengthCovariate.java @@ -48,18 +48,6 @@ package org.broadinstitute.sting.utils.recalibration.covariates; import com.google.java.contract.Ensures; import com.google.java.contract.Requires; -import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; -import org.broadinstitute.sting.utils.recalibration.ReadCovariates; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; -import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; public class RepeatUnitAndLengthCovariate extends RepeatCovariate { diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java index ed843310d..b32feb9a3 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java @@ -46,20 +46,6 @@ package org.broadinstitute.sting.utils.recalibration.covariates; -import com.google.java.contract.Ensures; -import com.google.java.contract.Requires; -import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; -import org.broadinstitute.sting.utils.recalibration.ReadCovariates; -import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - /** * Created with IntelliJ IDEA. * User: rpoplin diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java index 08d333f8b..14dedebc4 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidyGenotypeLikelihoodsUnitTest.java @@ -52,7 +52,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; import org.broadinstitute.variant.variantcontext.*; import org.testng.Assert; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java index 291489984..8deddc357 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/genotyper/afcalc/AFCalcPerformanceUnitTest.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper.afcalc; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.VariantContext; import org.testng.Assert; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java index f144f9b59..aabcd374d 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManagerUnitTest.java @@ -52,7 +52,7 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manage import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java index 300dd633d..9c0567464 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/ConcordanceMetricsUnitTest.java @@ -49,7 +49,7 @@ package org.broadinstitute.sting.gatk.walkers.variantutils; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.Allele; diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java index e4311a534..7ded176bb 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java @@ -46,21 +46,17 @@ package org.broadinstitute.sting.utils.recalibration; import com.google.java.contract.Requires; -import net.sf.samtools.SAMFileHeader; -import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.recalibration.covariates.*; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; -import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.utils.BaseUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; @@ -89,38 +85,38 @@ public class RepeatCovariatesUnitTest { @Test(enabled = true) public void testFindNumberOfRepetitions() { // First, test logic to compute number of repetitions of a substring on a given string. - int result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACAC".getBytes(), true); + int result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACAC".getBytes(), true); Assert.assertEquals(2,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACACACAC".getBytes(), true); Assert.assertEquals(4,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACACACACGT".getBytes(), true); Assert.assertEquals(4,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "GTACACACAC".getBytes(), true); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(), "GTAGGGT".getBytes(), true); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(), "GCAGCAGTAGGGTGTACACACAC".getBytes(), true); Assert.assertEquals(1,result); - result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(), "GTAGGGTGTACACACACGCAGCAT".getBytes(), true); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), true); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(), "GTAGGGTGTACACACACGCAGCAGCA".getBytes(), true); Assert.assertEquals(0,result); // Same tests but looking backward on string - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACAC".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACAC".getBytes(), false); Assert.assertEquals(2,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACAC".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACACACAC".getBytes(), false); Assert.assertEquals(4,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"ACACACACGT".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "ACACACACGT".getBytes(), false); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("AC".getBytes(),"GTACACACAC".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("AC".getBytes(), "GTACACACAC".getBytes(), false); Assert.assertEquals(4,result); - result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGT".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(), "GTAGGGT".getBytes(), false); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GCAGCAGTAGGGTGTACACACAC".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(), "GCAGCAGTAGGGTGTACACACAC".getBytes(), false); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(),"GTAGGGTGTACACACACGCAGCAT".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("GCAGCA".getBytes(), "GTAGGGTGTACACACACGCAGCAT".getBytes(), false); Assert.assertEquals(0,result); - result = VariantContextUtils.findNumberofRepetitions("GCA".getBytes(),"GTAGGGTGTACACACACGCAGCAGCA".getBytes(), false); + result = GATKVariantContextUtils.findNumberofRepetitions("GCA".getBytes(), "GTAGGGTGTACACACACGCAGCAGCA".getBytes(), false); Assert.assertEquals(3,result); // test logic to get repeat unit and number of repeats from covariate value @@ -208,8 +204,8 @@ public class RepeatCovariatesUnitTest { Assert.assertEquals(rurlValM,rurlValI); - int fw = VariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(offset+1,readLength).getBytes(),true); - int bw = VariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(0,offset+1).getBytes(),false); + int fw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(offset+1,readLength).getBytes(),true); + int bw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(0,offset+1).getBytes(),false); Assert.assertEquals(Math.min(fw+bw,RepeatCovariate.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); } diff --git a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java index 071bd2cad..5e863f4f7 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java +++ b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java @@ -31,7 +31,7 @@ import org.apache.log4j.Logger; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.JVMUtils; import org.broadinstitute.sting.utils.classloader.PluginManager; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.ApplicationDetails; diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java index b7c824360..e078e678b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/providers/RODMetaDataContainer.java @@ -26,7 +26,7 @@ package org.broadinstitute.sting.gatk.datasources.providers; import org.broadinstitute.sting.gatk.refdata.utils.GATKFeature; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java b/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java index ea83aab53..d0ba0fa21 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java +++ b/public/java/src/org/broadinstitute/sting/gatk/executive/Accumulator.java @@ -31,7 +31,7 @@ import org.broadinstitute.sting.gatk.datasources.providers.ShardDataProvider; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocSortedSet; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.ArrayList; diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java index a77341a5d..09f053187 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/VariantContextAdaptors.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.classloader.PluginManager; import org.broadinstitute.sting.utils.codecs.hapmap.RawHapMapFeature; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.*; import java.util.*; @@ -200,7 +201,7 @@ public class VariantContextAdaptors { if ( isSNP(dbsnp) || isMNP(dbsnp) ) addPaddingBase = false; else if ( isIndel(dbsnp) || dbsnp.getVariantType().contains("mixed") ) - addPaddingBase = refBaseIsDash || VariantContextUtils.requiresPaddingBase(stripNullDashes(getAlleleList(dbsnp))); + addPaddingBase = refBaseIsDash || GATKVariantContextUtils.requiresPaddingBase(stripNullDashes(getAlleleList(dbsnp))); else return null; // can't handle anything else diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java index ec51b2f53..c5f87d625 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/RMDTrackBuilder.java @@ -40,7 +40,7 @@ import org.broadinstitute.sting.gatk.arguments.ValidationExclusion; import org.broadinstitute.sting.gatk.refdata.utils.RMDTriplet; import org.broadinstitute.sting.gatk.refdata.utils.RMDTriplet.RMDStorageType; import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.file.FSLockWithShared; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java index 979cc2fbf..522414c00 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.gatk.samples.Sample; import org.broadinstitute.sting.gatk.samples.SampleDB; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.baq.BAQ; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.recalibration.BQSRMode; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java index 29f6ed388..c5a6fd624 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/annotator/VariantAnnotatorEngine.java @@ -33,6 +33,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.*; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; +import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.variant.variantcontext.*; @@ -249,7 +250,7 @@ public class VariantAnnotatorEngine { private VariantContext annotateDBs(final RefMetaDataTracker tracker, final GenomeLoc loc, VariantContext vc, final Map infoAnnotations) { for ( Map.Entry, String> dbSet : dbAnnotations.entrySet() ) { if ( dbSet.getValue().equals(VCFConstants.DBSNP_KEY) ) { - final String rsID = VCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbSet.getKey(), loc), vc.getType()); + final String rsID = GATKVCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbSet.getKey(), loc), vc.getType()); // add the ID if appropriate if ( rsID != null ) { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java index 383b22295..dbb8ed5a6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/DepthOfCoverage.java @@ -46,7 +46,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.codecs.refseq.RefSeqCodec; import org.broadinstitute.sting.utils.codecs.refseq.RefSeqFeature; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java index 77a4af1cd..668d3fd5f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/coverage/GCContentByInterval.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java index ac6d82375..8a5b3530e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaAlternateReferenceMaker.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.VariantContext; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java index d12ad3183..ed3ebe173 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/fasta/FastaReferenceMaker.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java index 82247d160..0423c6f0a 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountIntervals.java @@ -36,7 +36,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java index be1e264c6..a0f943f7e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODs.java @@ -43,7 +43,7 @@ import org.broadinstitute.sting.gatk.walkers.TreeReducible; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.collections.ExpandingArrayList; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.io.PrintStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java index 7135bffce..77490be93 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountRODsByRef.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RefWalker; import org.broadinstitute.sting.utils.collections.ExpandingArrayList; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import java.util.Collections; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java index 4e05033ec..cabc2f467 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/CountTerminusEvent.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.gatk.walkers.Requires; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java index 6b2c0f75c..fe2b75464 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java @@ -45,7 +45,7 @@ import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.clipping.ClippingOp; import org.broadinstitute.sting.utils.clipping.ClippingRepresentation; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java index 9f758706e..e24c725a6 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEval.java @@ -49,6 +49,7 @@ import org.broadinstitute.sting.gatk.walkers.varianteval.util.VariantEvalUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -197,7 +198,7 @@ public class VariantEval extends RodWalker implements TreeRedu protected double MENDELIAN_VIOLATION_QUAL_THRESHOLD = 50; @Argument(shortName="ploidy", fullName="samplePloidy", doc="Per-sample ploidy (number of chromosomes per sample)", required=false) - protected int ploidy = VariantContextUtils.DEFAULT_PLOIDY; + protected int ploidy = GATKVariantContextUtils.DEFAULT_PLOIDY; @Argument(fullName="ancestralAlignments", shortName="aa", doc="Fasta file with ancestral alleles", required=false) private File ancestralAlignmentsFile = null; @@ -285,7 +286,7 @@ public class VariantEval extends RodWalker implements TreeRedu // Now that we have all the rods categorized, determine the sample list from the eval rods. Map vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), evals); - Set vcfSamples = SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); + Set vcfSamples = SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE); // Load the sample list, using an intermediate tree set to sort the samples final Set allSampleNames = SampleUtils.getSamplesFromCommandLineInput(vcfSamples); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java index 5c16c7385..a63f32485 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalReportWriter.java @@ -34,7 +34,7 @@ import org.broadinstitute.sting.gatk.walkers.varianteval.util.Analysis; import org.broadinstitute.sting.gatk.walkers.varianteval.util.AnalysisModuleScanner; import org.broadinstitute.sting.gatk.walkers.varianteval.util.DataPoint; import org.broadinstitute.sting.gatk.walkers.varianteval.util.EvaluationContext; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java index 5ef414b00..de82b18cc 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/TandemRepeat.java @@ -27,8 +27,8 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.variantcontext.VariantContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.Arrays; import java.util.List; @@ -51,7 +51,7 @@ public class TandemRepeat extends VariantStratifier { public List getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) { if ( eval == null || ! eval.isIndel() ) return ALL; - else if ( VariantContextUtils.isTandemRepeat(eval, ref.getForwardBases()) ) { + else if ( GATKVariantContextUtils.isTandemRepeat(eval, ref.getForwardBases()) ) { print("REPEAT", eval, ref); return REPEAT; } else { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java index d792e4c67..681d32f2d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/manager/StratificationManager.java @@ -28,7 +28,7 @@ package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manage import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java index c54a57385..d0d6a68a8 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java @@ -38,6 +38,7 @@ import org.broadinstitute.sting.gatk.walkers.Window; import org.broadinstitute.sting.gatk.walkers.annotator.ChromosomeCountConstants; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -135,14 +136,14 @@ public class CombineVariants extends RodWalker implements Tree protected VariantContextWriter vcfWriter = null; @Argument(shortName="genotypeMergeOptions", doc="Determines how we should merge genotype records for samples shared across the ROD files", required=false) - public VariantContextUtils.GenotypeMergeType genotypeMergeOption = null; + public GATKVariantContextUtils.GenotypeMergeType genotypeMergeOption = null; @Argument(shortName="filteredRecordsMergeType", doc="Determines how we should handle records seen at the same site in the VCF, but with different FILTER fields", required=false) - public VariantContextUtils.FilteredRecordMergeType filteredRecordsMergeType = VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED; + public GATKVariantContextUtils.FilteredRecordMergeType filteredRecordsMergeType = GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED; @Hidden @Argument(shortName="multipleAllelesMergeType", doc="Determines how we should handle records seen at the same site in the VCF, but with different allele types (for example, SNP vs. indel)", required=false) - public VariantContextUtils.MultipleAllelesMergeType multipleAllelesMergeType = VariantContextUtils.MultipleAllelesMergeType.BY_TYPE; + public GATKVariantContextUtils.MultipleAllelesMergeType multipleAllelesMergeType = GATKVariantContextUtils.MultipleAllelesMergeType.BY_TYPE; /** * Used when taking the union of variants that contain genotypes. A complete priority list MUST be provided. @@ -203,12 +204,12 @@ public class CombineVariants extends RodWalker implements Tree validateAnnotateUnionArguments(); if ( PRIORITY_STRING == null && genotypeMergeOption == null) { - genotypeMergeOption = VariantContextUtils.GenotypeMergeType.UNSORTED; + genotypeMergeOption = GATKVariantContextUtils.GenotypeMergeType.UNSORTED; //PRIORITY_STRING = Utils.join(",", vcfRods.keySet()); Deleted by Ami (7/10/12) logger.info("Priority string is not provided, using arbitrary genotyping order: "+priority); } - if (genotypeMergeOption == VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE && + if (genotypeMergeOption == GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE && !SampleUtils.verifyUniqueSamplesNames(vcfRods)) throw new IllegalStateException("REQUIRE_UNIQUE sample names is true but duplicate names were discovered."); @@ -232,7 +233,7 @@ public class CombineVariants extends RodWalker implements Tree private void validateAnnotateUnionArguments() { Set rodNames = SampleUtils.getRodNamesWithVCFHeader(getToolkit(), null); - if ( genotypeMergeOption == VariantContextUtils.GenotypeMergeType.PRIORITIZE && PRIORITY_STRING == null ) + if ( genotypeMergeOption == GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE && PRIORITY_STRING == null ) throw new UserException.MissingArgument("rod_priority_list", "Priority string must be provided if you want to prioritize genotypes"); if ( PRIORITY_STRING != null){ @@ -278,7 +279,7 @@ public class CombineVariants extends RodWalker implements Tree List mergedVCs = new ArrayList(); - if (multipleAllelesMergeType == VariantContextUtils.MultipleAllelesMergeType.BY_TYPE) { + if (multipleAllelesMergeType == GATKVariantContextUtils.MultipleAllelesMergeType.BY_TYPE) { Map> VCsByType = VariantContextUtils.separateVariantContextsByType(vcs); // TODO -- clean this up in a refactoring @@ -296,13 +297,13 @@ public class CombineVariants extends RodWalker implements Tree // iterate over the types so that it's deterministic for (VariantContext.Type type : VariantContext.Type.values()) { if (VCsByType.containsKey(type)) - mergedVCs.add(VariantContextUtils.simpleMerge(VCsByType.get(type), - priority, rodNames.size() , filteredRecordsMergeType, genotypeMergeOption, true, printComplexMerges, + mergedVCs.add(GATKVariantContextUtils.simpleMerge(VCsByType.get(type), + priority, rodNames.size(), filteredRecordsMergeType, genotypeMergeOption, true, printComplexMerges, SET_KEY, filteredAreUncalled, MERGE_INFO_WITH_MAX_AC)); } } - else if (multipleAllelesMergeType == VariantContextUtils.MultipleAllelesMergeType.MIX_TYPES) { - mergedVCs.add(VariantContextUtils.simpleMerge(vcs, + else if (multipleAllelesMergeType == GATKVariantContextUtils.MultipleAllelesMergeType.MIX_TYPES) { + mergedVCs.add(GATKVariantContextUtils.simpleMerge(vcs, priority, rodNames.size(), filteredRecordsMergeType, genotypeMergeOption, true, printComplexMerges, SET_KEY, filteredAreUncalled, MERGE_INFO_WITH_MAX_AC)); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 8d5e7c2b8..048c7ef77 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -32,7 +32,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.report.GATKReport; import org.broadinstitute.sting.gatk.report.GATKReportTable; import org.broadinstitute.sting.gatk.walkers.RodWalker; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.vcf.VCFHeader; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java index e94a771d3..e4d182d13 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java @@ -39,12 +39,12 @@ import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.interval.IntervalMergingRule; import org.broadinstitute.sting.utils.interval.IntervalSetRule; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.broadinstitute.sting.utils.text.ListFileUtils; import org.broadinstitute.variant.variantcontext.VariantContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.io.File; import java.util.*; @@ -204,7 +204,7 @@ public class SelectHeaders extends RodWalker implements TreeRe } } - TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); + TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); VCFHeader vcfHeader = new VCFHeader(headerLines, vcfSamples); vcfHeader.setWriteEngineHeaders(includeEngineHeaders); vcfWriter.writeHeader(vcfHeader); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java index dfe604a7d..4d30408d8 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java @@ -39,6 +39,7 @@ import org.broadinstitute.sting.utils.MendelianViolation; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -337,7 +338,7 @@ public class SelectVariants extends RodWalker implements TreeR List rodNames = Arrays.asList(variantCollection.variants.getName()); vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), rodNames); - TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); + TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); Collection samplesFromFile = SampleUtils.getSamplesFromFiles(sampleFiles); Collection samplesFromExpressions = SampleUtils.matchSamplesExpressions(vcfSamples, sampleExpressions); @@ -661,7 +662,7 @@ public class SelectVariants extends RodWalker implements TreeR // if we have fewer alternate alleles in the selected VC than in the original VC, we need to strip out the GL/PLs and AD (because they are no longer accurate) if ( vc.getAlleles().size() != sub.getAlleles().size() ) - newGC = VariantContextUtils.stripPLsAndAD(sub.getGenotypes()); + newGC = GATKVariantContextUtils.stripPLsAndAD(sub.getGenotypes()); // if we have fewer samples in the selected VC than in the original VC, we need to strip out the MLE tags if ( vc.getNSamples() != sub.getNSamples() ) { diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java index 17d5ab1b1..5bf5b96e3 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java @@ -35,13 +35,13 @@ import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.*; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextBuilder; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.util.*; @@ -256,7 +256,7 @@ public class VariantValidationAssessor extends RodWalker //if ( popFile != null ) { // throw new StingException("We still need to implement this!"); //} else { - return VariantContextUtils.computeHardyWeinbergPvalue(vc); + return GATKVariantContextUtils.computeHardyWeinbergPvalue(vc); //} } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java index 91057c812..1ea85df47 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java @@ -29,6 +29,7 @@ import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; @@ -180,7 +181,7 @@ public class VariantsToTable extends RodWalker { if ( !genotypeFieldsToTake.isEmpty() ) { Map vcfRods = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), variants); - TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, VariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); + TreeSet vcfSamples = new TreeSet(SampleUtils.getSampleList(vcfRods, GATKVariantContextUtils.GenotypeMergeType.REQUIRE_UNIQUE)); samples.addAll(vcfSamples); // optimization: if there are no samples, we don't have to worry about any genotype fields diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java index 61746cbf1..5afeccffe 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java @@ -119,7 +119,7 @@ public class VariantsToVCF extends RodWalker { if ( tracker == null || !BaseUtils.isRegularBase(ref.getBase()) ) return 0; - String rsID = dbsnp == null ? null : VCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbsnp.dbsnp, context.getLocation()), VariantContext.Type.SNP); + String rsID = dbsnp == null ? null : GATKVCFUtils.rsIDOfFirstRealVariant(tracker.getValues(dbsnp.dbsnp, context.getLocation()), VariantContext.Type.SNP); Collection contexts = getVariantContexts(tracker, ref); diff --git a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java index 93246fd6f..10fb606f9 100644 --- a/public/java/src/org/broadinstitute/sting/tools/CatVariants.java +++ b/public/java/src/org/broadinstitute/sting/tools/CatVariants.java @@ -36,7 +36,7 @@ import org.broadinstitute.sting.commandline.Input; import org.broadinstitute.sting.commandline.Output; import org.broadinstitute.sting.commandline.CommandLineProgram; import org.broadinstitute.variant.bcf2.BCF2Codec; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.vcf.VCFCodec; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java b/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java index 05468c6c2..74009682a 100644 --- a/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java +++ b/public/java/src/org/broadinstitute/sting/utils/MannWhitneyU.java @@ -33,7 +33,7 @@ import org.apache.commons.math.MathException; import org.apache.commons.math.distribution.NormalDistribution; import org.apache.commons.math.distribution.NormalDistributionImpl; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.StingException; import java.io.Serializable; diff --git a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java index b316d1117..e2edf7421 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java +++ b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java @@ -28,7 +28,7 @@ package org.broadinstitute.sting.utils; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.StingException; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java index f158308b4..b1de89dd8 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/SampleUtils.java @@ -29,11 +29,11 @@ import net.sf.samtools.SAMFileHeader; import net.sf.samtools.SAMReadGroupRecord; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.sting.utils.text.ListFileUtils; import org.broadinstitute.sting.utils.text.XReadLines; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.io.File; import java.io.FileNotFoundException; @@ -117,15 +117,15 @@ public class SampleUtils { } public static Set getSampleList(Map headers) { - return getSampleList(headers, VariantContextUtils.GenotypeMergeType.PRIORITIZE); + return getSampleList(headers, GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE); } - public static Set getSampleList(Map headers, VariantContextUtils.GenotypeMergeType mergeOption) { + public static Set getSampleList(Map headers, GATKVariantContextUtils.GenotypeMergeType mergeOption) { Set samples = new TreeSet(); for ( Map.Entry val : headers.entrySet() ) { VCFHeader header = val.getValue(); for ( String sample : header.getGenotypeSamples() ) { - samples.add(VariantContextUtils.mergedSampleName(val.getKey(), sample, mergeOption == VariantContextUtils.GenotypeMergeType.UNIQUIFY)); + samples.add(GATKVariantContextUtils.mergedSampleName(val.getKey(), sample, mergeOption == GATKVariantContextUtils.GenotypeMergeType.UNIQUIFY)); } } diff --git a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java index 794caa315..8c7bce6ac 100644 --- a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java +++ b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java @@ -32,7 +32,7 @@ import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import net.sf.samtools.SAMUtils; import org.apache.log4j.Logger; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.sam.ReadUtils; diff --git a/public/java/src/org/broadinstitute/variant/utils/Pair.java b/public/java/src/org/broadinstitute/sting/utils/collections/Pair.java similarity index 98% rename from public/java/src/org/broadinstitute/variant/utils/Pair.java rename to public/java/src/org/broadinstitute/sting/utils/collections/Pair.java index 858d5fbd7..4c00331a9 100644 --- a/public/java/src/org/broadinstitute/variant/utils/Pair.java +++ b/public/java/src/org/broadinstitute/sting/utils/collections/Pair.java @@ -23,7 +23,7 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.utils; +package org.broadinstitute.sting.utils.collections; public class Pair { diff --git a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java index 1072fb1b7..39f5b06c6 100644 --- a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java @@ -29,7 +29,7 @@ import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.QualityUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java index 00dd037db..76ccede62 100644 --- a/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/fragments/FragmentUtils.java @@ -30,7 +30,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.utils.recalibration.EventType; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java index 099554a2c..bb0dc670b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java @@ -37,7 +37,7 @@ import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.refdata.tracks.FeatureManager; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.JVMUtils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; diff --git a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java index 403e166c5..7374dda14 100644 --- a/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/interval/IntervalUtils.java @@ -39,7 +39,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.GenomeLocSortedSet; import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.text.XReadLines; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index 46eceefd5..29f8c8dcd 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -32,7 +32,7 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.NGSPlatform; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.variant.utils.BaseUtils; diff --git a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java index b2069c7ee..cbc7c01ed 100644 --- a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVCFUtils.java @@ -31,7 +31,7 @@ import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.sting.commandline.RodBinding; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.datasources.rmd.ReferenceOrderedDataSource; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.vcf.*; @@ -147,4 +147,49 @@ public class GATKVCFUtils { return VCFUtils.withUpdatedContigs(header, engine.getArguments().referenceFile, engine.getMasterSequenceDictionary()); } + public static String rsIDOfFirstRealVariant(List VCs, VariantContext.Type type) { + if ( VCs == null ) + return null; + + String rsID = null; + for ( VariantContext vc : VCs ) { + if ( vc.getType() == type ) { + rsID = vc.getID(); + break; + } + } + + return rsID; + } + + /** + * Read all of the VCF records from source into memory, returning the header and the VariantContexts + * + * SHOULD ONLY BE USED FOR UNIT/INTEGRATION TESTING PURPOSES! + * + * @param source the file to read, must be in VCF4 format + * @return + * @throws java.io.IOException + */ + public static Pair> readVCF(final File source) throws IOException { + // read in the features + final List vcs = new ArrayList(); + final VCFCodec codec = new VCFCodec(); + PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); + FeatureCodecHeader header = codec.readHeader(pbs); + pbs.close(); + + pbs = new PositionalBufferedStream(new FileInputStream(source)); + pbs.skip(header.getHeaderEnd()); + + final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue(); + + while ( ! pbs.isDone() ) { + final VariantContext vc = codec.decode(pbs); + if ( vc != null ) + vcs.add(vc); + } + + return new Pair>(vcfHeader, vcs); + } } \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java index 82241ad55..2ae289214 100644 --- a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java @@ -25,12 +25,79 @@ package org.broadinstitute.sting.utils.variant; +import com.google.java.contract.Requires; +import org.apache.commons.lang.ArrayUtils; +import org.apache.log4j.Logger; +import org.broad.tribble.TribbleException; +import org.broad.tribble.util.popgen.HardyWeinbergCalculation; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.MathUtils; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.*; +import org.broadinstitute.variant.vcf.VCFConstants; + +import java.io.Serializable; +import java.util.*; public class GATKVariantContextUtils { + private static Logger logger = Logger.getLogger(GATKVariantContextUtils.class); + + public static final int DEFAULT_PLOIDY = 2; + public static final double SUM_GL_THRESH_NOCALL = -0.1; // if sum(gl) is bigger than this threshold, we treat GL's as non-informative and will force a no-call. + private static final List NO_CALL_ALLELES = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL); + public final static String MERGE_FILTER_PREFIX = "filterIn"; + public final static String MERGE_REF_IN_ALL = "ReferenceInAll"; + public final static String MERGE_FILTER_IN_ALL = "FilteredInAll"; + public final static String MERGE_INTERSECTION = "Intersection"; + + public enum GenotypeMergeType { + /** + * Make all sample genotypes unique by file. Each sample shared across RODs gets named sample.ROD. + */ + UNIQUIFY, + /** + * Take genotypes in priority order (see the priority argument). + */ + PRIORITIZE, + /** + * Take the genotypes in any order. + */ + UNSORTED, + /** + * Require that all samples/genotypes be unique between all inputs. + */ + REQUIRE_UNIQUE + } + + public enum FilteredRecordMergeType { + /** + * Union - leaves the record if any record is unfiltered. + */ + KEEP_IF_ANY_UNFILTERED, + /** + * Requires all records present at site to be unfiltered. VCF files that don't contain the record don't influence this. + */ + KEEP_IF_ALL_UNFILTERED, + /** + * If any record is present at this site (regardless of possibly being filtered), then all such records are kept and the filters are reset. + */ + KEEP_UNCONDITIONAL + } + + public enum MultipleAllelesMergeType { + /** + * Combine only alleles of the same type (SNP, indel, etc.) into a single VCF record. + */ + BY_TYPE, + /** + * Merge all allele types at the same start position into the same VCF record. + */ + MIX_TYPES + } + /** * create a genome location, given a variant context * @param genomeLocParser parser @@ -41,4 +108,885 @@ public class GATKVariantContextUtils { return genomeLocParser.createGenomeLoc(vc.getChr(), vc.getStart(), vc.getEnd(), true); } + /** + * Returns true iff VC is an non-complex indel where every allele represents an expansion or + * contraction of a series of identical bases in the reference. + * + * For example, suppose the ref bases are CTCTCTGA, which includes a 3x repeat of CTCTCT + * + * If VC = -/CT, then this function returns true because the CT insertion matches exactly the + * upcoming reference. + * If VC = -/CTA then this function returns false because the CTA isn't a perfect match + * + * Now consider deletions: + * + * If VC = CT/- then again the same logic applies and this returns true + * The case of CTA/- makes no sense because it doesn't actually match the reference bases. + * + * The logic of this function is pretty simple. Take all of the non-null alleles in VC. For + * each insertion allele of n bases, check if that allele matches the next n reference bases. + * For each deletion allele of n bases, check if this matches the reference bases at n - 2 n, + * as it must necessarily match the first n bases. If this test returns true for all + * alleles you are a tandem repeat, otherwise you are not. + * + * @param vc + * @param refBasesStartingAtVCWithPad not this is assumed to include the PADDED reference + * @return + */ + @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) + public static boolean isTandemRepeat(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { + final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); + if ( ! vc.isIndel() ) // only indels are tandem repeats + return false; + + final Allele ref = vc.getReference(); + + for ( final Allele allele : vc.getAlternateAlleles() ) { + if ( ! isRepeatAllele(ref, allele, refBasesStartingAtVCWithoutPad) ) + return false; + } + + // we've passed all of the tests, so we are a repeat + return true; + } + + /** + * + * @param vc + * @param refBasesStartingAtVCWithPad + * @return + */ + @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) + public static Pair,byte[]> getNumTandemRepeatUnits(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { + final boolean VERBOSE = false; + final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); + if ( ! vc.isIndel() ) // only indels are tandem repeats + return null; + + final Allele refAllele = vc.getReference(); + final byte[] refAlleleBases = Arrays.copyOfRange(refAllele.getBases(), 1, refAllele.length()); + + byte[] repeatUnit = null; + final ArrayList lengths = new ArrayList(); + + for ( final Allele allele : vc.getAlternateAlleles() ) { + Pair result = getNumTandemRepeatUnits(refAlleleBases, Arrays.copyOfRange(allele.getBases(), 1, allele.length()), refBasesStartingAtVCWithoutPad.getBytes()); + + final int[] repetitionCount = result.first; + // repetition count = 0 means allele is not a tandem expansion of context + if (repetitionCount[0] == 0 || repetitionCount[1] == 0) + return null; + + if (lengths.size() == 0) { + lengths.add(repetitionCount[0]); // add ref allele length only once + } + lengths.add(repetitionCount[1]); // add this alt allele's length + + repeatUnit = result.second; + if (VERBOSE) { + System.out.println("RefContext:"+refBasesStartingAtVCWithoutPad); + System.out.println("Ref:"+refAllele.toString()+" Count:" + String.valueOf(repetitionCount[0])); + System.out.println("Allele:"+allele.toString()+" Count:" + String.valueOf(repetitionCount[1])); + System.out.println("RU:"+new String(repeatUnit)); + } + } + + return new Pair, byte[]>(lengths,repeatUnit); + } + + public static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { + /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units. + Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)2. + */ + + byte[] longB; + // find first repeat unit based on either ref or alt, whichever is longer + if (altBases.length > refBases.length) + longB = altBases; + else + longB = refBases; + + // see if non-null allele (either ref or alt, whichever is longer) can be decomposed into several identical tandem units + // for example, -*,CACA needs to first be decomposed into (CA)2 + final int repeatUnitLength = findRepeatedSubstring(longB); + final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength); + + final int[] repetitionCount = new int[2]; + // look for repetitions forward on the ref bases (i.e. starting at beginning of ref bases) + int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases, true); + repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext), true)-repetitionsInRef; + repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext), true)-repetitionsInRef; + + return new Pair(repetitionCount, repeatUnit); + + } + + /** + * Find out if a string can be represented as a tandem number of substrings. + * For example ACTACT is a 2-tandem of ACT, + * but ACTACA is not. + * + * @param bases String to be tested + * @return Length of repeat unit, if string can be represented as tandem of substring (if it can't + * be represented as one, it will be just the length of the input string) + */ + public static int findRepeatedSubstring(byte[] bases) { + + int repLength; + for (repLength=1; repLength <=bases.length; repLength++) { + final byte[] candidateRepeatUnit = Arrays.copyOf(bases,repLength); + boolean allBasesMatch = true; + for (int start = repLength; start < bases.length; start += repLength ) { + // check that remaining of string is exactly equal to repeat unit + final byte[] basePiece = Arrays.copyOfRange(bases,start,start+candidateRepeatUnit.length); + if (!Arrays.equals(candidateRepeatUnit, basePiece)) { + allBasesMatch = false; + break; + } + } + if (allBasesMatch) + return repLength; + } + + return repLength; + } + + /** + * Helper routine that finds number of repetitions a string consists of. + * For example, for string ATAT and repeat unit AT, number of repetitions = 2 + * @param repeatUnit Substring + * @param testString String to test + * @oaram lookForward Look for repetitions forward (at beginning of string) or backward (at end of string) + * @return Number of repetitions (0 if testString is not a concatenation of n repeatUnit's + */ + public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString, boolean lookForward) { + int numRepeats = 0; + if (lookForward) { + // look forward on the test string + for (int start = 0; start < testString.length; start += repeatUnit.length) { + int end = start + repeatUnit.length; + byte[] unit = Arrays.copyOfRange(testString,start, end); + if(Arrays.equals(unit,repeatUnit)) + numRepeats++; + else + break; + } + return numRepeats; + } + + // look backward. For example, if repeatUnit = AT and testString = GATAT, number of repeat units is still 2 + // look forward on the test string + for (int start = testString.length - repeatUnit.length; start >= 0; start -= repeatUnit.length) { + int end = start + repeatUnit.length; + byte[] unit = Arrays.copyOfRange(testString,start, end); + if(Arrays.equals(unit,repeatUnit)) + numRepeats++; + else + break; + } + return numRepeats; + } + + /** + * Helper function for isTandemRepeat that checks that allele matches somewhere on the reference + * @param ref + * @param alt + * @param refBasesStartingAtVCWithoutPad + * @return + */ + protected static boolean isRepeatAllele(final Allele ref, final Allele alt, final String refBasesStartingAtVCWithoutPad) { + if ( ! Allele.oneIsPrefixOfOther(ref, alt) ) + return false; // we require one allele be a prefix of another + + if ( ref.length() > alt.length() ) { // we are a deletion + return basesAreRepeated(ref.getBaseString(), alt.getBaseString(), refBasesStartingAtVCWithoutPad, 2); + } else { // we are an insertion + return basesAreRepeated(alt.getBaseString(), ref.getBaseString(), refBasesStartingAtVCWithoutPad, 1); + } + } + + protected static boolean basesAreRepeated(final String l, final String s, final String ref, final int minNumberOfMatches) { + final String potentialRepeat = l.substring(s.length()); // skip s bases + + for ( int i = 0; i < minNumberOfMatches; i++) { + final int start = i * potentialRepeat.length(); + final int end = (i+1) * potentialRepeat.length(); + if ( ref.length() < end ) + return false; // we ran out of bases to test + final String refSub = ref.substring(start, end); + if ( ! refSub.equals(potentialRepeat) ) + return false; // repeat didn't match, fail + } + + return true; // we passed all tests, we matched + } + + /** + * subset the Variant Context to the specific set of alleles passed in (pruning the PLs appropriately) + * + * @param vc variant context with genotype likelihoods + * @param allelesToUse which alleles from the vc are okay to use; *** must be in the same relative order as those in the original VC *** + * @param assignGenotypes true if we should update the genotypes based on the (subsetted) PLs + * @return genotypes + */ + public static GenotypesContext subsetDiploidAlleles(final VariantContext vc, + final List allelesToUse, + final boolean assignGenotypes) { + + // the genotypes with PLs + final GenotypesContext oldGTs = vc.getGenotypes(); + + // samples + final List sampleIndices = oldGTs.getSampleNamesOrderedByName(); + + // the new genotypes to create + final GenotypesContext newGTs = GenotypesContext.create(); + + // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward + final int numOriginalAltAlleles = vc.getAlternateAlleles().size(); + final int numNewAltAlleles = allelesToUse.size() - 1; + + // which PLs should be carried forward? + ArrayList likelihoodIndexesToUse = null; + + // an optimization: if we are supposed to use all (or none in the case of a ref call) of the alleles, + // then we can keep the PLs as is; otherwise, we determine which ones to keep + if ( numNewAltAlleles != numOriginalAltAlleles && numNewAltAlleles > 0 ) { + likelihoodIndexesToUse = new ArrayList(30); + + final boolean[] altAlleleIndexToUse = new boolean[numOriginalAltAlleles]; + for ( int i = 0; i < numOriginalAltAlleles; i++ ) { + if ( allelesToUse.contains(vc.getAlternateAllele(i)) ) + altAlleleIndexToUse[i] = true; + } + + // numLikelihoods takes total # of alleles. Use default # of chromosomes (ploidy) = 2 + final int numLikelihoods = GenotypeLikelihoods.numLikelihoods(1 + numOriginalAltAlleles, DEFAULT_PLOIDY); + for ( int PLindex = 0; PLindex < numLikelihoods; PLindex++ ) { + final GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); + // consider this entry only if both of the alleles are good + if ( (alleles.alleleIndex1 == 0 || altAlleleIndexToUse[alleles.alleleIndex1 - 1]) && (alleles.alleleIndex2 == 0 || altAlleleIndexToUse[alleles.alleleIndex2 - 1]) ) + likelihoodIndexesToUse.add(PLindex); + } + } + + // create the new genotypes + for ( int k = 0; k < oldGTs.size(); k++ ) { + final Genotype g = oldGTs.get(sampleIndices.get(k)); + if ( !g.hasLikelihoods() ) { + newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); + continue; + } + + // create the new likelihoods array from the alleles we are allowed to use + final double[] originalLikelihoods = g.getLikelihoods().getAsVector(); + double[] newLikelihoods; + if ( likelihoodIndexesToUse == null ) { + newLikelihoods = originalLikelihoods; + } else { + newLikelihoods = new double[likelihoodIndexesToUse.size()]; + int newIndex = 0; + for ( int oldIndex : likelihoodIndexesToUse ) + newLikelihoods[newIndex++] = originalLikelihoods[oldIndex]; + + // might need to re-normalize + newLikelihoods = MathUtils.normalizeFromLog10(newLikelihoods, false, true); + } + + // if there is no mass on the (new) likelihoods, then just no-call the sample + if ( MathUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { + newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); + } + else { + final GenotypeBuilder gb = new GenotypeBuilder(g); + + if ( numNewAltAlleles == 0 ) + gb.noPL(); + else + gb.PL(newLikelihoods); + + // if we weren't asked to assign a genotype, then just no-call the sample + if ( !assignGenotypes || MathUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { + gb.alleles(NO_CALL_ALLELES); + } + else { + // find the genotype with maximum likelihoods + int PLindex = numNewAltAlleles == 0 ? 0 : MathUtils.maxElementIndex(newLikelihoods); + GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); + + gb.alleles(Arrays.asList(allelesToUse.get(alleles.alleleIndex1), allelesToUse.get(alleles.alleleIndex2))); + if ( numNewAltAlleles != 0 ) gb.log10PError(GenotypeLikelihoods.getGQLog10FromLikelihoods(PLindex, newLikelihoods)); + } + newGTs.add(gb.make()); + } + } + + return newGTs; + } + + /** + * Assign genotypes (GTs) to the samples in the Variant Context greedily based on the PLs + * + * @param vc variant context with genotype likelihoods + * @return genotypes context + */ + public static GenotypesContext assignDiploidGenotypes(final VariantContext vc) { + return subsetDiploidAlleles(vc, vc.getAlleles(), true); + } + + /** + * Split variant context into its biallelic components if there are more than 2 alleles + * + * For VC has A/B/C alleles, returns A/B and A/C contexts. + * Genotypes are all no-calls now (it's not possible to fix them easily) + * Alleles are right trimmed to satisfy VCF conventions + * + * If vc is biallelic or non-variant it is just returned + * + * Chromosome counts are updated (but they are by definition 0) + * + * @param vc a potentially multi-allelic variant context + * @return a list of bi-allelic (or monomorphic) variant context + */ + public static List splitVariantContextToBiallelics(final VariantContext vc) { + if ( ! vc.isVariant() || vc.isBiallelic() ) + // non variant or biallelics already satisfy the contract + return Collections.singletonList(vc); + else { + final List biallelics = new LinkedList(); + + for ( final Allele alt : vc.getAlternateAlleles() ) { + VariantContextBuilder builder = new VariantContextBuilder(vc); + final List alleles = Arrays.asList(vc.getReference(), alt); + builder.alleles(alleles); + builder.genotypes(subsetDiploidAlleles(vc, alleles, false)); + VariantContextUtils.calculateChromosomeCounts(builder, true); + biallelics.add(reverseTrimAlleles(builder.make())); + } + + return biallelics; + } + } + + public static Genotype removePLsAndAD(final Genotype g) { + return ( g.hasLikelihoods() || g.hasAD() ) ? new GenotypeBuilder(g).noPL().noAD().make() : g; + } + + /** + * Merges VariantContexts into a single hybrid. Takes genotypes for common samples in priority order, if provided. + * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with + * the sample name + * + * @param unsortedVCs collection of unsorted VCs + * @param priorityListOfVCs priority list detailing the order in which we should grab the VCs + * @param filteredRecordMergeType merge type for filtered records + * @param genotypeMergeOptions merge option for genotypes + * @param annotateOrigin should we annotate the set it came from? + * @param printMessages should we print messages? + * @param setKey the key name of the set + * @param filteredAreUncalled are filtered records uncalled? + * @param mergeInfoWithMaxAC should we merge in info from the VC with maximum allele count? + * @return new VariantContext representing the merge of unsortedVCs + */ + public static VariantContext simpleMerge(final Collection unsortedVCs, + final List priorityListOfVCs, + final FilteredRecordMergeType filteredRecordMergeType, + final GenotypeMergeType genotypeMergeOptions, + final boolean annotateOrigin, + final boolean printMessages, + final String setKey, + final boolean filteredAreUncalled, + final boolean mergeInfoWithMaxAC ) { + int originalNumOfVCs = priorityListOfVCs == null ? 0 : priorityListOfVCs.size(); + return simpleMerge(unsortedVCs,priorityListOfVCs,originalNumOfVCs,filteredRecordMergeType,genotypeMergeOptions,annotateOrigin,printMessages,setKey,filteredAreUncalled,mergeInfoWithMaxAC); + } + + /** + * Merges VariantContexts into a single hybrid. Takes genotypes for common samples in priority order, if provided. + * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with + * the sample name. + * simpleMerge does not verify any more unique sample names EVEN if genotypeMergeOptions == GenotypeMergeType.REQUIRE_UNIQUE. One should use + * SampleUtils.verifyUniqueSamplesNames to check that before using sempleMerge. + * + * @param unsortedVCs collection of unsorted VCs + * @param priorityListOfVCs priority list detailing the order in which we should grab the VCs + * @param filteredRecordMergeType merge type for filtered records + * @param genotypeMergeOptions merge option for genotypes + * @param annotateOrigin should we annotate the set it came from? + * @param printMessages should we print messages? + * @param setKey the key name of the set + * @param filteredAreUncalled are filtered records uncalled? + * @param mergeInfoWithMaxAC should we merge in info from the VC with maximum allele count? + * @return new VariantContext representing the merge of unsortedVCs + */ + public static VariantContext simpleMerge(final Collection unsortedVCs, + final List priorityListOfVCs, + final int originalNumOfVCs, + final FilteredRecordMergeType filteredRecordMergeType, + final GenotypeMergeType genotypeMergeOptions, + final boolean annotateOrigin, + final boolean printMessages, + final String setKey, + final boolean filteredAreUncalled, + final boolean mergeInfoWithMaxAC ) { + + if ( unsortedVCs == null || unsortedVCs.size() == 0 ) + return null; + + if (priorityListOfVCs != null && originalNumOfVCs != priorityListOfVCs.size()) + throw new IllegalArgumentException("the number of the original VariantContexts must be the same as the number of VariantContexts in the priority list"); + + if ( annotateOrigin && priorityListOfVCs == null && originalNumOfVCs == 0) + throw new IllegalArgumentException("Cannot merge calls and annotate their origins without a complete priority list of VariantContexts or the number of original VariantContexts"); + + final List preFilteredVCs = sortVariantContextsByPriority(unsortedVCs, priorityListOfVCs, genotypeMergeOptions); + // Make sure all variant contexts are padded with reference base in case of indels if necessary + final List VCs = new ArrayList(); + + for (final VariantContext vc : preFilteredVCs) { + if ( ! filteredAreUncalled || vc.isNotFiltered() ) + VCs.add(vc); + } + if ( VCs.size() == 0 ) // everything is filtered out and we're filteredAreUncalled + return null; + + // establish the baseline info from the first VC + final VariantContext first = VCs.get(0); + final String name = first.getSource(); + final Allele refAllele = determineReferenceAllele(VCs); + + final Set alleles = new LinkedHashSet(); + final Set filters = new HashSet(); + final Map attributes = new LinkedHashMap(); + final Set inconsistentAttributes = new HashSet(); + final Set variantSources = new HashSet(); // contains the set of sources we found in our set of VCs that are variant + final Set rsIDs = new LinkedHashSet(1); // most of the time there's one id + + VariantContext longestVC = first; + int depth = 0; + int maxAC = -1; + final Map attributesWithMaxAC = new LinkedHashMap(); + double log10PError = CommonInfo.NO_LOG10_PERROR; + VariantContext vcWithMaxAC = null; + GenotypesContext genotypes = GenotypesContext.create(); + + // counting the number of filtered and variant VCs + int nFiltered = 0; + + boolean remapped = false; + + // cycle through and add info from the other VCs, making sure the loc/reference matches + + for ( final VariantContext vc : VCs ) { + if ( longestVC.getStart() != vc.getStart() ) + throw new IllegalStateException("BUG: attempting to merge VariantContexts with different start sites: first="+ first.toString() + " second=" + vc.toString()); + + if ( VariantContextUtils.getSize(vc) > VariantContextUtils.getSize(longestVC) ) + longestVC = vc; // get the longest location + + nFiltered += vc.isFiltered() ? 1 : 0; + if ( vc.isVariant() ) variantSources.add(vc.getSource()); + + AlleleMapper alleleMapping = resolveIncompatibleAlleles(refAllele, vc, alleles); + remapped = remapped || alleleMapping.needsRemapping(); + + alleles.addAll(alleleMapping.values()); + + mergeGenotypes(genotypes, vc, alleleMapping, genotypeMergeOptions == GenotypeMergeType.UNIQUIFY); + + // We always take the QUAL of the first VC with a non-MISSING qual for the combined value + if ( log10PError == CommonInfo.NO_LOG10_PERROR ) + log10PError = vc.getLog10PError(); + + filters.addAll(vc.getFilters()); + + // + // add attributes + // + // special case DP (add it up) and ID (just preserve it) + // + if (vc.hasAttribute(VCFConstants.DEPTH_KEY)) + depth += vc.getAttributeAsInt(VCFConstants.DEPTH_KEY, 0); + if ( vc.hasID() ) rsIDs.add(vc.getID()); + if (mergeInfoWithMaxAC && vc.hasAttribute(VCFConstants.ALLELE_COUNT_KEY)) { + String rawAlleleCounts = vc.getAttributeAsString(VCFConstants.ALLELE_COUNT_KEY, null); + // lets see if the string contains a , separator + if (rawAlleleCounts.contains(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR)) { + List alleleCountArray = Arrays.asList(rawAlleleCounts.substring(1, rawAlleleCounts.length() - 1).split(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR)); + for (String alleleCount : alleleCountArray) { + final int ac = Integer.valueOf(alleleCount.trim()); + if (ac > maxAC) { + maxAC = ac; + vcWithMaxAC = vc; + } + } + } else { + final int ac = Integer.valueOf(rawAlleleCounts); + if (ac > maxAC) { + maxAC = ac; + vcWithMaxAC = vc; + } + } + } + + for (final Map.Entry p : vc.getAttributes().entrySet()) { + String key = p.getKey(); + // if we don't like the key already, don't go anywhere + if ( ! inconsistentAttributes.contains(key) ) { + final boolean alreadyFound = attributes.containsKey(key); + final Object boundValue = attributes.get(key); + final boolean boundIsMissingValue = alreadyFound && boundValue.equals(VCFConstants.MISSING_VALUE_v4); + + if ( alreadyFound && ! boundValue.equals(p.getValue()) && ! boundIsMissingValue ) { + // we found the value but we're inconsistent, put it in the exclude list + //System.out.printf("Inconsistent INFO values: %s => %s and %s%n", key, boundValue, p.getValue()); + inconsistentAttributes.add(key); + attributes.remove(key); + } else if ( ! alreadyFound || boundIsMissingValue ) { // no value + //if ( vc != first ) System.out.printf("Adding key %s => %s%n", p.getKey(), p.getValue()); + attributes.put(key, p.getValue()); + } + } + } + } + + // if we have more alternate alleles in the merged VC than in one or more of the + // original VCs, we need to strip out the GL/PLs (because they are no longer accurate), as well as allele-dependent attributes like AC,AF, and AD + for ( final VariantContext vc : VCs ) { + if (vc.getAlleles().size() == 1) + continue; + if ( hasPLIncompatibleAlleles(alleles, vc.getAlleles())) { + if ( ! genotypes.isEmpty() ) { + logger.debug(String.format("Stripping PLs at %s:%d-%d due to incompatible alleles merged=%s vs. single=%s", + vc.getChr(), vc.getStart(), vc.getEnd(), alleles, vc.getAlleles())); + } + genotypes = stripPLsAndAD(genotypes); + // this will remove stale AC,AF attributed from vc + VariantContextUtils.calculateChromosomeCounts(vc, attributes, true); + break; + } + } + + // take the VC with the maxAC and pull the attributes into a modifiable map + if ( mergeInfoWithMaxAC && vcWithMaxAC != null ) { + attributesWithMaxAC.putAll(vcWithMaxAC.getAttributes()); + } + + // if at least one record was unfiltered and we want a union, clear all of the filters + if ( (filteredRecordMergeType == FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED && nFiltered != VCs.size()) || filteredRecordMergeType == FilteredRecordMergeType.KEEP_UNCONDITIONAL ) + filters.clear(); + + + if ( annotateOrigin ) { // we care about where the call came from + String setValue; + if ( nFiltered == 0 && variantSources.size() == originalNumOfVCs ) // nothing was unfiltered + setValue = MERGE_INTERSECTION; + else if ( nFiltered == VCs.size() ) // everything was filtered out + setValue = MERGE_FILTER_IN_ALL; + else if ( variantSources.isEmpty() ) // everyone was reference + setValue = MERGE_REF_IN_ALL; + else { + final LinkedHashSet s = new LinkedHashSet(); + for ( final VariantContext vc : VCs ) + if ( vc.isVariant() ) + s.add( vc.isFiltered() ? MERGE_FILTER_PREFIX + vc.getSource() : vc.getSource() ); + setValue = Utils.join("-", s); + } + + if ( setKey != null ) { + attributes.put(setKey, setValue); + if( mergeInfoWithMaxAC && vcWithMaxAC != null ) { + attributesWithMaxAC.put(setKey, setValue); + } + } + } + + if ( depth > 0 ) + attributes.put(VCFConstants.DEPTH_KEY, String.valueOf(depth)); + + final String ID = rsIDs.isEmpty() ? VCFConstants.EMPTY_ID_FIELD : Utils.join(",", rsIDs); + + final VariantContextBuilder builder = new VariantContextBuilder().source(name).id(ID); + builder.loc(longestVC.getChr(), longestVC.getStart(), longestVC.getEnd()); + builder.alleles(alleles); + builder.genotypes(genotypes); + builder.log10PError(log10PError); + builder.filters(filters.isEmpty() ? filters : new TreeSet(filters)); + builder.attributes(new TreeMap(mergeInfoWithMaxAC ? attributesWithMaxAC : attributes)); + + // Trim the padded bases of all alleles if necessary + final VariantContext merged = builder.make(); + if ( printMessages && remapped ) System.out.printf("Remapped => %s%n", merged); + return merged; + } + + private static final boolean hasPLIncompatibleAlleles(final Collection alleleSet1, final Collection alleleSet2) { + final Iterator it1 = alleleSet1.iterator(); + final Iterator it2 = alleleSet2.iterator(); + + while ( it1.hasNext() && it2.hasNext() ) { + final Allele a1 = it1.next(); + final Allele a2 = it2.next(); + if ( ! a1.equals(a2) ) + return true; + } + + // by this point, at least one of the iterators is empty. All of the elements + // we've compared are equal up until this point. But it's possible that the + // sets aren't the same size, which is indicated by the test below. If they + // are of the same size, though, the sets are compatible + return it1.hasNext() || it2.hasNext(); + } + + public static GenotypesContext stripPLsAndAD(GenotypesContext genotypes) { + GenotypesContext newGs = GenotypesContext.create(genotypes.size()); + + for ( final Genotype g : genotypes ) { + newGs.add(removePLsAndAD(g)); + } + + return newGs; + } + + static private Allele determineReferenceAllele(List VCs) { + Allele ref = null; + + for ( VariantContext vc : VCs ) { + Allele myRef = vc.getReference(); + if ( ref == null || ref.length() < myRef.length() ) + ref = myRef; + else if ( ref.length() == myRef.length() && ! ref.equals(myRef) ) + throw new TribbleException(String.format("The provided variant file(s) have inconsistent references for the same position(s) at %s:%d, %s vs. %s", vc.getChr(), vc.getStart(), ref, myRef)); + } + + return ref; + } + + static private AlleleMapper resolveIncompatibleAlleles(Allele refAllele, VariantContext vc, Set allAlleles) { + if ( refAllele.equals(vc.getReference()) ) + return new AlleleMapper(vc); + else { + // we really need to do some work. The refAllele is the longest reference allele seen at this + // start site. So imagine it is: + // + // refAllele: ACGTGA + // myRef: ACGT + // myAlt: A + // + // We need to remap all of the alleles in vc to include the extra GA so that + // myRef => refAllele and myAlt => AGA + // + + Allele myRef = vc.getReference(); + if ( refAllele.length() <= myRef.length() ) throw new IllegalStateException("BUG: myRef="+myRef+" is longer than refAllele="+refAllele); + byte[] extraBases = Arrays.copyOfRange(refAllele.getBases(), myRef.length(), refAllele.length()); + +// System.out.printf("Remapping allele at %s%n", vc); +// System.out.printf("ref %s%n", refAllele); +// System.out.printf("myref %s%n", myRef ); +// System.out.printf("extrabases %s%n", new String(extraBases)); + + Map map = new HashMap(); + for ( Allele a : vc.getAlleles() ) { + if ( a.isReference() ) + map.put(a, refAllele); + else { + Allele extended = Allele.extend(a, extraBases); + for ( Allele b : allAlleles ) + if ( extended.equals(b) ) + extended = b; +// System.out.printf(" Extending %s => %s%n", a, extended); + map.put(a, extended); + } + } + + // debugging +// System.out.printf("mapping %s%n", map); + + return new AlleleMapper(map); + } + } + + public static List sortVariantContextsByPriority(Collection unsortedVCs, List priorityListOfVCs, GenotypeMergeType mergeOption ) { + if ( mergeOption == GenotypeMergeType.PRIORITIZE && priorityListOfVCs == null ) + throw new IllegalArgumentException("Cannot merge calls by priority with a null priority list"); + + if ( priorityListOfVCs == null || mergeOption == GenotypeMergeType.UNSORTED ) + return new ArrayList(unsortedVCs); + else { + ArrayList sorted = new ArrayList(unsortedVCs); + Collections.sort(sorted, new CompareByPriority(priorityListOfVCs)); + return sorted; + } + } + + private static void mergeGenotypes(GenotypesContext mergedGenotypes, VariantContext oneVC, AlleleMapper alleleMapping, boolean uniqifySamples) { + //TODO: should we add a check for cases when the genotypeMergeOption is REQUIRE_UNIQUE + for ( Genotype g : oneVC.getGenotypes() ) { + String name = mergedSampleName(oneVC.getSource(), g.getSampleName(), uniqifySamples); + if ( ! mergedGenotypes.containsSample(name) ) { + // only add if the name is new + Genotype newG = g; + + if ( uniqifySamples || alleleMapping.needsRemapping() ) { + final List alleles = alleleMapping.needsRemapping() ? alleleMapping.remap(g.getAlleles()) : g.getAlleles(); + newG = new GenotypeBuilder(g).name(name).alleles(alleles).make(); + } + + mergedGenotypes.add(newG); + } + } + } + + public static String mergedSampleName(String trackName, String sampleName, boolean uniqify ) { + return uniqify ? sampleName + "." + trackName : sampleName; + } + + public static VariantContext reverseTrimAlleles( final VariantContext inputVC ) { + + // see whether we need to trim common reference base from all alleles + final int trimExtent = computeReverseClipping(inputVC.getAlleles(), inputVC.getReference().getDisplayString().getBytes(), 0, false); + if ( trimExtent <= 0 || inputVC.getAlleles().size() <= 1 ) + return inputVC; + + final List alleles = new ArrayList(); + final GenotypesContext genotypes = GenotypesContext.create(); + final Map originalToTrimmedAlleleMap = new HashMap(); + + for (final Allele a : inputVC.getAlleles()) { + if (a.isSymbolic()) { + alleles.add(a); + originalToTrimmedAlleleMap.put(a, a); + } else { + // get bases for current allele and create a new one with trimmed bases + final byte[] newBases = Arrays.copyOfRange(a.getBases(), 0, a.length()-trimExtent); + final Allele trimmedAllele = Allele.create(newBases, a.isReference()); + alleles.add(trimmedAllele); + originalToTrimmedAlleleMap.put(a, trimmedAllele); + } + } + + // now we can recreate new genotypes with trimmed alleles + for ( final Genotype genotype : inputVC.getGenotypes() ) { + final List originalAlleles = genotype.getAlleles(); + final List trimmedAlleles = new ArrayList(); + for ( final Allele a : originalAlleles ) { + if ( a.isCalled() ) + trimmedAlleles.add(originalToTrimmedAlleleMap.get(a)); + else + trimmedAlleles.add(Allele.NO_CALL); + } + genotypes.add(new GenotypeBuilder(genotype).alleles(trimmedAlleles).make()); + } + + return new VariantContextBuilder(inputVC).stop(inputVC.getStart() + alleles.get(0).length() - 1).alleles(alleles).genotypes(genotypes).make(); + } + + public static int computeReverseClipping(final List unclippedAlleles, + final byte[] ref, + final int forwardClipping, + final boolean allowFullClip) { + int clipping = 0; + boolean stillClipping = true; + + while ( stillClipping ) { + for ( final Allele a : unclippedAlleles ) { + if ( a.isSymbolic() ) + continue; + + // we need to ensure that we don't reverse clip out all of the bases from an allele because we then will have the wrong + // position set for the VariantContext (although it's okay to forward clip it all out, because the position will be fine). + if ( a.length() - clipping == 0 ) + return clipping - (allowFullClip ? 0 : 1); + + if ( a.length() - clipping <= forwardClipping || a.length() - forwardClipping == 0 ) { + stillClipping = false; + } + else if ( ref.length == clipping ) { + if ( allowFullClip ) + stillClipping = false; + else + return -1; + } + else if ( a.getBases()[a.length()-clipping-1] != ref[ref.length-clipping-1] ) { + stillClipping = false; + } + } + if ( stillClipping ) + clipping++; + } + + return clipping; + } + + public static double computeHardyWeinbergPvalue(VariantContext vc) { + if ( vc.getCalledChrCount() == 0 ) + return 0.0; + return HardyWeinbergCalculation.hwCalculate(vc.getHomRefCount(), vc.getHetCount(), vc.getHomVarCount()); + } + + public static boolean requiresPaddingBase(final List alleles) { + + // see whether one of the alleles would be null if trimmed through + + for ( final String allele : alleles ) { + if ( allele.isEmpty() ) + return true; + } + + int clipping = 0; + Character currentBase = null; + + while ( true ) { + for ( final String allele : alleles ) { + if ( allele.length() - clipping == 0 ) + return true; + + char myBase = allele.charAt(clipping); + if ( currentBase == null ) + currentBase = myBase; + else if ( currentBase != myBase ) + return false; + } + + clipping++; + currentBase = null; + } + } + + private static class AlleleMapper { + private VariantContext vc = null; + private Map map = null; + public AlleleMapper(VariantContext vc) { this.vc = vc; } + public AlleleMapper(Map map) { this.map = map; } + public boolean needsRemapping() { return this.map != null; } + public Collection values() { return map != null ? map.values() : vc.getAlleles(); } + public Allele remap(Allele a) { return map != null && map.containsKey(a) ? map.get(a) : a; } + + public List remap(List as) { + List newAs = new ArrayList(); + for ( Allele a : as ) { + //System.out.printf(" Remapping %s => %s%n", a, remap(a)); + newAs.add(remap(a)); + } + return newAs; + } + } + + private static class CompareByPriority implements Comparator, Serializable { + List priorityListOfVCs; + public CompareByPriority(List priorityListOfVCs) { + this.priorityListOfVCs = priorityListOfVCs; + } + + private int getIndex(VariantContext vc) { + int i = priorityListOfVCs.indexOf(vc.getSource()); + if ( i == -1 ) throw new IllegalArgumentException("Priority list " + priorityListOfVCs + " doesn't contain variant context " + vc.getSource()); + return i; + } + + public int compare(VariantContext vc1, VariantContext vc2) { + return Integer.valueOf(getIndex(vc1)).compareTo(getIndex(vc2)); + } + } } diff --git a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java index bbd02e0a6..76b49edb9 100644 --- a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java @@ -26,8 +26,6 @@ package org.broadinstitute.variant.utils; import net.sf.samtools.util.StringUtil; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.broadinstitute.sting.utils.exceptions.UserException; import java.util.Arrays; import java.util.Random; @@ -176,7 +174,7 @@ public class BaseUtils { if ( baseIndex == Base.N.ordinal() ) { bases[i] = 'N'; } else if ( errorOnBadReferenceBase && baseIndex == -1 ) { - throw new UserException.BadInput("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'"); + throw new IllegalStateException("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'"); } } return bases; @@ -517,7 +515,7 @@ public class BaseUtils { case 'N': return 'N'; default: - throw new ReviewedStingException("base must be A, C, G or T. " + (char) base + " is not a valid base."); + throw new IllegalArgumentException("base must be A, C, G or T. " + (char) base + " is not a valid base."); } } } diff --git a/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java b/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java index 79014a0eb..2dbc865b5 100644 --- a/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java +++ b/public/java/src/org/broadinstitute/variant/utils/GeneralUtils.java @@ -141,13 +141,6 @@ public class GeneralUtils { return normalized; } - public static double sum(double[] values) { - double s = 0.0; - for (double v : values) - s += v; - return s; - } - public static double arrayMax(final double[] array) { return array[maxElementIndex(array, array.length)]; } diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/CommonInfo.java b/public/java/src/org/broadinstitute/variant/variantcontext/CommonInfo.java index fd3227dbf..16fa52ee0 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/CommonInfo.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/CommonInfo.java @@ -36,7 +36,7 @@ import java.util.*; * * @author depristo */ -final class CommonInfo { +public final class CommonInfo { public static final double NO_LOG10_PERROR = 1.0; private static Set NO_FILTERS = Collections.emptySet(); diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index a6378951e..fa2b5c9e5 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -29,27 +29,16 @@ import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import org.apache.commons.jexl2.Expression; import org.apache.commons.jexl2.JexlEngine; -import org.apache.commons.lang.ArrayUtils; import org.broad.tribble.TribbleException; -import org.broad.tribble.util.popgen.HardyWeinbergCalculation; import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.utils.GeneralUtils; -import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.vcf.*; -import java.io.Serializable; import java.util.*; public class VariantContextUtils { - public final static String MERGE_INTERSECTION = "Intersection"; - public final static String MERGE_FILTER_IN_ALL = "FilteredInAll"; - public final static String MERGE_REF_IN_ALL = "ReferenceInAll"; - public final static String MERGE_FILTER_PREFIX = "filterIn"; - public static final int DEFAULT_PLOIDY = 2; - public static final double SUM_GL_THRESH_NOCALL = -0.1; // if sum(gl) is bigger than this threshold, we treat GL's as non-informative and will force a no-call. private static Set MISSING_KEYS_WARNED_ABOUT = new HashSet(); - private static final List NO_CALL_ALLELES = Arrays.asList(Allele.NO_CALL, Allele.NO_CALL); final public static JexlEngine engine = new JexlEngine(); private final static boolean ASSUME_MISSING_FIELDS_ARE_STRINGS = false; @@ -158,10 +147,6 @@ public class VariantContextUtils { builder.attributes(calculateChromosomeCounts(vc, new HashMap(vc.getAttributes()), removeStaleValues, founderIds)); } - public static Genotype removePLsAndAD(final Genotype g) { - return ( g.hasLikelihoods() || g.hasAD() ) ? new GenotypeBuilder(g).noPL().noAD().make() : g; - } - public final static VCFCompoundHeaderLine getMetaDataForField(final VCFHeader header, final String field) { VCFCompoundHeaderLine metaData = header.getFormatHeaderLine(field); if ( metaData == null ) metaData = header.getInfoHeaderLine(field); @@ -180,443 +165,6 @@ public class VariantContextUtils { return metaData; } - /** - * Returns true iff VC is an non-complex indel where every allele represents an expansion or - * contraction of a series of identical bases in the reference. - * - * For example, suppose the ref bases are CTCTCTGA, which includes a 3x repeat of CTCTCT - * - * If VC = -/CT, then this function returns true because the CT insertion matches exactly the - * upcoming reference. - * If VC = -/CTA then this function returns false because the CTA isn't a perfect match - * - * Now consider deletions: - * - * If VC = CT/- then again the same logic applies and this returns true - * The case of CTA/- makes no sense because it doesn't actually match the reference bases. - * - * The logic of this function is pretty simple. Take all of the non-null alleles in VC. For - * each insertion allele of n bases, check if that allele matches the next n reference bases. - * For each deletion allele of n bases, check if this matches the reference bases at n - 2 n, - * as it must necessarily match the first n bases. If this test returns true for all - * alleles you are a tandem repeat, otherwise you are not. - * - * @param vc - * @param refBasesStartingAtVCWithPad not this is assumed to include the PADDED reference - * @return - */ - @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) - public static boolean isTandemRepeat(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { - final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); - if ( ! vc.isIndel() ) // only indels are tandem repeats - return false; - - final Allele ref = vc.getReference(); - - for ( final Allele allele : vc.getAlternateAlleles() ) { - if ( ! isRepeatAllele(ref, allele, refBasesStartingAtVCWithoutPad) ) - return false; - } - - // we've passed all of the tests, so we are a repeat - return true; - } - - /** - * - * @param vc - * @param refBasesStartingAtVCWithPad - * @return - */ - @Requires({"vc != null", "refBasesStartingAtVCWithPad != null && refBasesStartingAtVCWithPad.length > 0"}) - public static Pair,byte[]> getNumTandemRepeatUnits(final VariantContext vc, final byte[] refBasesStartingAtVCWithPad) { - final boolean VERBOSE = false; - final String refBasesStartingAtVCWithoutPad = new String(refBasesStartingAtVCWithPad).substring(1); - if ( ! vc.isIndel() ) // only indels are tandem repeats - return null; - - final Allele refAllele = vc.getReference(); - final byte[] refAlleleBases = Arrays.copyOfRange(refAllele.getBases(), 1, refAllele.length()); - - byte[] repeatUnit = null; - final ArrayList lengths = new ArrayList(); - - for ( final Allele allele : vc.getAlternateAlleles() ) { - Pair result = getNumTandemRepeatUnits(refAlleleBases, Arrays.copyOfRange(allele.getBases(), 1, allele.length()), refBasesStartingAtVCWithoutPad.getBytes()); - - final int[] repetitionCount = result.first; - // repetition count = 0 means allele is not a tandem expansion of context - if (repetitionCount[0] == 0 || repetitionCount[1] == 0) - return null; - - if (lengths.size() == 0) { - lengths.add(repetitionCount[0]); // add ref allele length only once - } - lengths.add(repetitionCount[1]); // add this alt allele's length - - repeatUnit = result.second; - if (VERBOSE) { - System.out.println("RefContext:"+refBasesStartingAtVCWithoutPad); - System.out.println("Ref:"+refAllele.toString()+" Count:" + String.valueOf(repetitionCount[0])); - System.out.println("Allele:"+allele.toString()+" Count:" + String.valueOf(repetitionCount[1])); - System.out.println("RU:"+new String(repeatUnit)); - } - } - - return new Pair, byte[]>(lengths,repeatUnit); - } - - public static Pair getNumTandemRepeatUnits(final byte[] refBases, final byte[] altBases, final byte[] remainingRefContext) { - /* we can't exactly apply same logic as in basesAreRepeated() to compute tandem unit and number of repeated units. - Consider case where ref =ATATAT and we have an insertion of ATAT. Natural description is (AT)3 -> (AT)2. - */ - - byte[] longB; - // find first repeat unit based on either ref or alt, whichever is longer - if (altBases.length > refBases.length) - longB = altBases; - else - longB = refBases; - - // see if non-null allele (either ref or alt, whichever is longer) can be decomposed into several identical tandem units - // for example, -*,CACA needs to first be decomposed into (CA)2 - final int repeatUnitLength = findRepeatedSubstring(longB); - final byte[] repeatUnit = Arrays.copyOf(longB, repeatUnitLength); - - final int[] repetitionCount = new int[2]; - // look for repetitions forward on the ref bases (i.e. starting at beginning of ref bases) - int repetitionsInRef = findNumberofRepetitions(repeatUnit,refBases, true); - repetitionCount[0] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(refBases, remainingRefContext), true)-repetitionsInRef; - repetitionCount[1] = findNumberofRepetitions(repeatUnit, ArrayUtils.addAll(altBases, remainingRefContext), true)-repetitionsInRef; - - return new Pair(repetitionCount, repeatUnit); - - } - - /** - * Find out if a string can be represented as a tandem number of substrings. - * For example ACTACT is a 2-tandem of ACT, - * but ACTACA is not. - * - * @param bases String to be tested - * @return Length of repeat unit, if string can be represented as tandem of substring (if it can't - * be represented as one, it will be just the length of the input string) - */ - public static int findRepeatedSubstring(byte[] bases) { - - int repLength; - for (repLength=1; repLength <=bases.length; repLength++) { - final byte[] candidateRepeatUnit = Arrays.copyOf(bases,repLength); - boolean allBasesMatch = true; - for (int start = repLength; start < bases.length; start += repLength ) { - // check that remaining of string is exactly equal to repeat unit - final byte[] basePiece = Arrays.copyOfRange(bases,start,start+candidateRepeatUnit.length); - if (!Arrays.equals(candidateRepeatUnit, basePiece)) { - allBasesMatch = false; - break; - } - } - if (allBasesMatch) - return repLength; - } - - return repLength; - } - - /** - * Helper routine that finds number of repetitions a string consists of. - * For example, for string ATAT and repeat unit AT, number of repetitions = 2 - * @param repeatUnit Substring - * @param testString String to test - * @oaram lookForward Look for repetitions forward (at beginning of string) or backward (at end of string) - * @return Number of repetitions (0 if testString is not a concatenation of n repeatUnit's - */ - public static int findNumberofRepetitions(byte[] repeatUnit, byte[] testString, boolean lookForward) { - int numRepeats = 0; - if (lookForward) { - // look forward on the test string - for (int start = 0; start < testString.length; start += repeatUnit.length) { - int end = start + repeatUnit.length; - byte[] unit = Arrays.copyOfRange(testString,start, end); - if(Arrays.equals(unit,repeatUnit)) - numRepeats++; - else - break; - } - return numRepeats; - } - - // look backward. For example, if repeatUnit = AT and testString = GATAT, number of repeat units is still 2 - // look forward on the test string - for (int start = testString.length - repeatUnit.length; start >= 0; start -= repeatUnit.length) { - int end = start + repeatUnit.length; - byte[] unit = Arrays.copyOfRange(testString,start, end); - if(Arrays.equals(unit,repeatUnit)) - numRepeats++; - else - break; - } - return numRepeats; - } - - /** - * Helper function for isTandemRepeat that checks that allele matches somewhere on the reference - * @param ref - * @param alt - * @param refBasesStartingAtVCWithoutPad - * @return - */ - protected static boolean isRepeatAllele(final Allele ref, final Allele alt, final String refBasesStartingAtVCWithoutPad) { - if ( ! Allele.oneIsPrefixOfOther(ref, alt) ) - return false; // we require one allele be a prefix of another - - if ( ref.length() > alt.length() ) { // we are a deletion - return basesAreRepeated(ref.getBaseString(), alt.getBaseString(), refBasesStartingAtVCWithoutPad, 2); - } else { // we are an insertion - return basesAreRepeated(alt.getBaseString(), ref.getBaseString(), refBasesStartingAtVCWithoutPad, 1); - } - } - - protected static boolean basesAreRepeated(final String l, final String s, final String ref, final int minNumberOfMatches) { - final String potentialRepeat = l.substring(s.length()); // skip s bases - - for ( int i = 0; i < minNumberOfMatches; i++) { - final int start = i * potentialRepeat.length(); - final int end = (i+1) * potentialRepeat.length(); - if ( ref.length() < end ) - return false; // we ran out of bases to test - final String refSub = ref.substring(start, end); - if ( ! refSub.equals(potentialRepeat) ) - return false; // repeat didn't match, fail - } - - return true; // we passed all tests, we matched - } - - /** - * Assign genotypes (GTs) to the samples in the Variant Context greedily based on the PLs - * - * @param vc variant context with genotype likelihoods - * @return genotypes context - */ - public static GenotypesContext assignDiploidGenotypes(final VariantContext vc) { - return subsetDiploidAlleles(vc, vc.getAlleles(), true); - } - - /** - * Split variant context into its biallelic components if there are more than 2 alleles - * - * For VC has A/B/C alleles, returns A/B and A/C contexts. - * Genotypes are all no-calls now (it's not possible to fix them easily) - * Alleles are right trimmed to satisfy VCF conventions - * - * If vc is biallelic or non-variant it is just returned - * - * Chromosome counts are updated (but they are by definition 0) - * - * @param vc a potentially multi-allelic variant context - * @return a list of bi-allelic (or monomorphic) variant context - */ - public static List splitVariantContextToBiallelics(final VariantContext vc) { - if ( ! vc.isVariant() || vc.isBiallelic() ) - // non variant or biallelics already satisfy the contract - return Collections.singletonList(vc); - else { - final List biallelics = new LinkedList(); - - for ( final Allele alt : vc.getAlternateAlleles() ) { - VariantContextBuilder builder = new VariantContextBuilder(vc); - final List alleles = Arrays.asList(vc.getReference(), alt); - builder.alleles(alleles); - builder.genotypes(subsetDiploidAlleles(vc, alleles, false)); - calculateChromosomeCounts(builder, true); - biallelics.add(reverseTrimAlleles(builder.make())); - } - - return biallelics; - } - } - - /** - * subset the Variant Context to the specific set of alleles passed in (pruning the PLs appropriately) - * - * @param vc variant context with genotype likelihoods - * @param allelesToUse which alleles from the vc are okay to use; *** must be in the same relative order as those in the original VC *** - * @param assignGenotypes true if we should update the genotypes based on the (subsetted) PLs - * @return genotypes - */ - public static GenotypesContext subsetDiploidAlleles(final VariantContext vc, - final List allelesToUse, - final boolean assignGenotypes) { - - // the genotypes with PLs - final GenotypesContext oldGTs = vc.getGenotypes(); - - // samples - final List sampleIndices = oldGTs.getSampleNamesOrderedByName(); - - // the new genotypes to create - final GenotypesContext newGTs = GenotypesContext.create(); - - // we need to determine which of the alternate alleles (and hence the likelihoods) to use and carry forward - final int numOriginalAltAlleles = vc.getAlternateAlleles().size(); - final int numNewAltAlleles = allelesToUse.size() - 1; - - // which PLs should be carried forward? - ArrayList likelihoodIndexesToUse = null; - - // an optimization: if we are supposed to use all (or none in the case of a ref call) of the alleles, - // then we can keep the PLs as is; otherwise, we determine which ones to keep - if ( numNewAltAlleles != numOriginalAltAlleles && numNewAltAlleles > 0 ) { - likelihoodIndexesToUse = new ArrayList(30); - - final boolean[] altAlleleIndexToUse = new boolean[numOriginalAltAlleles]; - for ( int i = 0; i < numOriginalAltAlleles; i++ ) { - if ( allelesToUse.contains(vc.getAlternateAllele(i)) ) - altAlleleIndexToUse[i] = true; - } - - // numLikelihoods takes total # of alleles. Use default # of chromosomes (ploidy) = 2 - final int numLikelihoods = GenotypeLikelihoods.numLikelihoods(1 + numOriginalAltAlleles, DEFAULT_PLOIDY); - for ( int PLindex = 0; PLindex < numLikelihoods; PLindex++ ) { - final GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); - // consider this entry only if both of the alleles are good - if ( (alleles.alleleIndex1 == 0 || altAlleleIndexToUse[alleles.alleleIndex1 - 1]) && (alleles.alleleIndex2 == 0 || altAlleleIndexToUse[alleles.alleleIndex2 - 1]) ) - likelihoodIndexesToUse.add(PLindex); - } - } - - // create the new genotypes - for ( int k = 0; k < oldGTs.size(); k++ ) { - final Genotype g = oldGTs.get(sampleIndices.get(k)); - if ( !g.hasLikelihoods() ) { - newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); - continue; - } - - // create the new likelihoods array from the alleles we are allowed to use - final double[] originalLikelihoods = g.getLikelihoods().getAsVector(); - double[] newLikelihoods; - if ( likelihoodIndexesToUse == null ) { - newLikelihoods = originalLikelihoods; - } else { - newLikelihoods = new double[likelihoodIndexesToUse.size()]; - int newIndex = 0; - for ( int oldIndex : likelihoodIndexesToUse ) - newLikelihoods[newIndex++] = originalLikelihoods[oldIndex]; - - // might need to re-normalize - newLikelihoods = GeneralUtils.normalizeFromLog10(newLikelihoods, false, true); - } - - // if there is no mass on the (new) likelihoods, then just no-call the sample - if ( GeneralUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { - newGTs.add(GenotypeBuilder.create(g.getSampleName(), NO_CALL_ALLELES)); - } - else { - final GenotypeBuilder gb = new GenotypeBuilder(g); - - if ( numNewAltAlleles == 0 ) - gb.noPL(); - else - gb.PL(newLikelihoods); - - // if we weren't asked to assign a genotype, then just no-call the sample - if ( !assignGenotypes || GeneralUtils.sum(newLikelihoods) > SUM_GL_THRESH_NOCALL ) { - gb.alleles(NO_CALL_ALLELES); - } - else { - // find the genotype with maximum likelihoods - int PLindex = numNewAltAlleles == 0 ? 0 : GeneralUtils.maxElementIndex(newLikelihoods); - GenotypeLikelihoods.GenotypeLikelihoodsAllelePair alleles = GenotypeLikelihoods.getAllelePair(PLindex); - - gb.alleles(Arrays.asList(allelesToUse.get(alleles.alleleIndex1), allelesToUse.get(alleles.alleleIndex2))); - if ( numNewAltAlleles != 0 ) gb.log10PError(GenotypeLikelihoods.getGQLog10FromLikelihoods(PLindex, newLikelihoods)); - } - newGTs.add(gb.make()); - } - } - - return newGTs; - } - - public static VariantContext reverseTrimAlleles( final VariantContext inputVC ) { - - // see whether we need to trim common reference base from all alleles - final int trimExtent = computeReverseClipping(inputVC.getAlleles(), inputVC.getReference().getDisplayString().getBytes(), 0, false); - if ( trimExtent <= 0 || inputVC.getAlleles().size() <= 1 ) - return inputVC; - - final List alleles = new ArrayList(); - final GenotypesContext genotypes = GenotypesContext.create(); - final Map originalToTrimmedAlleleMap = new HashMap(); - - for (final Allele a : inputVC.getAlleles()) { - if (a.isSymbolic()) { - alleles.add(a); - originalToTrimmedAlleleMap.put(a, a); - } else { - // get bases for current allele and create a new one with trimmed bases - final byte[] newBases = Arrays.copyOfRange(a.getBases(), 0, a.length()-trimExtent); - final Allele trimmedAllele = Allele.create(newBases, a.isReference()); - alleles.add(trimmedAllele); - originalToTrimmedAlleleMap.put(a, trimmedAllele); - } - } - - // now we can recreate new genotypes with trimmed alleles - for ( final Genotype genotype : inputVC.getGenotypes() ) { - final List originalAlleles = genotype.getAlleles(); - final List trimmedAlleles = new ArrayList(); - for ( final Allele a : originalAlleles ) { - if ( a.isCalled() ) - trimmedAlleles.add(originalToTrimmedAlleleMap.get(a)); - else - trimmedAlleles.add(Allele.NO_CALL); - } - genotypes.add(new GenotypeBuilder(genotype).alleles(trimmedAlleles).make()); - } - - return new VariantContextBuilder(inputVC).stop(inputVC.getStart() + alleles.get(0).length() - 1).alleles(alleles).genotypes(genotypes).make(); - } - - public static int computeReverseClipping(final List unclippedAlleles, - final byte[] ref, - final int forwardClipping, - final boolean allowFullClip) { - int clipping = 0; - boolean stillClipping = true; - - while ( stillClipping ) { - for ( final Allele a : unclippedAlleles ) { - if ( a.isSymbolic() ) - continue; - - // we need to ensure that we don't reverse clip out all of the bases from an allele because we then will have the wrong - // position set for the VariantContext (although it's okay to forward clip it all out, because the position will be fine). - if ( a.length() - clipping == 0 ) - return clipping - (allowFullClip ? 0 : 1); - - if ( a.length() - clipping <= forwardClipping || a.length() - forwardClipping == 0 ) { - stillClipping = false; - } - else if ( ref.length == clipping ) { - if ( allowFullClip ) - stillClipping = false; - else - return -1; - } - else if ( a.getBases()[a.length()-clipping-1] != ref[ref.length-clipping-1] ) { - stillClipping = false; - } - } - if ( stillClipping ) - clipping++; - } - - return clipping; - } - /** * A simple but common wrapper for matching VariantContext objects using JEXL expressions */ @@ -744,12 +292,6 @@ public class VariantContextUtils { return new JEXLMap(exps,vc,g); } - public static double computeHardyWeinbergPvalue(VariantContext vc) { - if ( vc.getCalledChrCount() == 0 ) - return 0.0; - return HardyWeinbergCalculation.hwCalculate(vc.getHomRefCount(), vc.getHetCount(), vc.getHomVarCount()); - } - /** * Returns a newly allocated VC that is the same as VC, but without genotypes * @param vc variant context @@ -814,317 +356,6 @@ public class VariantContextUtils { return builder.genotypes(genotypes).attributes(attributes); } - public enum GenotypeMergeType { - /** - * Make all sample genotypes unique by file. Each sample shared across RODs gets named sample.ROD. - */ - UNIQUIFY, - /** - * Take genotypes in priority order (see the priority argument). - */ - PRIORITIZE, - /** - * Take the genotypes in any order. - */ - UNSORTED, - /** - * Require that all samples/genotypes be unique between all inputs. - */ - REQUIRE_UNIQUE - } - - public enum FilteredRecordMergeType { - /** - * Union - leaves the record if any record is unfiltered. - */ - KEEP_IF_ANY_UNFILTERED, - /** - * Requires all records present at site to be unfiltered. VCF files that don't contain the record don't influence this. - */ - KEEP_IF_ALL_UNFILTERED, - /** - * If any record is present at this site (regardless of possibly being filtered), then all such records are kept and the filters are reset. - */ - KEEP_UNCONDITIONAL - } - - public enum MultipleAllelesMergeType { - /** - * Combine only alleles of the same type (SNP, indel, etc.) into a single VCF record. - */ - BY_TYPE, - /** - * Merge all allele types at the same start position into the same VCF record. - */ - MIX_TYPES - } - - /** - * Merges VariantContexts into a single hybrid. Takes genotypes for common samples in priority order, if provided. - * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with - * the sample name - * - * @param unsortedVCs collection of unsorted VCs - * @param priorityListOfVCs priority list detailing the order in which we should grab the VCs - * @param filteredRecordMergeType merge type for filtered records - * @param genotypeMergeOptions merge option for genotypes - * @param annotateOrigin should we annotate the set it came from? - * @param printMessages should we print messages? - * @param setKey the key name of the set - * @param filteredAreUncalled are filtered records uncalled? - * @param mergeInfoWithMaxAC should we merge in info from the VC with maximum allele count? - * @return new VariantContext representing the merge of unsortedVCs - */ - public static VariantContext simpleMerge(final Collection unsortedVCs, - final List priorityListOfVCs, - final FilteredRecordMergeType filteredRecordMergeType, - final GenotypeMergeType genotypeMergeOptions, - final boolean annotateOrigin, - final boolean printMessages, - final String setKey, - final boolean filteredAreUncalled, - final boolean mergeInfoWithMaxAC ) { - int originalNumOfVCs = priorityListOfVCs == null ? 0 : priorityListOfVCs.size(); - return simpleMerge(unsortedVCs,priorityListOfVCs,originalNumOfVCs,filteredRecordMergeType,genotypeMergeOptions,annotateOrigin,printMessages,setKey,filteredAreUncalled,mergeInfoWithMaxAC); - } - - /** - * Merges VariantContexts into a single hybrid. Takes genotypes for common samples in priority order, if provided. - * If uniquifySamples is true, the priority order is ignored and names are created by concatenating the VC name with - * the sample name. - * simpleMerge does not verify any more unique sample names EVEN if genotypeMergeOptions == GenotypeMergeType.REQUIRE_UNIQUE. One should use - * SampleUtils.verifyUniqueSamplesNames to check that before using sempleMerge. - * - * @param unsortedVCs collection of unsorted VCs - * @param priorityListOfVCs priority list detailing the order in which we should grab the VCs - * @param filteredRecordMergeType merge type for filtered records - * @param genotypeMergeOptions merge option for genotypes - * @param annotateOrigin should we annotate the set it came from? - * @param printMessages should we print messages? - * @param setKey the key name of the set - * @param filteredAreUncalled are filtered records uncalled? - * @param mergeInfoWithMaxAC should we merge in info from the VC with maximum allele count? - * @return new VariantContext representing the merge of unsortedVCs - */ - public static VariantContext simpleMerge(final Collection unsortedVCs, - final List priorityListOfVCs, - final int originalNumOfVCs, - final FilteredRecordMergeType filteredRecordMergeType, - final GenotypeMergeType genotypeMergeOptions, - final boolean annotateOrigin, - final boolean printMessages, - final String setKey, - final boolean filteredAreUncalled, - final boolean mergeInfoWithMaxAC ) { - - if ( unsortedVCs == null || unsortedVCs.size() == 0 ) - return null; - - if (priorityListOfVCs != null && originalNumOfVCs != priorityListOfVCs.size()) - throw new IllegalArgumentException("the number of the original VariantContexts must be the same as the number of VariantContexts in the priority list"); - - if ( annotateOrigin && priorityListOfVCs == null && originalNumOfVCs == 0) - throw new IllegalArgumentException("Cannot merge calls and annotate their origins without a complete priority list of VariantContexts or the number of original VariantContexts"); - - final List preFilteredVCs = sortVariantContextsByPriority(unsortedVCs, priorityListOfVCs, genotypeMergeOptions); - // Make sure all variant contexts are padded with reference base in case of indels if necessary - final List VCs = new ArrayList(); - - for (final VariantContext vc : preFilteredVCs) { - if ( ! filteredAreUncalled || vc.isNotFiltered() ) - VCs.add(vc); - } - if ( VCs.size() == 0 ) // everything is filtered out and we're filteredAreUncalled - return null; - - // establish the baseline info from the first VC - final VariantContext first = VCs.get(0); - final String name = first.getSource(); - final Allele refAllele = determineReferenceAllele(VCs); - - final Set alleles = new LinkedHashSet(); - final Set filters = new HashSet(); - final Map attributes = new LinkedHashMap(); - final Set inconsistentAttributes = new HashSet(); - final Set variantSources = new HashSet(); // contains the set of sources we found in our set of VCs that are variant - final Set rsIDs = new LinkedHashSet(1); // most of the time there's one id - - VariantContext longestVC = first; - int depth = 0; - int maxAC = -1; - final Map attributesWithMaxAC = new LinkedHashMap(); - double log10PError = CommonInfo.NO_LOG10_PERROR; - VariantContext vcWithMaxAC = null; - GenotypesContext genotypes = GenotypesContext.create(); - - // counting the number of filtered and variant VCs - int nFiltered = 0; - - boolean remapped = false; - - // cycle through and add info from the other VCs, making sure the loc/reference matches - - for ( final VariantContext vc : VCs ) { - if ( longestVC.getStart() != vc.getStart() ) - throw new IllegalStateException("BUG: attempting to merge VariantContexts with different start sites: first="+ first.toString() + " second=" + vc.toString()); - - if ( getSize(vc) > getSize(longestVC) ) - longestVC = vc; // get the longest location - - nFiltered += vc.isFiltered() ? 1 : 0; - if ( vc.isVariant() ) variantSources.add(vc.getSource()); - - AlleleMapper alleleMapping = resolveIncompatibleAlleles(refAllele, vc, alleles); - remapped = remapped || alleleMapping.needsRemapping(); - - alleles.addAll(alleleMapping.values()); - - mergeGenotypes(genotypes, vc, alleleMapping, genotypeMergeOptions == GenotypeMergeType.UNIQUIFY); - - // We always take the QUAL of the first VC with a non-MISSING qual for the combined value - if ( log10PError == CommonInfo.NO_LOG10_PERROR ) - log10PError = vc.getLog10PError(); - - filters.addAll(vc.getFilters()); - - // - // add attributes - // - // special case DP (add it up) and ID (just preserve it) - // - if (vc.hasAttribute(VCFConstants.DEPTH_KEY)) - depth += vc.getAttributeAsInt(VCFConstants.DEPTH_KEY, 0); - if ( vc.hasID() ) rsIDs.add(vc.getID()); - if (mergeInfoWithMaxAC && vc.hasAttribute(VCFConstants.ALLELE_COUNT_KEY)) { - String rawAlleleCounts = vc.getAttributeAsString(VCFConstants.ALLELE_COUNT_KEY, null); - // lets see if the string contains a , separator - if (rawAlleleCounts.contains(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR)) { - List alleleCountArray = Arrays.asList(rawAlleleCounts.substring(1, rawAlleleCounts.length() - 1).split(VCFConstants.INFO_FIELD_ARRAY_SEPARATOR)); - for (String alleleCount : alleleCountArray) { - final int ac = Integer.valueOf(alleleCount.trim()); - if (ac > maxAC) { - maxAC = ac; - vcWithMaxAC = vc; - } - } - } else { - final int ac = Integer.valueOf(rawAlleleCounts); - if (ac > maxAC) { - maxAC = ac; - vcWithMaxAC = vc; - } - } - } - - for (final Map.Entry p : vc.getAttributes().entrySet()) { - String key = p.getKey(); - // if we don't like the key already, don't go anywhere - if ( ! inconsistentAttributes.contains(key) ) { - final boolean alreadyFound = attributes.containsKey(key); - final Object boundValue = attributes.get(key); - final boolean boundIsMissingValue = alreadyFound && boundValue.equals(VCFConstants.MISSING_VALUE_v4); - - if ( alreadyFound && ! boundValue.equals(p.getValue()) && ! boundIsMissingValue ) { - // we found the value but we're inconsistent, put it in the exclude list - //System.out.printf("Inconsistent INFO values: %s => %s and %s%n", key, boundValue, p.getValue()); - inconsistentAttributes.add(key); - attributes.remove(key); - } else if ( ! alreadyFound || boundIsMissingValue ) { // no value - //if ( vc != first ) System.out.printf("Adding key %s => %s%n", p.getKey(), p.getValue()); - attributes.put(key, p.getValue()); - } - } - } - } - - // if we have more alternate alleles in the merged VC than in one or more of the - // original VCs, we need to strip out the GL/PLs (because they are no longer accurate), as well as allele-dependent attributes like AC,AF, and AD - for ( final VariantContext vc : VCs ) { - if (vc.alleles.size() == 1) - continue; - if ( hasPLIncompatibleAlleles(alleles, vc.alleles)) { - if ( GeneralUtils.DEBUG_MODE_ENABLED && ! genotypes.isEmpty() ) { - System.err.println(String.format("Stripping PLs at %s:%d-%d due to incompatible alleles merged=%s vs. single=%s", - vc.getChr(), vc.getStart(), vc.getEnd(), alleles, vc.alleles)); - } - genotypes = stripPLsAndAD(genotypes); - // this will remove stale AC,AF attributed from vc - calculateChromosomeCounts(vc, attributes, true); - break; - } - } - - // take the VC with the maxAC and pull the attributes into a modifiable map - if ( mergeInfoWithMaxAC && vcWithMaxAC != null ) { - attributesWithMaxAC.putAll(vcWithMaxAC.getAttributes()); - } - - // if at least one record was unfiltered and we want a union, clear all of the filters - if ( (filteredRecordMergeType == FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED && nFiltered != VCs.size()) || filteredRecordMergeType == FilteredRecordMergeType.KEEP_UNCONDITIONAL ) - filters.clear(); - - - if ( annotateOrigin ) { // we care about where the call came from - String setValue; - if ( nFiltered == 0 && variantSources.size() == originalNumOfVCs ) // nothing was unfiltered - setValue = MERGE_INTERSECTION; - else if ( nFiltered == VCs.size() ) // everything was filtered out - setValue = MERGE_FILTER_IN_ALL; - else if ( variantSources.isEmpty() ) // everyone was reference - setValue = MERGE_REF_IN_ALL; - else { - final LinkedHashSet s = new LinkedHashSet(); - for ( final VariantContext vc : VCs ) - if ( vc.isVariant() ) - s.add( vc.isFiltered() ? MERGE_FILTER_PREFIX + vc.getSource() : vc.getSource() ); - setValue = GeneralUtils.join("-", s); - } - - if ( setKey != null ) { - attributes.put(setKey, setValue); - if( mergeInfoWithMaxAC && vcWithMaxAC != null ) { - attributesWithMaxAC.put(setKey, setValue); - } - } - } - - if ( depth > 0 ) - attributes.put(VCFConstants.DEPTH_KEY, String.valueOf(depth)); - - final String ID = rsIDs.isEmpty() ? VCFConstants.EMPTY_ID_FIELD : GeneralUtils.join(",", rsIDs); - - final VariantContextBuilder builder = new VariantContextBuilder().source(name).id(ID); - builder.loc(longestVC.getChr(), longestVC.getStart(), longestVC.getEnd()); - builder.alleles(alleles); - builder.genotypes(genotypes); - builder.log10PError(log10PError); - builder.filters(filters.isEmpty() ? filters : new TreeSet(filters)); - builder.attributes(new TreeMap(mergeInfoWithMaxAC ? attributesWithMaxAC : attributes)); - - // Trim the padded bases of all alleles if necessary - final VariantContext merged = builder.make(); - if ( printMessages && remapped ) System.out.printf("Remapped => %s%n", merged); - return merged; - } - - private static final boolean hasPLIncompatibleAlleles(final Collection alleleSet1, final Collection alleleSet2) { - final Iterator it1 = alleleSet1.iterator(); - final Iterator it2 = alleleSet2.iterator(); - - while ( it1.hasNext() && it2.hasNext() ) { - final Allele a1 = it1.next(); - final Allele a2 = it2.next(); - if ( ! a1.equals(a2) ) - return true; - } - - // by this point, at least one of the iterators is empty. All of the elements - // we've compared are equal up until this point. But it's possible that the - // sets aren't the same size, which is indicated by the test below. If they - // are of the same size, though, the sets are compatible - return it1.hasNext() || it2.hasNext(); - } - public static boolean allelesAreSubset(VariantContext vc1, VariantContext vc2) { // if all alleles of vc1 are a contained in alleles of vc2, return true if (!vc1.getReference().equals(vc2.getReference())) @@ -1138,16 +369,6 @@ public class VariantContextUtils { return true; } - public static GenotypesContext stripPLsAndAD(GenotypesContext genotypes) { - GenotypesContext newGs = GenotypesContext.create(genotypes.size()); - - for ( final Genotype g : genotypes ) { - newGs.add(removePLsAndAD(g)); - } - - return newGs; - } - public static Map> separateVariantContextsByType(Collection VCs) { HashMap> mappedVCs = new HashMap>(); for ( VariantContext vc : VCs ) { @@ -1196,26 +417,7 @@ public class VariantContextUtils { return mappedVCs; } - private static class AlleleMapper { - private VariantContext vc = null; - private Map map = null; - public AlleleMapper(VariantContext vc) { this.vc = vc; } - public AlleleMapper(Map map) { this.map = map; } - public boolean needsRemapping() { return this.map != null; } - public Collection values() { return map != null ? map.values() : vc.getAlleles(); } - public Allele remap(Allele a) { return map != null && map.containsKey(a) ? map.get(a) : a; } - - public List remap(List as) { - List newAs = new ArrayList(); - for ( Allele a : as ) { - //System.out.printf(" Remapping %s => %s%n", a, remap(a)); - newAs.add(remap(a)); - } - return newAs; - } - } - -// TODO: remove that after testing + // TODO: remove that after testing // static private void verifyUniqueSampleNames(Collection unsortedVCs) { // Set names = new HashSet(); // for ( VariantContext vc : unsortedVCs ) { @@ -1230,117 +432,6 @@ public class VariantContextUtils { // } - static private Allele determineReferenceAllele(List VCs) { - Allele ref = null; - - for ( VariantContext vc : VCs ) { - Allele myRef = vc.getReference(); - if ( ref == null || ref.length() < myRef.length() ) - ref = myRef; - else if ( ref.length() == myRef.length() && ! ref.equals(myRef) ) - throw new TribbleException(String.format("The provided variant file(s) have inconsistent references for the same position(s) at %s:%d, %s vs. %s", vc.getChr(), vc.getStart(), ref, myRef)); - } - - return ref; - } - - static private AlleleMapper resolveIncompatibleAlleles(Allele refAllele, VariantContext vc, Set allAlleles) { - if ( refAllele.equals(vc.getReference()) ) - return new AlleleMapper(vc); - else { - // we really need to do some work. The refAllele is the longest reference allele seen at this - // start site. So imagine it is: - // - // refAllele: ACGTGA - // myRef: ACGT - // myAlt: A - // - // We need to remap all of the alleles in vc to include the extra GA so that - // myRef => refAllele and myAlt => AGA - // - - Allele myRef = vc.getReference(); - if ( refAllele.length() <= myRef.length() ) throw new IllegalStateException("BUG: myRef="+myRef+" is longer than refAllele="+refAllele); - byte[] extraBases = Arrays.copyOfRange(refAllele.getBases(), myRef.length(), refAllele.length()); - -// System.out.printf("Remapping allele at %s%n", vc); -// System.out.printf("ref %s%n", refAllele); -// System.out.printf("myref %s%n", myRef ); -// System.out.printf("extrabases %s%n", new String(extraBases)); - - Map map = new HashMap(); - for ( Allele a : vc.getAlleles() ) { - if ( a.isReference() ) - map.put(a, refAllele); - else { - Allele extended = Allele.extend(a, extraBases); - for ( Allele b : allAlleles ) - if ( extended.equals(b) ) - extended = b; -// System.out.printf(" Extending %s => %s%n", a, extended); - map.put(a, extended); - } - } - - // debugging -// System.out.printf("mapping %s%n", map); - - return new AlleleMapper(map); - } - } - - static class CompareByPriority implements Comparator, Serializable { - List priorityListOfVCs; - public CompareByPriority(List priorityListOfVCs) { - this.priorityListOfVCs = priorityListOfVCs; - } - - private int getIndex(VariantContext vc) { - int i = priorityListOfVCs.indexOf(vc.getSource()); - if ( i == -1 ) throw new IllegalArgumentException("Priority list " + priorityListOfVCs + " doesn't contain variant context " + vc.getSource()); - return i; - } - - public int compare(VariantContext vc1, VariantContext vc2) { - return Integer.valueOf(getIndex(vc1)).compareTo(getIndex(vc2)); - } - } - - public static List sortVariantContextsByPriority(Collection unsortedVCs, List priorityListOfVCs, GenotypeMergeType mergeOption ) { - if ( mergeOption == GenotypeMergeType.PRIORITIZE && priorityListOfVCs == null ) - throw new IllegalArgumentException("Cannot merge calls by priority with a null priority list"); - - if ( priorityListOfVCs == null || mergeOption == GenotypeMergeType.UNSORTED ) - return new ArrayList(unsortedVCs); - else { - ArrayList sorted = new ArrayList(unsortedVCs); - Collections.sort(sorted, new CompareByPriority(priorityListOfVCs)); - return sorted; - } - } - - private static void mergeGenotypes(GenotypesContext mergedGenotypes, VariantContext oneVC, AlleleMapper alleleMapping, boolean uniqifySamples) { - //TODO: should we add a check for cases when the genotypeMergeOption is REQUIRE_UNIQUE - for ( Genotype g : oneVC.getGenotypes() ) { - String name = mergedSampleName(oneVC.getSource(), g.getSampleName(), uniqifySamples); - if ( ! mergedGenotypes.containsSample(name) ) { - // only add if the name is new - Genotype newG = g; - - if ( uniqifySamples || alleleMapping.needsRemapping() ) { - final List alleles = alleleMapping.needsRemapping() ? alleleMapping.remap(g.getAlleles()) : g.getAlleles(); - newG = new GenotypeBuilder(g).name(name).alleles(alleles).make(); - } - - mergedGenotypes.add(newG); - } - } - } - - public static String mergedSampleName(String trackName, String sampleName, boolean uniqify ) { - return uniqify ? sampleName + "." + trackName : sampleName; - } - /** * Returns a context identical to this with the REF and ALT alleles reverse complemented. * @@ -1460,33 +551,4 @@ public class VariantContextUtils { } } - public static boolean requiresPaddingBase(final List alleles) { - - // see whether one of the alleles would be null if trimmed through - - for ( final String allele : alleles ) { - if ( allele.isEmpty() ) - return true; - } - - int clipping = 0; - Character currentBase = null; - - while ( true ) { - for ( final String allele : alleles ) { - if ( allele.length() - clipping == 0 ) - return true; - - char myBase = allele.charAt(clipping); - if ( currentBase == null ) - currentBase = myBase; - else if ( currentBase != myBase ) - return false; - } - - clipping++; - currentBase = null; - } - } - } diff --git a/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java b/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java index db2d47609..f61761652 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java +++ b/public/java/src/org/broadinstitute/variant/vcf/VCFUtils.java @@ -28,15 +28,9 @@ package org.broadinstitute.variant.vcf; import net.sf.samtools.SAMSequenceDictionary; import net.sf.samtools.SAMSequenceRecord; import org.apache.commons.io.FilenameUtils; -import org.broad.tribble.FeatureCodecHeader; -import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.variant.utils.GeneralUtils; -import org.broadinstitute.variant.utils.Pair; -import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; import java.util.*; public class VCFUtils { @@ -106,21 +100,6 @@ public class VCFUtils { return new HashSet(map.values()); } - public static String rsIDOfFirstRealVariant(List VCs, VariantContext.Type type) { - if ( VCs == null ) - return null; - - String rsID = null; - for ( VariantContext vc : VCs ) { - if ( vc.getType() == type ) { - rsID = vc.getID(); - break; - } - } - - return rsID; - } - /** * Add / replace the contig header lines in the VCFHeader with the in the reference file and master reference dictionary * @@ -198,35 +177,6 @@ public class VCFUtils { return assembly; } - /** - * Read all of the VCF records from source into memory, returning the header and the VariantContexts - * - * @param source the file to read, must be in VCF4 format - * @return - * @throws java.io.IOException - */ - public static Pair> readVCF(final File source) throws IOException { - // read in the features - final List vcs = new ArrayList(); - final VCFCodec codec = new VCFCodec(); - PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); - FeatureCodecHeader header = codec.readHeader(pbs); - pbs.close(); - - pbs = new PositionalBufferedStream(new FileInputStream(source)); - pbs.skip(header.getHeaderEnd()); - - final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue(); - - while ( ! pbs.isDone() ) { - final VariantContext vc = codec.decode(pbs); - if ( vc != null ) - vcs.add(vc); - } - - return new Pair>(vcfHeader, vcs); - } - /** Only displays a warning if warnings are enabled and an identical warning hasn't been already issued */ private static final class HeaderConflictWarner { boolean emitWarnings; diff --git a/public/java/test/org/broadinstitute/sting/WalkerTest.java b/public/java/test/org/broadinstitute/sting/WalkerTest.java index 6c0a18f1d..eec0f653a 100644 --- a/public/java/test/org/broadinstitute/sting/WalkerTest.java +++ b/public/java/test/org/broadinstitute/sting/WalkerTest.java @@ -35,7 +35,7 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.variant.bcf2.BCF2Utils; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.vcf.VCFCodec; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.StingException; diff --git a/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java index a56045165..9d4c562c7 100644 --- a/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/MWUnitTest.java @@ -26,7 +26,7 @@ package org.broadinstitute.sting.utils; import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.variant.utils.Pair; +import org.broadinstitute.sting.utils.collections.Pair; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index 35fa47ede..eb2eebd36 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -36,11 +36,9 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; -import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.VariantContext; import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; import org.broadinstitute.variant.vcf.VCFCodec; -import org.broadinstitute.variant.vcf.VCFHeader; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -252,13 +250,13 @@ public class BandPassActivityProfileUnitTest extends BaseTest { final File file = new File(path); final VCFCodec codec = new VCFCodec(); - final Pair> reader = VariantContextTestProvider.readAllVCs(file, codec); + final VariantContextTestProvider.VariantContextContainer reader = VariantContextTestProvider.readAllVCs(file, codec); final List incRegions = new ArrayList(); final BandPassActivityProfile incProfile = new BandPassActivityProfile(genomeLocParser); final BandPassActivityProfile fullProfile = new BandPassActivityProfile(genomeLocParser); int pos = start; - for ( final VariantContext vc : reader.getSecond() ) { + for ( final VariantContext vc : reader.getVCs() ) { if ( vc == null ) continue; while ( pos < vc.getStart() ) { final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, pos); diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/variant/GATKVariantContextUtilsUnitTest.java similarity index 79% rename from public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/variant/GATKVariantContextUtilsUnitTest.java index 9b24f64e7..6ff052bdc 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/variant/GATKVariantContextUtilsUnitTest.java @@ -1,6 +1,6 @@ /* * 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 @@ -9,10 +9,10 @@ * 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 @@ -23,33 +23,25 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.variantcontext; +package org.broadinstitute.sting.utils.variant; -import net.sf.picard.reference.IndexedFastaSequenceFile; -import org.broadinstitute.variant.VariantBaseTest; -import org.broadinstitute.variant.utils.GeneralUtils; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.variant.variantcontext.*; import org.testng.Assert; import org.testng.annotations.BeforeSuite; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.File; -import java.io.FileNotFoundException; import java.util.*; -public class VariantContextUtilsUnitTest extends VariantBaseTest { +public class GATKVariantContextUtilsUnitTest extends BaseTest { + Allele Aref, T, C, G, Cref, ATC, ATCATC; @BeforeSuite public void setup() { - final File referenceFile = new File(b37KGReference); - try { - IndexedFastaSequenceFile seq = new IndexedFastaSequenceFile(referenceFile); - } - catch(FileNotFoundException ex) { - throw new RuntimeException(referenceFile.getAbsolutePath(),ex); - } - // alleles Aref = Allele.create("A", true); Cref = Allele.create("C", true); @@ -186,10 +178,10 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { final List priority = vcs2priority(inputs); - final VariantContext merged = VariantContextUtils.simpleMerge( + final VariantContext merged = GATKVariantContextUtils.simpleMerge( inputs, priority, - VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.PRIORITIZE, false, false, "set", false, false); + GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, false, false, "set", false, false); Assert.assertEquals(merged.getAlleles(), cfg.expected); } @@ -244,10 +236,10 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { inputs.add(new VariantContextBuilder(snpVC1).id(id).make()); } - final VariantContext merged = VariantContextUtils.simpleMerge( + final VariantContext merged = GATKVariantContextUtils.simpleMerge( inputs, null, - VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.UNSORTED, false, false, "set", false, false); + GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.UNSORTED, false, false, "set", false, false); Assert.assertEquals(merged.getID(), cfg.expected); } @@ -261,14 +253,14 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { List inputs; VariantContext expected; String setExpected; - VariantContextUtils.FilteredRecordMergeType type; + GATKVariantContextUtils.FilteredRecordMergeType type; private MergeFilteredTest(String name, VariantContext input1, VariantContext input2, VariantContext expected, String setExpected) { - this(name, input1, input2, expected, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, setExpected); + this(name, input1, input2, expected, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, setExpected); } - private MergeFilteredTest(String name, VariantContext input1, VariantContext input2, VariantContext expected, VariantContextUtils.FilteredRecordMergeType type, String setExpected) { + private MergeFilteredTest(String name, VariantContext input1, VariantContext input2, VariantContext expected, GATKVariantContextUtils.FilteredRecordMergeType type, String setExpected) { super(MergeFilteredTest.class, name); LinkedList all = new LinkedList(Arrays.asList(input1, input2)); this.expected = expected; @@ -288,66 +280,66 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), - VariantContextUtils.MERGE_INTERSECTION); + GATKVariantContextUtils.MERGE_INTERSECTION); new MergeFilteredTest("noFilters", makeVC("1", Arrays.asList(Aref, T), "."), makeVC("2", Arrays.asList(Aref, T), "."), makeVC("3", Arrays.asList(Aref, T), "."), - VariantContextUtils.MERGE_INTERSECTION); + GATKVariantContextUtils.MERGE_INTERSECTION); new MergeFilteredTest("oneFiltered", makeVC("1", Arrays.asList(Aref, T), "."), makeVC("2", Arrays.asList(Aref, T), "FAIL"), makeVC("3", Arrays.asList(Aref, T), "."), - String.format("1-%s2", VariantContextUtils.MERGE_FILTER_PREFIX)); + String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX)); new MergeFilteredTest("onePassOneFail", makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), makeVC("2", Arrays.asList(Aref, T), "FAIL"), makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), - String.format("1-%s2", VariantContextUtils.MERGE_FILTER_PREFIX)); + String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX)); new MergeFilteredTest("AllFiltered", makeVC("1", Arrays.asList(Aref, T), "FAIL"), makeVC("2", Arrays.asList(Aref, T), "FAIL"), makeVC("3", Arrays.asList(Aref, T), "FAIL"), - VariantContextUtils.MERGE_FILTER_IN_ALL); + GATKVariantContextUtils.MERGE_FILTER_IN_ALL); // test ALL vs. ANY new MergeFilteredTest("FailOneUnfiltered", makeVC("1", Arrays.asList(Aref, T), "FAIL"), makeVC("2", Arrays.asList(Aref, T), "."), makeVC("3", Arrays.asList(Aref, T), "."), - VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - String.format("%s1-2", VariantContextUtils.MERGE_FILTER_PREFIX)); + GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + String.format("%s1-2", GATKVariantContextUtils.MERGE_FILTER_PREFIX)); new MergeFilteredTest("OneFailAllUnfilteredArg", makeVC("1", Arrays.asList(Aref, T), "FAIL"), makeVC("2", Arrays.asList(Aref, T), "."), makeVC("3", Arrays.asList(Aref, T), "FAIL"), - VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ALL_UNFILTERED, - String.format("%s1-2", VariantContextUtils.MERGE_FILTER_PREFIX)); + GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ALL_UNFILTERED, + String.format("%s1-2", GATKVariantContextUtils.MERGE_FILTER_PREFIX)); // test excluding allele in filtered record new MergeFilteredTest("DontIncludeAlleleOfFilteredRecords", makeVC("1", Arrays.asList(Aref, T), "."), makeVC("2", Arrays.asList(Aref, T), "FAIL"), makeVC("3", Arrays.asList(Aref, T), "."), - String.format("1-%s2", VariantContextUtils.MERGE_FILTER_PREFIX)); + String.format("1-%s2", GATKVariantContextUtils.MERGE_FILTER_PREFIX)); // promotion of site from unfiltered to PASSES new MergeFilteredTest("UnfilteredPlusPassIsPass", makeVC("1", Arrays.asList(Aref, T), "."), makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), makeVC("3", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS), - VariantContextUtils.MERGE_INTERSECTION); + GATKVariantContextUtils.MERGE_INTERSECTION); new MergeFilteredTest("RefInAll", makeVC("1", Arrays.asList(Aref), VariantContext.PASSES_FILTERS), makeVC("2", Arrays.asList(Aref), VariantContext.PASSES_FILTERS), makeVC("3", Arrays.asList(Aref), VariantContext.PASSES_FILTERS), - VariantContextUtils.MERGE_REF_IN_ALL); + GATKVariantContextUtils.MERGE_REF_IN_ALL); new MergeFilteredTest("RefInOne", makeVC("1", Arrays.asList(Aref), VariantContext.PASSES_FILTERS), @@ -361,8 +353,8 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { @Test(dataProvider = "mergeFiltered") public void testMergeFiltered(MergeFilteredTest cfg) { final List priority = vcs2priority(cfg.inputs); - final VariantContext merged = VariantContextUtils.simpleMerge( - cfg.inputs, priority, cfg.type, VariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false); + final VariantContext merged = GATKVariantContextUtils.simpleMerge( + cfg.inputs, priority, cfg.type, GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false); // test alleles are equal Assert.assertEquals(merged.getAlleles(), cfg.expected.getAlleles()); @@ -487,9 +479,9 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { @Test(dataProvider = "mergeGenotypes") public void testMergeGenotypes(MergeGenotypesTest cfg) { - final VariantContext merged = VariantContextUtils.simpleMerge( - cfg.inputs, cfg.priority, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false); + final VariantContext merged = GATKVariantContextUtils.simpleMerge( + cfg.inputs, cfg.priority, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, true, false, "set", false, false); // test alleles are equal Assert.assertEquals(merged.getAlleles(), cfg.expected.getAlleles()); @@ -528,9 +520,9 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { final VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), makeG("s1", Aref, T, -1)); final VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), makeG("s1", Aref, T, -2)); - final VariantContext merged = VariantContextUtils.simpleMerge( - Arrays.asList(vc1, vc2), null, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.UNIQUIFY, false, false, "set", false, false); + final VariantContext merged = GATKVariantContextUtils.simpleMerge( + Arrays.asList(vc1, vc2), null, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.UNIQUIFY, false, false, "set", false, false); // test genotypes Assert.assertEquals(merged.getSampleNames(), new HashSet(Arrays.asList("s1.1", "s1.2"))); @@ -561,12 +553,12 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { VariantContext vc1 = makeVC("1", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS); VariantContext vc2 = makeVC("2", Arrays.asList(Aref, T), VariantContext.PASSES_FILTERS); - final VariantContext merged = VariantContextUtils.simpleMerge( - Arrays.asList(vc1, vc2), priority, VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.PRIORITIZE, annotate, false, set, false, false); + final VariantContext merged = GATKVariantContextUtils.simpleMerge( + Arrays.asList(vc1, vc2), priority, GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.PRIORITIZE, annotate, false, set, false, false); if ( annotate ) - Assert.assertEquals(merged.getAttribute(set), VariantContextUtils.MERGE_INTERSECTION); + Assert.assertEquals(merged.getAttribute(set), GATKVariantContextUtils.MERGE_INTERSECTION); else Assert.assertFalse(merged.hasAttribute(set)); } @@ -583,78 +575,6 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { return priority; } - - // -------------------------------------------------------------------------------- - // - // Test repeats - // - // -------------------------------------------------------------------------------- - - private class RepeatDetectorTest extends TestDataProvider { - String ref; - boolean isTrueRepeat; - VariantContext vc; - - private RepeatDetectorTest(boolean isTrueRepeat, String ref, String refAlleleString, String ... altAlleleStrings) { - super(RepeatDetectorTest.class); - this.isTrueRepeat = isTrueRepeat; - this.ref = ref; - - List alleles = new LinkedList(); - final Allele refAllele = Allele.create(refAlleleString, true); - alleles.add(refAllele); - for ( final String altString: altAlleleStrings) { - final Allele alt = Allele.create(altString, false); - alleles.add(alt); - } - - VariantContextBuilder builder = new VariantContextBuilder("test", "chr1", 1, refAllele.length(), alleles); - this.vc = builder.make(); - } - - public String toString() { - return String.format("%s refBases=%s trueRepeat=%b vc=%s", super.toString(), ref, isTrueRepeat, vc); - } - } - - @DataProvider(name = "RepeatDetectorTest") - public Object[][] makeRepeatDetectorTest() { - new RepeatDetectorTest(true, "NAAC", "N", "NA"); - new RepeatDetectorTest(true, "NAAC", "NA", "N"); - new RepeatDetectorTest(false, "NAAC", "NAA", "N"); - new RepeatDetectorTest(false, "NAAC", "N", "NC"); - new RepeatDetectorTest(false, "AAC", "A", "C"); - - // running out of ref bases => false - new RepeatDetectorTest(false, "NAAC", "N", "NCAGTA"); - - // complex repeats - new RepeatDetectorTest(true, "NATATATC", "N", "NAT"); - new RepeatDetectorTest(true, "NATATATC", "N", "NATA"); - new RepeatDetectorTest(true, "NATATATC", "N", "NATAT"); - new RepeatDetectorTest(true, "NATATATC", "NAT", "N"); - new RepeatDetectorTest(false, "NATATATC", "NATA", "N"); - new RepeatDetectorTest(false, "NATATATC", "NATAT", "N"); - - // multi-allelic - new RepeatDetectorTest(true, "NATATATC", "N", "NAT", "NATAT"); - new RepeatDetectorTest(true, "NATATATC", "N", "NAT", "NATA"); - new RepeatDetectorTest(true, "NATATATC", "NAT", "N", "NATAT"); - new RepeatDetectorTest(true, "NATATATC", "NAT", "N", "NATA"); // two As - new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NATC"); // false - new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NCC"); // false - new RepeatDetectorTest(false, "NATATATC", "NAT", "NATAT", "NCC"); // false - - return RepeatDetectorTest.getTests(RepeatDetectorTest.class); - } - - @Test(dataProvider = "RepeatDetectorTest") - public void testRepeatDetectorTest(RepeatDetectorTest cfg) { - - // test alleles are equal - Assert.assertEquals(VariantContextUtils.isTandemRepeat(cfg.vc, cfg.ref.getBytes()), cfg.isTrueRepeat); - } - // -------------------------------------------------------------------------------- // // basic allele clipping test @@ -698,10 +618,11 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { @Test(dataProvider = "ReverseClippingPositionTestProvider") public void testReverseClippingPositionTestProvider(ReverseClippingPositionTestProvider cfg) { - int result = VariantContextUtils.computeReverseClipping(cfg.alleles, cfg.ref.getBytes(), 0, false); + int result = GATKVariantContextUtils.computeReverseClipping(cfg.alleles, cfg.ref.getBytes(), 0, false); Assert.assertEquals(result, cfg.expectedClip); } + // -------------------------------------------------------------------------------- // // test splitting into bi-allelics @@ -776,7 +697,7 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { @Test(dataProvider = "SplitBiallelics") public void testSplitBiallelicsNoGenotypes(final VariantContext vc, final List expectedBiallelics) { - final List biallelics = VariantContextUtils.splitVariantContextToBiallelics(vc); + final List biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vc); Assert.assertEquals(biallelics.size(), expectedBiallelics.size()); for ( int i = 0; i < biallelics.size(); i++ ) { final VariantContext actual = biallelics.get(i); @@ -790,14 +711,14 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { final List genotypes = new ArrayList(); int sampleI = 0; - for ( final List alleles : GeneralUtils.makePermutations(vc.getAlleles(), 2, true) ) { + for ( final List alleles : Utils.makePermutations(vc.getAlleles(), 2, true) ) { genotypes.add(GenotypeBuilder.create("sample" + sampleI++, alleles)); } genotypes.add(GenotypeBuilder.createMissing("missing", 2)); final VariantContext vcWithGenotypes = new VariantContextBuilder(vc).genotypes(genotypes).make(); - final List biallelics = VariantContextUtils.splitVariantContextToBiallelics(vcWithGenotypes); + final List biallelics = GATKVariantContextUtils.splitVariantContextToBiallelics(vcWithGenotypes); for ( int i = 0; i < biallelics.size(); i++ ) { final VariantContext actual = biallelics.get(i); Assert.assertEquals(actual.getNSamples(), vcWithGenotypes.getNSamples()); // not dropping any samples @@ -812,4 +733,159 @@ public class VariantContextUtilsUnitTest extends VariantBaseTest { } } } -} \ No newline at end of file + + + // -------------------------------------------------------------------------------- + // + // Test repeats + // + // -------------------------------------------------------------------------------- + + private class RepeatDetectorTest extends TestDataProvider { + String ref; + boolean isTrueRepeat; + VariantContext vc; + + private RepeatDetectorTest(boolean isTrueRepeat, String ref, String refAlleleString, String ... altAlleleStrings) { + super(RepeatDetectorTest.class); + this.isTrueRepeat = isTrueRepeat; + this.ref = ref; + + List alleles = new LinkedList(); + final Allele refAllele = Allele.create(refAlleleString, true); + alleles.add(refAllele); + for ( final String altString: altAlleleStrings) { + final Allele alt = Allele.create(altString, false); + alleles.add(alt); + } + + VariantContextBuilder builder = new VariantContextBuilder("test", "chr1", 1, refAllele.length(), alleles); + this.vc = builder.make(); + } + + public String toString() { + return String.format("%s refBases=%s trueRepeat=%b vc=%s", super.toString(), ref, isTrueRepeat, vc); + } + } + + @DataProvider(name = "RepeatDetectorTest") + public Object[][] makeRepeatDetectorTest() { + new RepeatDetectorTest(true, "NAAC", "N", "NA"); + new RepeatDetectorTest(true, "NAAC", "NA", "N"); + new RepeatDetectorTest(false, "NAAC", "NAA", "N"); + new RepeatDetectorTest(false, "NAAC", "N", "NC"); + new RepeatDetectorTest(false, "AAC", "A", "C"); + + // running out of ref bases => false + new RepeatDetectorTest(false, "NAAC", "N", "NCAGTA"); + + // complex repeats + new RepeatDetectorTest(true, "NATATATC", "N", "NAT"); + new RepeatDetectorTest(true, "NATATATC", "N", "NATA"); + new RepeatDetectorTest(true, "NATATATC", "N", "NATAT"); + new RepeatDetectorTest(true, "NATATATC", "NAT", "N"); + new RepeatDetectorTest(false, "NATATATC", "NATA", "N"); + new RepeatDetectorTest(false, "NATATATC", "NATAT", "N"); + + // multi-allelic + new RepeatDetectorTest(true, "NATATATC", "N", "NAT", "NATAT"); + new RepeatDetectorTest(true, "NATATATC", "N", "NAT", "NATA"); + new RepeatDetectorTest(true, "NATATATC", "NAT", "N", "NATAT"); + new RepeatDetectorTest(true, "NATATATC", "NAT", "N", "NATA"); // two As + new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NATC"); // false + new RepeatDetectorTest(false, "NATATATC", "NAT", "N", "NCC"); // false + new RepeatDetectorTest(false, "NATATATC", "NAT", "NATAT", "NCC"); // false + + return RepeatDetectorTest.getTests(RepeatDetectorTest.class); + } + + @Test(dataProvider = "RepeatDetectorTest") + public void testRepeatDetectorTest(RepeatDetectorTest cfg) { + + // test alleles are equal + Assert.assertEquals(GATKVariantContextUtils.isTandemRepeat(cfg.vc, cfg.ref.getBytes()), cfg.isTrueRepeat); + } + + @Test + public void testRepeatAllele() { + Allele nullR = Allele.create("A", true); + Allele nullA = Allele.create("A", false); + Allele atc = Allele.create("AATC", false); + Allele atcatc = Allele.create("AATCATC", false); + Allele ccccR = Allele.create("ACCCC", true); + Allele cc = Allele.create("ACC", false); + Allele cccccc = Allele.create("ACCCCCC", false); + Allele gagaR = Allele.create("AGAGA", true); + Allele gagagaga = Allele.create("AGAGAGAGA", false); + + // - / ATC [ref] from 20-22 + String delLoc = "chr1"; + int delLocStart = 20; + int delLocStop = 22; + + // - [ref] / ATC from 20-20 + String insLoc = "chr1"; + int insLocStart = 20; + int insLocStop = 20; + + Pair,byte[]> result; + byte[] refBytes = "TATCATCATCGGA".getBytes(); + + Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes(), true),4); + Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes(), true),0); + Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes(), true),1); + Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes(), true),1); + Assert.assertEquals(GATKVariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes(), true),2); + + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3); + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1); + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACAC".getBytes()),7); + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CACACA".getBytes()),2); + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("CATGCATG".getBytes()),4); + Assert.assertEquals(GATKVariantContextUtils.findRepeatedSubstring("AATAATA".getBytes()),7); + + + // A*,ATC, context = ATC ATC ATC : (ATC)3 -> (ATC)4 + VariantContext vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStop, Arrays.asList(nullR,atc)).make(); + result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + Assert.assertEquals(result.getFirst().toArray()[0],3); + Assert.assertEquals(result.getFirst().toArray()[1],4); + Assert.assertEquals(result.getSecond().length,3); + + // ATC*,A,ATCATC + vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+3, Arrays.asList(Allele.create("AATC", true),nullA,atcatc)).make(); + result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + Assert.assertEquals(result.getFirst().toArray()[0],3); + Assert.assertEquals(result.getFirst().toArray()[1],2); + Assert.assertEquals(result.getFirst().toArray()[2],4); + Assert.assertEquals(result.getSecond().length,3); + + // simple non-tandem deletion: CCCC*, - + refBytes = "TCCCCCCCCATG".getBytes(); + vc = new VariantContextBuilder("foo", delLoc, 10, 14, Arrays.asList(ccccR,nullA)).make(); + result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + Assert.assertEquals(result.getFirst().toArray()[0],8); + Assert.assertEquals(result.getFirst().toArray()[1],4); + Assert.assertEquals(result.getSecond().length,1); + + // CCCC*,CC,-,CCCCCC, context = CCC: (C)7 -> (C)5,(C)3,(C)9 + refBytes = "TCCCCCCCAGAGAGAG".getBytes(); + vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(ccccR,cc, nullA,cccccc)).make(); + result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + Assert.assertEquals(result.getFirst().toArray()[0],7); + Assert.assertEquals(result.getFirst().toArray()[1],5); + Assert.assertEquals(result.getFirst().toArray()[2],3); + Assert.assertEquals(result.getFirst().toArray()[3],9); + Assert.assertEquals(result.getSecond().length,1); + + // GAGA*,-,GAGAGAGA + refBytes = "TGAGAGAGAGATTT".getBytes(); + vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(gagaR, nullA,gagagaga)).make(); + result = GATKVariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); + Assert.assertEquals(result.getFirst().toArray()[0],5); + Assert.assertEquals(result.getFirst().toArray()[1],3); + Assert.assertEquals(result.getFirst().toArray()[2],7); + Assert.assertEquals(result.getSecond().length,2); + + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java b/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java index 8a6d2138e..51a47d86d 100644 --- a/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java +++ b/public/java/test/org/broadinstitute/sting/utils/variant/VariantContextBenchmark.java @@ -231,9 +231,9 @@ public class VariantContextBenchmark extends SimpleBenchmark { toMerge.add(new VariantContextBuilder(vc).genotypes(gc).make()); } - VariantContextUtils.simpleMerge(toMerge, null, - VariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, - VariantContextUtils.GenotypeMergeType.UNSORTED, + GATKVariantContextUtils.simpleMerge(toMerge, null, + GATKVariantContextUtils.FilteredRecordMergeType.KEEP_IF_ANY_UNFILTERED, + GATKVariantContextUtils.GenotypeMergeType.UNSORTED, true, false, "set", false, true); } }; diff --git a/public/java/test/org/broadinstitute/variant/VariantBaseTest.java b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java index be70b22e6..0d7d5a82e 100644 --- a/public/java/test/org/broadinstitute/variant/VariantBaseTest.java +++ b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java @@ -1,3 +1,28 @@ +/* +* 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.variant; import org.testng.Assert; diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java index d739e4aa5..4c948e8e2 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextTestProvider.java @@ -32,7 +32,6 @@ import org.broadinstitute.variant.VariantBaseTest; import org.broadinstitute.variant.bcf2.BCF2Codec; import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; -import org.broadinstitute.variant.utils.Pair; import org.broadinstitute.variant.variantcontext.writer.Options; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import org.testng.Assert; @@ -74,6 +73,24 @@ public class VariantContextTestProvider { } } + public static class VariantContextContainer { + private VCFHeader header; + private Iterable vcs; + + public VariantContextContainer( VCFHeader header, Iterable vcs ) { + this.header = header; + this.vcs = vcs; + } + + public VCFHeader getHeader() { + return header; + } + + public Iterable getVCs() { + return vcs; + } + } + public abstract static class VariantContextIOTest { public String toString() { return "VariantContextIOTest:" + getExtension(); @@ -150,15 +167,15 @@ public class VariantContextTestProvider { if ( ENABLE_SOURCE_VCF_TESTS ) { for ( final File file : testSourceVCFs ) { VCFCodec codec = new VCFCodec(); - Pair> x = readAllVCs( file, codec ); + VariantContextContainer x = readAllVCs( file, codec ); List fullyDecoded = new ArrayList(); - for ( final VariantContext raw : x.getSecond() ) { + for ( final VariantContext raw : x.getVCs() ) { if ( raw != null ) - fullyDecoded.add(raw.fullyDecode(x.getFirst(), false)); + fullyDecoded.add(raw.fullyDecode(x.getHeader(), false)); } - TEST_DATAs.add(new VariantContextTestData(x.getFirst(), fullyDecoded)); + TEST_DATAs.add(new VariantContextTestData(x.getHeader(), fullyDecoded)); } } } @@ -616,8 +633,8 @@ public class VariantContextTestProvider { writeVCsToFile(writer, header, data.vcs); // ensure writing of expected == actual - final Pair> p = readAllVCs(tmpFile, tester.makeCodec()); - final Iterable actual = p.getSecond(); + final VariantContextContainer p = readAllVCs(tmpFile, tester.makeCodec()); + final Iterable actual = p.getVCs(); int i = 0; for ( final VariantContext readVC : actual ) { @@ -655,14 +672,14 @@ public class VariantContextTestProvider { writeVCsToFile(writer, header, vcs); // ensure writing of expected == actual - final Pair> p = readAllVCs(tmpFile, tester.makeCodec()); - final Iterable actual = p.getSecond(); + final VariantContextContainer p = readAllVCs(tmpFile, tester.makeCodec()); + final Iterable actual = p.getVCs(); assertEquals(actual, expected); if ( recurse ) { // if we are doing a recursive test, grab a fresh iterator over the written values - final Iterable read = readAllVCs(tmpFile, tester.makeCodec()).getSecond(); - testReaderWriter(tester, p.getFirst(), expected, read, false); + final Iterable read = readAllVCs(tmpFile, tester.makeCodec()).getVCs(); + testReaderWriter(tester, p.getHeader(), expected, read, false); } } @@ -683,7 +700,7 @@ public class VariantContextTestProvider { * @return * @throws IOException */ - public final static Pair> readAllVCs( final File source, final FeatureCodec codec ) throws IOException { + public final static VariantContextContainer readAllVCs( final File source, final FeatureCodec codec ) throws IOException { // read in the features PositionalBufferedStream pbs = new PositionalBufferedStream(new FileInputStream(source)); FeatureCodecHeader header = codec.readHeader(pbs); @@ -693,7 +710,7 @@ public class VariantContextTestProvider { pbs.skip(header.getHeaderEnd()); final VCFHeader vcfHeader = (VCFHeader)header.getHeaderValue(); - return new Pair>(vcfHeader, new VCIterable(pbs, codec, vcfHeader)); + return new VariantContextContainer(vcfHeader, new VCIterable(pbs, codec, vcfHeader)); } public static class VCIterable implements Iterable, Iterator { @@ -738,10 +755,10 @@ public class VariantContextTestProvider { } public static void assertVCFandBCFFilesAreTheSame(final File vcfFile, final File bcfFile) throws IOException { - final Pair> vcfData = readAllVCs(vcfFile, new VCFCodec()); - final Pair> bcfData = readAllVCs(bcfFile, new BCF2Codec()); - assertEquals(bcfData.getFirst(), vcfData.getFirst()); - assertEquals(bcfData.getSecond(), vcfData.getSecond()); + final VariantContextContainer vcfData = readAllVCs(vcfFile, new VCFCodec()); + final VariantContextContainer bcfData = readAllVCs(bcfFile, new BCF2Codec()); + assertEquals(bcfData.getHeader(), vcfData.getHeader()); + assertEquals(bcfData.getVCs(), vcfData.getVCs()); } public static void assertEquals(final Iterable actual, final Iterable expected) { diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java index 25e9878ae..103c8ab3b 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/VariantContextUnitTest.java @@ -28,9 +28,7 @@ package org.broadinstitute.variant.variantcontext; // the imports for unit testing. - import org.broadinstitute.variant.VariantBaseTest; -import org.broadinstitute.variant.utils.Pair; import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -484,78 +482,6 @@ public class VariantContextUnitTest extends VariantBaseTest { Assert.assertNotNull(vc.getFiltersMaybeNull()); } - @Test - public void testRepeatAllele() { - Allele nullR = Allele.create("A", true); - Allele nullA = Allele.create("A", false); - Allele atc = Allele.create("AATC", false); - Allele atcatc = Allele.create("AATCATC", false); - Allele ccccR = Allele.create("ACCCC", true); - Allele cc = Allele.create("ACC", false); - Allele cccccc = Allele.create("ACCCCCC", false); - Allele gagaR = Allele.create("AGAGA", true); - Allele gagagaga = Allele.create("AGAGAGAGA", false); - - Pair,byte[]> result; - byte[] refBytes = "TATCATCATCGGA".getBytes(); - - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("ATG".getBytes(), "ATGATGATGATG".getBytes(), true),4); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("G".getBytes(), "ATGATGATGATG".getBytes(), true),0); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("T".getBytes(), "T".getBytes(), true),1); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("AT".getBytes(), "ATGATGATCATG".getBytes(), true),1); - Assert.assertEquals(VariantContextUtils.findNumberofRepetitions("CCC".getBytes(), "CCCCCCCC".getBytes(), true),2); - - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("ATG".getBytes()),3); - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("AAA".getBytes()),1); - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CACACAC".getBytes()),7); - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CACACA".getBytes()),2); - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("CATGCATG".getBytes()),4); - Assert.assertEquals(VariantContextUtils.findRepeatedSubstring("AATAATA".getBytes()),7); - - - // A*,ATC, context = ATC ATC ATC : (ATC)3 -> (ATC)4 - VariantContext vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStop, Arrays.asList(nullR,atc)).make(); - result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); - Assert.assertEquals(result.getFirst().toArray()[0],3); - Assert.assertEquals(result.getFirst().toArray()[1],4); - Assert.assertEquals(result.getSecond().length,3); - - // ATC*,A,ATCATC - vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+3, Arrays.asList(Allele.create("AATC", true),nullA,atcatc)).make(); - result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); - Assert.assertEquals(result.getFirst().toArray()[0],3); - Assert.assertEquals(result.getFirst().toArray()[1],2); - Assert.assertEquals(result.getFirst().toArray()[2],4); - Assert.assertEquals(result.getSecond().length,3); - - // simple non-tandem deletion: CCCC*, - - refBytes = "TCCCCCCCCATG".getBytes(); - vc = new VariantContextBuilder("foo", delLoc, 10, 14, Arrays.asList(ccccR,nullA)).make(); - result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); - Assert.assertEquals(result.getFirst().toArray()[0],8); - Assert.assertEquals(result.getFirst().toArray()[1],4); - Assert.assertEquals(result.getSecond().length,1); - - // CCCC*,CC,-,CCCCCC, context = CCC: (C)7 -> (C)5,(C)3,(C)9 - refBytes = "TCCCCCCCAGAGAGAG".getBytes(); - vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(ccccR,cc, nullA,cccccc)).make(); - result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); - Assert.assertEquals(result.getFirst().toArray()[0],7); - Assert.assertEquals(result.getFirst().toArray()[1],5); - Assert.assertEquals(result.getFirst().toArray()[2],3); - Assert.assertEquals(result.getFirst().toArray()[3],9); - Assert.assertEquals(result.getSecond().length,1); - - // GAGA*,-,GAGAGAGA - refBytes = "TGAGAGAGAGATTT".getBytes(); - vc = new VariantContextBuilder("foo", insLoc, insLocStart, insLocStart+4, Arrays.asList(gagaR, nullA,gagagaga)).make(); - result = VariantContextUtils.getNumTandemRepeatUnits(vc, refBytes); - Assert.assertEquals(result.getFirst().toArray()[0],5); - Assert.assertEquals(result.getFirst().toArray()[1],3); - Assert.assertEquals(result.getFirst().toArray()[2],7); - Assert.assertEquals(result.getSecond().length,2); - - } @Test public void testGetGenotypeCounts() { List alleles = Arrays.asList(Aref, T); From 29fd536c282ce97b64b43886b103d872ca2abd9d Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Tue, 29 Jan 2013 17:27:53 -0500 Subject: [PATCH 132/188] Updating licenses manually Please check that your commit hook is properly pointing at ../../private/shell/pre-commit Conflicts: public/java/test/org/broadinstitute/variant/VariantBaseTest.java --- .../covariates/RepeatCovariate.java | 30 ++++----- .../covariates/RepeatUnitCovariate.java | 30 ++++----- .../reducereads/SlidingWindowUnitTest.java | 65 ++++++++++++------- .../RepeatCovariatesUnitTest.java | 31 ++++----- .../sting/utils/SWPairwiseAlignment.java | 50 +++++++------- .../variant/VariantBaseTest.java | 6 +- 6 files changed, 117 insertions(+), 95 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java index 546bd6ac8..b6b954c4a 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -1,45 +1,45 @@ /* * By downloading the PROGRAM you agree to the following terms of use: -* +* * BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* +* * This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* +* * WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and * WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. * NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* +* * 1. DEFINITIONS * 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* +* * 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. * The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. * 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY * LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. * Copyright 2012 Broad Institute, Inc. * Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. * LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* +* * 4. INDEMNIFICATION * LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* +* * 5. NO REPRESENTATIONS OR WARRANTIES * THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. * IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* +* * 6. ASSIGNMENT * This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* +* * 7. MISCELLANEOUS * 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. * 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. * 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. * 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. * 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. */ diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java index b32feb9a3..ef0d3fc62 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatUnitCovariate.java @@ -1,45 +1,45 @@ /* * By downloading the PROGRAM you agree to the following terms of use: -* +* * BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* +* * This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* +* * WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and * WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. * NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* +* * 1. DEFINITIONS * 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* +* * 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. * The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. * 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY * LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. * Copyright 2012 Broad Institute, Inc. * Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. * LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* +* * 4. INDEMNIFICATION * LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* +* * 5. NO REPRESENTATIONS OR WARRANTIES * THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. * IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* +* * 6. ASSIGNMENT * This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* +* * 7. MISCELLANEOUS * 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. * 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. * 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. * 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. * 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. */ diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java index cfb8c53b4..3d3c4ad24 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java @@ -1,26 +1,47 @@ /* -* 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. +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. */ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java index 7ded176bb..c0cb2d7b6 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java @@ -1,48 +1,49 @@ /* * By downloading the PROGRAM you agree to the following terms of use: -* +* * BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* +* * This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* +* * WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and * WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. * NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* +* * 1. DEFINITIONS * 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* +* * 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. * The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. * 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY * LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. * Copyright 2012 Broad Institute, Inc. * Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. * LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* +* * 4. INDEMNIFICATION * LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* +* * 5. NO REPRESENTATIONS OR WARRANTIES * THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. * IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* +* * 6. ASSIGNMENT * This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* +* * 7. MISCELLANEOUS * 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. * 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. * 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. * 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. * 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. */ + package org.broadinstitute.sting.utils.recalibration; import com.google.java.contract.Requires; diff --git a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java index e2edf7421..7bd937af9 100644 --- a/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java +++ b/public/java/src/org/broadinstitute/sting/utils/SWPairwiseAlignment.java @@ -1,28 +1,28 @@ -/* -* 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. -*/ - +/* +* 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.utils; import net.sf.samtools.Cigar; diff --git a/public/java/test/org/broadinstitute/variant/VariantBaseTest.java b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java index 0d7d5a82e..6cec4d40b 100644 --- a/public/java/test/org/broadinstitute/variant/VariantBaseTest.java +++ b/public/java/test/org/broadinstitute/variant/VariantBaseTest.java @@ -1,6 +1,6 @@ /* * 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 @@ -9,10 +9,10 @@ * 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 From 6449c320b482132bf1b3c29aa744607f488af781 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Tue, 29 Jan 2013 20:30:36 -0500 Subject: [PATCH 133/188] Fix the CachingIndexedFastaSequenceFileUnitTest BaseUtils.convertIUPACtoN() no longer throws a UserException, since it's in org.broadinstitute.variant --- .../utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java index 0c1b5b069..b65811103 100644 --- a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java @@ -252,7 +252,7 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { Assert.assertEquals(changingNs, preservingNs + 4); } - @Test(enabled = true, expectedExceptions = {UserException.class}) + @Test(enabled = true, expectedExceptions = {IllegalStateException.class}) public void testFailOnBadBase() throws FileNotFoundException, InterruptedException { final String testFasta = privateTestDir + "problematicFASTA.fasta"; final CachingIndexedFastaSequenceFile fasta = new CachingIndexedFastaSequenceFile(new File(testFasta)); From 3d9a83c7595a4519022611f128e1adc04e2901ce Mon Sep 17 00:00:00 2001 From: Mauricio Carneiro Date: Tue, 29 Jan 2013 22:36:31 -0500 Subject: [PATCH 135/188] BaseCoverageDistributions should be 'by reference' otherwise we miss all the 0 coverage spots. --- .../walkers/diagnostics/targets/BaseCoverageDistribution.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java index a12008eb4..281c1c55d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java @@ -51,6 +51,8 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.report.GATKReport; +import org.broadinstitute.sting.gatk.walkers.By; +import org.broadinstitute.sting.gatk.walkers.DataSource; import org.broadinstitute.sting.gatk.walkers.LocusWalker; import java.io.PrintStream; @@ -62,6 +64,7 @@ import java.util.Map; * Date: 1/27/13 * Time: 11:16 AM */ +@By(DataSource.REFERENCE) public class BaseCoverageDistribution extends LocusWalker> { @Output(required = true) private PrintStream out; From 92c5635e196d3665e246782477634e4e4a6955bc Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Mon, 28 Jan 2013 11:53:43 -0500 Subject: [PATCH 136/188] Cleanup, document, and unit test ActiveRegion -- All functions tested. In the testing / review I discovered several bugs in the ActiveRegion routines that manipulate reads. New version should be correct -- Enforce correct ordering of supporting states in constructor -- Enforce read ordering when adding reads to an active region in add -- Fix bug in HaplotypeCaller map with new updating read spans. Now get the full span before clipping down reads in map, so that variants are correctly placed w.r.t. the full reference sequence -- Encapsulate isActive field with an accessor function -- Make sure that all state lists are unmodifiable, and that the docs are clear about this -- ActiveRegion equalsExceptReads is for testing only, so make it package protected -- ActiveRegion.hardClipToRegion must resort reads as they can become out of order -- Previous version of HC clipped reads but, due to clipping, these reads could no longer overlap the active region. The old version of HC kept these reads, while the enforced contracts on the ActiveRegion detected this was a problem and those reads are removed. Has a minor impact on PLs and RankSumTest values -- Updating HaplotypeCaller MD5s to reflect changes to ActiveRegions read inclusion policy --- .../targets/FindCoveredIntervals.java | 2 +- .../haplotypecaller/HaplotypeCaller.java | 32 +- .../HaplotypeCallerIntegrationTest.java | 24 +- .../traversals/TraverseActiveRegions.java | 6 +- .../utils/activeregion/ActiveRegion.java | 343 +++++++++++++++--- .../sting/utils/sam/ArtificialSAMUtils.java | 13 + .../activeregion/ActiveRegionUnitTest.java | 223 ++++++++++++ .../activeregion/ActivityProfileUnitTest.java | 2 +- .../BandPassActivityProfileUnitTest.java | 4 +- 9 files changed, 569 insertions(+), 80 deletions(-) create mode 100644 public/java/test/org/broadinstitute/sting/utils/activeregion/ActiveRegionUnitTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java index 3712a8e51..ac028d860 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java @@ -85,7 +85,7 @@ public class FindCoveredIntervals extends ActiveRegionWalker { @Override public GenomeLoc map(final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion, final RefMetaDataTracker tracker) { - if (activeRegion.isActive) + if (activeRegion.isActive()) return activeRegion.getLocation(); else return null; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 8b3eb9f1b..a27eaac8e 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -463,15 +463,19 @@ public class HaplotypeCaller extends ActiveRegionWalker implem allelesToGenotype.removeAll( activeAllelesToGenotype ); } - if( !activeRegion.isActive ) { return 0; } // Not active so nothing to do! + if( !activeRegion.isActive()) { return 0; } // Not active so nothing to do! if( activeRegion.size() == 0 && UG_engine.getUAC().GenotypingMode != GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ) { return 0; } // No reads here so nothing to do! if( UG_engine.getUAC().GenotypingMode == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES && activeAllelesToGenotype.isEmpty() ) { return 0; } // No alleles found in this region so nothing to do! finalizeActiveRegion( activeRegion ); // merge overlapping fragments, clip adapter and low qual tails + + // note this operation must be performed before we clip the reads down, as this must correspond to the full reference region + final GenomeLoc fullSpanBeforeClipping = getPaddedLoc(activeRegion); + final Haplotype referenceHaplotype = new Haplotype(activeRegion.getActiveRegionReference(referenceReader), true); // Create the reference haplotype which is the bases from the reference that make up the active region final byte[] fullReferenceWithPadding = activeRegion.getFullReference(referenceReader, REFERENCE_PADDING); //int PRUNE_FACTOR = Math.max(MIN_PRUNE_FACTOR, determinePruneFactorFromCoverage( activeRegion )); - final ArrayList haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, getPaddedLoc(activeRegion), MIN_PRUNE_FACTOR, activeAllelesToGenotype ); + final ArrayList haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, fullSpanBeforeClipping, MIN_PRUNE_FACTOR, activeAllelesToGenotype ); if( haplotypes.size() == 1 ) { return 1; } // only the reference haplotype remains so nothing else to do! activeRegion.hardClipToActiveRegion(); // only evaluate the parts of reads that are overlapping the active region @@ -495,7 +499,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem stratifiedReadMap, perSampleFilteredReadList, fullReferenceWithPadding, - getPaddedLoc(activeRegion), + fullSpanBeforeClipping, activeRegion.getLocation(), getToolkit().getGenomeLocParser(), activeAllelesToGenotype ) ) { @@ -505,9 +509,8 @@ public class HaplotypeCaller extends ActiveRegionWalker implem if ( bamWriter != null ) { // write the haplotypes to the bam - final GenomeLoc paddedRefLoc = getPaddedLoc(activeRegion); for ( Haplotype haplotype : haplotypes ) - writeHaplotype(haplotype, paddedRefLoc, bestHaplotypes.contains(haplotype)); + writeHaplotype(haplotype, fullSpanBeforeClipping, bestHaplotypes.contains(haplotype)); // we need to remap the Alleles back to the Haplotypes; inefficient but unfortunately this is a requirement currently final Map alleleToHaplotypeMap = new HashMap(haplotypes.size()); @@ -519,7 +522,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem for ( Map.Entry> entry : readAlleleLikelihoodMap.getLikelihoodReadMap().entrySet() ) { final Allele bestAllele = PerReadAlleleLikelihoodMap.getMostLikelyAllele(entry.getValue()); if ( bestAllele != Allele.NO_CALL ) - writeReadAgainstHaplotype(entry.getKey(), alleleToHaplotypeMap.get(bestAllele), paddedRefLoc.getStart()); + writeReadAgainstHaplotype(entry.getKey(), alleleToHaplotypeMap.get(bestAllele), fullSpanBeforeClipping.getStart()); } } } @@ -559,7 +562,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem private void finalizeActiveRegion( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion ) { if( DEBUG ) { System.out.println("\nAssembling " + activeRegion.getLocation() + " with " + activeRegion.size() + " reads: (with overlap region = " + activeRegion.getExtendedLoc() + ")"); } final ArrayList finalizedReadList = new ArrayList(); - final FragmentCollection fragmentCollection = FragmentUtils.create( ReadUtils.sortReadsByCoordinate(activeRegion.getReads()) ); + final FragmentCollection fragmentCollection = FragmentUtils.create( activeRegion.getReads() ); activeRegion.clearReads(); // Join overlapping paired reads to create a single longer read @@ -571,17 +574,20 @@ public class HaplotypeCaller extends ActiveRegionWalker implem Collections.shuffle(finalizedReadList, GenomeAnalysisEngine.getRandomGenerator()); // Loop through the reads hard clipping the adaptor and low quality tails + final ArrayList readsToUse = new ArrayList(finalizedReadList.size()); for( final GATKSAMRecord myRead : finalizedReadList ) { final GATKSAMRecord postAdapterRead = ( myRead.getReadUnmappedFlag() ? myRead : ReadClipper.hardClipAdaptorSequence( myRead ) ); if( postAdapterRead != null && !postAdapterRead.isEmpty() && postAdapterRead.getCigar().getReadLength() > 0 ) { final GATKSAMRecord clippedRead = ReadClipper.hardClipLowQualEnds( postAdapterRead, MIN_TAIL_QUALITY ); // protect against INTERVALS with abnormally high coverage - // BUGBUG: remove when positional downsampler is hooked up to ART/HC - if( clippedRead.getReadLength() > 0 && activeRegion.size() < samplesList.size() * DOWNSAMPLE_PER_SAMPLE_PER_REGION ) { - activeRegion.add(clippedRead); + // TODO BUGBUG: remove when positional downsampler is hooked up to ART/HC + if( activeRegion.readOverlapsRegion(clippedRead) && + clippedRead.getReadLength() > 0 && activeRegion.size() < samplesList.size() * DOWNSAMPLE_PER_SAMPLE_PER_REGION ) { + readsToUse.add(clippedRead); } } } + activeRegion.addAll(ReadUtils.sortReadsByCoordinate(readsToUse)); } private List filterNonPassingReads( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion ) { @@ -596,9 +602,9 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } private GenomeLoc getPaddedLoc( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion ) { - final int padLeft = Math.max(activeRegion.getReferenceLoc().getStart()-REFERENCE_PADDING, 1); - final int padRight = Math.min(activeRegion.getReferenceLoc().getStop()+REFERENCE_PADDING, referenceReader.getSequenceDictionary().getSequence(activeRegion.getReferenceLoc().getContig()).getSequenceLength()); - return getToolkit().getGenomeLocParser().createGenomeLoc(activeRegion.getReferenceLoc().getContig(), padLeft, padRight); + final int padLeft = Math.max(activeRegion.getReadSpanLoc().getStart()-REFERENCE_PADDING, 1); + final int padRight = Math.min(activeRegion.getReadSpanLoc().getStop()+REFERENCE_PADDING, referenceReader.getSequenceDictionary().getSequence(activeRegion.getReadSpanLoc().getContig()).getSequenceLength()); + return getToolkit().getGenomeLocParser().createGenomeLoc(activeRegion.getReadSpanLoc().getContig(), padLeft, padRight); } private HashMap> splitReadsBySample( final List reads ) { diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 97b9ce746..d446da830 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "11290b619bc79b629cf29b8f428254ce"); + HCTest(CEUTRIO_BAM, "", "664a14590d0966e63d3aabff2d7bab0a"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "897abb2b4f98e9e460f373f9e0db5033"); + HCTest(NA12878_BAM, "", "111f3dc086a3cea1be9bd1ad6e1d18ed"); } @Test(enabled = false) @@ -84,7 +84,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "efc2cae94069a1d6ee5fdcc7afeaa0ed"); + "c70f753f7918a1c670ce4ed5c66de09e"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -96,13 +96,13 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAComplex() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:119673-119823 -L 20:121408-121538", - "01f42c311fc3ce4f07ef86f8c01facfb"); + "b1d3070f0c49becf34101e480ab6c589"); } @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "4c117c84d1abeade1dee3f7b52a4a585"); + "20eba2e54266f6aebf35b7b7b7e754e3"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "939847eb7bbafc798916acffdb1b5697"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "f9805488d85e59e1ae002d0d32d7011d"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -124,7 +124,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleSymbolic() { - HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "25806874242973f00fb6f2a320ed4d9c"); + HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "4544a2916f46f58b32db8008776b91a3"); } private void HCTestIndelQualityScores(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "c50b06d56cf3d0ef53e73a4973207949"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "f3984a91e7562494c2a7e41fd05a6734"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,14 +146,14 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("ae2470e294d99ff2b825281b84730c72")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("3e9e025c539be6c5e0d0f2e5d8e86a62")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @Test public void HCTestStructuralIndels() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "AFR.structural.indels.bam") + " --no_cmdline_in_header -o %s -minPruning 6 -L 20:8187565-8187800 -L 20:18670537-18670730"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("6f18ae64bf466476d780a083dcb5fc43")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("34129e6c6310ef4eeeeb59b0e7ac0464")); executeTest("HCTestStructuralIndels: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("ecdb8e30ec5dd91efc179ab6732499f9")); + Arrays.asList("5f4c07aaf1d2d34cccce43196a5fbd71")); executeTest("HC calling on a ReducedRead BAM", spec); } @@ -183,7 +183,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void testReducedBamWithReadsNotFullySpanningDeletion() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, - Arrays.asList("36a90309dde1a325c274388e302ffaa5")); + Arrays.asList("6ead001b1f8e7cb433fd335f78fde5f0")); executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); } } diff --git a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java index 6933b45a7..5d2aa6be3 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java +++ b/public/java/src/org/broadinstitute/sting/gatk/traversals/TraverseActiveRegions.java @@ -460,7 +460,7 @@ public class TraverseActiveRegions extends TraversalEngine> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReferenceLoc()); + logger.debug(">> Map call with " + activeRegion.getReads().size() + " " + (activeRegion.isActive() ? "active" : "inactive") + " reads @ " + activeRegion.getLocation() + " with full extent: " + activeRegion.getReadSpanLoc()); } if ( LOG_READ_CARRYING ) logger.info(String.format("Processing region %20s span=%3d active?=%5b with %4d reads. Overall max reads carried is %s", - activeRegion.getLocation(), activeRegion.getLocation().size(), activeRegion.isActive, activeRegion.size(), maxReadsInMemory)); + activeRegion.getLocation(), activeRegion.getLocation().size(), activeRegion.isActive(), activeRegion.size(), maxReadsInMemory)); final M x = walker.map(activeRegion, null); return walker.reduce( x, sum ); diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java index 194f61933..13add5e7d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java @@ -25,37 +25,105 @@ package org.broadinstitute.sting.utils.activeregion; -import com.google.java.contract.Requires; +import com.google.java.contract.Ensures; +import com.google.java.contract.Invariant; +import net.sf.picard.reference.IndexedFastaSequenceFile; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.HasGenomeLocation; import org.broadinstitute.sting.utils.clipping.ReadClipper; -import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.sam.ReadUtils; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; /** - * Created by IntelliJ IDEA. + * Represents a single active region created by the Active Region Traversal for processing + * + * An active region is a single contiguous span of bases on the genome that should be operated + * on as a single unit for the active region traversal. The action may contains a list of + * reads that overlap the region (may because there may be no reads in the region). The region + * is tagged as being either active or inactive, depending on the probabilities provided by + * the isActiveProb results from the ART walker. Each region carries with it the + * exact span of the region (bases which are the core of the isActiveProbs from the walker) as + * well as an extended size, that includes the ART walker's extension size. Reads in the region + * provided by ART include all reads overlapping the extended span, not the raw span. + * * User: rpoplin * Date: 1/4/12 */ - +@Invariant({ + "extension >= 0", + "activeRegionLoc != null", + "genomeLocParser != null", + "spanIncludingReads != null", + "extendedLoc != null" +}) public class ActiveRegion implements HasGenomeLocation { - + /** + * The reads included in this active region. May be empty upon creation, and expand / contract + * as reads are added or removed from this region. + */ private final ArrayList reads = new ArrayList(); - private final List supportingStates; - private final GenomeLoc activeRegionLoc; - private final GenomeLoc extendedLoc; - private final int extension; - private GenomeLoc fullExtentReferenceLoc = null; - private final GenomeLocParser genomeLocParser; - public final boolean isActive; + /** + * An ordered list (by genomic coordinate) of the ActivityProfileStates that went + * into this active region. May be empty, which says that no supporting states were + * provided when this region was created. + */ + private final List supportingStates; + + /** + * The raw span of this active region, not including the active region extension + */ + private final GenomeLoc activeRegionLoc; + + /** + * The span of this active region on the genome, including the active region extension + */ + private final GenomeLoc extendedLoc; + + /** + * The extension, in bp, of this active region. + */ + private final int extension; + + /** + * A genomeLocParser so we can create genomeLocs + */ + private final GenomeLocParser genomeLocParser; + + /** + * Does this region represent an active region (all isActiveProbs above threshold) or + * an inactive region (all isActiveProbs below threshold)? + */ + private final boolean isActive; + + /** + * The span of this active region, including the bp covered by all reads in this + * region. This union of extensionLoc and the loc of all reads in this region. + * + * Must be at least as large as extendedLoc, but may be larger when reads + * partially overlap this region. + */ + private GenomeLoc spanIncludingReads; + + /** + * Create a new ActiveRegion containing no reads + * + * @param activeRegionLoc the span of this active region + * @param supportingStates the states that went into creating this region, or null / empty if none are available. + * If not empty, must have exactly one state for each bp in activeRegionLoc + * @param isActive indicates whether this is an active region, or an inactve one + * @param genomeLocParser a non-null parser to let us create new genome locs + * @param extension the active region extension to use for this active region + */ public ActiveRegion( final GenomeLoc activeRegionLoc, final List supportingStates, final boolean isActive, final GenomeLocParser genomeLocParser, final int extension ) { if ( activeRegionLoc == null ) throw new IllegalArgumentException("activeRegionLoc cannot be null"); + if ( activeRegionLoc.size() == 0 ) throw new IllegalArgumentException("Active region cannot be of zero size, but got " + activeRegionLoc); if ( genomeLocParser == null ) throw new IllegalArgumentException("genomeLocParser cannot be null"); if ( extension < 0 ) throw new IllegalArgumentException("extension cannot be < 0 but got " + extension); @@ -64,75 +132,254 @@ public class ActiveRegion implements HasGenomeLocation { this.isActive = isActive; this.genomeLocParser = genomeLocParser; this.extension = extension; - extendedLoc = genomeLocParser.createGenomeLocOnContig(activeRegionLoc.getContig(), activeRegionLoc.getStart() - extension, activeRegionLoc.getStop() + extension); - fullExtentReferenceLoc = extendedLoc; + this.extendedLoc = genomeLocParser.createGenomeLocOnContig(activeRegionLoc.getContig(), activeRegionLoc.getStart() - extension, activeRegionLoc.getStop() + extension); + this.spanIncludingReads = extendedLoc; + + if ( ! this.supportingStates.isEmpty() ) { + if ( this.supportingStates.size() != activeRegionLoc.size() ) + throw new IllegalArgumentException("Supporting states wasn't empty but it doesn't have exactly one state per bp in the active region: states " + this.supportingStates.size() + " vs. bp in region = " + activeRegionLoc.size()); + GenomeLoc lastStateLoc = null; + for ( final ActivityProfileState state : this.supportingStates ) { + if ( lastStateLoc != null ) { + if ( state.getLoc().getStart() != lastStateLoc.getStart() + 1 || state.getLoc().getContigIndex() != lastStateLoc.getContigIndex()) + throw new IllegalArgumentException("Supporting state has an invalid sequence: last state was " + lastStateLoc + " but next state was " + state); + } + lastStateLoc = state.getLoc(); + } + } } @Override public String toString() { - return "ActiveRegion " + activeRegionLoc.toString() + " active?=" + isActive + " nReads=" + reads.size() + " "; + return "ActiveRegion " + activeRegionLoc.toString() + " active?=" + isActive() + " nReads=" + reads.size() + " "; } - // add each read to the bin and extend the reference genome activeRegionLoc if needed - public void add( final GATKSAMRecord read ) { - fullExtentReferenceLoc = fullExtentReferenceLoc.union( genomeLocParser.createGenomeLoc( read ) ); - reads.add( read ); - } - - public void hardClipToActiveRegion() { - final ArrayList clippedReads = ReadClipper.hardClipToRegion( reads, extendedLoc.getStart(), extendedLoc.getStop() ); - reads.clear(); - reads.addAll(clippedReads); - } - - public ArrayList getReads() { return reads; } - - @Requires("referenceReader.isUppercasingBases()") - public byte[] getActiveRegionReference( final CachingIndexedFastaSequenceFile referenceReader ) { + /** + * See #getActiveRegionReference but with padding == 0 + */ + public byte[] getActiveRegionReference( final IndexedFastaSequenceFile referenceReader ) { return getActiveRegionReference(referenceReader, 0); } - @Requires("referenceReader.isUppercasingBases()") - public byte[] getActiveRegionReference( final CachingIndexedFastaSequenceFile referenceReader, final int padding ) { - return getReference( referenceReader, padding, extendedLoc ); + /** + * Get the reference bases from referenceReader spanned by the extended location of this active region, + * including additional padding bp on either side. If this expanded region would exceed the boundaries + * of the active region's contig, the returned result will be truncated to only include on-genome reference + * bases + * @param referenceReader the source of the reference genome bases + * @param padding the padding, in BP, we want to add to either side of this active region extended region + * @return a non-null array of bytes holding the reference bases in referenceReader + */ + @Ensures("result != null") + public byte[] getActiveRegionReference( final IndexedFastaSequenceFile referenceReader, final int padding ) { + return getReference(referenceReader, padding, extendedLoc); } - @Requires("referenceReader.isUppercasingBases()") - public byte[] getFullReference( final CachingIndexedFastaSequenceFile referenceReader ) { + /** + * See #getActiveRegionReference but using the span including regions not the extended span + */ + public byte[] getFullReference( final IndexedFastaSequenceFile referenceReader ) { return getFullReference(referenceReader, 0); } - @Requires("referenceReader.isUppercasingBases()") - public byte[] getFullReference( final CachingIndexedFastaSequenceFile referenceReader, final int padding ) { - return getReference( referenceReader, padding, fullExtentReferenceLoc ); + /** + * See #getActiveRegionReference but using the span including regions not the extended span + */ + public byte[] getFullReference( final IndexedFastaSequenceFile referenceReader, final int padding ) { + return getReference(referenceReader, padding, spanIncludingReads); } - @Requires("referenceReader.isUppercasingBases()") - private byte[] getReference( final CachingIndexedFastaSequenceFile referenceReader, final int padding, final GenomeLoc genomeLoc ) { + /** + * Get the reference bases from referenceReader spanned by the extended location of this active region, + * including additional padding bp on either side. If this expanded region would exceed the boundaries + * of the active region's contig, the returned result will be truncated to only include on-genome reference + * bases + * @param referenceReader the source of the reference genome bases + * @param padding the padding, in BP, we want to add to either side of this active region extended region + * @param genomeLoc a non-null genome loc indicating the base span of the bp we'd like to get the reference for + * @return a non-null array of bytes holding the reference bases in referenceReader + */ + @Ensures("result != null") + private byte[] getReference( final IndexedFastaSequenceFile referenceReader, final int padding, final GenomeLoc genomeLoc ) { + if ( referenceReader == null ) throw new IllegalArgumentException("referenceReader cannot be null"); + if ( padding < 0 ) throw new IllegalArgumentException("padding must be a positive integer but got " + padding); + if ( genomeLoc == null ) throw new IllegalArgumentException("genomeLoc cannot be null"); + if ( genomeLoc.size() == 0 ) throw new IllegalArgumentException("GenomeLoc must have size > 0 but got " + genomeLoc); + final byte[] reference = referenceReader.getSubsequenceAt( genomeLoc.getContig(), Math.max(1, genomeLoc.getStart() - padding), Math.min(referenceReader.getSequenceDictionary().getSequence(genomeLoc.getContig()).getSequenceLength(), genomeLoc.getStop() + padding) ).getBases(); + return reference; } + /** + * Get the raw span of this active region (excluding the extension) + * @return a non-null genome loc + */ @Override + @Ensures("result != null") public GenomeLoc getLocation() { return activeRegionLoc; } + + /** + * Get the span of this active region including the extension value + * @return a non-null GenomeLoc + */ + @Ensures("result != null") public GenomeLoc getExtendedLoc() { return extendedLoc; } - public GenomeLoc getReferenceLoc() { return fullExtentReferenceLoc; } - public List getSupportingStates() { return supportingStates; } + /** + * Get the span of this active region including the extension and the projects on the + * genome of all reads in this active region. That is, returns the bp covered by this + * region and all reads in the region. + * @return a non-null genome loc + */ + @Ensures("result != null") + public GenomeLoc getReadSpanLoc() { return spanIncludingReads; } + /** + * Get the active profile states that went into creating this region, if possible + * @return an unmodifiable list of states that led to the creation of this region, or an empty + * list if none were provided + */ + @Ensures("result != null") + public List getSupportingStates() { + return Collections.unmodifiableList(supportingStates); + } + + /** + * Get the active region extension applied to this region + * + * The extension is >= 0 bp in size, and indicates how much padding this art walker wanted for its regions + * + * @return the size in bp of the region extension + */ + @Ensures("result >= 0") public int getExtension() { return extension; } - public int size() { return reads.size(); } - public void clearReads() { reads.clear(); } - public void removeAll( final ArrayList readsToRemove ) { reads.removeAll( readsToRemove ); } - public boolean equalExceptReads(final ActiveRegion other) { + /** + * Get an unmodifiable list of reads currently in this active region. + * + * The reads are sorted by their coordinate position + * + * @return an unmodifiable list of reads in this active region + */ + @Ensures("result != null") + public List getReads() { + return Collections.unmodifiableList(reads); + } + + /** + * Get the number of reads currently in this active region + * @return an integer >= 0 + */ + @Ensures("result >= 0") + public int size() { return reads.size(); } + + /** + * Add read to this active region + * + * Read must have alignment start >= than the last read currently in this active region. + * + * @throws IllegalArgumentException if read doesn't overlap the extended region of this active region + * + * @param read a non-null GATKSAMRecord + */ + @Ensures("reads.size() == old(reads.size()) + 1") + public void add( final GATKSAMRecord read ) { + if ( read == null ) throw new IllegalArgumentException("Read cannot be null"); + + final GenomeLoc readLoc = genomeLocParser.createGenomeLoc( read ); + if ( ! readOverlapsRegion(read) ) + throw new IllegalArgumentException("Read location " + readLoc + " doesn't overlap with active region extended span " + extendedLoc); + + spanIncludingReads = spanIncludingReads.union( readLoc ); + + if ( ! reads.isEmpty() ) { + final GATKSAMRecord lastRead = reads.get(size() - 1); + if ( ! lastRead.getReferenceIndex().equals(read.getReferenceIndex()) ) + throw new IllegalArgumentException("Attempting to add a read to ActiveRegion not on the same contig as other reads: lastRead " + lastRead + " attempting to add " + read); + + if ( read.getAlignmentStart() < lastRead.getAlignmentStart() ) + throw new IllegalArgumentException("Attempting to add a read to ActiveRegion out of order w.r.t. other reads: lastRead " + lastRead + " at " + lastRead.getAlignmentStart() + " attempting to add " + read + " at " + read.getAlignmentStart()); + } + + reads.add( read ); + } + + /** + * Returns true if read would overlap the extended extent of this region + * @param read the read we want to test + * @return true if read can be added to this region, false otherwise + */ + public boolean readOverlapsRegion(final GATKSAMRecord read) { + final GenomeLoc readLoc = genomeLocParser.createGenomeLoc( read ); + return readLoc.overlapsP(extendedLoc); + } + + /** + * Add all reads to this active region + * @param reads a collection of reads to add to this active region + */ + public void addAll(final Collection reads) { + if ( reads == null ) throw new IllegalArgumentException("reads cannot be null"); + for ( final GATKSAMRecord read : reads ) + add(read); + } + + /** + * Clear all of the reads currently in this active region + */ + @Ensures("size() == 0") + public void clearReads() { + spanIncludingReads = extendedLoc; + reads.clear(); + } + + /** + * Remove all of the reads in readsToRemove from this active region + * @param readsToRemove the collection of reads we want to remove + */ + public void removeAll( final Collection readsToRemove ) { + reads.removeAll(readsToRemove); + spanIncludingReads = extendedLoc; + for ( final GATKSAMRecord read : reads ) { + spanIncludingReads = spanIncludingReads.union( genomeLocParser.createGenomeLoc(read) ); + } + } + + /** + * Clips all of the reads in this active region so that none extend beyond the active region extended loc + * + * This function may change the getReadSpanLoc, as it updates the read span based on the new clipped + * read coordinates. + */ + public void hardClipToActiveRegion() { + final ArrayList clippedReads = ReadClipper.hardClipToRegion( reads, extendedLoc.getStart(), extendedLoc.getStop() ); + ReadUtils.sortReadsByCoordinate(clippedReads); + clearReads(); + addAll(clippedReads); + } + + /** + * Is this region equal to other, excluding any reads in either region in the comparison + * @param other the other active region we want to test + * @return true if this region is equal, excluding any reads and derived values, to other + */ + protected boolean equalExceptReads(final ActiveRegion other) { if ( activeRegionLoc.compareTo(other.activeRegionLoc) != 0 ) return false; - if ( isActive != other.isActive ) return false; + if ( isActive() != other.isActive()) return false; if ( genomeLocParser != other.genomeLocParser ) return false; if ( extension != other.extension ) return false; if ( extendedLoc.compareTo(other.extendedLoc) != 0 ) return false; return true; } + + /** + * Does this region represent an active region (all isActiveProbs above threshold) or + * an inactive region (all isActiveProbs below threshold)? + */ + public boolean isActive() { + return isActive; + } } \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java index 0f5d6a2f7..1bf24814b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ArtificialSAMUtils.java @@ -115,6 +115,19 @@ public class ArtificialSAMUtils { return header; } + /** + * Creates an artificial sam header based on the sequence dictionary dict + * + * @return + */ + public static SAMFileHeader createArtificialSamHeader(final SAMSequenceDictionary dict) { + SAMFileHeader header = new SAMFileHeader(); + header.setSortOrder(net.sf.samtools.SAMFileHeader.SortOrder.coordinate); + header.setSequenceDictionary(dict); + return header; + } + + /** * setup a default read group for a SAMFileHeader * diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActiveRegionUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActiveRegionUnitTest.java new file mode 100644 index 000000000..d2ea5d11b --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActiveRegionUnitTest.java @@ -0,0 +1,223 @@ +/* + * 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.utils.activeregion; + + +// the imports for unit testing. + + +import net.sf.picard.reference.IndexedFastaSequenceFile; +import net.sf.samtools.SAMFileHeader; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + + +public class ActiveRegionUnitTest extends BaseTest { + private GenomeLocParser genomeLocParser; + private IndexedFastaSequenceFile seq; + private String contig; + private int contigLength; + + @BeforeClass + public void init() throws FileNotFoundException { + // sequence + seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + genomeLocParser = new GenomeLocParser(seq); + contig = "1"; + contigLength = genomeLocParser.getContigInfo(contig).getSequenceLength(); + } + + @DataProvider(name = "ActionRegionCreationTest") + public Object[][] makePollingData() { + List tests = new ArrayList(); + for ( final int start : Arrays.asList(1, 10, 100, contigLength - 10, contigLength - 1) ) { + for ( final int size : Arrays.asList(1, 10, 100, 1000) ) { + for ( final int ext : Arrays.asList(0, 1, 10, 100) ) { + for ( final boolean isActive : Arrays.asList(true, false) ) { + for ( final boolean addStates : Arrays.asList(true, false) ) { + List states = null; + if ( addStates ) { + states = new LinkedList(); + for ( int i = start; i < start + size; i++ ) { + states.add(new ActivityProfileState(genomeLocParser.createGenomeLoc(contig, i + start), isActive ? 1.0 : 0.0)); + } + } + final GenomeLoc loc = genomeLocParser.createGenomeLoc(contig, start, start + size - 1); + tests.add(new Object[]{loc, states, isActive, ext}); + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(enabled = true, dataProvider = "ActionRegionCreationTest") + public void testCreatingActiveRegions(final GenomeLoc loc, final List supportingStates, final boolean isActive, final int extension) { + final ActiveRegion region = new ActiveRegion(loc, supportingStates, isActive, genomeLocParser, extension); + Assert.assertEquals(region.getLocation(), loc); + Assert.assertEquals(region.getExtendedLoc().getStart(), Math.max(loc.getStart() - extension, 1)); + Assert.assertEquals(region.getExtendedLoc().getStop(), Math.min(loc.getStop() + extension, contigLength)); + Assert.assertEquals(region.getReadSpanLoc().getStart(), Math.max(loc.getStart() - extension, 1)); + Assert.assertEquals(region.getReadSpanLoc().getStop(), Math.min(loc.getStop() + extension, contigLength)); + Assert.assertEquals(region.isActive(), isActive); + Assert.assertEquals(region.getExtension(), extension); + Assert.assertEquals(region.getReads(), Collections.emptyList()); + Assert.assertEquals(region.size(), 0); + Assert.assertEquals(region.getSupportingStates(), supportingStates == null ? Collections.emptyList() : supportingStates); + Assert.assertNotNull(region.toString()); + + assertGoodReferenceGetter(region.getActiveRegionReference(seq), region.getExtendedLoc(), 0); + assertGoodReferenceGetter(region.getActiveRegionReference(seq, 10), region.getExtendedLoc(), 10); + assertGoodReferenceGetter(region.getFullReference(seq), region.getReadSpanLoc(), 0); + assertGoodReferenceGetter(region.getFullReference(seq, 10), region.getReadSpanLoc(), 10); + } + + private void assertGoodReferenceGetter(final byte[] actualBytes, final GenomeLoc span, final int padding) { + final int expectedStart = Math.max(span.getStart() - padding, 1); + final int expectedStop = Math.min(span.getStop() + padding, contigLength); + final byte[] expectedBytes = seq.getSubsequenceAt(span.getContig(), expectedStart, expectedStop).getBases(); + Assert.assertEquals(actualBytes, expectedBytes); + } + + @DataProvider(name = "ActiveRegionReads") + public Object[][] makeActiveRegionReads() { + List tests = new ArrayList(); + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); + for ( final int start : Arrays.asList(1, 10, 100, contigLength - 10, contigLength - 1) ) { + for ( final int readStartOffset : Arrays.asList(-100, -10, 0, 10, 100) ) { + for ( final int readSize : Arrays.asList(10, 100, 1000) ) { + final GenomeLoc loc = genomeLocParser.createGenomeLocOnContig(contig, start, start + 10); + + final int readStart = Math.max(start + readStartOffset, 1); + final int readStop = Math.min(readStart + readSize, contigLength); + final int readLength = readStop - readStart + 1; + if ( readLength > 0 ) { + GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "read", 0, readStart, readLength); + final GenomeLoc readLoc = genomeLocParser.createGenomeLoc(read); + if ( readLoc.overlapsP(loc) ) + tests.add(new Object[]{loc, read}); + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "ActiveRegionReads") + public void testActiveRegionReads(final GenomeLoc loc, final GATKSAMRecord read) { + final GenomeLoc expectedSpan = loc.union(genomeLocParser.createGenomeLoc(read)); + + final ActiveRegion region = new ActiveRegion(loc, null, true, genomeLocParser, 0); + final ActiveRegion region2 = new ActiveRegion(loc, null, true, genomeLocParser, 0); + Assert.assertEquals(region.getReads(), Collections.emptyList()); + Assert.assertEquals(region.size(), 0); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), loc); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.add(read); + Assert.assertEquals(region.getReads(), Collections.singletonList(read)); + Assert.assertEquals(region.size(), 1); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), expectedSpan); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.clearReads(); + Assert.assertEquals(region.getReads(), Collections.emptyList()); + Assert.assertEquals(region.size(), 0); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), loc); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.addAll(Collections.singleton(read)); + Assert.assertEquals(region.getReads(), Collections.singletonList(read)); + Assert.assertEquals(region.size(), 1); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), expectedSpan); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.removeAll(Collections.emptyList()); + Assert.assertEquals(region.getReads(), Collections.singletonList(read)); + Assert.assertEquals(region.size(), 1); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), expectedSpan); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.removeAll(Collections.singletonList(read)); + Assert.assertEquals(region.getReads(), Collections.emptyList()); + Assert.assertEquals(region.size(), 0); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), loc); + Assert.assertTrue(region.equalExceptReads(region2)); + + region.add(read); + region.hardClipToActiveRegion(); + Assert.assertEquals(region.size(), 1); + Assert.assertEquals(region.getExtendedLoc(), loc); + Assert.assertEquals(region.getReadSpanLoc(), loc); + Assert.assertTrue(region.getReads().get(0).getAlignmentStart() >= region.getExtendedLoc().getStart()); + Assert.assertTrue(region.getReads().get(0).getAlignmentEnd() <= region.getExtendedLoc().getStop()); + } + + @DataProvider(name = "BadReadsTest") + public Object[][] makeBadReadsTest() { + List tests = new ArrayList(); + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); + tests.add(new Object[]{ + ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 10, 10), + ArtificialSAMUtils.createArtificialRead(header, "read2", 0, 9, 10)}); + tests.add(new Object[]{ + ArtificialSAMUtils.createArtificialRead(header, "read1", 0, 10, 10), + ArtificialSAMUtils.createArtificialRead(header, "read2", 1, 9, 10)}); + tests.add(new Object[]{ + ArtificialSAMUtils.createArtificialRead(header, "read1", 1, 10, 10), + ArtificialSAMUtils.createArtificialRead(header, "read2", 0, 9, 10)}); + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "BadReadsTest", expectedExceptions = IllegalArgumentException.class) + public void testBadReads(final GATKSAMRecord read1, final GATKSAMRecord read2) { + final GenomeLoc loc = genomeLocParser.createGenomeLoc(read1); + final ActiveRegion region = new ActiveRegion(loc, null, true, genomeLocParser, 0); + region.add(read1); + region.add(read2); + } +} \ No newline at end of file diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java index 1df4a3348..b9fdb3afe 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/ActivityProfileUnitTest.java @@ -276,7 +276,7 @@ public class ActivityProfileUnitTest extends BaseTest { Assert.assertTrue(regionOffset >= 0 && regionOffset < probs.size(), "Region " + region + " has a bad offset w.r.t. start"); for ( int j = 0; j < region.getLocation().size(); j++ ) { final int siteOffset = j + regionOffset; - Assert.assertEquals(region.isActive, probs.get(siteOffset).booleanValue()); + Assert.assertEquals(region.isActive(), probs.get(siteOffset).booleanValue()); Assert.assertFalse(seenSites.get(siteOffset), "Site " + j + " in " + region + " was seen already"); seenSites.set(siteOffset, true); } diff --git a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java index eb2eebd36..cb2a6bfb2 100644 --- a/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/activeregion/BandPassActivityProfileUnitTest.java @@ -309,8 +309,8 @@ public class BandPassActivityProfileUnitTest extends BaseTest { lastPosSeen = region.getLocation().getStop(); for ( final ActivityProfileState state : region.getSupportingStates() ) { - Assert.assertEquals(state.isActiveProb > ActivityProfile.ACTIVE_PROB_THRESHOLD, region.isActive, - "Region is active=" + region.isActive + " but contains a state " + state + " with prob " + Assert.assertEquals(state.isActiveProb > ActivityProfile.ACTIVE_PROB_THRESHOLD, region.isActive(), + "Region is active=" + region.isActive() + " but contains a state " + state + " with prob " + state.isActiveProb + " not within expected values given threshold for activity of " + ActivityProfile.ACTIVE_PROB_THRESHOLD); } From 69dd5cc902122c432cb337a7219c7d28cdbbf456 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 29 Jan 2013 19:28:14 -0500 Subject: [PATCH 137/188] AutoFormattingTimeUnitTest should be in utils --- .../sting/{ => utils}/AutoFormattingTimeUnitTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename public/java/test/org/broadinstitute/sting/{ => utils}/AutoFormattingTimeUnitTest.java (98%) diff --git a/public/java/test/org/broadinstitute/sting/AutoFormattingTimeUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/AutoFormattingTimeUnitTest.java similarity index 98% rename from public/java/test/org/broadinstitute/sting/AutoFormattingTimeUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/AutoFormattingTimeUnitTest.java index b1aacd8b9..8bedfb547 100644 --- a/public/java/test/org/broadinstitute/sting/AutoFormattingTimeUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/AutoFormattingTimeUnitTest.java @@ -23,8 +23,9 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.sting; +package org.broadinstitute.sting.utils; +import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.AutoFormattingTime; import org.testng.Assert; import org.testng.annotations.DataProvider; From 8562bfaae1a028a2966d5cbd3aff78a88b7ac4dc Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 29 Jan 2013 08:10:56 -0500 Subject: [PATCH 138/188] Optimize GenomeLocParser.createGenomeLoc -- The new version is roughly 2x faster than the previous version. The key here was to cleanup the workflow for validateGenomeLoc and remove the now unnecessary synchronization blocks from the CachingSequencingDictionary, since these are now thread local variables -- #resolves https://jira.broadinstitute.org/browse/GSA-724 --- .../sting/utils/GenomeLocParser.java | 169 ++++++++++++------ .../sting/utils/GenomeLocParserBenchmark.java | 81 +++++++++ 2 files changed, 191 insertions(+), 59 deletions(-) create mode 100644 public/java/test/org/broadinstitute/sting/utils/GenomeLocParserBenchmark.java diff --git a/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java b/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java index e70182acf..36b23ae14 100644 --- a/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java +++ b/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java @@ -45,6 +45,14 @@ import org.broadinstitute.variant.variantcontext.VariantContext; public final class GenomeLocParser { private static Logger logger = Logger.getLogger(GenomeLocParser.class); + /** + * How much validation should we do at runtime with this parser? + */ + public enum ValidationLevel { + STANDARD, + NONE + } + // -------------------------------------------------------------------------------------------------------------- // // Ugly global variable defining the optional ordering of contig elements @@ -58,22 +66,25 @@ public final class GenomeLocParser { final private SAMSequenceDictionary SINGLE_MASTER_SEQUENCE_DICTIONARY; /** - * A thread-local caching contig info + * A thread-local CachingSequenceDictionary */ private final ThreadLocal contigInfoPerThread = - new ThreadLocal(); + new ThreadLocal() { + @Override + protected CachingSequenceDictionary initialValue() { + return new CachingSequenceDictionary(SINGLE_MASTER_SEQUENCE_DICTIONARY); + } + }; + + /** + * How much validation are we doing at runtime with this GenomeLocParser? + */ + private final ValidationLevel validationLevel; /** * @return a caching sequence dictionary appropriate for this thread */ private CachingSequenceDictionary getContigInfo() { - if ( contigInfoPerThread.get() == null ) { - // initialize for this thread - contigInfoPerThread.set(new CachingSequenceDictionary(SINGLE_MASTER_SEQUENCE_DICTIONARY)); - } - - assert contigInfoPerThread.get() != null; - return contigInfoPerThread.get(); } @@ -94,24 +105,28 @@ public final class GenomeLocParser { this.dict = dict; } + public final String internContigName(final String contig) { + return getContigInfo(contig).getSequenceName(); + } + @Ensures("result > 0") public final int getNSequences() { return dict.size(); } @Requires("contig != null") - public final synchronized boolean hasContig(final String contig) { + public final boolean hasContig(final String contig) { return contig.equals(lastContig) || dict.getSequence(contig) != null; } @Requires("index >= 0") - public final synchronized boolean hasContig(final int index) { + public final boolean hasContig(final int index) { return lastIndex == index || dict.getSequence(index) != null; } @Requires("contig != null") @Ensures("result != null") - public synchronized final SAMSequenceRecord getSequence(final String contig) { + public final SAMSequenceRecord getSequence(final String contig) { if ( isCached(contig) ) return lastSSR; else @@ -120,7 +135,7 @@ public final class GenomeLocParser { @Requires("index >= 0") @Ensures("result != null") - public synchronized final SAMSequenceRecord getSequence(final int index) { + public final SAMSequenceRecord getSequence(final int index) { if ( isCached(index) ) return lastSSR; else @@ -129,7 +144,7 @@ public final class GenomeLocParser { @Requires("contig != null") @Ensures("result >= 0") - public synchronized final int getSequenceIndex(final String contig) { + public final int getSequenceIndex(final String contig) { if ( ! isCached(contig) ) { updateCache(contig, -1); } @@ -138,12 +153,12 @@ public final class GenomeLocParser { } @Requires({"contig != null", "lastContig != null"}) - private synchronized boolean isCached(final String contig) { + private boolean isCached(final String contig) { return lastContig.equals(contig); } @Requires({"lastIndex != -1", "index >= 0"}) - private synchronized boolean isCached(final int index) { + private boolean isCached(final int index) { return lastIndex == index; } @@ -157,7 +172,7 @@ public final class GenomeLocParser { */ @Requires("contig != null || index >= 0") @Ensures("result != null") - private synchronized SAMSequenceRecord updateCache(final String contig, int index ) { + private SAMSequenceRecord updateCache(final String contig, int index ) { SAMSequenceRecord rec = contig == null ? dict.getSequence(index) : dict.getSequence(contig); if ( rec == null ) { throw new ReviewedStingException("BUG: requested unknown contig=" + contig + " index=" + index); @@ -168,8 +183,6 @@ public final class GenomeLocParser { return rec; } } - - } /** @@ -181,16 +194,32 @@ public final class GenomeLocParser { this(refFile.getSequenceDictionary()); } + /** + * Create a new GenomeLocParser based on seqDictionary with the standard validation level + * @param seqDict a non-null sequence dictionary + */ public GenomeLocParser(SAMSequenceDictionary seqDict) { + this(seqDict, ValidationLevel.STANDARD); + } + + /** + * Create a genome loc parser based on seqDict with the specified level of validation + * @param seqDict the sequence dictionary to use when creating genome locs + * @param validationLevel how much validation should we do of the genome locs at runtime? + */ + public GenomeLocParser(SAMSequenceDictionary seqDict, final ValidationLevel validationLevel) { + this.validationLevel = validationLevel; if (seqDict == null) { // we couldn't load the reference dictionary //logger.info("Failed to load reference dictionary, falling back to lexicographic order for contigs"); throw new UserException.CommandLineException("Failed to load reference dictionary"); } SINGLE_MASTER_SEQUENCE_DICTIONARY = seqDict; - logger.debug(String.format("Prepared reference sequence contig dictionary")); - for (SAMSequenceRecord contig : seqDict.getSequences()) { - logger.debug(String.format(" %s (%d bp)", contig.getSequenceName(), contig.getSequenceLength())); + if ( logger.isDebugEnabled() ) { + logger.debug(String.format("Prepared reference sequence contig dictionary")); + for (SAMSequenceRecord contig : seqDict.getSequences()) { + logger.debug(String.format(" %s (%d bp)", contig.getSequenceName(), contig.getSequenceLength())); + } } } @@ -283,13 +312,23 @@ public final class GenomeLocParser { @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop,mustBeOnReference)"}) public GenomeLoc createGenomeLoc(String contig, int index, final int start, final int stop, boolean mustBeOnReference) { - validateGenomeLoc(contig, index, start, stop, mustBeOnReference, true); - return new GenomeLoc(contig, index, start, stop); + // optimization: by interning the string we ensure that future comparisons use == not the full string comp + final String interned = validateGenomeLoc(contig, index, start, stop, mustBeOnReference); + return new GenomeLoc(interned, index, start, stop); } + /** + * Create a new genome loc, bounding start and stop by the start and end of contig + * @param contig our contig + * @param start our start as an arbitrary integer (may be negative, etc) + * @param stop our stop as an arbitrary integer (may be negative, etc) + * @throws ReviewedStingException if there's no way to create a meaningful genome loc given contig, start, and stop + * @return a valid genome loc over contig + */ public GenomeLoc createGenomeLocOnContig(final String contig, final int start, final int stop) { - GenomeLoc contigLoc = createOverEntireContig(contig); - return new GenomeLoc(contig, getContigIndex(contig), start, stop).intersect(contigLoc); + final GenomeLoc myLoc = createGenomeLoc(contig, start, stop); + final GenomeLoc contigLoc = createOverEntireContig(contig); + return myLoc.intersect(contigLoc); } /** @@ -306,50 +345,62 @@ public final class GenomeLocParser { * @param start the start position * @param stop the stop position * - * @return true if it's valid, false otherwise. If exceptOnError, then throws a UserException if invalid + * @return the interned contig name, an optimization that ensures that contig == the string in the sequence dictionary */ - private boolean validateGenomeLoc(String contig, int contigIndex, int start, int stop, boolean mustBeOnReference, boolean exceptOnError) { - if ( ! getContigInfo().hasContig(contig) ) - return vglHelper(exceptOnError, String.format("Unknown contig %s", contig)); + protected String validateGenomeLoc(final String contig, final int contigIndex, final int start, final int stop, final boolean mustBeOnReference) { + if ( validationLevel == ValidationLevel.NONE ) + return contig; + else { + if (stop < start) + vglHelper(String.format("The stop position %d is less than start %d in contig %s", stop, start, contig)); - if (stop < start) - return vglHelper(exceptOnError, String.format("The stop position %d is less than start %d in contig %s", stop, start, contig)); + final SAMSequenceRecord contigInfo = getContigInfo().getSequence(contig); + if ( contigInfo.getSequenceIndex() != contigIndex ) + vglHelper(String.format("The contig index %d is bad, doesn't equal the contig index %d of the contig from a string %s", + contigIndex, contigInfo.getSequenceIndex(), contig)); - if (contigIndex < 0) - return vglHelper(exceptOnError, String.format("The contig index %d is less than 0", contigIndex)); + if ( mustBeOnReference ) { + if (start < 1) + vglHelper(String.format("The start position %d is less than 1", start)); - if (contigIndex >= getContigInfo().getNSequences()) - return vglHelper(exceptOnError, String.format("The contig index %d is greater than the stored sequence count (%d)", contigIndex, getContigInfo().getNSequences())); + if (stop < 1) + vglHelper(String.format("The stop position %d is less than 1", stop)); - if ( mustBeOnReference ) { - if (start < 1) - return vglHelper(exceptOnError, String.format("The start position %d is less than 1", start)); + final int contigSize = contigInfo.getSequenceLength(); + if (start > contigSize || stop > contigSize) + vglHelper(String.format("The genome loc coordinates %d-%d exceed the contig size (%d)", start, stop, contigSize)); + } - if (stop < 1) - return vglHelper(exceptOnError, String.format("The stop position %d is less than 1", stop)); - - int contigSize = getContigInfo().getSequence(contigIndex).getSequenceLength(); - if (start > contigSize || stop > contigSize) - return vglHelper(exceptOnError, String.format("The genome loc coordinates %d-%d exceed the contig size (%d)", start, stop, contigSize)); + return contigInfo.getSequenceName(); } - - // we passed - return true; } + /** + * Would a genome loc created with the given parameters be valid w.r.t. the master sequence dictionary? + * @param contig the contig we'd use + * @param start the start position + * @param stop the stop + * @param mustBeOnReference should we require the resulting genome loc to be completely on the reference genome? + * @return true if this would produce a valid genome loc, false otherwise + */ public boolean isValidGenomeLoc(String contig, int start, int stop, boolean mustBeOnReference ) { - return validateGenomeLoc(contig, getContigIndexWithoutException(contig), start, stop, mustBeOnReference, false); - } - - public boolean isValidGenomeLoc(String contig, int start, int stop ) { - return validateGenomeLoc(contig, getContigIndexWithoutException(contig), start, stop, true, false); - } - - private boolean vglHelper(boolean exceptOnError, String msg) { - if ( exceptOnError ) - throw new UserException.MalformedGenomeLoc("Parameters to GenomeLocParser are incorrect:" + msg); - else + try { + validateGenomeLoc(contig, getContigIndexWithoutException(contig), start, stop, mustBeOnReference); + return true; + } catch ( ReviewedStingException e) { return false; + } + } + + /** + * @see #isValidGenomeLoc(String, int, int) with mustBeOnReference == true + */ + public boolean isValidGenomeLoc(String contig, int start, int stop ) { + return isValidGenomeLoc(contig, start, stop, true); + } + + private void vglHelper(final String msg) { + throw new UserException.MalformedGenomeLoc("Parameters to GenomeLocParser are incorrect:" + msg); } // -------------------------------------------------------------------------------------------------------------- diff --git a/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserBenchmark.java b/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserBenchmark.java new file mode 100644 index 000000000..478f02530 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserBenchmark.java @@ -0,0 +1,81 @@ +/* + * 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.utils; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; +import net.sf.picard.reference.IndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; + +import java.io.File; + +/** + * Caliper microbenchmark of genome loc parser + */ +public class GenomeLocParserBenchmark extends SimpleBenchmark { + private IndexedFastaSequenceFile seq; + private final int ITERATIONS = 1000000; + + @Param({"NEW", "NONE"}) + GenomeLocParser.ValidationLevel validationLevel; // set automatically by framework + + @Param({"true", "false"}) + boolean useContigIndex; // set automatically by framework + + @Override protected void setUp() throws Exception { + seq = new CachingIndexedFastaSequenceFile(new File("/Users/depristo/Desktop/broadLocal/localData/human_g1k_v37.fasta")); + } +// +// public void timeSequentialCreationFromGenomeLoc(int rep) { +// final GenomeLocParser genomeLocParser = new GenomeLocParser(seq.getSequenceDictionary(), validationLevel); +// GenomeLoc last = genomeLocParser.createGenomeLoc("1", 1, 1); +// for ( int i = 0; i < rep; i++ ) { +// for ( int j = 1; j < ITERATIONS; j++ ) { +// if ( useContigIndex ) +// last = genomeLocParser.createGenomeLoc(last.getContig(), last.getContigIndex(), last.getStart() + 1); +// else +// last = genomeLocParser.createGenomeLoc(last.getContig(), last.getStart() + 1); +// } +// } +// } +// +// public void timeSequentialCreationFromGenomeLocOriginal(int rep) { +// final GenomeLocParserOriginal genomeLocParser = new GenomeLocParserOriginal(seq.getSequenceDictionary()); +// GenomeLoc last = genomeLocParser.createGenomeLoc("1", 1, 1); +// for ( int i = 0; i < rep; i++ ) { +// for ( int j = 1; j < ITERATIONS; j++ ) { +// if ( useContigIndex ) +// last = genomeLocParser.createGenomeLoc(last.getContig(), last.getContigIndex(), last.getStart() + 1); +// else +// last = genomeLocParser.createGenomeLoc(last.getContig(), last.getStart() + 1); +// } +// } +// } + + public static void main(String[] args) { + com.google.caliper.Runner.main(GenomeLocParserBenchmark.class, args); + } +} From 45603f58cd285db612ca3af9bacab43310c2722a Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Tue, 29 Jan 2013 16:51:39 -0500 Subject: [PATCH 139/188] Refactoring and unit testing GenomeLocParser -- Moved previously inner class to MRUCachingSAMSequenceDictionary, and unit test to 100% coverage -- Fully document all functions in GenomeLocParser -- Unit tests for things like parsePosition (shocking it wasn't tested!) -- Removed function to specifically create GenomeLocs for VariantContexts. The fact that you must incorporate END attributes in the context means that createGenomeLoc(Feature) works correctly -- Depreciated (and moved functionality) of setStart, setStop, and incPos to GenomeLoc -- Unit test coverage at like 80%, moving to 100% with next commit --- .../evaluators/VariantSummary.java | 2 +- .../IntervalStratification.java | 2 +- .../broadinstitute/sting/utils/GenomeLoc.java | 51 +++ .../sting/utils/GenomeLocParser.java | 332 ++++++------------ .../MRUCachingSAMSequenceDictionary.java | 186 ++++++++++ .../sting/utils/GenomeLocParserUnitTest.java | 181 +++++++++- ...achingSAMSequencingDictionaryUnitTest.java | 97 +++++ 7 files changed, 627 insertions(+), 224 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/utils/MRUCachingSAMSequenceDictionary.java create mode 100644 public/java/test/org/broadinstitute/sting/utils/MRUCachingSAMSequencingDictionaryUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java index a3b703ad3..2a1dbd277 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/evaluators/VariantSummary.java @@ -193,7 +193,7 @@ public class VariantSummary extends VariantEvaluator implements StandardEval { private boolean overlapsKnownCNV(VariantContext cnv) { if ( knownCNVs != null ) { - final GenomeLoc loc = getWalker().getToolkit().getGenomeLocParser().createGenomeLoc(cnv, true); + final GenomeLoc loc = getWalker().getToolkit().getGenomeLocParser().createGenomeLoc(cnv); IntervalTree intervalTree = knownCNVs.get(loc.getContig()); final Iterator> nodeIt = intervalTree.overlappers(loc.getStart(), loc.getStop()); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java index be689fe55..312e506a2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/IntervalStratification.java @@ -77,7 +77,7 @@ public class IntervalStratification extends VariantStratifier { public List getRelevantStates(ReferenceContext ref, RefMetaDataTracker tracker, VariantContext comp, String compName, VariantContext eval, String evalName, String sampleName) { if (eval != null) { - final GenomeLoc loc = getVariantEvalWalker().getToolkit().getGenomeLocParser().createGenomeLoc(eval, true); + final GenomeLoc loc = getVariantEvalWalker().getToolkit().getGenomeLocParser().createGenomeLoc(eval); IntervalTree intervalTree = intervalTreeByContig.get(loc.getContig()); IntervalTree.Node node = intervalTree.minOverlapper(loc.getStart(), loc.getStop()); //logger.info(String.format("Overlap %s found %s", loc, node)); diff --git a/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java b/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java index c81e8e853..4f1b35f62 100644 --- a/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java +++ b/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java @@ -530,4 +530,55 @@ public class GenomeLoc implements Comparable, Serializable, HasGenome final int cmp = this.compareTo(other); return cmp == -1 ? other : this; } + + /** + * create a new genome loc from an existing loc, with a new start position + * Note that this function will NOT explicitly check the ending offset, in case someone wants to + * set the start of a new GenomeLoc pertaining to a read that goes off the end of the contig. + * + * @param loc the old location + * @param start a new start position + * + * @return a newly allocated GenomeLoc as loc but with start == start + */ + public GenomeLoc setStart(GenomeLoc loc, int start) { + return new GenomeLoc(loc.getContig(), loc.getContigIndex(), start, loc.getStop()); + } + + /** + * create a new genome loc from an existing loc, with a new stop position + * Note that this function will NOT explicitly check the ending offset, in case someone wants to + * set the stop of a new GenomeLoc pertaining to a read that goes off the end of the contig. + * + * @param loc the old location + * @param stop a new stop position + * + * @return a newly allocated GenomeLoc as loc but with stop == stop + */ + public GenomeLoc setStop(GenomeLoc loc, int stop) { + return new GenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start, stop); + } + + /** + * return a new genome loc, with an incremented position + * + * @param loc the old location + * + * @return a newly allocated GenomeLoc as loc but with start == loc.getStart() + 1 + */ + public GenomeLoc incPos(GenomeLoc loc) { + return incPos(loc, 1); + } + + /** + * return a new genome loc, with an incremented position + * + * @param loc the old location + * @param by how much to move the start and stop by + * + * @return a newly allocated GenomeLoc as loc but with start == loc.getStart() + by + */ + public GenomeLoc incPos(GenomeLoc loc, int by) { + return new GenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start + by, loc.stop + by); + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java b/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java index 36b23ae14..61478744d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java +++ b/public/java/src/org/broadinstitute/sting/utils/GenomeLocParser.java @@ -34,10 +34,8 @@ import net.sf.samtools.SAMSequenceDictionary; import net.sf.samtools.SAMSequenceRecord; import org.apache.log4j.Logger; import org.broad.tribble.Feature; -import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.variant.variantcontext.VariantContext; /** * Factory class for creating GenomeLocs @@ -49,7 +47,9 @@ public final class GenomeLocParser { * How much validation should we do at runtime with this parser? */ public enum ValidationLevel { + /** Do the standard amount of validation */ STANDARD, + /** Don't do any real checking at all */ NONE } @@ -68,11 +68,11 @@ public final class GenomeLocParser { /** * A thread-local CachingSequenceDictionary */ - private final ThreadLocal contigInfoPerThread = - new ThreadLocal() { + private final ThreadLocal contigInfoPerThread = + new ThreadLocal() { @Override - protected CachingSequenceDictionary initialValue() { - return new CachingSequenceDictionary(SINGLE_MASTER_SEQUENCE_DICTIONARY); + protected MRUCachingSAMSequenceDictionary initialValue() { + return new MRUCachingSAMSequenceDictionary(SINGLE_MASTER_SEQUENCE_DICTIONARY); } }; @@ -84,107 +84,10 @@ public final class GenomeLocParser { /** * @return a caching sequence dictionary appropriate for this thread */ - private CachingSequenceDictionary getContigInfo() { + private MRUCachingSAMSequenceDictionary getContigInfo() { return contigInfoPerThread.get(); } - /** - * A wrapper class that provides efficient last used caching for the global - * SAMSequenceDictionary underlying all of the GATK engine capabilities. - */ - private final class CachingSequenceDictionary { - final private SAMSequenceDictionary dict; - - // cache - SAMSequenceRecord lastSSR = null; - String lastContig = ""; - int lastIndex = -1; - - @Requires({"dict != null", "dict.size() > 0"}) - public CachingSequenceDictionary(SAMSequenceDictionary dict) { - this.dict = dict; - } - - public final String internContigName(final String contig) { - return getContigInfo(contig).getSequenceName(); - } - - @Ensures("result > 0") - public final int getNSequences() { - return dict.size(); - } - - @Requires("contig != null") - public final boolean hasContig(final String contig) { - return contig.equals(lastContig) || dict.getSequence(contig) != null; - } - - @Requires("index >= 0") - public final boolean hasContig(final int index) { - return lastIndex == index || dict.getSequence(index) != null; - } - - @Requires("contig != null") - @Ensures("result != null") - public final SAMSequenceRecord getSequence(final String contig) { - if ( isCached(contig) ) - return lastSSR; - else - return updateCache(contig, -1); - } - - @Requires("index >= 0") - @Ensures("result != null") - public final SAMSequenceRecord getSequence(final int index) { - if ( isCached(index) ) - return lastSSR; - else - return updateCache(null, index); - } - - @Requires("contig != null") - @Ensures("result >= 0") - public final int getSequenceIndex(final String contig) { - if ( ! isCached(contig) ) { - updateCache(contig, -1); - } - - return lastIndex; - } - - @Requires({"contig != null", "lastContig != null"}) - private boolean isCached(final String contig) { - return lastContig.equals(contig); - } - - @Requires({"lastIndex != -1", "index >= 0"}) - private boolean isCached(final int index) { - return lastIndex == index; - } - - /** - * The key algorithm. Given a new record, update the last used record, contig - * name, and index. - * - * @param contig - * @param index - * @return - */ - @Requires("contig != null || index >= 0") - @Ensures("result != null") - private SAMSequenceRecord updateCache(final String contig, int index ) { - SAMSequenceRecord rec = contig == null ? dict.getSequence(index) : dict.getSequence(contig); - if ( rec == null ) { - throw new ReviewedStingException("BUG: requested unknown contig=" + contig + " index=" + index); - } else { - lastSSR = rec; - lastContig = rec.getSequenceName(); - lastIndex = rec.getSequenceIndex(); - return rec; - } - } - } - /** * set our internal reference contig order * @param refFile the reference file @@ -205,16 +108,18 @@ public final class GenomeLocParser { /** * Create a genome loc parser based on seqDict with the specified level of validation * @param seqDict the sequence dictionary to use when creating genome locs - * @param validationLevel how much validation should we do of the genome locs at runtime? + * @param validationLevel how much validation should we do of the genome locs at runtime? Purely for testing purposes */ - public GenomeLocParser(SAMSequenceDictionary seqDict, final ValidationLevel validationLevel) { - this.validationLevel = validationLevel; + protected GenomeLocParser(SAMSequenceDictionary seqDict, final ValidationLevel validationLevel) { + if (validationLevel == null) + throw new IllegalArgumentException("validation level cannot be null"); if (seqDict == null) { // we couldn't load the reference dictionary //logger.info("Failed to load reference dictionary, falling back to lexicographic order for contigs"); throw new UserException.CommandLineException("Failed to load reference dictionary"); } - SINGLE_MASTER_SEQUENCE_DICTIONARY = seqDict; + this.validationLevel = validationLevel; + this.SINGLE_MASTER_SEQUENCE_DICTIONARY = seqDict; if ( logger.isDebugEnabled() ) { logger.debug(String.format("Prepared reference sequence contig dictionary")); for (SAMSequenceRecord contig : seqDict.getSequences()) { @@ -227,17 +132,13 @@ public final class GenomeLocParser { * Determines whether the given contig is valid with respect to the sequence dictionary * already installed in the GenomeLoc. * + * @param contig a potentially null string name for the contig * @return True if the contig is valid. False otherwise. */ - public final boolean contigIsInDictionary(String contig) { + public final boolean contigIsInDictionary(final String contig) { return contig != null && getContigInfo().hasContig(contig); } - public final boolean indexIsInDictionary(final int index) { - return index >= 0 && getContigInfo().hasContig(index); - } - - /** * get the contig's SAMSequenceRecord * @@ -278,7 +179,7 @@ public final class GenomeLocParser { * @return */ public final SAMSequenceDictionary getContigs() { - return getContigInfo().dict; + return getContigInfo().getDictionary(); } // -------------------------------------------------------------------------------------------------------------- @@ -286,14 +187,13 @@ public final class GenomeLocParser { // Low-level creation functions // // -------------------------------------------------------------------------------------------------------------- + /** - * create a genome loc, given the contig name, start, and stop + * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation. * - * @param contig the contig name - * @param start the starting position - * @param stop the stop position - * - * @return a new genome loc + * Note that because this function doesn't take the contig index as an argument for contig, it + * has a slight performance penalty over the version that does take the contig index. Does not + * require the created genome loc on the reference genome */ @Ensures("result != null") @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop)"}) @@ -301,34 +201,61 @@ public final class GenomeLocParser { return createGenomeLoc(contig, getContigIndex(contig), start, stop); } - public GenomeLoc createGenomeLoc(String contig, final int start, final int stop, boolean mustBeOnReference) { + /** + * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation. + * + * Note that because this function doesn't take the contig index as an argument for contig, it + * has a slight performance penalty over the version that does take the contig index. + */ + public GenomeLoc createGenomeLoc(final String contig, final int start, final int stop, boolean mustBeOnReference) { return createGenomeLoc(contig, getContigIndex(contig), start, stop, mustBeOnReference); } + /** + * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation. + * + * Doesn't require the start and stop to be on the genome + */ @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop, false)"}) public GenomeLoc createGenomeLoc(String contig, int index, final int start, final int stop) { return createGenomeLoc(contig, index, start, stop, false); } + /** + * Create a GenomeLoc on contig, starting at start and ending (inclusive) at stop. + * + * @param contig the contig name + * @param index the index into the GATK's SAMSequencingDictionary of contig (passed for efficiency to avoid the lookup) + * @param start the starting position + * @param stop the stop position of this loc, inclusive + * @param mustBeOnReference if true, this factory will throw a UserException.MalformedGenomeLoc if start or stop isn't on the contig + * + * @return a non-null GenomeLoc + */ @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, start, stop,mustBeOnReference)"}) - public GenomeLoc createGenomeLoc(String contig, int index, final int start, final int stop, boolean mustBeOnReference) { + @Ensures("result != null") + public GenomeLoc createGenomeLoc(final String contig, int index, final int start, final int stop, boolean mustBeOnReference) { // optimization: by interning the string we ensure that future comparisons use == not the full string comp final String interned = validateGenomeLoc(contig, index, start, stop, mustBeOnReference); return new GenomeLoc(interned, index, start, stop); } /** - * Create a new genome loc, bounding start and stop by the start and end of contig - * @param contig our contig - * @param start our start as an arbitrary integer (may be negative, etc) - * @param stop our stop as an arbitrary integer (may be negative, etc) - * @throws ReviewedStingException if there's no way to create a meaningful genome loc given contig, start, and stop - * @return a valid genome loc over contig + * Create a new GenomeLoc, on contig, including the single position pos. + * + * Pos is not required to be on the reference + * + * @see #createGenomeLoc(String, int, int, int, boolean) for exact details of the creation. + * + * @param contig the contig name + * @param pos the start and stop of the created genome loc + * + * @return a genome loc representing a single base at the specified postion on the contig */ - public GenomeLoc createGenomeLocOnContig(final String contig, final int start, final int stop) { - final GenomeLoc myLoc = createGenomeLoc(contig, start, stop); - final GenomeLoc contigLoc = createOverEntireContig(contig); - return myLoc.intersect(contigLoc); + @Ensures("result != null") + @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, pos, pos, true)"}) + public GenomeLoc createGenomeLoc(final String contig, final int pos) { + return createGenomeLoc(contig, getContigIndex(contig), pos, pos); } /** @@ -472,7 +399,7 @@ public final class GenomeLocParser { */ @Requires("pos != null") @Ensures("result >= 0") - private int parsePosition(final String pos) { + protected int parsePosition(final String pos) { if(pos.indexOf('-') != -1) { throw new NumberFormatException("Position: '" + pos + "' can't contain '-'." ); } @@ -533,89 +460,34 @@ public final class GenomeLocParser { } /** - * Creates a GenomeLoc corresponding to the variant context vc. If includeSymbolicEndIfPossible - * is true, and VC is a symbolic allele the end of the created genome loc will be the value - * of the END info field key, if it exists, or vc.getEnd() if not. - * - * @param vc - * @param includeSymbolicEndIfPossible - * @return + * @see GenomeLoc.setStart */ - public GenomeLoc createGenomeLoc(final VariantContext vc, boolean includeSymbolicEndIfPossible) { - if ( includeSymbolicEndIfPossible && vc.isSymbolic() ) { - int end = vc.getAttributeAsInt(VCFConstants.END_KEY, vc.getEnd()); - return createGenomeLoc(vc.getChr(), vc.getStart(), end); - } - else - return createGenomeLoc(vc.getChr(), vc.getStart(), vc.getEnd()); - } - - public GenomeLoc createGenomeLoc(final VariantContext vc) { - return createGenomeLoc(vc, false); - } - - /** - * create a new genome loc, given the contig name, and a single position. Must be on the reference - * - * @param contig the contig name - * @param pos the postion - * - * @return a genome loc representing a single base at the specified postion on the contig - */ - @Ensures("result != null") - @ThrowEnsures({"UserException.MalformedGenomeLoc", "!isValidGenomeLoc(contig, pos, pos, true)"}) - public GenomeLoc createGenomeLoc(final String contig, final int pos) { - return createGenomeLoc(contig, getContigIndex(contig), pos, pos); - } - - /** - * create a new genome loc from an existing loc, with a new start position - * Note that this function will NOT explicitly check the ending offset, in case someone wants to - * set the start of a new GenomeLoc pertaining to a read that goes off the end of the contig. - * - * @param loc the old location - * @param start a new start position - * - * @return the newly created genome loc - */ - public GenomeLoc setStart(GenomeLoc loc, int start) { + @Deprecated + public GenomeLoc setStart(final GenomeLoc loc, final int start) { return createGenomeLoc(loc.getContig(), loc.getContigIndex(), start, loc.getStop()); } /** - * create a new genome loc from an existing loc, with a new stop position - * Note that this function will NOT explicitly check the ending offset, in case someone wants to - * set the stop of a new GenomeLoc pertaining to a read that goes off the end of the contig. - * - * @param loc the old location - * @param stop a new stop position - * - * @return + * @see GenomeLoc.setStop */ - public GenomeLoc setStop(GenomeLoc loc, int stop) { + @Deprecated + public GenomeLoc setStop(final GenomeLoc loc, final int stop) { return createGenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start, stop); } /** - * return a new genome loc, with an incremented position - * - * @param loc the old location - * - * @return a new genome loc + * @see GenomeLoc.incPos */ - public GenomeLoc incPos(GenomeLoc loc) { + @Deprecated + public GenomeLoc incPos(final GenomeLoc loc) { return incPos(loc, 1); } /** - * return a new genome loc, with an incremented position - * - * @param loc the old location - * @param by how much to move the start and stop by - * - * @return a new genome loc + * @see GenomeLoc.incPos */ - public GenomeLoc incPos(GenomeLoc loc, int by) { + @Deprecated + public GenomeLoc incPos(final GenomeLoc loc, final int by) { return createGenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start + by, loc.stop + by); } @@ -626,7 +498,7 @@ public final class GenomeLocParser { */ @Requires("contigName != null") @Ensures("result != null") - public GenomeLoc createOverEntireContig(String contigName) { + public GenomeLoc createOverEntireContig(final String contigName) { SAMSequenceRecord contig = getContigInfo().getSequence(contigName); return createGenomeLoc(contigName,contig.getSequenceIndex(),1,contig.getSequenceLength(), true); } @@ -638,12 +510,12 @@ public final class GenomeLocParser { * @return The contiguous loc of up to maxBasePairs length or null if the loc is already at the start of the contig. */ @Requires({"loc != null", "maxBasePairs > 0"}) - public GenomeLoc createGenomeLocAtStart(GenomeLoc loc, int maxBasePairs) { + public GenomeLoc createGenomeLocAtStart(final GenomeLoc loc, final int maxBasePairs) { if (GenomeLoc.isUnmapped(loc)) return null; - String contigName = loc.getContig(); - SAMSequenceRecord contig = getContigInfo().getSequence(contigName); - int contigIndex = contig.getSequenceIndex(); + final String contigName = loc.getContig(); + final SAMSequenceRecord contig = getContigInfo().getSequence(contigName); + final int contigIndex = contig.getSequenceIndex(); int start = loc.getStart() - maxBasePairs; int stop = loc.getStart() - 1; @@ -662,19 +534,12 @@ public final class GenomeLocParser { * @param padding The number of base pairs to pad on either end * @return The contiguous loc of length up to the original length + 2*padding (depending on the start/end of the contig). */ - @Requires({"loc != null", "padding > 0"}) + @Requires({"loc != null", "padding >= 0"}) public GenomeLoc createPaddedGenomeLoc(final GenomeLoc loc, final int padding) { - if (GenomeLoc.isUnmapped(loc)) + if (GenomeLoc.isUnmapped(loc) || padding == 0) return loc; - final String contigName = loc.getContig(); - final SAMSequenceRecord contig = getContigInfo().getSequence(contigName); - final int contigIndex = contig.getSequenceIndex(); - final int contigLength = contig.getSequenceLength(); - - final int start = Math.max(1, loc.getStart() - padding); - final int stop = Math.min(contigLength, loc.getStop() + padding); - - return createGenomeLoc(contigName, contigIndex, start, stop, true); + else + return createGenomeLocOnContig(loc.getContig(), loc.getContigIndex(), loc.getStart() - padding, loc.getStop() + padding); } /** @@ -684,7 +549,7 @@ public final class GenomeLocParser { * @return The contiguous loc of up to maxBasePairs length or null if the loc is already at the end of the contig. */ @Requires({"loc != null", "maxBasePairs > 0"}) - public GenomeLoc createGenomeLocAtStop(GenomeLoc loc, int maxBasePairs) { + public GenomeLoc createGenomeLocAtStop(final GenomeLoc loc, final int maxBasePairs) { if (GenomeLoc.isUnmapped(loc)) return null; String contigName = loc.getContig(); @@ -702,4 +567,35 @@ public final class GenomeLocParser { return createGenomeLoc(contigName, contigIndex, start, stop, true); } + + /** + * @see #createGenomeLocOnContig(String, int, int, int) with the contig index looked up from contig + */ + public GenomeLoc createGenomeLocOnContig(final String contig, final int start, final int stop) { + return createGenomeLocOnContig(contig, getContigIndex(contig), start, stop); + } + + /** + * Create a new genome loc, bounding start and stop by the start and end of contig + * + * This function will return null if start and stop cannot be adjusted in any reasonable way + * to be on the contig. For example, if start and stop are both past the end of the contig, + * there's no way to fix this, and null will be returned. + * + * @param contig our contig + * @param start our start as an arbitrary integer (may be negative, etc) + * @param stop our stop as an arbitrary integer (may be negative, etc) + * @return a valid genome loc over contig, or null if a meaningful genome loc cannot be created + */ + public GenomeLoc createGenomeLocOnContig(final String contig, final int contigIndex, final int start, final int stop) { + final int contigLength = getContigInfo().getSequence(contigIndex).getSequenceLength(); + final int boundedStart = Math.max(1, start); + final int boundedStop = Math.min(contigLength, stop); + + if ( boundedStart > contigLength || boundedStop < 1 ) + // there's no meaningful way to create this genome loc, as the start and stop are off the contig + return null; + else + return createGenomeLoc(contig, contigIndex, boundedStart, boundedStop); + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/MRUCachingSAMSequenceDictionary.java b/public/java/src/org/broadinstitute/sting/utils/MRUCachingSAMSequenceDictionary.java new file mode 100644 index 000000000..c11aeb730 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/MRUCachingSAMSequenceDictionary.java @@ -0,0 +1,186 @@ +/* + * 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.utils; + +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; +import net.sf.samtools.SAMSequenceDictionary; +import net.sf.samtools.SAMSequenceRecord; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; + +/** + * A wrapper class that provides efficient most recently used caching for the global + * SAMSequenceDictionary underlying all of the GATK engine capabilities. It is essential + * that these class be as efficient as possible. It doesn't need to be thread-safe, as + * GenomeLocParser uses a thread-local variable to ensure that each thread gets its own MRU + * cache. + * + * The MRU elements are the SAMSequenceRecord, the lastContig, and the lastIndex. The + * cached value is the actual SAMSequenceRecord of the most recently accessed value from + * getSequence, along with local variables for the contig index and contig string. + */ +final class MRUCachingSAMSequenceDictionary { + /** + * Our sequence dictionary + */ + private final SAMSequenceDictionary dict; + + SAMSequenceRecord lastSSR = null; + String lastContig = ""; + int lastIndex = -1; + + /** + * Create a new MRUCachingSAMSequenceDictionary that provides information about sequences in dict + * @param dict a non-null, non-empty sequencing dictionary + */ + @Ensures("lastSSR == null") + public MRUCachingSAMSequenceDictionary(final SAMSequenceDictionary dict) { + if ( dict == null ) throw new IllegalArgumentException("Dictionary cannot be null"); + if ( dict.size() == 0 ) throw new IllegalArgumentException("Dictionary cannot have size zero"); + + this.dict = dict; + } + + /** + * Get our sequence dictionary + * @return a non-null SAMSequenceDictionary + */ + @Ensures("result != null") + public SAMSequenceDictionary getDictionary() { + return dict; + } + + /** + * Is contig present in the dictionary? Efficiently caching. + * @param contig a non-null contig we want to test + * @return true if contig is in dictionary, false otherwise + */ + @Requires("contig != null") + public final boolean hasContig(final String contig) { + return contig.equals(lastContig) || dict.getSequence(contig) != null; + } + + /** + * Is contig index present in the dictionary? Efficiently caching. + * @param contigIndex an integer offset that might map to a contig in this dictionary + * @return true if contigIndex is in dictionary, false otherwise + */ + @Requires("contigIndex >= 0") + public final boolean hasContigIndex(final int contigIndex) { + return lastIndex == contigIndex || dict.getSequence(contigIndex) != null; + } + + /** + * Same as SAMSequenceDictionary.getSequence but uses a MRU cache for efficiency + * + * @param contig the contig name we want to get the sequence record of + * @throws ReviewedStingException if contig isn't present in the dictionary + * @return the sequence record for contig + */ + @Requires("contig != null") + @Ensures("result != null") + public final SAMSequenceRecord getSequence(final String contig) { + if ( isCached(contig) ) + return lastSSR; + else + return updateCache(contig, -1); + } + + /** + * Same as SAMSequenceDictionary.getSequence but uses a MRU cache for efficiency + * + * @param index the contig index we want to get the sequence record of + * @throws ReviewedStingException if contig isn't present in the dictionary + * @return the sequence record for contig + */ + @Requires("index >= 0") + @Ensures("result != null") + public final SAMSequenceRecord getSequence(final int index) { + if ( isCached(index) ) + return lastSSR; + else + return updateCache(null, index); + } + + /** + * Same as SAMSequenceDictionary.getSequenceIndex but uses a MRU cache for efficiency + * + * @param contig the contig we want to get the sequence record of + * @throws ReviewedStingException if index isn't present in the dictionary + * @return the sequence record index for contig + */ + @Requires("contig != null") + @Ensures("result >= 0") + public final int getSequenceIndex(final String contig) { + if ( ! isCached(contig) ) { + updateCache(contig, -1); + } + + return lastIndex; + } + + /** + * Is contig the MRU cached contig? + * @param contig the contig to test + * @return true if contig is the currently cached contig, false otherwise + */ + @Requires({"contig != null"}) + protected boolean isCached(final String contig) { + return contig.equals(lastContig); + } + + /** + * Is the contig index index the MRU cached index? + * @param index the contig index to test + * @return true if contig index is the currently cached contig index, false otherwise + */ + protected boolean isCached(final int index) { + return lastIndex == index; + } + + /** + * The key algorithm. Given a new record, update the last used record, contig + * name, and index. + * + * @param contig the contig we want to look up. If null, index is used instead + * @param index the contig index we want to look up. Only used if contig is null + * @throws ReviewedStingException if index isn't present in the dictionary + * @return the SAMSequenceRecord for contig / index + */ + @Requires("contig != null || index >= 0") + @Ensures("result != null") + private SAMSequenceRecord updateCache(final String contig, int index ) { + SAMSequenceRecord rec = contig == null ? dict.getSequence(index) : dict.getSequence(contig); + if ( rec == null ) { + throw new ReviewedStingException("BUG: requested unknown contig=" + contig + " index=" + index); + } else { + lastSSR = rec; + lastContig = rec.getSequenceName(); + lastIndex = rec.getSequenceIndex(); + return rec; + } + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserUnitTest.java index 4a989b984..9621aecda 100644 --- a/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/GenomeLocParserUnitTest.java @@ -29,17 +29,31 @@ package org.broadinstitute.sting.utils; import net.sf.samtools.SAMFileHeader; import net.sf.samtools.SAMSequenceDictionary; import net.sf.samtools.SAMSequenceRecord; +import org.broad.tribble.BasicFeature; +import org.broad.tribble.Feature; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.variant.variantcontext.Allele; +import org.broadinstitute.variant.variantcontext.VariantContext; +import org.broadinstitute.variant.variantcontext.VariantContextBuilder; +import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + /** * @author aaron *

@@ -49,10 +63,11 @@ import org.testng.annotations.Test; */ public class GenomeLocParserUnitTest extends BaseTest { private GenomeLocParser genomeLocParser; + private SAMFileHeader header; @BeforeClass public void init() { - SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10); + header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10); genomeLocParser = new GenomeLocParser(header.getSequenceDictionary()); } @@ -231,7 +246,16 @@ public class GenomeLocParserUnitTest extends BaseTest { assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",1,11)); // past the end of the contig assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",-1,10)); // bad start assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",1,-2)); // bad stop + assertTrue( genomeLocParser.isValidGenomeLoc("chr1",-1,2, false)); // bad stop assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",10,11)); // bad start, past end + assertTrue( genomeLocParser.isValidGenomeLoc("chr1",10,11, false)); // bad start, past end + assertTrue(!genomeLocParser.isValidGenomeLoc("chr1",2,1)); // stop < start + } + + @Test(expectedExceptions = ReviewedStingException.class) + public void testValidateGenomeLoc() { + // bad contig index + genomeLocParser.validateGenomeLoc("chr1", 1, 1, 2, false); } private static class FlankingGenomeLocTestData extends TestDataProvider { @@ -333,4 +357,153 @@ public class GenomeLocParserUnitTest extends BaseTest { data.toString(), data.original, actual, data.flankStop); assertEquals(actual, data.flankStop, description); } + + @DataProvider(name = "parseGenomeLoc") + public Object[][] makeParsingTest() { + final List tests = new LinkedList(); + + tests.add(new Object[]{ "chr1:10", "chr1", 10 }); + tests.add(new Object[]{ "chr1:100", "chr1", 100 }); + tests.add(new Object[]{ "chr1:1000", "chr1", 1000 }); + tests.add(new Object[]{ "chr1:1,000", "chr1", 1000 }); + tests.add(new Object[]{ "chr1:10000", "chr1", 10000 }); + tests.add(new Object[]{ "chr1:10,000", "chr1", 10000 }); + tests.add(new Object[]{ "chr1:100000", "chr1", 100000 }); + tests.add(new Object[]{ "chr1:100,000", "chr1", 100000 }); + tests.add(new Object[]{ "chr1:1000000", "chr1", 1000000 }); + tests.add(new Object[]{ "chr1:1,000,000", "chr1", 1000000 }); + tests.add(new Object[]{ "chr1:1000,000", "chr1", 1000000 }); + tests.add(new Object[]{ "chr1:1,000000", "chr1", 1000000 }); + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "parseGenomeLoc") + public void testParsingPositions(final String string, final String contig, final int start) { + SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(1, 1, 10000000); + GenomeLocParser genomeLocParser = new GenomeLocParser(header.getSequenceDictionary()); + final GenomeLoc loc = genomeLocParser.parseGenomeLoc(string); + Assert.assertEquals(loc.getContig(), contig); + Assert.assertEquals(loc.getStart(), start); + Assert.assertEquals(loc.getStop(), start); + } + + @Test( ) + public void testCreationFromSAMRecord() { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(read); + Assert.assertEquals(loc.getContig(), read.getReferenceName()); + Assert.assertEquals(loc.getContigIndex(), (int)read.getReferenceIndex()); + Assert.assertEquals(loc.getStart(), read.getAlignmentStart()); + Assert.assertEquals(loc.getStop(), read.getAlignmentEnd()); + } + + @Test( ) + public void testCreationFromSAMRecordUnmapped() { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5); + read.setReadUnmappedFlag(true); + read.setReferenceIndex(-1); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(read); + Assert.assertTrue(loc.isUnmapped()); + } + + @Test( ) + public void testCreationFromSAMRecordUnmappedButOnGenome() { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, 1, 5); + read.setReadUnmappedFlag(true); + read.setCigarString("*"); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(read); + Assert.assertEquals(loc.getContig(), read.getReferenceName()); + Assert.assertEquals(loc.getContigIndex(), (int)read.getReferenceIndex()); + Assert.assertEquals(loc.getStart(), read.getAlignmentStart()); + Assert.assertEquals(loc.getStop(), read.getAlignmentStart()); + } + + @Test + public void testCreationFromFeature() { + final Feature feature = new BasicFeature("chr1", 1, 5); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(feature); + Assert.assertEquals(loc.getContig(), feature.getChr()); + Assert.assertEquals(loc.getStart(), feature.getStart()); + Assert.assertEquals(loc.getStop(), feature.getEnd()); + } + + @Test + public void testCreationFromVariantContext() { + final VariantContext feature = new VariantContextBuilder("x", "chr1", 1, 5, Arrays.asList(Allele.create("AAAAA", true))).make(); + final GenomeLoc loc = genomeLocParser.createGenomeLoc(feature); + Assert.assertEquals(loc.getContig(), feature.getChr()); + Assert.assertEquals(loc.getStart(), feature.getStart()); + Assert.assertEquals(loc.getStop(), feature.getEnd()); + } + + @Test + public void testcreateGenomeLocOnContig() throws FileNotFoundException { + final CachingIndexedFastaSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + final SAMSequenceDictionary dict = seq.getSequenceDictionary(); + final GenomeLocParser genomeLocParser = new GenomeLocParser(dict); + + for ( final SAMSequenceRecord rec : dict.getSequences() ) { + final GenomeLoc loc = genomeLocParser.createOverEntireContig(rec.getSequenceName()); + Assert.assertEquals(loc.getContig(), rec.getSequenceName()); + Assert.assertEquals(loc.getStart(), 1); + Assert.assertEquals(loc.getStop(), rec.getSequenceLength()); + } + } + + @DataProvider(name = "GenomeLocOnContig") + public Object[][] makeGenomeLocOnContig() { + final List tests = new LinkedList(); + + final int contigLength = header.getSequence(0).getSequenceLength(); + for ( int start = -10; start < contigLength + 10; start++ ) { + for ( final int len : Arrays.asList(1, 10, 20) ) { + tests.add(new Object[]{ "chr1", start, start + len }); + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "GenomeLocOnContig") + public void testGenomeLocOnContig(final String contig, final int start, final int stop) { + final int contigLength = header.getSequence(0).getSequenceLength(); + final GenomeLoc loc = genomeLocParser.createGenomeLocOnContig(contig, start, stop); + + if ( stop < 1 || start > contigLength ) + Assert.assertNull(loc, "GenomeLoc should be null if the start/stops are not meaningful"); + else { + Assert.assertNotNull(loc); + Assert.assertEquals(loc.getContig(), contig); + Assert.assertEquals(loc.getStart(), Math.max(start, 1)); + Assert.assertEquals(loc.getStop(), Math.min(stop, contigLength)); + } + } + + @DataProvider(name = "GenomeLocPadding") + public Object[][] makeGenomeLocPadding() { + final List tests = new LinkedList(); + + final int contigLength = header.getSequence(0).getSequenceLength(); + for ( int pad = 0; pad < contigLength + 1; pad++) { + for ( int start = 1; start < contigLength; start++ ) { + for ( int stop = start; stop < contigLength; stop++ ) { + tests.add(new Object[]{ genomeLocParser.createGenomeLoc("chr1", start, stop), pad}); + } + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test( dataProvider = "GenomeLocPadding") + public void testGenomeLocPadding(final GenomeLoc input, final int pad) { + final int contigLength = header.getSequence(0).getSequenceLength(); + final GenomeLoc padded = genomeLocParser.createPaddedGenomeLoc(input, pad); + + Assert.assertNotNull(padded); + Assert.assertEquals(padded.getContig(), input.getContig()); + Assert.assertEquals(padded.getStart(), Math.max(input.getStart() - pad, 1)); + Assert.assertEquals(padded.getStop(), Math.min(input.getStop() + pad, contigLength)); + } } diff --git a/public/java/test/org/broadinstitute/sting/utils/MRUCachingSAMSequencingDictionaryUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/MRUCachingSAMSequencingDictionaryUnitTest.java new file mode 100644 index 000000000..7a5fcf0c2 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/utils/MRUCachingSAMSequencingDictionaryUnitTest.java @@ -0,0 +1,97 @@ +/* + * 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.utils; + + +import net.sf.picard.reference.ReferenceSequenceFile; +import net.sf.samtools.SAMFileHeader; +import net.sf.samtools.SAMSequenceDictionary; +import net.sf.samtools.SAMSequenceRecord; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.exceptions.UserException; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.LinkedList; +import java.util.List; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class MRUCachingSAMSequencingDictionaryUnitTest extends BaseTest { + private static ReferenceSequenceFile seq; + private static SAMSequenceDictionary dict; + + @BeforeClass + public void init() throws FileNotFoundException { + // sequence + seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + dict = seq.getSequenceDictionary(); + } + + @Test + public void testBasic() { + final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict); + + Assert.assertEquals(caching.getDictionary(), dict, "Dictionary not the one I expected"); + + for ( final SAMSequenceRecord rec : dict.getSequences() ) { + Assert.assertFalse(caching.isCached(rec.getSequenceIndex()), "Expected index to not be cached"); + Assert.assertFalse(caching.isCached(rec.getSequenceName()), "Expected contig to not be cached"); + + Assert.assertEquals(caching.getSequence(rec.getSequenceName()), rec, "Couldn't query for sequence"); + Assert.assertEquals(caching.getSequence(rec.getSequenceIndex()), rec, "Couldn't query for sequence index"); + Assert.assertEquals(caching.hasContig(rec.getSequenceName()), true, "hasContig query for sequence"); + Assert.assertEquals(caching.hasContigIndex(rec.getSequenceIndex()), true, "hasContigIndex query for sequence"); + Assert.assertEquals(caching.getSequenceIndex(rec.getSequenceName()), rec.getSequenceIndex(), "Couldn't query for sequence"); + + Assert.assertEquals(caching.hasContig(rec.getSequenceName() + "asdfadsfa"), false, "hasContig query for unknown sequence"); + Assert.assertEquals(caching.hasContigIndex(dict.getSequences().size()), false, "hasContigIndex query for unknown index"); + + Assert.assertTrue(caching.isCached(rec.getSequenceIndex()), "Expected index to be cached"); + Assert.assertTrue(caching.isCached(rec.getSequenceName()), "Expected contig to be cached"); + } + } + + @Test(expectedExceptions = ReviewedStingException.class) + public void testBadGetSequence() { + final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict); + caching.getSequence("notInDictionary"); + } + + @Test(expectedExceptions = ReviewedStingException.class) + public void testBadGetSequenceIndex() { + final MRUCachingSAMSequenceDictionary caching = new MRUCachingSAMSequenceDictionary(dict); + caching.getSequence(dict.getSequences().size()); + } +} \ No newline at end of file From 59311aeea21842f7a6c69df1f49230edf90ee98f Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 10:06:14 -0500 Subject: [PATCH 140/188] Getting back null values from the tables is perfectly reasonable if those covariates don't appear in your table. Need to handle them gracefully. --- .../recalibration/BaseRecalibration.java | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index c8d460308..bc7c5a1ce 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -150,33 +150,36 @@ public class BaseRecalibration { // the rg key is constant over the whole read, the global deltaQ is too final int rgKey = fullReadKeySet[0][0]; final RecalDatum empiricalQualRG = recalibrationTables.getReadGroupTable().get(rgKey, errorModel.ordinal()); - final double epsilon = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : empiricalQualRG.getEstimatedQReported() ); - for (int offset = 0; offset < readLength; offset++) { // recalibrate all bases in the read - final byte origQual = quals[offset]; + if( empiricalQualRG != null ) { + final double epsilon = ( globalQScorePrior > 0.0 && errorModel.equals(EventType.BASE_SUBSTITUTION) ? globalQScorePrior : empiricalQualRG.getEstimatedQReported() ); - // only recalibrate usable qualities (the original quality will come from the instrument -- reported quality) - if ( origQual >= preserveQLessThan ) { - // get the keyset for this base using the error model - final int[] keySet = fullReadKeySet[offset]; - final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(keySet[0], keySet[1], errorModel.ordinal()); - final List empiricalQualCovs = new ArrayList(); - for (int i = 2; i < requestedCovariates.length; i++) { - if (keySet[i] < 0) { - continue; + for (int offset = 0; offset < readLength; offset++) { // recalibrate all bases in the read + final byte origQual = quals[offset]; + + // only recalibrate usable qualities (the original quality will come from the instrument -- reported quality) + if ( origQual >= preserveQLessThan ) { + // get the keyset for this base using the error model + final int[] keySet = fullReadKeySet[offset]; + final RecalDatum empiricalQualQS = recalibrationTables.getQualityScoreTable().get(keySet[0], keySet[1], errorModel.ordinal()); + final List empiricalQualCovs = new ArrayList(); + for (int i = 2; i < requestedCovariates.length; i++) { + if (keySet[i] < 0) { + continue; + } + empiricalQualCovs.add(recalibrationTables.getTable(i).get(keySet[0], keySet[1], keySet[i], errorModel.ordinal())); } - empiricalQualCovs.add(recalibrationTables.getTable(i).get(keySet[0], keySet[1], keySet[i], errorModel.ordinal())); + + double recalibratedQualDouble = hierarchicalBayesianQualityEstimate( epsilon, empiricalQualRG, empiricalQualQS, empiricalQualCovs ); + + // recalibrated quality is bound between 1 and MAX_QUAL + final byte recalibratedQual = QualityUtils.boundQual(MathUtils.fastRound(recalibratedQualDouble), QualityUtils.MAX_RECALIBRATED_Q_SCORE); + + // return the quantized version of the recalibrated quality + final byte recalibratedQualityScore = quantizationInfo.getQuantizedQuals().get(recalibratedQual); + + quals[offset] = recalibratedQualityScore; } - - double recalibratedQualDouble = hierarchicalBayesianQualityEstimate( epsilon, empiricalQualRG, empiricalQualQS, empiricalQualCovs ); - - // recalibrated quality is bound between 1 and MAX_QUAL - final byte recalibratedQual = QualityUtils.boundQual(MathUtils.fastRound(recalibratedQualDouble), QualityUtils.MAX_RECALIBRATED_Q_SCORE); - - // return the quantized version of the recalibrated quality - final byte recalibratedQualityScore = quantizationInfo.getQuantizedQuals().get(recalibratedQual); - - quals[offset] = recalibratedQualityScore; } } From 4852c7404e5e4ba55408c59a9e8088fc608b4edd Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 30 Jan 2013 10:12:27 -0500 Subject: [PATCH 141/188] GenomeLocs are already comparable, so I'm removing the less complete GenomeLocComparator class and updating ReduceReads and CompressionStash to use built-in comparator --- .../reducereads/CompressionStash.java | 4 +- .../compression/reducereads/ReduceReads.java | 5 +- .../sting/utils/GenomeLocComparator.java | 81 ------------------- 3 files changed, 3 insertions(+), 87 deletions(-) delete mode 100644 public/java/src/org/broadinstitute/sting/utils/GenomeLocComparator.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java index 9f2a7f270..2bc946618 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java @@ -46,8 +46,6 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import org.broadinstitute.sting.utils.GenomeLocComparator; - import java.util.Collection; import java.util.TreeSet; @@ -63,7 +61,7 @@ import java.util.TreeSet; */ public class CompressionStash extends TreeSet { public CompressionStash() { - super(new GenomeLocComparator()); + super(); } /** diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java index 25006bb49..7e82629b8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java @@ -64,7 +64,6 @@ import org.broadinstitute.sting.gatk.walkers.PartitionType; import org.broadinstitute.sting.gatk.walkers.ReadFilters; import org.broadinstitute.sting.gatk.walkers.ReadWalker; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocComparator; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.clipping.ReadClipper; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; @@ -267,8 +266,8 @@ public class ReduceReads extends ReadWalker, ReduceRea public void initialize() { super.initialize(); GenomeAnalysisEngine toolkit = getToolkit(); - readNameHash = new HashMap(); // prepare the read name hash to keep track of what reads have had their read names compressed - intervalList = new TreeSet(new GenomeLocComparator()); // get the interval list from the engine. If no interval list was provided, the walker will work in WGS mode + readNameHash = new HashMap(); // prepare the read name hash to keep track of what reads have had their read names compressed + intervalList = new TreeSet(); // get the interval list from the engine. If no interval list was provided, the walker will work in WGS mode if (toolkit.getIntervals() != null) intervalList.addAll(toolkit.getIntervals()); diff --git a/public/java/src/org/broadinstitute/sting/utils/GenomeLocComparator.java b/public/java/src/org/broadinstitute/sting/utils/GenomeLocComparator.java deleted file mode 100644 index c8380ee7b..000000000 --- a/public/java/src/org/broadinstitute/sting/utils/GenomeLocComparator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -* 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.utils; - -import com.google.java.contract.Ensures; -import com.google.java.contract.Requires; - -import java.util.Comparator; - -/** - * - * @author Mauricio Carneiro - * @since 9/28/11 - */ -public class GenomeLocComparator implements Comparator { - /** - * compares genomeLoc's contigs - * - * @param gl1 the genome loc to compare contigs - * @param gl2 the genome loc to compare contigs - * @return 0 if equal, -1 if gl2.contig is greater, 1 if gl1.contig is greater - */ - @Requires("gl2 != null") - @Ensures("result == 0 || result == 1 || result == -1") - public final int compareContigs( GenomeLoc gl1, GenomeLoc gl2 ) { - if (gl1.contigIndex == gl2.contigIndex) - return 0; - else if (gl1.contigIndex > gl2.contigIndex) - return 1; - return -1; - } - - @Requires("gl2 != null") - @Ensures("result == 0 || result == 1 || result == -1") - public int compare ( GenomeLoc gl1, GenomeLoc gl2 ) { - int result = 0; - - if ( gl1 == gl2 ) { - result = 0; - } - else if(GenomeLoc.isUnmapped(gl1)) - result = 1; - else if(GenomeLoc.isUnmapped(gl2)) - result = -1; - else { - final int cmpContig = compareContigs(gl1, gl2); - - if ( cmpContig != 0 ) { - result = cmpContig; - } else { - if ( gl1.getStart() < gl2.getStart() ) result = -1; - if ( gl1.getStart() > gl2.getStart() ) result = 1; - } - } - - return result; - } -} From 9025567cb8e7ba057f0f27acd19bf3f77d93fc48 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 30 Jan 2013 10:45:29 -0500 Subject: [PATCH 142/188] Refactoring the SimpleGenomeLoc into the now public utility UnvalidatingGenomeLoc and the RR-specific FinishedGenomeLoc. Moved the merging utility methods into GenomeLoc and moved the unit tests around accordingly. --- .../reducereads/CompressionStash.java | 20 ++-- ...eGenomeLoc.java => FinishedGenomeLoc.java} | 66 ++--------- .../reducereads/SlidingWindow.java | 13 ++- .../reducereads/SimpleGenomeLocUnitTest.java | 106 ------------------ .../reducereads/SlidingWindowUnitTest.java | 39 +++---- .../broadinstitute/sting/utils/GenomeLoc.java | 50 ++++++++- .../sting/utils/UnvalidatingGenomeLoc.java | 50 +++++++++ .../sting/utils/GenomeLocUnitTest.java | 60 +++++++++- 8 files changed, 195 insertions(+), 209 deletions(-) rename protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/{SimpleGenomeLoc.java => FinishedGenomeLoc.java} (81%) delete mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java create mode 100644 public/java/src/org/broadinstitute/sting/utils/UnvalidatingGenomeLoc.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java index 9f2a7f270..ebc5ef8ed 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import org.broadinstitute.sting.utils.GenomeLocComparator; +import org.broadinstitute.sting.utils.*; import java.util.Collection; import java.util.TreeSet; @@ -61,22 +61,22 @@ import java.util.TreeSet; * Date: 10/15/12 * Time: 4:08 PM */ -public class CompressionStash extends TreeSet { +public class CompressionStash extends TreeSet { public CompressionStash() { super(new GenomeLocComparator()); } /** - * Adds a SimpleGenomeLoc to the stash and merges it with any overlapping (and contiguous) existing loc + * Adds a UnvalidatingGenomeLoc to the stash and merges it with any overlapping (and contiguous) existing loc * in the stash. * * @param insertLoc the new loc to be inserted * @return true if the loc, or it's merged version, wasn't present in the list before. */ @Override - public boolean add(SimpleGenomeLoc insertLoc) { - TreeSet removedLocs = new TreeSet(); - for (SimpleGenomeLoc existingLoc : this) { + public boolean add(FinishedGenomeLoc insertLoc) { + TreeSet removedLocs = new TreeSet(); + for (FinishedGenomeLoc existingLoc : this) { if (existingLoc.isPast(insertLoc)) { break; // if we're past the loc we're done looking for overlaps. } @@ -87,17 +87,17 @@ public class CompressionStash extends TreeSet { removedLocs.add(existingLoc); // list the original loc for merging } } - for (SimpleGenomeLoc loc : removedLocs) { + for (GenomeLoc loc : removedLocs) { this.remove(loc); // remove all locs that will be merged } removedLocs.add(insertLoc); // add the new loc to the list of locs that will be merged - return super.add(SimpleGenomeLoc.merge(removedLocs)); // merge them all into one loc and add to the stash + return super.add(new FinishedGenomeLoc(GenomeLoc.merge(removedLocs), insertLoc.isFinished())); } @Override - public boolean addAll(Collection locs) { + public boolean addAll(Collection locs) { boolean result = false; - for (SimpleGenomeLoc loc : locs) { + for (final FinishedGenomeLoc loc : locs) { result |= this.add(loc); } return result; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/FinishedGenomeLoc.java similarity index 81% rename from protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java rename to protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/FinishedGenomeLoc.java index 85a1f8df1..13010f905 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLoc.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/FinishedGenomeLoc.java @@ -46,11 +46,8 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import com.google.java.contract.Requires; import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; - -import java.util.SortedSet; +import org.broadinstitute.sting.utils.UnvalidatingGenomeLoc; /** * GenomeLocs are very useful objects to keep track of genomic locations and perform set operations @@ -59,70 +56,27 @@ import java.util.SortedSet; * However, GenomeLocs are bound to strict validation through the GenomeLocParser and cannot * be created easily for small tasks that do not require the rigors of the GenomeLocParser validation * - * SimpleGenomeLoc is a simple utility to create GenomeLocs without going through the parser. Should + * UnvalidatingGenomeLoc is a simple utility to create GenomeLocs without going through the parser. Should * only be used outside of the engine. * * User: carneiro * Date: 10/16/12 * Time: 2:07 PM */ -public class SimpleGenomeLoc extends GenomeLoc { +public class FinishedGenomeLoc extends UnvalidatingGenomeLoc { private boolean finished; - public SimpleGenomeLoc(String contigName, int contigIndex, int start, int stop, boolean finished) { - super(contigName, contigIndex, start, stop); + public FinishedGenomeLoc(final String contigName, final int contigIndex, final int start, final int stop, final boolean finished) { + super(contigName, contigIndex, start, stop); + this.finished = finished; + } + + public FinishedGenomeLoc(final GenomeLoc loc, final boolean finished) { + super(loc.getContig(), loc.getContigIndex(), loc.getStart(), loc.getStop()); this.finished = finished; } public boolean isFinished() { return finished; } - - /** - * Merges 2 *contiguous* locs into 1 - * - * @param a SimpleGenomeLoc #1 - * @param b SimpleGenomeLoc #2 - * @return one merged loc - */ - @Requires("a != null && b != null") - public static SimpleGenomeLoc merge(SimpleGenomeLoc a, SimpleGenomeLoc b) throws ReviewedStingException { - if(GenomeLoc.isUnmapped(a) || GenomeLoc.isUnmapped(b)) { - throw new ReviewedStingException("Tried to merge unmapped genome locs"); - } - - if (!(a.contiguousP(b))) { - throw new ReviewedStingException("The two genome locs need to be contiguous"); - } - - return new SimpleGenomeLoc(a.getContig(), a.contigIndex, - Math.min(a.getStart(), b.getStart()), - Math.max(a.getStop(), b.getStop()), - a.isFinished()); - } - - /** - * Merges a list of *sorted* *contiguous* locs into one - * - * @param sortedLocs a sorted list of contiguous locs - * @return one merged loc - */ - @Requires("sortedLocs != null") - public static SimpleGenomeLoc merge(SortedSet sortedLocs) { - SimpleGenomeLoc result = null; - - for ( SimpleGenomeLoc loc : sortedLocs ) { - if ( loc.isUnmapped() ) - throw new ReviewedStingException("Tried to merge unmapped genome locs"); - - if ( result == null ) - result = loc; - else if ( !result.contiguousP(loc) ) - throw new ReviewedStingException("The genome locs need to be contiguous"); - else - result = merge(result, loc); - } - - return result; - } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java index 7ce606f20..e2f8b6682 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java @@ -53,6 +53,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.gatk.downsampling.ReservoirDownsampler; +import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.recalibration.EventType; @@ -213,7 +214,7 @@ public class SlidingWindow { * @return null if nothing is variant, start/stop if there is a complete variant region, start/-1 if there is an incomplete variant region. All coordinates returned are global. */ @Requires({"from >= 0", "from <= to", "to <= variantSite.length"}) - private SimpleGenomeLoc findNextVariantRegion(int from, int to, boolean[] variantSite, boolean closeLastRegion) { + private FinishedGenomeLoc findNextVariantRegion(int from, int to, boolean[] variantSite, boolean closeLastRegion) { boolean foundStart = false; final int windowHeaderStart = getStartLocation(windowHeader); int variantRegionStartIndex = 0; @@ -223,12 +224,12 @@ public class SlidingWindow { foundStart = true; } else if(!variantSite[i] && foundStart) { - return(new SimpleGenomeLoc(contig, contigIndex, windowHeaderStart + variantRegionStartIndex, windowHeaderStart + i - 1, true)); + return(new FinishedGenomeLoc(contig, contigIndex, windowHeaderStart + variantRegionStartIndex, windowHeaderStart + i - 1, true)); } } final int refStart = windowHeaderStart + variantRegionStartIndex; final int refStop = windowHeaderStart + to - 1; - return (foundStart && closeLastRegion) ? new SimpleGenomeLoc(contig, contigIndex, refStart, refStop, true) : null; + return (foundStart && closeLastRegion) ? new FinishedGenomeLoc(contig, contigIndex, refStart, refStop, true) : null; } /** @@ -248,7 +249,7 @@ public class SlidingWindow { int index = from; while(index < to) { // returns results in global coordinates - SimpleGenomeLoc result = findNextVariantRegion(index, to, variantSite, closeLastRegion); + FinishedGenomeLoc result = findNextVariantRegion(index, to, variantSite, closeLastRegion); if (result == null) break; @@ -699,8 +700,8 @@ public class SlidingWindow { int lastStop = -1; int windowHeaderStart = getStartLocation(windowHeader); - for (SimpleGenomeLoc region : regions) { - if (region.isFinished() && region.getContig() == contig && region.getStart() >= windowHeaderStart && region.getStop() < windowHeaderStart + windowHeader.size()) { + for (GenomeLoc region : regions) { + if (((FinishedGenomeLoc)region).isFinished() && region.getContig() == contig && region.getStart() >= windowHeaderStart && region.getStop() < windowHeaderStart + windowHeader.size()) { int start = region.getStart() - windowHeaderStart; int stop = region.getStop() - windowHeaderStart; diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java deleted file mode 100644 index cbac7e3c1..000000000 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SimpleGenomeLocUnitTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* -* By downloading the PROGRAM you agree to the following terms of use: -* -* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY -* -* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). -* -* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and -* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. -* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: -* -* 1. DEFINITIONS -* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. -* -* 2. LICENSE -* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. -* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. -* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. -* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. -* -* 3. OWNERSHIP OF INTELLECTUAL PROPERTY -* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. -* Copyright 2012 Broad Institute, Inc. -* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. -* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. -* -* 4. INDEMNIFICATION -* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. -* -* 5. NO REPRESENTATIONS OR WARRANTIES -* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. -* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. -* -* 6. ASSIGNMENT -* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. -* -* 7. MISCELLANEOUS -* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. -* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. -* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. -* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. -* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. -* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. -* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. -*/ - -package org.broadinstitute.sting.gatk.walkers.compression.reducereads; - - -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.util.*; - -public class SimpleGenomeLocUnitTest extends BaseTest { - - private static final SimpleGenomeLoc loc1 = new SimpleGenomeLoc("1", 0, 10, 20, false); - private static final SimpleGenomeLoc loc2 = new SimpleGenomeLoc("1", 0, 21, 30, false); - private static final SimpleGenomeLoc loc3 = new SimpleGenomeLoc("1", 0, 31, 40, false); - - private class SGLTest { - public List locs; - - private SGLTest(final List locs) { - this.locs = locs; - } - } - - @DataProvider(name = "SGLtest") - public Object[][] createFindVariantRegionsData() { - List tests = new ArrayList(); - - tests.add(new Object[]{new SGLTest(Arrays.asList(loc1))}); - tests.add(new Object[]{new SGLTest(Arrays.asList(loc1, loc2))}); - tests.add(new Object[]{new SGLTest(Arrays.asList(loc1, loc2, loc3))}); - - return tests.toArray(new Object[][]{}); - } - - @Test(dataProvider = "SGLtest", enabled = true) - public void testSimpleGenomeLoc(SGLTest test) { - testMerge(test.locs); - } - - @Test(expectedExceptions = ReviewedStingException.class) - public void testNotContiguousLocs() { - final List locs = new ArrayList(1); - locs.add(loc1); - locs.add(loc3); - testMerge(locs); - } - - private void testMerge(final List locs) { - SimpleGenomeLoc result1 = locs.get(0); - for ( int i = 1; i < locs.size(); i++ ) - result1 = SimpleGenomeLoc.merge(result1, locs.get(i)); - - SimpleGenomeLoc result2 = SimpleGenomeLoc.merge(new TreeSet(locs)); - Assert.assertEquals(result1, result2); - Assert.assertEquals(result1.getStart(), locs.get(0).getStart()); - Assert.assertEquals(result1.getStop(), locs.get(locs.size() - 1).getStop()); - } -} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java index 3d3c4ad24..d9b55963d 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java @@ -46,14 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; -import net.sf.samtools.SAMFileHeader; -import net.sf.samtools.SAMReadGroupRecord; -import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; -import org.broadinstitute.sting.utils.sam.ArtificialSingleSampleReadStream; -import org.broadinstitute.sting.utils.sam.ArtificialSingleSampleReadStreamAnalyzer; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -70,31 +63,31 @@ public class SlidingWindowUnitTest extends BaseTest { private static final int variantRegionLength = 1000; private static final int globalStartPosition = 1000000; - private static final SimpleGenomeLoc loc90to95 = new SimpleGenomeLoc("1", 0, 1000090, 1000095, false); - private static final SimpleGenomeLoc loc96to99 = new SimpleGenomeLoc("1", 0, 1000096, 1000099, false); - private static final SimpleGenomeLoc loc100to110 = new SimpleGenomeLoc("1", 0, 1000100, 1000110, false); - private static final SimpleGenomeLoc loc999 = new SimpleGenomeLoc("1", 0, 1000999, 1000999, false); + private static final FinishedGenomeLoc loc90to95 = new FinishedGenomeLoc("1", 0, 1000090, 1000095, false); + private static final FinishedGenomeLoc loc96to99 = new FinishedGenomeLoc("1", 0, 1000096, 1000099, false); + private static final FinishedGenomeLoc loc100to110 = new FinishedGenomeLoc("1", 0, 1000100, 1000110, false); + private static final FinishedGenomeLoc loc999 = new FinishedGenomeLoc("1", 0, 1000999, 1000999, false); private class FindVariantRegionsTest { - public List locs, expectedResult; + public List locs, expectedResult; public boolean[] variantRegionBitset; - private FindVariantRegionsTest(final List locs) { + private FindVariantRegionsTest(final List locs) { this.locs = locs; this.expectedResult = locs; variantRegionBitset = createBitset(locs); } - private FindVariantRegionsTest(final List locs, final List expectedResult) { + private FindVariantRegionsTest(final List locs, final List expectedResult) { this.locs = locs; this.expectedResult = expectedResult; variantRegionBitset = createBitset(locs); } } - private static boolean[] createBitset(final List locs) { + private static boolean[] createBitset(final List locs) { boolean[] variantRegionBitset = new boolean[variantRegionLength]; - for ( SimpleGenomeLoc loc : locs ) { + for ( FinishedGenomeLoc loc : locs ) { final int stop = loc.getStop() - globalStartPosition; for ( int i = loc.getStart() - globalStartPosition; i <= stop; i++ ) variantRegionBitset[i] = true; @@ -106,11 +99,11 @@ public class SlidingWindowUnitTest extends BaseTest { public Object[][] createFindVariantRegionsData() { List tests = new ArrayList(); - tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95))}); - tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc100to110))}); - tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc96to99, loc100to110), Arrays.asList(new SimpleGenomeLoc("1", 0, 1000090, 1000110, false)))}); - tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc999))}); - tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc999))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc100to110))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc96to99, loc100to110), Arrays.asList(new FinishedGenomeLoc("1", 0, 1000090, 1000110, false)))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc90to95, loc999))}); + tests.add(new Object[]{new FindVariantRegionsTest(Arrays.asList(loc999))}); return tests.toArray(new Object[][]{}); } @@ -120,7 +113,7 @@ public class SlidingWindowUnitTest extends BaseTest { final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); final CompressionStash locs = slidingWindow.findVariantRegions(0, variantRegionLength, test.variantRegionBitset, true); int index = 0; - for ( final SimpleGenomeLoc loc : locs ) { + for ( final FinishedGenomeLoc loc : locs ) { Assert.assertTrue(loc.equals(test.expectedResult.get(index++))); } } @@ -128,7 +121,7 @@ public class SlidingWindowUnitTest extends BaseTest { @Test(enabled = true) public void testNoClosingRegions() { final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); - final CompressionStash locs = slidingWindow.findVariantRegions(0, variantRegionLength, createBitset(Arrays.asList(loc90to95, loc999)), false); + final CompressionStash locs = slidingWindow.findVariantRegions(0, variantRegionLength, createBitset(Arrays.asList(loc90to95, loc999)), false); Assert.assertEquals(locs.size(), 1); Assert.assertEquals(locs.iterator().next(), loc90to95); } diff --git a/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java b/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java index 4f1b35f62..0a271b64c 100644 --- a/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java +++ b/public/java/src/org/broadinstitute/sting/utils/GenomeLoc.java @@ -30,10 +30,7 @@ import com.google.java.contract.Requires; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * Created by IntelliJ IDEA. @@ -581,4 +578,49 @@ public class GenomeLoc implements Comparable, Serializable, HasGenome public GenomeLoc incPos(GenomeLoc loc, int by) { return new GenomeLoc(loc.getContig(), loc.getContigIndex(), loc.start + by, loc.stop + by); } + + /** + * Merges 2 *contiguous* locs into 1 + * + * @param a GenomeLoc #1 + * @param b GenomeLoc #2 + * @return one merged loc + */ + @Requires("a != null && b != null") + public static GenomeLoc merge(final T a, final T b) { + if ( isUnmapped(a) || isUnmapped(b) ) { + throw new ReviewedStingException("Tried to merge unmapped genome locs"); + } + + if ( !(a.contiguousP(b)) ) { + throw new ReviewedStingException("The two genome locs need to be contiguous"); + } + + return new GenomeLoc(a.getContig(), a.contigIndex, Math.min(a.getStart(), b.getStart()), Math.max(a.getStop(), b.getStop())); + } + + /** + * Merges a list of *sorted* *contiguous* locs into 1 + * + * @param sortedLocs a sorted list of contiguous locs + * @return one merged loc + */ + @Requires("sortedLocs != null") + public static GenomeLoc merge(final SortedSet sortedLocs) { + GenomeLoc result = null; + + for ( GenomeLoc loc : sortedLocs ) { + if ( loc.isUnmapped() ) + throw new ReviewedStingException("Tried to merge unmapped genome locs"); + + if ( result == null ) + result = loc; + else if ( !result.contiguousP(loc) ) + throw new ReviewedStingException("The genome locs need to be contiguous"); + else + result = merge(result, loc); + } + + return result; + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/UnvalidatingGenomeLoc.java b/public/java/src/org/broadinstitute/sting/utils/UnvalidatingGenomeLoc.java new file mode 100644 index 000000000..5a611c21e --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/UnvalidatingGenomeLoc.java @@ -0,0 +1,50 @@ +/* +* 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.utils; + +import com.google.java.contract.Requires; + +/** + * GenomeLocs are very useful objects to keep track of genomic locations and perform set operations + * with them. + * + * However, GenomeLocs are bound to strict validation through the GenomeLocParser and cannot + * be created easily for small tasks that do not require the rigors of the GenomeLocParser validation + * + * UnvalidatingGenomeLoc is a simple utility to create GenomeLocs without going through the parser. + * + * WARNING: SHOULD BE USED ONLY BY EXPERT USERS WHO KNOW WHAT THEY ARE DOING! + * + * User: carneiro + * Date: 10/16/12 + * Time: 2:07 PM + */ +public class UnvalidatingGenomeLoc extends GenomeLoc { + + public UnvalidatingGenomeLoc(String contigName, int contigIndex, int start, int stop) { + super(contigName, contigIndex, start, stop); + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/GenomeLocUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/GenomeLocUnitTest.java index b5d495ddc..ed91114a4 100644 --- a/public/java/test/org/broadinstitute/sting/utils/GenomeLocUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/GenomeLocUnitTest.java @@ -29,6 +29,7 @@ package org.broadinstitute.sting.utils; // the imports for unit testing. +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.interval.IntervalMergingRule; import org.broadinstitute.sting.utils.interval.IntervalUtils; import org.testng.Assert; @@ -40,10 +41,7 @@ import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; import java.io.File; import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import net.sf.picard.reference.ReferenceSequenceFile; import net.sf.picard.reference.IndexedFastaSequenceFile; @@ -291,4 +289,58 @@ public class GenomeLocUnitTest extends BaseTest { if ( expected == ComparisonResult.EQUALS ) Assert.assertEquals(g1.hashCode(), g2.hashCode(), "Equal genome locs don't have the same hash code"); } + + // ------------------------------------------------------------------------------------- + // + // testing merging functionality + // + // ------------------------------------------------------------------------------------- + + private static final GenomeLoc loc1 = new GenomeLoc("1", 0, 10, 20); + private static final GenomeLoc loc2 = new GenomeLoc("1", 0, 21, 30); + private static final GenomeLoc loc3 = new GenomeLoc("1", 0, 31, 40); + + private class MergeTest { + public List locs; + + private MergeTest(final List locs) { + this.locs = locs; + } + } + + @DataProvider(name = "SGLtest") + public Object[][] createFindVariantRegionsData() { + List tests = new ArrayList(); + + tests.add(new Object[]{new MergeTest(Arrays.asList(loc1))}); + tests.add(new Object[]{new MergeTest(Arrays.asList(loc1, loc2))}); + tests.add(new Object[]{new MergeTest(Arrays.asList(loc1, loc2, loc3))}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "SGLtest", enabled = true) + public void testSimpleGenomeLoc(MergeTest test) { + testMerge(test.locs); + } + + @Test(expectedExceptions = ReviewedStingException.class) + public void testNotContiguousLocs() { + final List locs = new ArrayList(1); + locs.add(loc1); + locs.add(loc3); + testMerge(locs); + } + + private void testMerge(final List locs) { + GenomeLoc result1 = locs.get(0); + for ( int i = 1; i < locs.size(); i++ ) + result1 = GenomeLoc.merge(result1, locs.get(i)); + + GenomeLoc result2 = GenomeLoc.merge(new TreeSet(locs)); + Assert.assertEquals(result1, result2); + Assert.assertEquals(result1.getStart(), locs.get(0).getStart()); + Assert.assertEquals(result1.getStop(), locs.get(locs.size() - 1).getStop()); + } + } From 1ff78679ca75ef3843c2bdf7efc3b2c468f3e161 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 30 Jan 2013 11:18:58 -0500 Subject: [PATCH 143/188] UnitTesting example for copying -- Example combinatorial unit tests, plus unit tests that create reads and bam files, pileups, variant context (from scratch and from a file), and genome locs --- .../sting/ExampleToCopyUnitTest.java | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 public/java/test/org/broadinstitute/sting/ExampleToCopyUnitTest.java diff --git a/public/java/test/org/broadinstitute/sting/ExampleToCopyUnitTest.java b/public/java/test/org/broadinstitute/sting/ExampleToCopyUnitTest.java new file mode 100644 index 000000000..765511ae6 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/ExampleToCopyUnitTest.java @@ -0,0 +1,212 @@ +/* + * 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; + + +// the imports for unit testing. + + +import net.sf.picard.reference.IndexedFastaSequenceFile; +import net.sf.samtools.SAMFileHeader; +import net.sf.samtools.SAMFileReader; +import net.sf.samtools.SAMRecord; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.GenomeLocParser; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.activeregion.ActiveRegion; +import org.broadinstitute.sting.utils.activeregion.ActivityProfileState; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.pileup.PileupElement; +import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; +import org.broadinstitute.sting.utils.pileup.ReadBackedPileupImpl; +import org.broadinstitute.sting.utils.sam.ArtificialBAMBuilder; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; +import org.broadinstitute.sting.utils.sam.GATKSamRecordFactory; +import org.broadinstitute.variant.variantcontext.Allele; +import org.broadinstitute.variant.variantcontext.VariantContext; +import org.broadinstitute.variant.variantcontext.VariantContextBuilder; +import org.broadinstitute.variant.variantcontext.VariantContextTestProvider; +import org.broadinstitute.variant.vcf.VCFCodec; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + +public class ExampleToCopyUnitTest extends BaseTest { + // example genome loc parser for this test, can be deleted if you don't use the reference + private GenomeLocParser genomeLocParser; + + // example fasta index file, can be deleted if you don't use the reference + private IndexedFastaSequenceFile seq; + + @BeforeClass + public void setup() throws FileNotFoundException { + // sequence + seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + genomeLocParser = new GenomeLocParser(seq); + } + + /** + * Combinatorial unit test data provider example. + * + * Creates data for testMyData test function, containing two arguments, start and size at each value + * + * @return Object[][] for testng DataProvider + */ + @DataProvider(name = "MyDataProvider") + public Object[][] makeMyDataProvider() { + List tests = new ArrayList(); + + // this functionality can be adapted to provide input data for whatever you might want in your data + for ( final int start : Arrays.asList(1, 10, 100) ) { + for ( final int size : Arrays.asList(1, 10, 100, 1000) ) { + tests.add(new Object[]{start, size}); + } + } + + return tests.toArray(new Object[][]{}); + } + + /** + * Example testng test using MyDataProvider + */ + @Test(dataProvider = "MyDataProvider") + public void testMyData(final int start, final int size) { + // adaptor this code to do whatever testing you want given the arguments start and size + Assert.assertTrue(start >= 0); + Assert.assertTrue(size >= 0); + } + + /** + * A unit test that creates an artificial read for testing some code that uses reads + */ + @Test() + public void testWithARead() { + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, 10); + Assert.assertEquals(read.getReadLength(), 10); + // TODO -- add some tests here using read + } + + /** + * A unit test that creates a GenomeLoc for testing + */ + @Test() + public void testWithAGenomeLoc() { + final GenomeLoc loc = genomeLocParser.createGenomeLoc("1", 1, 10); + Assert.assertEquals(loc.size(), 10); + // TODO -- add some tests here using the loc + } + + /** + * A unit test that creates an artificial read for testing some code that uses reads + * + * Note that effective creation of RBPs isn't so good. If you need pileups of specific properties, you shoud + * look into building them yourself as in the example below + */ + @Test() + public void testWithAPileup() { + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); + final GenomeLoc myLocation = genomeLocParser.createGenomeLoc("1", 10); + final ReadBackedPileup pileup = ArtificialSAMUtils.createReadBackedPileup(header, myLocation, 10, 400, 10); + Assert.assertFalse(pileup.isEmpty()); + // TODO -- add some tests here using pileup + } + + /** + * A unit test that creates an artificial read for testing some code that uses reads + * + * Builds the pileup from scratch to have specific properties + */ + @Test() + public void testBuildingAPileupWithSpecificProperties() { + final SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); + final GenomeLoc myLocation = genomeLocParser.createGenomeLoc("1", 10); + + final int pileupSize = 100; + final int readLength = 10; + final List reads = new LinkedList(); + for ( int i = 0; i < pileupSize; i++ ) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead" + i, 0, 1, readLength); + final byte[] bases = Utils.dupBytes((byte)'A', readLength); + bases[0] = (byte)(i % 2 == 0 ? 'A' : 'C'); // every other base is a C + + // set the read's bases and quals + read.setReadBases(bases); + read.setBaseQualities(Utils.dupBytes((byte)30, readLength)); + reads.add(read); + } + + // create a pileup with all reads having offset 0 + final ReadBackedPileup pileup = new ReadBackedPileupImpl(myLocation, reads, 0); + // TODO -- add some tests here using pileup + + // this code ensures that the pileup example is correct. Can be deleted + Assert.assertEquals(pileup.getNumberOfElements(), pileupSize); + int nA = 0, nC = 0; + for ( final PileupElement p : pileup ) { + if ( p.getBase() == 'A' ) nA++; + if ( p.getBase() == 'C' ) nC++; + } + Assert.assertEquals(nA, pileupSize / 2); + Assert.assertEquals(nC, pileupSize / 2); + + } + + /** + * A unit test that creates an artificial read for testing some code that uses reads + */ + @Test() + public void testWithBAMFile() { + // create a fake BAM file, and iterate through it + final ArtificialBAMBuilder bamBuilder = new ArtificialBAMBuilder(seq, 20, 10); + final File bam = bamBuilder.makeTemporarilyBAMFile(); + final SAMFileReader reader = new SAMFileReader(bam); + reader.setSAMRecordFactory(new GATKSamRecordFactory()); + + final Iterator bamIt = reader.iterator(); + while ( bamIt.hasNext() ) { + final GATKSAMRecord read = (GATKSAMRecord)bamIt.next(); // all reads are actually GATKSAMRecords + // TODO -- add some tests that use reads from a BAM + } + } + + /** + * Test code that creates VariantContexts + */ + @Test() + public void testWithVariantContext() throws Exception { + final List alleles = Arrays.asList(Allele.create("A", true), Allele.create("C")); + final VariantContext vc = new VariantContextBuilder("test", "1", 10, 10, alleles).make(); + Assert.assertTrue(vc.getAlleles().size() >= 0); + // TODO -- add some tests that use VariantContext + } +} \ No newline at end of file From 2967776458e736175636d8321a3232f02634b7db Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 12:28:14 -0500 Subject: [PATCH 144/188] The Empirical quality column in the recalibration report can't be compared in the BQSRGatherer because the value is calculated using the Bayesian estimate with different priors. This value should never be used from a recalibration report anyway except during plotting. --- .../recalibration/BaseRecalibration.java | 2 +- .../sting/utils/recalibration/RecalDatum.java | 1 + .../recalibration/RecalibrationReport.java | 2 +- .../walkers/bqsr/BQSRGathererUnitTest.java | 6 ++-- .../recalibration/RecalDatumUnitTest.java | 33 +++++++++++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index bc7c5a1ce..f3d4a3096 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -188,7 +188,7 @@ public class BaseRecalibration { } } - protected double hierarchicalBayesianQualityEstimate( final double epsilon, final RecalDatum empiricalQualRG, final RecalDatum empiricalQualQS, final List empiricalQualCovs ) { + protected static double hierarchicalBayesianQualityEstimate( final double epsilon, final RecalDatum empiricalQualRG, final RecalDatum empiricalQualQS, final List empiricalQualCovs ) { final double globalDeltaQ = ( empiricalQualRG == null ? 0.0 : empiricalQualRG.getEmpiricalQuality(epsilon) - epsilon ); final double deltaQReported = ( empiricalQualQS == null ? 0.0 : empiricalQualQS.getEmpiricalQuality(globalDeltaQ + epsilon) - (globalDeltaQ + epsilon) ); double deltaQCovariates = 0.0; diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java index 0b4441439..bd0063a7d 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java @@ -181,6 +181,7 @@ public class RecalDatum { if ( Double.isNaN(estimatedQReported) ) throw new IllegalArgumentException("estimatedQReported is NaN"); this.estimatedQReported = estimatedQReported; + empiricalQuality = UNINITIALIZED; } public final double getEstimatedQReported() { diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java index 2f9a38972..f10c26ddc 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalibrationReport.java @@ -131,7 +131,7 @@ public class RecalibrationReport { * Combines two recalibration reports by adding all observations and errors * * Note: This method DOES NOT recalculate the empirical qualities and quantized qualities. You have to recalculate - * them after combining. The reason for not calculating it is because this function is inteded for combining a + * them after combining. The reason for not calculating it is because this function is intended for combining a * series of recalibration reports, and it only makes sense to calculate the empirical qualities and quantized * qualities after all the recalibration reports have been combined. Having the user recalculate when appropriate, * makes this method faster diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRGathererUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRGathererUnitTest.java index 2815599d9..f82f24439 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRGathererUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRGathererUnitTest.java @@ -125,19 +125,19 @@ public class BQSRGathererUnitTest extends BaseTest { testTablesWithColumns(originalTable, calculatedTable, columnsToTest); // test the RecalTable0 table - columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.EMPIRICAL_QUALITY_COLUMN_NAME, RecalUtils.ESTIMATED_Q_REPORTED_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); + columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.ESTIMATED_Q_REPORTED_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); originalTable = originalReport.getTable(RecalUtils.READGROUP_REPORT_TABLE_TITLE); calculatedTable = calculatedReport.getTable(RecalUtils.READGROUP_REPORT_TABLE_TITLE); testTablesWithColumns(originalTable, calculatedTable, columnsToTest); // test the RecalTable1 table - columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.QUALITY_SCORE_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.EMPIRICAL_QUALITY_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); + columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.QUALITY_SCORE_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); originalTable = originalReport.getTable(RecalUtils.QUALITY_SCORE_REPORT_TABLE_TITLE); calculatedTable = calculatedReport.getTable(RecalUtils.QUALITY_SCORE_REPORT_TABLE_TITLE); testTablesWithColumns(originalTable, calculatedTable, columnsToTest); // test the RecalTable2 table - columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.QUALITY_SCORE_COLUMN_NAME, RecalUtils.COVARIATE_VALUE_COLUMN_NAME, RecalUtils.COVARIATE_NAME_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.EMPIRICAL_QUALITY_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); + columnsToTest = Arrays.asList(RecalUtils.READGROUP_COLUMN_NAME, RecalUtils.QUALITY_SCORE_COLUMN_NAME, RecalUtils.COVARIATE_VALUE_COLUMN_NAME, RecalUtils.COVARIATE_NAME_COLUMN_NAME, RecalUtils.EVENT_TYPE_COLUMN_NAME, RecalUtils.NUMBER_OBSERVATIONS_COLUMN_NAME, RecalUtils.NUMBER_ERRORS_COLUMN_NAME); originalTable = originalReport.getTable(RecalUtils.ALL_COVARIATES_REPORT_TABLE_TITLE); calculatedTable = calculatedReport.getTable(RecalUtils.ALL_COVARIATES_REPORT_TABLE_TITLE); testTablesWithColumns(originalTable, calculatedTable, columnsToTest); diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java index 09f751fbc..37f0fcc0c 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java @@ -58,6 +58,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; +import java.util.Collections; public class RecalDatumUnitTest extends BaseTest { @@ -277,4 +278,36 @@ public class RecalDatumUnitTest extends BaseTest { Assert.assertFalse(Double.isInfinite(log10likelihood)); Assert.assertFalse(Double.isNaN(log10likelihood)); } + + @Test + public void basicHierarchicalBayesianQualityEstimateTest() { + { + double RG_Q = 45.0; + RecalDatum RG = new RecalDatum( (long)10000000, (long) (10000000 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); + double Q = 30.0; + RecalDatum QS = new RecalDatum( (long)10000000, (long) (10000000 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); + RecalDatum COV = new RecalDatum( (long)150, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality + + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 45.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + // initial epsilon condition shouldn't matter when there are a lot of observations + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 25.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 5.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 65.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + } + + { + double RG_Q = 45.0; + RecalDatum RG = new RecalDatum( (long)100, (long) (100 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); + double Q = 30.0; + RecalDatum QS = new RecalDatum( (long)100, (long) (100 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); + RecalDatum COV = new RecalDatum( (long)150, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality + + // initial epsilon condition dominates when there is no data + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 45.0, RG, QS, Collections.singletonList(COV)), 45.0, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 25.0, RG, QS, Collections.singletonList(COV)), 25.0, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 5.0, RG, QS, Collections.singletonList(COV)), 5.0, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 65.0, RG, QS, Collections.singletonList(COV)), 65.0, 1E-4 ); + } + + } } \ No newline at end of file From 9985f82a7af60dbbdf0c1343a02bd6b10ada218c Mon Sep 17 00:00:00 2001 From: David Roazen Date: Wed, 30 Jan 2013 12:54:57 -0500 Subject: [PATCH 146/188] Move BaseUtils back to the GATK by request, along with associated utility methods --- .../gatk/walkers/annotator/GCContent.java | 2 +- .../walkers/annotator/HaplotypeScore.java | 2 +- .../gatk/walkers/bqsr/BaseRecalibrator.java | 2 +- .../DiploidSNPGenotypeLikelihoods.java | 2 +- .../GeneralPloidySNPGenotypeLikelihoods.java | 3 +- ...NPGenotypeLikelihoodsCalculationModel.java | 2 +- .../GenotypeLikelihoodsCalculationModel.java | 2 +- ...elGenotypeLikelihoodsCalculationModel.java | 2 +- ...NPGenotypeLikelihoodsCalculationModel.java | 2 +- .../genotyper/UnifiedGenotyperEngine.java | 2 +- .../haplotypecaller/GenotypingEngine.java | 2 +- .../gatk/walkers/indels/IndelRealigner.java | 2 +- .../sting/gatk/walkers/phasing/BaseArray.java | 2 +- .../gatk/walkers/phasing/PhasingRead.java | 2 +- .../walkers/phasing/ReadBackedPhasing.java | 2 +- .../gatk/walkers/phasing/SNPallelePair.java | 2 +- .../VariantRecalibrator.java | 4 +- .../sting/utils/recalibration/RecalUtils.java | 2 +- .../covariates/ContextCovariate.java | 2 +- .../covariates/CycleCovariate.java | 2 +- .../covariates/RepeatCovariate.java | 2 +- .../ArtificialReadPileupTestProvider.java | 2 +- ...eralPloidyGenotypeLikelihoodsUnitTest.java | 2 +- .../ConcordanceMetricsUnitTest.java | 2 +- .../sting/utils/pairhmm/PairHMMUnitTest.java | 2 +- .../RepeatCovariatesUnitTest.java | 2 +- .../sting/alignment/Alignment.java | 2 +- .../sting/alignment/AlignmentValidation.java | 2 +- .../bwa/java/AlignerTestHarness.java | 2 +- .../alignment/bwa/java/BWAJavaAligner.java | 2 +- .../sting/gatk/contexts/ReferenceContext.java | 2 +- .../AlleleBiasedDownsamplingUtils.java | 2 +- .../gatk/walkers/annotator/BaseCounts.java | 2 +- .../gatk/walkers/annotator/NBaseCount.java | 2 +- .../walkers/annotator/VariantAnnotator.java | 2 +- .../gatk/walkers/coverage/CallableLoci.java | 2 +- .../gatk/walkers/coverage/CoverageUtils.java | 2 +- .../walkers/coverage/DepthOfCoverage.java | 2 +- .../coverage/DepthOfCoverageStats.java | 2 +- .../walkers/coverage/GCContentByInterval.java | 2 +- .../diagnostics/ErrorRatePerCycle.java | 2 +- .../sting/gatk/walkers/fasta/FastaStats.java | 2 +- .../sting/gatk/walkers/qc/QCRef.java | 2 +- .../gatk/walkers/readutils/ClipReads.java | 2 +- .../validation/ValidationAmplicons.java | 2 +- .../evaluators/MultiallelicSummary.java | 4 +- .../evaluators/TiTvVariantEvaluator.java | 6 +- .../evaluators/VariantSummary.java | 4 +- .../variantutils/LiftoverVariants.java | 6 +- .../walkers/variantutils/VariantsToTable.java | 3 +- .../walkers/variantutils/VariantsToVCF.java | 2 +- .../{variant => sting}/utils/BaseUtils.java | 17 +++-- .../sting/utils/duplicates/DupUtils.java | 2 +- .../CachingIndexedFastaSequenceFile.java | 2 +- .../utils/genotyper/DiploidGenotype.java | 2 +- .../sting/utils/pileup/PileupElement.java | 2 +- .../utils/pileup/ReadBackedPileupImpl.java | 2 +- .../sting/utils/sam/AlignmentUtils.java | 2 +- .../sting/utils/sam/ReadUtils.java | 2 +- .../variant/GATKVariantContextUtils.java | 67 +++++++++++++++++-- .../variant/variantcontext/Allele.java | 4 +- .../variantcontext/VariantContextUtils.java | 63 ----------------- .../utils/BaseUtilsUnitTest.java | 14 ++-- ...chingIndexedFastaSequenceFileUnitTest.java | 2 +- .../sting/utils/sam/ReadUtilsUnitTest.java | 2 +- .../GenotypeLikelihoodsUnitTest.java | 7 +- 66 files changed, 153 insertions(+), 155 deletions(-) rename public/java/src/org/broadinstitute/{variant => sting}/utils/BaseUtils.java (95%) rename public/java/test/org/broadinstitute/{variant => sting}/utils/BaseUtilsUnitTest.java (93%) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java index 2b3290595..93bdf8c9d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/GCContent.java @@ -54,7 +54,7 @@ import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompa import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.ExperimentalAnnotation; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.InfoFieldAnnotation; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.variant.vcf.VCFHeaderLineType; import org.broadinstitute.variant.vcf.VCFInfoHeaderLine; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java index 3acba48ae..13969eb54 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/HaplotypeScore.java @@ -55,7 +55,7 @@ import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.AnnotatorCompa import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.InfoFieldAnnotation; import org.broadinstitute.sting.gatk.walkers.annotator.interfaces.StandardAnnotation; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.variant.vcf.VCFHeaderLineType; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java index 2df5fefa8..354e508c2 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BaseRecalibrator.java @@ -60,7 +60,7 @@ import org.broadinstitute.sting.gatk.iterators.ReadTransformer; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.clipping.ReadClipper; import org.broadinstitute.sting.utils.collections.Pair; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java index 8c8de2bad..2baa89999 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/DiploidSNPGenotypeLikelihoods.java @@ -47,7 +47,7 @@ package org.broadinstitute.sting.gatk.walkers.genotyper; import net.sf.samtools.SAMUtils; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.exceptions.UserException; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoods.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoods.java index aa117eb3b..14bffbc34 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoods.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoods.java @@ -49,9 +49,8 @@ package org.broadinstitute.sting.gatk.walkers.genotyper; import net.sf.samtools.SAMUtils; import org.broadinstitute.sting.gatk.walkers.genotyper.afcalc.ExactACset; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.pileup.PileupElement; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoodsCalculationModel.java index 9aa8c13ec..9ea027698 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GeneralPloidySNPGenotypeLikelihoodsCalculationModel.java @@ -77,7 +77,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.utils.*; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.*; import java.util.*; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GenotypeLikelihoodsCalculationModel.java index b3740bbb7..f48ae81cf 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/GenotypeLikelihoodsCalculationModel.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/IndelGenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/IndelGenotypeLikelihoodsCalculationModel.java index 84c109c9d..5a1bdf9e5 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/IndelGenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/IndelGenotypeLikelihoodsCalculationModel.java @@ -52,7 +52,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.indels.PairHMMIndelErrorModel; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.Haplotype; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/SNPGenotypeLikelihoodsCalculationModel.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/SNPGenotypeLikelihoodsCalculationModel.java index 7dc3e8ee3..0652cc236 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/SNPGenotypeLikelihoodsCalculationModel.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/SNPGenotypeLikelihoodsCalculationModel.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.MathUtils; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java index 8f6097661..19d218023 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyperEngine.java @@ -62,7 +62,7 @@ import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.classloader.PluginManager; import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.variant.vcf.VCFConstants; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.pileup.PileupElement; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java index 9aeffe966..d254f5b8b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java @@ -58,7 +58,7 @@ import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.*; import java.io.PrintStream; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java index 851703648..ad554a130 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java @@ -75,7 +75,7 @@ import org.broadinstitute.sting.utils.sam.NWaySAMFileWriter; import org.broadinstitute.sting.utils.sam.ReadUtils; import org.broadinstitute.sting.utils.text.TextFormattingUtils; import org.broadinstitute.sting.utils.text.XReadLines; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.variant.variantcontext.VariantContext; import java.io.File; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/BaseArray.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/BaseArray.java index de91765b7..cbc6a1f94 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/BaseArray.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/BaseArray.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.phasing; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import java.util.Arrays; import java.util.LinkedList; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhasingRead.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhasingRead.java index f2ba027f8..a04789f61 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhasingRead.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhasingRead.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.phasing; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java index 56fc59c7f..980894112 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java @@ -59,7 +59,7 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.*; import org.broadinstitute.sting.utils.variant.GATKVCFUtils; import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.HasGenomeLocation; import org.broadinstitute.sting.utils.SampleUtils; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/SNPallelePair.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/SNPallelePair.java index 0a4783214..8dca985c8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/SNPallelePair.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/SNPallelePair.java @@ -46,7 +46,7 @@ package org.broadinstitute.sting.gatk.walkers.phasing; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.variant.variantcontext.Allele; import org.broadinstitute.variant.variantcontext.Genotype; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java index 433900d02..d8d79e26c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java @@ -59,6 +59,7 @@ import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.R.RScriptExecutor; import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.variant.GATKVariantContextUtils; import org.broadinstitute.variant.vcf.VCFHeader; import org.broadinstitute.variant.vcf.VCFHeaderLine; import org.broadinstitute.sting.utils.collections.ExpandingArrayList; @@ -66,7 +67,6 @@ import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.io.Resource; import org.broadinstitute.variant.variantcontext.VariantContext; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; import java.io.File; @@ -274,7 +274,7 @@ public class VariantRecalibrator extends RodWalker { if ( toInterval != null ) { // check whether the strand flips, and if so reverse complement everything if ( fromInterval.isPositiveStrand() != toInterval.isPositiveStrand() && vc.isPointEvent() ) { - vc = VariantContextUtils.reverseComplement(vc); + vc = GATKVariantContextUtils.reverseComplement(vc); } vc = new VariantContextBuilder(vc).loc(toInterval.getSequence(), toInterval.getStart(), toInterval.getStart() + length).make(); @@ -133,7 +133,7 @@ public class LiftoverVariants extends RodWalker { .attribute("OriginalStart", fromInterval.getStart()).make(); } - if ( originalVC.isSNP() && originalVC.isBiallelic() && VariantContextUtils.getSNPSubstitutionType(originalVC) != VariantContextUtils.getSNPSubstitutionType(vc) ) { + if ( originalVC.isSNP() && originalVC.isBiallelic() && GATKVariantContextUtils.getSNPSubstitutionType(originalVC) != GATKVariantContextUtils.getSNPSubstitutionType(vc) ) { logger.warn(String.format("VCF at %s / %d => %s / %d is switching substitution type %s/%s to %s/%s", originalVC.getChr(), originalVC.getStart(), vc.getChr(), vc.getStart(), originalVC.getReference(), originalVC.getAlternateAllele(0), vc.getReference(), vc.getAlternateAllele(0))); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java index 1ea85df47..f6c02592d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java @@ -41,7 +41,6 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.variant.variantcontext.VariantContextUtils; import java.io.PrintStream; import java.lang.reflect.Array; @@ -432,7 +431,7 @@ public class VariantsToTable extends RodWalker { getters.put("QUAL", new Getter() { public String get(VariantContext vc) { return Double.toString(vc.getPhredScaledQual()); } }); getters.put("TRANSITION", new Getter() { public String get(VariantContext vc) { if ( vc.isSNP() && vc.isBiallelic() ) - return VariantContextUtils.isTransition(vc) ? "1" : "0"; + return GATKVariantContextUtils.isTransition(vc) ? "1" : "0"; else return "-1"; }}); diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java index 5afeccffe..29e7ad8d7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java @@ -39,7 +39,7 @@ import org.broadinstitute.sting.gatk.refdata.utils.GATKFeature; import org.broadinstitute.sting.gatk.walkers.Reference; import org.broadinstitute.sting.gatk.walkers.RodWalker; import org.broadinstitute.sting.gatk.walkers.Window; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.SampleUtils; import org.broadinstitute.sting.utils.codecs.hapmap.RawHapMapFeature; diff --git a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java similarity index 95% rename from public/java/src/org/broadinstitute/variant/utils/BaseUtils.java rename to public/java/src/org/broadinstitute/sting/utils/BaseUtils.java index 76b49edb9..e6e1db813 100644 --- a/public/java/src/org/broadinstitute/variant/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java @@ -23,12 +23,14 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.utils; +package org.broadinstitute.sting.utils; import net.sf.samtools.util.StringUtil; +import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.exceptions.UserException; import java.util.Arrays; -import java.util.Random; /** * BaseUtils contains some basic utilities for manipulating nucleotides. @@ -95,9 +97,6 @@ public class BaseUtils { baseIndexWithIupacMap['v'] = Base.N.ordinal(); } - // Use a fixed random seed to allow for deterministic results when using random bases - private static final Random randomNumberGen = new Random(47382911L); - /// In genetics, a transition is a mutation changing a purine to another purine nucleotide (A <-> G) or // a pyrimidine to another pyrimidine nucleotide (C <-> T). // Approximately two out of every three single nucleotide polymorphisms (SNPs) are transitions. @@ -174,7 +173,7 @@ public class BaseUtils { if ( baseIndex == Base.N.ordinal() ) { bases[i] = 'N'; } else if ( errorOnBadReferenceBase && baseIndex == -1 ) { - throw new IllegalStateException("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'"); + throw new UserException.BadInput("We encountered a non-standard non-IUPAC base in the provided reference: '" + bases[i] + "'"); } } return bases; @@ -251,7 +250,7 @@ public class BaseUtils { */ static public int simpleBaseToBaseIndex(final byte base) { if ( base < 0 || base >= 256 ) - throw new IllegalArgumentException("Non-standard bases were encountered in either the input reference or BAM file(s)"); + throw new UserException.BadInput("Non-standard bases were encountered in either the input reference or BAM file(s)"); return baseIndexMap[base]; } @@ -491,7 +490,7 @@ public class BaseUtils { int randomBaseIndex = excludeBaseIndex; while (randomBaseIndex == excludeBaseIndex) { - randomBaseIndex = randomNumberGen.nextInt(4); + randomBaseIndex = GenomeAnalysisEngine.getRandomGenerator().nextInt(4); } return randomBaseIndex; @@ -515,7 +514,7 @@ public class BaseUtils { case 'N': return 'N'; default: - throw new IllegalArgumentException("base must be A, C, G or T. " + (char) base + " is not a valid base."); + throw new ReviewedStingException("base must be A, C, G or T. " + (char) base + " is not a valid base."); } } } diff --git a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java index 39f5b06c6..c78294505 100644 --- a/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/duplicates/DupUtils.java @@ -25,7 +25,7 @@ package org.broadinstitute.sting.utils.duplicates; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; import org.broadinstitute.sting.utils.QualityUtils; diff --git a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java index a749625cd..c30ac4f7f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java +++ b/public/java/src/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFile.java @@ -33,7 +33,7 @@ import net.sf.samtools.SAMSequenceRecord; import net.sf.samtools.util.StringUtil; import org.apache.log4j.Priority; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import java.io.File; import java.io.FileNotFoundException; diff --git a/public/java/src/org/broadinstitute/sting/utils/genotyper/DiploidGenotype.java b/public/java/src/org/broadinstitute/sting/utils/genotyper/DiploidGenotype.java index febc62716..ceae4bb47 100644 --- a/public/java/src/org/broadinstitute/sting/utils/genotyper/DiploidGenotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/genotyper/DiploidGenotype.java @@ -25,7 +25,7 @@ package org.broadinstitute.sting.utils.genotyper; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; public enum DiploidGenotype { AA ('A', 'A'), diff --git a/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java b/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java index 5a5358208..51753ca5e 100644 --- a/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java +++ b/public/java/src/org/broadinstitute/sting/utils/pileup/PileupElement.java @@ -29,7 +29,7 @@ import com.google.java.contract.Ensures; import com.google.java.contract.Requires; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; diff --git a/public/java/src/org/broadinstitute/sting/utils/pileup/ReadBackedPileupImpl.java b/public/java/src/org/broadinstitute/sting/utils/pileup/ReadBackedPileupImpl.java index fe43f85bd..65c47c23b 100644 --- a/public/java/src/org/broadinstitute/sting/utils/pileup/ReadBackedPileupImpl.java +++ b/public/java/src/org/broadinstitute/sting/utils/pileup/ReadBackedPileupImpl.java @@ -32,7 +32,7 @@ import org.broadinstitute.sting.utils.fragments.FragmentCollection; import org.broadinstitute.sting.utils.fragments.FragmentUtils; import org.broadinstitute.sting.utils.locusiterator.LocusIteratorByState; import org.broadinstitute.sting.utils.sam.GATKSAMRecord; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index b7a813ec2..9c5f95472 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -30,7 +30,7 @@ import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java index 29f8c8dcd..39d058aea 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/ReadUtils.java @@ -34,7 +34,7 @@ import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.NGSPlatform; import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import java.io.File; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java index 2ae289214..f22066f8e 100644 --- a/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/variant/GATKVariantContextUtils.java @@ -30,10 +30,7 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import org.broad.tribble.TribbleException; import org.broad.tribble.util.popgen.HardyWeinbergCalculation; -import org.broadinstitute.sting.utils.GenomeLoc; -import org.broadinstitute.sting.utils.GenomeLocParser; -import org.broadinstitute.sting.utils.MathUtils; -import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.*; import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.variant.variantcontext.*; import org.broadinstitute.variant.vcf.VCFConstants; @@ -108,6 +105,68 @@ public class GATKVariantContextUtils { return genomeLocParser.createGenomeLoc(vc.getChr(), vc.getStart(), vc.getEnd(), true); } + public static BaseUtils.BaseSubstitutionType getSNPSubstitutionType(VariantContext context) { + if (!context.isSNP() || !context.isBiallelic()) + throw new IllegalStateException("Requested SNP substitution type for bialleic non-SNP " + context); + return BaseUtils.SNPSubstitutionType(context.getReference().getBases()[0], context.getAlternateAllele(0).getBases()[0]); + } + + /** + * If this is a BiAlleic SNP, is it a transition? + */ + public static boolean isTransition(VariantContext context) { + return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSITION; + } + + /** + * If this is a BiAlleic SNP, is it a transversion? + */ + public static boolean isTransversion(VariantContext context) { + return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSVERSION; + } + + public static boolean isTransition(Allele ref, Allele alt) { + return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSITION; + } + + public static boolean isTransversion(Allele ref, Allele alt) { + return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSVERSION; + } + + /** + * Returns a context identical to this with the REF and ALT alleles reverse complemented. + * + * @param vc variant context + * @return new vc + */ + public static VariantContext reverseComplement(VariantContext vc) { + // create a mapping from original allele to reverse complemented allele + HashMap alleleMap = new HashMap(vc.getAlleles().size()); + for ( Allele originalAllele : vc.getAlleles() ) { + Allele newAllele; + if ( originalAllele.isNoCall() ) + newAllele = originalAllele; + else + newAllele = Allele.create(BaseUtils.simpleReverseComplement(originalAllele.getBases()), originalAllele.isReference()); + alleleMap.put(originalAllele, newAllele); + } + + // create new Genotype objects + GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples()); + for ( final Genotype genotype : vc.getGenotypes() ) { + List newAlleles = new ArrayList(); + for ( Allele allele : genotype.getAlleles() ) { + Allele newAllele = alleleMap.get(allele); + if ( newAllele == null ) + newAllele = Allele.NO_CALL; + newAlleles.add(newAllele); + } + newGenotypes.add(new GenotypeBuilder(genotype).alleles(newAlleles).make()); + } + + return new VariantContextBuilder(vc).alleles(alleleMap.values()).genotypes(newGenotypes).make(); + } + /** * Returns true iff VC is an non-complex indel where every allele represents an expansion or * contraction of a series of identical bases in the reference. diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java b/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java index 0a0b4d0b7..e0a6495a5 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/Allele.java @@ -25,7 +25,7 @@ package org.broadinstitute.variant.variantcontext; -import org.broadinstitute.variant.utils.BaseUtils; +import net.sf.samtools.util.StringUtil; import java.util.Arrays; import java.util.Collection; @@ -130,7 +130,7 @@ public class Allele implements Comparable { if ( isRef ) throw new IllegalArgumentException("Cannot tag a symbolic allele as the reference allele"); } else { - BaseUtils.convertToUpperCase(bases); + StringUtil.toUpperCase(bases); } this.isRef = isRef; diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index fa2b5c9e5..11d84e318 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -30,7 +30,6 @@ import com.google.java.contract.Requires; import org.apache.commons.jexl2.Expression; import org.apache.commons.jexl2.JexlEngine; import org.broad.tribble.TribbleException; -import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.vcf.*; @@ -432,40 +431,6 @@ public class VariantContextUtils { // } - /** - * Returns a context identical to this with the REF and ALT alleles reverse complemented. - * - * @param vc variant context - * @return new vc - */ - public static VariantContext reverseComplement(VariantContext vc) { - // create a mapping from original allele to reverse complemented allele - HashMap alleleMap = new HashMap(vc.getAlleles().size()); - for ( Allele originalAllele : vc.getAlleles() ) { - Allele newAllele; - if ( originalAllele.isNoCall() ) - newAllele = originalAllele; - else - newAllele = Allele.create(BaseUtils.simpleReverseComplement(originalAllele.getBases()), originalAllele.isReference()); - alleleMap.put(originalAllele, newAllele); - } - - // create new Genotype objects - GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples()); - for ( final Genotype genotype : vc.getGenotypes() ) { - List newAlleles = new ArrayList(); - for ( Allele allele : genotype.getAlleles() ) { - Allele newAllele = alleleMap.get(allele); - if ( newAllele == null ) - newAllele = Allele.NO_CALL; - newAlleles.add(newAllele); - } - newGenotypes.add(new GenotypeBuilder(genotype).alleles(newAlleles).make()); - } - - return new VariantContextBuilder(vc).alleles(alleleMap.values()).genotypes(newGenotypes).make(); - } - public static VariantContext purgeUnallowedGenotypeAttributes(VariantContext vc, Set allowedAttributes) { if ( allowedAttributes == null ) return vc; @@ -483,34 +448,6 @@ public class VariantContextUtils { return new VariantContextBuilder(vc).genotypes(newGenotypes).make(); } - public static BaseUtils.BaseSubstitutionType getSNPSubstitutionType(VariantContext context) { - if (!context.isSNP() || !context.isBiallelic()) - throw new IllegalStateException("Requested SNP substitution type for bialleic non-SNP " + context); - return BaseUtils.SNPSubstitutionType(context.getReference().getBases()[0], context.getAlternateAllele(0).getBases()[0]); - } - - /** - * If this is a BiAlleic SNP, is it a transition? - */ - public static boolean isTransition(VariantContext context) { - return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSITION; - } - - /** - * If this is a BiAlleic SNP, is it a transversion? - */ - public static boolean isTransversion(VariantContext context) { - return getSNPSubstitutionType(context) == BaseUtils.BaseSubstitutionType.TRANSVERSION; - } - - public static boolean isTransition(Allele ref, Allele alt) { - return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSITION; - } - - public static boolean isTransversion(Allele ref, Allele alt) { - return BaseUtils.SNPSubstitutionType(ref.getBases()[0], alt.getBases()[0]) == BaseUtils.BaseSubstitutionType.TRANSVERSION; - } - public static int getSize( VariantContext vc ) { return vc.getEnd() - vc.getStart() + 1; } diff --git a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java similarity index 93% rename from public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java rename to public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java index 738fa28e2..cb80dbc09 100644 --- a/public/java/test/org/broadinstitute/variant/utils/BaseUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java @@ -23,20 +23,22 @@ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.broadinstitute.variant.utils; +package org.broadinstitute.sting.utils; -import org.broadinstitute.variant.VariantBaseTest; +import org.broadinstitute.sting.BaseTest; import org.testng.Assert; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; -public class BaseUtilsUnitTest extends VariantBaseTest { +public class BaseUtilsUnitTest extends BaseTest { @BeforeClass public void init() { } @Test public void testMostFrequentBaseFraction() { + logger.warn("Executing testMostFrequentBaseFraction"); + compareFrequentBaseFractionToExpected("AAAAA", 1.0); compareFrequentBaseFractionToExpected("ACCG", 0.5); compareFrequentBaseFractionToExpected("ACCCCTTTTG", 4.0/10.0); @@ -44,7 +46,7 @@ public class BaseUtilsUnitTest extends VariantBaseTest { private void compareFrequentBaseFractionToExpected(String sequence, double expected) { double fraction = BaseUtils.mostFrequentBaseFraction(sequence.getBytes()); - Assert.assertTrue(GeneralUtils.compareDoubles(fraction, expected) == 0); + Assert.assertTrue(MathUtils.compareDoubles(fraction, expected) == 0); } @Test @@ -64,6 +66,8 @@ public class BaseUtilsUnitTest extends VariantBaseTest { @Test public void testTransitionTransversion() { + logger.warn("Executing testTransitionTransversion"); + Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'T' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION ); Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'C' ) == BaseUtils.BaseSubstitutionType.TRANSVERSION ); Assert.assertTrue( BaseUtils.SNPSubstitutionType( (byte)'A', (byte)'G' ) == BaseUtils.BaseSubstitutionType.TRANSITION ); @@ -89,6 +93,8 @@ public class BaseUtilsUnitTest extends VariantBaseTest { @Test public void testReverseComplementString() { + logger.warn("Executing testReverseComplementString"); + compareRCStringToExpected("ACGGT", "ACCGT"); compareRCStringToExpected("TCGTATATCTCGCTATATATATATAGCTCTAGTATA", "TATACTAGAGCTATATATATATAGCGAGATATACGA"); compareRCStringToExpected("AAAN", "NTTT"); diff --git a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java index b65811103..0c1b5b069 100644 --- a/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/fasta/CachingIndexedFastaSequenceFileUnitTest.java @@ -252,7 +252,7 @@ public class CachingIndexedFastaSequenceFileUnitTest extends BaseTest { Assert.assertEquals(changingNs, preservingNs + 4); } - @Test(enabled = true, expectedExceptions = {IllegalStateException.class}) + @Test(enabled = true, expectedExceptions = {UserException.class}) public void testFailOnBadBase() throws FileNotFoundException, InterruptedException { final String testFasta = privateTestDir + "problematicFASTA.fasta"; final CachingIndexedFastaSequenceFile fasta = new CachingIndexedFastaSequenceFile(new File(testFasta)); diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java index 20971643e..b01c53e77 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/ReadUtilsUnitTest.java @@ -27,7 +27,7 @@ package org.broadinstitute.sting.utils.sam; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; -import org.broadinstitute.variant.utils.BaseUtils; +import org.broadinstitute.sting.utils.BaseUtils; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java index fb180c476..562130101 100644 --- a/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java +++ b/public/java/test/org/broadinstitute/variant/variantcontext/GenotypeLikelihoodsUnitTest.java @@ -31,7 +31,6 @@ package org.broadinstitute.variant.variantcontext; import org.broad.tribble.TribbleException; import org.broadinstitute.variant.VariantBaseTest; -import org.broadinstitute.variant.utils.BaseUtils; import org.broadinstitute.variant.utils.GeneralUtils; import org.testng.Assert; import org.testng.annotations.Test; @@ -154,9 +153,9 @@ public class GenotypeLikelihoodsUnitTest extends VariantBaseTest { public void testGetQualFromLikelihoodsMultiAllelic() { GenotypeLikelihoods gl = GenotypeLikelihoods.fromLog10Likelihoods(triAllelic); - Allele ref = Allele.create(BaseUtils.Base.A.base,true); - Allele alt1 = Allele.create(BaseUtils.Base.C.base); - Allele alt2 = Allele.create(BaseUtils.Base.T.base); + Allele ref = Allele.create((byte)'A',true); + Allele alt1 = Allele.create((byte)'C'); + Allele alt2 = Allele.create((byte)'T'); List allAlleles = Arrays.asList(ref,alt1,alt2); List gtAlleles = Arrays.asList(alt1,alt2); GenotypeBuilder gtBuilder = new GenotypeBuilder(); From 85dabd321f342e8893f72fb3f64892a4f977b777 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 13:26:07 -0500 Subject: [PATCH 147/188] Adding unit tests for hierarchicalBayesianQualityEstimate function --- .../recalibration/BaseRecalibration.java | 2 ++ .../recalibration/RecalDatumUnitTest.java | 33 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java index f3d4a3096..bb62cd74d 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/BaseRecalibration.java @@ -46,6 +46,7 @@ package org.broadinstitute.sting.utils.recalibration; +import com.google.java.contract.Ensures; import net.sf.samtools.SAMTag; import net.sf.samtools.SAMUtils; import org.apache.log4j.Logger; @@ -188,6 +189,7 @@ public class BaseRecalibration { } } + @Ensures("result > 0.0") protected static double hierarchicalBayesianQualityEstimate( final double epsilon, final RecalDatum empiricalQualRG, final RecalDatum empiricalQualQS, final List empiricalQualCovs ) { final double globalDeltaQ = ( empiricalQualRG == null ? 0.0 : empiricalQualRG.getEmpiricalQuality(epsilon) - epsilon ); final double deltaQReported = ( empiricalQualQS == null ? 0.0 : empiricalQualQS.getEmpiricalQuality(globalDeltaQ + epsilon) - (globalDeltaQ + epsilon) ); diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java index 37f0fcc0c..da78932d1 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RecalDatumUnitTest.java @@ -50,6 +50,7 @@ package org.broadinstitute.sting.utils.recalibration; // the imports for unit testing. +import org.apache.commons.lang.ArrayUtils; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.MathUtils; import org.broadinstitute.sting.utils.QualityUtils; @@ -57,6 +58,7 @@ import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -281,32 +283,27 @@ public class RecalDatumUnitTest extends BaseTest { @Test public void basicHierarchicalBayesianQualityEstimateTest() { - { - double RG_Q = 45.0; - RecalDatum RG = new RecalDatum( (long)10000000, (long) (10000000 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); - double Q = 30.0; - RecalDatum QS = new RecalDatum( (long)10000000, (long) (10000000 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); - RecalDatum COV = new RecalDatum( (long)150, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 45.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + for( double epsilon = 15.0; epsilon <= 60.0; epsilon += 2.0 ) { + double RG_Q = 45.0; + RecalDatum RG = new RecalDatum( (long)100000000, (long) (100000000 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); + double Q = 30.0; + RecalDatum QS = new RecalDatum( (long)100000000, (long) (100000000 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); + RecalDatum COV = new RecalDatum( (long)15, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality + // initial epsilon condition shouldn't matter when there are a lot of observations - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 25.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 5.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 65.0, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( epsilon, RG, QS, Collections.singletonList(COV)), Q, 1E-4 ); } - { + for( double epsilon = 15.0; epsilon <= 60.0; epsilon += 2.0 ) { double RG_Q = 45.0; - RecalDatum RG = new RecalDatum( (long)100, (long) (100 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); + RecalDatum RG = new RecalDatum( (long)10, (long) (10 * 1.0 / (Math.pow(10.0, RG_Q/10.0))), (byte)RG_Q); double Q = 30.0; - RecalDatum QS = new RecalDatum( (long)100, (long) (100 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); - RecalDatum COV = new RecalDatum( (long)150, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality + RecalDatum QS = new RecalDatum( (long)10, (long) (10 * 1.0 / (Math.pow(10.0, Q/10.0))), (byte)Q); + RecalDatum COV = new RecalDatum( (long)15, (long) 1, (byte)45.0); // no data here so Bayesian prior has a huge effect on the empirical quality // initial epsilon condition dominates when there is no data - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 45.0, RG, QS, Collections.singletonList(COV)), 45.0, 1E-4 ); - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 25.0, RG, QS, Collections.singletonList(COV)), 25.0, 1E-4 ); - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 5.0, RG, QS, Collections.singletonList(COV)), 5.0, 1E-4 ); - Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( 65.0, RG, QS, Collections.singletonList(COV)), 65.0, 1E-4 ); + Assert.assertEquals(BaseRecalibration.hierarchicalBayesianQualityEstimate( epsilon, RG, QS, Collections.singletonList(COV)), epsilon, 1E-4 ); } } From ff8ba03249ff81c523f02dfe753eb46ba7611a60 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 13:30:18 -0500 Subject: [PATCH 148/188] Updating BQSR integration test md5s to reflect the updates to the hierarchicalBayesianQualityEstimate function --- .../sting/gatk/walkers/bqsr/BQSRIntegrationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java index 254bfd92c..1f4875298 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java @@ -188,12 +188,12 @@ public class BQSRIntegrationTest extends WalkerTest { public Object[][] createPRTestData() { List tests = new ArrayList(); - tests.add(new Object[]{1, new PRTest(" -qq -1", "64622d37e234e57cf472068a00b4ec89")}); - tests.add(new Object[]{1, new PRTest(" -qq 6", "735270581d1ee836f3f99d68ecbd5f24")}); - tests.add(new Object[]{1, new PRTest(" -DIQ", "1e3b0a11f246a238ac4c06b084142715")}); + tests.add(new Object[]{1, new PRTest(" -qq -1", "b8d296fb78adc5cff7ce12073a69d985")}); + tests.add(new Object[]{1, new PRTest(" -qq 6", "2ee0cedf84c1a33a807438172bc36c11")}); + tests.add(new Object[]{1, new PRTest(" -DIQ", "46cf74900bf8b13438e6a195b3085c48")}); for ( final int nct : Arrays.asList(1, 2, 4) ) { - tests.add(new Object[]{nct, new PRTest("", "39ecde2c2ba4a7c109e65372618a419a")}); + tests.add(new Object[]{nct, new PRTest("", "88b88f006ebb1aade85089bfba5a9e8d")}); } return tests.toArray(new Object[][]{}); From 591df2be4473bbf5845a4c1548a4ed1f4c3bbb09 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Wed, 30 Jan 2013 13:46:59 -0500 Subject: [PATCH 149/188] Move additional VariantContext utility methods back to the GATK Thanks to Eric for his feedback --- .../walkers/phasing/ReadBackedPhasing.java | 2 +- .../walkers/variantutils/CombineVariants.java | 4 +- .../variantutils/ConcordanceMetrics.java | 8 +- .../walkers/variantutils/VariantsToVCF.java | 3 +- .../variant/GATKVariantContextUtils.java | 119 ++++++++++++++++++ .../variantcontext/VariantContext.java | 4 + .../variantcontext/VariantContextUtils.java | 117 ----------------- 7 files changed, 131 insertions(+), 126 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java index 980894112..fe38461c5 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java @@ -320,7 +320,7 @@ public class ReadBackedPhasing extends RodWalker subsetAttributes(final CommonInfo igc, final Collection keysToPreserve) { + Map attributes = new HashMap(keysToPreserve.size()); + for ( final String key : keysToPreserve ) { + if ( igc.hasAttribute(key) ) + attributes.put(key, igc.getAttribute(key)); + } + return attributes; + } + + /** + * @deprecated use variant context builder version instead + * @param vc the variant context + * @param keysToPreserve the keys to preserve + * @return a pruned version of the original variant context + */ + @Deprecated + public static VariantContext pruneVariantContext(final VariantContext vc, Collection keysToPreserve ) { + return pruneVariantContext(new VariantContextBuilder(vc), keysToPreserve).make(); + } + + public static VariantContextBuilder pruneVariantContext(final VariantContextBuilder builder, Collection keysToPreserve ) { + final VariantContext vc = builder.make(); + if ( keysToPreserve == null ) keysToPreserve = Collections.emptyList(); + + // VC info + final Map attributes = subsetAttributes(vc.getCommonInfo(), keysToPreserve); + + // Genotypes + final GenotypesContext genotypes = GenotypesContext.create(vc.getNSamples()); + for ( final Genotype g : vc.getGenotypes() ) { + final GenotypeBuilder gb = new GenotypeBuilder(g); + // remove AD, DP, PL, and all extended attributes, keeping just GT and GQ + gb.noAD().noDP().noPL().noAttributes(); + genotypes.add(gb.make()); + } + + return builder.genotypes(genotypes).attributes(attributes); + } + + public static boolean allelesAreSubset(VariantContext vc1, VariantContext vc2) { + // if all alleles of vc1 are a contained in alleles of vc2, return true + if (!vc1.getReference().equals(vc2.getReference())) + return false; + + for (Allele a :vc1.getAlternateAlleles()) { + if (!vc2.getAlternateAlleles().contains(a)) + return false; + } + + return true; + } + + public static Map> separateVariantContextsByType(Collection VCs) { + HashMap> mappedVCs = new HashMap>(); + for ( VariantContext vc : VCs ) { + + // look at previous variant contexts of different type. If: + // a) otherVC has alleles which are subset of vc, remove otherVC from its list and add otherVC to vc's list + // b) vc has alleles which are subset of otherVC. Then, add vc to otherVC's type list (rather, do nothing since vc will be added automatically to its list) + // c) neither: do nothing, just add vc to its own list + boolean addtoOwnList = true; + for (VariantContext.Type type : VariantContext.Type.values()) { + if (type.equals(vc.getType())) + continue; + + if (!mappedVCs.containsKey(type)) + continue; + + List vcList = mappedVCs.get(type); + for (int k=0; k < vcList.size(); k++) { + VariantContext otherVC = vcList.get(k); + if (allelesAreSubset(otherVC,vc)) { + // otherVC has a type different than vc and its alleles are a subset of vc: remove otherVC from its list and add it to vc's type list + vcList.remove(k); + // avoid having empty lists + if (vcList.size() == 0) + mappedVCs.remove(type); + if ( !mappedVCs.containsKey(vc.getType()) ) + mappedVCs.put(vc.getType(), new ArrayList()); + mappedVCs.get(vc.getType()).add(otherVC); + break; + } + else if (allelesAreSubset(vc,otherVC)) { + // vc has a type different than otherVC and its alleles are a subset of VC: add vc to otherVC's type list and don't add to its own + mappedVCs.get(type).add(vc); + addtoOwnList = false; + break; + } + } + } + if (addtoOwnList) { + if ( !mappedVCs.containsKey(vc.getType()) ) + mappedVCs.put(vc.getType(), new ArrayList()); + mappedVCs.get(vc.getType()).add(vc); + } + } + + return mappedVCs; + } + + public static VariantContext purgeUnallowedGenotypeAttributes(VariantContext vc, Set allowedAttributes) { + if ( allowedAttributes == null ) + return vc; + + GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples()); + for ( final Genotype genotype : vc.getGenotypes() ) { + Map attrs = new HashMap(); + for ( Map.Entry attr : genotype.getExtendedAttributes().entrySet() ) { + if ( allowedAttributes.contains(attr.getKey()) ) + attrs.put(attr.getKey(), attr.getValue()); + } + newGenotypes.add(new GenotypeBuilder(genotype).attributes(attrs).make()); + } + + return new VariantContextBuilder(vc).genotypes(newGenotypes).make(); + } + + private static class AlleleMapper { private VariantContext vc = null; private Map map = null; diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java index 05edee153..1fce89431 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContext.java @@ -625,6 +625,10 @@ public class VariantContext implements Feature { // to enable tribble integratio public double getAttributeAsDouble(String key, double defaultValue) { return commonInfo.getAttributeAsDouble(key, defaultValue); } public boolean getAttributeAsBoolean(String key, boolean defaultValue) { return commonInfo.getAttributeAsBoolean(key, defaultValue); } + public CommonInfo getCommonInfo() { + return commonInfo; + } + // --------------------------------------------------------------------------------------------------------- // // Working with alleles diff --git a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java index 11d84e318..a5b7b6c04 100644 --- a/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java +++ b/public/java/src/org/broadinstitute/variant/variantcontext/VariantContextUtils.java @@ -316,106 +316,6 @@ public class VariantContextUtils { return r; } - private final static Map subsetAttributes(final CommonInfo igc, final Collection keysToPreserve) { - Map attributes = new HashMap(keysToPreserve.size()); - for ( final String key : keysToPreserve ) { - if ( igc.hasAttribute(key) ) - attributes.put(key, igc.getAttribute(key)); - } - return attributes; - } - - /** - * @deprecated use variant context builder version instead - * @param vc the variant context - * @param keysToPreserve the keys to preserve - * @return a pruned version of the original variant context - */ - @Deprecated - public static VariantContext pruneVariantContext(final VariantContext vc, Collection keysToPreserve ) { - return pruneVariantContext(new VariantContextBuilder(vc), keysToPreserve).make(); - } - - public static VariantContextBuilder pruneVariantContext(final VariantContextBuilder builder, Collection keysToPreserve ) { - final VariantContext vc = builder.make(); - if ( keysToPreserve == null ) keysToPreserve = Collections.emptyList(); - - // VC info - final Map attributes = subsetAttributes(vc.commonInfo, keysToPreserve); - - // Genotypes - final GenotypesContext genotypes = GenotypesContext.create(vc.getNSamples()); - for ( final Genotype g : vc.getGenotypes() ) { - final GenotypeBuilder gb = new GenotypeBuilder(g); - // remove AD, DP, PL, and all extended attributes, keeping just GT and GQ - gb.noAD().noDP().noPL().noAttributes(); - genotypes.add(gb.make()); - } - - return builder.genotypes(genotypes).attributes(attributes); - } - - public static boolean allelesAreSubset(VariantContext vc1, VariantContext vc2) { - // if all alleles of vc1 are a contained in alleles of vc2, return true - if (!vc1.getReference().equals(vc2.getReference())) - return false; - - for (Allele a :vc1.getAlternateAlleles()) { - if (!vc2.getAlternateAlleles().contains(a)) - return false; - } - - return true; - } - - public static Map> separateVariantContextsByType(Collection VCs) { - HashMap> mappedVCs = new HashMap>(); - for ( VariantContext vc : VCs ) { - - // look at previous variant contexts of different type. If: - // a) otherVC has alleles which are subset of vc, remove otherVC from its list and add otherVC to vc's list - // b) vc has alleles which are subset of otherVC. Then, add vc to otherVC's type list (rather, do nothing since vc will be added automatically to its list) - // c) neither: do nothing, just add vc to its own list - boolean addtoOwnList = true; - for (VariantContext.Type type : VariantContext.Type.values()) { - if (type.equals(vc.getType())) - continue; - - if (!mappedVCs.containsKey(type)) - continue; - - List vcList = mappedVCs.get(type); - for (int k=0; k < vcList.size(); k++) { - VariantContext otherVC = vcList.get(k); - if (allelesAreSubset(otherVC,vc)) { - // otherVC has a type different than vc and its alleles are a subset of vc: remove otherVC from its list and add it to vc's type list - vcList.remove(k); - // avoid having empty lists - if (vcList.size() == 0) - mappedVCs.remove(type); - if ( !mappedVCs.containsKey(vc.getType()) ) - mappedVCs.put(vc.getType(), new ArrayList()); - mappedVCs.get(vc.getType()).add(otherVC); - break; - } - else if (allelesAreSubset(vc,otherVC)) { - // vc has a type different than otherVC and its alleles are a subset of VC: add vc to otherVC's type list and don't add to its own - mappedVCs.get(type).add(vc); - addtoOwnList = false; - break; - } - } - } - if (addtoOwnList) { - if ( !mappedVCs.containsKey(vc.getType()) ) - mappedVCs.put(vc.getType(), new ArrayList()); - mappedVCs.get(vc.getType()).add(vc); - } - } - - return mappedVCs; - } - // TODO: remove that after testing // static private void verifyUniqueSampleNames(Collection unsortedVCs) { // Set names = new HashSet(); @@ -431,23 +331,6 @@ public class VariantContextUtils { // } - public static VariantContext purgeUnallowedGenotypeAttributes(VariantContext vc, Set allowedAttributes) { - if ( allowedAttributes == null ) - return vc; - - GenotypesContext newGenotypes = GenotypesContext.create(vc.getNSamples()); - for ( final Genotype genotype : vc.getGenotypes() ) { - Map attrs = new HashMap(); - for ( Map.Entry attr : genotype.getExtendedAttributes().entrySet() ) { - if ( allowedAttributes.contains(attr.getKey()) ) - attrs.put(attr.getKey(), attr.getValue()); - } - newGenotypes.add(new GenotypeBuilder(genotype).attributes(attrs).make()); - } - - return new VariantContextBuilder(vc).genotypes(newGenotypes).make(); - } - public static int getSize( VariantContext vc ) { return vc.getEnd() - vc.getStart() + 1; } From 5f4a063def1832283157494a8acc1cbedf43502d Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 16:14:07 -0500 Subject: [PATCH 150/188] Breaking up my massive commits into smaller pieces that I can successfully merge and digest. This one enables downsampling in the HaplotypeCaller (by lowering the default dcov to 20) and removes my long-standing, temporary region-based downsampling. --- .../haplotypecaller/HaplotypeCaller.java | 36 +++---------------- .../HaplotypeCallerIntegrationTest.java | 24 ++++++------- 2 files changed, 16 insertions(+), 44 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index a27eaac8e..6cfbc3830 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -56,6 +56,7 @@ import org.broadinstitute.sting.gatk.arguments.StandardCallerArgumentCollection; import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.AlignmentContextUtils; import org.broadinstitute.sting.gatk.contexts.ReferenceContext; +import org.broadinstitute.sting.gatk.downsampling.DownsampleType; import org.broadinstitute.sting.gatk.filters.BadMateFilter; import org.broadinstitute.sting.gatk.io.StingSAMFileWriter; import org.broadinstitute.sting.gatk.iterators.ReadTransformer; @@ -132,7 +133,7 @@ import java.util.*; @PartitionBy(PartitionType.LOCUS) @BAQMode(ApplicationTime = ReadTransformer.ApplicationTime.FORBIDDEN) @ActiveRegionTraversalParameters(extension=65, maxRegion=300) -//@Downsample(by= DownsampleType.BY_SAMPLE, toCoverage=5) +@Downsample(by= DownsampleType.BY_SAMPLE, toCoverage=20) public class HaplotypeCaller extends ActiveRegionWalker implements AnnotatorCompatible { /** @@ -180,9 +181,6 @@ public class HaplotypeCaller extends ActiveRegionWalker implem @Argument(fullName="minKmer", shortName="minKmer", doc="Minimum kmer length to use in the assembly graph", required = false) protected int minKmer = 11; - @Argument(fullName="downsampleRegion", shortName="dr", doc="coverage, per-sample, to downsample each active region to", required = false) - protected int DOWNSAMPLE_PER_SAMPLE_PER_REGION = 1000; - /** * If this flag is provided, the haplotype caller will include unmapped reads in the assembly and calling * when these reads occur in the region being analyzed. Typically, for paired end analyses, one pair of the @@ -463,7 +461,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem allelesToGenotype.removeAll( activeAllelesToGenotype ); } - if( !activeRegion.isActive()) { return 0; } // Not active so nothing to do! + if( !activeRegion.isActive() ) { return 0; } // Not active so nothing to do! if( activeRegion.size() == 0 && UG_engine.getUAC().GenotypingMode != GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ) { return 0; } // No reads here so nothing to do! if( UG_engine.getUAC().GenotypingMode == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES && activeAllelesToGenotype.isEmpty() ) { return 0; } // No alleles found in this region so nothing to do! @@ -474,7 +472,6 @@ public class HaplotypeCaller extends ActiveRegionWalker implem final Haplotype referenceHaplotype = new Haplotype(activeRegion.getActiveRegionReference(referenceReader), true); // Create the reference haplotype which is the bases from the reference that make up the active region final byte[] fullReferenceWithPadding = activeRegion.getFullReference(referenceReader, REFERENCE_PADDING); - //int PRUNE_FACTOR = Math.max(MIN_PRUNE_FACTOR, determinePruneFactorFromCoverage( activeRegion )); final ArrayList haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, fullSpanBeforeClipping, MIN_PRUNE_FACTOR, activeAllelesToGenotype ); if( haplotypes.size() == 1 ) { return 1; } // only the reference haplotype remains so nothing else to do! @@ -571,18 +568,13 @@ public class HaplotypeCaller extends ActiveRegionWalker implem finalizedReadList.addAll( FragmentUtils.mergeOverlappingPairedFragments(overlappingPair) ); } - Collections.shuffle(finalizedReadList, GenomeAnalysisEngine.getRandomGenerator()); - // Loop through the reads hard clipping the adaptor and low quality tails final ArrayList readsToUse = new ArrayList(finalizedReadList.size()); for( final GATKSAMRecord myRead : finalizedReadList ) { final GATKSAMRecord postAdapterRead = ( myRead.getReadUnmappedFlag() ? myRead : ReadClipper.hardClipAdaptorSequence( myRead ) ); if( postAdapterRead != null && !postAdapterRead.isEmpty() && postAdapterRead.getCigar().getReadLength() > 0 ) { final GATKSAMRecord clippedRead = ReadClipper.hardClipLowQualEnds( postAdapterRead, MIN_TAIL_QUALITY ); - // protect against INTERVALS with abnormally high coverage - // TODO BUGBUG: remove when positional downsampler is hooked up to ART/HC - if( activeRegion.readOverlapsRegion(clippedRead) && - clippedRead.getReadLength() > 0 && activeRegion.size() < samplesList.size() * DOWNSAMPLE_PER_SAMPLE_PER_REGION ) { + if( activeRegion.readOverlapsRegion(clippedRead) && clippedRead.getReadLength() > 0 ) { readsToUse.add(clippedRead); } } @@ -711,24 +703,4 @@ public class HaplotypeCaller extends ActiveRegionWalker implem return new Cigar(readCigarElements); } - - /* - private int determinePruneFactorFromCoverage( final ActiveRegion activeRegion ) { - final ArrayList readLengthDistribution = new ArrayList(); - for( final GATKSAMRecord read : activeRegion.getReads() ) { - readLengthDistribution.add(read.getReadLength()); - } - final double meanReadLength = MathUtils.average(readLengthDistribution); - final double meanCoveragePerSample = (double) activeRegion.getReads().size() / ((double) activeRegion.getExtendedLoc().size() / meanReadLength) / (double) samplesList.size(); - int PRUNE_FACTOR = 0; - if( meanCoveragePerSample > 8.5 ) { - PRUNE_FACTOR = (int) Math.floor( Math.sqrt( meanCoveragePerSample - 5.0 ) ); - } else if( meanCoveragePerSample > 3.0 ) { - PRUNE_FACTOR = 1; - } - - if( DEBUG ) { System.out.println(String.format("Mean coverage per sample = %.1f --> prune factor = %d", meanCoveragePerSample, PRUNE_FACTOR)); } - return PRUNE_FACTOR; - } - */ } \ No newline at end of file diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index d446da830..ad682734c 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -68,12 +68,12 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSample() { - HCTest(CEUTRIO_BAM, "", "664a14590d0966e63d3aabff2d7bab0a"); + HCTest(CEUTRIO_BAM, "", "72ce6a5e46644dfd73aeffba9d6131ea"); } @Test public void testHaplotypeCallerSingleSample() { - HCTest(NA12878_BAM, "", "111f3dc086a3cea1be9bd1ad6e1d18ed"); + HCTest(NA12878_BAM, "", "f9d696391f1f337092d70e3abcd32bfb"); } @Test(enabled = false) @@ -84,7 +84,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGA() { HCTest(CEUTRIO_BAM, "--max_alternate_alleles 3 -gt_mode GENOTYPE_GIVEN_ALLELES -out_mode EMIT_ALL_SITES -alleles " + validationDataLocation + "combined.phase1.chr20.raw.indels.sites.vcf", - "c70f753f7918a1c670ce4ed5c66de09e"); + "4e8beb2cdc3d77427f14acf37cea2bd0"); } private void HCTestComplexGGA(String bam, String args, String md5) { @@ -96,13 +96,13 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleGGAComplex() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:119673-119823 -L 20:121408-121538", - "b1d3070f0c49becf34101e480ab6c589"); + "75e1df0dcf3728fd2b6e4735c4cc88ce"); } @Test public void testHaplotypeCallerMultiSampleGGAMultiAllelic() { HCTestComplexGGA(NA12878_CHR20_BAM, "-L 20:133041-133161 -L 20:300207-300337", - "20eba2e54266f6aebf35b7b7b7e754e3"); + "1d244f2adbc72a0062eb673d56cbb5a8"); } private void HCTestComplexVariants(String bam, String args, String md5) { @@ -113,7 +113,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerMultiSampleComplex() { - HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "f9805488d85e59e1ae002d0d32d7011d"); + HCTestComplexVariants(privateTestDir + "AFR.complex.variants.bam", "", "a1bc844f62a9cb60dbb70d00ad36b85d"); } private void HCTestSymbolicVariants(String bam, String args, String md5) { @@ -124,7 +124,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleSymbolic() { - HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "4544a2916f46f58b32db8008776b91a3"); + HCTestSymbolicVariants(NA12878_CHR20_BAM, "", "23956e572f19ff26d25bbdfaa307675b"); } private void HCTestIndelQualityScores(String bam, String args, String md5) { @@ -135,7 +135,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void testHaplotypeCallerSingleSampleIndelQualityScores() { - HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "f3984a91e7562494c2a7e41fd05a6734"); + HCTestIndelQualityScores(NA12878_RECALIBRATED_BAM, "", "1255f466aa2d288f015cd55d8fece1ac"); } // That problem bam came from a user on the forum and it spotted a problem where the ReadClipper @@ -146,14 +146,14 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { @Test public void HCTestProblematicReadsModifiedInActiveRegions() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "haplotype-problem-4.bam") + " --no_cmdline_in_header -o %s -minPruning 3 -L 4:49139026-49139965"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("3e9e025c539be6c5e0d0f2e5d8e86a62")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("103c91c4a78164949e166d3d27eb459b")); executeTest("HCTestProblematicReadsModifiedInActiveRegions: ", spec); } @Test public void HCTestStructuralIndels() { final String base = String.format("-T HaplotypeCaller -R %s -I %s", REF, privateTestDir + "AFR.structural.indels.bam") + " --no_cmdline_in_header -o %s -minPruning 6 -L 20:8187565-8187800 -L 20:18670537-18670730"; - final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("34129e6c6310ef4eeeeb59b0e7ac0464")); + final WalkerTestSpec spec = new WalkerTestSpec(base, Arrays.asList("87fe31a4bbd68a9eb5d5910db5011c82")); executeTest("HCTestStructuralIndels: ", spec); } @@ -175,7 +175,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void HCTestReducedBam() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "bamExample.ReducedRead.ADAnnotation.bam -o %s -L 1:67,225,396-67,288,518", 1, - Arrays.asList("5f4c07aaf1d2d34cccce43196a5fbd71")); + Arrays.asList("0fa19ec5cf737a3445544b59ecc995e9")); executeTest("HC calling on a ReducedRead BAM", spec); } @@ -183,7 +183,7 @@ public class HaplotypeCallerIntegrationTest extends WalkerTest { public void testReducedBamWithReadsNotFullySpanningDeletion() { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( "-T HaplotypeCaller -R " + b37KGReference + " --no_cmdline_in_header -I " + privateTestDir + "reduced.readNotFullySpanningDeletion.bam -o %s -L 1:167871297", 1, - Arrays.asList("6ead001b1f8e7cb433fd335f78fde5f0")); + Arrays.asList("5f4cbdcc9bffee6bba258dfac89492ed")); executeTest("test calling on a ReducedRead BAM where the reads do not fully span a deletion", spec); } } From b70733133260bc76cdd1cfcb6efdc89107f0f005 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Wed, 30 Jan 2013 16:41:23 -0500 Subject: [PATCH 151/188] Encrypt GATK AWS keys using the GATK private key, and decrypt as needed as a resource when uploading to AWS logs -- Has the overall effect that the GATK user AWS keys are no longer visible in the gatk source as plain text. This will stop AWS from emailing me (they crawl the web looking for keys) -- Added utility EncryptAWSKeys that takes as command line arguments the GATK user AWS access and secret keys, encrypts them with the GATK private key, and writes out the resulting file to resources in phonehome. -- GATKRunReport now decrypts as needed these keys using the GATK public key as resources in the GATK bundle -- Refactored the essential function of Resource (reading the resource) from IOUtils into the class itself. Now how to get the data in the resouce is straightforward -- Refactored md5 calculation code from a byte[] into Utils. Added unit tests -- Committing the encrypted AWS keys -- #resolves https://jira.broadinstitute.org/browse/GSA-730 --- build.xml | 3 + .../sting/gatk/phonehome/GATKRunReport.java | 59 ++++++++++++++++-- .../sting/gatk/phonehome/GATK_AWS_access.key | 2 + .../sting/gatk/phonehome/GATK_AWS_secret.key | Bin 0 -> 256 bytes .../org/broadinstitute/sting/utils/Utils.java | 28 +++++++++ .../sting/utils/io/IOUtils.java | 12 +--- .../sting/utils/io/Resource.java | 24 +++++++ .../test/org/broadinstitute/sting/MD5DB.java | 9 +-- .../gatk/phonehome/GATKRunReportUnitTest.java | 52 +++++++++++++++ .../sting/utils/UtilsUnitTest.java | 15 +++++ 10 files changed, 181 insertions(+), 23 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key create mode 100644 public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_secret.key create mode 100644 public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java diff --git a/build.xml b/build.xml index e92e41c10..1e88bb400 100644 --- a/build.xml +++ b/build.xml @@ -708,6 +708,9 @@ + + + diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index c2a064dbe..839ebcfa1 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -31,8 +31,11 @@ import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.crypt.CryptUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; +import org.broadinstitute.sting.utils.io.IOUtils; +import org.broadinstitute.sting.utils.io.Resource; import org.broadinstitute.sting.utils.threading.ThreadEfficiencyMonitor; import org.jets3t.service.S3Service; import org.jets3t.service.S3ServiceException; @@ -48,6 +51,7 @@ import org.simpleframework.xml.stream.HyphenStyle; import java.io.*; import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -309,6 +313,51 @@ public class GATKRunReport { } } + /** + * Decrypts encrypted AWS key from encryptedKeySource + * @param encryptedKeySource a file containing an encrypted AWS key + * @return a decrypted AWS key as a String + */ + public static String decryptAWSKey(final File encryptedKeySource) throws FileNotFoundException { + return decryptAWSKey(new FileInputStream(encryptedKeySource)); + } + + /** + * @see #decryptAWSKey(java.io.File) but with input from an inputstream + */ + private static String decryptAWSKey(final InputStream encryptedKeySource) { + final PublicKey key = CryptUtils.loadGATKDistributedPublicKey(); + final byte[] fromDisk = IOUtils.readStreamIntoByteArray(encryptedKeySource); + final byte[] decrypted = CryptUtils.decryptData(fromDisk, key); + return new String(decrypted); + } + + /** + * Get the decrypted AWS key sorted in the resource directories of name + * @param name the name of the file containing the needed AWS key + * @return a non-null GATK + */ + private static String getAWSKey(final String name) { + final Resource resource = new Resource(name, GATKRunReport.class); + return decryptAWSKey(resource.getResourceContentsAsStream()); + } + + /** + * Get the AWS access key for the GATK user + * @return a non-null AWS access key for the GATK user + */ + protected static String getAWSAccessKey() { + return getAWSKey("GATK_AWS_access.key"); + } + + /** + * Get the AWS secret key for the GATK user + * @return a non-null AWS secret key for the GATK user + */ + protected static String getAWSSecretKey() { + return getAWSKey("GATK_AWS_secret.key"); + } + private class S3PutRunnable implements Runnable { public AtomicBoolean isSuccess; @@ -331,17 +380,17 @@ public class GATKRunReport { // are stored in an AWSCredentials object: // IAM GATK user credentials -- only right is to PutObject into GATK_Run_Report bucket - String awsAccessKey = "AKIAJXU7VIHBPDW4TDSQ"; // GATK AWS user - String awsSecretKey = "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"; // GATK AWS user - AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey); + final String awsAccessKey = getAWSAccessKey(); // GATK AWS user + final String awsSecretKey = getAWSSecretKey(); // GATK AWS user + final AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey); // To communicate with S3, create a class that implements an S3Service. We will use the REST/HTTP // implementation based on HttpClient, as this is the most robust implementation provided with JetS3t. - S3Service s3Service = new RestS3Service(awsCredentials); + final S3Service s3Service = new RestS3Service(awsCredentials); // Create an S3Object based on a file, with Content-Length set automatically and // Content-Type set based on the file's extension (using the Mimetypes utility class) - S3Object fileObject = new S3Object(key, report); + final S3Object fileObject = new S3Object(key, report); //logger.info("Created S3Object" + fileObject); //logger.info("Uploading " + localFile + " to AWS bucket"); s3Object = s3Service.putObject(REPORT_BUCKET_NAME, fileObject); diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key new file mode 100644 index 000000000..45242c3cd --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key @@ -0,0 +1,2 @@ +BÜw“ìX~¨[užûG¢£›ÔøÅ¦e‰÷á‡,툉)s­/sg1µáÙL„±ƒQ¹šaG%$·RÝŠìŸ{xÿqPz׊Ž”J®¬}”á\¸–´”{(äâÑÍBœK’&ܶ™ŽõÇ,’`¥³÷”@`oX +%/`mâ֑Ȥ3Àhø3ÜàrQº v1šaªW•š?ˆ‘uH¼ŒÖÕÇÛØæsðÅâŽaÌz¬Þ¿­ÅMÆË¦?îUzh÷ì·k#+ŒxÄ„Müík“ ¦©Xž²)ºý°MıšÕ• Çipò-î?jêŠúHµ@d+HR|šbò³F \ No newline at end of file diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_secret.key b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_secret.key new file mode 100644 index 0000000000000000000000000000000000000000..b86a25036e84ae8a1373776e52f1ef04a135bfd0 GIT binary patch literal 256 zcmV+b0ssClQ_lh#EL zNy%zD4$cZr3OHzad*T{?JVK|@Tkm)?rp1pN33JU-fi{b*XQH?g&z%d%(ha|KT`EjN zBSe){t0~(z%*aiOc6s(*c)DT0;m|PNz6Iq-NLK3b$Te4ViCd4fXKs%s(Pj` clazz = resource.getRelativeClass(); - InputStream inputStream = null; + InputStream inputStream = resource.getResourceContentsAsStream(); OutputStream outputStream = null; try { - if (clazz == null) { - inputStream = ClassLoader.getSystemResourceAsStream(path); - if (inputStream == null) - throw new IllegalArgumentException("Resource not found: " + path); - } else { - inputStream = clazz.getResourceAsStream(path); - if (inputStream == null) - throw new IllegalArgumentException("Resource not found relative to " + clazz + ": " + path); - } outputStream = FileUtils.openOutputStream(file); org.apache.commons.io.IOUtils.copy(inputStream, outputStream); } catch (IOException e) { diff --git a/public/java/src/org/broadinstitute/sting/utils/io/Resource.java b/public/java/src/org/broadinstitute/sting/utils/io/Resource.java index 1f181a826..85ca5ce1c 100644 --- a/public/java/src/org/broadinstitute/sting/utils/io/Resource.java +++ b/public/java/src/org/broadinstitute/sting/utils/io/Resource.java @@ -26,6 +26,7 @@ package org.broadinstitute.sting.utils.io; import java.io.File; +import java.io.InputStream; /** * Stores a resource by path and a relative class. @@ -64,4 +65,27 @@ public class Resource { File.separator, path); } + + /** + * Get the contents of this resource as an InputStream + * @throws IllegalArgumentException if resource cannot be read + * @return an input stream that will read the contents of this resource + */ + public InputStream getResourceContentsAsStream() { + final Class clazz = getRelativeClass(); + + final InputStream inputStream; + if (clazz == null) { + inputStream = ClassLoader.getSystemResourceAsStream(path); + if (inputStream == null) + throw new IllegalArgumentException("Resource not found: " + path); + } else { + inputStream = clazz.getResourceAsStream(path); + if (inputStream == null) + throw new IllegalArgumentException("Resource not found relative to " + clazz + ": " + path); + + } + + return inputStream; + } } diff --git a/public/java/test/org/broadinstitute/sting/MD5DB.java b/public/java/test/org/broadinstitute/sting/MD5DB.java index aed98b78a..2b0d52a11 100644 --- a/public/java/test/org/broadinstitute/sting/MD5DB.java +++ b/public/java/test/org/broadinstitute/sting/MD5DB.java @@ -28,11 +28,10 @@ package org.broadinstitute.sting; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.broadinstitute.sting.gatk.walkers.diffengine.DiffEngine; +import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.*; -import java.math.BigInteger; -import java.security.MessageDigest; import java.util.Arrays; /** @@ -252,11 +251,7 @@ public class MD5DB { */ public String testFileMD5(final String name, final File resultsFile, final String expectedMD5, final boolean parameterize) { try { - byte[] bytesOfMessage = getBytesFromFile(resultsFile); - byte[] thedigest = MessageDigest.getInstance("MD5").digest(bytesOfMessage); - BigInteger bigInt = new BigInteger(1, thedigest); - String filemd5sum = bigInt.toString(16); - while (filemd5sum.length() < 32) filemd5sum = "0" + filemd5sum; // pad to length 32 + final String filemd5sum = Utils.calcMD5(getBytesFromFile(resultsFile)); // // copy md5 to integrationtests diff --git a/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java new file mode 100644 index 000000000..03f19968c --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.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.phonehome; + +import junit.framework.Assert; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.Utils; +import org.testng.annotations.Test; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class GATKRunReportUnitTest extends BaseTest { + @Test + public void testAccessKey() throws Exception { + testAWSKey(GATKRunReport.getAWSAccessKey(), "c0f0afa1ff5ba41d9bf216cfcdbf26bf"); + } + + @Test + public void testSecretKey() throws Exception { + testAWSKey(GATKRunReport.getAWSSecretKey(), "db2f13b3a7c98ad24e28783733ec4a62"); + } + + private void testAWSKey(final String accessKey, final String expectedMD5) throws Exception { + Assert.assertNotNull(accessKey, "AccessKey should not be null"); + final String actualmd5 = Utils.calcMD5(accessKey); + Assert.assertEquals(actualmd5, expectedMD5); + } +} diff --git a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java index fc10f1102..5d6ecd0f9 100644 --- a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java @@ -25,10 +25,13 @@ package org.broadinstitute.sting.utils; +import org.apache.commons.io.FileUtils; +import org.broadinstitute.sting.utils.io.IOUtils; import org.testng.Assert; import org.broadinstitute.sting.BaseTest; import org.testng.annotations.Test; +import java.io.File; import java.util.LinkedHashMap; import java.util.Map; @@ -135,4 +138,16 @@ public class UtilsUnitTest extends BaseTest { actual = Utils.escapeExpressions(" one two 'three four' "); Assert.assertEquals(actual, expected); } + + @Test + public void testCalcMD5() throws Exception { + final File source = new File(publicTestDir + "exampleFASTA.fasta"); + final String sourceMD5 = "36880691cf9e4178216f7b52e8d85fbe"; + + final byte[] sourceBytes = IOUtils.readFileIntoByteArray(source); + Assert.assertEquals(Utils.calcMD5(sourceBytes), sourceMD5); + + final String sourceString = FileUtils.readFileToString(source); + Assert.assertEquals(Utils.calcMD5(sourceString), sourceMD5); + } } From bb29bd7df75b258cc122cbff0968bb5b8da46c3a Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Wed, 30 Jan 2013 17:09:27 -0500 Subject: [PATCH 152/188] Use base List and Map types in the HaplotypeCaller when possible. --- .../haplotypecaller/GenotypingEngine.java | 44 +++++------ .../haplotypecaller/HaplotypeCaller.java | 26 +++---- .../LikelihoodCalculationEngine.java | 73 ++----------------- .../haplotypecaller/LocalAssemblyEngine.java | 4 +- .../SimpleDeBruijnAssembler.java | 18 ++--- .../broadinstitute/sting/utils/Haplotype.java | 6 +- .../utils/activeregion/ActiveRegion.java | 4 +- .../sting/utils/clipping/ReadClipper.java | 4 +- 8 files changed, 60 insertions(+), 119 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java index d254f5b8b..8b789791d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngine.java @@ -84,7 +84,7 @@ public class GenotypingEngine { final List haplotypes, final List samples, final Map haplotypeReadMap, - final Map> perSampleFilteredReadList, + final Map> perSampleFilteredReadList, final byte[] ref, final GenomeLoc refLoc, final GenomeLoc activeRegionWindow, @@ -124,12 +124,12 @@ public class GenotypingEngine { // Walk along each position in the key set and create each event to be outputted for( final int loc : startPosKeySet ) { if( loc >= activeRegionWindow.getStart() && loc <= activeRegionWindow.getStop() ) { // genotyping an event inside this active region - final ArrayList eventsAtThisLoc = new ArrayList(); // the overlapping events to merge into a common reference view - final ArrayList priorityList = new ArrayList(); // used to merge overlapping events into common reference view + final List eventsAtThisLoc = new ArrayList(); // the overlapping events to merge into a common reference view + final List priorityList = new ArrayList(); // used to merge overlapping events into common reference view if( !in_GGA_mode ) { for( final Haplotype h : haplotypes ) { - final HashMap eventMap = h.getEventMap(); + final Map eventMap = h.getEventMap(); final VariantContext vc = eventMap.get(loc); if( vc != null && !containsVCWithMatchingAlleles(eventsAtThisLoc, vc) ) { eventsAtThisLoc.add(vc); @@ -142,7 +142,7 @@ public class GenotypingEngine { if( compVC.getStart() == loc ) { int alleleCount = 0; for( final Allele compAltAllele : compVC.getAlternateAlleles() ) { - ArrayList alleleSet = new ArrayList(2); + List alleleSet = new ArrayList(2); alleleSet.add(compVC.getReference()); alleleSet.add(compAltAllele); final String vcSourceName = "Comp" + compCount + "Allele" + alleleCount; @@ -180,7 +180,7 @@ public class GenotypingEngine { if( eventsAtThisLoc.size() != mergedVC.getAlternateAlleles().size() ) { throw new ReviewedStingException("Record size mismatch! Something went wrong in the merging of alleles."); } - final HashMap mergeMap = new HashMap(); + final Map mergeMap = new HashMap(); mergeMap.put(null, mergedVC.getReference()); // the reference event (null) --> the reference allele for(int iii = 0; iii < mergedVC.getAlternateAlleles().size(); iii++) { mergeMap.put(eventsAtThisLoc.get(iii), mergedVC.getAlternateAllele(iii)); // BUGBUG: This is assuming that the order of alleles is the same as the priority list given to simpleMerge function @@ -232,7 +232,7 @@ public class GenotypingEngine { return genotypes; } - private void validatePriorityList( final ArrayList priorityList, final ArrayList eventsAtThisLoc ) { + private void validatePriorityList( final List priorityList, final List eventsAtThisLoc ) { for( final VariantContext vc : eventsAtThisLoc ) { if( !priorityList.contains(vc.getSource()) ) { throw new ReviewedStingException("Event found on haplotype that wasn't added to priority list. Something went wrong in the merging of alleles."); @@ -251,7 +251,7 @@ public class GenotypingEngine { private static Map filterToOnlyOverlappingReads( final GenomeLocParser parser, final Map perSampleReadMap, - final Map> perSampleFilteredReadList, + final Map> perSampleFilteredReadList, final VariantContext call ) { final Map returnMap = new HashMap(); @@ -284,7 +284,7 @@ public class GenotypingEngine { } protected static void cleanUpSymbolicUnassembledEvents( final List haplotypes ) { - final ArrayList haplotypesToRemove = new ArrayList(); + final List haplotypesToRemove = new ArrayList(); for( final Haplotype h : haplotypes ) { for( final VariantContext vc : h.getEventMap().values() ) { if( vc.isSymbolic() ) { @@ -407,7 +407,7 @@ public class GenotypingEngine { // remove the old event from the eventMap on every haplotype and the start pos key set, replace with merged event for( final Haplotype h : haplotypes ) { - final HashMap eventMap = h.getEventMap(); + final Map eventMap = h.getEventMap(); if( eventMap.containsKey(thisStart) && eventMap.containsKey(nextStart) ) { eventMap.remove(thisStart); eventMap.remove(nextStart); @@ -418,7 +418,7 @@ public class GenotypingEngine { boolean containsStart = false; boolean containsNext = false; for( final Haplotype h : haplotypes ) { - final HashMap eventMap = h.getEventMap(); + final Map eventMap = h.getEventMap(); if( eventMap.containsKey(thisStart) ) { containsStart = true; } if( eventMap.containsKey(nextStart) ) { containsNext = true; } } @@ -457,7 +457,7 @@ public class GenotypingEngine { if( refBases.length == altBases.length ) { // insertion + deletion of same length creates an MNP --> trim common prefix bases off the beginning of the allele while( iii < refBases.length && refBases[iii] == altBases[iii] ) { iii++; } } - final ArrayList mergedAlleles = new ArrayList(); + final List mergedAlleles = new ArrayList(); mergedAlleles.add( Allele.create( ArrayUtils.subarray(refBases, iii, refBases.length), true ) ); mergedAlleles.add( Allele.create( ArrayUtils.subarray(altBases, iii, altBases.length), false ) ); return new VariantContextBuilder("merged", thisVC.getChr(), thisVC.getStart() + iii, nextVC.getEnd(), mergedAlleles).make(); @@ -492,10 +492,10 @@ public class GenotypingEngine { eventMapper.put(new Event(vc), new ArrayList()); } - final ArrayList undeterminedHaplotypes = new ArrayList(haplotypes.size()); + final List undeterminedHaplotypes = new ArrayList(haplotypes.size()); for( final Haplotype h : haplotypes ) { if( h.isArtificialHaplotype() && loc == h.getArtificialAllelePosition() ) { - final ArrayList alleles = new ArrayList(2); + final List alleles = new ArrayList(2); alleles.add(h.getArtificialRefAllele()); alleles.add(h.getArtificialAltAllele()); final Event artificialVC = new Event( (new VariantContextBuilder()).source("artificialHaplotype") @@ -572,13 +572,13 @@ public class GenotypingEngine { } @Ensures({"result.size() == haplotypeAllelesForSample.size()"}) - protected static List findEventAllelesInSample( final List eventAlleles, final List haplotypeAlleles, final List haplotypeAllelesForSample, final ArrayList> alleleMapper, final ArrayList haplotypes ) { + protected static List findEventAllelesInSample( final List eventAlleles, final List haplotypeAlleles, final List haplotypeAllelesForSample, final List> alleleMapper, final List haplotypes ) { if( haplotypeAllelesForSample.contains(Allele.NO_CALL) ) { return noCall; } - final ArrayList eventAllelesForSample = new ArrayList(); + final List eventAllelesForSample = new ArrayList(); for( final Allele a : haplotypeAllelesForSample ) { final Haplotype haplotype = haplotypes.get(haplotypeAlleles.indexOf(a)); for( int iii = 0; iii < alleleMapper.size(); iii++ ) { - final ArrayList mappedHaplotypes = alleleMapper.get(iii); + final List mappedHaplotypes = alleleMapper.get(iii); if( mappedHaplotypes.contains(haplotype) ) { eventAllelesForSample.add(eventAlleles.get(iii)); break; @@ -597,8 +597,8 @@ public class GenotypingEngine { return false; } - protected static HashMap generateVCsFromAlignment( final Haplotype haplotype, final int alignmentStartHapwrtRef, final Cigar cigar, final byte[] ref, final byte[] alignment, final GenomeLoc refLoc, final String sourceNameToAdd ) { - final HashMap vcs = new HashMap(); + protected static Map generateVCsFromAlignment( final Haplotype haplotype, final int alignmentStartHapwrtRef, final Cigar cigar, final byte[] ref, final byte[] alignment, final GenomeLoc refLoc, final String sourceNameToAdd ) { + final Map vcs = new HashMap(); int refPos = alignmentStartHapwrtRef; if( refPos < 0 ) { return null; } // Protection against SW failures @@ -609,7 +609,7 @@ public class GenotypingEngine { switch( ce.getOperator() ) { case I: { - final ArrayList insertionAlleles = new ArrayList(); + final List insertionAlleles = new ArrayList(); final int insertionStart = refLoc.getStart() + refPos - 1; final byte refByte = ref[refPos-1]; if( BaseUtils.isRegularBase(refByte) ) { @@ -639,7 +639,7 @@ public class GenotypingEngine { case D: { final byte[] deletionBases = Arrays.copyOfRange( ref, refPos - 1, refPos + elementLength ); // add padding base - final ArrayList deletionAlleles = new ArrayList(); + final List deletionAlleles = new ArrayList(); final int deletionStart = refLoc.getStart() + refPos - 1; // BUGBUG: how often does this symbolic deletion allele case happen? //if( haplotype != null && ( (haplotype.leftBreakPoint + alignmentStartHapwrtRef + refLoc.getStart() + elementLength - 1 >= deletionStart && haplotype.leftBreakPoint + alignmentStartHapwrtRef + refLoc.getStart() + elementLength - 1 < deletionStart + elementLength) @@ -667,7 +667,7 @@ public class GenotypingEngine { final byte altByte = alignment[alignmentPos]; if( refByte != altByte ) { // SNP! if( BaseUtils.isRegularBase(refByte) && BaseUtils.isRegularBase(altByte) ) { - final ArrayList snpAlleles = new ArrayList(); + final List snpAlleles = new ArrayList(); snpAlleles.add( Allele.create( refByte, true ) ); snpAlleles.add( Allele.create( altByte, false ) ); vcs.put(refLoc.getStart() + refPos, new VariantContextBuilder(sourceNameToAdd, refLoc.getContig(), refLoc.getStart() + refPos, refLoc.getStart() + refPos, snpAlleles).make()); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 6cfbc3830..027c62e68 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -274,10 +274,10 @@ public class HaplotypeCaller extends ActiveRegionWalker implem // bases with quality less than or equal to this value are trimmed off the tails of the reads private static final byte MIN_TAIL_QUALITY = 20; - private ArrayList samplesList = new ArrayList(); + private List samplesList = new ArrayList(); private final static double LOG_ONE_HALF = -Math.log10(2.0); private final static double LOG_ONE_THIRD = -Math.log10(3.0); - private final ArrayList allelesToGenotype = new ArrayList(); + private final List allelesToGenotype = new ArrayList(); private final static Allele FAKE_REF_ALLELE = Allele.create("N", true); // used in isActive function to call into UG Engine. Should never appear anywhere in a VCF file private final static Allele FAKE_ALT_ALLELE = Allele.create("", false); // used in isActive function to call into UG Engine. Should never appear anywhere in a VCF file @@ -429,7 +429,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem genotypes.add( new GenotypeBuilder(sample.getKey()).alleles(noCall).PL(genotypeLikelihoods).make() ); } - final ArrayList alleles = new ArrayList(); + final List alleles = new ArrayList(); alleles.add( FAKE_REF_ALLELE ); alleles.add( FAKE_ALT_ALLELE ); final VariantCallContext vcOut = UG_engine_simple_genotyper.calculateGenotypes(new VariantContextBuilder("HCisActive!", context.getContig(), context.getLocation().getStart(), context.getLocation().getStop(), alleles).genotypes(genotypes).make(), GenotypeLikelihoodsCalculationModel.Model.INDEL); @@ -450,7 +450,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem // we're benchmarking ART and/or the active region determination code in the HC, just leave without doing any work return 1; - final ArrayList activeAllelesToGenotype = new ArrayList(); + final List activeAllelesToGenotype = new ArrayList(); if( UG_engine.getUAC().GenotypingMode == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ) { for( final VariantContext vc : allelesToGenotype ) { @@ -472,7 +472,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem final Haplotype referenceHaplotype = new Haplotype(activeRegion.getActiveRegionReference(referenceReader), true); // Create the reference haplotype which is the bases from the reference that make up the active region final byte[] fullReferenceWithPadding = activeRegion.getFullReference(referenceReader, REFERENCE_PADDING); - final ArrayList haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, fullSpanBeforeClipping, MIN_PRUNE_FACTOR, activeAllelesToGenotype ); + final List haplotypes = assemblyEngine.runLocalAssembly( activeRegion, referenceHaplotype, fullReferenceWithPadding, fullSpanBeforeClipping, MIN_PRUNE_FACTOR, activeAllelesToGenotype ); if( haplotypes.size() == 1 ) { return 1; } // only the reference haplotype remains so nothing else to do! activeRegion.hardClipToActiveRegion(); // only evaluate the parts of reads that are overlapping the active region @@ -484,10 +484,10 @@ public class HaplotypeCaller extends ActiveRegionWalker implem // evaluate each sample's reads against all haplotypes final Map stratifiedReadMap = likelihoodCalculationEngine.computeReadLikelihoods( haplotypes, splitReadsBySample( activeRegion.getReads() ) ); - final Map> perSampleFilteredReadList = splitReadsBySample( filteredReads ); + final Map> perSampleFilteredReadList = splitReadsBySample( filteredReads ); // subset down to only the best haplotypes to be genotyped in all samples ( in GGA mode use all discovered haplotypes ) - final ArrayList bestHaplotypes = ( UG_engine.getUAC().GenotypingMode != GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ? + final List bestHaplotypes = ( UG_engine.getUAC().GenotypingMode != GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES ? likelihoodCalculationEngine.selectBestHaplotypes( haplotypes, stratifiedReadMap, maxNumHaplotypesInPopulation ) : haplotypes ); for( final VariantContext call : genotypingEngine.assignGenotypeLikelihoods( UG_engine, @@ -558,7 +558,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem private void finalizeActiveRegion( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion ) { if( DEBUG ) { System.out.println("\nAssembling " + activeRegion.getLocation() + " with " + activeRegion.size() + " reads: (with overlap region = " + activeRegion.getExtendedLoc() + ")"); } - final ArrayList finalizedReadList = new ArrayList(); + final List finalizedReadList = new ArrayList(); final FragmentCollection fragmentCollection = FragmentUtils.create( activeRegion.getReads() ); activeRegion.clearReads(); @@ -569,7 +569,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } // Loop through the reads hard clipping the adaptor and low quality tails - final ArrayList readsToUse = new ArrayList(finalizedReadList.size()); + final List readsToUse = new ArrayList(finalizedReadList.size()); for( final GATKSAMRecord myRead : finalizedReadList ) { final GATKSAMRecord postAdapterRead = ( myRead.getReadUnmappedFlag() ? myRead : ReadClipper.hardClipAdaptorSequence( myRead ) ); if( postAdapterRead != null && !postAdapterRead.isEmpty() && postAdapterRead.getCigar().getReadLength() > 0 ) { @@ -583,7 +583,7 @@ public class HaplotypeCaller extends ActiveRegionWalker implem } private List filterNonPassingReads( final org.broadinstitute.sting.utils.activeregion.ActiveRegion activeRegion ) { - final ArrayList readsToRemove = new ArrayList(); + final List readsToRemove = new ArrayList(); for( final GATKSAMRecord rec : activeRegion.getReads() ) { if( rec.getReadLength() < 24 || rec.getMappingQuality() < 20 || BadMateFilter.hasBadMate(rec) || (keepRG != null && !rec.getReadGroup().getId().equals(keepRG)) ) { readsToRemove.add(rec); @@ -599,10 +599,10 @@ public class HaplotypeCaller extends ActiveRegionWalker implem return getToolkit().getGenomeLocParser().createGenomeLoc(activeRegion.getReadSpanLoc().getContig(), padLeft, padRight); } - private HashMap> splitReadsBySample( final List reads ) { - final HashMap> returnMap = new HashMap>(); + private Map> splitReadsBySample( final List reads ) { + final Map> returnMap = new HashMap>(); for( final String sample : samplesList) { - ArrayList readList = returnMap.get( sample ); + List readList = returnMap.get( sample ); if( readList == null ) { readList = new ArrayList(); returnMap.put(sample, readList); diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java index 57e071189..655b3e529 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LikelihoodCalculationEngine.java @@ -91,11 +91,11 @@ public class LikelihoodCalculationEngine { DEBUG = debug; } - public Map computeReadLikelihoods( final ArrayList haplotypes, final HashMap> perSampleReadList ) { + public Map computeReadLikelihoods( final List haplotypes, final Map> perSampleReadList ) { final Map stratifiedReadMap = new HashMap(); int X_METRIC_LENGTH = 0; - for( final Map.Entry> sample : perSampleReadList.entrySet() ) { + for( final Map.Entry> sample : perSampleReadList.entrySet() ) { for( final GATKSAMRecord read : sample.getValue() ) { final int readLength = read.getReadLength(); if( readLength > X_METRIC_LENGTH ) { X_METRIC_LENGTH = readLength; } @@ -115,7 +115,7 @@ public class LikelihoodCalculationEngine { pairHMM.initialize(X_METRIC_LENGTH, Y_METRIC_LENGTH); // for each sample's reads - for( final Map.Entry> sampleEntry : perSampleReadList.entrySet() ) { + for( final Map.Entry> sampleEntry : perSampleReadList.entrySet() ) { //if( DEBUG ) { System.out.println("Evaluating sample " + sample + " with " + perSampleReadList.get( sample ).size() + " passing reads"); } // evaluate the likelihood of the reads given those haplotypes stratifiedReadMap.put(sampleEntry.getKey(), computeReadLikelihoods(haplotypes, sampleEntry.getValue())); @@ -123,7 +123,7 @@ public class LikelihoodCalculationEngine { return stratifiedReadMap; } - private PerReadAlleleLikelihoodMap computeReadLikelihoods( final ArrayList haplotypes, final ArrayList reads) { + private PerReadAlleleLikelihoodMap computeReadLikelihoods( final List haplotypes, final List reads) { // first, a little set up to get copies of the Haplotypes that are Alleles (more efficient than creating them each time) final int numHaplotypes = haplotypes.size(); final Map alleleVersions = new HashMap(numHaplotypes); @@ -235,72 +235,13 @@ public class LikelihoodCalculationEngine { return likelihoodMatrix; } - /* @Requires({"haplotypes.size() > 0"}) @Ensures({"result.size() <= haplotypes.size()"}) - public ArrayList selectBestHaplotypes( final ArrayList haplotypes ) { - - // BUGBUG: This function needs a lot of work. Need to use 4-gamete test or Tajima's D to decide to break up events into separate pieces for genotyping - - final int numHaplotypes = haplotypes.size(); - final Set sampleKeySet = haplotypes.get(0).getSampleKeySet(); // BUGBUG: assume all haplotypes saw the same samples - final ArrayList bestHaplotypesIndexList = new ArrayList(); - bestHaplotypesIndexList.add(0); // always start with the reference haplotype - final double[][][] haplotypeLikelihoodMatrix = new double[sampleKeySet.size()][numHaplotypes][numHaplotypes]; - - int sampleCount = 0; - for( final String sample : sampleKeySet ) { - haplotypeLikelihoodMatrix[sampleCount++] = computeDiploidHaplotypeLikelihoods( haplotypes, sample ); - } - - int hap1 = 0; - int hap2 = 0; - int chosenSample = 0; - //double bestElement = Double.NEGATIVE_INFINITY; - final int maxChosenHaplotypes = Math.min( 15, sampleKeySet.size() * 2 + 1 ); - while( bestHaplotypesIndexList.size() < maxChosenHaplotypes ) { - double maxElement = Double.NEGATIVE_INFINITY; - for( int kkk = 0; kkk < sampleCount; kkk++ ) { - for( int iii = 0; iii < numHaplotypes; iii++ ) { - for( int jjj = 0; jjj <= iii; jjj++ ) { - if( haplotypeLikelihoodMatrix[kkk][iii][jjj] > maxElement ) { - maxElement = haplotypeLikelihoodMatrix[kkk][iii][jjj]; - hap1 = iii; - hap2 = jjj; - chosenSample = kkk; - } - } - } - } - if( maxElement == Double.NEGATIVE_INFINITY ) { break; } - - if( !bestHaplotypesIndexList.contains(hap1) ) { bestHaplotypesIndexList.add(hap1); } - if( !bestHaplotypesIndexList.contains(hap2) ) { bestHaplotypesIndexList.add(hap2); } - - for( int iii = 0; iii < numHaplotypes; iii++ ) { - for( int jjj = 0; jjj <= iii; jjj++ ) { - haplotypeLikelihoodMatrix[chosenSample][iii][jjj] = Double.NEGATIVE_INFINITY; - } - } - } - - if( DEBUG ) { System.out.println("Chose " + (bestHaplotypesIndexList.size() - 1) + " alternate haplotypes to genotype in all samples."); } - - final ArrayList bestHaplotypes = new ArrayList(); - for( final int hIndex : bestHaplotypesIndexList ) { - bestHaplotypes.add( haplotypes.get(hIndex) ); - } - return bestHaplotypes; - } - */ - - @Requires({"haplotypes.size() > 0"}) - @Ensures({"result.size() <= haplotypes.size()"}) - public ArrayList selectBestHaplotypes( final ArrayList haplotypes, final Map stratifiedReadMap, final int maxNumHaplotypesInPopulation ) { + public List selectBestHaplotypes( final List haplotypes, final Map stratifiedReadMap, final int maxNumHaplotypesInPopulation ) { final int numHaplotypes = haplotypes.size(); final Set sampleKeySet = stratifiedReadMap.keySet(); - final ArrayList bestHaplotypesIndexList = new ArrayList(); + final List bestHaplotypesIndexList = new ArrayList(); bestHaplotypesIndexList.add( findReferenceIndex(haplotypes) ); // always start with the reference haplotype final List haplotypesAsAlleles = new ArrayList(); for( final Haplotype h : haplotypes ) { haplotypesAsAlleles.add(Allele.create(h.getBases())); } @@ -332,7 +273,7 @@ public class LikelihoodCalculationEngine { if( DEBUG ) { System.out.println("Chose " + (bestHaplotypesIndexList.size() - 1) + " alternate haplotypes to genotype in all samples."); } - final ArrayList bestHaplotypes = new ArrayList(); + final List bestHaplotypes = new ArrayList(); for( final int hIndex : bestHaplotypesIndexList ) { bestHaplotypes.add( haplotypes.get(hIndex) ); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LocalAssemblyEngine.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LocalAssemblyEngine.java index b0e340dc2..3efa342b1 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LocalAssemblyEngine.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/LocalAssemblyEngine.java @@ -51,7 +51,7 @@ import org.broadinstitute.sting.utils.Haplotype; import org.broadinstitute.sting.utils.activeregion.ActiveRegion; import org.broadinstitute.variant.variantcontext.VariantContext; -import java.util.ArrayList; +import java.util.List; /** * Created by IntelliJ IDEA. @@ -67,5 +67,5 @@ public abstract class LocalAssemblyEngine { protected LocalAssemblyEngine() { } - public abstract ArrayList runLocalAssembly(ActiveRegion activeRegion, Haplotype refHaplotype, byte[] fullReferenceWithPadding, GenomeLoc refLoc, int PRUNE_FACTOR, ArrayList activeAllelesToGenotype); + public abstract List runLocalAssembly(ActiveRegion activeRegion, Haplotype refHaplotype, byte[] fullReferenceWithPadding, GenomeLoc refLoc, int PRUNE_FACTOR, List activeAllelesToGenotype); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java index e16994fa4..a9768557d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java @@ -84,7 +84,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { private final boolean DEBUG; private final PrintStream GRAPH_WRITER; - private final ArrayList> graphs = new ArrayList>(); + private final List> graphs = new ArrayList>(); private final int MIN_KMER; private int PRUNE_FACTOR = 2; @@ -96,7 +96,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { MIN_KMER = minKmer; } - public ArrayList runLocalAssembly( final ActiveRegion activeRegion, final Haplotype refHaplotype, final byte[] fullReferenceWithPadding, final GenomeLoc refLoc, final int PRUNE_FACTOR, final ArrayList activeAllelesToGenotype ) { + public List runLocalAssembly( final ActiveRegion activeRegion, final Haplotype refHaplotype, final byte[] fullReferenceWithPadding, final GenomeLoc refLoc, final int PRUNE_FACTOR, final List activeAllelesToGenotype ) { this.PRUNE_FACTOR = PRUNE_FACTOR; // create the graphs @@ -168,7 +168,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { } protected static void pruneGraph( final DefaultDirectedGraph graph, final int pruneFactor ) { - final ArrayList edgesToRemove = new ArrayList(); + final List edgesToRemove = new ArrayList(); for( final DeBruijnEdge e : graph.edgeSet() ) { if( e.getMultiplicity() <= pruneFactor && !e.getIsRef() ) { // remove non-reference edges with weight less than or equal to the pruning factor edgesToRemove.add(e); @@ -177,7 +177,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { graph.removeAllEdges(edgesToRemove); // Run through the graph and clean up singular orphaned nodes - final ArrayList verticesToRemove = new ArrayList(); + final List verticesToRemove = new ArrayList(); for( final DeBruijnVertex v : graph.vertexSet() ) { if( graph.inDegreeOf(v) == 0 && graph.outDegreeOf(v) == 0 ) { verticesToRemove.add(v); @@ -187,7 +187,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { } protected static void eliminateNonRefPaths( final DefaultDirectedGraph graph ) { - final ArrayList verticesToRemove = new ArrayList(); + final List verticesToRemove = new ArrayList(); boolean done = false; while( !done ) { done = true; @@ -313,8 +313,8 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { } @Ensures({"result.contains(refHaplotype)"}) - private ArrayList findBestPaths( final Haplotype refHaplotype, final byte[] fullReferenceWithPadding, final GenomeLoc refLoc, final ArrayList activeAllelesToGenotype, final GenomeLoc activeRegionWindow ) { - final ArrayList returnHaplotypes = new ArrayList(); + private List findBestPaths( final Haplotype refHaplotype, final byte[] fullReferenceWithPadding, final GenomeLoc refLoc, final List activeAllelesToGenotype, final GenomeLoc activeRegionWindow ) { + final List returnHaplotypes = new ArrayList(); // add the reference haplotype separately from all the others final SWPairwiseAlignment swConsensus = new SWPairwiseAlignment( fullReferenceWithPadding, refHaplotype.getBases(), SW_MATCH, SW_MISMATCH, SW_GAP, SW_GAP_EXTEND ); @@ -343,7 +343,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { // for GGA mode, add the desired allele into the haplotype if it isn't already present if( !activeAllelesToGenotype.isEmpty() ) { - final HashMap eventMap = GenotypingEngine.generateVCsFromAlignment( h, h.getAlignmentStartHapwrtRef(), h.getCigar(), fullReferenceWithPadding, h.getBases(), refLoc, "HCassembly" ); // BUGBUG: need to put this function in a shared place + final Map eventMap = GenotypingEngine.generateVCsFromAlignment( h, h.getAlignmentStartHapwrtRef(), h.getCigar(), fullReferenceWithPadding, h.getBases(), refLoc, "HCassembly" ); // BUGBUG: need to put this function in a shared place for( final VariantContext compVC : activeAllelesToGenotype ) { // for GGA mode, add the desired allele into the haplotype if it isn't already present final VariantContext vcOnHaplotype = eventMap.get(compVC.getStart()); @@ -378,7 +378,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { return returnHaplotypes; } - private boolean addHaplotype( final Haplotype haplotype, final byte[] ref, final ArrayList haplotypeList, final int activeRegionStart, final int activeRegionStop, final boolean FORCE_INCLUSION_FOR_GGA_MODE ) { + private boolean addHaplotype( final Haplotype haplotype, final byte[] ref, final List haplotypeList, final int activeRegionStart, final int activeRegionStop, final boolean FORCE_INCLUSION_FOR_GGA_MODE ) { if( haplotype == null ) { return false; } final SWPairwiseAlignment swConsensus = new SWPairwiseAlignment( ref, haplotype.getBases(), SW_MATCH, SW_MISMATCH, SW_GAP, SW_GAP_EXTEND ); diff --git a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java index baab1f5fa..6e8a412c3 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Haplotype.java +++ b/public/java/src/org/broadinstitute/sting/utils/Haplotype.java @@ -40,7 +40,7 @@ import java.util.*; public class Haplotype extends Allele { private GenomeLoc genomeLocation = null; - private HashMap eventMap = null; + private Map eventMap = null; private Cigar cigar; private int alignmentStartHapwrtRef; public int leftBreakPoint = 0; @@ -81,11 +81,11 @@ public class Haplotype extends Allele { return Arrays.hashCode(getBases()); } - public HashMap getEventMap() { + public Map getEventMap() { return eventMap; } - public void setEventMap( final HashMap eventMap ) { + public void setEventMap( final Map eventMap ) { this.eventMap = eventMap; } diff --git a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java index 13add5e7d..dd6735d89 100644 --- a/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java +++ b/public/java/src/org/broadinstitute/sting/utils/activeregion/ActiveRegion.java @@ -67,7 +67,7 @@ public class ActiveRegion implements HasGenomeLocation { * The reads included in this active region. May be empty upon creation, and expand / contract * as reads are added or removed from this region. */ - private final ArrayList reads = new ArrayList(); + private final List reads = new ArrayList(); /** * An ordered list (by genomic coordinate) of the ActivityProfileStates that went @@ -355,7 +355,7 @@ public class ActiveRegion implements HasGenomeLocation { * read coordinates. */ public void hardClipToActiveRegion() { - final ArrayList clippedReads = ReadClipper.hardClipToRegion( reads, extendedLoc.getStart(), extendedLoc.getStop() ); + final List clippedReads = ReadClipper.hardClipToRegion( reads, extendedLoc.getStart(), extendedLoc.getStop() ); ReadUtils.sortReadsByCoordinate(clippedReads); clearReads(); addAll(clippedReads); diff --git a/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java b/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java index 87526545d..45dd55af7 100644 --- a/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java +++ b/public/java/src/org/broadinstitute/sting/utils/clipping/ReadClipper.java @@ -362,8 +362,8 @@ public class ReadClipper { return GATKSAMRecord.emptyRead(read); } - public static ArrayList hardClipToRegion( final ArrayList reads, final int refStart, final int refStop ) { - final ArrayList returnList = new ArrayList( reads.size() ); + public static List hardClipToRegion( final List reads, final int refStart, final int refStop ) { + final List returnList = new ArrayList( reads.size() ); for( final GATKSAMRecord read : reads ) { final GATKSAMRecord clippedRead = hardClipToRegion( read, refStart, refStop ); if( !clippedRead.isEmpty() ) { From 404ee9a6e40c28792d2039e8d4dcd1435c785070 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 09:08:26 -0500 Subject: [PATCH 154/188] More aggressive checking of AWS key quality upon startup in the GATK --- .../sting/gatk/GenomeAnalysisEngine.java | 4 ++ .../sting/gatk/phonehome/GATKRunReport.java | 25 ++++++++++ .../broadinstitute/sting/utils/BaseUtils.java | 46 +++++++++---------- .../gatk/phonehome/GATKRunReportUnitTest.java | 4 +- .../sting/utils/BaseUtilsUnitTest.java | 46 +++++++++---------- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index 389b1371a..de5a96237 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/public/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -47,6 +47,7 @@ import org.broadinstitute.sting.gatk.io.OutputTracker; import org.broadinstitute.sting.gatk.io.stubs.Stub; import org.broadinstitute.sting.gatk.iterators.ReadTransformer; import org.broadinstitute.sting.gatk.iterators.ReadTransformersMode; +import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.gatk.refdata.tracks.RMDTrackBuilder; import org.broadinstitute.sting.gatk.refdata.utils.RMDTriplet; import org.broadinstitute.sting.gatk.resourcemanagement.ThreadAllocation; @@ -222,6 +223,9 @@ public class GenomeAnalysisEngine { * @return the value of this traversal. */ public Object execute() { + // first thing is to make sure the AWS keys can be decrypted + GATKRunReport.checkAWSAreValid(); + //HeapSizeMonitor monitor = new HeapSizeMonitor(); //monitor.start(); setStartTime(new java.util.Date()); diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index 839ebcfa1..8ef24d373 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -73,6 +73,9 @@ import java.util.zip.GZIPOutputStream; * GATK run report database. */ public class GATKRunReport { + protected final static String AWS_ACCESS_KEY_MD5 = "c0f0afa1ff5ba41d9bf216cfcdbf26bf"; + protected final static String AWS_SECRET_KEY_MD5 = "db2f13b3a7c98ad24e28783733ec4a62"; + /** * The root file system directory where we keep common report data */ @@ -358,6 +361,28 @@ public class GATKRunReport { return getAWSKey("GATK_AWS_secret.key"); } + /** + * Check that the AWS keys can be decrypted and are what we expect them to be + * + * @throws ReviewedStingException if anything goes wrong + */ + public static void checkAWSAreValid() { + try { + final String accessKeyMD5 = Utils.calcMD5(getAWSAccessKey()); + final String secretKeyMD5 = Utils.calcMD5(getAWSSecretKey()); + + if ( ! AWS_ACCESS_KEY_MD5.equals(accessKeyMD5) ) { + throw new ReviewedStingException("Invalid AWS access key found, expected MD5 " + AWS_ACCESS_KEY_MD5 + " but got " + accessKeyMD5); + } + if ( ! AWS_SECRET_KEY_MD5.equals(secretKeyMD5) ) { + throw new ReviewedStingException("Invalid AWS secret key found, expected MD5 " + AWS_SECRET_KEY_MD5 + " but got " + secretKeyMD5); + } + + } catch ( Exception e ) { + throw new ReviewedStingException("Couldn't decrypt AWS keys, something is wrong with the GATK distribution"); + } + } + private class S3PutRunnable implements Runnable { public AtomicBoolean isSuccess; diff --git a/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java index e6e1db813..61a558c09 100644 --- a/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java @@ -1,27 +1,27 @@ /* -* 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. -*/ + * 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.utils; diff --git a/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java index 03f19968c..be2065b17 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java @@ -36,12 +36,12 @@ import java.security.NoSuchAlgorithmException; public class GATKRunReportUnitTest extends BaseTest { @Test public void testAccessKey() throws Exception { - testAWSKey(GATKRunReport.getAWSAccessKey(), "c0f0afa1ff5ba41d9bf216cfcdbf26bf"); + testAWSKey(GATKRunReport.getAWSAccessKey(), GATKRunReport.AWS_ACCESS_KEY_MD5); } @Test public void testSecretKey() throws Exception { - testAWSKey(GATKRunReport.getAWSSecretKey(), "db2f13b3a7c98ad24e28783733ec4a62"); + testAWSKey(GATKRunReport.getAWSSecretKey(), GATKRunReport.AWS_SECRET_KEY_MD5); } private void testAWSKey(final String accessKey, final String expectedMD5) throws Exception { diff --git a/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java index cb80dbc09..6f645b34d 100644 --- a/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/BaseUtilsUnitTest.java @@ -1,27 +1,27 @@ /* -* 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. -*/ + * 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.utils; From 75ceddf9e5edff5d281aae31ed484a6194a0f02a Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Thu, 31 Jan 2013 09:46:38 -0500 Subject: [PATCH 155/188] Adding new unit tests for RR. These tests took a frustratingly long time to get to pass, but now we have a framework for testing the adding of reads into the SlidingWindow plus consensus creation. Will flesh these out more after I take care of some other items on my plate. --- .../reducereads/CompressionStash.java | 8 +- .../reducereads/SlidingWindow.java | 7 +- .../reducereads/SlidingWindowUnitTest.java | 251 +++++++++++------- 3 files changed, 170 insertions(+), 96 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java index e0e49cba3..bd7bdfe89 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/CompressionStash.java @@ -74,7 +74,7 @@ public class CompressionStash extends TreeSet { * @return true if the loc, or it's merged version, wasn't present in the list before. */ @Override - public boolean add(FinishedGenomeLoc insertLoc) { + public boolean add(final FinishedGenomeLoc insertLoc) { TreeSet removedLocs = new TreeSet(); for (FinishedGenomeLoc existingLoc : this) { if (existingLoc.isPast(insertLoc)) { @@ -87,10 +87,10 @@ public class CompressionStash extends TreeSet { removedLocs.add(existingLoc); // list the original loc for merging } } - for (GenomeLoc loc : removedLocs) { - this.remove(loc); // remove all locs that will be merged - } + + this.removeAll(removedLocs); // remove all locs that will be merged removedLocs.add(insertLoc); // add the new loc to the list of locs that will be merged + return super.add(new FinishedGenomeLoc(GenomeLoc.merge(removedLocs), insertLoc.isFinished())); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java index e2f8b6682..985fbba57 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindow.java @@ -141,7 +141,10 @@ public class SlidingWindow { protected SlidingWindow(final String contig, final int contigIndex, final int startLocation) { this.contig = contig; this.contigIndex = contigIndex; + + contextSize = 10; nContigs = 1; + this.windowHeader = new LinkedList(); windowHeader.addFirst(new HeaderElement(startLocation)); this.readsInWindow = new TreeSet(); @@ -293,7 +296,7 @@ public class SlidingWindow { } - private final class MarkedSites { + protected final class MarkedSites { private boolean[] siteIsVariant = new boolean[0]; private int startLocation = 0; @@ -302,6 +305,8 @@ public class SlidingWindow { public boolean[] getVariantSiteBitSet() { return siteIsVariant; } + protected int getStartLocation() { return startLocation; } + /** * Updates the variant site bitset given the new startlocation and size of the region to mark. * diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java index d9b55963d..91dfb94a9 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java @@ -46,23 +46,48 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; +import net.sf.picard.reference.IndexedFastaSequenceFile; +import net.sf.samtools.SAMFileHeader; import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.GenomeLoc; +import org.broadinstitute.sting.utils.UnvalidatingGenomeLoc; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.sting.utils.fasta.CachingIndexedFastaSequenceFile; +import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils; +import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; +import org.broadinstitute.sting.utils.sam.GATKSAMRecord; import org.testng.Assert; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.io.File; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; public class SlidingWindowUnitTest extends BaseTest { + private static final int variantRegionLength = 1000; + private static final int globalStartPosition = 1000000; + + private static boolean[] createBitset(final List locs) { + final boolean[] variantRegionBitset = new boolean[variantRegionLength]; + for ( FinishedGenomeLoc loc : locs ) { + final int stop = loc.getStop() - globalStartPosition; + for ( int i = loc.getStart() - globalStartPosition; i <= stop; i++ ) + variantRegionBitset[i] = true; + } + return variantRegionBitset; + } + ////////////////////////////////////////////////////////////////////////////////////// //// This section tests the findVariantRegions() method and related functionality //// ////////////////////////////////////////////////////////////////////////////////////// - private static final int variantRegionLength = 1000; - private static final int globalStartPosition = 1000000; private static final FinishedGenomeLoc loc90to95 = new FinishedGenomeLoc("1", 0, 1000090, 1000095, false); private static final FinishedGenomeLoc loc96to99 = new FinishedGenomeLoc("1", 0, 1000096, 1000099, false); private static final FinishedGenomeLoc loc100to110 = new FinishedGenomeLoc("1", 0, 1000100, 1000110, false); @@ -85,16 +110,6 @@ public class SlidingWindowUnitTest extends BaseTest { } } - private static boolean[] createBitset(final List locs) { - boolean[] variantRegionBitset = new boolean[variantRegionLength]; - for ( FinishedGenomeLoc loc : locs ) { - final int stop = loc.getStop() - globalStartPosition; - for ( int i = loc.getStart() - globalStartPosition; i <= stop; i++ ) - variantRegionBitset[i] = true; - } - return variantRegionBitset; - } - @DataProvider(name = "findVariantRegions") public Object[][] createFindVariantRegionsData() { List tests = new ArrayList(); @@ -127,115 +142,169 @@ public class SlidingWindowUnitTest extends BaseTest { } + ///////////////////////////////////////////////////////////////////////////// + //// This section tests the markSites() method and related functionality //// + ///////////////////////////////////////////////////////////////////////////// + @Test(enabled = true) + public void testMarkedSitesClass() { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); + final SlidingWindow.MarkedSites markedSites = slidingWindow.new MarkedSites(); + markedSites.updateRegion(100, 100); + Assert.assertEquals(markedSites.getStartLocation(), 100); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 100); + markedSites.updateRegion(300, 100); + Assert.assertEquals(markedSites.getStartLocation(), 300); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 100); + markedSites.getVariantSiteBitSet()[10] = true; + markedSites.updateRegion(290, 100); + Assert.assertEquals(markedSites.getStartLocation(), 290); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 100); + Assert.assertFalse(markedSites.getVariantSiteBitSet()[10]); + markedSites.getVariantSiteBitSet()[20] = true; + markedSites.updateRegion(290, 100); + Assert.assertEquals(markedSites.getStartLocation(), 290); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 100); + Assert.assertTrue(markedSites.getVariantSiteBitSet()[20]); + markedSites.updateRegion(300, 100); + Assert.assertEquals(markedSites.getStartLocation(), 300); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 100); + markedSites.getVariantSiteBitSet()[95] = true; + markedSites.updateRegion(390, 20); + Assert.assertEquals(markedSites.getStartLocation(), 390); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 20); + Assert.assertTrue(markedSites.getVariantSiteBitSet()[5]); + markedSites.updateRegion(340, 60); + Assert.assertEquals(markedSites.getStartLocation(), 340); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 60); + markedSites.getVariantSiteBitSet()[20] = true; + markedSites.updateRegion(350, 60); + Assert.assertEquals(markedSites.getStartLocation(), 350); + Assert.assertEquals(markedSites.getVariantSiteBitSet().length, 60); + Assert.assertTrue(markedSites.getVariantSiteBitSet()[10]); + } + @Test(enabled = true) + public void testMarkVariantRegion() { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, globalStartPosition); + SlidingWindow.MarkedSites markedSites = slidingWindow.new MarkedSites(); + markedSites.updateRegion(100, 100); - /* + slidingWindow.markVariantRegion(markedSites, 40); + Assert.assertEquals(countTrueBits(markedSites.getVariantSiteBitSet()), 21); - private static class DownsamplingReadsIteratorTest extends TestDataProvider { - private DownsamplingReadsIterator downsamplingIter; - private int targetCoverage; - private ArtificialSingleSampleReadStream stream; - private ArtificialSingleSampleReadStreamAnalyzer streamAnalyzer; + slidingWindow.markVariantRegion(markedSites, 5); + Assert.assertEquals(countTrueBits(markedSites.getVariantSiteBitSet()), 37); - public DownsamplingReadsIteratorTest( ArtificialSingleSampleReadStream stream, int targetCoverage ) { - super(DownsamplingReadsIteratorTest.class); + slidingWindow.markVariantRegion(markedSites, 95); + Assert.assertEquals(countTrueBits(markedSites.getVariantSiteBitSet()), 52); + } - this.stream = stream; - this.targetCoverage = targetCoverage; - - setName(String.format("%s: targetCoverage=%d numContigs=%d stacksPerContig=%d readsPerStack=%d-%d distanceBetweenStacks=%d-%d readLength=%d-%d unmappedReads=%d", - getClass().getSimpleName(), - targetCoverage, - stream.getNumContigs(), - stream.getNumStacksPerContig(), - stream.getMinReadsPerStack(), - stream.getMaxReadsPerStack(), - stream.getMinDistanceBetweenStacks(), - stream.getMaxDistanceBetweenStacks(), - stream.getMinReadLength(), - stream.getMaxReadLength(), - stream.getNumUnmappedReads())); + private static int countTrueBits(final boolean[] bitset) { + int count = 0; + for ( final boolean bit : bitset ) { + if ( bit ) + count++; } + return count; + } - public void run() { - streamAnalyzer = new PositionallyDownsampledArtificialSingleSampleReadStreamAnalyzer(stream, targetCoverage); - downsamplingIter = new DownsamplingReadsIterator(stream.getStingSAMIterator(), new SimplePositionalDownsampler(targetCoverage)); + ///////////////////////////////////////////////////////////////// + //// This section tests the consensus creation functionality //// + ///////////////////////////////////////////////////////////////// - streamAnalyzer.analyze(downsamplingIter); + private static final int readLength = 100; + private final List basicReads = new ArrayList(20); + private IndexedFastaSequenceFile seq; + private SAMFileHeader header; - // Check whether the observed properties of the downsampled stream are what they should be - streamAnalyzer.validate(); + @BeforeClass + public void setup() throws FileNotFoundException { + seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); + header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); - // Allow memory used by this test to be reclaimed - stream = null; - streamAnalyzer = null; - downsamplingIter = null; + final int testRegionSize = 1000; + final int readFrequency = 20; + + basicReads.clear(); + for ( int i = 0; i < testRegionSize; i += readFrequency ) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "basicRead" + i, 0, globalStartPosition + i, readLength); + read.setReadBases(Utils.dupBytes((byte) 'A', readLength)); + read.setBaseQualities(Utils.dupBytes((byte)30, readLength)); + read.setMappingQuality((byte)30); + basicReads.add(read); } } - @DataProvider(name = "DownsamplingReadsIteratorTestDataProvider") - public Object[][] createDownsamplingReadsIteratorTests() { - SAMFileHeader header = ArtificialSAMUtils.createArtificialSamHeader(5, 1, 10000); - String readGroupID = "testReadGroup"; - SAMReadGroupRecord readGroup = new SAMReadGroupRecord(readGroupID); - readGroup.setSample("testSample"); - header.addReadGroup(readGroup); + private class ConsensusCreationTest { + public final int expectedNumberOfReads; + public final List myReads = new ArrayList(20); - // Values that don't vary across tests - int targetCoverage = 10; - int minReadLength = 50; - int maxReadLength = 100; - int minDistanceBetweenStacks = 1; - int maxDistanceBetweenStacks = maxReadLength + 1; + private ConsensusCreationTest(final List locs, final boolean readsShouldBeLowQuality, final int expectedNumberOfReads) { + this.expectedNumberOfReads = expectedNumberOfReads; - GenomeAnalysisEngine.resetRandomGenerator(); + // first, add the basic reads to the collection + myReads.addAll(basicReads); - // brute force testing! - for ( int numContigs : Arrays.asList(1, 2, 5) ) { - for ( int stacksPerContig : Arrays.asList(1, 2, 10) ) { - for ( int minReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) { - for ( int maxReadsPerStack : Arrays.asList(1, targetCoverage / 2, targetCoverage, targetCoverage - 1, targetCoverage + 1, targetCoverage * 2) ) { - for ( int numUnmappedReads : Arrays.asList(0, 1, targetCoverage, targetCoverage * 2) ) { - // Only interested in sane read stream configurations here - if ( minReadsPerStack <= maxReadsPerStack ) { - new DownsamplingReadsIteratorTest(new ArtificialSingleSampleReadStream(header, - readGroupID, - numContigs, - stacksPerContig, - minReadsPerStack, - maxReadsPerStack, - minDistanceBetweenStacks, - maxDistanceBetweenStacks, - minReadLength, - maxReadLength, - numUnmappedReads), - targetCoverage); - } - } - } - } - } + // then add the permuted reads + for ( final GenomeLoc loc : locs ) + myReads.add(createVariantRead(loc, readsShouldBeLowQuality)); } - return DownsamplingReadsIteratorTest.getTests(DownsamplingReadsIteratorTest.class); + private GATKSAMRecord createVariantRead(final GenomeLoc loc, final boolean baseShouldBeLowQuality) { + + final int startPos = loc.getStart() - 50; + + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead" + startPos, 0, startPos, readLength); + final byte[] bases = Utils.dupBytes((byte) 'A', readLength); + // create a mismatch + bases[50] = 'C'; + read.setReadBases(bases); + final byte qual = baseShouldBeLowQuality ? (byte)10 : (byte)30; + read.setBaseQualities(Utils.dupBytes(qual, readLength)); + read.setMappingQuality((byte)30); + return read; + } } - @Test(dataProvider = "DownsamplingReadsIteratorTestDataProvider") - public void runDownsamplingReadsIteratorTest( DownsamplingReadsIteratorTest test ) { - logger.warn("Running test: " + test); + private static final GenomeLoc loc290 = new UnvalidatingGenomeLoc("1", 0, 1000290, 1000290); + private static final GenomeLoc loc295 = new UnvalidatingGenomeLoc("1", 0, 1000295, 1000295); + private static final GenomeLoc loc309 = new UnvalidatingGenomeLoc("1", 0, 1000309, 1000309); + private static final GenomeLoc loc310 = new UnvalidatingGenomeLoc("1", 0, 1000310, 1000310); - GenomeAnalysisEngine.resetRandomGenerator(); - test.run(); + @DataProvider(name = "ConsensusCreation") + public Object[][] createConsensusCreationTestData() { + List tests = new ArrayList(); + + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(), false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290), false, 9)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc295), false, 10)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc309), false, 10)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc310), false, 11)}); + + return tests.toArray(new Object[][]{}); } - */ + @Test(dataProvider = "ConsensusCreation", enabled = true) + public void testConsensusCreationTest(ConsensusCreationTest test) { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, 10, header, new GATKSAMReadGroupRecord("test"), 0, 0.05, 0.05, 20, 20, 100, ReduceReads.DownsampleStrategy.Normal, false, 1, false); + for ( final GATKSAMRecord read : test.myReads ) + slidingWindow.addRead(read); + final Pair, CompressionStash> result = slidingWindow.close(); + + Assert.assertEquals(result.getFirst().size(), test.expectedNumberOfReads); + } + + + + + } From ca6968d038b5ca8ed449fbc49b75f0e8c726834e Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Thu, 31 Jan 2013 10:12:18 -0500 Subject: [PATCH 156/188] Use base List and Map types in the GenotypingEngineUnitTest. --- .../GenotypingEngineUnitTest.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngineUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngineUnitTest.java index f82c0a8ba..8b09e91ae 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngineUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/GenotypingEngineUnitTest.java @@ -93,7 +93,7 @@ public class GenotypingEngineUnitTest extends BaseTest { haplotypeAlleles.add( Allele.create("AACA", false) ); haplotypeAlleles.add( Allele.create("CATA", false) ); haplotypeAlleles.add( Allele.create("CACA", false) ); - final ArrayList haplotypes = new ArrayList(); + final List haplotypes = new ArrayList(); haplotypes.add(new Haplotype("AATA".getBytes())); haplotypes.add(new Haplotype("AACA".getBytes())); haplotypes.add(new Haplotype("CATA".getBytes())); @@ -101,11 +101,11 @@ public class GenotypingEngineUnitTest extends BaseTest { final List haplotypeAllelesForSample = new ArrayList(); haplotypeAllelesForSample.add( Allele.create("CATA", false) ); haplotypeAllelesForSample.add( Allele.create("CACA", false) ); - final ArrayList> alleleMapper = new ArrayList>(); - ArrayList Aallele = new ArrayList(); + final List> alleleMapper = new ArrayList>(); + List Aallele = new ArrayList(); Aallele.add(haplotypes.get(0)); Aallele.add(haplotypes.get(1)); - ArrayList Callele = new ArrayList(); + List Callele = new ArrayList(); Callele.add(haplotypes.get(2)); Callele.add(haplotypes.get(3)); alleleMapper.add(Aallele); @@ -135,7 +135,7 @@ public class GenotypingEngineUnitTest extends BaseTest { haplotypeAlleles.add( Allele.create("TACA", false) ); haplotypeAlleles.add( Allele.create("TTCA", false) ); haplotypeAlleles.add( Allele.create("TTTA", false) ); - final ArrayList haplotypes = new ArrayList(); + final List haplotypes = new ArrayList(); haplotypes.add(new Haplotype("AATA".getBytes())); haplotypes.add(new Haplotype("AACA".getBytes())); haplotypes.add(new Haplotype("CATA".getBytes())); @@ -146,14 +146,14 @@ public class GenotypingEngineUnitTest extends BaseTest { final List haplotypeAllelesForSample = new ArrayList(); haplotypeAllelesForSample.add( Allele.create("TTTA", false) ); haplotypeAllelesForSample.add( Allele.create("AATA", true) ); - final ArrayList> alleleMapper = new ArrayList>(); - ArrayList Aallele = new ArrayList(); + final List> alleleMapper = new ArrayList>(); + List Aallele = new ArrayList(); Aallele.add(haplotypes.get(0)); Aallele.add(haplotypes.get(1)); - ArrayList Callele = new ArrayList(); + List Callele = new ArrayList(); Callele.add(haplotypes.get(2)); Callele.add(haplotypes.get(3)); - ArrayList Tallele = new ArrayList(); + List Tallele = new ArrayList(); Tallele.add(haplotypes.get(4)); Tallele.add(haplotypes.get(5)); Tallele.add(haplotypes.get(6)); @@ -187,16 +187,16 @@ public class GenotypingEngineUnitTest extends BaseTest { private class BasicGenotypingTestProvider extends TestDataProvider { byte[] ref; byte[] hap; - HashMap expected; + Map expected; - public BasicGenotypingTestProvider(String refString, String hapString, HashMap expected) { + public BasicGenotypingTestProvider(String refString, String hapString, Map expected) { super(BasicGenotypingTestProvider.class, String.format("Haplotype to VCF test: ref = %s, alignment = %s", refString,hapString)); ref = refString.getBytes(); hap = hapString.getBytes(); this.expected = expected; } - public HashMap calcAlignment() { + public Map calcAlignment() { final SWPairwiseAlignment alignment = new SWPairwiseAlignment(ref, hap); return GenotypingEngine.generateVCsFromAlignment( new Haplotype(hap), alignment.getAlignmentStart2wrt1(), alignment.getCigar(), ref, hap, genomeLocParser.createGenomeLoc("4",1,1+ref.length), "name"); } @@ -206,14 +206,14 @@ public class GenotypingEngineUnitTest extends BaseTest { public Object[][] makeBasicGenotypingTests() { for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(1 + contextSize, (byte)'M'); final String context = Utils.dupString('G', contextSize); new BasicGenotypingTestProvider(context + "AGCTCGCATCGCGAGCATCGACTAGCCGATAG" + context, "CGCTCGCATCGCGAGCATCGACTAGCCGATAG", map); } for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(2 + contextSize, (byte)'M'); map.put(21 + contextSize, (byte)'M'); final String context = Utils.dupString('G', contextSize); @@ -221,7 +221,7 @@ public class GenotypingEngineUnitTest extends BaseTest { } for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(1 + contextSize, (byte)'M'); map.put(20 + contextSize, (byte)'I'); final String context = Utils.dupString('G', contextSize); @@ -229,7 +229,7 @@ public class GenotypingEngineUnitTest extends BaseTest { } for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(1 + contextSize, (byte)'M'); map.put(20 + contextSize, (byte)'D'); final String context = Utils.dupString('G', contextSize); @@ -237,7 +237,7 @@ public class GenotypingEngineUnitTest extends BaseTest { } for( int contextSize : new int[]{1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(1, (byte)'M'); map.put(20, (byte)'D'); final String context = Utils.dupString('G', contextSize); @@ -245,7 +245,7 @@ public class GenotypingEngineUnitTest extends BaseTest { } for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(2 + contextSize, (byte)'M'); map.put(20 + contextSize, (byte)'I'); map.put(30 + contextSize, (byte)'D'); @@ -254,7 +254,7 @@ public class GenotypingEngineUnitTest extends BaseTest { } for( int contextSize : new int[]{0,1,5,9,24,36} ) { - HashMap map = new HashMap(); + Map map = new HashMap(); map.put(1 + contextSize, (byte)'M'); map.put(20 + contextSize, (byte)'D'); map.put(28 + contextSize, (byte)'M'); @@ -267,8 +267,8 @@ public class GenotypingEngineUnitTest extends BaseTest { @Test(dataProvider = "BasicGenotypingTestProvider", enabled = true) public void testHaplotypeToVCF(BasicGenotypingTestProvider cfg) { - HashMap calculatedMap = cfg.calcAlignment(); - HashMap expectedMap = cfg.expected; + Map calculatedMap = cfg.calcAlignment(); + Map expectedMap = cfg.expected; logger.warn(String.format("Test: %s", cfg.toString())); if(!compareVCMaps(calculatedMap, expectedMap)) { logger.warn("calc map = " + calculatedMap); @@ -420,9 +420,9 @@ public class GenotypingEngineUnitTest extends BaseTest { } /** - * Private function to compare HashMap of VCs, it only checks the types and start locations of the VariantContext + * Private function to compare Map of VCs, it only checks the types and start locations of the VariantContext */ - private boolean compareVCMaps(HashMap calc, HashMap expected) { + private boolean compareVCMaps(Map calc, Map expected) { if( !calc.keySet().equals(expected.keySet()) ) { return false; } // sanity check for( Integer loc : expected.keySet() ) { Byte type = expected.get(loc); From 9c0207f8ef07816c772d1b10837ef95b22d260f7 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Thu, 31 Jan 2013 11:03:17 -0500 Subject: [PATCH 157/188] Fixing BQSR/BAQ bug: If a read had an existing BAQ tag, was clipped by our engine, and couldn't have the BAQ recalculated (for whatever reason), then we would fail in the BQSR because we would default to using the old tag (which no longer matched the length of the read bases). The right thing to do here is to remove the old BAQ tag when RECALCULATE and ADD_TAG are the BAQ modes used but BAQ cannot be recalculated. Added a unit test to ensure that the tags are removed in such a case. --- .../org/broadinstitute/sting/utils/baq/BAQ.java | 7 ++++++- .../sting/utils/baq/BAQUnitTest.java | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java index 8c7bce6ac..73e129105 100644 --- a/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java +++ b/public/java/src/org/broadinstitute/sting/utils/baq/BAQ.java @@ -673,7 +673,9 @@ public class BAQ { } else if ( excludeReadFromBAQ(read) ) { ; // just fall through } else { - if ( calculationType == CalculationMode.RECALCULATE || ! hasBAQTag(read) ) { + final boolean readHasBAQTag = hasBAQTag(read); + + if ( calculationType == CalculationMode.RECALCULATE || ! readHasBAQTag ) { if ( DEBUG ) System.out.printf(" Calculating BAQ on the fly%n"); BAQCalculationResult hmmResult = calcBAQFromHMM(read, refReader); if ( hmmResult != null ) { @@ -683,6 +685,9 @@ public class BAQ { case DONT_MODIFY: BAQQuals = hmmResult.bq; break; default: throw new ReviewedStingException("BUG: unexpected qmode " + qmode); } + } else if ( readHasBAQTag ) { + // remove the BAQ tag if it's there because we cannot trust it + read.setAttribute(BAQ_TAG, null); } } else if ( qmode == QualityMode.OVERWRITE_QUALS ) { // only makes sense if we are overwriting quals if ( DEBUG ) System.out.printf(" Taking BAQ from tag%n"); diff --git a/public/java/test/org/broadinstitute/sting/utils/baq/BAQUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/baq/BAQUnitTest.java index 1e3386426..da82e9de5 100644 --- a/public/java/test/org/broadinstitute/sting/utils/baq/BAQUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/baq/BAQUnitTest.java @@ -203,6 +203,23 @@ public class BAQUnitTest extends BaseTest { Assert.assertTrue(baq.calcEpsilon( ref, alt, (byte)i) >= 0.0, "Failed to get baq epsilon range"); } + @Test(enabled = true) + public void testBAQOverwritesExistingTagWithNull() { + + // create a read with a single base off the end of the contig, which cannot be BAQed + final SAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "foo", 0, fasta.getSequenceDictionary().getSequence("chr1").getSequenceLength() + 1, 1); + read.setReadBases(new byte[] {(byte) 'A'}); + read.setBaseQualities(new byte[] {(byte) 20}); + read.setCigarString("1M"); + read.setAttribute("BQ", "A"); + + // try to BAQ and tell it to RECALCULATE AND ADD_TAG + BAQ baq = new BAQ(1e-3, 0.1, 7, (byte)4, false); + baq.baqRead(read, fasta, BAQ.CalculationMode.RECALCULATE, BAQ.QualityMode.ADD_TAG); + + // did we remove the existing tag? + Assert.assertTrue(read.getAttribute("BQ") == null); + } public void testBAQ(BAQTest test, boolean lookupWithFasta) { BAQ baqHMM = new BAQ(1e-3, 0.1, 7, (byte)4, false); // matches current samtools parameters From ac033ce41abe748714f85dbda63fc7468e649fc3 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Thu, 31 Jan 2013 11:32:19 -0500 Subject: [PATCH 158/188] Intermediate commit of new bubble assembly graph traversal algorithm for the HaplotypeCaller. Adding functionality for a path from an assembly graph to calculate its own cigar string from each of the bubbles instead of doing a massive Smith-Waterman alignment between the path's full base composition and the reference. --- .../walkers/haplotypecaller/DeBruijnEdge.java | 2 +- .../walkers/haplotypecaller/KBestPaths.java | 448 ++++++++++++++++-- .../SimpleDeBruijnAssembler.java | 14 +- .../sting/utils/recalibration/RecalDatum.java | 2 +- .../sting/utils/sam/AlignmentUtils.java | 25 + .../utils/sam/AlignmentUtilsUnitTest.java | 44 +- 6 files changed, 496 insertions(+), 39 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java index 74a95db37..881fe4204 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java @@ -86,7 +86,7 @@ public class DeBruijnEdge { multiplicity = value; } - public boolean getIsRef() { + public boolean isRef() { return isRef; } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java index 7d79edf93..edfe8254d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java @@ -46,8 +46,14 @@ package org.broadinstitute.sting.gatk.walkers.haplotypecaller; +import com.google.java.contract.Ensures; +import net.sf.samtools.Cigar; +import net.sf.samtools.CigarElement; +import net.sf.samtools.CigarOperator; import org.apache.commons.lang.ArrayUtils; +import org.broadinstitute.sting.utils.SWPairwiseAlignment; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.sam.AlignmentUtils; import org.jgrapht.graph.DefaultDirectedGraph; import java.io.Serializable; @@ -55,7 +61,7 @@ import java.util.*; /** * Created by IntelliJ IDEA. - * User: ebanks + * User: ebanks, rpoplin * Date: Mar 23, 2011 */ // Class for finding the K best paths (as determined by the sum of multiplicities of the edges) in a graph. @@ -72,28 +78,47 @@ public class KBestPaths { protected static class Path { // the last vertex seen in the path - private DeBruijnVertex lastVertex; + private final DeBruijnVertex lastVertex; // the list of edges comprising the path - private ArrayList edges; + private final List edges; // the scores for the path - private int totalScore = 0, lowestEdge = -1; + private final int totalScore; + private final int lowestEdge; - public Path( final DeBruijnVertex initialVertex ) { + // the graph from which this path originated + private final DefaultDirectedGraph graph; + + // used in the bubble state machine to apply Smith-Waterman to the bubble sequence + private final double SW_MATCH = 15.0; + private final double SW_MISMATCH = -15.0; + private final double SW_GAP = -25.0; + private final double SW_GAP_EXTEND = -1.2; + + public Path( final DeBruijnVertex initialVertex, final DefaultDirectedGraph graph ) { lastVertex = initialVertex; edges = new ArrayList(0); + totalScore = 0; + lowestEdge = -1; + this.graph = graph; } - public Path( final Path p, final DefaultDirectedGraph graph, final DeBruijnEdge edge ) { - lastVertex = graph.getEdgeTarget(edge); + public Path( final Path p, final DeBruijnEdge edge ) { + graph = p.graph; + lastVertex = p.graph.getEdgeTarget(edge); edges = new ArrayList(p.edges); edges.add(edge); totalScore = p.totalScore + edge.getMultiplicity(); lowestEdge = ( p.lowestEdge == -1 ) ? edge.getMultiplicity() : Math.min(p.lowestEdge, edge.getMultiplicity()); } - public boolean containsEdge( final DefaultDirectedGraph graph, final DeBruijnEdge edge ) { + /** + * Does this path contain the given edge + * @param edge the given edge to test + * @return true if the edge is found in this path + */ + public boolean containsEdge( final DeBruijnEdge edge ) { final DeBruijnVertex targetVertex = graph.getEdgeTarget(edge); for( final DeBruijnEdge e : edges ) { if( e.equals(graph, edge) || graph.getEdgeTarget(e).equals(targetVertex) ) { @@ -104,7 +129,7 @@ public class KBestPaths { return false; } - public ArrayList getEdges() { return edges; } + public List getEdges() { return edges; } public int getScore() { return totalScore; } @@ -112,7 +137,12 @@ public class KBestPaths { public DeBruijnVertex getLastVertexInPath() { return lastVertex; } - public byte[] getBases( final DefaultDirectedGraph graph ) { + /** + * The base sequence for this path. Pull the full sequence for the source of the path and then the suffix for all subsequent nodes + * @return non-null sequence of bases corresponding to this path + */ + @Ensures({"result != null"}) + public byte[] getBases() { if( edges.size() == 0 ) { return lastVertex.getSequence(); } byte[] bases = graph.getEdgeSource( edges.get(0) ).getSequence(); @@ -121,6 +151,142 @@ public class KBestPaths { } return bases; } + + /** + * Calculate the cigar string for this path using a bubble traversal of the assembly graph and running a Smith-Waterman alignment on each bubble + */ + @Ensures("result != null") + public Cigar calculateCigar() { + + final Cigar cigar = new Cigar(); + // special case for paths that start on reference but not at the reference source node + if( edges.get(0).isRef() && !isRefSource(graph, edges.get(0)) ) { + for( final CigarElement ce : calculateCigarForCompleteBubble(graph, null, null, graph.getEdgeSource(edges.get(0))).getCigarElements() ) { + cigar.add(ce); + } + } + + // reset the bubble state machine + final BubbleStateMachine bsm = new BubbleStateMachine(cigar); + + for( final DeBruijnEdge e : edges ) { + if( e.equals(graph, edges.get(0)) ) { + advanceBubbleStateMachine( bsm, graph, graph.getEdgeSource(e), null ); + } + advanceBubbleStateMachine( bsm, graph, graph.getEdgeTarget(e), e ); + } + + // special case for paths that don't end on reference + if( bsm.inBubble ) { + for( final CigarElement ce : calculateCigarForCompleteBubble(graph, bsm.bubbleBytes, bsm.lastSeenReferenceNode, null).getCigarElements() ) { + bsm.cigar.add(ce); + } + } else if( edges.get(edges.size()-1).isRef() && !isRefSink(graph, edges.get(edges.size()-1)) ) { // special case for paths that end of the reference but haven't completed the entire reference circuit + for( final CigarElement ce : calculateCigarForCompleteBubble(graph, bsm.bubbleBytes, graph.getEdgeTarget(edges.get(edges.size()-1)), null).getCigarElements() ) { + bsm.cigar.add(ce); + } + } + + return AlignmentUtils.consolidateCigar(bsm.cigar); + } + + private void advanceBubbleStateMachine( final BubbleStateMachine bsm, final DefaultDirectedGraph graph, final DeBruijnVertex node, final DeBruijnEdge e ) { + if( isReferenceNode( graph, node ) ) { + if( !bsm.inBubble ) { // just add the ref bases as M's in the Cigar string, and don't do anything else + if( e !=null && !e.isRef() ) { + if( referencePathExists( graph, graph.getEdgeSource(e), node) ) { + for( final CigarElement ce : calculateCigarForCompleteBubble(graph, null, graph.getEdgeSource(e), node).getCigarElements() ) { + bsm.cigar.add(ce); + } + bsm.cigar.add( new CigarElement( getAdditionalSequence(graph, node).length, CigarOperator.M) ); + } else if ( graph.getEdgeSource(e).equals(graph.getEdgeTarget(e)) ) { // alt edge at ref node points to itself + bsm.cigar.add( new CigarElement( getAdditionalSequence(graph, node).length, CigarOperator.I) ); + } else { + bsm.inBubble = true; + bsm.bubbleBytes = null; + bsm.lastSeenReferenceNode = graph.getEdgeSource(e); + bsm.bubbleBytes = ArrayUtils.addAll( bsm.bubbleBytes, getAdditionalSequence(graph, node) ); + } + } else { + bsm.cigar.add( new CigarElement( getAdditionalSequence(graph, node).length, CigarOperator.M) ); + } + } else if( bsm.lastSeenReferenceNode != null && !referencePathExists( graph, bsm.lastSeenReferenceNode, node ) ) { // add bases to the bubble string until we get back to the reference path + bsm.bubbleBytes = ArrayUtils.addAll( bsm.bubbleBytes, getAdditionalSequence(graph, node) ); + } else { // close the bubble and use a local SW to determine the Cigar string + for( final CigarElement ce : calculateCigarForCompleteBubble(graph, bsm.bubbleBytes, bsm.lastSeenReferenceNode, node).getCigarElements() ) { + bsm.cigar.add(ce); + } + bsm.inBubble = false; + bsm.bubbleBytes = null; + bsm.lastSeenReferenceNode = null; + bsm.cigar.add( new CigarElement( getAdditionalSequence(graph, node).length, CigarOperator.M) ); + } + } else { // non-ref vertex + if( bsm.inBubble ) { // just keep accumulating until we get back to the reference path + bsm.bubbleBytes = ArrayUtils.addAll( bsm.bubbleBytes, getAdditionalSequence(graph, node) ); + } else { // open up a bubble + bsm.inBubble = true; + bsm.bubbleBytes = null; + bsm.lastSeenReferenceNode = (e != null ? graph.getEdgeSource(e) : null ); + bsm.bubbleBytes = ArrayUtils.addAll( bsm.bubbleBytes, getAdditionalSequence(graph, node) ); + } + } + } + + private Cigar calculateCigarForCompleteBubble( final DefaultDirectedGraph graph, final byte[] bubbleBytes, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex ) { + final byte[] refBytes = getReferenceBytes(graph, fromVertex, toVertex); + final Cigar cigar = new Cigar(); + + // add padding to anchor ref/alt bases in the SW matrix + byte[] padding = "XXXXXX".getBytes(); + boolean goodAlignment = false; + SWPairwiseAlignment swConsensus = null; + while( !goodAlignment && padding.length < 1000 ) { + padding = ArrayUtils.addAll(padding, padding); // double the size of the padding each time + final byte[] reference = ArrayUtils.addAll( ArrayUtils.addAll(padding, refBytes), padding ); + final byte[] alternate = ArrayUtils.addAll( ArrayUtils.addAll(padding, bubbleBytes), padding ); + swConsensus = new SWPairwiseAlignment( reference, alternate, SW_MATCH, SW_MISMATCH, SW_GAP, SW_GAP_EXTEND ); + if( swConsensus.getAlignmentStart2wrt1() == 0 && !swConsensus.getCigar().toString().contains("S") && swConsensus.getCigar().getReferenceLength() == reference.length ) { + goodAlignment = true; + } + } + if( !goodAlignment && swConsensus != null ) { + throw new ReviewedStingException("SmithWaterman offset failure: " + (refBytes == null ? "-" : new String(refBytes)) + " against " + new String(bubbleBytes) + " = " + swConsensus.getCigar()); + } + + if( swConsensus != null ) { + final Cigar swCigar = swConsensus.getCigar(); + for( int iii = 0; iii < swCigar.numCigarElements(); iii++ ) { + // now we need to remove the padding from the cigar string + int length = swCigar.getCigarElement(iii).getLength(); + if( iii == 0 ) { length -= padding.length; } + if( iii == swCigar.numCigarElements() - 1 ) { length -= padding.length; } + if( length > 0 ) { + cigar.add( new CigarElement(length, swCigar.getCigarElement(iii).getOperator()) ); + } + } + if( (refBytes == null && cigar.getReferenceLength() != 0) || ( refBytes != null && cigar.getReferenceLength() != refBytes.length ) ) { + throw new ReviewedStingException("SmithWaterman cigar failure: " + (refBytes == null ? "-" : new String(refBytes)) + " against " + new String(bubbleBytes) + " = " + swConsensus.getCigar()); + } + } + + return cigar; + } + + // class to keep track of the bubble state machine + protected static class BubbleStateMachine { + public boolean inBubble = false; + public byte[] bubbleBytes = null; + public DeBruijnVertex lastSeenReferenceNode = null; + public Cigar cigar = null; + + public BubbleStateMachine( final Cigar initialCigar ) { + inBubble = false; + bubbleBytes = null; + lastSeenReferenceNode = null; + cigar = initialCigar; + } + } } protected static class PathComparatorTotalScore implements Comparator, Serializable { @@ -130,12 +296,12 @@ public class KBestPaths { } } - //protected static class PathComparatorLowestEdge implements Comparator, Serializable { - // @Override - // public int compare(final Path path1, final Path path2) { - // return path2.lowestEdge - path1.lowestEdge; - // } - //} + protected static class PathComparatorLowestEdge implements Comparator, Serializable { + @Override + public int compare(final Path path1, final Path path2) { + return path2.lowestEdge - path1.lowestEdge; + } + } public static List getKBestPaths( final DefaultDirectedGraph graph, final int k ) { if( k > MAX_PATHS_TO_HOLD/2 ) { throw new ReviewedStingException("Asked for more paths than MAX_PATHS_TO_HOLD!"); } @@ -144,7 +310,7 @@ public class KBestPaths { // run a DFS for best paths for( final DeBruijnVertex v : graph.vertexSet() ) { if( graph.inDegreeOf(v) == 0 ) { - findBestPaths(graph, new Path(v), bestPaths); + findBestPaths(new Path(v, graph), bestPaths); } } @@ -153,14 +319,14 @@ public class KBestPaths { return bestPaths.subList(0, Math.min(k, bestPaths.size())); } - private static void findBestPaths( final DefaultDirectedGraph graph, final Path path, final List bestPaths ) { - findBestPaths(graph, path, bestPaths, new MyInt()); + private static void findBestPaths( final Path path, final List bestPaths ) { + findBestPaths(path, bestPaths, new MyInt()); } - private static void findBestPaths( final DefaultDirectedGraph graph, final Path path, final List bestPaths, MyInt n ) { + private static void findBestPaths( final Path path, final List bestPaths, final MyInt n ) { // did we hit the end of a path? - if ( allOutgoingEdgesHaveBeenVisited(graph, path) ) { + if ( allOutgoingEdgesHaveBeenVisited(path) ) { if ( bestPaths.size() >= MAX_PATHS_TO_HOLD ) { // clean out some low scoring paths Collections.sort(bestPaths, new PathComparatorTotalScore() ); @@ -172,27 +338,253 @@ public class KBestPaths { } else { // recursively run DFS final ArrayList edgeArrayList = new ArrayList(); - edgeArrayList.addAll(graph.outgoingEdgesOf(path.lastVertex)); + edgeArrayList.addAll(path.graph.outgoingEdgesOf(path.lastVertex)); Collections.sort(edgeArrayList, new DeBruijnEdge.EdgeWeightComparator()); Collections.reverse(edgeArrayList); for ( final DeBruijnEdge edge : edgeArrayList ) { // make sure the edge is not already in the path - if ( path.containsEdge(graph, edge) ) + if ( path.containsEdge(edge) ) continue; - final Path newPath = new Path(path, graph, edge); + final Path newPath = new Path(path, edge); n.val++; - findBestPaths(graph, newPath, bestPaths, n); + findBestPaths(newPath, bestPaths, n); } } } - private static boolean allOutgoingEdgesHaveBeenVisited( final DefaultDirectedGraph graph, final Path path ) { - for( final DeBruijnEdge edge : graph.outgoingEdgesOf(path.lastVertex) ) { - if( !path.containsEdge(graph, edge) ) { + private static boolean allOutgoingEdgesHaveBeenVisited( final Path path ) { + for( final DeBruijnEdge edge : path.graph.outgoingEdgesOf(path.lastVertex) ) { + if( !path.containsEdge(edge) ) { return false; } } return true; } + + /**************************************************************** + * Collection of graph functions used by KBestPaths * + ***************************************************************/ + + /** + * Test if the vertex is on a reference path in the graph. If so it is referred to as a reference node + * @param graph the graph from which the vertex originated + * @param v the vertex to test + * @return true if the vertex is on the reference path + */ + public static boolean isReferenceNode( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + for( final DeBruijnEdge e : graph.edgesOf(v) ) { + if( e.isRef() ) { return true; } + } + return false; + } + + /** + * Is this edge a source edge (the source vertex of the edge is a source node in the graph) + * @param graph the graph from which the edge originated + * @param e the edge to test + * @return true if the source vertex of the edge is a source node in the graph + */ + public static boolean isSource( final DefaultDirectedGraph graph, final DeBruijnEdge e ) { + return graph.inDegreeOf(graph.getEdgeSource(e)) == 0; + } + + /** + * Is this vertex a source vertex + * @param graph the graph from which the vertex originated + * @param v the vertex to test + * @return true if the vertex is a source vertex + */ + public static boolean isSource( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + return graph.inDegreeOf(v) == 0; + } + + /** + * Pull the added base sequence implied by visiting this node in a path + * @param graph the graph from which the vertex originated + * @param v the vertex whose sequence to grab + * @return non-null sequence of bases corresponding to this node in the graph + */ + @Ensures({"result != null"}) + public static byte[] getAdditionalSequence( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + return ( isSource(graph, v) ? v.getSequence() : v.getSuffix() ); + } + + /** + * Is this edge both a reference edge and a source edge for the reference path + * @param graph the graph from which the edge originated + * @param e the edge to test + * @return true if the edge is both a reference edge and a reference path source edge + */ + public static boolean isRefSource( final DefaultDirectedGraph graph, final DeBruijnEdge e ) { + for( final DeBruijnEdge edgeToTest : graph.incomingEdgesOf(graph.getEdgeSource(e)) ) { + if( edgeToTest.isRef() ) { return false; } + } + return true; + } + + /** + * Is this vertex both a reference node and a source node for the reference path + * @param graph the graph from which the vertex originated + * @param v the vertex to test + * @return true if the vertex is both a reference node and a reference path source node + */ + public static boolean isRefSource( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + for( final DeBruijnEdge edgeToTest : graph.incomingEdgesOf(v) ) { + if( edgeToTest.isRef() ) { return false; } + } + return true; + } + + /** + * Is this edge both a reference edge and a sink edge for the reference path + * @param graph the graph from which the edge originated + * @param e the edge to test + * @return true if the edge is both a reference edge and a reference path sink edge + */ + public static boolean isRefSink( final DefaultDirectedGraph graph, final DeBruijnEdge e ) { + for( final DeBruijnEdge edgeToTest : graph.outgoingEdgesOf(graph.getEdgeTarget(e)) ) { + if( edgeToTest.isRef() ) { return false; } + } + return true; + } + + /** + * Is this vertex both a reference node and a sink node for the reference path + * @param graph the graph from which the node originated + * @param v the node to test + * @return true if the vertex is both a reference node and a reference path sink node + */ + public static boolean isRefSink( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + for( final DeBruijnEdge edgeToTest : graph.outgoingEdgesOf(v) ) { + if( edgeToTest.isRef() ) { return false; } + } + return true; + } + + public static DeBruijnEdge getReferenceSourceEdge( final DefaultDirectedGraph graph ) { + for( final DeBruijnEdge e : graph.edgeSet() ) { + if( e.isRef() && isRefSource(graph, e) ) { + return e; + } + } + throw new ReviewedStingException("All reference graphs should have a source node"); + } + + public static DeBruijnVertex getReferenceSourceVertex( final DefaultDirectedGraph graph ) { + for( final DeBruijnVertex v : graph.vertexSet() ) { + if( isReferenceNode(graph, v) && isRefSource(graph, v) ) { + return v; + } + } + return null; + } + + public static DeBruijnEdge getReferenceSinkEdge( final DefaultDirectedGraph graph ) { + for( final DeBruijnEdge e : graph.edgeSet() ) { + if( e.isRef() && isRefSink(graph, e) ) { + return e; + } + } + throw new ReviewedStingException("All reference graphs should have a sink node"); + } + + public static DeBruijnVertex getReferenceSinkVertex( final DefaultDirectedGraph graph ) { + for( final DeBruijnVertex v : graph.vertexSet() ) { + if( isReferenceNode(graph, v) && isRefSink(graph, v) ) { + return v; + } + } + throw new ReviewedStingException("All reference graphs should have a sink node"); + } + + public static DeBruijnEdge getNextReferenceEdge( final DefaultDirectedGraph graph, final DeBruijnEdge e ) { + if( e == null ) { return null; } + for( final DeBruijnEdge edgeToTest : graph.outgoingEdgesOf(graph.getEdgeTarget(e)) ) { + if( edgeToTest.isRef() ) { + return edgeToTest; + } + } + return null; + } + + public static DeBruijnVertex getNextReferenceVertex( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + if( v == null ) { return null; } + for( final DeBruijnEdge edgeToTest : graph.outgoingEdgesOf(v) ) { + if( edgeToTest.isRef() ) { + return graph.getEdgeTarget(edgeToTest); + } + } + return null; + } + + public static DeBruijnEdge getPrevReferenceEdge( final DefaultDirectedGraph graph, final DeBruijnEdge e ) { + for( final DeBruijnEdge edgeToTest : graph.incomingEdgesOf(graph.getEdgeSource(e)) ) { + if( edgeToTest.isRef() ) { + return edgeToTest; + } + } + return null; + } + + public static DeBruijnVertex getPrevReferenceVertex( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + for( final DeBruijnEdge edgeToTest : graph.incomingEdgesOf(v) ) { + if( isReferenceNode(graph, graph.getEdgeSource(edgeToTest)) ) { + return graph.getEdgeSource(edgeToTest); + } + } + return null; + } + + public static boolean referencePathExists(final DefaultDirectedGraph graph, final DeBruijnEdge fromEdge, final DeBruijnEdge toEdge) { + DeBruijnEdge e = fromEdge; + if( e == null ) { + return false; + } + while( !e.equals(graph, toEdge) ) { + e = getNextReferenceEdge(graph, e); + if( e == null ) { + return false; + } + } + return true; + } + + public static boolean referencePathExists(final DefaultDirectedGraph graph, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex) { + DeBruijnVertex v = fromVertex; + if( v == null ) { + return false; + } + v = getNextReferenceVertex(graph, v); + if( v == null ) { + return false; + } + while( !v.equals(toVertex) ) { + v = getNextReferenceVertex(graph, v); + if( v == null ) { + return false; + } + } + return true; + } + + // fromVertex (exclusive) -> toVertex (exclusive) + public static byte[] getReferenceBytes( final DefaultDirectedGraph graph, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex ) { + byte[] bytes = null; + if( fromVertex != null && toVertex != null && !referencePathExists(graph, fromVertex, toVertex) ) { + throw new ReviewedStingException("Asked for a reference path which doesn't exist. " + fromVertex + " --> " + toVertex); + } + DeBruijnVertex v = fromVertex; + if( v == null ) { + v = getReferenceSourceVertex(graph); + bytes = ArrayUtils.addAll( bytes, getAdditionalSequence(graph, v) ); + } + v = getNextReferenceVertex(graph, v); + while( (toVertex != null && !v.equals(toVertex)) || (toVertex == null && v != null) ) { + bytes = ArrayUtils.addAll( bytes, getAdditionalSequence(graph, v) ); + // advance along the reference path + v = getNextReferenceVertex(graph, v); + } + return bytes; + } } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java index a9768557d..a007bfa0c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssembler.java @@ -152,10 +152,10 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { final DeBruijnVertex addedVertex = new DeBruijnVertex( ArrayUtils.addAll(incomingVertex.getSequence(), outgoingVertex.getSuffix()), outgoingVertex.kmer ); graph.addVertex(addedVertex); for( final DeBruijnEdge edge : outEdges ) { - graph.addEdge(addedVertex, graph.getEdgeTarget(edge), new DeBruijnEdge(edge.getIsRef(), edge.getMultiplicity())); + graph.addEdge(addedVertex, graph.getEdgeTarget(edge), new DeBruijnEdge(edge.isRef(), edge.getMultiplicity())); } for( final DeBruijnEdge edge : inEdges ) { - graph.addEdge(graph.getEdgeSource(edge), addedVertex, new DeBruijnEdge(edge.getIsRef(), edge.getMultiplicity())); + graph.addEdge(graph.getEdgeSource(edge), addedVertex, new DeBruijnEdge(edge.isRef(), edge.getMultiplicity())); } graph.removeVertex( incomingVertex ); @@ -170,7 +170,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { protected static void pruneGraph( final DefaultDirectedGraph graph, final int pruneFactor ) { final List edgesToRemove = new ArrayList(); for( final DeBruijnEdge e : graph.edgeSet() ) { - if( e.getMultiplicity() <= pruneFactor && !e.getIsRef() ) { // remove non-reference edges with weight less than or equal to the pruning factor + if( e.getMultiplicity() <= pruneFactor && !e.isRef() ) { // remove non-reference edges with weight less than or equal to the pruning factor edgesToRemove.add(e); } } @@ -195,7 +195,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { if( graph.inDegreeOf(v) == 0 || graph.outDegreeOf(v) == 0 ) { boolean isRefNode = false; for( final DeBruijnEdge e : graph.edgesOf(v) ) { - if( e.getIsRef() ) { + if( e.isRef() ) { isRefNode = true; break; } @@ -299,10 +299,10 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { if( edge.getMultiplicity() > PRUNE_FACTOR ) { GRAPH_WRITER.println("\t" + graph.getEdgeSource(edge).toString() + " -> " + graph.getEdgeTarget(edge).toString() + " [" + (edge.getMultiplicity() <= PRUNE_FACTOR ? "style=dotted,color=grey" : "label=\""+ edge.getMultiplicity() +"\"") + "];"); } - if( edge.getIsRef() ) { + if( edge.isRef() ) { GRAPH_WRITER.println("\t" + graph.getEdgeSource(edge).toString() + " -> " + graph.getEdgeTarget(edge).toString() + " [color=red];"); } - if( !edge.getIsRef() && edge.getMultiplicity() <= PRUNE_FACTOR ) { System.out.println("Graph pruning warning!"); } + if( !edge.isRef() && edge.getMultiplicity() <= PRUNE_FACTOR ) { System.out.println("Graph pruning warning!"); } } for( final DeBruijnVertex v : graph.vertexSet() ) { final String label = ( graph.inDegreeOf(v) == 0 ? v.toString() : v.getSuffixString() ); @@ -338,7 +338,7 @@ public class SimpleDeBruijnAssembler extends LocalAssemblyEngine { for( final DefaultDirectedGraph graph : graphs ) { for ( final KBestPaths.Path path : KBestPaths.getKBestPaths(graph, NUM_BEST_PATHS_PER_KMER_GRAPH) ) { - final Haplotype h = new Haplotype( path.getBases( graph ) ); + final Haplotype h = new Haplotype( path.getBases() ); if( addHaplotype( h, fullReferenceWithPadding, returnHaplotypes, activeRegionStart, activeRegionStop, false ) ) { // for GGA mode, add the desired allele into the haplotype if it isn't already present diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java index bd0063a7d..be537f294 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatum.java @@ -201,7 +201,7 @@ public class RecalDatum { * Returns the error rate (in real space) of this interval, or 0 if there are no observations * @return the empirical error rate ~= N errors / N obs */ - @Ensures("result >= 0.0") + @Ensures({"result >= 0.0"}) public double getEmpiricalErrorRate() { if ( numObservations == 0 ) return 0.0; diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index 9c5f95472..59ea3d905 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -25,6 +25,8 @@ package org.broadinstitute.sting.utils.sam; +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; @@ -499,6 +501,29 @@ public class AlignmentUtils { return true; } + /** + * Need a well-formed, consolidated Cigar string so that the left aligning code works properly. + * For example, 1M1M1M1D2M1M --> 3M1D3M + * If the given cigar is empty then the returned cigar will also be empty + * @param c the cigar to consolidate + * @return a cigar with consecutive matching operators merged into single operators. + */ + @Requires({"c != null"}) + @Ensures({"result != null"}) + public static Cigar consolidateCigar( final Cigar c ) { + if( c.isEmpty() ) { return c; } + final Cigar returnCigar = new Cigar(); + int sumLength = 0; + for( int iii = 0; iii < c.numCigarElements(); iii++ ) { + sumLength += c.getCigarElement(iii).getLength(); + if( iii == c.numCigarElements() - 1 || !c.getCigarElement(iii).getOperator().equals(c.getCigarElement(iii+1).getOperator())) { // at the end so finish the current element + returnCigar.add(new CigarElement(sumLength, c.getCigarElement(iii).getOperator())); + sumLength = 0; + } + } + return returnCigar; + } + /** * Takes the alignment of the read sequence readSeq to the reference sequence refSeq * starting at 0-based position refIndex on the refSeq and specified by its cigar. diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java index f088574d7..b03399b7a 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java @@ -26,12 +26,14 @@ package org.broadinstitute.sting.utils.sam; import junit.framework.Assert; -import net.sf.samtools.SAMFileHeader; -import net.sf.samtools.SAMRecord; +import net.sf.samtools.*; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.util.ArrayList; +import java.util.List; + public class AlignmentUtilsUnitTest { private SAMFileHeader header; @@ -121,4 +123,42 @@ public class AlignmentUtilsUnitTest { start, ArtificialSAMUtils.DEFAULT_READ_LENGTH); } + + @Test + public void testConsolidateCigar() { + { + //1M1M1M1D2M1M --> 3M1D3M + List list = new ArrayList(); + list.add( new CigarElement(1, CigarOperator.M)); + list.add( new CigarElement(1, CigarOperator.M)); + list.add( new CigarElement(1, CigarOperator.M)); + list.add( new CigarElement(1, CigarOperator.D)); + list.add( new CigarElement(2, CigarOperator.M)); + list.add( new CigarElement(1, CigarOperator.M)); + Cigar unconsolidatedCigar = new Cigar(list); + + list.clear(); + list.add( new CigarElement(3, CigarOperator.M)); + list.add( new CigarElement(1, CigarOperator.D)); + list.add( new CigarElement(3, CigarOperator.M)); + Cigar consolidatedCigar = new Cigar(list); + + Assert.assertEquals(consolidatedCigar.toString(), AlignmentUtils.consolidateCigar(unconsolidatedCigar).toString()); + } + + { + //6M6M6M --> 18M + List list = new ArrayList(); + list.add( new CigarElement(6, CigarOperator.M)); + list.add( new CigarElement(6, CigarOperator.M)); + list.add( new CigarElement(6, CigarOperator.M)); + Cigar unconsolidatedCigar = new Cigar(list); + + list.clear(); + list.add( new CigarElement(18, CigarOperator.M)); + Cigar consolidatedCigar = new Cigar(list); + + Assert.assertEquals(consolidatedCigar.toString(), AlignmentUtils.consolidateCigar(unconsolidatedCigar).toString()); + } + } } From 6ec1e613a263ba1af19448f1873ed537e0515258 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Thu, 31 Jan 2013 11:40:40 -0500 Subject: [PATCH 159/188] Move AWS keys to a resources subdirectory within the phonehome package Resources must be in a subdirectory called "resources" in the package hierarchy to be picked up by the packaging system. Adding each resource manually to the jars in build.xml does not cause the resource to be added to the standalone GATK jar when we package the GATK, so it's best to always use this convention. --- build.xml | 3 --- .../sting/gatk/phonehome/GATKRunReport.java | 4 ++-- .../phonehome/{ => resources}/GATK_AWS_access.key | 0 .../phonehome/{ => resources}/GATK_AWS_secret.key | Bin 4 files changed, 2 insertions(+), 5 deletions(-) rename public/java/src/org/broadinstitute/sting/gatk/phonehome/{ => resources}/GATK_AWS_access.key (100%) rename public/java/src/org/broadinstitute/sting/gatk/phonehome/{ => resources}/GATK_AWS_secret.key (100%) diff --git a/build.xml b/build.xml index 1e88bb400..e92e41c10 100644 --- a/build.xml +++ b/build.xml @@ -708,9 +708,6 @@ - - - diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index 8ef24d373..12e87f613 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -350,7 +350,7 @@ public class GATKRunReport { * @return a non-null AWS access key for the GATK user */ protected static String getAWSAccessKey() { - return getAWSKey("GATK_AWS_access.key"); + return getAWSKey("resources/GATK_AWS_access.key"); } /** @@ -358,7 +358,7 @@ public class GATKRunReport { * @return a non-null AWS secret key for the GATK user */ protected static String getAWSSecretKey() { - return getAWSKey("GATK_AWS_secret.key"); + return getAWSKey("resources/GATK_AWS_secret.key"); } /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key b/public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_access.key similarity index 100% rename from public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_access.key rename to public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_access.key diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_secret.key b/public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_secret.key similarity index 100% rename from public/java/src/org/broadinstitute/sting/gatk/phonehome/GATK_AWS_secret.key rename to public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_secret.key From c3c4e2785b08822b59d80af40df4d2023b00f8ce Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 13:57:23 -0500 Subject: [PATCH 160/188] UnitTest for calcNumHighQualityBases in AlignmentUtils --- .../sting/utils/sam/AlignmentUtils.java | 32 +++++----- .../utils/sam/AlignmentUtilsUnitTest.java | 60 ++++++++++++++++++- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index 59ea3d905..d270f251d 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -261,16 +261,23 @@ public class AlignmentUtils { return n; } + /** + * Calculate the number of bases that are soft clipped in read with quality score greater than threshold + * + * @param read a non-null GATKSAMRecord + * @param qualThreshold consider bases with quals > this value as high quality. Must be >= 0 + * @return positive integer + */ + @Ensures("result >= 0") public static int calcNumHighQualitySoftClips( final GATKSAMRecord read, final byte qualThreshold ) { + if ( read == null ) throw new IllegalArgumentException("Read cannot be null"); + if ( qualThreshold < 0 ) throw new IllegalArgumentException("Expected qualThreshold to be a positive byte but saw " + qualThreshold); + + final byte[] qual = read.getBaseQualities( EventType.BASE_SUBSTITUTION ); int numHQSoftClips = 0; int alignPos = 0; - final Cigar cigar = read.getCigar(); - final byte[] qual = read.getBaseQualities( EventType.BASE_SUBSTITUTION ); - - for( int iii = 0; iii < cigar.numCigarElements(); iii++ ) { - - final CigarElement ce = cigar.getCigarElement(iii); + for ( final CigarElement ce : read.getCigar().getCigarElements() ) { final int elementLength = ce.getLength(); switch( ce.getOperator() ) { @@ -279,21 +286,16 @@ public class AlignmentUtils { if( qual[alignPos++] > qualThreshold ) { numHQSoftClips++; } } break; - case M: - case I: - case EQ: - case X: + case M: case I: case EQ: case X: alignPos += elementLength; break; - case H: - case P: - case D: - case N: + case H: case P: case D: case N: break; default: - throw new ReviewedStingException("Unsupported cigar operator: " + ce.getOperator()); + throw new IllegalStateException("Unsupported cigar operator: " + ce.getOperator()); } } + return numHQSoftClips; } diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java index b03399b7a..ea3e2bdbb 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java @@ -25,13 +25,16 @@ package org.broadinstitute.sting.utils.sam; -import junit.framework.Assert; import net.sf.samtools.*; +import org.apache.commons.lang.ArrayUtils; +import org.broadinstitute.sting.utils.Utils; +import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class AlignmentUtilsUnitTest { @@ -161,4 +164,59 @@ public class AlignmentUtilsUnitTest { Assert.assertEquals(consolidatedCigar.toString(), AlignmentUtils.consolidateCigar(unconsolidatedCigar).toString()); } } + + @DataProvider(name = "SoftClipsDataProvider") + public Object[][] makeSoftClipsDataProvider() { + List tests = new ArrayList(); + + // this functionality can be adapted to provide input data for whatever you might want in your data + for ( final int lengthOfLeftClip : Arrays.asList(0, 1, 10) ) { + for ( final int lengthOfRightClip : Arrays.asList(0, 1, 10) ) { + for ( final int qualThres : Arrays.asList(10, 20, 30) ) { + for ( final String middleOp : Arrays.asList("M", "D") ) { + for ( final int matchSize : Arrays.asList(0, 1, 10) ) { + final byte[] left = makeQualArray(lengthOfLeftClip, qualThres); + final byte[] right = makeQualArray(lengthOfRightClip, qualThres); + int n = 0; + for ( int i = 0; i < left.length; i++ ) n += left[i] > qualThres ? 1 : 0; + for ( int i = 0; i < right.length; i++ ) n += right[i] > qualThres ? 1 : 0; + tests.add(new Object[]{left, matchSize, middleOp, right, qualThres, n}); + } + } + } + } + } + + return tests.toArray(new Object[][]{}); + } + + private byte[] makeQualArray(final int length, final int qualThreshold) { + final byte[] array = new byte[length]; + for ( int i = 0; i < array.length; i++ ) + array[i] = (byte)(qualThreshold + ( i % 2 == 0 ? 1 : - 1 )); + return array; + } + + @Test(dataProvider = "SoftClipsDataProvider") + public void testSoftClipsData(final byte[] qualsOfSoftClipsOnLeft, final int middleSize, final String middleOp, final byte[] qualOfSoftClipsOnRight, final int qualThreshold, final int numExpected) { + final int readLength = (middleOp.equals("D") ? 0 : middleSize) + qualOfSoftClipsOnRight.length + qualsOfSoftClipsOnLeft.length; + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, readLength); + final byte[] bases = Utils.dupBytes((byte) 'A', readLength); + final byte[] matchBytes = middleOp.equals("D") ? new byte[]{} : Utils.dupBytes((byte)30, middleSize); + final byte[] quals = ArrayUtils.addAll(ArrayUtils.addAll(qualsOfSoftClipsOnLeft, matchBytes), qualOfSoftClipsOnRight); + + // set the read's bases and quals + read.setReadBases(bases); + read.setBaseQualities(quals); + + final StringBuilder cigar = new StringBuilder(); + if (qualsOfSoftClipsOnLeft.length > 0 ) cigar.append(qualsOfSoftClipsOnLeft.length + "S"); + if (middleSize > 0 ) cigar.append(middleSize + middleOp); + if (qualOfSoftClipsOnRight.length > 0 ) cigar.append(qualOfSoftClipsOnRight.length + "S"); + + read.setCigarString(cigar.toString()); + + final int actual = AlignmentUtils.calcNumHighQualitySoftClips(read, (byte) qualThreshold); + Assert.assertEquals(actual, numExpected, "Wrong number of soft clips detected for read " + read.getSAMString()); + } } From d82b855c4ced24dc0545f0e551ff60e7d9116b5e Mon Sep 17 00:00:00 2001 From: David Roazen Date: Thu, 31 Jan 2013 16:00:13 -0500 Subject: [PATCH 162/188] Rev picard, sam-jdk, and tribble This is a necessary prerequisite for the org.broadinstitute.variant migration. -Picard and sam-jdk go from version 1.67.1197 to 1.84.1337 -Picard-private goes from version 2375 to 2662 -Tribble goes from version 119 to 1.84.1337 -RADICALLY trimmed down the list of classes we extract from Picard-private (jar goes from 326993 bytes to 6445 bytes!) --- .../gatk/datasources/reads/BlockLoader.java | 2 +- .../gatk/datasources/reads/GATKBAMIndex.java | 4 ++-- .../variant/vcf/AbstractVCFCodec.java | 2 +- public/packages/PicardPrivate.xml | 17 ----------------- .../picard-private-parts-2375.jar | Bin 326993 -> 0 bytes .../picard-private-parts-2662.jar | Bin 0 -> 6445 bytes ...2375.xml => picard-private-parts-2662.xml} | 2 +- .../repository/net.sf/picard-1.67.1197.xml | 3 --- ...ard-1.67.1197.jar => picard-1.84.1337.jar} | Bin 1373399 -> 1525728 bytes .../repository/net.sf/picard-1.84.1337.xml | 3 +++ settings/repository/net.sf/sam-1.67.1197.xml | 3 --- .../{sam-1.67.1197.jar => sam-1.84.1337.jar} | Bin 573202 -> 615411 bytes settings/repository/net.sf/sam-1.84.1337.xml | 3 +++ ...{tribble-119.jar => tribble-1.84.1337.jar} | Bin 319935 -> 259515 bytes .../org.broad/tribble-1.84.1337.xml | 3 +++ settings/repository/org.broad/tribble-119.xml | 3 --- 16 files changed, 14 insertions(+), 31 deletions(-) delete mode 100644 settings/repository/edu.mit.broad/picard-private-parts-2375.jar create mode 100644 settings/repository/edu.mit.broad/picard-private-parts-2662.jar rename settings/repository/edu.mit.broad/{picard-private-parts-2375.xml => picard-private-parts-2662.xml} (58%) delete mode 100644 settings/repository/net.sf/picard-1.67.1197.xml rename settings/repository/net.sf/{picard-1.67.1197.jar => picard-1.84.1337.jar} (61%) create mode 100644 settings/repository/net.sf/picard-1.84.1337.xml delete mode 100644 settings/repository/net.sf/sam-1.67.1197.xml rename settings/repository/net.sf/{sam-1.67.1197.jar => sam-1.84.1337.jar} (67%) create mode 100644 settings/repository/net.sf/sam-1.84.1337.xml rename settings/repository/org.broad/{tribble-119.jar => tribble-1.84.1337.jar} (51%) create mode 100644 settings/repository/org.broad/tribble-1.84.1337.xml delete mode 100644 settings/repository/org.broad/tribble-119.xml diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java index 428b7355c..72b778ec9 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java @@ -25,7 +25,7 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import org.broad.tribble.util.BlockCompressedStreamConstants; +import net.sf.samtools.util.BlockCompressedStreamConstants; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.FileInputStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java index 9cf0a9493..1cfb527cd 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java @@ -25,8 +25,8 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import org.broad.tribble.util.SeekableBufferedStream; -import org.broad.tribble.util.SeekableFileStream; +import net.sf.samtools.seekablestream.SeekableBufferedStream; +import net.sf.samtools.seekablestream.SeekableFileStream; import net.sf.samtools.*; diff --git a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java index 11d152e65..a4ccd050a 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java +++ b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java @@ -30,7 +30,7 @@ import org.broad.tribble.Feature; import org.broad.tribble.NameAwareCodec; import org.broad.tribble.TribbleException; import org.broad.tribble.readers.LineReader; -import org.broad.tribble.util.BlockCompressedInputStream; +import net.sf.samtools.util.BlockCompressedInputStream; import org.broad.tribble.util.ParsingUtils; import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.variantcontext.*; diff --git a/public/packages/PicardPrivate.xml b/public/packages/PicardPrivate.xml index a800294d6..d898a5d07 100644 --- a/public/packages/PicardPrivate.xml +++ b/public/packages/PicardPrivate.xml @@ -2,26 +2,9 @@ - - - - - - - - - - - - - - - - - diff --git a/settings/repository/edu.mit.broad/picard-private-parts-2375.jar b/settings/repository/edu.mit.broad/picard-private-parts-2375.jar deleted file mode 100644 index bfa2f65ad9fd5539fa8fe4a4dcdbed2e42a87d5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326993 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 z 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%0Ai~p#U{}s@ulF!pR#9wA)xE8EOKFi=xo^qSM2r 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 I2Xye}&;S4c literal 0 HcmV?d00001 diff --git a/settings/repository/edu.mit.broad/picard-private-parts-2375.xml b/settings/repository/edu.mit.broad/picard-private-parts-2662.xml similarity index 58% rename from settings/repository/edu.mit.broad/picard-private-parts-2375.xml rename to settings/repository/edu.mit.broad/picard-private-parts-2662.xml index b467f934a..119255e8d 100644 --- a/settings/repository/edu.mit.broad/picard-private-parts-2375.xml +++ b/settings/repository/edu.mit.broad/picard-private-parts-2662.xml @@ -1,3 +1,3 @@ - + diff --git a/settings/repository/net.sf/picard-1.67.1197.xml b/settings/repository/net.sf/picard-1.67.1197.xml deleted file mode 100644 index 7d9042d6b..000000000 --- a/settings/repository/net.sf/picard-1.67.1197.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/settings/repository/net.sf/picard-1.67.1197.jar b/settings/repository/net.sf/picard-1.84.1337.jar similarity index 61% rename from settings/repository/net.sf/picard-1.67.1197.jar rename to settings/repository/net.sf/picard-1.84.1337.jar index 9243c02df6a34d312e1ae1673ee6e938b0113ac8..68db4184822193ef73c7859b80e9c17982343b4c 100644 GIT binary patch delta 323680 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

?ufn=-m3=s3h) zCL834IF8bWWE!Us)RVrt*mQ?h{(rq953}SdzFsMGpK^mC(O!eo(#Kyxdt*XO%h3u& z(PT4Sm>ac`u~Dsl+tsGUH4U&Ahtj6B2^G&juSPozw!mORqzE=WkL6n!%Y7}V{bhie zW1TIa5Crdy7S=sY(!WyYW(N7It*mBYWGpe*nHCLnNtO+^+`>wrMe5~fSPz^_Izcl# zP*nj9FIm-jk5dSO0uUwzi`fRv78V8kU|IaKw#4&YTnU$iCf`Q zMihOZb&3JpkJn2PHFvwR#e%-tr@W`w^p4gd-rA&1Izg93yfGuvHk%7mT`6zG;`H|) z^&TR2vhEepKj|*9?=h{b=+v(H+yN0o@4u~%k_xmuK^;Y+0Ms~hsOvjKfK;B!a5yqh z*5BF^@X4{2dm8g%xI+yU^Noiv2Ui|K9(e}-$Q3hi3-_c-8ZzZ;#XT)!XyuC&xmG7Qdb2k zt)>tvqlz30k-j*>IEiP0F`x?EfC&UT4-U-kMzx9?D7TwinG=(&3yzQc8m-nA7V#vD zg!V@i5=K}1R8Ne&IQ|O{=HFPXq~g}FJ~-KGACjv?5mr}@1r=F~;U)=}$z)0g%@16r z*s+$S{>WCAYA-{n?Y6<33rkNo>&hcoCFt}N9_?c@pu#Yldss7gy5&3$mU8jzQl7|G zg0CaE(2{EgTHOz7HY#R@Oh$?}#B3p~k%Uz`m`bvh1-zdZXVReU2vXb|F(;AbXxRBEpvR-3YD-hkXw>%v9~cRzpTEX{K7}zg%aI*azx&r(8Kk4u$9p0kD+jMw`4)4<8Js0~*#)yEHL|=Kd18-GWgWjPAuTRp~JuE@GTv_bMf!_56}{b=Z7fek1hZcepUDL zpIrQB{vW#fFFbx%te~r34F0PN;s%7MfG$B7I{&V+sNqE>KkS0L&m$&>Qo(+H3sIq+tG?j&>(qt&jF1AK#F}Z1i`{PM2Ws%bA1Z>+}%3?~0m_Tck zGficwsVp;+^IrgD*~ zTx=+pxZsSn3q88jR4y}>%U%2{#>u6Y$(v? z-lKG(15~>AC~)qvM_FYk!o{BD?>m*%3RJtFRo3F*Q`Q;EO)j{T#E^PPx!F)|LG9%D zQf_rA>y-^u#BJ0(RN!{>fHIkYatB@Yr^B5F-$rTfq65Oy-tC0P&U@%^FCFfq!~Ga- z$^!;3qb_;SP#$uz&ruP)@jYxPn+)X;&_BVFjQBJ|dF&5(GDF#X zoQj5@M>Lczev85GAudiz!wseVPq**Iu(5o)=sZ>%E#5n%_7-RC)e19bji_${qXlmP zb>1A>jvH4td}8s$>Y0_r6N}3y<#zLW#hSg^>1L$=h4^-_R@794BsQVp+GEMW zCT#Jx){A~GY1s?0xmP@~q+&$r%$}jkUZl_+d@fZOvY=z2qDL zyQ^n;dwJn@fpVHS$~#YPPI+qbTaR`FrRxc7MUuk_nSk6dz${@&{TX;jd%E+Q(Y=A>OB=9#iH-P%rnY(+_z6}! z&C+!PDzdm{uK$yI0Hxf{v$nNfVhQC{lwRvebvEe0cf2Izd6MT*eETm>F zmP%M~kI^KZVPFfqv70!j3gN;ER!!Dw#EMt6pZE=8$$sq`eR1oO`fk$uf=;Gdw}>$Z zv<~8|1Mr3V-~p{7Ce{!6Ni_>eM<3gF>xX+1h4PwKDk5LiUWsv`lWbisY@wyK)hrY> zLQ58(T&JayE5z5Wj-mo?U>y2lz@|;`JB&Or>NRbS*fTgHBf*1q)t$(BW{OP-Ry;WV zFn$!AbL>*8z=?_7b8CZMFtITlw#5^CjBmsJsLd>?D5n8dRRLXue5zui=)A>D5Ep%A zjS%Toj%3?y#WRPaVubI%uE zlSTGjS{dext)LtsPn=k3`D=K*o|CK{YNprKH`YK$3XXTB!@B6Y=HnNM$c;c}JFyen z?$WYjuo|UDv_SH2&IVVb3G{L3g?}|VQe2no$dSraU7?p|DBD1`TZE6#Dk;pq$A^*BrJTP|Kw0}Zc6ad533-_r`XW5E-2e&oW2wl*x->@V>E z{(%-^^%#027Tu+EF%0E#&KBf|6%~llaO^6VLtI>esDrumpz~=lwe#w07fhU6RTIj{ zlM~jh*y^?w>uTlT1NCn`E^#!*$n1u?y85Qka!8{hUF^c<(B`YRrMYEEBL;1c56-RS(W5D2FWcy&X22^U5`CW10!-gT*|xFvF6uF`BME5I=r%64*YwWOi34r47WKk3Q_ zPVPj;QYCiP4Gx!hFcr}wd%dLnLj8;N4b!T$vC14ycypP(dak+e*$ZJuX|P=&=K?3?I461y{7MxQB=p zce?wDs<*WY{-wC%ZSAT*UOr2s(!h#SE}55cxsRSJX3o@fv9b+=mW)h9(DowvL_!ky z{KU=i;HvpJO^ztiB_|9v1B1= zk;T32H^JwqiHfpYoEN3{8*V92DSIsCX*xVZhrP-kL)m93&nnNM5aoFbDxNu(@`CcB z#k+E_!!Oaz%ToKy);fc8r?{Z!qmC=TyeCQwJK!m>epu^L;PR?^r^ zQmev^K-#IO&wNOgzuyQut7 z%gpGBqIon`E{P87`38&M&F`_4!^#nhU&SYj@2@gb#1EUa^nMnPq%^TOC`XlJsHlp- z_S{kxRkaY}WQL*Ymg-OqOEp!)P@R_QQr#h)#R&SsveXDQlKTy!JDozBMyaAKH5y&1 z#-IZHel62CZ)8nFBmAv;;n$0t=YbuR-n~de4$PX(-V7pEt$ramK=doPCsN#i2HR5b zMS)pIYKR3t02_*KM`kp3;Gc`E2vrYyUX6uHAu9|P+Vf9KZL6>MHa6QVT3tP)qm6Cd zR&JOY?^EMc#3UMgJPU6lGgJ+UH?yZl)W04KUSnhPQmVQ=i?!Lxc4~t1B*uDy*H9BJ zHAzjj)D-1_rKVEWL(9O)&8=zl(%>5fEN&rQQL=fMYYJ%wvz?!{SuU)C8@fn!K?djXwNRyuzAC>3AaT$q&=QhDR7r9>ZPnUmG z7#yELqZH1}YMZ6>ST@+-OfNaTtC(C>Ik~DJxY`+CTwYpG?VVIyUI}Nn#pB9~Ck0mr z!Hb!Lrw$D+4FJs=Oyq4a8a@L z)pP__RWl5=6Q*|mV!=`~)hviNgKGzymQR6K& z8{Ngv;pbZX5`L+eby4iV95qMH1#dUrQuEYEOUCg-7&rPdcUXP*nvDAKQe@h*p4z$!lb&%-MH#!@I4OWLpuh%GO zs5;D0i!8NR9d2<8aUU~z8B01^ z68V>Bbs3ggqK>fCQgx&SU1LmsW8emQ!+b}snDw1*cC^${>S#+Xqr(_FjHSakwcJw2 zs})3=d!ZSX>S&4#+g0SM9P`+_TDqRqJD|%McM4t3Fg@$A{gj{*bYQFCRIc&@4&MLB zZ|s445`#fwh3f%#^vdP;M~jU4+L_{v&$Sg!bL6zeW zG4u;9Q+#-Ngj)=qsCE(=zoAF>pQ(vY&cnjxhkTwcmOSk2CVnuq&SJ=K9+%;OTI1OI zvqBny=$0rm`&4lQz&B#J))Jcwt-;nNS`aO|5kanIJqCvb>uaqpVpfvdwes2-apJpw z!XCEh1=AI0&4%WDeNB_(2JvOiG$`Z;RbP7(n;qK*KE7^AV}0@Bkqyi0>n4KaVxkLY zz`?3a z34>?|?(J2b0nNlbQJY&fJw0C;3Z zv1yK#Du#cr4HW;r(aIAKPLH(OU;kbk%Ehd-=!}({W_1=vzlD#0$gz5bc-ol^KEmLA|rVaZOoVb&dvxuPr zJjdq%#>Ag6UgjXnilc<_JYgEPGdM9hG6@t=yfTeOr6g0D6q)Au9Kl@6Hn(*Gh14m|=b1rK@h+g^dU zuwgm*t*>w3HLO}rE^`2EC$TO<$#!)Ip~_eo$*N;*B+uZZu;^x%wx z_oJ}GhY17eQfST~?Y$IQZpja^_L66;%Wzg``G9jWan->LCSl)@(~1m7^7MENY6uWB zvpb>w=7c`23(9Y9XvERho+lCq7;$fA(RrSj&CHYMiQNq6Iiz)KJjoKO)kl~w5xS9& zuq3G9Ji?MERYP|t1)GGa?F^pxJLIV_(B90_^R%tZiy*sso=%%tCNjuEF`a2slQdG> zSvHxjZ)Z8xaBc6&^`I`$7$$Auz>@;`gv;GeJ_Yr)BOF&kdkcCH9ie=j1s#_>=yp^= z-Dw8Y{pz4|Gas5TV2l#>DrVr{^1=nN=-(W=s}0R}h4kzi~Qc0r*bg^l)YaD>Q6GpiRVHV?xEX8B#L z4{2ug1^wH_`i%$Nu<_a-imLNr*`z$|+A$S6Oe!>*RGp1g9c+SXuqxHbW~eYaQ(ZnbOLemr zHA1$LwpR4(SYVsmvn-EyxFin zQY3Vu$>V60!593-MvMWNqVXKda2rf&1Udm=QhXU`((t{~9l>zuYvOK%eK%sObmf|{ zg^gUpfJ&pPwRSdoTpTMa#@$%bFCVuVIE~lZJFfJFDExCg64=-A=-< zY73i;(**i$Wv8{XDbQkn1Yx3V82X2fXDY@FC4tJBJ$eAzX~-v@@`1kRbU89+;AX}n z?DVbd3|!6J%Pvy~lRwlM+t@75Zev5}I&~YXA?@bbcF8kwT8}X$Uj@?ofF89fRJUeq zWX=mY{K`H-ui%;C#7}Q!UAD8j>Oei~?Rp~9Ii9(8P21T#@~hCWSGqi~t3vlE_YRB* znXmsoP-vb{Lca?hYn)P$R_%QJ7Uc1E*4WM#ZevZ-`=-N zv&EaGqlt8swHD-ND_erF%TRsTh++5`qsKR)3if0FgIV<2$0Dg%NSV=Kr@(4^svI_CQP3S;e;4v541?Yv>CL^6{ci_5sm~F5gF0rFhbz{?t@p*-`L=8xoV$|Q1Bxem7kCd2R$M}vUn>y zYYO2X6z)iG1E5)MTL(ybk_k#7>B;Qz`PMWM4)&S6TtW2#3u;+rVzyYy3k4;t^SiL%*HK+?%o4QcKXDFJI3k8=p%+D$&uv|$@ zNNca7kBkoS5bgAna|=pua>|66K|ZVzmjWsQ3S+-p1_%-Th1$jugvI4&Ng|VT42~^e zg!T{lU^&#;`Pp#wM(bT1X|6mBnnM}|RomI6)tHek8{akGw~bv6IDx=kfej{>EkSUl zE@?4iK}u1wlfKituWmoWkf5mVp2|U7d$31=Gk_em<^L=$}~p0$gbl4uouW z`U`{UFAS!?Fqr;Aq$eoBY35-z)ZiESSs2(D(DL7g3HJ>FNOUAyBM1C8L|ldC3FfHl z&?+=eLZw$Y;kn)>JOmkBc~;Wl>H>fV7hpCBK=>R}9x2>Q6fMGqM9~`vVq4ga`W-CS zpQVrZ70)VsOK%V*kq)avS#3P_Bn^HWvNGJVdKGi4SF>34S`7T_FsI$X=BPKaW_1-? zt*#A1cMc|_%fQ+ae=$mKa$bas z+zf>B-BRu!+vJUW!ei{#Eo{BEo>k_1Hf&+Htzl7JJsbREnKk8mZVx=XJ@61SLTFaF z1CX=Pc8=%H5EQk3T0D_ffBv_#tgilf#OJvS$>IU~jp#f(&kHq7L$4K}*X{-q2MQe=KGNkBcncfsZJG_gwZt(>NO$f~| z#zL5>8$f1nXPN39EML8o4a7`3T)mr(SMOm{)O*1*+|Mpn9|Foh%pS#goB9~rt!`#7 zLecM4aP8lLgE)l1hrg*$a8-ShXQ(@PZ}llYLEXb=s!#Jv)MxoM>hs+9p!x!TN`0As zu0l&pJplc%S0P1zP3fY(A;;2f;F2!`8%y(;#xqzHoO=HTrA0S1#E2y{5rjGh0jht4 zzsuF|(M``>>=3-aT+4INa}(e}@jARUk*1zskF}JOe-4GmSzs|;>^mPq$*$x#VuE;! zr^}B)jFjxaT%e@#Rfu}cS*D`#)ig>mCmiN$khRKQ1mjPG*rtobyV}LBMX`2a>p(^A zFNs3hU#<;)NfgpYB=QUveUyzi_)Qqwm_6b;9mZ(>jdeeQ=$Q0m!BKdx<~Ijsn(SzG zq`_}F%wRfy%MliB@LS~!lzWWy6Xgu#&k0|{OEofE&o|(RNeF8`RnptF_9DvH8ROqx zw1KT6)ZJ#IF4)yMK;7~Ads#<+3e4>G>-??kaa_~u0?&2~I6}Ds4{?s3z|E7miL-BT zwPP>K*v@tmE!xq}cENhivzrL+Q<(p3{w@Mfxc}qOTqYGY)sGOL>|?N4pRiK(Q&ypV z4%X@m%>No6a^=pSTJP#$BNPIoO zRI;7zp+>j1v!{t>fy;TOE39XdbpUfOXn`-dLbJ`h6ijJza4=u>DU8(5}s7$Bu3 z>vWA}*)Dd2|0%Avuzeek?c2_t#Z2~`ZT<567WM*Yh`xorxShR(=PxHaG?2|#LV)dt zxrJ;1eHvO6qaJ06nAI~N1S*9!LxrZY1)9MYYbHBeLnJHBC80V4=v>M&`Mp?_!5KN$ zgf!Y5)Yc$;ujltkK@2^+A3&wm@bw555Ae#X2QdOQc-K9TKZJ1cx(^!f9r-2>elQ4q zyNE}Ljlri6@^u&|1btW*9%dN^f9x=#2l532LbD%Yd+;q-FxWB)3P(qrOw@L^AB{f% zam1@z*=wQ2zqDl0B3Yys<&zDw7xYnlD=?5I`^WiqJ1n@vWGZ+{9`zz50Rp%%8lW1*#$4!(^cHjxY+|9J8!|=?`cNUmX2;Rka`+-~z z5EGCoNCS9=H!w>+!rntviTA0Fwn#&UOVs)?m)0M!9vB8{5AFVf8l6s(CJ0X>q4@a} z-{a3aJSeA0*(q}EC9Q{`s~r--==^EoU-9uXut`JjQ~ZheiGP`TAAiBkR zmBhopMZVAR=ViW8x47eT!rz^;7BBD@W$NOC&cBiRCH}HZjqs3vBlRmVBc~P~Kuvsq zS(5{Hz0sm@U}D7mB``5lz8YX8VKYq3KKubfUiSgX>pqm?I^Rc9UUyK+>pq_JD0>fm zkN-QgSzFmByV$3XviD=z{;lk@N107d`(P(kc9P_Ai|O0Sf#zg!Dc#{Q4Fb-+@{|+nIfjLHYyE zhj9K8=YQjTHqJlc{4>t~DM~?b_WkS^oW~*~`ukiSP3WzE#q)}ip+m0lT89&IzBT*? z#+AijcDy*RX3wg9i;}}lxE#ZVS8dBGZudHLEvD;e0I4r(R)z)O7?z9zI%4tK3oa8& zStYDUC$Qx>UW~=;b!@Vjkf?tLZP%hC{hy_?!GhF+!KuSn^;l2NgH1;RU@)H*!9&6* z)`)x-;=3lKT0}NNXw(uciO+=D&T?4moXu`xzV_+K`m?<366A3?tOc%s81qUn0#~tO zq^iPs8tgacA@xNt?YSK0)mMQfya6K4P562XELe9y%=rw2Mz6Cw;hy(y(U_{gU|yeh9z+2uE*#xnTp~)nClY)3YfSs5*O2 zE9r~$9H{4rSs8k)xB|MJV$xHlSC-U{l3wCwAgnkd#_ENLO@=t#WPOEL;pxmv?odYP z^srDIdO^)Y*a(C>K*ZTq&zs@(jmXw_#n`dFNxU71_5DG%-iap)o}CjonGS{ehu zr$}6ifxRFR6gam53P7a*Py5MxEQ3KOIh?!8S%@X#jhuzhN$|xl&hr_GI*^Seh;wrE zWH-IH$z7@7J|o^hHRanUbM%z#(AzTjf(Xc?o&I`&S+z?SN0C)VDDi}_#HO7%x){21 zE8GYhQl6_DVHp>OrPcjuO-3Q;sg74yCq{fJ9?~$j^GlH0SYfn8kgo)dF>5J4L zUiR##A9K0=c)7VS?*%caSRZ9I8f+oKyvbnA;_703mYC$@p7!sG_0JUXz+k;vJQR;| z#+2$8acv>&EX8Xh^(*+4_L-yfCJvciuGl|X&%?!KBBlfOKxg&SU6~fzdAWt{1DN)W zpdfN(Y>WjGfI}slU_l;!x~M4A6HP=gqn7s%?bEm4TBa{hqHLV$AfeQerHJN-qdRoS z1Q3xYpxs5jAZv4uqH=M}6KCA1r%odCFB^w?V%YS8;M}%PqNiQS8cV+K4!b3q;#?pr zX=puNA&Q3N#>gLiUl1>i>LoMYJx)*QNg3P7*I#C8qd7*VKT{_oqbF=_lV5XWnJ27r zJq7+Co~bHgjTT^BcY2&gW0(~6K)F)X2w5puvT8~%kRWGtJ4`OcL2 z+RU2f&)3eQgkgi#juDq99xB(1c)s|dT+f^x018D}9*II}I_vKL)P#-IC`h-UyNc0; zenS<=-VU9Is*gj;Wb#lEk2Mu5H?Tls75IU8`Uvn%y%1868Kdu^p& zh01+0 zVMt~twsF%DL^22FQQ)R5bj~RX{X1m>p5(5`u5mAkGT1NG$t#AKGEq+{4`F0C0KmpT z+p&>?X`AK(qH{Lq#9#}U#0ER8_jFa>n8o6m~;feAvzw_ zqs7x6V`2M>Y5I3+3W7OHdSs!uG3m{;(8Dzp`m&RVnXDIJvP>cZCTC0vtaRudOybDI zqhk z8BKb0MH8G&oha}StrcBzx*_U>;$_A!-l^yKLKzRm1WSY@K=u-Y87Bg%3S`EK5;G{{ zL?B-enQPbw6m3@+HgZyFHZ3fXB_(+MwG6ePFEEs7R)3I1 z1VR+I*6Q)HmiBk$^1A@hvOgonKw$%c+`Td4>>7mmOxVJlCzhUTmo5v30}(#}9Y8J= zj(oCVYHH^*6F}BQ_C`ISB2;<%a~uA4=qJwIOnsFr zcsJxceOp}c?#PY$AT7o}mA4Q0VA*`^0?m&Q#l?D-Sh!a2@HYoXF9kL|2eV)cUa>)U zwGX>lAFTb^c$l#I6yssSAR`aV<8gyQU@-I-O>1?tz4bQzHRbOQi>??J-NLZr8MD{>rB?H4_!-w+yF-o5&KH86Y%1}Ve10{_)xg;<$o#pID--mNgk@gG` z`nYe{$GX3onq;mN%!Oj#e%-@k#XI};4uK{6)zepeG7bnqzaI9I9UX0n0SELrC(PL0 zEZ<-SV)6mdT3RZJAy*r1?f*KUzpvQKY!6En2VU2^qu)Ig>nM^%g|P|cZ|H)He|6Uj z^?dX~fynQnkJh^bsy)QA9(r$a`$;FI7u0se~4$1|Fzn;`%?8)u8vigXj-RJHdt9iN3( z$QjX&6i0wublLRkk>~p{M!#Xf>c+NTk>GfL;c6;dIAvxfGYs9$4eJBy_j0&T)|u z$bVi-&I>QaGWJreIIt7c4qxYp2lqQn@zx4QWcx#nju&GC)xYhPd!x2yGe*C0V$E=%-^b63YX z#0M)JW_#3&jwT5Ul6$pZs2C4fl#jeCj55wj2e77sdxJ#y#Ene8y$kc-= zMWHcPiYer~uLc>rwcxu=MaF=LU@kwD8$)7)cYSJ%9-$Hz)EZ0TgWr9z%y5Q8AOAhe zNOT0&3{O@cIV_S_7?;|sf(Tuo#nZHj%`g~oCvL(0HFv5`_zY>I_wQ*1kwX|nk7Vk2h~anLr!o`&%{ z9mG5!ltNTeN#HoB6Zx1Vf*&pt(}E(gP#$MsH8E3M^MX4*-zEn1Q8!*EFI^Z95h#gj zA6#mjA6x{Ud&Tu5+ZSAAydKdZF8Eaq>k=-GmZ&vjoiR9s6t~`FJl8FVOwBJCN36i0 zeWL1?9uq)xC&b%az(*e&7;JADXT(FKE(iXIii+)TqOdo`q8kvX?}zs=?eF}~aEoi! zW2kg|A8X9_3k^%m`_6bSh?E1qH>yKuzxpR*b_nhHe~fP(!IVEA1{WP50xy1lc18n8 zNP}tu}z{V-Zs^j_rbvpnW*M z#1q+TJgME8Xhv|JDiV{-@#5n(0eHb-&TK_r`(cPNA&!5~y=FhX|@!G7>iHU#Gq+?VlUSP`4=N0dP|YYfZcW1($S zE|#a7mjnQ2MyjtIz%u(lM_Z73?d@@~zUPlVz5_kmi$l^rhCS$J53z?0w#j6VkR<+5 zgFQx3iZ;8jEzs@+-?Wu(AEc{ol=g8qdE2AIlLp)2gcNtD!FIW@oBN>2cGLMOI_xni z+EEO9#s#U>K7&2$!mxi18Ti=q&?;ju(3da5GYUmJLf}A?9iZf|n(Q?y>UD#?L8B6$ ziwYS$7ZoyiE-Ga3TvW*3apCYT9o{p^{aqA$h91Ms3gQa7*hlQ3$v&nhpU~k`dh!_^ zKBt1dfP0vi*q8LxSJeKm4fusYv;IX-zNN!=l;C@l!H3aH3@(fc*^hMix5<7o+0Q2X zk4Zt0K48C?G6IspemB@*u#PZ`KhDbvI|8%VvZgxtajz?bRV8^EKpL^HgBj_HkQQF0 zRizWfdC$NbMCDJ;XcgumqTOj`uDtfBB^C~GdWClm44o>D8ZHr?X=_dE(@2}4#5vhDTn@@&zNW%g0$A$G%}O^&4Oc`&8r4ht%c*fBwXFAFptM!HV! zLOm?*<`%4i5ziCMV8*J>X0#f`riq%1)ilw)vss)L&0}C&%RQj7xzhKX!DB5R2Wu4Y zcIQ20WDY0A$^;7oXf@g2BI{&!8!Bh<6n2@xQ!Snb`#qL0xv6bQOG~qK3qppTRcE!- zdtvt*4cop$oz3oQHOhrS+MofHA?CHy*%=hu1czC4sG$Sgnc^*LkfBEm?zMOZ1&LBD zp2;n-s*9Q5rH)Oca3pgqo<&XTOrb}}HXPMJ1LpBO84g97G-s2oIO2mKysHJ1fy>D5 z7)tlNz~Vj0$=+(#d zbC_`LIR?$=CvweP%@=`TL=o4ZmybcLK#Uwioq>B25i1Z2$3P%F4c9T$Kk^I!$TMId z&j5ow0}?o=Q1#>)HI!$xT%K*e?I{EV+?yz4o&#Hx3Y*_Pt(*BF_btF<=&Ry57oxLy znA{q`N;HBsUkH&~6V@s%kcTaT?5Gt(tqoOPjE*=H1ug{#yA0c*XR%d~l|RnT0hKtH zy@h?;57>Fw-aQ{XxEBBmF5;aLt)>^dg!g5a@!{-pUIBH`iR>yqlU?oOv)Oh0VmM~I zjNQPmgmd-lnBeQ#YW@(mZ+Eb@{3W&y)nV|39)SY(pjy+wEMLr3RIV9on--piDlP&8 zz_1VBDqWn?)nWB1LVCz{5mNzBy9n~>ZfES18B@N#V7@R9@aOA8 zzAKPN33E{(Jf8xe#c=#i7C2Lx+rGg)=C1RD|2gh1Aid+x2D>oxFg&cMrA1}_g4}I{ zxrn+IJ;AZz%+OP|(^h956qlfFpKq_FsiSS)?shcj4hho)vJPNql^<-lxKY?PtBvfd~&vzPWRe_kA0)K^drVpT75Ts1bWLw66#LfC~A_Pa#r3 zC@n_yHhmJKrNs){iH7dNbg&ze&}WdvURK2Ru~E>cpT(X7oS5MHI)a9a-W$=4 z`TmYtg~T8*IL;Rf`j|_@>Uscp@hbT9*FhZKKneduo!^F7{2dU0cQMG{#_q|7L2&f~ zAH7B*GeZpny*CHS0PB!>GSm%j!az_YxIEa&u@19T;MQSiYUE=t2Wdd!pc8?5)b=&U zO{ea$9Z7x)qVpNL<8#O!KSLLNCCj8$Yb=^ZWrlZ53}hO&;F;YqK(8ZUyRc!@8IZe` zt(OgT^)o+_4VC_u!8g#JoC8`FCLG>+u}zi*YB&H?umWJ6gJUB`LJKJ1Vl@3abjv2t zd!hie$K}N~+Xm=3I6wntvD<;iBsiD>jfZLIxLADEf-73JFM`1rb)f^Dxp9<49uwIh zdb1xcxlARu_1NYDB3+Fkb}#2N$g&J}-!Zga^}j$KiXY`45RdjZLu=H7{mpNKQf(yj z|B3ZiI3e|$W+p|RuqH?zV*Vth5^{wQH_|K!EgVNpGA}d&BAvDuudKKSfTrJ2kulQD zT{YKq!dBUIwx>)tw}jS|Z=P;Og);eez8M`stRoe0PRW^P+y@J_`=VCXjJ7KzDmTW( zw^uAPABhSsE6hvH%1{n7Z#371*30}h^A^eS%L?Chx4Bd<4&+_dgXV>yyN4b%uhaw8 z-(K}z(q*8L^qVSrK4_MRYd4u50UkfP{jqK4#i2ZlcbSgRKEe3c%{iexgzX=gABRe~ z<5P3JJ5Xye_6IX3aMS*eAIuj*AQ|^>^ZHOGpB*vZQUeQXeOCWi@ho@tp8FH zdWP_mEj$J6iNVvL&cG8)-hs|Aq-o*lbmayAY$wYwc_(_DY4R*Occw!ZlV_Ve$K<&t zhrF#t)F{q4pUHcfyf?k?WAeU~O+SEfd}b`EdgWhNhEa=4DZfsZqJxxvSSljarlX{8BYF&xeyhx+Kj z4IHi@Z{SsQm~3#kf-K=vOg`1%)dru2-AF#&35OV`yI|XJ1|^zFhgl}Calr(ymJ-w% zyx!n*==ofV(>c!t)x8FT&!-O;P;k#i$`$e5nhf3y7u6gts;hZR9~X4J2e~LBn8_DY zl0wR32|X#IcSR;Y)8tEC6zYrKz~E-N*q}PcRifgR{7P!>RVKe08sBtzt;w&W^Yu=E zVWKEcHRqY!7-+CZ0B|wn9W|wWn8TT>@vqvayPSg+4Gm8d>nx{NUCq|m4E1N0GncOx zQ4!91zPEizg!62L?-f5rIg5~Hz33b5oWs|MO*`C4;<0FF2PAzp+L;r-o0xpH+uVOZ z-J;v-6?f1kxaV!w!kvCgF^t~$;+oF5c7 z#X0ADR&zKI`3~v%WBe(L?d9K#ga3#wXde;pY;_obH71U=(i434IuKQx%P7E{77$12 zn7?kpozp+dtQEhdI!!$zHrg49G3m~U;_;5oA;|2P zjwjUMZe(_14ekkjNVR?^{cn78uM7;aRup)hzu}wg4Cf>tRhqQ9=V9ZP!a5k>P0vC+ zf``zMQJ4xJ#+3?gU_K_%M=(K70vGWpuE_iGbOa1|08rVE*_vGb)4YC=waePl)m8}v zf*hiE^gRZ^V5+=J{@-RW{D0iY0oxC63Y}@n?*$bbP*Xbz1%cV#85MiN-_VRs&Vd7{ zFQqOqYUM=TvQd*zU*&`WTV*^ONr1l+6Rz*%T!ALXW;!$b1o~+J#C$tZZR)2fVV}Zm zIwnyYjq;HJ2ARxYex|dmG*tXs;2GWlqw}sTo_akdEVmwExdHXy?3uE{2$os>lIirJ zF3Ylux%N~!1n+;cS#W8%RNv80=AJc&Aj5l{<3Rb*DqF3ucZuwdRX2qaRzAm)qy68*W*XHcy^xdCHOXaMhgasyE4 z3&F2T{o_1!I~!Ro9`52y3k`lAKKN7pm2iT2e@WK(-(8%!VTt>Pm6Q}r46-T{mt;FD zD}uPdM||8j_Wa4huH zsfh{{wZ07wmmKCG>tN^+-i0CjoxNVbsJ^R+A4B#;{4jtci>Mx$C#fFDW0&}EKIXo4 zqOic3K97J*b)hBFA(Y`j4LZrXsMuETDC?pD2UBHTbfoUAm zF!7Of`2|a1C(XVR0J{soimVekU7h)oP|@(DaDYb_!U@8yWFntAC<5dYx|5LB;(vgG9sw0V zWH0eJau1_hA4^2Br4kALL3b2+X~>})DtQcDWp_|NR1r7Kf`!p?&)J@Hwy<+gq+VZy z+bA>tWtU$msMsktB%2}5>L!3!=DvouT($L*28%zvO3(unID9| z4oMMV0NKzD#XiYF)MXTQ&jOQbvma)D_)8LkUOqgCx*%)@Bk{2;#Mjd~ABB9~(~odO zv0|}F0kJaPcf>{vWXmYT3x**I#i>95cd)n#JX+E&Dy{<|m)GDi2KS)E1oIg68l=s3 zmn+z%!O+Bhjlh`-pNBJ~HNoY!E*HQnZ$?!6Yx+5zVplJx+)d?$C2%a20HuX2G^Pewa%|X%h$B|&Wl4D>-Q{lK9Ckj zDXzUv>9{hg)C`jX&`y=O?sDf*N+dV@R$bxzLM~S2-G!^1cMS>bmj7Je`fHvWa|wPW z;<{DN6yK7@#SP=?&#Wi^#1!E`g2l^+{1u_snsWTb0x;)%SdXey!m z$seDpsZ?q!1?d$TZAyaJ^>}nLpF@R@Kl%H?Rpq5s6U$0wR#jJ)4yqbmHmRy&6nxOn z99vpFsH%A4DEWM7w-YM{C=U`72D%4{>NldW3;3P`fohVi&XME;&hLi~0zz@%RYa?~ z7OvdH(jTn^QTqljh_-5K$w4bBi14sv_A((=i4!fS$3}}4$yThBve0T;=eCJMS89m~ z&R{h->yZ<<5i#xloD-y1=!k_i3&`)hjRCYZ6e@b|Au9&(GgB(-Tgf?cc|EYAHkcUj zT7HVulTMxbZ$gYZ0sgfc+7M<65q!}kilMXe*lj(i^tPOMn&0`C^k97zJR zMK)Iyg_rEU6shsyv-wJTnHGH60WUk^P5~EBI~5tI5LJaNPKXOtq&cQtC{-5P4PgZ- z!GaX~afG0}MJG383Z72hIW)4^4~puGRwxjhB;srv%MF&miNGW~QVWX$MbrL|KM(liV<7#<5mHcJ@wzj@ zcRY2-3L_vV%&n&Ji*T}_8+upn~b@eDWZrPI|+x|&6Y z8aH-xv7W7UW1Q7tvl9;!*c`f>ONV&~>xa;Dpa8X^Xd>?*c4cW6UnUN|9npgZd(o)} z``?{Bh7JXWn59Fl@`NYY;HpH5A`}5gqGQF<+pThhvn5;yqBb?DLY(dDII_Zoy#BwD&16vBr2>;IjnnfSlQ(?AQ;0!<$(Dq@w?WSYCsBNlC#qgyQ63AQjrE(yBC&H$lJ z4@IKHW^{iD#$-A=(ws_2RrHk~3EC!W< z<$f(Drn`8)Kuz|6rL>vZwyI|0{WLGA7|~ZE@HC0rc2k({z&hC4st%0;@}*OLhYaW?hC=v<4=FvFV{`i`$tBu0n(JQTQ%%NFQWS+#nxJ1K}pe^sIWv#D3>R|VVJyRIV0`+3ftnS_wtb-(5J`{RAloH_TNb5Ac%e?VAvC_7dSaDi>Z zZKXUH<3icQ+~yN(T)}#36ALA)hi9Lm>)VPem*GML>IeA~2Lwc-L9EY)ut^_G$1n(( zOv4DzfY=C$;}G`T2bVkP3fqv&*G1jXR)7zKK;Fw#xBg7ro!yZcjmPEG6CLV>xOqKM z8eKzXS`O0sAP!2(Srh@15ozUXEEihy5VU{|763ssmZX1%X-9~$0eb}?J$^ID!lSJT zl9@0x8E)DkRpSu@@I;MA1lb{l*Pi;be{b%rN$tN9on8az;%e0~f>+vOzz2caL?%HK zRB!0o&+zvq&<8VDK5`+==kE@6!bz^PAzOiFlfKDdP_Wcgf<#aHv_P3%u5lShVblbM zdUUcDca(*AtYjL^hWU#Un7;@#Jlcc+%!yI<_8_xjffR@aCQum6E<{1JBnA>7UD<}_ zSqZ}o4#g{?6Q%_xAPqA(9F3uO1WFMQN6HKkGiWg>l;4~b%0B}6sXyQdoQ4HLK$PYj zjKcfTph23QdKAA_tO{iUv&9_HfU7x(MZ}x~SR!nK+c`|aC#@&p4h;H64Dp?65{N$C z9^Ir#uwW7r)g;hB6F6orsZ7F*&=Q&sFRP$gqYv`&ftk(h2xS}R??{V@N$~e&JX${i z9|%Z!bi*%^YhoaLlieB$y7<-)UaQ4Eq(2ZzK<*fS{vFoQ@0X#)9n}gRf>%a3&nAJ_ z4kUdF20g%GjfjU`gK)-wpL`MFYSj?)(!TT*SC@9yA8L6UcQ-G^jo21W`$sSDR?Yfv z&@TQLpetY7_sk#c8{wdT5cSs>1Y8|V*G$LFnHnMX+02>*{T+pUcWiML5f$zHVGG=C zsjYIhSa~gAwz?`gp)N8OUMRvt(M&ie@RzvZ=I1?d`$g1*Rxmy6kq{>C&lkkRvDJtR zVq(DP2Vz9SMQ5;uKnVl~S5cZltu`@W*i;m>*)70}2i?a@SE29%t>F)p1l}@O@HQ@lhDS_4f>+l@YUwn1or>U38TB3 zt6e?1o%~lvOE70}75#4hjVS7t8-IAWeAWx$Q6^nwNKmDu^btjdStb{C;9hD`EsMA%Ldf z{ICDurJr?vCI9cxX$jBtQ?Nycf48Lm%V!QKunwF#G!1f9xF!Cd0W(o_*qDT`xH0Uo|;ZKg> zt|P$3#~K`fi)wY?agfJNVas$V#4M*^1qCZLb}^)s*(H?gQqpv}+zG6674!y(U3`TT zIw))C^;H_XS_gau%JXGxt;Vj=0ZgigYc+Nq(Uz~E;;*LPy^doN9p!37dg?EZuBUm_I;9U5;(*Rz$+Thoo1DWHyh+>mV9$c9a0U^?3 z=e7|NKu?asvW0M=2oH^%DJtdEwzK}hV+gnT^)PJ4O8VfXNAIdPdt zCKC9t;G6~9`Uk6MNw<}&J~Kusjd3coHJfh3$>ih>)t7jN{+H`QcQnODtXU{uUJw@*V_)%?CB~L^dJs>K7 zKF|NZjb68jkb+#(HXI3Yz1q^cW!0RuHyydjwGOLWR!$CaxLlBXSXMzksLQG<)!n4r zX@?rM#TAoCUIXF~wK8%dA1(_oa9$w6VFnd1(|IuHWR2j$07B9oByBjFY19yh1LCAi0S0Y)i*fW>&>z{ z^6@2_C92RlGKNkamO z$LC#Q29(l}+ayhOZI%0c(v$%KgJAZ4t+Jnw?-@|z%QYYsx(iFufXv~;21Ez;1R%m* ztqN$-CD;@&Aa4AK0rj~@Ne3E(xF5=}Af*yP%cj2EPtzt&bIvJV5XwOM;9D`@SFztT!|q zi3^39KuKmT{qT$>8GI(&g(g#k>KuwEs?(mvIpi<=V%laUo`u<2N<+{5)eJ|$BNQ`+ zs+mk)`KX>SRS)X2wbhY1EvgC&Ruy($Rg`vaRU?B{P4o9CGFTI83xQSs^M-9+i`pWC zwMCv+8>O9Fn`u}U9pj0>NQlaMEt~*oMOq`X!*N0SJ_e^PU;%DqF(7L?$TpZS4aC_{ zaLwTV2I=sN(=t7xh>|0N$?&<+GC4{m!}o^&YxlXyF)BIMOg5Q4v^Y%7=hK*;Gc3*r z7Y^xIM145;N#Ju%g`991x3gv30lhe<8VX{^p)0|mxE5620=4q41^0)HNz!aL=b}NO z{9_c;hhk%)vupBrpkkGtl$7LO4HHS6XA*Rd%uVzrDk8dePFgy+a&g3rgF3kfK6JpJ zYl5>gj9dc6;yF9a63ER)CT20QfhEYGT~4rfIV2FHdY1!E>rAwp9AJ=DT}!Z^W+Agti1{V;*vvHtxhCLA zX`n+gd9KEaPvJ!2bTsij+Nio0jfmMha-x=8fA+KHZYjb&mKHf- z?Z~~sxq&RS>XJa$+L26;YCYK;3ha2I)|yOh2m>d=RvgIOOvgFF>eAg?CidpLd>}dz=N&77m^SSu>+zNur&GoLm7q;1ve*OMFVzeK#Uz z_ra%ZVBY$(pSJFQI{HtZBePTkh)YSEji%Is{>Q8SQy)7AXS6eP#uuU|fmLeepRMMg z7iBXSEM;4SY&3m}OKFZtJAWt2U^QtmjQ(P&Dy!(e;8@^@CI)C=EXrxvk+}kD<>tEX zhpMPaT3Y%Hh$PZb3b5h>=d}5`$%28%gqk&4PgU5ev{K9ink-n*cQs&H(kAX>0~(#8 zr1zrmOTvK>`0b2evUQ(|-vs=2Y01z~!tLE(b!Z|WLGHMEYT|F0WcuqtBmqz8Ij|Rz z1tM9bM!fWhAb2fzZ`0kkYp@jcLa}Bf7(qE?B?fbju#X%c%LmFU@3xW5G31)>bc8wS z&RyDn@UZ-GCh#T?-Rnp=4`K_Cia)0*3Ko`I9Z~H_WWH51tM5;cZjMf%lkUe-2ZcRIpY;_#@v>?9~g~w3mg2Jd~2hh2Q`5$!e^I)iz~+kY+Nut?rjLV+geDVV0j{1Yk&& z{ADtz`P-mz0=Go4fjaS0c#h1Ik#9KSI<_@&%_W%_9MMzwIF*0MAIT47q5ovsAW%Xe z-2;+-50Fzh32)U$q|0r;J7A?q6`Igiq4=ilCHU6`QHlbi=rM^3brUOqSGA;QJ=ki0 zCT*y>B(@Fd%X6Bk+7i*aE%GLA#N=fDn;{RPy8cy*P3vE)?c4m)z=G?aYYAylix#X!1BcwKMT4l^xwTL(>Wu(^Kq1-i zrQd|+eMUmcp@WJl&ThfgPJeyXWfB#fljeD#z2&0q1VJ@2Mwb91eAr`ZPstOn!h|KA zhjD>b)cj%dR+4X(+s$l!{#mwvy@TdA?;!cK$LW?{IH$I>bzJ|Ey|S^by^?f3wW;M^ zA&s2`+077EnYB4IG&`k@k!rmqurig-3ZM#F@Xd!<>oIDv$cLS~$g#fZcBFqKGeT>f z?#DLQHwl)QM>AZs%o9})=tNlA>>H)&v)C6MtYT6QAcgcX}Vr@Mjq?*sx;X_eFZ zG4}?=OktDe@+lX}$GQ%~nm5azmW<+?*R^O}izavHiP(I%+HeFv#b7}bFcfICW)_Nf zv8sC0C^eRI^DTK<`Su-$HE5AX{`R3GJD|ST*!?5N$*|y)=Lg5!h~U#I zi{8*|o_l~>PmT^)-I-n35YZQ-)7LIf&ay|#36DhU@}~Z}OD4zZw#FS@^UfKz7c_bcl{^mJgX{m*>>W%d!KflVrPL&O@lY_jO#jT7hVy_@ad z+*qo230l0_fBcd-d3cdN*#~-m zz>;vf!S2;mA2$D$UpYF;x$9td)Hj}YmSbPHI2yk#(+_hU)~kzQat$@g$N|oF@|^{G zd)Oq0iD(0|i7=-%kL>T2C{Ir^v|L|k=>$tVC;I8_<;HS-0q=Bsh2D*KlHDuxE0DBY zPF$$>YqV7AZV_r)8SkLhMMwGOx2}vt63h%N9UA~{0>d3j2$Hi@Sy`>ergp(AbBE-% z$Q%NkINP6@+~B0jUDf){yo(&TR8RL&p@fL$V`Y-Q2t*Nqf{=d-+DrusYoS%X!e0u- z$l(NS)>=@9NOvR`>5%z7!@?lpsdz|3>Xy8C8`y(j5z20V zh1JR6nmcs09@4nHMqi@`3_hvP{eesJGrBwO+-+BW(bqra;bh9QDtNnb!e#pP78rE> z+bTVe7t6%e`WRj!%U0_X1N*39>NgELhcmWwxE$0uB2M0PogOQ<9Ec9N{R-XgvuHXr zQr2qx8auxh035&00XgmKH8LA?BVR`k>nXTNgVi8t5v`>Mm=1!MSPE{nFm1b+Vz*In zyT&ChVtxlbY}ENCSPw#Q7d>vKU<(EC&bkdaINz=_Upu~oUXei|jo$-H4}7hi-%G#s zI{6T_^9ShRK^^{cRMU1*_J=5VSmV2Oc(_$f+T&o~^1bwWAH92oY(70ovHec+gh>ep zC}^VKF$xY+;CtM`pWsjG{188^LreFF#-GwzKWbV({xk*8P$AD!a8%>RsMzOp*gO0a z#h%yrpEdph8GZVT#$mj5Bwwp@I3{%RCv@1$M4oQ^Bz^Y*#Xh9qBg*hGz59e>f2W#0r34sn4dI{b{0si2 z#=o-jukHLBJBQ8IQhps|k_YE${5w1UUgtmXAMN}nn%JMIaWLKL%jbW!^Ixb(zuNgJ z`u&H-e*+sEJwb4qDmmlizf*U9H@kCIhtMI%1PY-Gi?BL`O@!zOG+o$*L&sYu8Ym1n zM-`!z8b%4>P7xs@?ZSn56;XIV{oMBwaBShm6pI+Uh_wqC5*sEwnrLSi@#vd?A+Znv zD`Fu6=*2LRtP8J5p@1Zl1tgP0L`Pk85}heXr7T@2=t==hhz%3zy2ucjy2ujQ^w^D- z!x>F1DyTI)*Ou*V$@-Q*pE+)_y6RB5| zur@@YE+&g9Se|04X=F=`2z57Zxk|qZem^(xZP9X0S=dl{{WZD)+s>EWVC2fbUZYpE zPpPgct0=BnnO_c;dqrtwU12F{HiL0kSO=54r3+We&q`-K%@9=Um)eu+$4uRqOaH-4~QpTd)$(!?B1%+|zQ z+T5a8gE1B{UlTCjb`L41?`^au%0KT3PlQBFV#HvJ?1l6=`CddRM~>(d7$l+}*;r-KR?iQobM^K|nr-*~&8WaV}Y+*e0<`%r`1 z#R7xDHV$!;j<43cy3kfbEEJ0j7{PqSfW?`&6<;p)L-vsYlP5nKFkA9B1NKK?%j{S7 zH#uJFSzW1|G6M!fe$&KaLo5;HhNwUQ8#%8Tkbg$-clH`*J>~XTktylg3a4+%4ZfH! zF(4iNrp&+E0-N4<=pCagMHMF05Y=KSl+m-i-YK=EGQ}2_C@;N3@8GHtOAT1XK_lL! z-~<}6_YS@Nq?7CeL)5bG$uipahNu(E3|`5r3~`ZIj-_FU6=J2qU~9%;pHuJ!^#}%1 z3^H}CiHi+!315L_WQa>qgSbpwE|0(BOo`T^3oa$h6Fx_7ieO;A$EwnW&WM|+K`=wxJTS8U%XRqZ?6~k8RC8{fM4#^ zGqfA|C=j1hWVhZCsVL(C@t}e3?!uZi#6#4qhYhh?>@mb%u}>3^7~)Z}UlR?6XcPww z(L^~OGsHphI5wUko)AwO;*i*Hh{G`OERIl~rzox15Kr?s&SJem^sCmpyr!(KuC&ry zSLHRtGh%6!A)e*&Af`;Ksj4f*yGn6Xes-6hZRsf1$*-qGc9lan>#=i=3E0>x;spku zgFyUAJga%2f@=Dbuhzs@hWMJAbP27VZ^XBT_>OXYFMiNOsUd!(ho5Ls z{Ve{$nY*&IF1vO?c5SiT9ODd)!!o+c5Wk3DA?!bWvLQ~1-wbhDoRK$f(FeEto!0hQ zC>vO~MQ9d_VX<0lWVG-lTAnyq9}IVHczH*JOxUVlDL)=%3-1C-Y4*Q8TZvhI^0v@S zd3I-LSmQfe_4kFm(iz%S9=l&pm4m;rX358M6ck6wGC8Y6zyY=_1^3kx+DEaDrdVksdem$ShmfPz?yU0FsEMam&2dDLq z-3D_uM0DkG8@5k~N}N(xRt_~@_x!Sj#WiD#t82$q4KA)Ng|;Gy$uc{^nGih#l4t>0 znkkhP#nsiNB{-SG+sj2y8D&u}9Hp%;Es(8J<*KJFQSz59==|3%eeWaQ@6*06_m20OO=w*N!FzaTlGo>X+<`(KF6S^^0Rt{o*jh zub`t>J>#fTzc}sGdz@D483&*G#kr?`aYCcMkHKof$Dg2J9Jwli%xh6aIQ7&o4nE4L z@_mi>I4)Hjr@Q*a0k3{>#^cwej7U+LIPTRmj(PmXfoYEOFIdv=K&;4;Qz5wING6{o zgaHZ5E($rtO&o49C%nt#!w7EW#6X}NA;6_@7~ytu;0a}j_Y|(ixK}>DNAK^m?1u~Z zgK!!N=6}?F77eS~?u-L0CKJD;f)ksTu^;9rGWRnNvb8J9Y-I7^2a|_+M*~aP&k_+! zJjOa7WJyH_Su)TvuPdd2wa;u|9q{Aoh@gRWYGj=crMa#9S!$Zwwx4xLbBFAQpLyRw zmWEGIQAV1_ILhoEqn?HAW2i3+1!o}Ez_LBsQB>*C8dx`aNi{aG?jHM57LK^#u{Xg$ zBb%1yaqMS3(>(fq)+^29+|PQac|!NI9KsQ;YOrom45%A11S5dzkAi2YFZSxOzC0Lx zFMvYi1SmvKhPCbKP>P%dbJ+7>6ni1N9k{E6?&=-zO}!D4FPmYWVhc<{Y=xl)(>uQzY!{DW4{;CM&66RQLi4l^*fM4yFi$@2RSOo= zgBUGYOe|uw){q@BTCTt^5u*i*$wiEoDyY4P(c;xqjFu~?Gk8bq)1hLtLV@Sv9j#H& zuMnfv3E~oBWX#ML3dF&`dhqH)EOfJwFWA@2$%*7u!fa>JsW6QjaH?khk2R@ryb0HM zg!&&5vS|fl`!Hs87M=KG*#)cvRe0n&|VI}Qz9s>yx@h79~7>*0f}UlFQ^ZDjomzy=;L77rPS z3~XS78d#oXpe4tOos?e$b8Lf=mea_F?1xQ|Mm99p7R82HhNSQ@fT z+r&DxEN%Mv*?6wc?y()^160#Iwgy&&rf=k#6rEw+$uw&{vs!W-{?0#T$w+ z#uRzN@U$sVQ8>;PkKqaRgf+4`9%loayOG)5;Tu`JCxjl0{qG!WtQ?2g8VmOr=VroV zv3e&@Ht0#d89P`WwbL-$Sr2`Cw2o>~jholV=Kr&j*XX?d?BnL*sb^&vCpNTsoDQ&( zEv(l;RvJ8+7tr{cL)hN6(40D-IpK@&q$aTJ5LQgrO%PWJp`wb>4LWK=@rW6t$3(Yv zu4{4iCLFVmGQ0H&wxq}sIQz>{4Bpx(&s7bq0*|grvuG@-s`@jjSe%fmMIMatQYdZX z4rp#*jrlo}YSl!ych#96H!{^OBrLMmxwZ!k$@9S=_WY;u_eB zTsy6fkOsCgSNA}S>0%PbIZUxjXdC&4VJXlwZeqpw!f}+%pdb7t((6kb7@16LU_PuC z=RUTofvu(mU_pj12iO${*p)a-DCe4e?5ca{qkZh^b2F{=XR>>oP3#&0O#|+Bs1fXw z_NcGb5Tab0+YuPMYs~>cKdx&rif8-NrFT8#?$NCq@I|XxxDk1AN3L_NH$U&Xk!cnz zEVq?j-qc(Y&Oo^IphJ+)U{i5aK97sx&$t|4fMtmnSqk8*j=);`;DQT!W%K8e&;@7+j`-YEa-}6cAXTFgA%9lf0 z!v{lCnip8@e4I6kkGE#>$<`b`#hTBjT37HQtB=pH zuHhG25Aj)arSJ%lqSv#-aL_{>;*Gdl6A|+{`F3XENr)Q!K6s9ymrlM5{$$K|``Id< zjCY~@Nw%DO5ewt*L)|J|2ua+#X6sc z=~O-_B@f0%VZ$`#41Ge0XIPRMF)VrfG)Uah!iXmD#Az1kYf+||k#2N25`h^G02BFm zcbauT2z~_Ko?`aj*s$bZS+3}tOr~*D0tK}w2TjbwUp~3qxI}$A0$-m6hXl^307A9w zhfie&6NC@eIPCZj!ShfuLwbHzGiS&-ISJwc6~hnlRA4#?#EeRBU^fFq*fW-{SJwuD zzfmOd7VUs;EzMvL_Z4F?&cjs9S8xvrLqggJLLwtDMkpx=VMVn7fPi+4)L>d#5S7MX z_m%jPzM#X|Jli{%vD$)kM56JR)4*;;%VunWmi?akvu}|=8RS@1Ym|u+UXH3Oz^$kR zZ=nhcx|*f(8W8$xgFu;!x%p_UG3rf***FE0k=SZyqJo1~<8M(7UeRd8D{+F`RCqh; zmj~D#I1z#DY}`xh&uoD55yLOVy1NW3=yDc=qpBTW9UK*u6C8_pJ{Eh4nh*~gkQ!A;@mlerc>EyH6)95CRfjXp{Ngmz~JjS`TryYLga zi5cp-_W`!K8BjIH=z5IN4QSqttOH+%F<1}3dpEKE{1(;JUS^HKrVii}{7oIeCsI?X zJ?cQAp&7t^bfQ>Q`yt}0I}MmcAX1On1$4zq*acgMal;jPEn147EAX@h(Jfoqa*AR! zGXRFAkMlpI;~^v0n%Tg%lC7X^JJzBCDyqx z&wqg3?GD+(+Ib*Ai`Ob}hXm7_$E1fsWj5nb+zNrr?eG(_gZ1L~usnV*;N*HXo!<|q zQV+1D{9!OpcH@A3OpOznj4l9g#aD=f$OfdZH=m3cnNnEDr(jITv`rD8N~1&l4-V)$ zJ`L|^?$`0@h?#TWm4$T7Q)dOvl|dByoef0DaYV$!-wthiI*#y}l}K&=;e{NrxkT>8 zXzpxcpl6SR6(0qo^hZR2DEBIJOpmhq26o>@wUG>u6^~8iLuVuK8udiM1As;9&mN)m zG`E30NWTDJcG2(F2KEsBZfRf-)9>sCwi`cleVcGvAR-&s9{Sze!1iGlfk!y$@sS4h zXkbzgu>H;BK9~?5{w((CF|g#G!&v{BP3AAL3;A(Y!v6{bTCcD={wjL#I$Wi_325bQ zb_;(8Ue8WK!Q%t;^kX#-K3cFi<@pSLAx2tfgVpszi}T*#nBQxjJ?h=8;F!lU?KB;e z`Q(y{&pyS#HWmZJAfH2YO#cXzkxbyT>@a%KfWO8DcA$YZ(MsKh1^1Y5CrhVaJa5JF z%CWkwh+;Gj9$=5dEi@cS7I|!q>`9Cd#$$U9C2!9mGa(ow9Y2#df<*Et>j@y4eo%fr z^8nl;YgxU_m%Y?WpeZ440AcQsxg|MTI#rVnIsPqf%^h-p9YO{8B6TD4q`M9`up>ud z$4SMW!q?ajH1;MTBZovx_~*F(zrYdo70$@7v3$S5(ER{@=Z|b0{|TqG&f$N@P3fWcf)Ods3wwJu-U{{QUhtU%C z@i{cFOiSW^l z-4A!Jl^7TPgR|L-IKXfcmuW%m5?0j@DjHfV{v~4N<+wLYw7=!YeOiA^2FQc55%e+6 ze^d>whX3mo=pvnwshA584MGV$aXqc@574Oquq%B28TEUBJ=?q?+TrYA!U2P(5F`-> zixHtLNx&AV2v>EQ(II=IB8u5klun> zNa7c%IfO(UPgQe>x`J)%L&SOva0q5|CB8M!ILOSxG#Syb}tJ@RVcFALC6AX;KoQyQTtjTm2#No=GMHm6_FfJ6#<+MeUs3`}E$zuBDF6m7I5 ztQEObbZVm|oUh`m{T~m+*wYdSNdvJntabemUlD0${pOUmBtj9P7l;kNqRo~>wr)vg zn=QGr?UqEgY)Lj6C~$O&-l~Z6TSBB|n7`+1%mJ3q9@V|`o}(hTg0}#|AwC>Kdlh~K z{8T=V-yWE9knq&MFGVNzRh|dF9@5x%c^=*kwg_EHxE@=FLHD5a#J$$pfL!?`Q5vEeEbDSGY>~E#I5?_iTPFW`pDGx^e2(;llSy7GbkV3y>6rqM3oi{RbQo~ zM_cQm;I|J!mWoH^+i8}7`=ysX@-!eF=n=ZGnntMRT>n1CudjUheLZy! zRYOu^aX5Zpnj96<{WBUB5?IwUSWQo8T~ReQ^uGY9bo^yN|B4z$6&lQfg9j(Pmz+E@ zXlRjURv$U_g#IGx>U2^c;iJ09Wz=NoKTUuFogGcDg-T#H%F2R?#z}Y=0&r}rs-H@E zB3Se&a?JW0Kog<*4H#;k1`yE-Of)dKl%JeKQrqAc=69T<-C>9rC?;%@ zUU(We(`nWju_!kTIsQtBqYYdI>@+yMw6i(>iA(rEZ|5d09&f64kM2Aj1{TUUh;)^13q<;Tsw`;0Ak7 zNAQl0b^JFcm?ePbGg!`TUXJfX3Za?lt)Q>K2TAK)J}p7=;V$!*q2BZf|v6K7iB z=lV@+SezI-8QL49YwR6SQ?;zxTeGavTT)yn^G}B_lJ{?e-pjX{hD~NZ27i+i{;rSa zhP}F`YGF-jEqJ6I)!P@$SBtJeiu(0b4Fn2D~*ykj9 z@udN0K3|f2MSB$XWzb6QXl(1R$;&i~{f1(5DfTVJ7EtUvip{6k_Y^Cm*bfvdr`V4a z!?8*-DnD=NJ{XpfKi9K|C>f7mNzmgI1;4Rh;L3#5GJiLSV+jHb7wDq_(jKTXu&8Yd zy5^q9rYNu6Nxt!K*YgGQRnn};jr@KZcQ_PgC^FUN1w zv*ez|*8XziG`&`4oq#=tFTd31$}tO#4)W=X!;)n;8DVX#`bzI0Alor90j3yUzQ`)~ zTKQD@(Kq`2BBVxoQ=&S_mmjcLd(1Ddsx1XE$d0{8&YL)np1}x*;EB%nq4*nCixZO5 z66#U5hiVpcY3L$DuWaG9eY5CZt*@6&jK=a10>}>3L#V__MSq zU?!zri1(QA^HXP2>KwesB2cM-ep`H8Ov&?*fc0?x$0d|niuYJI=cg{D)J1rY735EC z(elNVy2NZgr={i3GPXsY3d&O%$b&_9elbfaOO2VuMLPiF1F8#M@(7np+xL2oZv|c| zz!+dId7C0jJmH{cM+3EQhr4Jc(#;F96YLXTf+q(k*_TlPi05J==&~~oGCOz)P7rAf z1$aT4nFNXnFdU329nzv4Wjz}2t!x!rP2-7z#Pukac(7yT^WWKB-0hr%K&emWKw+3?e;uqXsSoeK}J)WQbV1;}F8allj4NTV3vMiyBz zkcQV(DCkQd2~ebgWgTSMXm~f1a?%}dx`RRDvw|c;Obc5B>yc|a$a)f=QEz0uazju^ zZ(=4ku^i%!^q^QD;*Ipp1p{%P;+7(_*1-CCY{Yr!4}BWN4jKUa&(GuYfgW2Eh{?=C z0Io%i)B>e)GaNVX2=Kc{ftJP!Fae}?Jr0-Ocud3uYzJEBlfYmu#B5FhXgM9W9Exz= z&R|Etzdep+{39y{b~ukGviUp%q=nv)q0NJ;_fWQ&kHMOv>BOavbT533UkQ*G#-G8K zxC&Kc^!-x|spg)50M=r1I`dTJ0$iY~9gJLgTTtO$>;}ZFsIG|2I^q6?C1}v=Z^G4l zGpfL?eTGfZ*ex2{5EgcZ^Z;(f|7WqlAixewPn2N3BPU*D_vtJ?3#5$|g_=^i&;TB1KLtUk z%-8gOa_8)j2qm91^bdEVAIz~h-xT7jd%H~U684?S{tI*Lh?@jJnP}Is= zZ`L1fuU|zlnRy{DrF_gTgJ@Ouq~gkwD%iSDW-|=vuOt~*`xh#wyxw->s=UPk>ET)u z?W6vB7u1;fXDM0I?#XPnfrEW66ivvM$%S;KR#z*}c5u2k>~R>TZI$=$3GF3c!L@(OP^9`X1Hww!GDLL zdpvGq;Tdl00kYf?0r4pkS2(*PqY28olGM10X92~ z_3`0)=!*kA7t6RG7H)qW@dI%?_rTFU1en`Ub`00XaU3vj04$=RC5$f%7fL$tMbb$s zMgH$21=YE3?nni#AjWFY%-+#cq~y-)?so|&yT zvXOC$M5agn<8iltA>_^O&$xED|_geClc3MaV=*9bD1@%{LG8RA7+6Z_ho<*N=|6 za}nq*^hfIg(yDUwPkO{{4>^s-4rlabuE0Tm{5EV%z^ipgWF8$D$^=@vs$MslVWQqb``nW zxtbo=I&g4YL&3H5?mCTKPro<7d4P_K9VNuFbrf5V5@Xp-8iOj*EoAyIiQVdCx3SwP zAp2lC=4c}Yn<%(b$Fu;S+rqZe<2D^KbUP?^HwC~`v)Mg5z<_#<5Y%jTKfMN)+JQmc zr~}*O1Q7yAY7*N`u|257#`eIJlYHq^_-%6hM4aR6KGLKJ8}3t<%jrXu&rtmLpc@|`H>&c6FFX6U@e9?{sN=%u={_qRI#Lx+@? z7FWXbmH&7Lguh|$X9@L)mugvh)Eh_a^RhF;xE+|`( zxvaX@TU=A>?Vc;!yPae5`guVF!j0hVkxS=2PAl)&{0S2&-pyOKz+3FCA>_2I*1OCv zXq!cDqfi%2FhNg5-n_&a1*|7p>uq3d!}%MWUTExbgPcwq*g*pgID$g#Fgs$vx${DD zxQ^f%3Z7+0O(b#zoVb$^JBVAy*mDLPD8mOkByan#TU3#H0yxeHjB~VE_Ep zfHdx_a`mr9;$WcYczm6Tfh?}Z-Xb6BfC1or{cr4DQWwAjysMvJg$CqG5WrKe0k*`) z0en~99OG=)afGRA@P)y?q)cD2uQ4&E-*zCf-xKCKQsI1!U&T1nEwbmw+@r9(mKfaX zJFPt$hqrUug@lZ87r*tc{M)QO&OzyX0hG?E_A;RvriCjasS&xRKYj!LMCcs>{)4dB z@@fh9tHo(WXdihSX_Y#RQitP^3E+aG@HOea)1A^aaHq)2c7}IOAB|VEfysl26$jfG z#LT;-E5OsScycIG7;r>+UusyQula)uu#aBO0{yX_Q5JrGaM%7si9VLBcMa2?<{^(>N7eLXfZq=0GCGt(2&#Cic$ zu~9;Apeh%EqY4yc17Lv6mJyjV z3{&UAI#0kA)E>i2nk z3$Z=sfKoLVYn_;H^C34?f{GV{%CZR6E(GpTre=<~b$8>knT#a`QXDFu!lq)%*J3Ra zMG_v8fCLu-T_WAxr`b#&3KwY4ZeUJiC}<=Ie1Hov&C_5Tuo#yr$e!HdUpp>TIv>@V zUS^4jU{+CvD$FkzmvhZ`7oT=3e6kx)- z&f=a25>!D(fw;zM?I@XWb%8-yfM3$fEy2A}dLDN3QnGW3@)@fX+SAjVZ#TQ3HL{$Q z1A-dmtCu*ze)khd8&8xwzi(C(f2+#*m+)ZPLq6xp>=81xME;MPzPGL&(0oElutpF&ls{Z9K#wdzO!e~QtW`8HR(8eLH3Mc zk890D&nR|SBa&wfU0g9l_k5Z?Lz$knv!nEDQav3$M4u=6=AZ2hTB}h+`Hb;XKK+*- z4%Fl1=>-LKW`A|ksjA~ZeO+U3=m2^^zI{{2$?%}lB!Ird_BrWPwX^r=7v#?vB7dHQ zMi%=(2k`PC=wv#C%AvQ~mreVGqJP&JM8@sxbISY$z5kNh_?4Y~ZD-$5^jmoJrjCA3 z!4Db()bSYmNyk3;nSy`lShgSA*{}3_N@Kq%I&0(A+ntRT>k*7gWBxtPJt7pot+|y>olmM;hA(xWA&L_sHVfMe^p6ksf*UKBpV}YWePc&TLV^WcSbPi8B3u zrz4ufEp>pRsBsOtV%#A|-tWA&i_RSepuh=!Y-bTj1k5saXm5=>4Q}vI1M9dPfVX^c zCk$&QKj7?dso-JqWGxhXJWoc)LBlDWMA;)vLL>Id1aKo3z#A6~OoBH+6iyyZmCRt1 z4H8j@^<ZOaku4bjTcwuo_Wrnw^##>um zI=^fI-gryO7ARXxb>6CF(PTkceS+J(g2O(*T6PWT;iXui=;cv&vD>6`@&p6qj!KOu z8Ia`h%A2!cNVfNb&ge)e&!zD87+Z|6!8`Dda>j$sJ_hf^I~t%b+=a21$(Mz9fmTxm zY!pBhuhU4LN?y+@co&01$WP!LvA+U9)IBM1CQHDU%4lq{qSu z2Ka)N2H4m=WdB`GPgGA1lcW{Am%(+8vByc~l}mRyW96z{PJ2iJhhh2$N;gljntWxY7$EW<+b>BHk&g8Cnu+sV3zDtcf7yod4Xh% z#Q7DM1X6)|`%{SwOhjEY%RF(*&QDm3s|Cvx9nz3!8e*%$(-9oQg2^BDIp@HjcHtw= z^nN&Uu`dO{3@7fVT4ZM!7dXhn??w2FAc;fJS%Dc)u!3xvfcuGjRkG<3r#HPCnM}}P z7VeeV%1WCFT7(ma6scC=U6-p5tdBbT_~-*uSE2;XD+MC8u*FB6Tht9urX#)vYn8sn zXUFhl#V^TLC&4`6M%M8li-KUf031QU2VO#A+2-;hfM2slmU4)+j1nNLTyT(eK(3Cy zv7|}S=^*Qjr_>DpS6xV6s%wz+NNqIT&@DyhYH&U-!-aJbfVJhgLRVm|ti-i>v1)gk z*(86vd*O6l4J3#FyCkv)kFlMEOZO^}4J|aHkW^$m9pz(Rn%&};qXd%DSWB{d#sQWF z$S57HgY4TumWfDKu8o9#LXaG`gB1Z~&gQIW+)*fNkQ7|ECf1!qxKdgShN}mLfYO>r z!psYcgFS($gU$;! z{LL~&BPG{;%Vu`o?iD5@qpC>HQp0MO0v zK^Se3k_5v5tv^9&L^i$4zsg8qj<~vI2U%YtoOHwA1&u6sEPnfqQ}mO}CwH*uOt%&P z_dLM*PgZ1)FEU&MXix`2O9wNR2eF?FS3bq?BEvvr!%o}|pzCfxZ#!|6-h-`EuLho2@NxKWGlrXXNLgUG z5u?cfoe=QddSJ{xa;ZES#cea!Bd93W-&vfdEINY|9~%$pQ#!Eyqj3l&Q;8GN*vJMp zjD9c>!w<3%MFh3u-AE`HMF4sqO*T8nM0mHdPOgG+{$1%Ruta$2eF-#-uo!)a)7~80 zqSvNl!3QyeyTD_42uH%h07Z7A*L!dn?F(+RZWxbya86pNJ;5GM1g5_Yt?h_!>X8ci z1=8&d6qWHH03hXlJPY=KqMA4;NlA`0`VKg|G{b%mH#yfhgV5du&pO`<3ZM+Xy8N?p z5Le1wGXEz%PF{W}I!cav0c4ZYI#9D~l~V^nM2>Kxa0qsTo!w|>>+Ed3om@HycC!OX zx9C{aw^9r?Rl*f)*1n1`j{pvdW99 z<|~uS+Kxnmotw$ zqZ77+t)f`y$29gFMoD9T0`*5@&tm}OHOHMDEx7R&?FEzy1FFI=HokJ)c_~kPi5_8r zT4OK!i4$YlI0I{O5(v98CB}%7zE_-KLtpV*SOA(u1dBNa?$@D!v<;98LA4moh7#%G ztv0Fm%7Vf)_O3}kna18yFq^KdArNijr0o8FNVFwDKJ8bfUYZ!zwAEA5}mHdAVdQ};&JvZar6}-TrhB2PRRX_F6GB0NM{ z567k>pe>T-0{c5(J&~JJh9?ZQ{~dv0!>~e!*8;g1SqoYPc@1qNbqu8zAQjVj{5u0_#>lsp+16(Q9oCz+6H+|V-iZRgZJGw?D--6*E7z)WnS-k{>42BR1sSb>etrw?$(k@jgg#vo7r z^0spps3;wY*b?dLBW6) zq>h#eeKo7cXkuAJ!_S6_W9Tt;A(9ex*d3b#I&)!^xw|q??J?Y-0rdcw0qM$V^-L!{ z$X+>N?l1_MXOi+7K#mv!&jQ(y{zl1@P9w%wTvJ{KcH!`v;)P`9s5L+KJhMlw_|IS*q_6^wO!Q&=9L!5> zUPK@$Q9YE5B6hq@?u-O#M(b!yiT})ri zqZ;PZrzI4WYHR`hE+hsxWJ}{&nU2X`0?L)5UsX2qr};3M^1U;9%zxU|f6k+>Zi`1P zKe~x`OphW0!tk;h#mwS1P`E>>7Fk;-_dZ2EpM5 z@S%(4T(@ZN0TP7N8!1>vg{?P$LqVN&i2RNlQQ7}t*Z*_o`7P%%&rimRD8(8Nx3vP9*p>3zdqN@Hc1LJC`CSrR)Zer_G`%gBc}5!?azFcAvFOj?r*C*DBSYTZl_zu! z#Y!S5rl7QPVcjB#0s5Z{>xygeIl0<1ljMXkqJ#V@%^oSO+d{K_DcHj)IF#DskDMEH z#Nh;78!XYz2vhO&Z#eEy)a*hNNMmRg9s}-{sh4BxO2gn3_1K5yl z6HfbcIqt-5cL7GtfxeCn%ynei!D`dpxVa3IbrDLJEod3UR|v~dJd1F!C$z-vECS&+ z*4b@$TX(W#;QJA%*=++)MRCcexwV0AJ8{z!RK^&}=u@ot<~(a`KBoH#dqFFI!hoC2enIQHN&5AaqGFl&1PjpzkTtT%=v z2Ty%)r}kyTeYj@F;=-MaYjy!B{WW;K3`2e?F2!rrb=w=)?QkG)Bf%ga1F(3k8ew9* z_r&E%%<~YWkH=Fl+-t-O>5Z5j6S@)=5sHh^_Rj>xOtYXK__QaM8W7tA@G1KtqXn%4 zT8yn`c87lB4{sD|9y|4sOUlQ?`1SVFAb?&a<@WKtmj1jSw|xBu!K z2Q?>yt)ghGbe?kFmAMA+%vI>Z)!2Azu{W;4Lbw(H_;r}Y>(PnzfKzS+K)VjG&rOZ5 zo^s~!QMaN^x1&>=@ZBBY-au0gM2?QYa#2bDxmdifymzu zL>_vGnA(T2f_BTo(?BmDm7kn;4n*#QLN!(80cpK zl|3)VSdBaQWAY=bF)hFk`nq~zyKX4HTZpo;-#FK1oUlaB!u-ua$#Vf876Y-KCnq|L z{(OO4=P(BFg>s?}Ea*drkD6#vF7KeH3Nyo3IxRs4I+J0<21U% z9@kE%(KXP53F-IWdJ1UKse#IVtV9bEWw>F4`vBocKFH4VNFzI+g25q!wj7xF#Z^hL zoT~F76bz+cn8t_ed;}j!52MH`>>vt8(<4Ok7V!cnAIry4Fka&mbf^Nuu4N&gOabg# zcHmPrK277(A=5!M7SXS728A>2{6hMjMdi=d_#A+0q{=#1>DzwGKV3E9r3!1y@nquBHaT zp6xXnZ0q9rI-QN>*F&M2-x!hy(3k${d>vnpz{f!W!l+THH&dOrP_V(yZ?*H=?EH2+ zmv(-K4l@>;>||AU1PAd)=bNcfTbz6=b!wXvBCFdqzJq@6hDlvYyhr2r+F?x>60G;x zIY>S_e}IYx3vUqzv1c_07jiN8JxoKoo09j?35tK8&$aWtb~30t76x_Ee&}TAWKj1a z-k@=ie=g&L;JTE92DF&ofH}FCssknHO8z*dfD*KtKS{Ae6da~cj_CX;nASz`4AuB7 z#g6JcZ5^!ZVl1Ac+5nG_B@??Hl!;wXv-k^k{udhI7d8G;y!YDVwzPH zSFZHdl~t71daEuftx=*f6%elhiw%6Uy3!K!GjDC##id!^QCSEe6GH+uWxh&cp+P3F z4y?9XZ})B$rld?YYFC11#ax^4j1L9V1C71*I zi74!!Rq0(`wXD3vI}eP#YIJG^#0cw3A;{Cco43XS;HUAV%Xm%1!`|J}W#nX~cJNBS zmpdHrs>AZQ+jz~{T4N;aT+t*sZjaGhz8PbTOmLPL*VaKHVlu`AD8OjI{M0z5o6?vb zYlK>JU&i)V=9-UV>tTOu{IA$+*iven&IQp6%N>gm>kvy1ayJ@(1R9IAj5Q z@mOQ`WMiW>7UEe3PU(8WhW8rm5sK|+^<|6OkHXr$Rc<)0b+bN+?N<@}5Ro17R~nh|mnOtZa~FWkVPu)DU3^*k5=bLxi&z4H3a%1vAnR zE&(%~(I7htHw7^w)(~+5c5XWx^L@XHb_Qz_@tR05VBO|JO(Yp2S-@0hifC`}G%#aD z2llKXIznredB#`3z$Z~+)j|Rtwr-KRNjS^)?-^RV!JVQOF(hi|VIP6CSA+HGRhuEp zi`6)`bYOAi008D0-u(G>%ZkepH?q7F;6$`+MQLrWR}-)~nku@0yXMVCo4WEZ$S!L) zL!^mxO=QU8y;=-LBa^?Q^dRF6kww!U)-2gv0Jb<<&(F&0RHL7zNo321Q;nGR#G9tU zKv~^I4@2}6y$sP?u9V4F$M!I z3dC4LjN>p`Y8B&yx>HeN0{;y3&?%KmDyx=P8e$^Io^wA4&1vl0)woCSLit|0ad#`) zXzk{(UUF`g#VgP3&^t-z3!;-u&IH^sS>7KSTHBbOWmNM3wUp10M=HXyRqMnRZaPRtKWm1}OWL3nvY zWT@;Ls;66*7uQtElfzvpGOL@>aYJ-^w4A$($4K}6k#UVp-Hef3+IkqzTP+o3mGUn= zj7NQdGjO@sfhJ)41Jc}rC(?o5ieKWeZ^JLAO^$bWtF)aejcBR&;N88o0QByw1(e5W zWD(MrEmC(;>O**slf|D(?C^W=hXmhl{NlJdKV=_Y;RrfE;ZeN8v2=by129OOOQ>E$ zBF;602k}$~I2?Ea3`>&CwoB{>+ZnzMt!dHVZ0(23nTY89a7Y=+e3de|%zqP#Z^tS|!BiiiZt~1VU|GV8Vmp zo(%G=_aL;B8d>|XmVr^M15u+JP0l+;FEt)z!1h^JVsfVunc8rryI`^~GuIYu5FyHD zlXwBe%r@m}2U!-1%FeYPWZjC$Fkg4jwtXI069wD5r;^v3Mo+y>VmI}PJBZk=3dk{u z-F-GGVmFbX`)*>2f_;H{^^ylR)<9@(V*LchpaW>&#xXX;6d>rI3ln>kO2+pFY&7k= z4J5+2590D3Bf}F4B__c(z)+*V9HO7+gN&=b8%!S$K@W*}3fbPFIiWBFXgtb>!FZoL z6gF^x)>|$6*)YmD7`6oQGaS|dJ)o+OpohL2VMovKgzaY|iMp<0qfmm6jXVldHz;b< zQRea&sT27gtXYUJ;?ptH>VN;C{&%tv;-5ZOfjLiO!TN7t;~Lrc+>pTNHV-pw-yL8R z`smg~TY0o%1zT;4)*fJm>&g$X$vFm*FsAr6iUo?8F_lK6iA{rofPtDEi*_=fClt`Z zbaObvnyU}29++cHpscihW+3jGiNKA9C%P^~%wHTm&Z5V#N7+b{+^`-X3p5F?IrP%k z>aDp3=hpKVVZs%hk7A5vSQB)>u%G9{sb;tbt6nXQr4&<3qa-)N6VU|SFwFac+(?Qq zr1+v-mq+t}`cg(+SezS$scn9W_Cy_Hy+Ht4T;y8fiEL!$xl!hWtAZY)>03{fxeDk@ z51f|Lim>Fk-EI%unqsVWuunZMH`E~fqZH$bIYtDc7yO$jH`eWj{A!##F8IL^d;p@2 z{{x@L<56Fvrg>sK9t;mQMkUP3cw#-CCRRmKAIQ&PIuTW`i3544(F6CWsCx^WjZ88A zOy;|sI8T&2?f_fbz-rPwu_&&#fz{=rlH7Klc2DNSTXGWI3GVnEEZNh}ozOGKm*`HU zr5PRgYE1&FI04~UPZTDK%30&a8(01B*TZ;W49><0(QH}it#>IKjIGX-<(N{pS`RA_ z^PeYb5!Ro%gVx(hTCf-6^t%MhO>1J8`T`THrdge1AJT-YiCuu{)@Yjj6BvPMXnu-3 z$S%Wyaye$%?-wgt@+Yg5_r8n#vf-T^V~Z(t3+ z2l~VNU=yAIo%-(}G=GX~@-tjDpW`<80(Kd{0>AfbkiWj+(CX&l><8{;Kk`nnxR}NM z!TYmc_z(c*Q(<)xTZ3N)TPe4~j@+G)o4k($uY~^fW84?UkHFgEThOpR0l~&kc?_&C z#saeT0Pal?(5Dt|SXfMgb;T6kUUcRiV0p2V7|v4xGj$bnU|q4Cr;9gXS@9iMRs4we zw%B=&C7SoKcwtyEi|1PU!?8JOb;Af8qs}H~Co02Yj66E4=@KPqLihg;ot#79(I~u^pdg?aZfJ^I&OlJbtI} znbzrimbI7!2SOYj{wo?Ie;0D@$Mw=i~Igr-kF4c0Z{DaxvCP4-N_48 zz7SE4bwfpmS&o31_Xc8QfvNyP3-vH7o(Ev%EmW6iC1Uv7SX=F^*`Tfe4XN?g9?aJP z#egJjjQ~USUG+(4(DdFzMvvttH0pg67-QLv1M~z=yI9LbXzWSkb7PJR*$03bBQet> zz}eivT$t|*7*sb{6lOgge9wAi^%AQY(*K*4gY*cC-sK@r3f>r+t@5GyJuHthY`_4(|+ z=Ti~M|8r(;V+!_(8KDm-v=l2Xw2x27 z8(?mSA4w2p9m1C)q7~w?C_ELLk+{&cv%-_nmMDcxjE8#)+yQ;LHr$3z0p`ef_&od# zeTXEJ<&*+=@H#k84V;^pcyx|wHSk5Xp|^z< zybZe8cB>8ng=yO~uER8{Z9qba2GjsH1r10j(SRCXwn4M$2)?sztMNuGXbsXOT7yuH zpl%xE_n<-=T(qDXI;FB2tQk^`IQ1YHNt853Nog)~rOLDTYH9dau24voyGj7B9e)qx%2c$7yn6d1Ra(1 z-OV4kztp+5eTFMq@UP#LM7Cw5SzO(STfuK_@9M_RFz2_p>TA0tO93wbUvgn67-1X) z#~{6g8Hz53x~4Tmg+n51rj~fIXNpi zE4)oLmv`N)e|n+UGBPB%8{(H1dJW@pG7Iqb)`ER@4ZvyFg1Na4JzgKo&Ff)` zZbY-hSJU-o%nNRUo4N()-pyd|-6Gop0<|c@uspk5CZlgs8KT&U)ks3Jz{=_L8oPEI z39*Mipqw~M_xUXSpf_{mE72_oC9%X8>z0IER_U3#6`_dCSjdJXL77da740CYBMXm= z5E*ZRNhH6J8Ss@@7C08`cC2?vym?yXfvu&aAUxv}c`$yX8p{uevP}vC zp{O+BHq|blM#~C!5a>zy-KyH~WJuzP{B99CxV9B&z9`z;YXd^HwBjDCL>jUOU(t_J z`floQ4`bzS9H6F=iWM=Diq+KErpy*Eg>__V+S$v3S4W>f z>wz*Eut1=%lrX~*4GF3)-%;wa#2IV^2XPMO0@slsLQj*BB|@7Ngf$1`aGAQ+Y*CHd z*ihm$!0GckIXv%EsTu1FlHzo-{90o+O99UlsE&QAcIDy1B}%AhIh8;thbvq7@_bQF z4qCWCwm){;h<*x5&C}@1Kcm{~y=s8or$+1js7bxZIC_Z_)63ZA9{{xTRRAPkQbA@XekU9yeg*PLHUqBr;t4)BK9$sK^|en8uN$YJ3lRiED`=m<22 zGd)ayZmYkP5t@P+Fc@s;sG|Ye6;iB~Y63ZRfF^0n>=bg!Mdnx!f`b{!H&3o=h?Bux zJYXw!GStxl8iLq3l$;P81a)^p0v6C2nw=4CE89v%u(~r^49hDRcfq{IVMbjhwY`d= zV%=CDEOB&CvN5_BJRkwFk**QFURe{OY7?bt!tV|I&eki{Ka!Hs96PnS-VK5JJtu=7 zl9CMuS;icT=hwztSf@O9kk`}^d#uyKk$IJ3%bVN2{pK~DSg1Pr2QEy{^w-A0#A>%E zGcCUV@WYSs;r0gk;q`hr_~^+{6eA;gl>Cl%5k0CTJzQ?ag4(6WNeCfiOiz$YAcl-- zbirZ>A_0b-DvwWg5kWG4h6D8~_sAhL^$ZCWC4^%w(j|T-+{{d*k$Sc+mV4B@GW1+Y zHxJm+2%<>6Krf6SfMlpImYXH=A*7Hok(VHVY$;_%2H6rBB$pKtjlFwIq>%ayy-G4# zEuk~zg|l3dJa&+>cF^Yli;3JZF4D(Lq>o(AkLnBbg_80jxgdQUq%Tg}-?t(VJ&WbGq+B!o}T3-qQaM>?dB zF}*nw*EdDTd9q{8RZU0_Gzc0TZMD^bTFP_AH9MPXd#Chie zoOklw&t3h6i>PUITxa@sEj5k&)K3t%{m!!w$<_-}tBhtc^ zMGIFTZ7i{Z&A^y%e(~(UsQ)y?DD#(N*S};Lg26yjekN-0*aTYHWzmY|ONf|1t7zfE zRptFhd9OM8AJ$=H`IvEDQxkDTNK?G5z5jhbr@r5Cs^u#a)#T4&C?V!x=ADZet=z;wJXAxmgQHR?0Gf6)!(`Ldr$wMe-!EDeJC8S(>a)O&<^Rxwu683G_PsfZR!>@ z=ry|VcM=kDpQnFTboPHdwM~N<_nST_lD;$}wu#vqmC zF#01fdg@2NXbq0pAI>zf4!D5z@Bm^lPvABopv!%LYRj(x3&tz zq`>Y;h*O7G6Q|OYR>nzlnKZ)|`%i#e5rXOgdZ0CiwSrDY2(nI-6^J=?JJ1V}bt3=F zMn@5Ml#TsKr+6Kl&yn;BE<_hHMP`_T5Y*HciE0B0H8eF{D*;toJk!`T5#gunnr5D9 zZd!OcU$^zYJjLstY+9ODB8jY7C9fNa+=q8si%@m9gxW~xNeSgk=rIYkmC(}?IzdA4 z20YWw0JHdtJZmq{#K)#cB(3#rridk7gIE`#B*R+jUtqkMy<(^vQNpPAuZ)n}-|0poCb zl*2vh6Un(OA`9m;nmkCMALYUP#erS1l}5T|tcPb>mkC9R@n)F6uE@)eOfVBYGs#R2 z@DG13@_zB1k67Ryn-)t7HE(&+RR812UgKm`2@;kX6>n$MvXd$Q*vZsXMECtrsX*yd ztCXYex>l`49sk>FtV=b3Rw)*Tw}O;4XoW?}EV7`A_NzJn?RCG=99?U}Q|Va^>&!2a zwXSMH7FN#FzZtzKxJYnAYxG{XxQyrxNapZV$qxJGZvb}GZA>+ z3Tby+i9pztBrMn}V+HE)R;WETN)jd-ZGEtF#N~YD4+%HMu4^*aMt{(Fdq92sJ z0!e6Pv8olJOmaZjDU;%ucX@4>#0J9A%GhdOe?(#*Rq;d#nK;Ln@Nr4=L}dY)WydGk zBT1gBOv0o)KFKqZWN&2>;nY=Y3Ng8*tj|fB{gr8i&uL(vLhi!Ttln&-dO1kNOG0fk zrK@KbdvehJJ{E!$NhR!)((@<+r+ z{IG=`AMpvJNgVZwDYdwa{DSM3+%4tHa_*@vpU&{lUgWii|AWVYp=EoH2sn{JpD|rc z@G6%sdcp>YLZ$4v zgfcC!mQ|YNx+0wjS+=UpOP@u~a>#oF9zczK$`|*Mc#p(NJ5yxAS>>vhc)hE=Pt|Ij z3G?|;o`Y41!tJC|)gqA!bg)_@Bs!dko*c@zNl?43hr|z;E!#zQR38VGarg!eHmZ#6 zsv()>0-D)~q>Ycq6w;8qztZH?HwO$OiO z6K&-^CjhXNCb14KIMljvl$g^n(W!^+Kx34mJ7N7?2+wT1Iv4rO`EGdT*r0hd}j?QeAEFLv1c z%3V#B^as*OSN-OygH4+LrgCEaPzjeEKj>IJioE5Zd7-rYPAiRTw^N;1tuKZlv2TxA zdI##<(HhNTSl&sDp~Y&PM!{?xHy2ho-Ibqi1xa~$<3vnXP!8T_l2aa6J%r`pAT-Yx zMnf+PspDe)9Dv5{gHzN8iE-%Iwp+_7^csfLI)?mpD0Z($1K&ribv-=ejc8D8LO^i? zYPL7R7TXMq|0cA~H`2&AV~w%RHl45?hQ&E%i(AwrlGd`!b>S3Tm}s%O94!>BDENHE z9E%~0_{=z1?jc&c1D0UYo*_OtKv0NjFKOAj!UgV)61jG1T31J0JdatQ72WY@05KJ` zFMDoS#f5hw4&f3FT>H=4x!TAcE^Uq(wQci!5qC?QTh>{%Mi<;wGy>K#-1)iGw!O(faB9Rx&}5J#l>lMRJ^hj;vf)%ylfYvf7BYXJp`(KaY~1NLSXbKeUv2X z1HC8Ogb|w%;XXqtr79F6LNB%_4TIxolR8Py|1NZRrBG zrK{P1Zh%s|88%=k+s*w@Xgk?bo`z=IkKW4x_KtT{{ApIw?JSb}SdN}!DD0;jU$o;x z4Eg5bEk~fIEfkWD5sL7E`7ltnuu@$BoF%5%teID1>YGj|g-;IDHIQ5g8CW0tJz=fT z!-)aaNc}_Cv;!(%y{|LXzu=Bjo44%P5-j>>?AQuXvpsffg{fbe9a~9uY&BA$3LYVR zuw(1!;q|*(mkC=-;A4Uzro|<%M>D=AcKNN#)nGug1Oa%6MSVDl6>MmBm<}739o~+o z&xgcdvcz-Z8g5_-tt6ElytZyuAf=^+?>e^U;z5lkT#>-vPmfakSDml3kPqgj;+N-xWz`kGxfguV8f zAcE7*QO1u*=fV_mi_RtMpv&@wzjl)NHKEs73lLB=W;tl$>ZbfJ4D>%#3$1@sy^#gh zru#TBCAzPeRYv$vyLYQelk?(qPq~_GJ)WTrGnHmP8Q^DWezakx@pDSz7VVem+|Eec z&OpnB+nI^mnPs>Kdq~Yr+|Djj#oW$G+|DUebGe}_z%K|eQWg>kO!K0^ znbcy@3#%>ce9hciS`fnf7```4E4~mLqA1E82|x$w*IsN;sF~9tUqkqQ1K03d2LE?# zVBcd{`vXhxkJzpLgyr17+46p7oBM^y|0|RHcSy=ZVmKSPmAC^IUkf@S#L{0Mr-m(Q zCt4}dV;)ENRyvP1ya+y6uxbbEa9o?35h+f>yU3Ecx}^u1c6I z%iG??4gdW0E4(`K6{RY3yIRSpJ{>))AasThJB}rG0*)^yZCKDP*(O@Ep0r1_+KDxw z2WyE`A=ehSXVn1fX-A9DP(Aet09+V5)$y3tG$}cWqH)v>ie_4=rmjqA-7v3p2vCt# zGM}CH!tW2YFL3kPfQiRbf7D7ZGroG0YGBvaGa-Z^ZL*U<0nd&I86)#C+ufKx5R zhwH4)DOpkYxLGM1)g%eEl=t%TE2leNO2wm8>x^?Mr*qsc*D0ISB{pR?8-B1doJ$HC zjim9T(q_9E=b@N$T-N84%4U7R(aDoDF0{#89h3h>B(wP+lRoLl@)39stBvzJT?esR zHctKOA@j*m&6wP+nX8?2E&x+aP;qL?3f>I6h~~HtYoQ+1t<*QjuX1#L)zU#zSN0R~ z(Dn=t`iW47U>zVN>p8=P5bHTZ5*;SQ5#J*i=i}+fBal;3geZc7Evz=p)Io#=TUc#c zqf673P%`#i&+2Y`D2jfqBUn0EHyQ~&A!~kjyNuW;x{)j(wY6@Q z*A~wr!UPBg%V5px{HN50)){MPOdR4K-K`hXme9d%GA>DUf?cU?*S5~M6osPBAx6$p z|Bf@f-1y~qgB>fwEYXiSHXL+PI)kvaMC!4ns7!L>2!ODpKhiCMGrjiAhK?YKc7hP- z!d}@G&(q!TLf;+byPn8~dZ}}DZ)8J#F#;KAdqIS803>aw>;|=gM7A3U^=7q}<#+?V zBHd7cw4)EtLaL9Npk-kRXflL1?f+1@th?PiV$7-Gi3F_#b#3f)1ZvriU^}?33>xGr zX&n6AGD72OEka6yw2{;)INHcTUFo6KW_4awG4pJZxTrkcp8^Y44Te_Yv-A0=EHbrQ zXIxvR*7eLWTk#r+mPc!cF1g}Jvsu$qJu0qTJ-XU=YFB-ywjN}g1N9AC^l%cr4Dtzx zu_m&(O|nH1!$Pu36h+opki=?aAnrP;>g?IZra@u5ri$%U8y-{*cPjruwNjQ$UG03> zfqAfmCK}3fqlI`EO4?z2fq+VnG-kU$RlVCMThB)1^2@Qnc0T(Z`^I-Lg)UFF5~>XU@k=nQLrgPY zy?~n;K{$R%E-%YPkQU|lRRO$zO)jrnq(ym#fZ+`RT3n;vk=u90h(;k_NSAy*kYBvb zq^l1j>Z2$-=Eo8BiKP29B4CSa)aMcPg~Wd;NQ?2WT!C6_Ac&6*)Yq>1CNP&%-wF)E zcTu#kzL(1nauE4Rp8ZR1|1G!wmSX+eRX;}rc@gy_iT+hWzeQx_`CYz#D9UF z0qvk0Ms%+HHj*;G1I-oDO>kALo67q%^CI0WqMJu_3%X0UbagAfC~Y=d=S9U0vAmn_ zYPjboFvwwc4_OSCu^;wQCB-GKZdbnfGVepJPb@$C3U9BrzzTl9tGw_22l|ls>xsSM z;?GH=q0)iw@yA~6weXvsRs;U})n5O)t!QUgcXV|pT6e%1v%t}rzhp6=?CjTB>*a?; zM7wUr6J7m>UQX%hzdRM!GjFc-YB>O;`QNYgZjAvCVx5KvtiTl(FQ_T#ARfo%`#jx6 zcje0-+f9L>5M1Kv?z)GkdomYBOsG+J!?j-flX~ku9^OR@k^D}}^<=GtIh&i`D|h7h zaihkM>nYd-D~0_(wPeY%S1hSgE=VoIlndU}{1?un0ETE^3(^k@%nv12_wj;ek8q;7nwB*Vqe1U=EiKPs*g zYUhqE96ko9{$;aEa!(KP5^Fn3SKU0!6G5-5PxkaQjSGULwj#j-_Td^m-P1FqU5fNf z4>!fLX?7_=vG@UM&_J{Gf;KrvK023VA|CSeJU!pjrvhQUwPnp#VR>zVfB!nKMeG{A zQ1Zmt0{C72s27|%{`YS>sc8ZMAswJ?J(u`DKJT>g2VCcMh%A)~pN1cobFcGiMV9G) z9{v;u`!{jtEY~YU6p-b=a2=*nSs_&Tr90r1uT_+8LN+dY+;n&D}L$F5%O ziN8cNK=nBR3g)fryGMJA~bE)KDlL*=!^C6L>+DEPol4u#!$7gVLRVjtzq?tt5a$QF`hf+rWmd#$n z-q&%5|4Oa}T%p&naZiJHu%0Ku7MX>Wx>!LO85qI)9QYz~(8M>CzRBA>M^tVANX}@S z(F8oo0vAG~8FnQ6G{;j89&vWzfm5M`1IMQ2MBtc+X(iS#&>2Fr@Gg6KnwZ|Cb6P`p zz0KqdjtFf9==uZ;`B*dKME}GsUfsA9IB=IxLIIa^7+XOPu4J)4UFFd+oj5gLN|$V= z2kwOn`4CO`Fpc~ajr=?t&Pz1)tE6~`BiaXe-vzwiR#re89_H}AiQSt$7xFu(wuD5= z!K~y6bklT84P|mV+Db+apFRwmW*cqSiG%wsWELjznXtQWV-Ve|7Kp@y*1v;dXN#-8 zJh1F6K-=Ai(f9!$&{g;5(zwh{uIv1UTfN%x_QEl)gW*r2K|tc}Sf*-bbmD^TK)LEX z0<7;Y`OZ#!5s7!CZgQB~B`EhBX*EK~mY#qGmL#Ve+or;~>?wKl3i5!nRa)_qoOt_4 z7m!_Ha1x|}?j&~B-OCTLa@gk3r3}BM#n)=>o|?a0a1V|vGx$xv|+q93v4RpBYn3Awo2G3 z`I~O`n#Kpf8A_7&CX(?v(855%ZsIUHq+Fd;sy0Gi|5+lZdZOijnrNuxJB*x$my0D5 znGHKO-7NdbAR#$cC2Wd=0!n84j!fvMQPO*(D@VYX$9YQiq?VP{t3&midxlAbb-&yp z2#xo*ZsSZnfmeeE6N60Pe@$ZQwLWU@Wnj1@$(VUSs>o;~*_6;dw6U^Gr?GUGOu_&{ zrxQmD*-w&wdcN26m%l{XCMg;K*_+MdZjr56)JL`_yH@d_!G) z?1|-~%k|ds!?$|>akTFb8=YF;&$!d;o4komxPi0CjsCPdy#bY{nCGv#_5L|6nA9x- z?6h;A%BCEYAH?kp@>Zt2e9#QkQAMo;Z!+B^tGSV1Bwnygz#A0zFFgxf8d)t3*yVukGhVl{N#~$=nJ7CxPmp$km za6m;9OZyhk&I{FTR!{2$oa(uH9=>MuA~N;_z{S%`p^cBGA9>s+URvQFF?J7^7rO)>CIg%=_?hLeq`tAUrXR|)n)92~)J@gw%aUtrb zbDVmh(_f_5c=}>gCsnNN%wiO_rVC!d?6#i1RIfok+ID8qB2QnYFZUmKETxVgDf3Q> zUBNqQv%b>PSE&ttpX*Wu0)MlpZA|O%|LY zR_--Vy3W(<(HxdjhkxV7Xd@cy@BWi%v6}wW!Y>r0(?e4boT(Jbk0y zBK6r&apd8sy51YA)likG{<+WS& zZJxeem%926Pv0r6eiyY!-;&nF!ON}h@AQT_m4~-p)edj+p}ReOk3P-Q_v$sS{+p-o z(<@zlzo#G2+XFW{`a%7W$7P47%jo@PySx$3=LA;n@=naytjj&UQ@)5gr>A!VXS8dV zm)qbGy}{FuN=G~@45j6aK`Q(%SFT1>c&K?@8=fmFpSx@Pw1MdU+84s=VPd&X) zKN}o>@Xh*qNIz$R6v|7V02-m1c22T*gbOV#E?$5$oM;<=@E-5d6jU7LD2comm$>Dj z`amcMOrbp;mH)WMdqc<1Vv!dMD8?|0{&{xkH_&CldFKLtHI(v2#I3P$7uz^FZ(PE& zOG^|^AxrEzL{QGPjg>=<5W>Xb6mklO43Y%rj19*m$s>(lmF9YAXND0Ul3n9Qe&vk9 zJmb2>U-FEX1O8j321aKRb%EZjJd~tBa^J#TvL&>6fp7t3ls(VetwL;`VK&dCVCUS* z(_rTu%Jwv@T0Wj7&!q@=KsDHWlDo5yrm#KFDUa^;wi=9}$8fsoT&~6nIc*86Gv#;u z6RH3OfZ$20{7&FWDa)9+2gQg$PA?PX%mckOX`||7UlLn{NOpLqnrwyHfaQ^3N_G<5 z>H_2(ZXoACLV!>DR(VFAcz4xfNIHZ)sW`Pm2e~UNfu{7?li_P5wwm} ztW3?`q)!PBbHy9=I0&XJNn5;8y)ChGHmO!sA4}wwF_$bPlF~?4lwe-y9wD`WP~WII zK*p?&3<5j9-F_rhr@FJt)B+M`EUf(aqJregA|lm0QbgL!7W7YFK}3`trEHs2i{r|) zSjt3XwKA2e=WMdLv}k47mq^$U^M{&^F$>; zz>8G;WKPkiaEhMJ+%AIBoXHF;=0rD#Eax#~=0mieO6H5nej(z}MG#kKa8h2STcCC@ z0Aa{@EWT!|bM!J5Xa71^uK`}`Qoy#ZR~PD1gd}%k4Yo^Np`TS(>aP)D{jAoR5SA8M z>L$}PuC|%}>K0S1ZZ!*4sX0&GVJ=s9n`_j)$Qu4;?os!dht&P%G4+6XT|H>NQV*H$ z)eiHkDl><1LljawoqB4w(?~tyv{H{bZPeq=iRwwGhuY(eP|rBi)IO(3?RSdR^UiYh zq61sNxm&&LJgN>jFP_$%r)=V$f0^NV^bq}AJ@0`+cak@_HXy83(Q2K70l`a0ZReH-qfz6;M(KZa*RnzC9Umu*1v=5jo`8+yMb8aVf`a)vm= z41ziEH`dK>pg8fV#JVibeIKx~yW{lIc7kD=GG<>+)?%0}ufX=DTOMSYc4^?ooU%6X zY#CX~0Xmt6cI=reOtVLkJ^u~CR}HK!6_?|JunG!twrE!~nc^ae~`AA?^Z zN3OU_vyMmGXfAilJ&Qc-7({<|%!>)cH*KFza;teA;a*--!BP!kQG z%-KYCl+~ecIHT-U4u-;`6NM>t9uJCY?lBK@cG*uWJkJmvEE1!jmM;(r>hWS#JzlD+ z$IDgqAXWt*!-gpF3DTj7p~$$|VeB2OTlv?1SN*W5tP$;l&1tHxCF%`Hu6kW!`Fn%^ zm3HIm&EHgR1ycUx$~f`~G7t_#v*f;D-&fEhp(F8!IRfKz%2lt`IHUlme5XzYed|^x za78vEu`q)A@%BMA*dkQFcSr=|@Au*F5GI%E{og=dHH~nkj0a>X&+klx-_?@e)!5&d z(jmB3e-CylP!F)mqhL*7Dy(45UMb?}U}JDYY(%1A#d34{4waDdZzXZC5gugZ{9!l3 zz}T-zqU*?vE{X5t3(|B*Wh)el9aMtCD+h0cuKLJTA6F1r`II(DJeA_%p)gUreiTlM zmqIbl!0d08Va&*Jb1PR{47Tg24)leCVkGu;)K%DmKV$ewju2gm9J}%>TYOY<+{H?B zT!tdU4p-aYqltPUW~$1i+R-?)Q=R#s>MX?ylwE_9akqh#Qbdj-Dm{l^k>>U1SN>hc z`EotNyv>}(ZaUU3to-)_UQ>>U$~xp2*Q3>?*SWmn`nflvXKr!B*S_MVxufO|nLVg@ zv0t<;k`-Sp?!~&gs+%+lhqo-n$*sHUk-~wnR|@R3K5{9n^faA9Q3l9mpd=k6A;!%R zIsA5&%SjP6Gzyu6?NOQ<;aaqC&IAE{Xj$XM7|bBpP_^dIE*Up3t!R1Svf{$PW7oK% z1^(#UQN$nqrjzVXTTo+cB(ij_6;t?Id&XM&Umc3&cp)+PAy27>f75xouD`Es8j{3n zRa^JYsE+-Khqmb{e$f}{HT@^9 zNlnl3SR!X6oIcO;;AIqh4C6W;8`vyygHd}fniDL~u7WTJ*4$$kBmE*jHwV+2>ecWc zI5oYV|3~YTh`+mTN}YAD-I?X5Z_KD^oR90czt&4_>;K?}n)>~pPR;b2 zy^>nnpK)(SivRtIp|F4XdrpH|A;D#|`uMbaq!Np9-Dw|o_itNHv#x$DwUdubBgOyp zT~1CEAvMm%k;TZ6VQ8fIgfgTR7_0T{(;S|Q&)o(*X-H@f!!*S2P#9Bz17_fT0rO&6 zfG3=UHwb`zF^brz8W4yGk2rY*b18(n8(2~)0P2)hd?=jK&@Sb{vD%?xGB+GbB9kDA zqPz!O!aFL>ysz4r4^&U{p*qQY1p7TOT5SVssxfPbLphuBUo%_6p{$gxNFkC3f!cuW zPdG~!7ntI%%Ezg&*le@3HX))N#-db6R)OdFCc=9)N6N$+l4>|I)J@z-dGi3EiG^lR z(AJ^`0J}Sll`x$e*T?`^riP85ViW8Xt{p0YnUjaxjI3*jm*gcHL-I=Kd*$*y(S<_6 z@lzEuU#L3fOV!x?Lp6oSm~4Jjv&~Po!lDc{f^KP#KCN`boT_ThfydGzQBBkun;udf z(W4@fSlk+pGA;Ryk{}C7a0?YV+TXwj_jg%;a#)q;zv|Tq>3#mdH@(tE&w-t>pQ1dk znwuB!-}$2IYhF^L%*$%JIiMDsSN+ttyyc|6;4N=tN@4*zf9ler@(!hd=6lZ-LRB{72vSCReUj)8A=)*4mSmT8oQy(F>?tty2BrAD|q7Jz~0vxh6F# zmQK{l)QFf2`K=i-qP%IcF}bNDmu$Jzr5B&V(AAiFa>+^ReSjw5pWMM2 zGp2!S8nO@uFXqaVMy_cbRds_W@g}Zm8ddd!yJjqvCMK8WQGsHVl35s4bIc+s{Nfa| zL>g|1G#pmHiwwZS#w?Ri32(*CatW@G%Sy@Rbh(@%w;2DB<>#SwFfeC1Lp<7KY7JVmWBSIFf`5gy4uZrQXV5&RITqBjaHfq+H>*Uq-a@mk#d}+&B=6Z?PD3?t#Cf3V%yumd$V)1P@%jG6% zpe?T18ZkFV5l(K4m|O6^ZKg`{TU~RT{NC=GQb~MAl;*h;n)t4$y3^e4ntP(0MedcG zzscacFKX^L4@As%`F${A9+KZ35mP3=munt&&F-k$EmP@{sCqOQ z&yPmUV+Q15W1f)9ldjo=YgBVXpa5f@N-^;X=2mIRr=#W>vsW5zpS<&IvU$$HLtkW` zm+|;Q#JngsFQu55%>hK3<`oIODxufp^158!kjtBLL49YDd0TQrujFC#u3X-e+xH{p z19@|O#Qa@;Ka5ArM-lUJ#C#GlpUN<~SU&$5SWGe&7n#rH@`YT!l=uH3IlJCC+cRSrr#aI6UUKDh-P)d5=vq;Ij-wO zTnHSoZ%(yj4Ahud;w@QL{`kipBk8e@vF!N%alpn}Na7;FOcn-P?vVas!fL^g`-~ct zc-pe0Rc>JIYx$Gb9y;+}Tk9yS%1Ia+9<%3{h{bVk)!V_VsLGIboS0IVShwrBLl+gT z%AHrV5>Vybk`;4c=L))VFfS7JR|w+Keglb*LI5K z#}`(8uHUf#^XFD9U5euzYDxRgTCxc6>)C<5XC*KA&%f9fM;W8Wj2twkaCic5dxW3U zIhNL@byXoo{m(l4&wlF7EAR7}Hy|8IUJ8XOo+TB0*isW?v ziFdpV|Ld>3)h=YLrH8*=6YWwjYW=qgkqb*UCb?7%Fu!-BG@Oh;E4PsJRnL*xd$Z;N z(Oo=SogocDk0)h^%iPw#;KAL5RsZ+qSS`@Zo8`!h+Ev-+0b z@trqWN1QY^R2I?lSzDxJ)!56zxyNULjTaJj-U3cSGRohzq~KB zF(JR(&)#JYYD$6LkI=R;*Qwz-8BR?PK)pKte}4AvYY0qLT|knD7cE=Re+Au-+q~iu zPa{PWov*t7HCH6nY1Bg_Q0Rl1JOV2&1A$BCB*Vq(UyaAJFV5t$k^?=f$uPl}mL@lH zrs|V9L)02|3QAK>rjzA5wLGV`QwIn?(4w3)Pj7&a=tMoIu2T;TZ71hg*^N`*a~e2& zy9Ew`om>gE)-CMlAT6QV-E-gYWs`V*!hM)(y!j2?oJb@ zsmG<6sD1@&3E=D4(pS~Bt>-j%TA<@K5P*W&xt`O~X(eyu`Ir3aHL5F;2@N2>hmLX^ z*U3j_;GEz&?VJ;>*>%`++Eb9K6HMo$1{Z2#4vJ|VXiTT0gS~iX33YN>fc)e+U7W5A z2G8l{6dXB4;YGPfKjAsu<}9%F1?*TRzWV)a|)fl9^MkhNwf9yoc>rCk6w;f zymph)lbwNl${FMgK7vji@th&j&w)x^<7!fwYASUU_9Xg5`wU2H5vgY{7j9{dJMb0@1DIUSNmEuj3r{{Xkd6MV(Qm6|&=R)TqmZjV|%ZiJK7lY5R zsvy^M);RsNO6$(nvb<>Fk;fOy;}|dwMQ0p&c!|@`pMS`EsLrJ_fiCl$%N=BvBlRfJ zd&C8HqriFO6VIlk#{(aZ&ehIZ*SW@XuB9#XYoO&*jdiYbo#(8VvADtUWw2k*xxB!0 zHp<9M_nb}64W4r&6P&TR*>i4^&=$FDmCMc2(A&VpcW#m4@uB|6b8h7s!1z-<{i*&8 zb)#|qCx3X&>))oa`$?~wc)$g)Nw8mp$DmK?cRcL1?0-9oluoJi)E#oU(?Rz6F5u_L zSf_Z-UCzBCl%0ZV>6k&D^EVkw_c>>RfapBnIoq8FJ?9~3hrjhOD?*u5?w23-rq$i) z?4n7h4y&%w*peRZW)TiAk}Aep(xyS^i~GY`vqO3PhZ_ zDX~k8e!3he_-joZQ#H&BP?l$JAXGzk1~h^KrbigfASRxYvNTG`4}mWKqr zY$j5&-Xvv`#BgNC26LuE>I7RhUoy!H-NCoi-^WpiJb`+7S7{NAnV6Kt?U zHME>=J)7?bCZQc*%!wP%?g(lI!%Ca1a)Ci>4WF_d(zQx)Efh>EX(t#mp` z&OiuvCXdfo%gvj*n9Ks5+!d&G&*d&z^tlt&t)@FBjz)74S2o(I8XqYKXCGc!Lm4iv zmQ|WQRWIOqNH5fjf~+F(18~1GdA1bhSd(4Y%vd0O2$ujzzqv3DTL_STOMvuA(+U^w z{Gg_qmuC_0g{g*Ix-D|)6A<>cqYF;V%V-Z4KA{eI86725m1ei=C5I+^8ouPQ5aEA4#0(9kK84GaU5FLNN;ND|mxwexmis2RvJ) zKxNieDqB=$ZLJ1~j6W{QvI9#iJ|!)J{8CW~730Lg*cF50xKETxL7>OIDz`%ux5IX* zp^0x>y#I!~z`#T|QJ?|rN2WH>+^t4U&Q8XRZM5M0 z%g4&p7#kQ`rpDR;2;$?iqasWnkEwbTt%K5vEr4I@g79uNk#?Mv9TFt|R%L2(K~i!T zQGgVaTa1x{(8(muRMWa7(=OA4mPipNwziN1B^0-%oFNAE0x}CkUYJNcq-EgYpwo5Hw4CyWsS}22P zkpSzLsl}VrYuMw*fUzt{Z4K^y)#re;ul70a#7h95OBJkh`JBAIbR&KW(qIIi7A@L= z1+T(o0p`0X{mO4iW$bc^U0#ZnpQK$OcPnbSwUV#fq()iW|CNc?;zz%Cx}?NnHhAw0 zxjUn(QPUEQ+9er%4cn|3!dX0lm4QoO;$s_mmy)cq{t;z}Gpcg4W82kgz~1TqM5s)i zWh>73KO3D78vPv9=51l(_&Inc_|&<18Rs#5M1TH#t@1K1khuh8JN>i^bV`J}GVUy7 zyzSD9q-Si8t_eH@Tr4d=0KWhoAA zGxayN_xp8cu)`;+?d%*6>c#3I9bct(=<@+DxLlR%>(owtgW9FHp`mu0+O6+UkD$Ep zxPDAMt)E1F`CU|(e^<{MqnPDfOI^H)0 z-6GUkw+!{vtwMct>(EKMO{iF(5L&EHlubm>Kwty9J1UPY*#UYxA2bo5 zaij84kgSV5CXEbN>oXB!{EmVuT9R01e9oAc52w(q`)s;Y8uwwFF3n5_m*5=K2x6f| z*p;43*Vc62RCCdvtgF(UPr%WY{Az?!K`*{gU!>w0&VDe3*XT=Bnu9X}n>A=Bp{0p^ z_hF|Dok~a)^hzEOjY{hNv~!Of&LKMXJGbKsnV0?J`^gi zrG4Ht8}vFt$$+Be<9=X0#UEl?=nZl0D-I&+Ieoom+18>YhlNF=HEvMhL_Kb#9zj7t zbXP&45S1rBOS&LCy`?I*t>ktyxgAzbEQI+s3t_%f0AFsgj?!)uKWK6O81G2q8e(|N zhf6^xuZh>}>WL)HtwhlaNB@W(1yXwTlMsTeYjJ2Ej-lmhBj`=`N!0@Z z8VM+(5gqOOyNtCE$3L4arEr4~7iH>3OE9EvQtgGJ*bD)3n?OC?gkeWO@oa%^ z5tY8J{AS!75HYAtJT*5LCg3GB<~@SB%6CaFp7FHTP!x8=q7!Nmiz`vBeLtC^qjaQZfmHI z(XegEBx|e=pk^yaADIcFDH6mzTot#QI2qTiRp_vcphxWg+YT!%Cm(h7V~pwwC|bvk z42e|8qm8KNCa7oTBjsS4;fi%0fJ)F9N`rKtiajlqc}g-?V2%IQx8&xJUee2QvvB4*XJ$C>bI zBETRqZ|qd}m8l(T!UDcBm)wsz=6;iQRLAmfo$Nk{N#vyb5|&aI&1GUPY@Y#E#BRz1E{ZnN)fsn;}gz$Y{;+AdHZRNLQlWv~qDareVGWBAadMV>&>Mzj;f_A`9R!DB;148M( z0_*~G=|0Grs{Fm|I3A`RQm;aJL8rbJ!hr9E?C3-4bsSsq^G4^?EZkLbe~YS}2yIn` zS*h~ujhhwJZ5A}~tNcK#zM1XS;=uVT`7h=pZ(wK|=B`Ye4G zx}#^aEo0@$u6~O?4_fYgNVGNT34O78Lu1*=mi!f4@HhGzkV>vq6>PLPrv*Q0156Yj zhQua44lw2Em?12~Bkd}^6}sRSeUrY8|Khjndvqyl*d6*+LhoZE@P+=H{s9|-UvLd{ zSU+IGdb??)%S?M+Zo2D7O(8q{Q2n@B!~TA$e#$(qpEi5-KJ%h}*1WEtvlAXvE-0Tp z`Wd(!F?}wyZl6er zvL7VEE4U7=;M;$d9HXcs=~=TSy^d9=L4WzipS|$kzEC|qHM1YkVbMlPrV8=ns!bh) z96CvsWH{Hsl5D!r!eS@;?QZoj>*+sa)0f>`Ru`GA_U0WqhVt;MQas-A`_CQfjjEVn zDPRf64(IMr?`4PcgwGKFfC(#UIl|VF-x918gLl5RS-(oc){^p@9qL*w)c4t;j2~D5<(MaMdedP;B<)oLv)#R_P}mS~bVQdwLBX_@kR@Sez>Y}918&7YaAFRn)`tDkpBK`ed~OxFezJ zBkD#q0@u27oY+R@Z$b+Qz4mR@-ubN^`Px2{@osELXnqtz)o1!GW>UCnya#!_&2G$i z$DSD%FD+Hr(gwFP8t#_yhZeAYrGnS1J(tHae8rJ4acDdrd8aC_-C@<=P7BD4ZPo$9 zJ3^EmlTnCRJr_ zQdQ`HyuD{K8~~ zwyB(a9KUo<%1ZJVG>_G(RtN}NldI~PMye&hZB0{K2o8Lz9{U7dpBeV9YN5Z>|A0nK zp#{FuO=*i%d$Mk7+q_*>VcXfZV4cPM6e(Duu&7zeC`_^g_HM>@{A<=?l?`qmDUeYI zHE^c#Ep!L|U%ZXMHA|ePvg6_5r4?Ik6eZ=0p*$^ga1}LF zQ-`HE0Kz(*#eeG_DU|izY74ba4rqx&xo!5Uz7)fCY%#i6I9NHeWra4e_`78~snQE- z=TKJIK8y2kQ-T!i94=LbRpm{~3U5TiJwJ;|xs}Cc&6W(a-QhO7&LR6#ErW{ri8q3x z+S=@?UYkgwai^5&WGF3GM!QhlE{eIPt*QaDs*7o-roynAW;&>Orn5SO9nLph)eWW_ zx^V^QyY;}(rl)$s^nuY;2y?4H%&YLmTGEa&Px_7~Y6Lb^4^Mew1RiBWt4os`jXJH`jU_x=BSf%i*ob#;h9x#0A?LgTJbvklA~XPRH~Y^&}#X& zAu{8hVbASV^_Z3l;h&dP6#@v2qW?2(`nKvDcWuK^0*<9umaeZTWlL%R(yNhGXZbxBrPb@q(n7g`#s`9p~)YkJB!^dN9U4%P-~Pb61BdQ z;UyI0?K#-x2E(L^pVwIUdDuQYp&ph^$gb0zv_ru#DXn;~R4sFQ=>joFkl|&KckG_P z5ULtp>=X>d`W&N#c#GM)UfD?nA%@p+FE&2<#q7{+907qauKeV?N7~)`+%xwv4DVMB z%>$~l*`c}`SUd)NT}0e-4FI?1VTR#jcu{*?Z8T578+_XKiMZ=(2!Bt8UWjl@JM^5Y z;h3Z+vI}~puxax_G{I^MSyKmY-f79Cch_f?x-Pa7kDLu zNR`Pzew5!VesMRUYcWW#L?Uq>Gii;Pq%X#q*HCr4)3#5xbA@@#xiTpk^Tl-Mo@0%; z{=UbJPMyMeTmJg`Me|W_>C-b7i#Hv$Z2ltjF$)*YpSyTb@nX?+K}m7$s zmztAI`}T>dLe&@4R9E#!Fro&?1(Pihvc*%u5Lcb#s-dnL=8C13r$$5+kQ$!CR$#Ci zEg@_LQqCln4FKLCrc-c$Wo=ErK=GPU?`WlFNnrBI12 zZ0R>jNzd|^wu{xM^H*=IJ1?z;9^?O5n%2T5%>Ju{tNhXXl6v}wK6f(xkKRg)rAk%0 zTX+Rg;r6e&2H1slpQYFK-z&+emnw#8i%XUlEuK}ZRTuxsYob}L{&$tN(j?FFUpWo< zx^Bhk>3XRD%CvAzJ<30CaYn-vu zGnU@&FJJbsxthl2qfYTuE?!sFbPt7-siHWR)#!f~-=6`XpWkwqY3#SVBe_l|$*2dW zgX5MhSs_a7^KFAHpN}gjTto?Ad6B1PDr6j7uf5@VtYT!3olF{Bj>oYfP{m59@wvzwj0@KxR-K|DFzvRB;jCCa+ zcJt3(n;i9b*D-bc+_jOYzv1lk*1h_)V|vwPkqPz5mVzk7FIn;=LmH7KrLinUs!4iX z7+=i@hv76dS1pKX=|AyIdc7Hz1@c-+=g)~o1IMZ1V6Ybe6SRYmjoYP<_ui8M^xL@B!wrm0vB3s}4{eN7Z*oF$fF zR|uv@Mor}2ndK_$K~>A%*ACTGV4iWG9e$Jq&URG`{EY1?d+dWsODpMWt+X1=zcZ=$ zD&=%d)Ex6#5*gJS8FpZg7h(&{=~L%ud%V@ZJ+x;$Z8g5J-)I;v9j##;3s7#nFp9d? zQ?7bil&hYKf`Ipog!V?%zKD7jJg$h^A5mE581+Iju>kAl2(WIB0PE%`40LkTE7+As zk!U?7H`wUpC~S0c6gE0J3LBlx>MaSqoy>lRjZTijMkgl$vWudi{pbf#Y{Ea3=O4N1 zV?nCH)kwbc$zjvRn^Ca}7{Ym9H&3Eoyafy!#9VL-SM z9TDiQxGp<$a`c6qU?u|DiDM?ocA7CUr^k23V3?qf%e88?08 znEv4bWAFxU5vu&3y2pAps5@%Rkl}@6CQrBJ8a`mexaniZjVT;AU=TYvn9h~E;9t`i z-L<~3avQZ4NF~AMNm1jbF143x zW8yR?vH!Qp74w_L;=Hd2PkvB93&_M~Xvv{A$7F~B)1RbC*i0Q?R+7(|zYuMEGF=iE zPl6;ZS+b}YW$mI8YZNtN$#UyKaCz>rv>A5e4g{{gI=hX;uU9*8X?j+kw<#37xHQ%i6>*ydEIlt#_xTtUItR9a{wSr9q+#tX$YnCIc?*={ya( z7|PIr5y#apWM)kD)MzoqpDUMB4^hK-P=P5dxwR_(nm<1 zzowU5-N*lNz1PMs>leEqxr#tuck_iq{RK%Wb;?n7AFb0;{)C`w_CIM0CSps!#x&54 zw_b?~eA_vxd;L$Ar_}sE&{FRYj7@D&zodBi(Bk5y_7qXPY?NJVMloauE-ac`;&&Pp zTkGbquV8WSAABICOMEih#}vC!O~qVXv4?4(dqQel3HlZjN)*@!Qx)u<=_NvaO@aE- z((1>&RsYCav*fMW@|G^4vl6e+M}PWCj{Q=xyff$6cjo%-wx?u9=Sd`*$m&#kA73E% z3%O@xa+N|0P?%tcQs~7JyQK27jML+joF++@RVHBoAD?8oBw10JgpqwDNxbq)r%ReM zD$_7V6KT@<9ZO}2JyS|_7Wd4EL~LbC5gV7-a}%{buQDShb0R6i5Hiw|(S`gl!6hP2 zeXGT+;Tf}DVvdfugh#9diHK^2x?Dbc1MT%+469Y}1|G3qReh-_Xk9YdDw*6& zMBokbnEKyJ1Pfc@y=ocW4(-i^r?mvhmDQCi5?J*r14!sb%t{)k*YWTFJsS4=yqgmB z8xM_j61DwWdD{cce2Bmu07Zm$sCq&O8i1DsA`UG+i0cr)cO zY&2780#j!ylVb*p+g$LF76S_|h~M|}WO0_B^#S5(FtiPlYS zxoT`(C^Z2?O?)Rc17TZ!TY#&b_Ye-@_Nv->2vhQe6mE^ToHjdDeyM6f5+rd#wZq%O z<_R_as$?f5lI>RQ15x6Jxy8!oD6C?oZdUm&Q_km@Z#;DrTxy3i{7I<}1h--6fCQUUaI7To^& z48&%XIG+*L5o&la<7_J9Y9T5L&oDGzWN^IA;P?oyoInQMYa2I^;C+$kD8q9BBG$an z2sq+heBfakI7NjH3HHeDx*6&8fZ$@;VWt~#Cp}O~F>?_(@zZ3VMICCk*MhjwDfZ#s z;2{h?T0PzubBBHwT)69A+dy4+ss7>|)eQ+6ljv!63nIE5716UE;vqPZDg4!_x5;KE zc@406b(T)0;q5D%RF+MAB+*!lW5|D(^MBm9yU^wf$dq*j2EzKCrX(A+u7G{eu%@LmD3xKN;$ftDbSyv(}9z=eAE= z^@pqe;i|*b%#xPYLB{q;u`FkqD)IMEijC0~e*MX@UR_}+!Rj|2GR+WPmBc?om<&Cg zq+Jh9r{rVJmvt0h*xIwuv)z|zk29A}^)z0d_^PLC=nRSkTU8!r>MRdOP_;eq05Kk| zBdN26X*5s`vZ$}&DX|IIV{dss)X+b3N~~>$5TOVxh6_2GE2L)QN+{W7(3k=x3&86# ztQJwkPPfL&6sNgv;c0M=tsQZ!iptFYGt*#syRB601ezy7S6-&u`)jAh>Zf;5Sc!Mk zolua5sMM|iz}ENQof@m_bk*GgU(evFb}yfPa_rj>hV-LzysUKxR)(A*ttMbR>y7a* zxFxMYfRy@3QS3eqSdQ#Fv^v-2{u#4kgR#jHA&ZDg+ORsb57{RI!ecpM*(Va)#PJ?yHo*tdB9gurGfsOGfC#=X71c{3`roN6MB)}J4kN=Dn$rIr6Ypvih^Lnf--3A}_0 z!E$07IXXAfgZI%1d+36f!M@%E-9j8lHfwFE%XA3FZ5nDUE>No8R;)RTKF79%)zbE(K6* zaJ2qNpmZU(?`zse3a2zeFKzj3d0-LFM+rXqT4bN<6TM2qJ_@~mC)vc z^beKL@)zTk)Zlc&d@c;^#vEzlr~}L1;7qH~c1fiNN;wc$Q|`3@;&C9R(F+|p6xRW; zc$*TIYAmSswnVkJ)2{V=T&R%eD-tt@8?>!9`u}gTDIKL4m=Bw6b!T2~Hw5^gG*+fj zD!=GBN*A`ei%-p9*Cew0?`(Cqt+wFV!Y>I`f$B$94V(cSQw4#4i&}K(UpQxE1>HV9 z(qg>KsDNO(5e#P&$sp168FtcrtUM~V!NohDx6 z8IfX}^||rlu06^|&WLnPPCTuf75OGqVdm|k%bAksLtB`g+z z#V->^euk?1Q;A{b=N|PySdK?|+$vwUNo>0W58LXIG;p>Z!l@~fH#_BVR~o3rZV4W@ z)e};}lVNlx_QPgj$Hj}bdP(?n2P8OX ztCzzJ-YZi1t5VWyQXjR{7OLS8amVF|J1$4PCF!X2?J&3!c75&rT9an034{Zop;evu<* zZjpN3R^NogOn)ySgL3ZnRfnZ%--|y$p(5h{O03O~_c|`-_)=xpERJ-rlAh4&Z11%v zozC86d)z$#WGriNN#t59=_MLaw)3*ce%(>12y(XJnbctg%$8txY_XZySnZ};VqI@L>cvV(owQ4Tu^v;SydSe=E2(eXFZie2V$Ifsf6 zT2gg5u(dGYipaoFsZJAbFB84>S45VjY;<%cS@te;8`cH}o#op)z4T=J_^$nmMME|RBK;_}MT`3jo^1-j5b`@G#tBU$Mrt}Acr>0-z&YNhwl(n!8u z=^a@bS&8BGQgI{Inub9u342@TMJD(!eX{|gEoK_-+MGgE1 zE4WKd=VNeCwd1!vo4#T$2*%tfjji@vB7$9?N8Q?wi8~3yc_9C!2E65|XiR^f>-{##rE0xeK>3z`WCd3=`F19C z$Wg#PBtEUdk1nv)A{!gUHYX8MJ9sd==!mKZ3tEj%C!z7l0HqvY0^IhMk@Enq=Jk>M z1aQq*b(eCYB&$45{R-gDNC0<60=P3cZ!V`CMYmT1C);#ThMYk1Z3$;k0A^lb4KV@c zvH;8@?DHAHa3X&qGmQ?M=Dm1*WCYOFxFJ%rdqwZpWmlE1t!qV?S zs%zs7N)r}-$geA(kAcbfXhtQ3*ctqRo3 zRZ0p4C8c+l4OQu`em^yf7a-R62cMj~ewEzG@!TO0fjgvjZ{-k^JG-*|CnnzPZz@)N z0~7CB0@&TqaQp=>I%muT!|@aR8_%gd!Drd-Q?ZlfJ9_k3_Tf<0-_T_5)3ZVqhA!`o z6nOXF5=pP!CY2#57SA)a!YueY64VU~Z`W20Y_uCyiKp+3Z1rZJ6Up?BUXzsWU3Ocf zmbZU(WVCnSMJwIA`fF>P*YWm9v3Kvek?aOg#M4w`he^pb2qrJqPU9@@7OJJKAd0s} z(p@$4KD{N<#A|RK0ujd^vg)sTc7K*vbY~>r`{W)Z9-5~|t9g&V=Vbk!(f>Os3+^?q zEyEU8pRHDPrf7OYeafm$L$eA;Etqj0LKHcZXH1(k50R1igJ<`ExiNp_?BS(Ty=Dbz z1;yhOs3L7gu0-kdbOD+!mAyU9U*r+*wPK7FJvll#x0iVC6iFP-&Li|)@L>)eky{h* zuxR!{rr;-Or?{vJh#+#gK+>BqnCAVw*q%_eST1W3&Y%C<%CNf0G|Xm~4a$^jm_X3r ze_*1EU;drQC%$avnGci|u8Ryx!GX%*&qF!hWg8>YA~%Ar-=wPPRjP}=#rtt% zA}zHZF-2R9;)GGdG6lZ_^eGHMgB$x!%y)X-WSB zyXX1|R@+*|agJxD(Ade#)vNi2lUs5!d?QXyhU8S?)EV>UFYszU7pd-@@*Mli#x0RP z-l`ihkThDrYvXPG-of^?W752?_e36Tmy0E@^A?|6^n4upvf2ipKl9`-BNiafrqwvF z_ySWb+gee{pQQqvwE3l_v*JadisltR0W#mbhT{qZAus2-jHq8m-k+A?{cum@2wud# z-yg<&_`Q)5uhD&x46kX;lptrrKh4Q5v#14wH)-+y|;SLQSXbu)dvp5f{z^au_XFLeHwT}eg6JPT?_o$o6{}S-Q@a{C%aFBz>5&} z@V@{vYABZEM8IGk5_6?KlX}+qGyBb0FuwtFuA#$~3t-L^Ijz5`FXfU$Y=)ZaeRqFk zaO1Dkr?^3Lpq~DddzYj{V#9&1ve>~*`0Eas??PK0b`)-rz3cxHDdCLzmm?HUTm9^) zf2&^{^{ZT^eiOitLh<8LMNqDed5=60X^K<^ds@ff{3*XP;(C)(LnXS8|DtA{KN|zK z$Oa8Zue$L-uJ?I0lObl%2YN3y#$?|O$w`^s^AAS)c}?C6o$YP!?G`2{H5kXSobdRy=8&mvjvemDP4p7b08b7o9F_vCcm-Val)(Yma<)=#;%#U!yn|Fbt*NOd9j;c(V zKlDyFo(zQXOqo=b&zz7) z!2L>&PNtz`B3_Ao;m8Av>|4F)=&bx=LKdmp~0 z4@aiOByoT*KEo0BEcnenn({nE`xpGoq9RtvK_@p#QLQQf`I5uEXX0J+#5-{Z8MJ4N zUuue2mr!F*@#W9CZ}>6t2DeaYYd0_Zkx1?Ol@PyL1>)R9i&+sq#N!`{H0e>^EqXF!NGpWFDF0{iWB7& z$IEdU+(~gVsCZdKtqcj=vniHk>Vr4*Q4HNy7W*~eeM8aT{jcERpg_t2-eVvda^qc? zk1NG|u;}WWRI}YGAMrb%ub5e5hpGuTtthjYhw!Zwsh{rHRe@?xpcTgvy#{oeBDQQ!jh2rc;yW=c7Foe%`HMitwr z@j6LOMfYts@6SipOQv;+=vofqwmp@L0BZHzTV)gk6ioG;dz(J(O?Ik5XSVLbOdag!RKp0Ui9!L)3}k3S(Z z_Y~$NZBSStNhJD%G!(djuE|OAAuayTi3_Pb-3KAuxMUZ;5ZGPg(-wRcyk0@DLlz72 zdk#LPb5&PeP4$NeH&z!gZws;QQxn%zMKBg>p{YJ%Yx)-(rdSfFX)<^Hqef67I zN_-E;@xPGexE_Q$%3xDh4>Qg6aMKo+f-D#zUW@`wkyT>p!5k}oOs0FqdLec$BqdfJ zv6;|hj9$xKeYT%tGo*_-#83mEw0bHVLpw*kpLa&8r}xylc4JYE0D~ax>qU2?_Ij!i zG@QnTdY5X06)bMj7??qE2q9txyS)fg z#33X$kAu-bv8y=aY_E~EoMR;3##>7X*Qkt)^8>dXp8Rfuiu4%MVlu*>X2M=-J9>`-mF`xbDu-mcnh zP3r8A=qtf<`>oqm2O+=&gX?oH^*jb(J{BhyFu3OrbwL^zp}u19>o+3LSt;CRYmThzfNtSu@fBRdWZZPfAdg|Lq!S8I@iO z#Wg@FPAKPGeKM*Tfbk~8S$_B4 zhaS{f-o}#j;b}g<1_p9{-cRbMi}Owzxd~&O{8tdac?I#CJ&_(U2%v-14Ys;bGD2q> zpjO#JWlB~!U>Oi6HHDNX4{IdAUEMlc-D)e`thnlSJU^@T!YAAyA2&)2dK1#j5^RR& zEKbkvf{Pr6>PBkB{p1Tor(_{F#R7U$4RwQ0Z>k~mrW!uINq(U?6$-^ES3zt-a!vvm zvAL=&Eb?6vJce9XNT^JWgM{#6Pf<^%A&T&nB-|^HPlwbq@&;1V9`#&E?F)k-!iU|X zUN|Ea<~)iUFRBBQ{9s7`>a|p^Vy{c^MjB!R@Lo?*Z-<2KdWtj(k1BnI zOoz$_e*eNy4?d7y_|R4#;VjQ{Z;jN!L*OU>Va{`n73x5r+4ImiE1ic9p7KSO%F_2n zkgxe4iAw(ijjHL>5M4gI2hV8<0`q^*Rkq~mNQTyzcyou?4ZJxkvr@hEC#*XED_!iP z(RidV&qijY{EnbC=h?`L>bX9dtM{xal{B+}E)`tmhyRCNpxS(&@b?FKBWx6t&xPnc zQk<`#C*w;ne8x;%k;WReDS&;5zD`>T40^zs4v3cuVd}t>fLWKQf@xcS8F4PJIs{qo_-f zqkd5TkP7~U0yGa%vjh=nUcmLP_d=vy^>Sc<4ipzGqb_cFyh+yDTg3NNog$C64tcv? zh;*r;Qym@l8Ra@+$A!s|B%^Mfsk6MC7bC6F$@NZqG15L?=jdEKeL$Dfr>M(qo#!hs z1T69EUW}ZD@VYnmytG`O-9c$0PNr$eC^g#qbZ2IlI4SDS_rhxc05%2pkWX!9S)lg_#v&pVSVfOfatR9)^Te?%xl0(R5`y~+IyD?%M)*|*cv>i4 zrItk)FQk$Z=NFP4;7n3RfP9Vq!~FBP()d6m<_W+&B6!iJSxs7Tl`>lSrR*r+P#lgvhZI6Pjd? zN3pMylaxqzM@(HO4>>^G-oO#c$e(zFQ^4#OD;JL@$zHEFN#)*0w zFq(ex0(!Mci5JkTjh&OiwWn#0P1qnOCCB#fKot#()y(V-DDX4;@Dm3n?w3-gpHJO@ z=;*R)tFbEbSfy=Qr#+dFlbOgXSr=;|6s%`5-@$Yi5ju=Pz}{F0k@Esr0*j#kFGlq6 zLR}9x-3_6GbVnF-G{Ts35yXsLs;HD(L$%B_Q#YFS zSeEFCzwXIc2bzO*pbOP)W+@g1J+%RA6nFS*LrnGbRG<47{3NUmuJOhDl1ST;yY?cL zLXH;5;VhD^0oxV9vUg82_i`B)b)0HuBa%3BEzUFRxo}>F>*)48%PlgA>KFKuoXN;~ zAOoSYj;lNylZ5I@TP;7T7T9V<)Vu91WOr&KzRCYl=QlPSjZj9#M$wX@{f$D*`(xaH z4+RDLM6ky1{{0$9)`83me z19qy@9##WopVIz571ZB?EjQS%MRZ1ByB^8JK-|HAOb(%khw(eSTXm4m0qkiw&*D4( zs@%yUNJExfTYUL_H1$61HOHmsu#=f7zvDEX$aGdwTd4VIf5M8fRm6MfPI!^ee3+7v zV98|EulL`p5zNUy5sUs?TCe+yq3jf!3x8F#$eVW_8j&I*(J4g+L$-H1F$qM-KXF7{ zNjgphI%NBYAj}m58grEn5^2%sJCWDygtX|FA4PU2p0?ckw}_kgwDrfx6cm_MAY_{V zbL5>mT($kD#ovg{~Gso-pVs?sGnC}+GaL(9FonxzW<@h;AROHW-*vycc z6;iW9YK}b3P31k9*?jr#Ct4uaj`LGFrx!}>0!e_kO+?8hc98@Z%i|@sx>OS2Ycp3} z7MAs4t1CikX;_F9AvJ6{1PC!b!Ya60L^dhCNL^#AYjLKjR*G=T^^*05G!dhcAh_o> zRJWw5)gnbuTln#-)mlj zQy%dS?0u4go96s{H@&%oC{RBKNuVu`x<@Qrpe*Lg(;%_ni2Sj`hJ(?H&JsMR9`H3F z(!0s~htyVTb|4-<9ALp^#V$5?93*u&d2biHb**k{hp(LwLc$j}04nfVR#K&bw%X;0 zz^?;s=y3-Hq9+|l()kJ91#eptEdL32h8=H4J$F=v zhb3Q$q1t3|R|XF=jhQDDKrNl7w6|wmxUDT}b|6W&j0;!KX*(b8X8ZY&j6@u*n@{-a z;mx=++9AKEzhY!XHKc?RpT`*>Obxvbg=sas9rfL4v@%r(YU}7NEKIAJT9XVSG*s># zt?zp1CDb09rP6lF$y!(ZtAOYPeo^X+Dq2G^ND3GHDb-MHl7i1*M@cM_He%~f5%q<} zC@Z`nCX&z%;bd$oB{ap^O!^juzdecMrS3s(LAaFPaKtJ8e)fMY&LDPRIV+*40#?5zMHOjN2$iYBXwxr^EOk3#)LP`id3# z4JCdLR{A5q$2f(1QMy<@e};O{_GZ_4fHH@$UE8o^P=rER8t9rcKSofjMP*wldN=@i z6fb<$WGd_niayrgs>*#PXY9;O_D?7fm z&HLAi29Gck4*=Ca4Qlv6Q2RmN^yY5w z3gM=U7tB3#1;R}$YIsjJcbmu9yC$eTwh&{C2>)aXMFyQQC^DhIoW^shyxf-xBJ;e& z5dX;(@t;f)|H)J@*+Q6!ibah~UkXTy@XLWd^O}%mGDS8X(u~BAiGNeQP7MB?kIFGC^_-$;yS{6l_` z>;FjoGYz2(6wkgELHJrC1z$@Ymaj;`H&Q=H@Gl8|l;9@`eva8ybx#!j0BhHig_H`?FS(5imr%0*y>e9?~Z_d876z|Dqu3h$eJ9p#%q%~LG zELzvw+QF@p`&W9})|hcE7Ltvw<*Umb^D;W8Rrh}G;AU7HVu9_2+JS;uJ+Em;cVlsV zo>&``(J@0m47`hAp}N2U=OnloX{EW%+@c6N0U~~Lsc7%!drS7CFjGwvV+Jk!v!u>-zNEfBRa|Peb-+p|J5c;51G88+SS!{II#hVX%!qUp zAUkQ_szIIL*g4Y4JT6 zxsvQW31&(#OFqn&4|C*kuEgf)2^9o1Oo@3H53@ow9c*qcV4xiw!%!KHU>vecj^32m(6p&&?G7h8~nl7S@Lx@shMrR&$~drp3i%xAx`%E>Z%mI zNIoy-GZQqPSwNf4A0IB_he`YU50~(Y*$a4=0k&}2q#0FmUQPlgWjv>d=}zYaI=7ct zETBaoiR09A-ZE!TPBR}30g_xDB&jYFhq48q2&DP1_kQW?p5FBaUIrwdrhF6yhxQ;0 zorraX;M0?*KA@Eq#G5{d=&#}_6%qVfDC&A|Wk0v5trQ|BfQsL4D>Fm|4ds0jm&mn} zf#_ZiOo!%PQg*1HdzR=vc0~8FQ)cJPE@i4~2OEk=x4^==ukLJX?3+Jkb z*fuZ!3?hWH7C%-2B<)tm1)@4_ZJVitXPaM!9^C2?Qz=#{!t z_4B{<&x@sEf^mTVa9Un!=D;0lkpD1P5)WCY^8KfwemKkzhv%h&#f*^eBiF{ikMh5a z&XdA$h{5+U)S2PqJpx@^cfY#C{KkyMpG9h3n%>b=jiWVSOZbsH1GLHa?rZQ<%=9GY z%?iYoFJP#TK`y)b&;tA= z0FI%lj75W-%T6`^Vbv+1Ajm=rCb_(+z5?z2J2>$_7~p@hseaAo_zm0Rw+#Jv4DVrj_j~&72TU~l z$PMWy^#REHzc4g*RQ+1kVuITeYzLtU=76h?dow4x!(d44ndt7yNM@W>WDW?OB1Dp1N+%?#t>b zby-~q|91B3gV_bEFAs;3^}I0LhlP{fy)h!b(E!<>enlq{OJ?e~G%P6`1*}x|Q}DA^ zsvIfWuxcaNSu2gmkA-TSm_BQdZoY5$3=w^eR}GM}uIexpicLjf;h>3??Iqp&zEKkm11vjoV zg;gDR;z%OWt%50n`hmPOgD>B0u6s@27QW#tz!!bar+wR3zq8H&;)bb$xBxh^s=_@a zh?~(Y72{Yi_0a^vM|h}kn#TP?r@$_j248dnR1q``RI$psOd8djg0}d3>R-k}BVRn_P}b*B_HRq)K|ww@sfW^Zrib?L=f=j!up zoOPowJ4>+3Sy+7ZUR%Q0A3EP{tmm9);LPi>5X#b_{>jn0^C!)0_TPw(i&wpNZ?#Hl zjCb=wca#1(G3N$&bMlPsb-5-y_J5sehv#Q@FFSRSd%oqBUF6nH3s0Usd)^eNV+%^X z@6T|r^~O#_rEJl~?lpR@ci-mlb>5bzoKwo~y~N$DA@>Z5xucqii0m{@N&|aLC3j+1 zgt%b}a2$^FE~_9kTN<;p1*8 zKeR;+6EC4*%vt}Jl;Sk>KPL08zsw!iAZxeE8Jm|?rgEi{?W)=iJlSOLPb1J%FFgLmbh7+_~08%+NUNsamci8cWzk56J?x~7*0MG?+W+N%sg=0v#klEB(AbzA5f@<6d$5jf<2AI)cH47-3 z2?Oh8G5sL13&{*JLF^)8;NZkACI%)z>=H^z@?)2RWF`Bt7%^z-e3h${uy6{ve@ym~ ztO6xc`>9IBcqx+Y&;p4q;U(s~iHQ*nLEa0vfm|UT;zwgk*Es9_@ST)7lUaT5~7t)w_^4>UEW9PBd7_63}f zaq|Da2{a8{VwLg4}VB>4XpRO=w_ryf-iG=z_+!a%uMV!oEMM1E7f2U5~8JU>X0 zYhu5OMlq@aYsk_9U5LK6T6;vLmNV`Cuj@{#5U;vbmqWb#U-IXl0DN*~0g%1D;w#jDcb#O_*5C;O;jOgJ!Z&&{1XhWw``5J7m$pp~=V)-!7tEjK>C)J~zQ|6g?7Q zwM0m<$d35S}k%ig6Vwx#@q-KrIL zy4FpQmOoXTTelf2KCqI?RNH~#?W)}%=J;;aeyqr*i%Bw^5_TBa=qc46hOzi>OkSsw z8*R-}op!6vWAUrhWw+`Iqpw?L_noT8U>MH`*Y=bxv2PP%nZ3llU2hn_IZ5lwzsgC< z?BnfO?&hZT#kiWtrT5G1?|rh|tr;7TcySsr$kihtQBwj3=x#M=tZ?cFHz`v?w)!0@ zU3d9EYyM)f&X3v+u%n0t&M^yWAuIkM88@v@)xjmDH?oh+LSFUoaPvoAt^!X36 z*y^&3_i>GAO|R%?x2Wu*jc$>tAbX$QBXY@lglFWhk@x-DXrA}#Z%)*k_zJAO5ASf@ z!dt^!k8hLU_EZAI9q-iGCD|Berf={fn_UP4yuTYaxyVH7d*nep*JAD&Q~EsIFL`mK z^`QJdB(JwhY+IU|skf(Tyr@d>sI3uh%+LroZq_>`wkuUXrctBK(2q;-M4En5BMzCN z_t^R=`Q2;lr{!hrnXsy_pSAUKVO640rk$yuxAlH3xd@;yz?#$>B>juFM%b~XhNj*` zQXI7P%W{|55Yn&6FGTe=`n8aLJ*1(kx6yBg5f6FG))3aaYNQ^UXpGHl))=VXtf8!L z)=<_r>kq;){h|IyD)<-$GJPPVKk=I;xjqePNbCjrb7|ri^7@eE`J2SPlp-Lsch&o( zPya4(0@Xj{8!c+1{~6L>b1Tzth4eR4$hRR4*}Xs?4rz$)1^S1OhU7k4$Dp~7)^DbP zAO2+PpXE+PVFeoEdx8GN*1v|;4C#US8go0P`iQN$*Ols{Y5JJnZtLS|$N`oU;111j zuWMpV$XEbpl57Ln{Q|uqO>HqLA!7?v&(Z)BB4)VbwJ{LjV;Keu*AE!SHqhUfNL8B+ zSG&yyBK#7QZW}1@R~jhrn++8BE17&ICuDL%rW$QFr%1zTa5IfWX*21TB_@wfFx4e( zepszD1(L2%^4E}{rUXSHQ*4`BAyd0f$kee--7qHiHrS?K7_tt(^}}kD{5G&nL#^_> zB@c7ifA=o8g#B6H?M@42Jt)qVO~f`$=n-Zt#8I#NcSsy}dt9e^HO_R=ZQtY8D*NC; z7wwk)%pPR0yt((g%~r2Vvb~La+@!K|wz(-u={uNa%oA#2{4fZ6QliHmbth>1XQr(n zxF`@0_lE9t>y@o3a|b3TA#HfP?5oG!WTRj9UbDm1%R+nHPDW>x_1^2ICSzw#U+iRi zllQsps_j>A`zo)FY?Q+5eTbM|?REVyT39IdA2FMx9&^~E2_BcnCnWZyD)WY9nQD;{ zr3=VlAog!p4+#mrmMiRI6vEH24dk{i-ly%7a=n`OgwwpWqjVvZ`3YQkOmo8xFGc<2 zn3kp$9p;$UdYNNRHEk-dVqwR$HSHYs+@HJy&$}b_ey@1HTQ6m~V@@*zS8W=T?M>S6 zzL~P$^uZ~Hx9K*wYYhQrq+>?u)eh3lk2+xNdjreK!bkSjyxx!9$1K z<(Q#np<^yEi)gZU@k?%t$V8#|FVN>Z=3>*!E6y_YyiZFV()%0fK`B|Rn?!@!+TpKhq>?N?H1Kz=R+`I_~DK(&6 zU&Q%(F~_n}fiz=?G6u>>pL_ZvSy-6Np*6SfAy<;7tjvS^LQAd z9;Nd^3X@BAmmT`6TTAPMUg$mdf|#^WEZGi63jaNX+mk@TbD`UP#O>gAknxYzCmi+5 zxm$gT{<|2uOXZmVg7ByKyAU+Nrl2to&|`1F_?C3sCv<*ALx@Q~fs7K98Ng9Z%x_4H z+s?i5innqLMq{3erFFg*i=ROzO7QI~zWtqV!v*mkCnoOxfq_k1ea+Ozdf73qTo9AW zNe_lx@d;aIVj?OVt@?@D&-P6}46JaRm|6s@lo)@liFz)=9sr>|dE1{<_fOt&+V~T2?mdBlk{2 z(~f-N?(v)U1E7zEGHNsZLhzlY`prPEh6}7T4XZv}|NJS5I7hLDPfiy+uR3tDGyU|# zIJ!z>nnv{99Of8>1I@hwF%HR*1`l$Yj_@v3FIQu^d>13dYa{3T+m^q{9E`<5w3lHMoyTfwsv(cN$x(GVjf*ihd>*?`Lz3&ZRv1&0OL4 zxP>I-g}R#G&rjkH^%P>kv|p-Xk$8*1zk?QOG!^6R$fF$r^!PUpVCHKm0GZWN0dfIA z1%T$!e*#o|2n7_<#X(^(1VDRtfjAIL@UNsl-p(bRE%s5 zxFL+}F;Rh%#npxdbzDSS$ik)hFxDsSIOG5DZ|XE0fsw$^(At*+U}cUM{dAcb5ul1U~E6&gj*c_uwj}f{dv2-M* ze)LBT2e`NxE+Jir`_mWPbYutXM@P$K3PVA9RX64=NrU5aP&Z+m9aUc)_s2N}l($+i z)sR0TYkYr(u-ueklWnb$ZboL=)*9*N{{Eb*YgJiBVt>J}Lbsrbpx`{2EK&yDT~US{ zZGKLFG-N%kQITURBk0s}6*~{N*)kY(YfILKbhY2FHEi8V{%1sVOXNC;E7grq_C4K7 zwDPkdFCWFrU3NLgAcT+qp%g4Wm(xwb_)C>F;&sZ6GrnO$2sauZ5Ii3!Oa0RQmyFf1 zuiPy%R!q$T&W7n|Ubm&7Q=#Al{oM)IvF#XxG{lV1#HRBw3k+}_=+FoqG&@*fjP#0N zh3R4%(2*SJdOf~cJCP%c1>IVAX8bbsgb*WyM?Bhl^;?$X}TCLDTw^!*526Vk+8!dp#eN9{MzYt^uXLssLGw>WR$6cT`knBGXG9F6RVJOd&RQ%YQ91q+&u2wPP|DnUpO9ud3?%a$03q z%)1jZ$!?O))S}#ue^Rb|we_%|MB*YSH`sqMlw|+`uLYk{eDWP9duJ9xN2>ls%;jc_ zmBe7SpHQn5S#=_VRKPkJNe3P9#(nMfW*%?++HKUe0tc+FqIwkgsvPgFAS*rVMB8eet z;ZHOuwXo1DkibsyGsJMTokfnS*rt4wb6M)HCiF=f`W>zESo63W$7!26=OV=m=!e z;M5mDCbA&uWsapH@5gW5W5DvmckbyvEEh6MS^^8wN%T_z$B!)1WT@VydJ27>3K@E? z|1|_B`fC5HP5Tcg;5)2K=_i&Qj;W^lJ%*qk+@?&9x(xL(qD_L%byHjQ49ZIexp)8` z6t#`^7i2*Hlnm!4GKkMs>0~4bJ!x}UkS{HF92OOhTuZMH$9K1`1BI93pGW3 zJ?PB&JaVb?YkB#5cR#gwKe(+D9oY~l7Sgn2$d$GIu1Z3Gy+B{UyHvWgVrRou23Un` zPE*tny_inJO(n>UOoL=N5{u$_6=^CaW?6h1@Q&?QCT0i$l8dC9V}1kV-sBgoFQ#D0 zT7gAMvP<|XjT$IeLsmt9*78j%un)9|FIupU?}Cr27d=r8ew8n>oCU9!i4@jL7#9=2 z)=AkSiFLqh_M_XtzaaQR8s@qx#Z*faQ_b&2DW+Py7|nh9Pl5AJ2F|Ne>K_1i3eYV* z0Xi=0K6Kv#UB}8sZmd$yA43-uqt!0G%r9WrPi}7g$^!243kc?Aa=dxa$>WJvlDJA= z-1moxp9m7u7tN?a`b7M(JAWZ!s*J}&f0S8Y3AXNU8z*GWs?uMzq)79~ALd@6uVNM) z@Xb7&TG^=Ge~`G!?Ok8ZRJw+&vXkHN^9fDd`v+NlVDznF(Z6E$c{h%9J)#hzfrovYw>S)A&dT=f5&%nK{OTjz=|ncnwWc~@giJxy1t3E zXhFVjtXENNaMP1v^}n%NgO$ntEiP4b%cHWh-OQeRi(W0YQp4ZLB}?k8^g53xKddfJ z@7~cH@QXVJST_ISwrx>yIgY{t2)4O;_{k1pVNOraKRqLO%w9u`6U`X3n2+)|D9#43qAk2byV9a%wSIH=IS?8DZbxe(lJLrRk?PSl)alcM%&oY_zRhbI ziZ{X|mXDH@bb+LI~EjRns3iE>ZL^%2ZEm)Tp9mdbsY0+2(gJpcv;&<nC&+PC&rv%1M)9Xg-m%UIedSo2@bg%t9Y_qW1m|KzW!^Bb>qjc6y5&8-nVt3vuL?c0~`_uj1$y22zfSh5c8dm*!fhKq}XDqLbW0u}nYCftQECPZMuWooKg|X4ug| z0j9+K6&$AGI8TRWR+}eHeRT{Uv5^JCuQk}#~&_u9QW8#)r%+i?mZz|>ULJ)mftK$7B8Fkh)QO0$GEvSh1Dd2HH z{jOhIum`z`+T28KZoD>(8zVAj0R6TG(Gnl@V1<0BqUIyN5TA5Me*|rXxWaKRYS`RK zeY7TcBih|Tf3-y!lRl5bTX{0zkhUtA0_7`JIy0FHQt8cfnE9%Mch9qFwPW!F0R)mj zdRx>s14pz*b>_){(&X|hOw3G_U2=dhD#`fg@SM*x#1nODN-Dc#e`*MEi|DULri4z^ zHY{({V?uQXK>m7?d6xInTC~|d8NmW*ToV0GCts*i%tc;N<7lgj+5O;tH;yiH zo0_^z54=1fTAP7JZk{P&2{uxVO%pbZrmXg6s;@!$$h2g&xAKxYMz3npmMrba(q6fy z1A9zIvUO55O=l!myP#*)74`6Ls;%jcgP0!PV;!UAdA*raeb`U>vY+%1Lvv!G=wYj( zH@l{%-dnb}H`|^uQEx-vXse37eth|sdiTPrmcIsxz25QC`bDF$H&d|%@kLmz)Q4>S zH|}jPEP3;#1Yb$;cL`8d`Da*vt-q0nZzcFng2NJgFToEI{3}iWsDF}lKZo_d^)F%G z{VD;nr4}CuehcZNA&vTvr4cW+bgY~_hHeLH2`t+rg&9QHkf|m`V(=g>6S9T*SVtd{ z2RM)x3`oWa6`(q>Aj#{p@z@6KpT_!7NZ5~!h5gvrWQ7cJrHxHa*yNgOw(uTXo4l~8 z4xiB!n8H}t)PTK6v?x`NHpO9rTDGYTMbyA%tQ$7}>vN}3Y+)+l5e3m?%m z4Vh+P)yFjF*flL^wrMFT;hD7#3%e|=2AZ~Xj%g>a+e^?PY&x1ww&_ekG1Dc?Br%~1bA6Z~ zc7r6oQEITynEH>LxdEPDq z{;+Kx!AO&N6rBlECf_hKo@#c5%wqx;A`&l}$HV3c^Q83i9)aj7`A|zz?G2fyrQe}vBvH%c|Xv9ur{vI~}F#oj8*MVN%f`QQv`Wx?|fzdAd zTg-(;tCb}Wif&9v`kQUO^DZh%&-b1k5$!EI--9*NYkDOkqxJP+Z}>=TM1F6Z!~RnJ z!8Sj5)kj6A>ds|LMn$KacD-!#FY01dv7l`8qgJ&R;y8K=lB**o%^Z%=rFm24cb_$7 z*!jF&uo$~lGbdrRs*RU1hVB26i6;A|VQJph)U>2kZ||+&(3$7wz*_1PR z22Kh3&mS$tVqqUg&J^Lz?(Z}IW zdZJb6ol}-n&2M>5Mn#v2v7x^6W}lCdsm|VOuUpM4I>(#*mM&o<`NTUoHu_AeIlm=a zmaVsW4~~oWN%{p74Bn~*r5sCJ#?gEA(~h33r#O~nC877wd)_=8Z;xC&rxXe9p0m%NwE!@zWXDReY{v>& zsmwkHZPoW2E6qZBw`i7k=h*a2Z{pGPNVa1|EZ4E3R=R`pha|_!w6azWTUsa2v9hfk z$I6wUnstg}jU)Tg8r5%c^Z#bsVd%RnNBSJ5~d$p<|U;jU2179^+U|tfs!krZ@3Y zE)kB^%xdl(nHVj}w^}$>OQ57_xMzAxzwKD9CBvyC=sGF7IH$yF<5+F=gG+n*{N37>TWf6 ztR7Z6{tO1su4vp;dX_%#si*rc8b#K=kGJ~lXeYPC>LvZ$Th^)7$D6dx&IR%e%khc| zqAkLX)z|9hSp9jPJIu#C$bIBi ztftVazulYRb$u-})Uc{Xsm6^XlmLI_vLQ?lXzO&x8e@%h5GA_L(R(DgQ{Uz2GQHE$&&uP265LB*jgxtFhShxalxXqDCDxg? zb(UjIuqHazBF0)X6xYC*$Oa!)>W^`x1HBJ10WqDhtL>tGZTQeN%9I2zIJJU|Kz#^R4 z&zv!TJ{v~SB;Nr&s<*6j$2wOg_j%IDnHF<%mSk&{$Toe_{1ejqF75rnu5dg*oh~h% z*P#ebdgCI;nr)>6&m8M?@8c=aCV6u$b}iSpM28~nv}OZm&zj~~^BKmvrO~=g7U-*G zIL^1Ng^qQBwaBp+3pf{A7dh6&)+LU0sRS{Bsa|idcxtq6Gu!;?SeIE#9P4uH3fo%h zSj(&{ZHr!AVO?cgS3A}<*0qjxowd@juBV>2N~7)4Z;&iEI@V26#VXzwPK`DyxY@eJ zu~xGvbeZKj)*5TAW398!bgWxRF=c9WWZ`X=v8~%3YrVC>u{H`Uo2)wo;>~oDx2c+G z;_bOIoPsJyiFK!K-Q`$!(;{n&b&q4+OCdFbpg?t=f6o$0G{S3i@UgCyK*@7dX2VSgv9RtW2lv!+a%2WFAmfAHw;1N--y zFl-b*BganYGi3On?ju>)(Jo%E%R@C+O`6c|+`Qqvdkz`iYr>%ZBS!Qe+;_t8-rajm z=sSGKsG&3t2QxCFgD1`8xQoP}`~w|8LwKH9FlojtqS=+XCJY`jlA1;h?!`i_nxp>| zuj%>G)4cE7MMrw?pCA3$dtHcF)wiY9@?Kt<+^}ro1<_k{S?=QKG|O9YadfXY_LAsg z@AFHdUnfldq0O!XOT7?aHK#u0UdWZi#R$3xnMfR`g#IrGf&W__nGSi6SqJ}@)5!k? z9Z2M_#dk0R|2@co{|kQL|AHd$o2kJ$gfdcHjsf{4GsY7L8+#jK(Xp{6ylexDS;$J_ zrY(y8W47uBv8Ox4rk>EFdO>*V4XLLO1f9N+TL!5fFzPT3h_r-K0ez{TsMPTUZ^myC zlpSK!4QWQ}7VwOX7FyN}o*}KMOhocC#Dtx9!DZau1&Ba^ZWI^1(a?j(_=N{lpUgzz znYtC?2^t1|KzEV`wn9`vBaPq_$}-|T3+YKrI}l2(UE;N-l;l6EoNc@@TB-~L1J6(m zlhv73>Ptz~m*RIXC@?nVJ4s<)(qM5u68QZ5I7B8yWgJg!ACC z%~wlM>A4#5ts9YZTF0C9C?ZL}4TlhZIwbGTx+_Gh?pSm0rn^Jd!XgYBgW~dhk*Wn( zzn9Md*q8umqwYNsZ6@j9jk>SyN7Jff3QjEOTYkUDfCL2(px~gm(-OrEMB-2S3Z~w1 z%!t@}5a#cXs3u1sIBGp4-pVI0k52GgSqmr?x<09hZDgXslY?|)F70WDv4L(F8t4VV zMOq_lid^6ws)zZc$vz2q5siq0i(Sb{TTSKLOq9-Np=7?8 z=NQjdBKA=MXl+E-N9i#DI!mPi@>n0_xrjfdjm$jvh~@&$~+UqTc!%lK+?(|y?I{sW$f25E3>@L%c6s0ry|?e z8FNDl`I+g2)0sf>i(do69zp;`+|WjLFA4{=7;#V$I&2Cj{#3Xt9nd@JjD&3$xIV)W znLY!F=}8DOmO=)e&hK2c*Key3n!6xdg0iOH!g&=f#P)w;ROb2XHE1E$;V-fE)U0S9 z+Js#q(dd+>l(oMynxXx%7!2cCVRtDE*C-1HUkw;t_2EvnfWEA0oc{5#qU@B60c|@`+#gaLz%j074Y3bt0&6w4GfBx@%uQ>5kEJJcm5d1+;;`i1aoyx=9Y$w`rW#)2?N*6VhV2>7q zsq%dV+GA~ekW+77uiA;F&Z~B)t7%Qjc6H5NIKK%pUz>Sd@)K(1SSv4O#MmT0jfm~U z$#_uS7M0f_r6Qq}dPDpJy@N>m7B#*@ir8UAXD)LU%5#2wJJikeRP!CGWd|F8)AQ(o zR=ZW7u~_6t5gU_=$kysnMKf{>m^1F=LF29=? z)M0v!|GP@n?B1my*@mAz1js%?{`HW?{qv%Q=n0jT%6)a9?y1^e|!f zr|>?T9ccxzIUIji>8sf}N1)v_RA0k8R7r_lOL;7eiv5Zh%=efadPD=xd6r#1?PUKT6yzZQ#RC+{c^%B@097bek>jeit=HOmovm*z=RgbltNAut z-=27F>-8*Lbg@{}M^vmX+;feT3L0d;PYagO!`2&f`q_HZd|Tgf23u%2j*V<)-E&)dcE|ihb$jOe_{^5H z%_ny8I^Y@-R zFw&d+h}yhY-MJPQN5NXZt75I*Eo+s}TY|Po3yaFsJ^mi`XsohPK5G@cub7RwF`}Mh zL8B^8_hL5r`;jC_W}XiAXQ_1dxI_cTB^o%+pRd8u2ljbXr7_aKsR1HnXM~^;Gz}r! zu%JPRB{$lx?%kp8+oA4%N==dW?NiUn-tre9eP9EQpn~>1nE6nA?~-pj)mC;eNg**d zu`10Xx=qX$?^N46q*&M=w)2vo%u9K4r+WAfH6t%M$HuVnBkRm)B5of>)xVLm!kYwem$+)RoN=WXP@dOO1vkv zD)w0B?s)0)@jo@Ia-@9RO?OjKj^b=YY>N=C9flz5>AD}D%K9T0JOJhU)6@zCRM)W1 z4(Q=*X8nD2*)P!8|4EP0^+3WH-I$LvPeQ5xA?_76NbaS2tKP;yk4M*UJ28KzR}3__ zkN8X`CL0s>b=UidbpMOMI|3qLwU_? zfY8+{J{=me=dhpn>v!2&m7FB~^mvCPy77q}>d8h$JJg;I$-X`CC%xNNMmzh6lYht3 z6WHt~vJTG%mdPp?OtBE;thSyCsxu8~!5OU0bJRc(;Nc)XV=$Q^(^~Ed1IZM5RObRIi{RBI5ioZpQj8O0m6v#(%a#d35FXha`#6347P6zVVs(bmlX*e|+;g_ADm1 zcBtoMF0vrjjTp;}-=X%680*^`eg5~$qH_KOD}5e~pU?bRK$pa-Y+GY12AdtAV%r)U zA8a&f^iynQNxH3I@4jciG3@9x1^RfrDL2y)i?40jYX@yt`|rlt+io>>YzgQ83*L1% zMDu36C?+pn!f<{iP{E#hImg-+oIcAq43{%@D^wfK9~m#Xf>CAyxVHYyNA}dV!Jg`O zH8odHivkWLa{ll)i)Nws??{6?^tOvS%}#f6aWCSPsZo^UU{tw|`f5p6|O*uVNwGOjEec zA%oTg8)vQcZK{`!-L6LJjcO7|lZR%j^rnbc_d)^WIc#(!gLe1S&$IqhxFjvt`}GU{ zS-K|C*J~0JVNI3o-S>Bo=-Z1&gajc}?0Cm@WMaq_cR3yK{#q3t&hH0n#kb!hYD~OS z_*u70eTd&gzdLKkKYc`h$*0|F(%42EQy=eApCo~McFhBCkH3=dUinSYR{ppm86tQH zLjDgjrrXeW-p;&v7$oUYHp4P?iQdUYXSd&K@j!P8%QUzYO-o#g#wRXC0G(*{@P?k=b2x`(c~>^=yr98M4#|kW`um_C-d(TY#@X6 zgqpHT{ljpd{bw*^;^mR@>mBMF+%1Uxiztt`?!u-Nx0qOVyyWjP4_7Aseh}{1kc9d{ zyh`4oW)&t)^j#PDZ|+cI8W-+T|1#<+_2UlpQ)6*Dka*gmeqO6u#0&j*1-QQe&Iy?+ z!1Ho$iDpl`RV-BGB!Qg8Yn+>tM3u=oa#7>e9co;YL@mF9n_>MYUZ*_yb+(Mxd8DGw z->BonT)5|o*7Rr2R0tkQKgnsahgq{1q~~eXO+Nz-?pbvmYrxYlqK0ySd%;13eP2QE z>s5}@*D#Uyx;m!cKr87rsBo|1Ch=X}3Gask_4^pj`+&{#LlB+!ISb#zXu;?H%oFbb zD2(|t&r;!-%8y^9UsDtHEB}YJ_W+ElO2dZFnRch#WbRA~2?=BZfrNz6rGy%K2{i!( zL#n*g|MQ$XGf4pT`@jE3 zbLQT2PcQFz&s(weTo}l;`Ve;Fv|gm++#q9}q2s6{vp2pl@$@1jQl)ql%{Yi7%>fEi zRKA2Kn_5LA-TwA+;@d0uMvy&7SU|m^`UGm<{(qt@Ir|r)-e&RYQ8cGnN?Z)%Shu~?KgDI{bDR!eLM-+x zh#-EAIr~P8livdU`A#g5|I*`a6FC>ghYW+vJ#XJra7HABQc2Bx9af2WNbFX@>`|l= zX?iJo?UujbkoZ*>Wgk3&L{R}rGBOX1fF>k6Pz3lcx}fzRC#6O8t<;uvm%0S|h;heC zkXRbWC88#=tF4Hr4!3YSJgvIZnubc!G-;@B%Xe5aat>R^&y;I_nJ0Hv6% zN-+{WF(e7wG`RP!JQORXMXqqCkas54g2PI_2C15Sxb z$8PC-P^@B~WXp(%iRj@6y4VkK%@(+cTewi8-H;xfD;>CYL&^oeq?A!^%3V1cG*h6RqRk`H%8FNAb3-s$Wo!jm{b2~u zh?5KfSty4%iQWq!1LY74ykenOfWWtiZ&mbGP!0R!{H_x%X3P>lXox#ibmLuR(#rGw5Qh}5}(Xk>WfmR|Vs`7Pbnt!=L9}95Kut8mZU9g)IPQ+oQ zI@=4wxh9m5FIVqf7hL1r#JAp}ht03s|8ig5Cxbe?OZ!8hJ&obEIpz;<2;Q&m z>6{EXm)ZW4n!no??B}qVQ^#>z&}Z}ICwEkHoK~+k=9%+bycTf(x<2`LTcaY0E}X(S%_8#HUXg3NNa)loI!{6NJe#u7 zh4@G=DH~l$Rn0GPcc&kO0*5Fj{@e|O&VL|vAxehDN+$u76O5iXyKNW{yx}4l9q54A z-WZ387>NpW59V*jW1CC>(_$j*LX}~iO~yi^7h)S5J_~GtNrAg8rlTv7zjM zn=;)Sa7vbeAU^{GzX)S!dpDSglp3(GoQYlxg@*KJ-px4cQ*Os7Y;1O#UHHbZRp z(x+tyyQr(Y;tsF4(<|;`hP$;_%VKda^xwQ&XFbG6pmo%#xbDVmDLo@q@Vm zS;k`evn&?-7(B}0F&|dN<9-BB@byWi`wO4?JjD>wjK$&r0|+vX63;OB8-r&VJjV~u z8`^tX({~0tw;L}em^A(YgSZS{VeqPWNv#~=EmhC$45oWu z6R(@%4e_S>VrTH=DR0r-&v@|&x%;8u9iA^?(gErn!Ck?Q>bzaSkn=0FV#}`JvcT6SDC?*T zo)ZR4z%kH2(wZ!T(D*UqrKypkc&YOq}5m zi*q35VHwRC4rPxr7a80876A(^RkB@Ms=TE}E zvN4o=?BF;Ubn9Kr;s1`gDyjo6DKRgo5@6B|!*2o2VKU4kTY`vf9d!zuC2xei^ zt^tjHHlE;fTus{-%nr;!acCAkO;l_51N7?k`OC|roa(CnOnR`Q8X znH}I915FT>fLV(WYeQ>(tHL)LjPnRrvP=p>!ITiA26bVW+0W*Qj|NjDDm(eH;HZAA zOk=n}oR->^;i*iG|WhK)j9oR);qhj)SOutbz3?o`yC#5gYagPeJkj-5<;!%;L$t201G+7;|ES z(O1wrIXR4DQGFAhoT$tIUec&XdCud(EJHgCK(EhuJa`FvZ9Ex#EXq9(*utg{6uyJdJ8Q-v6N+Rs5Nu>51KxH8s?yeLRV&aEN^#~*%7-Kf&-!sQ%R z*kP9#S;T;ibLqy}g&aT*&c~VAx`F&QKE6m{ zlBV4V+j)dTT!3a?h*}-sHjl$EkGC;^wPRZ!Z`*KqeRX*B$f-Z>c!T|ae zePmz8_47-Z+A!n*{tl!qK3I<~@q^R}34_6K>ctEpIm8bJ$1qr|^U2|c9N`D5Qp)&| z0ZNE47-Pt>eo)uPF&NKaLV%7)3|YpP$qc42W-5beY{m2dNC`98igK@na)nRMWQDUB zJ=>5cdgUDGdC9rVI?pev1#}FD8VuRPZe!@%dUhq!%2ByJx*d7)Qc1BSd6Q;zA?49n`~Rj&jmIppbT-)q4iQ_sd6 zVd?2lw}B>BwY+wvn&t_mH^28fG!W!AmGx#Y*9oI+&BNae?v&Z<;r$l~C{?O8F?NyK{9#-oio9vc$A{X`}HAyGKltg zeS*Q0w3&H}NrG@(u6A`(?ed;wwT%#LKfolQ3!Cz9@@WbzKNs_7{JeO|1Uh|{6pjUb z>_ZQ+M5I4&X>Sqc0IBF7DoCT!GF$dEHFhveau(F?}lZ)|CK z#q>xc1e0qQ*HWk*?SIJxwG9n;MZU@gzNT)RZ)RV0i_?>7in|1Ea7QEn@B?@vMF&!_ z;$a#=>=<}U{=<-Oo1n)XRF&sDvkN?9DNY_SN$_Cs9%RiUtLtKIg7!sCqX~M(Gui-r zc!N0KglU@lO%U-uGQ}owe%!4QbbZlbm_huQWAX`uPvvLO;pnlrvaty`%ofm`g{j4p zYwLSbG?X3rTtaGw^?qT>FPZ5p1i+%tHs#mQU8#K7oqpo2a7rp5VlTgy-OskVR8pVc2 zl*;>QyyP^UTGzjosjsn9OK$pDfvu8U$0XOsl0*p;Vrk-?L<6@m&5el1nmD$EoB8#Y zcqLdU$0oUrNw&w60OTB7#~n-(y%Qg>caAOL9)7+zUIO6Nu_f$alKT;lEq81I5Ay5I zcmaTQu_OWf(liCWLS`=v3AWvsZQ}B@V+j)(>hUjv!=sNN(w2}Mgh?v_LNOIL^BE!) zh;t?|G}?vl47`zkUTg%q2Z-H|>7sBoWI=cy3WS7+cMyD45GYLGPD!x*uPLmM?2A)Q z)`C`WYOA7xBI^l=(-DdKi+IW|%QX;7lk~tmwe`zjKX_isA_W9OUfJO4!T3JKth6M? z7I^}na!9#|(Bb1Qk-G)xBS_j?Az^UjAB^c_$GCOOGqnG`OLX1?T~%c20uN4j?Fx}J z{^pnXx>M#1)DIR2v9kjr6h#zmhIfNR>UMEmVWvM5LS}{9f28&@&;#{#-vXZi-r_=C zco??1dw>tJNA#kdagt$r&j~}QrSD_>-j5ErjqSpn>4ywkJi^Ziqr`+X8w4p%$n@f1 z>(6#X2cUcp{s!&>-!jv5>#rc#=&$@pL9h~h+zuZHnefz-$l5w5mPZl}~zLqZ}kSw<^VVh~>q;7xPJfAAoW4(4*DJts<4; zd81(P7ZKXY705?_-+tsCP>;q)?8O3(1f|uQ#klZzcr~^^z_V3&65e)+G7gfaGP(4s zxk(g6u{vzCr|Gy`bi}=)D`-Rg0LV(QA?E{>Ee9B@$5KBFi1B)HF`&){P?|2qzTSw9 zbs5MVmt&p&Sv&(8)GL54|G*ac9-!t3xJ{P0Ugkmwd6>9S&VwQ7li`NyRB)iyi95g- zzY9F^=)K_m+$VQJRPAMPKdAo?$dAN>^4}0!`$hYpdPJ{hxR^p=lOPy%0DOvEY^1;9 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 z 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 z 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 jO5VP!n=eyX%#-=jEE9m-FoWw}*R`FAhaU}e + + diff --git a/settings/repository/net.sf/sam-1.67.1197.xml b/settings/repository/net.sf/sam-1.67.1197.xml deleted file mode 100644 index d43aba4ed..000000000 --- a/settings/repository/net.sf/sam-1.67.1197.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/settings/repository/net.sf/sam-1.67.1197.jar b/settings/repository/net.sf/sam-1.84.1337.jar similarity index 67% rename from settings/repository/net.sf/sam-1.67.1197.jar rename to settings/repository/net.sf/sam-1.84.1337.jar index 8a8343cfa40d9fb09ee34e9f0cc16ef1e30d9684..3d28e1928aff76b4386b832384f49e75f8412cd9 100644 GIT binary patch delta 116072 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%0DXaObozrmK9@`6G9{v5j_GO9Y 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 delta 84050 zcmbS!2Y^&X5_VO;nRzp_Z__NZyR!jy$?Pr}7Fg1fB_{6yc+ry{ujSN&#Y2juSl|5x^fejTc-tE;Q4s%w6Dy4mL6 z8>fvLYPkF)|Mk6LTji#-rVa4e2ag4ZQpWAYv-~x%7c}wZY?{=*v`d@zss4V8XG~c- zV|wepD=UiHcWKkE_0;y|MJ>l(Jilo8>}iV^ELpi^>5O?xHXUm0Deuy3+!Ft}@HBtM(zf*=NV|#8crar*mds4bB-KP_a|`(>&($`Ub7t)2$nRHP-qav! zYS>f0^=3yFdh#|m_E+Z`s}w&SvE6fVb$JHFvtKdl-OYP_=%g?5VSZ`krL64gjKCl`Gv$|S!EP`b*ZT$N3QDwj%Ch&rk~>aOx>sw$)lRS{jJ8q!?Vh*qlN$YafZ?A(-; zYKGFyDWFQJjmsONl2Qx~8&Q;};LHB-~6gPK8I)P+=`W}-*4Xr`JS z8C-Ii(47otqb-fP-`SE#{z@VrsTP|{)5BN$X#)N1r}O9+AD(`d%W;!_^OKuSm~_$) zQaK@sze~nCTo^cKR(>|vWwP63kDt=%7cZN*vsW%YFZ)eS@l%j3c~A9Y#MAsVmD5ob zXGkrXpry@2!+z?*0eKu^a+a4H_^A=6c{wOqvL$`6Q3UwqHOE~S`%m6-m!>t5>61kMhrOZ#g zxwW6$a9fkx$xC~aJNT&&cl2{7?(D~m=pwarl}k6H5g;LxggXr3ruNnqs$=!Z4jG(UVbY&XdIm_q zLv>!KCCsC$H*{{o8JAeJh}K%PfEHSG5zUR%mG|Y*xVDTuUYy;?qIopmqJPn67JW%y znLNhgv9!wMvn@V{$3+%hUTBwIWE4bR>(bOap3k*-JXb~Px)e0}%Hj!p9%|=_7F{Dv z%%Te|x|Xi9coJP_fAp5wC{opRL|_ALwCEco(|6L!w{)95YPrfa{z;$Nne90wRh)0~ zNQ*Dv$&o9LX4#`&;*3;Do?`M;i>L8)`=blZY`;aX(;F7OOgGqlDm*#O(6i4hp20IE z?<|Wid-2lQbKCZvy>#r1r50aIpP9VO;^orF3SMdQD2p%QOD(>P zFSmFV-DYuEURU!K7GEist9Xq?b7+R$CtJ0Oe0?;Zv3eaArRG8k#x^T`GD zEJjUB@HPZ*n4aV81VHYAG(}ILn(`fA$=ruq*2tBMpG{ugB)Ygr*XQsoiy~}m5J`I zOmuf8Io(C)=u)~2jdZ0xbUCd;17S4Ok&HTOLN1e5n{0y!v({eJ#p!CTsi&avnzYw|iQr@9m0E;y) zJUV$g@Bn&_Wo?JCllDBwn%741s#xA>k~}Y|B@eCB)Wx(uQG6OO09v7j`THqZ%$ZhWsN<9I0KJh4l(GeV9O|&@%c?!9*PC#_Y zJPz7niX?il4IP%b(5VCvH0i0q>{Xy)-%8#<(;XD{OCoSpIKA8@T`8O%XclzMz0fsT zhQq;I0Ei&8=Ru1Ws&7U&C6Q{U1WcV`FnK`WH))71YDqWa$v~NOx&==TrTR#nq&((< zVIesC{{i4X!t0vsKzus9cLLtK0Po#sd+UFKH>{EP{{XPSduxK$yT%CEUt)rNfa5f; zCt}UV=w1xKpOWaY7P^f%EX)u*%LT4RG(AyGj|SADk5TRly7ITv2&uT-ZIpY0 zo}ha>6-u^NI?*i2$OxJj;&qLOchvn|CnDQjlvR@94SHPDM5aC;Esg=ws?h|DgW#35}pn>1_HZu<#ic*Uz!0eF8H1l2(T4Yq}DJu7#u` z{NNJM^VwLD?*)nkY1yEyZAcqLZRtKB(1)r=&<>613OXw`B0XsU-A_9)N-by#J%F#m z6gDO1?IwCqBR>_KXBRyL-Hh_|V0zHnPGv&A zC0#P~6`}^nGb1}7ziWEA z6}05OpL&(28V6G<(t;^L|90vWObw89+?1~4W^@ZTr>#ia$t`I&m(pWk*+;lF9pg6i8n>nQkoGaRr%$;9ea@ZeUtCVV za~F1VSGKqtXK_A7!ZI+q7Qlpn~ecnGiK zVM5OUp%5ZMp`P>^SbB2wqz{0q+v!Q44%Qt1dMxp^I`Q=!uyA1sDG=%RYnEU^n16^K z!(VC`Qv3s&JEUPM1@#J^4$kq4<`aIN0p?YU!s!6ykvPY|(?O(R-r?zSJYkyQ=@6a_ zAb*?YA}$QU?RvtwF#tEvVSwoY>Q`!ZVqyT6VLb_7hM6{i=g<>aSbW?Fi-Rl_ejxpN zEHi)_s9Z@;;mP7Y*ian9Qz{Px*iU2mN#k{pc%P-`0HE-vY=GkQZ8!Lo1Ilj9Y?<-D zQ{W^O2wyruX(l~i2S%C_miaGSY7hRNmxsTgTXoc$GS2WtXN+^Sw(0~RK2B}j-a0Cx zlr!WP#^*js+06aGZQ7lo&hTFxCiwzdJx;m8KF{1RAbY{27s>7Ab@+$Zmry16*cqDD z9n!fyNx2!g!A{lTaM(6z)*GfEwlhY44fU&`{yj0j2kaUiXt+xT7d$dE!F9C|$m1{y zk-^KMwOoPOuoA535^Bwt zQ&;TMdqE7G%&Tb)UqSctmGmNCML+Ty4Z6ry055^cpY?o`-u|rTn+)QQ5Hn=vWzjz% zY{*jG6j*v2Pa=8krg!k<=?Wwth8%JPBASdtV@f}P$u$6z!5_O~9hXUv>kIip{ycvk zDteFJk8B*39UdAJxGLPG2WS|Rta%4$xJa?fYf8X8%26J+llbsvV@2WXUJ zX%KRUOlP$UnH8=bbx(y{l5_NJ)X;evbK4&>QNFG$gst|-@J)A7s*`hM4UOGVcXh~J z&-z7>CB7E;y^c)2o-)8~+JG^1<@MB^H-f#~2rj>g#`0zw$G6ZNwrMHfN|*9&;O@7B zyWg#GeHKvD2DthFvXTiAViiQSkF>B6-jW!AEt+r20BoVZYf06>#zw>|7r?jd&TD#{a*ksbeS#bcGNFP@_?b{@ zr16;SaPwYzLr}P#8tTQ^t*;)DN(Yq|iAPRTN$@?u)1NSvcR<5> zKjrgID&_~N1n=$mA@Jx&pt!sTc-xbp!F-yNj>SPpsyHUA6NFvo6PLUw-=;US6=WO z`GtJc*ZwFT7mEjV3h%4wl*T&vh3>j;u_JOupzV2-3RByWM-cZo}3?{<=o? z++G~ny~MINw)CahFI2gG)%VVw;3}L71I9E;Q4=Uboku}65yp$@RIFyeL@_gxzi4~$ zMKGky#oK&pp%zkCwTK3*#dNk>LRD%hO;pPw?=PAW2c~N13tT;7aeG%9R%<`B4vp0B z)ZC!R`ekF3`YrO&vhndA?^yoy=AW~`ShMUK@AG5>`oikVmVch+eu_MNEHdYs)y23KuHI99H@uHmri8*W&X(t0EL)OuKgZbZpV6jGb1iHg8hbQ85#H^WM0(=fFK zR;t@*g1SA@%Kn#o8!SuPBSp7P%Y1-L^&sAMQMP)B8mfmQH{E)1a34~k^HNa^+yM;J zV^pFJMjCDz%1=b*Z25K4Gq7Jhix!`UW$FdA_9CokFTw8g3UyPjV<_LGq3UhG{ytj# zfF`StXp#B^*0g`prRod1T75~ksITZ&^$l%T-%_>uj`pb^K&C&^VfAz5$ZcDARb;~L z{oFw#?#C z?x}O*?e2k>R`euV(bHZ%US-=0OMF?87q-dv|Pr>WvpDz_R~f_ zN1n#XWxQO@l}nXeCdlPHxlA;95;mz~d$_>l$$k*o`F;pmxNP7l@@1+#P4mn2>n6 zmsd#AN-tkx@}*MqWq!V#SBa4+Z1QS946LxU1^9{-u_Ks#m6zA}u}&=ahWTnKdX33z zO}^HT_4YbHNcDP?ZxHL(I+NFXd4tIt#RhhxpZf78lQ+A=2}|5Sj>xB*OupI6xA;Ng z%Y9gpZMobkplp$++vMqXY5k6b70={5(f@ILmzVDr;I{gB8*lgXJ$$d1|0JL+m*o58 zvcu&2{SdOwk;_h#AMn#O`8=5)^wSF7W%5H_epnFph?jSJd5@oF$@dMsS1?iS$9C{h zKkwrjFGsz+U)~RR`7txhwSKyo52oDo1rpZG5H;n-vwo%FqG%^_shJw_L29^ zRC_~?F~{v%vUKr0`)DmUuq!_>v-v^0{k@!H7v-6Gkx38ijlBQhFc%tqFVbe$F@C@L zr(ONowU%j+omtLV)uSH%Gn*fnjDK%OH_mrA?K7D=1!lnxM=BxQ|1@- z?K8Z{;&1p{+`Xh^f=3fMyU+pUnd9&=+OI6ToL16p`P-FKA7)|XzFLAeVTYQ{ZkW$2Kyd>MF{H98=l*O5* zO0`s)f}SlWa@XM;zojx%rlkTZ%ii>?YKB5$IYpmZ;!^_^v{bgrluy}q#%3cuGVD+* z<13XDS#hXWu#g*CDp!Rpl_x0uKq}6UJb$Rar$A*gwU4}is5nx7xMfO>Dg^mhs-env z&{g!b%JJ5yMwTjqXT|M@dl-#X6Z@6n+%(5hO;s}iy}6}YDD<`!EPvD`)-#t~+sc<+ zB;QM6-)=K?$~;Sz0ja9BYGYvuKwsLa_K~?qa#K5KT&s?j>O>zzHXUiq@7dqHsEX|c zKcF`wE_SyRp{Ba{XrfMS-fEov{Rd`CyG_WjBCq~=YxRpyj&_H{n1o#|1T)e0 zi#Q3w#yw!0g+`+blu)ux2GL_i@6^u^U>A+)pr0`#^c_<{-$C^H4!YNOOd#Bg@mGUA zwSsaL_1sfZD8|ze%ECJ8#sXi$uy{HU9YEV7u=ONpms~Jl`Cv9kgQ_D7 znuA>G9ENJD9HMA{Y5_B68M3yA?VucjX?HpwyVDEsG#TRP6xfufLcKE$qWpAhnF!*n z2iK+0J{`neo*u`JR|Nc}*vM{2XXQx{B^uZjLb5qGE4VUZXq@uA#60=QRt)}rSxOeQ*Jesj}Q4b-9a!a7SvK9 zj1LV1jcTaK`5MAgpcoe^j#~}E?AHX}JYgrLsUXXMdRbId5Px9@hnA7L0NSar@6LmY ztG>_k6Mdc!71(y&=lO{~&rkGuexlFwV|{)KHIEQ0a3*;moFBth{}{IPPs0;~6cV1T z0}!zU9F+|4k_`HKh*lip<=EU*XtW1#CJchhDabUCS>`<;i z$FEH4WKN=!IrJBLL3c7I(aD@dCvy^=%sFLX1s)~LJT|VS7**Mhh~3}o&^5^16Zy+? zDHZ>H4uGtE;v;Y-;*T7CF%-@&!AL@;ZGov2?-#*rFZ-J7&qVZRp!pj>^XmZeda8tp zc^vq{dDt9J!IpX!OpxD=^YxNuozT?i^U;I zg9Z*IblTrA{}j}-VrEf;O?tf!kA|kAH?ZMFf~l2lZ$dNWG(Q=&$=uBWQd5qJQN3kV zpcPC2hfDIoq3Ypq%+B`^RJ8Ykp#KB{x=#ZnN?w#tz>@=Aplsp=3WK2UXDGk^Yjfas zPIGCeH}^2G{|H*!gVy#st%d(ra|8`rytzKeEYSIcWS|i!t0x!-ulu0Tt4ZpHFVPKO ztQ!O^-Fq=)RiLu4)aMZjHR~&L+$r`aRpd!jV=%W|;Z7k3%4RKNwU<``2P zlesV@r@BMBI!ED}8msOp(O0=irBq4OFgQv4)nwn>vb4wL+`4RXqYNR06_(!355eJ7QXJW;dOkZ{srv*fYJR4bNAF`!N0)XPfkGYD}E^PQ1y! zr0-)LyibT3WrhNr|IxwHqtxd%p=|WHukLXz^{Xl=Jwkn8D~Zy8M5p4ks!4_2(Eq^G zfxXZW`KU3cgkgPzhLkgCAh=V!2Y?|l&_kga`~iIt7Um`+Gb1Ag{f|ia2`F(UT_s3S zI-D(*(OMcP^T%pHgJ6k>(h!+5N>hnr{3wWzHD)ky7H8i-1G|na1X)1Ot4LbM@bR%ge!SY=iU%ki;eAPi4?bhqg?=XMK zBUT>#tAkI1aPXvW5ONaVOthfIZj>QbENhd@g9m{cX=vd8Cu-DQ8lAvL7<7LsiHre0 z#sVMb03YLkk8^>KD&XThs6r-cd=xp&C-5;afscVPe4I`z>>>v3#bz>y4TOYdSC%{) z{$G^-$I-2!F$Z8Up~^-L=0x#yce#EQHcueqdRk9lxA0K(m00QUg>5t*- z2v^N{a}%?@0vwchGI~D+y`P5OPe<=(qW81V`#IE;FM`=&F3d&?V31!#7xH47$4h8F z{9$F@2v&N+Na2Afz}PONfWUKN-arAfl@JT-KFFS*0d+@=rsR(A32oXK~4pDQwsUNQhWFn zz?hK=*L#=+LdU`Up3q3u+aeA_%>wX*kv#)UyKx^QbP2NTS>U>d8YYv*rKb+BjdKmr9@*Z^pWUgoq--N_=4(msr@wB^I`E+=5%8-v*d(D=xv%`Cw)*rL9t@*t=u(Gcln|eEYb_(Xe@qp=Ii9jdalyb%Fz6xt?-;fv>|f!BG#bfV{C?SAH?14wMK}GlK#jk?(7dt2QbOZ z{Y2FW5c~6hSVf6V3Fdj^o9oU0*}H)}NCUj>8vfs?IEx4C%tuzc|99_(@X#{=r77f( zeLDr|;10tC1K{18aqo+{aU(P>V*DP5djz<-lDcnzl12OyHqgzu--5ecnF}}N4RGpK z^bo&J4_Ag@t$Ur{ba_v;09F@#+&q|xsw-g~f9tJz@9Y9A-<9K-12al}S@!z_4cNnQ z1Z*^I@ZosJM!DQ*(k4G9^k#X9m~@j#H~Rq`OkF13B8j#in;n?COxhwDVd`?x?UHtf zJl$#1U4G;e6BlijT-)TbU0&~z5BK^+i|of`he`KCS+dg)_mT}>f{m+yVBRXAU2;JS z`Sg&Kc-Tvi_{F;7rM+^8b!#_0YSKPvCZt_tYDH1G?Dx_ElOFTK%eU5~gI;=EDmf&T zz|!TSBLc-ylb+D0y>~>3N^1`2_SAjeoHQIoAi#KhS0lmc~5e^FLiz3r4LQ|$fUnBWiGgQ>B5Vb z_MI)~)cP%$K4V(7?|4rYS#{!J|HtT%&Uet>v&P*iGVA0^{EtYN-^Zj*pt<5keU3%v zQkA`GjL{JXxp3gg0;P;kvLOBY_rm5A=o1S|)mRH#c$~%hCtWF7r^#ie1?L>3O`th; zaSugI)<>%|#L3tpzKn{VU^#sv1r zv9w&<%^V6$U{jy3vqbi_*iV<*i>7d%oj!uSc9Y?pDJCR)K675)1WrMtY{>;8MViIw zoB_iRifm`@(mP;r7B{ds$k`U>a4sYh3sQ+3n6y|dI&f@-k*t^-o3Jo(Q*H*ICX1U3 za9GZ?kp{(E0TWyz*-K>vuA{m3D8)@+X32{z{KaG6s(4O;cj8-d+^1y;rPuvB?PJvh2tiKc}6GP)=Yd!|I`)rWW?&DV#qZTD2NE6qn=Z z(Iz2-qtES+c{~8<9EgKXXX%C=HeMEMcph>>iCc=>{6rg<#MIh6i2)Dq%i z>F`==g&kV~Hh|$mj8dZjWEyOUi=$LJ0`gJW7HWoDYq&JlQhqFFVW15%AsNCFGB!S3 zOKq!KqhMB)+U-V_`Bi}qI78C$utwo*nnUf;d%>2Ybv%bcAkj`>RNX2%VAfVib^g5JuijJnurL?5~I2dR48XK1Tw1)us~5n%S+CR;zSvohL6!q+^{p~+(*V9;&*xM zy^E_)L~cQ(!b4 zmcU6lMpljux!~iS0@BX{VZt#H?yhq|#Pg7M5pvI`;TYI47~1(j#WJ8k$Xn2q1>{_& zJ)fIWGx!f)j+%yt!6D*!TAskuawrW~$MEDQ<7YW6xw6K9TRoLKCkIy$I66#FtI(4$X3}b~v@5`huF}1g$$S=csaN4hk3pT`)_OIL z778g$PjqoQtrb$hULDCP1pm0sCS7|R`fQi*=2$1!;!Vmm6WD4?;skEld%KrHAuY{s-NrdZ9Tr;0E%6QVcP&;p_~-v8j6vtu##pm z7zHpd8Nt55Jq|g-*e2fV!rYR5Jpom=BmBy|(W+0F)nv>a&f<;LrqHA?|Mk$cidB*! zGQCXy%BT#TD(FSqW%8pSf6|g(^veJ*gT^rSc43HjLX{YM%WVX2tjyTkOKMTSZ$d=h zgzUD9UD^83cyw^b}aPBO%xIB^ZH$xpnk-OfW(6K`)l0+*=ebR+F?DE*#)&RmI zk8_s&a;eXw{V$_WKE`4sj@A0Y5l(llRlJaqv3}9m&+viauEsPsMc1@gsc77{lR~&jIMxh6c3hp*O;^xks$~UYUuc&O!wyk16|{n#_yBo$A)8G^b< z&=Azy(ydxdZzN)Rx`^p*MNDr?a78NLI2Iw}NUb@;nvQ%S!Bzi%X z>dM}()Xl;y=xE>FK;;Fy(rybJuCoQvyPqZO%%Z9G!bdqTcaN6r;rv2TRAyo4c)-Gz zwN?i#XaYOuK}#GfVD+@HGd_YgEtn6Vu;4I(j8D>2+OH@Z_P3`k5$B;~uwZ=qiv^qg ziwRdG1V`vfFG(bXSHw%`igsD{cSqROTasV3U@$vm!D#$9iI;%O8}z0Hi|N}I45#l} zFm~eW`}D3!ABblXUOu9~3p5|sM@WE#{tpqwKc#=#SKP*p?-9{^cMsjz$HtCkbQ9mEkuTHs?7u$`u0KrJEB5mrRenCC#A>V>;J z^(NVy%TpgLzan7)!%`X2=7J>&|IbAXgF-|Uut(*q>~MYkrQmu^z=WEjbeXQ-k+E_U z^~=`NsXsSXzZfw4LqLKE1QAKL*=R|%M>`f;`nm)rWt^Z0xnc(nwK#J%i zE>4xEBnANnbZM~)`^!_TLalYqc5?VbejJ(AZ8nleoh7FtC1i#GQf|DN_jc6n7m(sD zmEb$pyHG(5<-y6O!W1b>RKwt7S2Lm(bRQB{-LP88Y0Fp z2oNc7OKh&w{HUjc&IjItJd#h&Jew+9(_-1ewU=XgnFH@>9L-Z~@-e z^~S>uGJ8R9Jv;#OQpk4WkxMopvJN`mCV(`ZZ|C8gv*JNRjALt)ekbty^G&+Iq{-Mb zs+5zI>AamJ2q@txNdJ|Z$rr#hRqsxOTCV{rMG>4=B1F?LK|~U)AYasXMUEb>o_;St zKPLkpQ^4t_X{A2rHOucm`se9KyaI zUm??RZmA~dQpkWkOF#(bh}I5;Bc*YnwvTF6%M+} z%{69S(7c@n1pdTecqHqPsZY^YrYGqQu zC%~B$(fHi*#wP+uJ~0vS6q^Vje#jx9f0-+&FP5c|JjEu074n9x(ZV;NeEG$_N+ zbD2e6fIcH1unC0m3FQ=!3FTxv57}Z9%5xH;n4VJY=ZD-cB95B6mFHjRY!wyBLE3#tn>(#?S^2S^g0~Qg?T0NS^UdlpRjvuJsvspU8;uK z{I@JI)woPaXYX?thU0E*Shi!`yC;mL?p}=2pMb#ofZPXwv7h(BItYHW_mn172P=rRi zHBnDm35m|tPJL`7-oELmX6Gf|&L5#}a3$Wp8>7PYZ_CE3*XqUFQL|KsdLjF|xoWm2 zE{HxqrrqJkz<%Yg6hX)wH)^}h5|w^FjyVLWr(AmZu`}vzQl%&<`}naq^h=RtHAU7` zxtwLvU_ZJwM3RR}hGBjX)Cegz(xg#1(?B?;I!5%HeM}l_(%JUbCF)0!&}>L(qoeyT zR%vXWW70SiO2ZeHsYR&>Qec6H7dv`I2`N>SO%qH}G@eHjk<-E&1b#xuxp)+N(R7vO@J$Sq;!p`AL^sF)6&UCq=vhyQ8ND!vdSfPtTp<3PUZkZ0e=X44X1KS6 zMjX2*EMajh&IA@pH5O-Lc9d!?&J2S|mZG;ljCLDH`7TsH9P_n3xED-u;Eo(i>4=n0 zNNGUE2|38!`6M+ksobP4$I+k*qNd2LG9W!rwG1fMg#fUVbr{difH?cz{u*RQN!c-Z zG%7TFj`Oaf9!awollRd2va?R2+LJ1>jkE1}oqPq+c9$zx{S5BDT3zT(%-IL7RTtE6 z5HmKa5KPtNY?IsFqHe7(_tF-1BC#E;oYwP__t4CH%HER(J^AW;lokDbyZS=KXZ1fn zs`+*&2u}Xm*xx?@hx@yCD1WrYeabd?vYgavhZ_!R^}?;~18TK<3WjB}9Mx(S-$4H9 zrHmV~3PG2lPkPx~A5l5c{0G%eZ%TIzh716s_RQzq1@@QK2te4~{&%(N=j(?-?T>;3 z?7okx$vo7)=TUWS5FR?123c4<8-b-3VSNE<*p>U#-qfC;n_eLD-WcBQcHKUe0O6g% znY~6sbve4!F$=xig;VW`HQ2-A6w@FHe>epS5@v8(gh7NFNXf-8*#+~4lj4>Xk15d* zQ=Am9r1<3G_i~C?LLv^5kcfjM&|$h?91tXLAVrk)ri4CB;cU6&$R$^jL*W$B*QdZ+ z0D9m8Zs>>SO(XeIB$r}SYwrCxnGPF%Q@J^dcj)Eze(K0Az1+b^GZ69+mrio&9QJa#577y`NQlC&a>2Q|LEO!Ulj9X~ zDy+LS5lTUf3|JMw!v{$K#60fp=SuEla$ia5Colb_Q@9M07>Fr|frzw$CJ*w<8FU}R z+9*#F^3YFX5XTTN!%Qw8E^p|}IRYKn{0JT?b&N83w3o+td8{9Dt_ zqP?x7JI`KlKTh{7CPemwo`G|zb3wR;I4iXMReZzh1%x6@Av6z?G?VeH114|`T z;yUcv`C=Hfco}W9FMLJ~NLh{mg}g#*6P%Mv?>?j2v{?zYfQ~>2YwAY8ItU>YFT?&H zX_s3NJ^{ljxrBMO$yY>1R|PZPl)A6vt4u^DjO+p+u%kv} zC!8>}7$*y*L+@CSjTYG7zlf7mqt3~RUiF-s%0tsL`me z3X*w!I}>8<#AE7RWAA=d<+i8?YH3ntGm-g5>^uOB{q3olSDZ1k69n%XJ3K>WC)Ipe zQf7CeX6W+-RrW=%L3XbPV|7wy?cIdc&&E9b@pD1M$VbkW<;qVBd+bPMF0+mebVL%bDdDg|Qj5Gji0PU$?9PoHfgAfuPhvauCsW&4MO^yI~55^jR zvacf^YaIGSi^=8<&wdJ?j_jkl%D8z$dXW{M&xoZeI$m6_v3tCsE*K(1YL0)`AzDTYZJm-ubyOh@ra0!!&( za=oR7YA~D~z(=6}zeB$N80_pH*q(d>D)|&(d<3@kc><&+5CfmoAf;l*^b~p~OrQ<$ zC}d5bGKYp_gdo+4n`R3q%AJI#a^}t$l#skRB?0@zw^UwN84@QL>DOQn-vEg3k_I#< zsY*~rD#}WLD;a>Iw^c#X?Eeu>{**KbDG5xah>9LXShV!I=%Tk(%cO>XLBqeI;otsy z!!JQ`DhBv;_ReGPi6UUpb%sd zY25zd9o1u?6w>Ab&O@j3;i6iIqe2an+AU3BUFccbl|EwR8sYJ6khid^i{Di}H3FTw znn6@;4#~O&0*JKIbqW19!OV~v3{2Gg1e+>L)L#}m8CK7xB<1~Bi<i?Jy= z{q7}-!U_sA?P0)0y!&{UU~rWI^uzDq%KVn+zzt1M6HeU z6LIfx)-Y|jK~0R=1zZR+o_S9-A1h_`Bw*~txhu>8-IB@&6Xk<&x{~8?^_`ZK&ycbZ zH7Lwg7D*A;YwSMnt2=cEwZwwcB_{X6PNxz+xqYbx_rv*{{;;|aK#;$IbS)1;P=&#| zQAa(pF45>Z@!dj|g^+r_K}VDx(*|(3PJc99W+d%IJd{e-#o2 zVD%HZh9;agk+C$^i+=Hm-1#_4iF*)S>EYrWmooA514t+8Q%mPnc^-!wwh_o2TjdH& z99!iMOtMQqQti%8&=!`3B5mS3i6ROvy3=vb!z7tXgJ@c12#T{oG_x{ za~b8S%k7uGP``w(pj34wHBeU}YRwudQ&-b{Y8^eOHrOA2sV49yyZcwF54Itf%PnFb z{z~=Wi|i9$sqS(0#PG`}bYE=}VsqOKe^N~)qCkV_>aW!{51(r{{!x7?stfTgZF)|1 z<7n)sHG^v_0*3y$Yhu{tlO| zg7I@zxmH0$ZhRosK5|^8h54k9*2zy5tm9I-z)y8Ox0bXva&dmIz;sgDOA7Yz>tqkV zjj6Jmc3IjIqsj`7z$KCw2S@!OmxjWp8;qnaKDMRtPnR|P=Qto}^f}Q(j?A$55 zS$6H4W!Jt=p4RaIlLvaSad-CYn|X+Q9%?c)v6~tD^=7h9-z@v|%?yR?W*#l2ppxB; z-8wD^tJ9OuF?k#a8`gAbyC1QX3jwu0j`fzJ6UnKXra+&9+O77+5`CeY&<%M2ei_ua2pM4X|h%uJlPze)%zotNnPoMslz9!-o-G z3ZwaY`2ZY`mS{S&bTl24H^}2gKh2bQI_q>i9Y0+pDeE|5@=acbgYkSp$4tJ(%QjXb zaOp5k$iTmN9YX2g>2{Ohwy>P<^zmJYp2J&tndtHizJTD1j&6L4)XZv z3aNEHLg`@4c6#{%FT&>l)?HqHNUDC=M>p{!ChsNp+498T(L{#Gh$kZ_F{$?VfC;*nh6&fR0IH7i};bMpKkA znz_aN^eaJAz8+lO-pKfrD$@@({0GHX>^JhbQa#4MB4vBQr|CV3aW#4QX z1+L4mqmO)lUsL<;JfojZHhe~VKU5NrnOrM?_3|0#L2-AR&-jbE*<_5|0eha`c&7lH zK?_1{wOnfC0$+t&X^Vx8)a_cCU@x4davE6Jtlb$?!(b}~=UrCz=r`TEkE!-E*=C0Q z!;73L-AlC(Jm|4h=T9Pcgw_ybA7O6&`tRog5APTi|phN?1$2gM#h``p$?m4_l~$) z>JJ~;9Wsn*?ROH0^6wUZERNJWB^;1M0%D*1%1kYS0SRzB`7^obm_UB&SX)c-N$bfLhn?}e*JqSvono$o}K)aSYURi8@U0Hl7(PG-&h>r zEQ`OTL-w-?hx5BfJk0|A?600AEH`m(6hdiwYmhKlYu zH?h|SjN$YGu}q5%YLo#kcAe6truL-w!VX=^oLk9C3J!IDZc#{t%i*^ zIkEJBRAApxXyk_L3oJ$(OLPHe{|YxM2+Z;yJeaU|m$oqMQWR;Gs9rV^uxGImbzFv% zo4*95E={VJ(x{LqzbK}9UfOsvBAZ>&f(B##dN(4Z<1MD!;)9_>d1F$aHX!11bk6R^L9 zjmX=e*>^OKoEe&zXeUp%gUC#=E@YxDtY`nN#oVM8^{>)6*m7F@7%lz-Eq;m?|M_29 zJf*>>!ig690A+$SQS3^W@=nLuH<+#8CROZ9bj6oI8J6K#2ZqF|OOuc-x=zt?*4OE1 zetv3$&Hle3%Kw~Haay9{G>rS5s4%Ykxz`@m)X3KC!C|f^bukMWBw~a!gbb~ZD2jyT zC94qOnN;BDSY?=Wd3Gh0kI!@#5#r3{wJ)9uYZ`Sbu+CV)iwOXRp&|h;2c9tvah?LV zMn|bA9>`zdaR$+;E|^rEM1PX+LLZ3M5v-J&L=^>^k-ja6QF*b{ISgSsiuA#KP$mvp zWFOAbakv^EiF>pqXcHP4Hy7dfR51>kH`Wb0v{@W$&<*d1SFqeUl;RbaHMls7K1-sG zBWUp%Fx$l02-jn_c~Vd6F$>`f6-fD0$PJ{?w4O8^T}oSQ)g4CcKvz$0VIMSFHtJy! z0%G-b6E=W)@pB2yBp?VzyLpsaoDNp^B(TyG1oH;wssmPk@H&|V8S!cWTFcYw0saXZ z6k$dVXc@7JP)w`31TrUj(HSt+>U5BXC4p3rDJN)=l%I)-?Z&-99Hg+0IZ{KgPW_>O z({*Kzhhl>SSPkeyXmkZV4YWo}de{Km;$t99o<0G`69onQieq>fjV4|AhL~Ulg$BI3 zlAsPtO}tXKVi?zhiSDmqbxVR+OudCnipR3pHgMo`~PIIh8{gAt3 z@SlMkaIEGJ=-Qlw`+9P46lsEc@wF2aWyWz|3a6Sd0zCbpru%eFj-->BKzwEb9hot3 zIi^!X?Mj?cp$p+W5Lp{NdD~V6+958~VI*|GU&pNycn67{;)y+x8t#lUMrx}*SokcF|Q1nbakv_rOD^4zP2dT*(Fvz97xHmMK1 zY5E5GAtr!)#to-!qBQU@LZhWg<__RoJL(>k$BsCwgRu5nPpOCchFr&}TXJQC>MIMJ zg=bXd4Gi8v?!XYd1%}o)5^_s0{E;D7g&Xi9tUjXJS9oHNp2Ha8q3mHqkixl;Ot~Xa zhUUQd%}yj%L%sPZ!l;0|Gk%wbp_#>rt8#|ni4URZQFu8#0gc0-;coFHqTWA6EBP4N z{2bkm-P?Wq0)F)3B|3uW)lcy&^c(*bXG>p444gO6=v#VFB^I3=Gyew5pXl4dcWPay z8}5Tgp|Jd3CJOZ8F#!TkKWI&8DYE~FQ2_j4+fL!1Kuf|ioa+9K>YQ)#Bz%4arDZla z0p;Wgf;-{QFr=9D%L#GR`z6g^2UjRK9{q|l9=|ZY;)Z`@ApQaVnRL7k#4j06{q9P9 z$1jqm9Y(N*w_3%S5=-#AcqSs!a}uY3J(GQUveI zaroa^3U#aq{sgPjr-;h`Ps9@W92(;<5ewp5M7sEz!sqfg7|ieV;7H(ubFp8m15Xkz zIW0a8c#>F8!t|ykgwSa*Aym?24RL9#BO-iue%@JdNrLr2)D#XH)I6X;=4b!XW0VOW zR%b3&g=I2IeuW3WmVr2$7gTskLY^p1-a>;l#*p0) zx7R7RQGrGt9Jhmrvgx32sz%?zkf(;G>91u;AE)b&cZXmGov|g1V`zpm05j3_tSV{b z!gxKib=He@%X4rXGdb%;I_un1vkuW&=WU@5tufTP{aTt|6<83Zg@@})hdgDma$#De z+lc3_tO_g^ZUM(b46m%c(j!QFGSVJB(g4sI=^X9^OGkX9FTrk(_(ueY{s}byD@OV_ zey`#;C=5@)NO2MxzdHOTFyl9YVHj5~+Nj)glL~ui59Y;V%8Ov?2h-IWL+|Y1>9CU;TYt9pQ zi%}FN0ap6>%e~4KQ{fR;b70c=)zwRZ|@H`OHjN8a<>dv1g?i&PPKqLX-jDTTOrO%2^FbQYO2Z*62CR|2`kyf#$(f-7e^1=dmWvFh2I$w zKX^qshl!uC}Fmj7C7FojpN=AZ^$p0e>|;QtcN!IQ%)&>3-%KY`WeI4pMIdLWhP#T?E7 zO`ieY0T~?wb6I?4zg#cknT>Enc2zB1B+-WFO0bx4FPHw=$<;B=ctusB3$lpp13dPeySS?MUx;2dV$%?$fFt2E9Mx%nStT2IFTYhEQ`g6oWkmzo0MaB)Tr5b@a zG-D9#XB=YDoQ+sC=g@dH8b3NQh9)6xGSa3ZP3XhzrVrb>Fiz>kYxIqGalW|A+n4y?m1Ync3ac0-29Ez_qC z<-r;xRVUP8e(RM^ay7!%C6AQ#AJkW(-~4K$6cgNsV3^) zI$Hsi02qN(91R>xye4ONakU-kWMqc5xP@KY8XXU)f8ZKN7(%$9)4#067ckQl9dM|> z1RUy*wNzwrXQ|Y?Xf*}HHx;G*ct{M8n0BEUCd@ausfGjmE7^v5eUfO8@8T~n zqj&12+RM#!+-YG;jdU*HX)oOn(_+dg;<&;SQKGmx-rxhmE%m(>RCSKAvKhSWZY%-1 zH{&4!$>b*7Z$8~xIqX=k!zMVYX*kxqtyg>P$=!S@(VsdSX@<~+SO}y3ZpIZ5U1Dz! z4m5gWW;<`QTA1yRATo{om53{Ko?SHA@YpYpHcWf%ER}9|I?H$>FGoVX zR+YcB*6oe19Bn*h*mqrMw6`xg$Jplc&Yr(?+?2T&&#*`Q#nUj_Wt{P`dsHc=ewoCM zY=9}=dM_bJLR$$%?1YE)AEUHVSxalEJp^#s9UGWY_?=%7NkCaX=ylVeH7tU+S5qiY zOYJ!mjk8qKO#9J^#&T{SEt_OCXKrufUL0L|zOj&@v8tvoPRDli*9(lV>aqIOG-G8> z0;_W`HQLpGOMTdwRewO`(#MS@Pz=QI|I=&6W=yr%+lDudRZ4iHjMUoeYD-3}M^Ntd zcF`QT*iXKmebFB880W1|zjm-0Wc&resgUoI(r zM8303aVqz)y`b))vkW{kqXZ>uGM&3dyQ*@$20B1#S7-yAN}MCMF*~ReT^RwadCRI z<8`hg#n(m8zQOgm;v1s9Hn@J}UN;dufp4Z=VxqfWE;#cHtHvq6vOZ?Y{OJqkSx~oc zs<-iJ!=CeF@%X`O9oNP{Q9F90tIXI;k$PwDz+Jq>;@kLk3lRzLwD>OCWq-fKjWhSX zeIa}FCf7g%hF8b>wR@8*SaKJ=i$ib&#|#*7!Pq{-M-3Zb@m3s;#!s4{p6vt+-97ZI z1;@VUokm{1!jfRO!)$)TJk6Q8z zCOC=Bdn}HM1?~XXXj@gSq#VQrYKqV7n$51k2F}RaD&kthciC$ruFA$x4O)n`h&AFS zi{EBg7T=NI6^U5(e7{9M+bDBpBUJ!-9Jkl4$k_$_ zL%6%I#AP42!)29j!;4n6;oJv)eG>MoIMesZVST(w@%wSzYJYc!E7ZHbzzFc5k-9(; zY85k%Q$U^^Qc1A3=e~q`QXKo19r9^ z1zUsb?g5JAq>va8wm@#{3$p?NK~&;=dmP^m;af{G>i`MP0v!fJ zI)cBW2>S)$1KaSDZYSi!pAm)9FK28JG(dWdQhm^dU`e##UIfc&0cPG6t^6O#&I2&2 zB7gidZ};unY&K!DkVZ}DkOV?#(m|SZq$nT?5kl`EQe8l>feNCIVgnWN1RE-=qJpQV zp53#az5Mj-{q$6n|K~ezHwm8iyWf8yZ_1mQH+{ZszTcYuTt=hMu>I*n5$ORSk8rjr zM~l`0DbIX=U9j08$?B8+&!WuWo_5)!$Tb?VMw zGX`Y+&S1VB5dZ77vkJTOn5;q@7p`Y*7y=1kABK=>Swc25x@J1bK*@CS=c@=}3KiQg z1fZQT?KJtjg4ykB3fNk!fOL2G1-w88UyuJzGj3P#01e2zJ~()?d{7{K1uT+o`)&x< zvXmt5WoD0KeXrn?0oe`x_!fpXiv=XA`CZ#bsK`AcIyPP}AS0?7cs;K|6 zusV}{Tgtb5G0C0gt($|Bsb%*+1>4(N%3R4|fBA&&1Ym#?m!37l>=2?p8_elb-a4$W z;}Ndh%&f^qR{L{&etnTov}Q(ZeP5?vzu-U9P4ow8OY>vI*+|=vUcRw7J}y2U4EEzc z1y@j)%3Fe6ZC!-K7)8WhWGEeOk%WOW|4yD>0NZy#Pn6lZI8{HnfDQmk`5l?>sL>#Nrv0-FD} zfI%TR`Hsy^<^yWZ?^l1xA7l=Ty1swQd^b1e{@2_(VE2wN$lrC6+dR5A_~>A%r+;>p zvUWwylHD6n0x0X>VIcP4#_5^eoCi1cEmUm@^E>wHXY#py!6h{}J5RVLxVHwp{rS=0 z(+JWlAK7^3t>E`HfbbLV1<$O>H|Wz~hm7i!XMGoZ3@x;&e8YYVPRvNdo)v=#WgkNmg8)TxxI0okGVIwpL2+OW>)98)t4;4 zylK*+$uSmr%q$x2<(aRarx4)_s<{#~Umgp> zYGDLmW09v8%N_8!VYNiUOXaaFLZ6-?$(ExKEi7t>R*KG{QqeioL9Gdk#-XO_EEH{U zhf?yc6L-BlHiXe5G!@TA$+RgGnb~vYaUPeOB+~_9wK=S|$V)U2og+FrFGfqLgttlf z5>IW9fEQkdz99~K6d=w&p{f!~WMitPEnG5v+{#5&p1Q)^8g(Zp`_y$$(b3GgRV(`~ znC>H3MZ++CHo9&oXs)g2u5Oeyc3I`Lxg#nUjjKF;9vLYT^`qybJeY883zq0x6|tL!Uw*Cv?TFL4?a5X6!ir)h1`wsO_U7Ygh0wazw8 zJG=1)XeX_0qiqkCE0w0i9qMLlXU%++@76;eOXR84UajgB(Sq*F1wkxYR5^Qz*nk5V zzfIj}6%tJry+(Jc{c=?>aF@EnlozV{nX{M8DvAOL-53QdI-pf{ z(Y)CUs*2{%Ub++&l0`_16)mfr83isP#l3330NgD-Uj@=h=FS55qL90E(Y)EqOwI}v zVx3*g_2fu>ca=Wqi}StP$0;)R)^|sNP3ClT6Hfn8=H0WrJUzrb+%N-+V28YJ=Fo0$ zOtN!Bcd{NO_q{F88akBR?2ZF73HhWeez95MAWniZmRN!GF|J%b@5MWGVlV`KNZFT! zr?O+Rn)Mj-ZX>rmQ5uh;5^`kQvOq*{+|J&`4e-3gc# z+pltO5>OXwCU-(z%MF%2biH~5ih4yn&qZEC7-A2(*QqwB=qrHxRTvkIBa#z7Qk<*! zNI*2+4`N2Cd(_opJwO+_fr|SeDl#Efkunu7cGO|jw9pM!VC-s#n)-(YHm5+zjuS^8 zBz{TWAl~A4@xL#Y*R~!lb;4Fe%#_>jN&)w&RsodDi^1dOeoJj14@8$p4m)B$dUFoQ zgyLMt;GC$(Nm0njR1Tx3D=_Oo_R15qgW~ak8prlJQDYZZXQ=6ryk9(1Gv-GTelouIo7f+;s#7wHpqF-N2ifDMHW-XEkQ2vGVMr}-cT zaz60OU@8`r0fihnjI`ntEkh2~X#g{A5S1Q9bT0)-xLoWfjrOem2{A?AF<%IIsR(pY z2oN(a2kYGqv{;l}jQvHO^RvqFZyk+??8ziD+p;tA64DPADAlcO71M;RR3!k|CipWB zjKgRC_my7eiU&iz!zy`n(vt+0QPq>AHGYUS4dQLmqtsSrOJJWR5c>TOj1H!uI{>X! zz>4hzPqK@xgb!)=P4@&7ej+`gZTo?Ud*k($u=b_)HPkxhr+-@3G^*DhHfnNpqY{1S zV24t~qEM<;J_WO;4AJV97G@A-lXi3fM^3eMQm7G}lIo)4Q-z873n|Q>{lBl%z*^-c zva1Wst}bwDb%B)>DA0{`YfXWoU{OMH$)>cXbpNKz5G3%2LP8#9zv4sU4XQuVAoY=K z!1_w+pKwrq?JI!l%Xez`WeW1B?gzjs>4)?LnQr?bEGkJ-t?!I0zj$2*@eVDgUJ$LQ z?8%pAg!Cv$UdbeNNa?ZoN1hemm9mzo*Rg zyS>Mjb5WKdf7n@so&|}qj;U(K0Y4<7cIloG7}&kI-Xp3MdSwvP$CFzJAwSSBLp`jI zm+1bUuQI@<87MJ>S+j;^8ww@yoG3T49=j#QTI>CMYOubm{A1u~OJ-sZG z)A|fgFBkXBh+d&rN()vYnIe}D_KNsAFw60}S6D3i=B6zA=F0tpL2^4HS8tF;oGsr6 za@nglg{?hbQIc?KSd99P(6rIX@==DkZp^Io13`iI_qj($+W4@tKi%0w-~;c&`|?;!n%B!3k1>=8ZdG5xr7 z#36Y+A!Xs~iN$1mE2VXZ!eZKYTFSKVG%@XaftdDPAqfNeSBjZnlNYsg-_W(K`UY#5Txn2`h=zxzS=P2MAe(?@ zw^@p6meox8fWT&u9t1Y)(p5k^bXGo%Az1yMmEf-y-p7J3n$1P6y49`z9X?KS9-rtY zzDkOEo!#bf4E&0f-_N5+PoQe@X!wLCXJ8 zH}SC9tAElzd-@lI?j`b9q14LNf#0HHeAjby)Nvd->aC~~q>_&7gv_&@-GYFJr}DQz zZv8NNRh^8e6Tzackf1QDo3g2E!D}wlIzt9nv%2P+D}v21ksEjF`nGg|9&>NIj1drp(> z>myu2X&S0ydaw5K&2e4b@`gn^9(9VHI#H*oUpz`joZ%y*PBSi&h;`ivz2-EJIxU;S}wz?$hREQ5-DN(1R_==^uoy6BzitNn15_`z@V#h=&v*aU_Q=pKdZ4ZR!HG{j|iPLHV5)9Dp;ddsK<#*QRGAL|`1-o7%R zUpW1uDAeljBQxiBb4TPd7z1S}2gxuEmYMTcrfG4d&NZmpJXN0{R)M=Fuj%f-m0_M8 z;FcwJan%7COrTDm`FXoN_BM0C`L=uGvKnk0Q`)-Be(SOTtn1&}zu)=~l8>dpq3eeq z1e0JD*>|iV>k64wj?~A$^g)QG zh|&IyP+D-7Pw8*TAV6?4%Fd+hsMsS$L^|6yMJ%eitP$ck?^E8o)T-WN>WYIZccLhL zN8@|GC|fVsp^(J;aK9=fAm~dwvvZK!I?-^C8r&8EkVbn{A8{M+QC-DtvPZQiyBNO& z2PxX4iVvz{1c+=C<4r+d{Bl56S|CYxXwT7^lKh}*B?7haqypk?lPUm>-cpq;BscF< zr6O!thali_Sv=A1dgPq_?+^isW4}tude-n|%KFY9L!Gs)tmPbQYBbiPz&VZOldkhE_cr#QI)`%=I18 zV?;p>xJTvT7rSMQM6);ooz29)lvSqU_ep)hebt%3L)^m!JQOuKP0-tpvS(X$AA#tc zs&It9^6ATehZ`X1&Jl#Fs0aHdPpQ}=w9v)viK6u`npM?RtC2`q9w&p>22VGU6zvW= zT^O|TqlZ;b@%57Eo`{9+Ir@^!{-7N)Uwr>OhUt8e_${_dLiR0E1qo=pA}tdI)<#<~ zpOxDt{z?#^FJvsfkDPM0Fo0}OT1GoM%vKeq&i_l+fsz9 z#BLn7RFqwol z8;6$rZK@66l?}x79tX5vY5g^o79!!xex>)T;s0BmOX4G_{mBQ_$m*((s;PQueDncz z;z-2z%CSq97;`caEakDR@b1C%9u^<(FYsn8$^Ggi(RHg!<0q3*lny>-77BN}G4y6bY`#Y7-(SvoFT#3^_+U}&WBdwu^aV*j8 z^w`8yubu{*Pk~oAfGO3SE21sHd`jVkb%$o$pRpVY>2@S^v9a(mCb55?3d3#+1hLf| z9cOcRoX5J{&M|N~Fw+&xhpXY*$)WI9SPCyO%b#cdThXH_>?%Sh50b1Uz8_f@+f^4! zCzplra`m9SY&QTjEK()k%H~ig{6|>!0X{hfddY2+B6AU43JoAmbQM~}ZE7s z5Nmh1dc#@R6i58NbRb7sWR0|o!ReQyCn_>YYIV!3D~|tQocbBSa3oB(o`GQ z@lH0wigX*R{-}*JQcbfbN@_XQEJOdGeTh21%!GM`3G*5>=)c=K`nzC7bsZ~6laS>n zgOyrz2vo{(EQc?0Zgvmco1WG)natFvS$r0c)Nah=9*#G%U(MdF+8tDL=weL-JNI0z zHX*bp3x4bmT2c)pR~H`#OE;^cZ;^<{S-!u~#nZF4;Aw25rHQ`P?@I59qA z@qA)?NVr^mISaCMHXSk%k=i?BZ1%sX@kbOw zDy$Ef+hPML)updcs;s8J3jC7Aez80uf{kb1qgDX6tYk-BbwI7Y4||n0r%itPw3$YS z$wstx&(V)adDeeOHZqkg;U`=7ACe97lO@!8Ki!7^kgjK{xU)${kFP)wZx58^gX$a+ zn?2V`q~C3Kl}&Vj04T=`WkR3C8GbT14JI({Cvt{PQhhXrX!L2Q7?`Ry>PnOXAby_E z)79O2raGwSsE70{L3LZS;q7a;E&WI)q#8yPt{ zL4v4wNylN3R~OpxGu3g2pzeOJMHPq`u6{u!1mqO&qfk|4Q2(kM!and1(-JYU+0-7U z4UZ_8R-CGT;2GkHypkh`hd<72yS@-ZvGf>I_dJ1DRtV&B-pTYHThTcp0#ENjDd(eg z0g%((XJHw=5OLW>(CL>V7PS~@&n2ozFSETOhiHDP6*BjVt7m4hF0wOImb0gvlTy_J zGfGwKe!52*eln`lgLk@A?0oEeU!c|02UX7zrGfN1+|25-#%Y?fuEv(K4t=P13-M&S z5Jz5cmDx?Ii`vF7W`Es^5N^%tvp0M7nb^!+!8}-nnvd0Ngliz9ujSIpS=>xW_>D>U z6{>E-$#xV`)QE!5X1aN5AV4^v4r;KyR7-A5wPcJmV%vXi!*K4({b3s}Nwp#IhmCOT zMD|Bw10ri@Lm}FTl=UVxSf9hLaBlTT$myBh8OGRI35Tk>?nrfVR`}a#bE+&S*ya=} zBim*cnuoVr;8JY+Sm3fN9v`?Ac$1q+hgHuwd;X<6RAEVV44yQodD)($j|J%k%K1+t zS(WMq+RFZM%z$zJ`!K3K?DQ7y5nhDh)QhRZR@9$fiuT#dxC3-Kj15EiSJ;LN?Altj zVkiB8;X{G8U6?W%H>WxSwx({)I)bExK)64U0=mlC;^+K~oJ`aNy%qRX<$Age%c~nE z2pDJZ`_wppn(DOGH1P7rP$h+9+bNXfUZI9EaYvT@ZsJZ!HMgvK;u?SAUXdE~GB-V= zuf+C+Oz9o>s;g2j+m@68s!1mS9{$m+zKR{~Y9!jP0XMmpyEfOs0NRP=ylxu=}+yhwo^n7($pj= z7hehmaZ4L*49JlSlP*1B#K-(V$ZPDLqfg7Stc8f^y%3o9LEXKL$};|P=pk=zN7Ds? z=xRq(rfUD{7WCKc5e<>8D!nYlS58|37A28!^~?B-ddmi65fMZx*fP6t26oVLyI2sA zQ^_Jzr5>A5*1<{Y+KKV&l4|E6!Rsx>z&}N-z?Qy~9b`Wo41i_0mD0C95L2(ZX7yMg zk5IIHlWig!Go>A29q}zQ>}0nvAt#d0WoT7vY{I&;B{m?|qr0Sz^RVukI?luTID4Fj zb+`2L1sIS@1Dw@WyAG)9Yq%MG(sOAu6KKD>;efgkPyAwkIwkH>yQTmA9mSWzXa&cy zZ+hIb`pUR>mn6Ceki6&z6oHIg&|kvLm|XxTA}7B~?dw|~s`u;a&wUFa+s{|;hpKA2IXyTbr$0!pK2PbhAvKff>2x z-R@$D^mVb#@OB1|cTm4%jb=*V{Rj&kS)mWZ>LW3#`40(yERRnl!>3{OnYf=z3^F}m za`j!b;gbvz9Z!Ahsqf$!sCUEadvX66RzHaQqon^=Sp6iz7C(no;ukc2VUR(hf0GCL zqM14o?iU8c7Yu7RtV0nHh%g2!!y<_sOsTid)mdSkO(xV^^N3{%Y$m?C5wWK&zC2IV zTX#n8n3zI&)R#wtu!tO=r5mB|sGe>dM&?)->Ef_%DzVKZNppF$K)rQXw+bU=OsGxR zDz*;m(y-`#YA12+?^?{)LWtwedLRM z#oG`2i|E1P(O(_|!YIMQ9b}bX)zc@)>md>Y3+gQNR^uCEBN#tN z`BhMuPiN_IVPQRe0P9JgY*kfDU{WRo?o&KHIYXVJ;P+qA*F*9i@K9!xK# zOov5oGqYg1+rspk>>kL%m|Yb7bYm1i>k<(T$;2ujwMC<~Ug%T*7oO_Yi*JJQ0QusQ zs9vNON5O$FHJ6?0mW6Lpmq+yyz1W&l*j{ICUZ$s)BJP4x>ofr!ZA6`l&d|#dcrKc@ zaNZg77ep~2zapwv>Q%I^S5&XoYfSNlfeww<>a)^1t&h=V9o6UR^URzJ1I@#pK0hiP zG_(7{K+lu6=yOmNG;sc+Wh;wp#}!pBD_XR0>Fi~*7cMA5*EUM7RaQ~!RaHwCmYrU? zv}$^rsJ=*}t9z?e_Z8Km<62*)udsT(uhcuD`YL^OwSCvnFgnIco$KomBiFk`g8UG| zFoTBo8!S>iq`yJmNHf}cR%9G`apjH~*>A)^UwTL1EF7CZq0I|@QHw7QYwo>V5LKRTAE&sLkzk?z0yM&dtBWerm+%QDZ4|$k-v15M{rUob$E@ zE-2nFneO5tl#3`w0S}Q$Pm819Z}PVVjvJ;A!Y)${=2b12xolSJ6UX-(-lnLyS5YcF zcHoJ0$ODr1LCO0NqU;dEAB*Zk`Y`h=s!@8yB#T0_da;IAQAe~~F@lex?~41&e>N{} z3!qgBex7G_T@qel8!{ajQ(uU-@lS7JHK<9o1=%CZ%%V7w#OEQ z%+@JhjwxK?W`-)t%b}c^ZHwJjX5~{(wwbcT4F@`wmv4XgvOM$rrGce>OsDd4Gj)?w zkXB9=+Wy^Rx!YqsBj&mb0`<&*%K}B2k;-Y)s+KNo-kG#mi_0}rm%DYg|MRi68_bX`sRMefk*U>8%lJe)5ZL96YHre|zF`{8EhhRXwE%uC-|#ci)y z#cih7*MSSoTNP~L$5m%23j*WzG26ZlG}(U9rjyMf6Ns8yW(8W9IVPBG{%!&z%$H9E z+nDVpSl4vBf{9i4d>ELsuLxYNP1%k>qwI90x=Dxhv0Y`h=D@P5d#jsc8H;95G}JYk znQCN*a{B1RTWdN5vkuQcu5+C>Cz-W70@uc}=2R}PY=6eG+4I^X49A6q$_>YvXTEb9 zCsYyVoZxKhIF#e)Sl?hJvczVlLWII$b2*2%=Mq|$f^%93VB>(^2ioSeiXj{is|2!5 zNT46(O^jo)DI-OPB;gf#Il766@ zvIQ}6kXSpp=bOtm$ry3n3yU2Y?E==IOc+8S=oA3u=A8q}KPrgmXs9 zMFey?h9sL?+AQ5T72p%&E)H(GpkOF+@)DxzC}FtxHD z7c?uvj1xuf0*;sZ)ew?xDK`zSwS|=;>3c0TcfrSY0wo6Qv|xNsz{u4RAbnDcsJ36} zH+U~SzpNyVZjMG+`YVk$ww|C!0#?_aix+YTd@a08=}RN@|k1Z__2&OwrS&X3Se0HOf2e){m zgJj_|lImW|!ow-QPjzsx+AERVN<GH-Q=c>Qp=Cu?(ikX?xIo zv0p*Pm}-+p(#iW#hsym4HRYyMGftP%QGvk}O{K(lUFzj@d08D@Nd5&t$kzbZ-vd(rOs_$_=Pa~oCXmrt=Va>jPCb3L(wMqrOp~{oDKR4=RAF-WAqN^dVQ61hrY&1>g$}x z^iJn_z03K#zQOrI-{}0HZwdtU&4En4H;}9M1&VQ7>DvQk`i?+_z7svR`vX&RbuaP!5e(oGr4qf-B}Z!;wGP#fjA1=?w{Q7gY38rwa_lYdLLi)%PUeD_*O@v|qFo z?m~$~e+b|A;EM#xs2FC0q5j-UO`!^(MmiGv$EnxRBwrj6-V4(nKU{pt7E9RVOHpfN(4|Qk^ifz>!}Ak^`KbTkPBpo zQb*kRsUxlxn>Yth$@QuUYPk+5(a-{{A+t8Vm??Xw-Lc=PIh1^I?;(!h!+;YHBhLP3 zRiqE0CFw8Khmpg_I!bQ~F{oAbxzvgkA;+;a5rI9Cvu-59)sEl{Qm60W!vNoS;D$q zI&zQ7_JI&N5YB+ZJq0>3=;*`h%qvyjvilMe!1{%p9q=QrE!hGVAz`sSV z*`xAmBKWXU!aH$pY=QgvJzPuj z`G8t`2W8ZP4PoomfV!?BHKeRmG4zy2o^wau)OsKjIAtYutl3IXg{|010 zy>7oE!ZGr-w~!MNKq&~q@d0#o2g=M`^$aw>mk2`}#4gpV+Wem8*JbEaPfcz?hfQwb z+mkDw;i5SgL_*fng@CK+)N|<~-c$b+TbGdX1_&u{fGF7dDXf0xCchF&p19BfVMLEVc(-BW`-v0qoJz6y)Bfl{IJmFhZS9TOKS zU`|*ledxTAaJ{gGmykzwgxGhS`i1)Hb_Mb*%+MIL6KbDsggHAjoD_x8C!m|^X0%5) z_jC(Sw}KIY6m2~dn(5{w`>$t5HXVO+jyDr$y04hbv)xj2_Gda5(apBLGV-aj+@Z9D zto$$8-frKcX8ByVj-yMh-tpvvbKQrWWMYAPhRzfXMj^V*(`8oh)_9u(J#rz9RW4n) zfUEp7X3wh{0UBO8v&u}lATZWA?cIFyx4usOXtZj{l7&nBm*#~F0*y__nO?(c)EAUi ztKU%x@<6Pe6~w3U<3A)A#2^^dB>7)y1$AT23bY5Li~BcPf!X>HZTvkg;0W65e@8B; zh5eg#iy>wF9&`Ucq3YIV-rJMi+&+(sHtr<~a-21hH$!oKYmQh$#h{K)<>7QVY>lHv z)hw}W$pq^lrZZG%2$hS(Zwp2jVda2tf zuu45)rYv=P1;7n`I^rWs-6?@py4dxx0z1bFX2QlCf z@4D!&@;J`CaY>-8UQ~DE{u^P&&x;J_a$5JIYARE#P>z(S?nyO)s?Ov(Lsa*X^P#ip zwa;y2ZoVW?SV#AZ0%ASk>Hbm9lEbEWdjRSeM72R0VjdQ@kI_~hVm6nEbZW6!nBa!m z8SXz!$3!U5Dh*@58*cZu5rjw93XdW@x>oo^!eeTM#}Y<+Qg#0Egiop! zKAG@@TH%R=C#ghDhEs@`Tr0t;gios#ocWu2+ePJ;xaL91e40TV$n~|BqbAxHm$*TAN#zVaswfNWXi=nR~{Mih{{7` zMY5qQaE;GFxHfhVLZf2W72%P(u+2oAB&TiJJt|24dIHj57*Oa06#@bx94eQiGvM@P zBf(i0M7e<5H_edLXv;WsL2$GO{f}7?#%m1cjW6p-Z6I~6BP2c{b;)@(P!mKTGw;va3Iq&7r#3 zek|L5Rz8+(KP#QZUD;IkEh3G5*A~s0UJ1-$`YaLfVY{^?we&937-lhy(mww@&aU;z z^B5IrpKq1S;lvd|X$O|XmZNwB9u_gxMeL|V;34W_=xzS!_2%Q!BT$p_CdTuVs^AbI zL|f(4J{U05e%5DR3Ttg0Z=_mc@<=|r?LQP&m@2GxS#$qOS(o@_^{3d*{7KDp%?SAQ zSyZbGFoINlbaj1v0^l06u1PR2VcX$%;ZnwGS*^UG>bxO4F47jC&?nQOl(tEX6WAxu zTK#dREdvC>#;3n;Akq0O(R) ztb~oa%ERmH{a9m;UJ%Yp)QtK0wQ`Eyk#!_ZE18krseQZ7TAQxjz6<{_vrzcbbIxyH zNXW}MHN%_m$7vhmbcrp(pL4ax>3SBh^sSHu9lQOkA+^MGl3uce>4p>ISn+NwD%+!0 zmnRWTY{WrTG_frtt76%jcq_nhz>ci#!vwwIL7mKjK3AZ20>NHSLvN_nnohMkF$i%s z2I47Wdy}owo>Y~NT~kf}U>WSI)x4S|Mf(K@_I0c|V8J50w=dOcwaC6K)MkHB=-ss{ zT2rVX9DYy9v8sNyO(@7LSb17oDP^EIv;nP+;5&p86OX8p>TsCR0NXSu_RAFSG)6>Wo zVSSP#;wcCnPa}5w3!9+-)eP9EY;yYvJZ7k*7gAk zlR-NzUNXXOcawvvluofUIWexO1_%4XZax@pa>Mb%4~W~wFIB6nH8s1Pm0qZEyz3!Z~#Aw&p+v`-ujk)kN9K; zX+%F6P+S;Q$4zVttkEs0y4Q4vf0DdYYhbceB0c%CQr~d|2v7C!6{(rr(Uv9slCxj+ zfS4)eBM;eKwi}{)-XyA5d&NcVHZJ|pr)GNi7Y#n(T>X&g;Tv#h#_fm_WOysoXNg*^ z?pWRGj;Y#&tRQ!~)mC{?A+0W;nII9VYF?G9W*1Qv-j`PY|I~E$zg6{1Ag`~0y1oYe z{f2S*mKpsWC-XmR)wD}>O}jAbpQa)i|6bFEQd5M2eEXbhOutWpd97-Wo7T2G|DbXa zU|c6u0_YqsNVClIXJQNDza{>gpO_)9Ih$CVzaR2H{*rI+K;}(%x>M#2XA}3qYI38C zSQeO{J$)|Oib`Un(V3W3`4y(Hzlx42C{%OE{ol$F!irx`sx>BKb2$26dra(al5P7t z7yS3$^$i!SF^7%|{P)DZm4Y?q@H+Ru55>F43y~W?dN7_0`TOK-(U(dav8KQ61gD)7eopnD7d^87e=cLOP4;V%@Yx zPzK5gQodZsRS#CvD(aZXKDR+`OWjJU(K@Qzs0X2&MRf_pvF`ia=GmB&YbUj8AJyfk z%Nczp)Q1iG+!hTh#0HvAED>K9A)9oS2ZEXAy@lK}UNc#?Q zX(er$`jhq&9T;=br&A1Uf2>BG`l=g9Z(74nci#7?74Av6SFLbw!hLFm`x5R~D||fR z{MD4m+-t=;rWCY)Cw;oyr@=qG2tb(!b=IaSyn6J3{|L>Tdc<)k`<6; zGzkAHo~zBa_jFz>Ik)^{rJ3Ck)90v&`+$aWny$Brd*9=ZMT+l|d)#JyPLslf{gDgW zbO9L!%NPz|D?}sl`NfKFi!CBw4VxstEN7MKHzh8Ngj}(nCRnE$u|$U zmutSY^j>#V7x|WLpxy+nK)xV3b5)LTn)o@W9z{Wc{ZR(Hj4k6|_qta}8JFIFOc@va zdl~7>HD$0h*(Mhrbnl>uCl9)#>Q+|+TrpJ*Q~H40&|@>RiAO!)eoo?^4<3{Fjq1eL zK1gC;zw2uA@Pq7|Ys|kMbenXRk_EsJ4Y4u`a`Lr6G(^TonwnzLH4r9U2K%6p9afv+ z54lZ_lZoK-=*EGejEDOvcc{}8fNVs7(uD++4%yst!mc(qJmmIHNN!(*YZ|$yqspiX zRqoRf;hJen5wy_bHj-2-NZK-3T~eO-u1;07%#OOl`!*ob*D}IV<*0Ig6~*h?VZ8bs~-Ik(rxNaoX4cPFF7DvtGdbLbVx$M#a%>8V7S}IA$g?{6kGW~w0Bcx=} zzPs9-dDv|~Tq@>EZplTH3lR?3f?DT`ZRPyoYEV5~jlodUJ#7JXhZ6m|?y)6)d)Vz& ztEoms^%dOH*-@*hrIr@p4>?VZ)@LCLUtB6Q>tS~}O?~HKw^>Dcx+rM8`)uck?^fGD zX%-hD^XtarIb^>LOdWos>GWqik3amgTVla#QA%0D^1Tbp-DN2WNBjW2x1KsDZQNWA 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 + + diff --git a/settings/repository/org.broad/tribble-119.jar b/settings/repository/org.broad/tribble-1.84.1337.jar similarity index 51% rename from settings/repository/org.broad/tribble-119.jar rename to settings/repository/org.broad/tribble-1.84.1337.jar index c74bea398312b68b2f27a60b2061ef2ebf076ff6..a4c33610184b50fa34f6aa6da9595645945da7bf 100644 GIT binary patch delta 41067 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 z

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

?ufn=-m3=s3h) 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%0DOvEY^1;9 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 z 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 z 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 jO5VP!n=eyX%#-=jEE9m-FoWw}*R`FAhaU}e + + diff --git a/settings/repository/net.sf/sam-1.67.1197.xml b/settings/repository/net.sf/sam-1.67.1197.xml deleted file mode 100644 index d43aba4ed..000000000 --- a/settings/repository/net.sf/sam-1.67.1197.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/settings/repository/net.sf/sam-1.67.1197.jar b/settings/repository/net.sf/sam-1.84.1337.jar similarity index 67% rename from settings/repository/net.sf/sam-1.67.1197.jar rename to settings/repository/net.sf/sam-1.84.1337.jar index 8a8343cfa40d9fb09ee34e9f0cc16ef1e30d9684..3d28e1928aff76b4386b832384f49e75f8412cd9 100644 GIT binary patch delta 116072 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%0DXaObozrmK9@`6G9{v5j_GO9Y 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 delta 84050 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%0D^1Tbp-DN2WNBjW2x1KsDZQNWA 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 + + diff --git a/settings/repository/org.broad/tribble-119.jar b/settings/repository/org.broad/tribble-1.84.1337.jar similarity index 51% rename from settings/repository/org.broad/tribble-119.jar rename to settings/repository/org.broad/tribble-1.84.1337.jar index c74bea398312b68b2f27a60b2061ef2ebf076ff6..a4c33610184b50fa34f6aa6da9595645945da7bf 100644 GIT binary patch delta 41067 zcmce1r!h! zuuubB5Ebl-K0ab^sGy>c73>A!{mkyoCHVOL`o6zEerR^jo;qjFoH;Xd=A3)->AEMr z3a!((r|R$!xrlZy?$B{lofOBt@@}))u|wW(HL%~mHnHADB4^f-gvDpSe6o|1sFTxd zIGkgR9ZIA*`miIYdOg3Rx|@)LlF3a?jTz2qoNm199LG6EyPyHw!q^zp!>X$K!=S4U zJ9IAi?GUS0W%0ekH-!*w3Ngx_i8Vq?!;SCaLcNPTRFC><)Xzf-^>R>AYZk`K+obGb`q3G`%`F zp{2sTj359BhPgTwQYQ(`Gw%H*%IF&%5v@}P z>LF3{nb@t-0-YAp4aTO(D8XQLe$r!%k5s2)>dYw>=9wED(Pq&R){U$;+(y{@;Y}S$ zz(qYG;2}cbL&zae;q68UJwZy65z{!MtP$cO5J!|lPD-IL%0$^*YK)j@QPhVU`j>!T3T8lEgfkY_)<^@qwm>PE8Zs2#_`6vUTG;BZ4kAfAZkfEwW1JeO^v9H z)mjUrHNw#5pmhgQ5~&$ACl&d#0uW?T9!fLHr%*ofDHbd`V(eT3OH2Gk5nn|Esz$9e zYOSFKj?t)q+9J(?-0kpJ2>4WB!P}%uE!aAs?qU?}2nb35PpAJsU~70iY&H(t1I7+i zWZ`gpa;gQRP&QEyjAE$;SE7ZVm;ioa{P=NG9rPmpI{Zj3!Ot}uL z#w+7!)0AC4$X{MYsIwosGQ5QnLLy=^j!|r{^vt6aehoq!EmH_{xfWVN0zigP7wU>e zH1y@KWaE`=0WPu6-8)H> z))asJy`rhN_1Whd-xhXU?M-c=+RW6Kv6F3HJu2(69W^TZC&l8g$J_sQPZ4Hsk;6RK zP>B`pVJ7;(wKq2VQVDMZVlSXb40#+#z5x{)H@BF`B}Ptul%eIPa1VsKa6e;SexEp* zyeSqWseggw!~94;BtN%~V3$Dm%I=|0SBDk!^+eqOT3iHbTMWj#1kEf3pYc}D?Nq|O zZo-6K2c~f|2yp|tdkd!at(elAfY95hh;FA|bO-gNyTJB$&`{b!!)Pl_pu54g@1aSw z4V7+3sryjke#6=2Fz+!Q?XoB85!Aa6%^m{5?Z-4dfZ?e&=6Ah~j~SkB1DuZ`?Qw)s zjJ4gG@F`GtJX$D$r z4r&{O@8S3!OTCPJLze-|Im3=bjYchFfQK@S%Q#HG3Fv3J@!PPcLZ(nCs5h3TfzYNK zFAN{cvyHS7V=Z+5(mCj@>P;ikR8BNbjPA+FhBjsprx~NhG_}$bUvHONee;;^ihBxh zGZjnYG~;Yp4=XJ$t*TCS&bU9B2N_utio#|1-bt_b`~8?t@>gJ-TaavQpX@R&F7Z?! znZPQ@qT%Eu4NVG3s4nEM73ss_F1cuXFV~3!ZQ~o1%P*upr~m(q_(dSlZ9o z9PxRGpBhqtP+L%0JB)duam2gE!rprgM|OP&>zMp?K}+$**j16n;$`y_b4ve0KRI*C z%cqr%n_fPrsM!(hG@Lg1gcT*Jap%{LcQuq<$-0G#)40t!Y=U^>{NQ*JU?^a@O+mu$lZ_PO6 zAEB>KUHho3VT=DAE_25iN3;=oTR7NE(rr-<{`cI~rME@$|3z054by1w&zLj%Ezhgw z+lMGkIUH!IOOYH2v_w$@j;1CYLpdBvc^pTrIDz^=EL(c#o7~tKXzqzhAt$GyOcv>! zP9dB@Jvh5M{4R~N@~AGiphV86G;T>PxD|@Frb%2tleryD;|^5GMYNEMX(^Xfciy~< z%S%b)UgYAwsA&KOU?89vOzAv?vUw;q2^P-kvuvcKPS5qvnL|d!S z+cn0DyT|idIAi?#~?>M4(Z?&O{OPlIz45~c=#56&ba*Wo~YB99xtQJtC%AH0waC}?CwnU@kb)K z&HG3?3y$_7s{0sH#Chk(*$-E&vzq2(Wr%86HagXe9MFGEVMsk3iic0rn{4gOim!&ggS$E>Ep~_LPhB ztH9FdV&R;R4 zC%NCmI{y|H^EZsvXELo$*o-q(WCSn+-V3?+1NGdQWbLd9I-b5QAeVDYKc0vMq z5VFK!#5{%pdI|&d0#aUs#PJR!jth`9+8CWb{+RDKnx6Z*^FwI;VTz%>ln7ZP1#(6< zq%Qqj_|UR?~4ZFkQBy?tAG8x*ur|(Non!&N~=$W#lJa__T4~ zCxzSunCNOfK!I`b6p}?Q^m^ob?v1So-O!cwPpLY5e zyk*~1Bu&Mv>jw~rfPVZ|6pYHW@v?>+0N$oLh`#-^3XEz8ev>6La}K=ur2g+yfAGc7fFP7!58C z=YvMSOHsxx7gP9AEA-OELVntCU+T&)<9np@42btNMVc@Ib(4r%aj6e2- zH$cIL6v2s<%#A1?*#Gp85zb5s~`)3M|u|oB(wB^ah;457rxJgR&l^NmpQe)nUQum?M z{nVXz8O^R%@Iy#1bnZhN`;GHgi!7Wxwth(N5{+nyW{IU{;**ZpJI1oR943+wON$jH zr;Qs!RuBxv*-oQE59Vlld32CRkvxh$$k0)v5{)`()LEl0z*gr4Gb@@i>D?nJXP^IMmd%!R8|`D{*F)ljo;Gq}9<2#@LGfgbMMF z0)J90ivXj-Sj5DcX+hk?D~5|Ymb#Y;R+0f2G3BSkceReRusIQqS}hyra&pFQERiTs%_2FX;ocU%m%N&KhTSkxFd?Og{S8 z(qf$Tz!Ig$cI9Hgv3pz}Q#%Vqvyp~AhFWz=_u@>S#;q;P)dLj}BvvsiMPOx(1HVj! zw$&61xzyPWI3@I|rp^>h?j%$pan1Z#OhM-aixQWIkl;N9hLPjE)Gte!1E9X2YL-SYhu7N)ro@WlqFErvNjls5A}Lr&~Z|qWNZM z7{ZphG?a&PD>EsQqs(tZIfdKW;fyeZJJ{jL5-zdB4}@{5vn$~2X7;PgG3I~5IM>+| z-=+3HpWidDrw`9Ho;E& zNYWaU-*R90!^IieitoH2*Me(i-1KQT&Gn4yRF; z`B4HFa;}-sfQPyJV`U$N5gP3CHsChgZzOVz0{0z{v6z5KRgRIEh!uP)2xl5r>*-j6 zXF$WNz9ydq1;8vwpE6roYn$6T8V+8JynrGa*SO9hP#mvB2CZAZ;XL)1h& zd>{>oo(e=yGdU9=|CokBsIb%8q$8~oX>;tfCFw|;XQw?SX*VEkk)0NlfwZM|TF(rm ztw7pJJMC6UTVtoaA!+N7cC(~);alwJQJILo4bg^O>A2x$-7Y3;I+w$Dymo{h9aNUOHfo|UwtcA6&#X^$f9 zgq_wq2Wd~(X@;adg|w&bw6`VgIXf*r7ippuykw`1%|+TPcG?4y_8QV&x6}TU%W*dG z-sMmmnXgV|cT8aCLTm<^FL&PV0n_wE$%aItS(L}RH+#G+U#G7;`UF@`bGqUIKl6HE zZds<$at~P63VEz_(<)l6(Halv+Uuel<$aT+taZ^k`MB8wp>Tr-65*}#*eF$OlE-cG zFf_W|12%q#2V$ZrkGq0tGi?d>;<;6$yIpjT)UwS*+vUAOqkA>l>7x5Q;I;R==m8h) za?x%V?ePGT2R)DmAC~4HanW861j_v`Iv@=ll#fFiRcmzE14=(4B!4s*V&yRj9e2^A zQtX6_9`isAd!n_APHJ?@14$I!deTKtY4o%QQvhGjxae7pp7TKQ@M`qDi(c?R5n7?q ziyECainT6AH*D#QZN`yiX&&$6<-R}icnycVq|wV7{Y#@)&0ntGb-F}n%tzaBPSE$#@(<>B zZMdgvzU;aDNOR3oyOb8DmaWu}>P|mNw|~~?C7phuUvnhhUVlI*(0%!g)Uh9V6ugsl(FM=00+i!i*2D zk#dNFPLMXtN3IC>QSu-*7_SH&kE0ZFlM#8fmnMOUm;MWhCqNA3YBjtjK3-jrqWrj!+n|ZvF#UL#ApIEVfU6dps#LZ*^~~@ z>h_LTwo^#fDT<80@hC+N;Q~iG`j(M(jG_x1?pDq?$5DzY(Bib?FpFU3#!4uTVaupj z;EHy7%33*hU;VTedg=ou(N6R~J|Y1@)YibpP_%Pzf%60<4y!?A(zWC`r;i$)1cb3z z7AvuMIxIA`$I?aUbPzfkj4nr^tFh>0WAvvfkdp-sw-pxL5-hmgvEY_M)18TBwvwiL zL5I^U+>JzcOHjpV6mX$fDUF5c*onfOQG7forwXFs1QeHjwM|&F2jMLt!KVmyn^3Lb zI0%aHWT?n0fLMrieHy@=j&zZH?b>FbHo<>7@PC=2u$_5@uxU2aq0y`cS0S!BF(Mkx zW~3mR@U8@SU=H@^fF?x(CrSoJBN~IQ;_Wy_DMC+dA<7n5=b(R8kR9g& zKJPqm(M6Eo7o&bK1AqOe0ld)q!1QC3+KYQ*4=8Q(b>xi!^B~qgXb1%#qm16Wsd23_ zMr^G->6xIUtlnAnc8-vDBXW81S_6!(1xD6GLfrtV;})zon=s{W!;s!li>?P+)Qkdn z+cazJRg!!mr- z%ty@&99eOWp<_?l$d{w60`h-h#>&2H1yBc27rTLmI#7A9|L{9A@uns zvJ6!E;gKjZP62iyhIl$33Ro@>Y$KUiPdSvA{=n6i8f7u zl?S>e+pR>4Ff=VAS{#z6nugTz?s?}u;SX;>0axjuqH!$WawaLD5_OK zaZP$hq?a5xL7f7#v-35a_^8WCv~RO68x@B@V%6yEVF-{%AT}OFAAFctk6Ng}glHiE z`#UQm=c1rkEe8LgD@*XL(9-KQo2_|OYkk|h@{1vyYEBshIXlbTJ%}sAn`4~wKtV0Q z_wu22wlvcR^Ra}sh_U zxp7()!RaBDqW??Ih@xW4mjd<-9ZauFKrk>*jO4tKDC(+%wZck)1=Or)??{Z$F-xPh zS{91FX4WWfulA$jz;bK>m1KOK7wwxrnmcnHtj40Z%ReaA=7z_WRBsc@dQf8;sE0*P z)?U$@#b8179KK{;biv}e{V!`TR^DS2bc(dnj1%MnVY=~$h1nqsvyVJJS%dZ6r1t_p z5{4Lh5Va;?{M!Ms!lYqeZi)s($_)YyxuFdwfM6vfvMd2&xm8W-b3%h5b=JHZN!8K}sS0w2ODtSPR4iFKx~N3bJGrQ{2j5*Z>gs_i+f5$b<*V<44{Eb;faamv*(sgpOc!FSeTeRE*b0KAYFtQ9g_?No13|#AYMO>66!D- zZeEzc9h!`wk^e>2u{0ce4>VfGx;|FJE+!m{L`?JpxuTqxuthW?O2@L7`lXTXRr*9(YL$FrIuMvn5zxD+nss z*20%mC{kNp@W3Qc4=O@>V}umsi3BAjTZBIu6qJIzV(WrANdE)NfLrisl^{^5P$HRI zCUbm}0Abs?ia<)wX?pt;~7U#S#7%1 zsF?>`rMU-40&(X3H*pH(*-S4_OtA3NL7#$(ZY@HyVkCrPjS#C%qy^Lk`OTbDYEN@) z9Y>@nyI{wfE5k6!SWdl&mHKMdV(A?lf4J0#INnebd3pv(ON30rp0L}#)9XbvVqE(ow0 zSZi~HKn|EV?eQFdAs&YC7)+cA=!A`Yi8nA=8l#UweLKw@i=3yqjFgx6TQZVxsYJ?@*!M{_} zUy<(aCzN9&7;sxtk3tSnctpfes_QsLk+#e&9kk8s#elFQxIqaDg3+${H z*k^B$LLXoGCLY6ugOPm*hG#g~=?HXkB$oEkV2Wc9GZqTn7)X5MuNMtcDRp(Z?MDbCA`!Qzj!x4k+l*qtpZG|!9Lc2#&3iGbQ7Rl zisdo1{kDoF%RFvQ{t9`66`_ia{XY5rM$V-@%}G=+R`^`8@E-QUbxXL zGY{Aui{S^9n=#YmFT*_eEBN8J+d0H+crS-~pL3JOn)9mvpM1IG;dZe{<6t-I z9OB|S8i#r~jKd`;}P=Z7z zddR~`64OWn=^)Z;eKpZIS?XyDX`EB!ktB(!@<@|}ba`Z`LpyaJ=z)D1a=pfo>k~Og zK6B-P6)u6X!X@enWTaDYvyU>H_(?K3Z9`?59V#vJ9u*7NH zQA(F++{wid#R|Ep##rbQ81h&VLmtz(doXq79`fiZ38nCg(YUw9eLUC z%Qc=TgE7g)lLf_7WH_cuUDI4V-Hm<_8mP6+ecZse@IKzEaIi0G7w=KR7hUf}&WnAo?BUzsMQ)Zo z%=0w>IZ@*!zKPhpnWgI>;Q4)r4xu+_4I)@x{-Tx-N~qIxpkp z=J9=86ud&`mAp#F7%Vg$`#C*qwGK1xjXFFZkaQDmHrwy#(Lrk^cAdF%KQ~j?AnRNE zIaR%xZZi1*XSue~cJXdmXwE*Y)br|?Q#bvWkh+a_=y1Z^sq@XeUWf5*v(C5BgF4?z z4{E$o=S_T@&P@AsHs}$ZZ%2Nsrn;6j zd2ZE|={dd1%zqzXx4NCzn`IZ2sD?Wv&%HV}&QZ&KQuF<26`n@V>HGk;HbM__Rs3$g z3&8Onu_(iw{2C+2Yy6PT5A!4Dr8ha*eC8leFWSqfV?XMEmhaQi^@AE8(qT6B>GUir zL>1_R!m7sAIv++q!9LN>5oz`)Z8v8f;$-$2WmR3wuvjI@{PPgkbM570Qu4Ujuo^pX z{3wQ|Yc(e|J;9IZ{J5a)EBe~f7pi7fl}%3^H+|;#X^_As===mNH8)jrym}IW1J#@l zRu|Sosc#gmcRF=GMGu<6hq-CclQMiynXM%Jw9e1)vy!cmZ{1;j-QiGY&aE;>9Otes z&C;Z&SD5b}=i9t+{MRrw8Jd3xxF!Y|lv@v$oJELRjIbC2>%oYzH1I8(;oj@M9YR{j z>kx{v-k?qE4f3?!pit`#y24u#>Op;LMd((*k{w{lc7%MdM*|y>u?BzwEU7FTFL-V= zN1xzE%{QSId$n!@16z&Y7!IGB+wpY={+y(Q7BNcP=`VNa`f`Q;RL=C53wn$bYqeKg zt6b>y?S)wF-37Zb;PefBjEAsS03B!P!2^NlL0FUqL!KJ~>1{X`$&o<7D41MELvJdB z;c^_>91p9Z?aurJtZS#ROuvF<`af8vzrwQhGt8+ma374Lxts$3zmD)#>4f1DB#1^& z+{F)+gtlbE!w5bJoCuGl+kslaOc=SfxXWUwxu;=#c6wGia$t4~(B{Y|xU{RlY+DkR zVPtHJR2YO-sN9gqmqQX=0r6rb^uATKkkQuPu2iD0=P|}+1qN>=?T>7L7gjz zg|xR}&sjQm=Sd#e?^@^XK>0fXlL^V?E~tu|(XlO%TDGFAcSFp*r&hfsfqF||6ulkQ zF$|+NLAE``Nwo-MmsQL*0)_dD`3bU4k(Ap-yYbv;-g1hgE%exg{7|iO*v_>GnPGK( zP%@*_Ip{pNyycX_djq(z3-9~e!VmpzVMndPjjSpU{cY)o=@Dt#IMX6}f?&;V>FD3) z-HTnx8Zf1gHki?m`~}QM|F-acyRdok$?FjE#NTE{<_>9;PMlT4X@WWYEX+ZRATYY#Cn70M)S&3yu+f40uVaEzfHxqr3)M& zjJ^aX`3l_dYp5aLK&|{13dwiS#=eKR{R0H}AHk@90;l}NYDvyV%>-c|gQ401RUi)z zhmToym|FuKxK%cZ0lo^ZdlEcX0mlJ5ZH_3r=#wZa?(+=aYQfzRkP?=87c1~&R^e%fZ2^X&$3gI;)~F}D;B6O7Lm4&&4xtHL2hvn1 z&Ezn;fx~GD*A2iwg~I81pjZVs!5Gj*Xm%7h-HR5igyp4XSeMdidMOn!+0d$gP~Xd> zL)UG19kdV%ENE9h%k3;^EfYTmz{w5Zw%w5GaUvj2f@u+MJGjd=Y%%>Cd*B#lWNJfZ(Q{lsCos1-vlfBW ztSxJiQ=v0x;x+7=3w^A6&d*k@3CS%35K6l>aE15@Q{vw6<0=H(>;k`CWU^QgVrpCd6mV*5)*|oj{T8Dgvx;L6Vp6B+10#gA? zmCo?B#&VT`r75sr!SYZ8be6v=9n0hU^Z@`8WV*yi2V?75R0=Un05;D)&!yJrS(ZQU zhtV5|st3VqaxfL}&;U+yG5@4074t8_qJQaS%~~a)k1YC^hJs1CObHf+$6q&Q5b&f` z5cNb5f)iP91Deb|FYw`71V0WyOn}s1j!lV4&^{(pDo+8?Po?%ejf%MvNSy$YCM#x6vLO7q^fHMn=;1IhQlYNN= zl|AAk{iBoyHu4`ZB6u%|%xVqvv#0q73lSE_;#HXWt5MAwjKodUf!CtbH)GbXhpe)J zZiF^q@J8Csx6ysj1J3dt^f8-OQxhSI&IiT9-2w}H8RnF5EEkLncYx0=1bSpY^&&!Y z{_#F|VtkL`NCVmY;I)`s6eeR0lRF=vtMg!tKLJt~2vcCUnVj^?uH@&MO29a6Zihpi zf69*bub_sjXcR|k?*ZqMPaHAO=yw)Qh`rz6Nx2HK&Y{HyG7y|Q6x8#Fy?&anyv#lF z1 zy~$-?_YK~gP*VOHldtL(Uaf|t0;4!?1KV32*jR#IF%8qyPumSRon1rFZZ{OENqwJe0boHzIe#SZR$i^J?=?!G5~ z4GfY#CC5%SW7$l8_J9!!0(8pmZ9S`%w1T3ZH=4YC+i>I0ET}m(aOz@vs zXk)f{-lg>9xn{Oo>BWo8#crh&tW{6Cm9Ea!FlVeWLp;jO3F}}HUJstRfs&x4=VLau z#;k0^@L6EPJmOIXaT_x@SQ%{L;+H>LJoATx=nsdnX-urSQCCuY`+}8URgA*!P$d_y zcS4o+c*TS%Gu+KFiDkQ}nYkfMu}^*!t#dehPlhSqcu?>D`Y6)I{J6f-jystN@ydFb zGlOA7l&ywTj8+=;G9QgsCUbwYae^{7Y7plBVB{DAd0;3skzt^{;pSZl%5)xOIvb#x zGP7d?WqwFGjNcQ%CCgzbpJYDQKzSL5@?yZ}vtb16KyA$J4V4yFmpY#PJo>jpqTdo_ zc-wf#!3so=x#)2ZR)mvqn$ze>4<`B3940iZk<~;NaOl|bM2fEt}@_5lB zJQ!|g!JxE%c_0k@TQb0B?NyD=xaf7+A9_QhH#K@oE*^N>jY98upa#AxkN4bOe82Ce zvGjp_pOrd4l*dOJeXP+r53~~icV6C~Nc^V~`pknFazQ>n4+dBNk49g5u%Lb=ReY_{ zH=50vi}JXFfTlCA?d4v~ufEulIt4n>I!VAmYy<$T7f`JQX!9WLBtVr|HX-A~BQM=;? z?2LgDBYd|sQYLZq%No~%Kcj{5H#M%WaXg;B;3i78>cG1Gjju38IjeYJx@iDJ!D?zY zNmm{)H(rH@F`T0y1!qsX0i|?Kq;q3#qSH7|mPb>w-{&x6Z+uya zkI^}WQ*}<`ba`aJJzwW6&KAo{qOQZ2H5V}H+>DG%jyR)iaa(g*rqV(k2djF~4{EHT zFRq^@b>`{Zf;Q>UC^yOj7N&fBa!cB#L!7@`=T_28Yi?uQJ21s8icwOuRojY;~!yo=!ijr)xBaftalIriZofN;wQVK%Gac7C|qH|a7 zW}dmg**Lf{j=Sq{7*B;o>YCZDTiKk+y~<`uYEPX@xsA^7snWq`vG0A1j_ce{0O`*I zfM1;l@&I#Jwo(i}Vl00&+UV=hoI2E`qh@f9GOt;J4)cfw@=%?J@o=3-@JJnObu`wh z0v#I}=x_m+2jVQ9%itz+C`Z}i>zAuMqL?Lp)F|UXRJwT~Pnl|VUEye>I4aE0r{9Abv4I@~wh>5w>aK@vJ#rI1jlOSZ-D+ z(1P-z`Lu^E2L8I>nk!*HS`EEu4eHwfYtbzz<-H9}ZiJ|0pxPUe{U#XM)*^Wwnpls9 zHo!sx>nzs(N03h}2nS(w5Jb!ZqwPeAFg;BN!|MS)J_8|~cmU(5fFc%zS|!(Pq%H-g zue3rNfY3^K5;;U%pjlo-%8qR{V3~`zg6ii1BoQ3YwU4^ ze4ru=;?gq?QT<~SZ%aagY+Gj8VfEh@%-q1*O-PX{)>dS-KiHv`7M+(1FUtJ|$Jb z<2B(gb$M|dP>^YhYMwx4IHYb>CiJ%+XjM?{hQEif!QVi5^dBJHPy?a&dJr4@4TxCW z{%;|? z^HB>Q<>NM!0!~w%1S(mkbN@ zip2>ngD65=k)KZX>TutXQZjJAh%2ta^6)N)`$Rqv+2J zx7c>W!cu)ySm1=sul;6v3$G5Xg77SYZ#cYYk5RF>(spDjaAiG5dX^Q2vpW~K<6LoY zk1yFm8{?dDuH)260aslR(Ye4QwB`k|#d$zw5nb@Gb95EWv)eK1ZWEuKF_5nZV$tuv zPwXj`0GwK>rNiRHx7ixA*R=Y3NSBOzGKi>aSXM z9fyV1!4OGtT@*C5U>sW2arr?A%wKh&n}k8jh=4JrE){Vk4s%4ocPJVHUJR{Z;1t^r zk8?eGiR0;QPNZ|(h(6`U^f?ImD{g8H&qObfJ{)VnPH=y@yz4adbsRVVogIehd@d-l z2;aL9a)S<^hf#cwHKIQUM)YSaP7h(wFjU~B2B=PfBL4{TsaSOWgS7)EVzHLkE4LkU z05LMDdXhKj3WaD`bTm4271nc5C1_O6%^=eH|BwS~1yK>6muWqo!B?@q2G!0dg;ASF zpF^xqu$sT{NtOe1H9|)&>{@%Q zh9F4!8+sP#kQJsX<2kCtgh#y@)^jI~M*t*=NIXG;o2lOkDh;r>p=deNdmUVMd4X#f z67Av$STNhQA`L*+(32?hHqWrq`DVHC^)#D72_ zP+*#o_5Xy#L4lXk2*a`W<$~HWoW>O4N;bU9@Q#8u^BU*@cU8eg{1>wT$_D-=nc


m-;Bbxon00+o8%S`$D;1S;0%r!;pTyj#;!%$ulqBpg4U$PE^jgL-t}C z?}L85A8POc^R-#Z=h}*>NY3^D!hn4)*f|l=PEGJ_VFK zX}&aD>CLa2^(vK9$!|j+dY3{O27f+_ne-uM(#M!d=iqj59_H;&a9PI%-_=TG0r&e7 zn)p|+27C?O{u?xS5vtH7SPZ|X=KKRJhCjhX{xdH9_=U#uuQUtxycIy^jWC7Y#(&aI zh3Q2_p;r}^-c=lQUU8Z)R4H#JYy+U%0mkzH;RRR{UPQI0DT`mCmi)5$=v*b!GFya{ zj7{5wBf|2RXW`OJj8k+oWu6l1eHHExaw0B>R*5sZ^;j*THJTiZ3zCCzd9+p@>*Vuh z>u8)tw|JnwuasyUkqe@YQo|+>R%IhtRyX;)Qy!-5+1(|f&GOhHpIfEu-BR`*ueuE5 zEWvH67hW?G+AhuSz;QFUq}WaDl%n^^<9>NOAdg*=b+YqFBy+q6_E;t2R} z;#@to(Fq>bI?N00%(5*?u0>t(avNV)ox0F;NruLBOk~>QI_AMh>zMpN9Q^RR0e7SB z8lBK#=6qbECv-YVr*t@Fq0XnMoerxl9?!_ogX}Wbr?kPDN_pChTNj=svwi_h0P!6;$ zm4}xW*q)vrFIN(RUeU3KvBZQT7Ues&Ldj(Fhm}fNORU7=<|qq32~O~YMa=&Oda&;t zD^Mb~9vGb5Q^&B=-LXnZZ`Bczws0l4MkZl(PKFhyDOT?kY;M)?$T-MPo$`P9zE<(3%thueu=Tu1}_@RTOWANDdg>kD#S2rNA*XPoQZ?TSO?me zFjYAiCx_yIOnhIn^jaW>+H20WUX|3sr#R#bKIJ&wFg&IF`+!;oaCGKj3WLPp4c|<4 zvgG49MJNz04pUw9d<(@(=rBcQ9HyvysSf0KeB(F~`VRIP$P#^+Vvr^FK7W>ID~ok_ z%0`cUz@{sPyc_!11LM{cws@dP;i!zdxan2Lfm^dd3+ z5hDn5k{aEpksoElfh_pg`@6gvSrlYx`ro6Pe%MP+AH|iXOB&?wdPAVjUq7tP55Iu1Z*$Mi?cUxsrOV3D(X_Hf+i1#lt*sUDU^EI!G(kt( z0dvXl!Y)V1fzqK6UD|;X1mof4^jv|E!CZtDH3Yi|)LIcv`aeORPy>B~8t5DNp@+-e z_0X>Y^fv@f*Min7}XW{k#1s7Z$0dGY{!|1}bhExBs;gsE1z7e$8ow7w^q1JV9u_q`d5p=s3 zOVyoNeN4=$yTG0{gQac(5pIRS>~0Y8Jy=DzVFlTa9QQ&e+6g%so{G?fjzR}|8egwK z+c^V$=L3i;7m#uh`pqx258Cd2_(mLrx^;*f65I#r2xrq#Zc9Gyg4^A?(+M6x-p4HJ z5>7b*lX`}=xP1@^ffj1!3qlo0wK-3H3XX^jzD(nBJ~#4rN>VOUVNDQ31mVR$A>_mi z_(AO}aRdYQT6u~}%shu04kCn<;V&Up24P)OfZpg{*7|USqGg!?D%A%lSc34}Nw&xa zZy5$j+65{hU_MCYZ zll?g?rO!hic!3fj3#CF7%7b5MTVT5j#F&1-_%QfKjD}~#c-%iQ85_hUfZ3KCrqrMe zmS7uYxV*)WT45r=nz#0jjKw*ZLm)f7SQsT78ec*7v&7 z_vqSvm#$kZ)b9I-==(?L`^V_}IrQff^!-!x{WJ9abM*ZS^!-cp{TuZCTlD=B`u^kp z_r62w6apzW>)om}ZVa9th0e~| zrTyeCOSXdgqJ+0@p)i5kVqK-XuYPxpWmu9b*N5^KPr8>A0D40U99v?D3P2O(U)6-r zq@}v}gUs%4O&p@6wGP5b{c;#&tw@|+M}(}Y2pxfVW+#gbCZgCei$@Et5jsNN7y(SN zri`uTH-hU^V`!gEYQfYY0Fzv6ESv*}W~kH;Ngm2$1YlAZ4(X#T+i@%p#?o151HG$8?83tgNgPn$&?47;lXHl2xjw8_&yAyL>^%Qk!V*L0HTo} zhzMwKiy#o$`ViPJE&#z84yb(W_zS3!uJ2h$J4RlWhnp~dijS_((EWw5)ffM>;Ot2g#6s9A~! z2>xNW2(6>*aYZt=P`CZSizlWKX|q~m3yB$sjJ!6e7GQ{iERCRlPy>M36Xj;0c0EwL zq1Ko-^P>~(H~Y(=CR=bo2l zT1J+Y0A0!lJn}CB$B=QQ#TI{WtEu5N7G?`04g3n9BJTJKwn&A;t-uzB*p%d=Ik_gz zWqBN7OBeegmgz9(PUQ`!Z93HMRx%>&V9R~V>0mqPcvN}Y&R~9YQfXtI2wVHq>qmTv zry*C>QgOKzTe0YJU`}4EC{LC~5|u-Fz5|dO>a+ z3**pg*l*TD(lH?Em@xa?Pp8cluPM(tUqjK?&0eo7UHC2Y_Scn;&i4S~`{w(vD|_=l zM&Hk&-t+LJ`2;G;r&tj$P;*EIEnr)31?gZY9Q;OOx2POa!VJixbLo=#_#4XAHb0{1 zPbm5`l*wOE{10eexPJ$WG4v>0Ajvq|4$B0q@b7ZK?&-vV1*Qe8`F?s+afu@c4!*(W zii;Rn` z8g=4y^SgJHTi|Z7^j)|fH8&rBSD6#u5*4=sA8C!7liOemqpex|p0YZ*h*ZYeaqf&2 zt_ysrx}mO~aPTdK(9j1*(fU#m_xFAEp3;Ex2c!59*l&j--*CzVE6V4Qa045IgZX1= zBA4O9NpwF?rrkKU*!}}$kGle3&O|e_%t%)5pQYyYjjG>YAkW}-qCic*K#2y+) z-hIK?K|xuVL+=rDsEZCs>$W*GiH=B#qaHkbE;<9LV_nfbV_`s zaJ!fXH2I8#p7p@O@Ekm(=mn|bMQr!Da6>Hw@RudezvS_Xiz2(Y#8K*bg3vAv+ zBs*)k5^pa0NXatajOK9j!H<+4X2b%en>prA+?F7>e3|1vR#s}-l!^&c#+S=wq^9GX zveARR9lwv2Z`(QLd&XSa^ode!_W4vfq`i$^0+pugGi6{pY>3tcrSQnovB~_dd`v`X z9V)>4@X^wth)uO_8#BkQhP#i|Xq^`ncN72ZW9R5yjn4Zo8S6ox>Ch5T-~xTF(HC-{ ztT8SYfkUT8U+WODae3H9sxZrXDD^_+3bF5{!5?(7WLYNR;2-7JV0zF`aKJLp3{s;) ztQ*7T(r-HaN&g7kVuHdwXuJ-_SS&`|dFIIr%9P-@tt-TI@yZGu4l@UQt|X3t3%bUN z&MG@}c3Qq!^5N1U6;r`)zu+LueS~y`f%VdPXU796qRRwS*_^4@n0%?6*Hoc>zWI`QO({|Ru)v?G?imz*$CtSa6W-m9K+04EZ%!D=eKDkDz zFTNNElAEQZ@G}q}%!}VDMP4amn~A%EI=g|9b_d6jd%o?>`^I40a^aW*@20S54YCA} zmi{{BM`CO%tAuQOsa*79FX)m6M8gJ1P`4D>Ma0(PD2+yI1n29q@Cc3shb=?00&z)^ z5flK;r@vD=)q<=Sl$zd@h&JWibPZ&Q0m$@PkmUs+%Y#xXwngmZSTNdmE7_1q%m_3U zfK2y8W&o`Sks$7^r{%{9c^UQ^Zus1}H};t~`9CkSS=$*6;6K1f~W zg^Nnh(Sm>5#y=DTJp#;OB;Xwd6N6m)M(DMQINkC&l1qNYSSz+|*+j6%Rr(M@a?_g* zoHnqXtY<)JlQwR>q{OCNql*bvoi+||8-|}Q@LNk3+F!Y(G_%ld6Vc>anFaYmMA8_f z%J5#ezsx^ym1qb*!6eNgF&l4z&QX_Kww3)_>oaOq=m@lq$!eFyPC7gg#1mr@ZkF1N z`M|UgS&nse1%3!%mDP^i&)XFi z&H12S83sAUIRJ5OVCG$jp>TrMTU*$aLo9vaa5coD?MZ&f00u(`#ZJz9WBUtQMs|J)ZF`n5_b*pytY=?U4gFK$45)eZ+=idvJh|g&%loA z?O5>dfPj1_wZ$QTQG6FY!&~Sy-%bDGd#uXjT8vR3B`?H5>8Uuoi92v>Y#T1OW^7w{ zcdP(QaYC}%ZuMF2LpoyRQ_z7|0zG|&R(jztW>3|8vERgkmabwnHEY7I#ush@g#i~< zgs}vPW`+2-V75q#?b#m*SD3ZZchuY-C{pnbN^f|Cn*U{z@V)TJ-f8ur)+C8Wc41%Z z&=n4I!92X)LgdFk!DsLq4dtWP8v;yFe%46-B}e2%v^Ylj$EYQIeX6N(MC*t)*0;FN z;53_~nqmbE*|(}WDA^jKS|KJ_2UKzkVilmP1KzlR8I2^N6CyHvMc)*~#a-`-|3%9= z#EP@TqcYfti-^V{IZQbE=6G<8b*KADK9J%o1j!daYEVZ@KB+72%8 z*u!hjDdsGP+Qbs$On3#rzt`ql7OlG3&bT2) zE%yh1j#WdVEYaUvF}bZTI9qL{x*?fb^EJin*-RY>p>#(xwGZc*7n`Xq?HbaXt9fkw ztj+GTXWMnfZJ1rn(C5`S^HhH|-nTtZz2XRO_SfHdv3^OYZd+Wm@|Ryku@a0mMz}A! zjrys>ZsJOzTC7@I`&-{?^z$&#r2I9rt}IGyug3Tm7pv1$JMUMW)csB?@2Xq2YK1vjZ#By#1yiA&j@S( zI&;kdb%^^GklC%6Ya7iA2h<{~#UAe+9@G!hQ~pw}tIT7LIH-ntcY3h650~Fp8zGO8 za%5l>+-^jkA0v;ka>{C)CO?Ddrr|F6B}BLU3}O;ZbkQXFm@JPe9`N63fjdkjeY%Tg z$h*P=hu~RQCFKK`V8qfK+{-D2=DHfwJQvNEgasb3S#__1UFyH_jd*S2(P~wgI3--+mUU04y(IN^$I5jS#>Ni&mLBjGO}ou4%VM3SF@#C zH($ZYxLfDqPI5KI8tbkKjn?X5xi`zL!!cUt%F3CQiK#kR?*?(Ozm+LIG0o(jj@SbE zxyAM3hQEn!#jmsIP^(eJ?X(Ja6PL`as4B0h$|^0dm{c`c7cEUAQ-@l=8FXco88OyK zHq){9(@h7@+X{ojxP?{abKvQ|p6-UokcG3N{mUvQmFv*AwrO&!Mqk=th8Ichqr{J61m8)1sJ`36;vMHA`dy!t4XyNLaEZ07Mr8W zJgX{OBy&QDmV2rgc81ng1?_4J`iDueMJlPmmeE>XSK0=IA>tGOv>dbL3H3g!2ll0P zvd|SnR3Ol{KP8h!?1x(}*_>bia~oNz4Yj`i8To2aG|(T${%3y-P2%cT-~+{Ob{6ENiE z7`=&BWwujtVPM<}A+z*CWpWv_T(zvCL@TQSC(6ZP1#X9!Yw#){P0^%s%*~Ih`L#%7 z8nR7?J)r_(`m6vVAt(BwB~)i4vJr~gJrG2~5Fd%{c0t#*R@lj;n=}+3N}1Z{vMJP4%`wmK0Esyjy^l^-0Q_MTMxI$`&^@{C&QmR~dx zy(q&R@T__RepE0VQ!WmDmftmPgY#@3KC2$Y;m3LaTSU1+I91*KoI24GH!cNlSu`Bt z#&93R4Tsx%H?V|-hgylxQrHA|EtQHj9GB>A8dkWOV&d->PXQ-91%ggy#N(dP-B-__ zpwM9$fG}Up?`OuN0^6ZvCZ_jn!gVAN{pLW*n+v`$ALu4)UWwbdTrMiz&B6>Uf>|6i zBf?-uV4^7!taI|%QY(QR&YHRPRdr&TxV(s}M6awi+eu%e?ZiG`6I* zX8IX*rnL^X&F#6pDO|ecFTZ9T3^!jrqtoV|rdw z6H=h~%hy2b_k<;c>!YCL%LC|(lv}JvLJKf^zowq!(Z1Z*)gq1!ol{;lq;g6XR)mt7 zxHS=seZ0KQiZ|3Yt>B%9+xv6?j|&=cS0B^|zrS9-+`ZRcSM&4=Sj4dV{N zkTk%T@Y3!WE@9L?@P*$Ry`K7>zViFS(U^YGPBZjjM}qn4hia7X>krg}ic=i(nwmR5 zQtwL2L^IjgkIX@}xmaMDg9+z>Q;1!p6^#W+j`&#Z2fORuk0FD%Gr#;;?aqZ}i*xEo zZf|Znr}n_luzYY%weJbM-P=O<)jO}=!p;P=(Zt;QiE3L)_0_{Wgfsz>G%+uIqPF(J z^th0&xCjoRY1YX@+%JK1hZ;M?p6tXf83)Nj!v$;j#b|0Adj{lIRFS-FfQiAt!v0pB-x53 zt)m;!B?4b34L7bKV;2{$fZ}d0?yljQHSWo!f~rznv*v-rv3=26f4U+y^mTDR7x#DZ z02dE*aoHdj4|eeo7vq<*KXvgi7Y}#w2p5lZ@hBIMcJUY&k3~KgedgkExLVD{6I@*G zVu+F#T-Lp6E}r7zsV?hAHJ5dtnu}+;826gZ#tmw|i5JvQIegCbk{?(3Mtq@q*fAGF z=bQ2$^%v%OzOt{>cbJpSf^XEG{JOd38})=M0cOT_0}BewC%?o(G5TBeT?ekF>uk3D zPHmmYG0!vXx5PmY4u z@4<^|Wa0{#`^h=Es%jR_CeEjekn7}QP5~s%iHJ0tO>@9O7$O^(oc+re(hO?XAcXDV*~fA;c_)%+zqE>ChE9= z(X_5h^WKF^)*!kbN7@nzJSGmu&s+Dd;nFoWC3KIDOV_qbg*zm4FD_T(`!v2^E>uI> zF5a!-Dm8u(7pP%nMH6)_)RxV!$|;#SeP$)<#!*;Yt%kaJuV!7U#s>u4gBT`mEGF^u z;$Mt=-VWh%Ivzq_=v>W*jr|=O;aao(e8l|Vdo?ko!T&sDa)+(PM|Jk$O0+RQs`cVm z@Ug!?vbv0x`!@cl#;{>THZ=$2Ds_!hxgPUut`cFkpX&%SU;hbL?XGtyF0=huhi+c1 zR_pm%|E$J2Om#6wb9ZC;+fdaYgZIYBTfa;KGIgYOPa6#8Zr_@wV%4vGZ`u-wBIqBO z?P81BdXWw|5Dr5e2nx?t);+j+t1aFvf>{dIxEiyv6NZwT@MWKzQ{dGOONFPP@#s_xsH&eYV z97Ks3k`+jluiaNa!8x(m|5MhLfJaee;qIB5nM?=}nhd!QZZZiW90n4S5Fi4|DSRu+ zp&+L~ARL0Y;4rQS?t%wFN)R=~*+t!;EP*5t2_Qny0D=)j6a*9m6$D{*(zUkMK)BDHa;=hdl>nR!4PR2Iwh%s+Zl_>-O&~0W1w#o3m9N8 zjfy~b(n?!PbXx1M87uv7ug8qc4lO;S-y|rqbRnUN0fi#dm?f;93@&fL`O=a^y>j0H z4gsv9$uiS2GZ8IWp&v+g%nZyZ?rl85i4R4-i%7|1?*R>X4w7i7Ss*;s^-4kmCzH_fDwKpFgocjT zP*g;sstm)iHbM8ExIt~~R+6$kfbQ=L6fY+2gJ;@jYSoU1H|@}Y8a4C zBW|>bb|ojO%NtaoJIHWu+BHQQl-5UjS_hDplhTZjo4ii63Zi3591Q+@vKSO)G8`U9 ze2Ef+lc}KG=xCPWade}*XC1IUeF632ldVCvYdQ6K4QZ}HKCffgyB6bcxbp$cy5hbk z*qa&y=}*UC>_&#ah&ytESmx+h(z{)VrIO~L0;@rDa=Awhglz7KMgWu2;Xe4V!pWpK zP-^vs04-RowO)MY1YUz)%Soi z9l)t>R_X3>co-=xdmL=C&b{KE$cuD)cqt7yN+Et7wNZ&B_!1>TzRn5(Eb1USWR%B2 zrIYj@1Iem@stojUfqvK&_kpiI#_PQpe}4i7-iL`$4F=A&n7bVWiygwW=m^B{QOK_^ zAg}5$tNsdO_Y+Dnj$&+t?EDaBuPUL%NfkE^B=`{F07yo&+^Qh)s)EF;(uqg0pDI&6 z18xkBz7{w!V6_$5Qmu!gp->Gwf#Cb1hFzjw(IW2vN1T;B_-j`Ol+mKGq?^Bc-rx8g1}SqA2wL)Y0KtIRl9{vmX>IcP~jz$W@x1<)Vc(> zRHjtt*mJQ8?+wR!o%9TcH#`ZyJe0Axp*@Lp-cn}7$CW@8F#cJ)>h&;>t6b4}hIy#j zbrrP^3D_$>LPt|PXH0^gkw zY=HxS4cMZsf}^o*h~PoCfD9afMG;kvkB-M3!x?X%u>2-_z&pr`U>16lMsA0EEOG47Kw1^;&q0$@OO*|$Ao}Q!|J!9CStOe1cJ53dpx(sl%TR!WReO%K%T3Fp@SAHH-#sDL%JL`RfW5xnf^Sp4iYEU|+C5-o|ZF^1-|J>KP;tg>iroc#7&zIk~nd1BOuc zAo@U@7EjrXrvaORARTD<2No!0BOZovkD~U(1iBZ-YMD@n%7Ue+-ssx1p;eWGE!$ie zwCkfhpypxQwjbEk*B{1d^I?>B5R|O%gO1c-On8PuM{2mTLY3o7+RLS7>F*()Z0J$q zp>{^SOFH_O^SEPJ4sHq^8e+x*Q0_;tv<+{bhTyvh6zK?_G?E4yV#|``2Gv3|8NKrj zg04+Olq;0h=~VD4{kaTThpC37KiFH^9_UR?JKR~UbobgFX!7CVI9Z?Vbx`vc_c>ly zIJyA&kV{mLjf)4(H>;+Y6T=rwT-@qI*rb10@wHaRKQa&wpb}tC!>;K zJ4>C4bIa3F(X(Ky?Qx}tIunYl1&~d%q2E^+l-@mnC>i0iBdtUqEJ)nIi#}*v|AlfO z6>lUI1gUtfF$DP^PGCp_aj}Xs)}DuTQ;l}l522d=q`JCkyNN|Va~cr>%|bCt0$%e) za)7E*Mu?@$2g;P*Rmw<=P)C(1`7IS^nNPuir+n=%+Jlm_>0z|?kooYiHpYAytBo@s z#%qt5507dS%!i5EW9GvoZL;|=MVo3qOw*>r;sUiN%Jp$=h8Zr!!Y5_`l3EwId~ELZH3pMPxjQx(3cY>x_KZ+)jTx#U;s zzj3C*H=T8|V|kBZ1r6JGX)<1UF|A3#upyPVp2c3oUi!ahvA<$Pykh|y zBvyRgtM|OK6IoMeu=9Cl3Jc`}&e@w+lohaxs)JlBX7b`WY%G=>Z_Qy(h*k0C@!ita zK-{h2iRbJI{K$2?yW*dP>;<(gwA@e@+GnBtvF4)S;nsrlX{D@}z~S}h&;D@3p(qrx z#j11h2drJirBdc}vJ%)M;McdXo@@i%rIoQ!wy&hA=V z!0%8>4k(_YJVis6wB*C8^h&B)(eB-EQ9%?2T2fjySAeft=q`GBL93$E^PIe(R?q*L zKZjp@A74<&wR}~#K>sR^|7>8pwYE-ek2XbtHolB2;Qx9NL1zdKIGH$Z;0d%M3Ihxf z{098_K2%Y9(b8p6{LV)@24ANQe$WLCY6^WV(950!bbpf}D!NzH55{1df)&>b>qWZX zy%{c`1-WwHYFWas>;$=1eu&sEyjPvkUh>-BG1@UNQppb4!C!4^diqh*M_~Ko9 z{dHNF9@!FOGz#r3(3_6v&>_4Q(7HI-g=}pPL8TOZ{+o-R*{xU7M=M6BFGZzOu(rjScL=(Ey#R;ATmB3^I?JJ-fL|_17TvR31GYP5{4_^qw zxK}^XsY?#R5+KAV^ftip8}R?HA^iCHI1f^}Psf_Pf@%1G0-fkFu7H2eoM0wxh5VIV ze|R5@!Qq#qa3m?5f!)=1$tPGnmX;`3`MUXh{_1{~${*dYXHI^*hCu95koHYv_5uHx zr35-qh!Jw!#n0@A7^(Ns+jw5s8>d{_)aa>@|ExEW83k*GhgVAY34d3c^JNCSQAGN+ zvif#TMULQk=Ts*@2(A_Rlbb4jrUv={s>hQ{Af9-D#fy5fIIC)qc)(w|==(eN)17;@&P184-Hhs=1M^eKyxwULWE+w#x#xK6fc9(C0C?oEnY ze>wPF6Mp3e%60lv7A8NwLIA#NK>&?xF-vB)SYbBt1TV#0m+%vkZEawW8O}wG(Sm8w zxN%RO$N05cNT{oy=^ZJVF6N1~AnEIF5w%9Mh4N{&dhVtn;l{FV3;Y~XO1l6m3(@r; z3UNJ?UJH9dZeDoMDBv=R>y{OaYr$&{8sD9wxGw!0#9fWDh4J)5Iu53lE3&?0UIG90 z5y6jQ_!!-Chj4Z)AxeAzf#b3vWEL=Wkk$cseJ z&W-Y;Gw?fcSJS8Cd->2-pBA7%6s$rU+w}ggP{Q5!H{~7bSUZ{VusUSiAzDOnC@;esZ#TP(uQetN zK_zMoSV;5BxG)!qkspy>HHTicZ0<7ECSM}e-`fRKP2yvZ804NwalJbQ<03iKr9=3V zQwG3i1n_-I5WvHW2O@RPF};WuMQQ^d{097My6Pz14}I^Im3rsb00b+D#zh=^d_2KN z^XaT}0g2y$zsVy6I!LgYMHScr)$TEZYRkh;=(v)OSsaFC6xv!qcg&G_AK7IO zyQ{SXb;<6cdgLO0?F4HNZzi@Te3y}pMJdaY&0asj_ZN7ZDo2fnIoT_9WT1q^pZQux zp45d_V(vx3I$11P6@+*5;|9E`M5JIz#JmFj`Ku*-vmfjl|JIn_HD1>+z6khhDkXgJ z>##71b)umyZQ*3ZsP*Q|6>a5>w-(T9p>7 zw1mmMu)3ydTvd5xL0le21J)uO7JhI%GfW!1v!Mb!;ebxeMBRrO03 zHt2nmR@jm$Md!ao=pQ9GjdjHw(mt7%Y7|cisAhVDO3O4_PAfD@q$G`sXplyoX|VC+ z)tqE>3Ra@^f@CdfC9TqEHLcMonXb^NKMj`9TAd3c^wV9#!wYDnM0fy{OQRAR%|!ax zzoa+5ko*{Tw5I?WaYR5(s5Fd_U7Ew&jSv7tN~#{xF0;HH;zAKe0K!2XDVQ=ThH|Jq zVj_`?P*VrQ%fDDkqjX~Ggm7zGMoU^I(z5WSP&PuHQH!*4XS*RDX(bZ%6Llj$>OmUi zQ2_O%RO)56)E#N580lQ<0$2h7VOQj|A%AvD>)F&DC4p){k%xSW35SLlE0@606MqrJ z7tnxBrCuuaRw^oTYuDDfTD$fU?AWr`u_vAq>Ev* z@HYT3761;x-;56F(*%D)=tRRYKS!EyC7bw(YQayG4?ix<;eiril6G;8GU9_#M=J7+Ld^oLUq)lLoC(7;cw_rBBxP2!t^4@DxC#66vGDm-cUUoBk;+ z4J*J(G0L>!P|~C|#UnG=SM6KqolKOWp)n=4JbQ#a^Y}f~=NS1<@sgH(gaR`o>|OCX zLO~^xXs^77BHJVb8)n*7cHVp8nQVd0ZsI3PW4KA4=oQE(00GZZ`VBx>JRJMz!+SK^ip{kK_Pj?VFHi2Zp&CyYzTVvEcOY70Q9q zTw=k}7f&Oh8{a?ve~Qn%oArn3nBU}#Mt#41k>GpLQO0*9vF6;!zf(B zVaAwK>@dzI*{ zx1WILRD73Fp8n*dbr_0)lMhD>MJ>aSV+45jNbs^^^sq$NraToej)FjZ(IC4NnxMZs zrHrTQeW#Y0!flHd~vGX#xDKTjFB9u$IhIxjX;-C8Ub{4M0Wd`fIbp^_Uew#`jxoj>g-|_b~U@ z3n~iCnjRiI=9b2d6@@lX(@S&aat}OH^wPPV%(|{mb3Ob3=t%zZP*=8odW~P>$+;^P z?ycv~FEBHWDgA0&KA@Jre#q2O|EMIq@!9z|E3PR(#Z(B!Y5MdLD@PfYc@Np;H|Lt z0GIp?HJd%Y%xQGq&ykI1myA^$Lr{LGKD1%1V>rr=(C=)pz+HZPTUv9U`uoa7GAGUoSuIa0H=}V14Y`DE-+hx;Vm+GhF}mim{G3#K$9k zen2~f+JjO%fOy>jfvl5#?`)&UbdvH+z;D2O~J#q&_`uT^0{FUiT=z z?^L~Oxy3z_pNz zv*Rg@6DXMzsS_trcTPsp6q?KJXdZW<1)NTG+=*6l2Ce0+#@lYYk3Bs|Y0sAdeb({Z$pOX&t4PdD)d zx|t`^KAuEJc`Cia)96i}LDRt5Md+*pcUl4-r_eqMfs`7oKe6LRuGB}|zAT~|!?OUx zQ$x|b5Kt@v9%}VJ-(JCWdha_XDD<7a`HnJ^+=4=Pc5nRm9lHZM+zI5}g{tlbm)#9! zvInC4UZ_;}LDJq&^XLK0jR*CU58TX;=%XLp7tshH4x`Lb5a1C2;|2S9tWnz^%DtaK z(sSTE&!f5*A^TqjAA1Et?=^6=)2R9laI!a{Vg3oa<)6{aTj0=dL;ZM1pY+g9eqaCT zp|OsSA$>p5iyt1zpX=Knp2)Z8XC5vwpY8REN4lH95BaU;#m1eF90}~y39};;lQj$a zxWzf!gJkG}T!KGz`BJs4mQ(Q{7J@ksri6HB?YG5VyFd&~er zXF>v&A-NokvjPfy6{?y8!7?8`TmTk47Xo=6t;F{=_}&73G2zMYB37Z&)tHKF(WnQ_ zu7mj5pih44Hoj3m`_w8^0P3|*_cS4Yv*I6DG(P-vjf4I4gco!1EP1iW<&R!y;06Ku zju&qXiGbLPgk*>U1|tAQwBGZj$2zF!pC5qC1sy2RPy3ng{;j%!h*v%G&T$ug9I9>pBiOdji7r3H^rCS!U6cU#CoO zJaPK8zatVoi_&j-Z%jZELdh7|6ksM*Kl|QL?x^>Ee_c#BpuRgm?+HfK3jp@UAos9|!1bK8?|fKkaOWhWftW|1`%^dxAeZu9)0$ z-^xv$Uvd-4UyiAs9r!V-(f^C59gb0$GsXIw-_)c`#H8v6I0s?;hXK)(Fd-*{2Brbt z>A=L1@tL`YuYJ{asJT8hl-Wuc3~sk^36` ztMBR}ZpKvI1bW(xa$7KGwt|vw(U*KbmG9JF`MxjTr@PLKL+7TS8Olxio-@-OPeAiM zt~<`o;HUJ8v;7>;p|0okd(Re_WOC-cRzuM{*9^gGpOTNP{KL%>^v=J z(%1g7FT@RQ?N6Z$dB=g&gM;;+zfN;RQxN3%x4%Z|5C59)NWoVszJ@w7kULZFeXcH| z8~AZ|aKj#y3jUnQJt-Hu#L070d7yswe1x8RJ`FrTLW|D#;qm(Y=Z8Y4J9~aZ$W7Fa zZ$^ntD6yG_^H%+;-)eZ9nb&zC-LV60+^+YyP+)3*{NwJQN?=_oaa!8nfgeNlhb{z- zfaNBL`l-}kR$2pG7?T2j@YR7T6}d4J2gzfwJch_)s2drEsWjXTZZlGHk5Z{vr4p4! z>*p>cC)*a*&Si=jRa-YVr+jgF#k{H<#B`sZGpcs(+^V`hhhzDOVqEB}BpUB49BIQ; z(?2YZ4vwRI4U`|P(pU|1tQ01ftQZY5alD2JI8g(g;W1erutb=K6Z9YeW+)9B)iez> z6KSlU$`M9^#*xNh8_zd7*!kv8Oi_OT3rs$9s~Rl0uqM<$jtv|Bhj4?bXh0N$gDc<@ zXwBqofEaNxW;ho3VL%*@XM*vro!fg7kq`*>LJ<2Z#7(HlG6_nv9dTip<|%kfC>3PP zW~e>5G*mdmbwtR9STWNmAXm&vd`T`x#v!uHT2O%=(Yy|i0i8Cld>v-hVdMj?6G~-Z zI-wS0i-V&^ODStZ^Wc0@BovfCd7w}P7)in3F*(xNx{mH>uL!?s6 z_>_YFr2<{;O>>igWmO*6Qh6LEwpa(cA`N{M%yxz>l)9?@xR;4JK`5c`8iaEw;EzEM zlEGp+f`?0;!+=u)cABx6h6&mMRY+V99~Q;9Bv_QVo(KuvMGAC4w}rd}3O_La-e9w6 z9I2^NgXl5tFw&YRppgO}#TU21bPy2P2XP|dfMWosU~o0O#h#^Mu=!$%7plCyVW&nU zf2NhzTc+}IzfLiL$28I684RKd0Yssoi7>zzi=M^-x_I;;VOtzSv?N2*=c)7PcoPSjv5g?LCqdcDbag4Duo~O9_K)L7-G!O7{0{7;zgOOth`1~jg zKrslb1f(_^BvMKRSecf9{mg^xT>=iY3hVTZU^iPpA3GrJc0&prghKWtf-M5~rAwR$002w;O_p%DwH}#n*-FneUFRAph8#+0@UUAZ^DxGp;CS0x3 zYfd`t#_|dHc%9yGp{+Mn`jbk324{vM0u|&xX(xK2I>e}%%<+Qu$M`z$@UDCf2fU@y z+baDz1l^gex{(uW!p(2tF=4|4nnha@Iz;2NK5^cj856qsCDTUB4vkd|DvqPo68 zgOd8WN?&MDQr}bQOO3vwuQmFHzSXdhSTD=K*&3D?tBfTfN>0Le^gUqJ=nS3JpuGMQ zP-{?NKhU7T{-~eXoM_C?V|Uyq^b<6hYC&^&0zdn-?brH-!ve>cqWg# z*-GeVFQ)3sq<#XWRLHhbr?Tn({{6&Du z{u*l>040-(MY;3MhSGe#H7E6VTHV0%`s#|J+L}4lbC=eYH`HRJT@}91D!qJV?2$fP zWS{e&6v6-~gyU*!Ta?1M^iKatBZLZUY6flr5Fsbzzh(L#V>~&IBRyjgX>F3kL8)z4 zqr^fv9$zleY*Azk!k>fOMK`HvA|>OvV-NW?k?k1Sr)1c=ddV>g8!vu4DD5Dr$HByc!z(lZ4{M_UrBM8C3d*o|ZSqhsHdFSJUFnzEM4=^_+3`&jHd)je8_Y!tda1tO7= zF97+bLlv3^L|`|VY#zu(>9k!tM?F+33n{>m2*p~R=9^HJ3puuA0KD*$cx5LAWS^vn z_-l_)Af zZBXQi2VNo_M<^jQ5h2u;WML`N@lZZkamtitWTv(z$2h#y?gSu=hRm;n#I>8K>JMoQ zqalWKAdprBE;$4_hCyu~35B!-$QujEI}RzOkjLYJmWkx41(xc7p9Ww^#(z4xTZAeq zU_5Z5*eDne=0GB3gJaEwnt}am=%CeD;=?)$HDdwF$-gZoK1H+L0y~%B*pF_YMKC(p z0K`g|9u@=4B}f-V-KwpQR15zYuyYiF-SXcEJEskHm6j%65Cs?`g6(U}MAvZbVABK`4Q-DNDtUMCy*v8eX?WY4C|ziZO+;B*`)u^D0`!NDMx&F-=u&%h z$0e-FSN}@@UPyj?MiX@^<`QgmWo*BQ#6jNvi1iH`LeR&vO7>E_He-xEv^IG%vOr0l zOU!*T8=3Pj6_5~&F%EQ1Y+!-dTuH+gOjq#Fk=TM62V;zkjYZevO=`v`hEQl223;Uz zHO4_f>0%$wEwWb5Q&$s*^-1U$_@A$1FQbf%Uy&yxtBG<-j!`ZMt;>{5FJUfs%eQC8 z*pE_og@mAcWFJ6=R!YokrNnF>Az}zXE3!c>bJp7U+YAcOG5c#K`#LKlhrQxxH46VB zw4sIElgy40sZBJjk%qStw8g*^kbETyD|FSxYrF3kzq%wN6!e3?uE-#AX?9(0d1X$6 zH)k*(4B!yslW|ynL>kGZTo)1tT8Rf0CSaMEh*e&avAdL;651oWBUUA8;4JA#=!8%P z*l{MG)j_-r8Y4osWgVE-T$Dly&0Bnwl);*K#S|DYZ@lhm(MkV zhADBz=6|rCF@FjN4uR{8&%BhN0cmk6m1>yg6I9E-G+Bdv1ztUuC~omS6O&5QHJKg8 zt|?p=5Kptj38>6ez>L#Bb8@H#wvGlWHDT(S@N=VJD))C*O9k_3foL%OJ^!QL!W8*C zMQ2piGVxz>3>rLe0y-Rh85Koxz|ZOTrmw7KdzZ5wwlAxqxb#1$K|eh~0r9R_-|Va7D8MB=SvZ5f1ut3*Kk=>+v>Fy#L**bat+x{EQV#zGfJ zMj2tv!@*31O)CN@=59LPoy`9-&_*V{!pRnK0rN;vDN7{}%x5ZfcA{^fI$uw-eIhsD zAccoUKnb#76wxZMS*FBcXlXcR%Lu%4TZ*<}Ur~)@v)ETFj?+*@7gV88SBrf`ptR{~ zxK;0)vJ*33{&K7}XWECh2v5trhcBL=O!OG)EsuN`u+i7)vl(NWJE_n~10_?DQ>OV~ z8X{SSVn;>Tz;Gvxz{-tAsxrw#Ws-+di9ANTq56V(jHPidR9vdk_|{cg+l~qKuQvb20*eR`+le#sqXcc@Wmh6a9#iC#vNj45T@(+1tu(93v0 z7ie&o;S{r5=e}w>Hfqp$7MjdPd1f?zOUpU&l(Ya zm_qr~M;vAQ%08MUC}qqF-C!ozav4a2Tr!26G*tD8NSRWWh=lWuTUMA(8sk^6sQ@sD z8Q+{ggQ?U><3*%Sko*&6>P=EPa@I>87)X{C7I58Sl*Hi2pYQ@ZfRdMvwddQUDuwIBk=SNS_`XzS>h@Md2f<= zYBQ(&5QuYlXyL0TSXVx{NFNCCeh{Ml!ITDo1r=cHrV#&O_kRRdJ+rW%U4^-~0IT}N z@CMj|j0WbCU}PM6U4?f?6jhN=WV_|jF~{U)HdHeP>?s@kZ!t=AM#vBEWnfaBOn!Eo zkM|^D_1hJ3@c2P};8_vpJ><{)8>NB;+4&dh_;0}Gk_luX9aV`!0q@I$6cHMEgrcAk z_!v?$qAiVJG$0&ej-j5Rgv^Y}7i>UgXp3ai~{NgCpa1rFkj$LiSf%iFiO>I3ikS{|Y} zT*%~ZQ$7G-1X|@okQ8c_4@db3v%F;)|E!LCn2g#jrMM&4@Pgsq?FR&yCAc+=K!JUaqlKG%$4S8%*p z`MAogpS=sO;2_0eI;|P&JUq;i1_;xQS3R6>W~!Q5@{>1c9k+8kl0gS4M$hZ9sB3T8 z@^8GJr-XDx>)p_D9+a7$AeUa=AFtLj$9-Y%O`Ku^Mt?hS+WXN>yw=ev z7wGE(`soV75Jtf<`*HOmTrB;g7xoUjeyxmI}UHa?!c5HKwQ zOf?|RT1=3|n0-so_d4{oUbr}7mcpTB8Mf7y8-oq5j+qbg91LPrXvihh`MlxV<@@Bv z>hoT{jr%B$^>7E=U=;4)Jaa{x*MHC6ZrPB*_{+5R*Y1TFKClB~_>_xOb~`Tk{>hiW zJTxc6;vDGWAP#nNh{~aE4&!i1ig0qIo1-{dK4RQ(yo+^moRj0-*g;Hm!`lPjNs^fC z

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 + + diff --git a/settings/repository/org.broad/tribble-119.xml b/settings/repository/org.broad/tribble-119.xml deleted file mode 100644 index 08037b20e..000000000 --- a/settings/repository/org.broad/tribble-119.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - From 206eab80e3ec1d15b54a329e77998c634c730940 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:26:22 -0500 Subject: [PATCH 172/188] Expanded unit tests for AlignmentUtils -- Added JIRA entries for the remaining capabilities to be fixed up and unit tested --- .../sting/utils/sam/AlignmentUtils.java | 225 ++++++------------ .../utils/sam/AlignmentUtilsUnitTest.java | 112 ++++++++- 2 files changed, 188 insertions(+), 149 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index 8c6059d08..f29721a7e 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -40,9 +40,16 @@ import org.broadinstitute.sting.utils.recalibration.EventType; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; -public class AlignmentUtils { +public final class AlignmentUtils { + private final static EnumSet ALIGNED_TO_GENOME_OPERATORS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X); + private final static EnumSet ALIGNED_TO_GENOME_PLUS_SOFTCLIPS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S); + + // cannot be instantiated + private AlignmentUtils() { } public static class MismatchCount { public int numMismatches = 0; @@ -118,103 +125,6 @@ public class AlignmentUtils { return mc; } - /** - * Returns the number of mismatches in the pileup within the given reference context. - * - * @param pileup the pileup with reads - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(ReadBackedPileup pileup, ReferenceContext ref, boolean ignoreTargetSite) { - int mismatches = 0; - for (PileupElement p : pileup) - mismatches += mismatchesInRefWindow(p, ref, ignoreTargetSite); - return mismatches; - } - - /** - * Returns the number of mismatches in the pileup element within the given reference context. - * - * @param p the pileup element - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(PileupElement p, ReferenceContext ref, boolean ignoreTargetSite) { - return mismatchesInRefWindow(p, ref, ignoreTargetSite, false); - } - - /** - * Returns the number of mismatches in the pileup element within the given reference context. - * - * @param p the pileup element - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @param qualitySumInsteadOfMismatchCount - * if true, return the quality score sum of the mismatches rather than the count - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(PileupElement p, ReferenceContext ref, boolean ignoreTargetSite, boolean qualitySumInsteadOfMismatchCount) { - int sum = 0; - - int windowStart = ref.getWindow().getStart(); - int windowStop = ref.getWindow().getStop(); - byte[] refBases = ref.getBases(); - byte[] readBases = p.getRead().getReadBases(); - byte[] readQualities = p.getRead().getBaseQualities(); - Cigar c = p.getRead().getCigar(); - - int readIndex = 0; - int currentPos = p.getRead().getAlignmentStart(); - int refIndex = Math.max(0, currentPos - windowStart); - - for (int i = 0; i < c.numCigarElements(); i++) { - CigarElement ce = c.getCigarElement(i); - int cigarElementLength = ce.getLength(); - switch (ce.getOperator()) { - case EQ: - case X: - case M: - for (int j = 0; j < cigarElementLength; j++, readIndex++, currentPos++) { - // are we past the ref window? - if (currentPos > windowStop) - break; - - // are we before the ref window? - if (currentPos < windowStart) - continue; - - byte refChr = refBases[refIndex++]; - - // do we need to skip the target site? - if (ignoreTargetSite && ref.getLocus().getStart() == currentPos) - continue; - - byte readChr = readBases[readIndex]; - if (readChr != refChr) - sum += (qualitySumInsteadOfMismatchCount) ? readQualities[readIndex] : 1; - } - break; - case I: - case S: - readIndex += cigarElementLength; - break; - case D: - case N: - currentPos += cigarElementLength; - if (currentPos > windowStart) - refIndex += Math.min(cigarElementLength, currentPos - windowStart); - break; - case H: - case P: - break; - } - } - - return sum; - } - /** * Returns number of alignment blocks (continuous stretches of aligned bases) in the specified alignment. * This method follows closely the SAMRecord::getAlignmentBlocks() implemented in samtools library, but @@ -225,31 +135,54 @@ public class AlignmentUtils { * @param r alignment * @return number of continuous alignment blocks (i.e. 'M' elements of the cigar; all indel and clipping elements are ignored). */ + @Ensures("result >= 0") public static int getNumAlignmentBlocks(final SAMRecord r) { - int n = 0; + if ( r == null ) throw new IllegalArgumentException("read cannot be null"); final Cigar cigar = r.getCigar(); if (cigar == null) return 0; + int n = 0; for (final CigarElement e : cigar.getCigarElements()) { - if (e.getOperator() == CigarOperator.M) n++; + if (ALIGNED_TO_GENOME_OPERATORS.contains(e.getOperator())) + n++; } return n; } - public static int getNumAlignedBasesCountingSoftClips(final SAMRecord r) { + + /** + * Get the number of bases aligned to the genome, including soft clips + * + * If read is not mapped (i.e., doesn't have a cigar) returns 0 + * + * @param r a non-null GATKSAMRecord + * @return the number of bases aligned to the genome in R, including soft clipped bases + */ + public static int getNumAlignedBasesCountingSoftClips(final GATKSAMRecord r) { int n = 0; final Cigar cigar = r.getCigar(); if (cigar == null) return 0; for (final CigarElement e : cigar.getCigarElements()) - if (e.getOperator() == CigarOperator.M || e.getOperator() == CigarOperator.S) + if (ALIGNED_TO_GENOME_PLUS_SOFTCLIPS.contains(e.getOperator())) n += e.getLength(); return n; } + /** + * Count the number of bases hard clipped from read + * + * If read's cigar is null, return 0 + * + * @param r a non-null read + * @return a positive integer + */ + @Ensures("result >= 0") public static int getNumHardClippedBases(final SAMRecord r) { + if ( r == null ) throw new IllegalArgumentException("Read cannot be null"); + int n = 0; final Cigar cigar = r.getCigar(); if (cigar == null) return 0; @@ -264,7 +197,9 @@ public class AlignmentUtils { /** * Calculate the number of bases that are soft clipped in read with quality score greater than threshold * - * @param read a non-null GATKSAMRecord + * Handles the case where the cigar is null (i.e., the read is unmapped), returning 0 + * + * @param read a non-null GATKSAMRecord. * @param qualThreshold consider bases with quals > this value as high quality. Must be >= 0 * @return positive integer */ @@ -273,6 +208,9 @@ public class AlignmentUtils { if ( read == null ) throw new IllegalArgumentException("Read cannot be null"); if ( qualThreshold < 0 ) throw new IllegalArgumentException("Expected qualThreshold to be a positive byte but saw " + qualThreshold); + if ( read.getCigar() == null ) // the read is unmapped + return 0; + final byte[] qual = read.getBaseQualities( EventType.BASE_SUBSTITUTION ); int numHQSoftClips = 0; @@ -300,16 +238,12 @@ public class AlignmentUtils { } public static int calcAlignmentByteArrayOffset(final Cigar cigar, final PileupElement pileupElement, final int alignmentStart, final int refLocus) { - return calcAlignmentByteArrayOffset( cigar, pileupElement.getOffset(), false, pileupElement.isDeletion(), alignmentStart, refLocus ); + return calcAlignmentByteArrayOffset( cigar, pileupElement.getOffset(), pileupElement.isDeletion(), alignmentStart, refLocus ); } - public static int calcAlignmentByteArrayOffset(final Cigar cigar, final int offset, final boolean isInsertionAtBeginningOfRead, final boolean isDeletion, final int alignmentStart, final int refLocus) { + public static int calcAlignmentByteArrayOffset(final Cigar cigar, final int offset, final boolean isDeletion, final int alignmentStart, final int refLocus) { int pileupOffset = offset; - // Special case for reads starting with insertion - if (isInsertionAtBeginningOfRead) - return 0; - // Reassign the offset if we are in the middle of a deletion because of the modified representation of the read bases if (isDeletion) { pileupOffset = refLocus - alignmentStart; @@ -462,47 +396,27 @@ public class AlignmentUtils { * specification, one may need this convenience shortcut. Checks both 'read unmapped' flag and * alignment reference index/start. * - * @param r record + * Our life would be so much easier if all sam files followed the specs. In reality, + * sam files (including those generated by maq or bwa) miss headers altogether. When + * reading such a SAM file, reference name is set, but since there is no sequence dictionary, + * null is always returned for referenceIndex. Let's be paranoid here, and make sure that + * we do not call the read "unmapped" when it has only reference name set with ref. index missing + * or vice versa. + * + * @param r a non-null record * @return true if read is unmapped */ public static boolean isReadUnmapped(final SAMRecord r) { + if ( r == null ) throw new IllegalArgumentException("Read cannot be null"); + if (r.getReadUnmappedFlag()) return true; - // our life would be so much easier if all sam files followed the specs. In reality, - // sam files (including those generated by maq or bwa) miss headers altogether. When - // reading such a SAM file, reference name is set, but since there is no sequence dictionary, - // null is always returned for referenceIndex. Let's be paranoid here, and make sure that - // we do not call the read "unmapped" when it has only reference name set with ref. index missing - // or vice versa. if ((r.getReferenceIndex() != null && r.getReferenceIndex() != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX || r.getReferenceName() != null && !r.getReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME)) && r.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START) return false; return true; } - /** - * Due to (unfortunate) multiple ways to indicate that read/mate is unmapped allowed by SAM format - * specification, one may need this convenience shortcut. Checks both 'mate unmapped' flag and - * alignment reference index/start of the mate. - * - * @param r sam record for the read - * @return true if read's mate is unmapped - */ - public static boolean isMateUnmapped(final SAMRecord r) { - if (r.getMateUnmappedFlag()) return true; - - // our life would be so much easier if all sam files followed the specs. In reality, - // sam files (including those generated by maq or bwa) miss headers altogether. When - // reading such a SAM file, reference name is set, but since there is no sequence dictionary, - // null is always returned for referenceIndex. Let's be paranoid here, and make sure that - // we do not call the read "unmapped" when it has only reference name set with ref. index missing - // or vice versa. - if ((r.getMateReferenceIndex() != null && r.getMateReferenceIndex() != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX - || r.getMateReferenceName() != null && !r.getMateReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME)) - && r.getMateAlignmentStart() != SAMRecord.NO_ALIGNMENT_START) return false; - return true; - } - /** * Need a well-formed, consolidated Cigar string so that the left aligning code works properly. * For example, 1M1M1M1D2M1M --> 3M1D3M @@ -593,22 +507,41 @@ public class AlignmentUtils { return cigar; } - private static boolean cigarHasZeroSizeElement(Cigar c) { - for (CigarElement ce : c.getCigarElements()) { + /** + * Does one of the elements in cigar have a 0 length? + * + * @param c a non-null cigar + * @return true if any element has 0 size + */ + @Requires("c != null") + protected static boolean cigarHasZeroSizeElement(final Cigar c) { + for (final CigarElement ce : c.getCigarElements()) { if (ce.getLength() == 0) return true; } return false; } - private static Cigar cleanUpCigar(Cigar c) { - ArrayList elements = new ArrayList(c.numCigarElements() - 1); - for (CigarElement ce : c.getCigarElements()) { - if (ce.getLength() != 0 && - (elements.size() != 0 || ce.getOperator() != CigarOperator.D)) { + /** + * Clean up the incoming cigar + * + * Removes elements with zero size + * Clips away beginning deletion operators + * + * @param c the cigar string we want to clean up + * @return a newly allocated, cleaned up Cigar + */ + @Requires("c != null") + @Ensures("result != null") + private static Cigar cleanUpCigar(final Cigar c) { + final List elements = new ArrayList(c.numCigarElements() - 1); + + for (final CigarElement ce : c.getCigarElements()) { + if (ce.getLength() != 0 && (! elements.isEmpty() || ce.getOperator() != CigarOperator.D)) { elements.add(ce); } } + return new Cigar(elements); } diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java index ea3e2bdbb..d9f514593 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java @@ -33,9 +33,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class AlignmentUtilsUnitTest { private SAMFileHeader header; @@ -127,6 +125,114 @@ public class AlignmentUtilsUnitTest { ArtificialSAMUtils.DEFAULT_READ_LENGTH); } + private final List> makeCigarElementCombinations() { + // this functionality can be adapted to provide input data for whatever you might want in your data + final List cigarElements = new LinkedList(); + for ( final int size : Arrays.asList(0, 10) ) { + for ( final CigarOperator op : CigarOperator.values() ) { + cigarElements.add(new CigarElement(size, op)); + } + } + + final List> combinations = new LinkedList>(); + for ( final int nElements : Arrays.asList(1, 2, 3) ) { + combinations.addAll(Utils.makePermutations(cigarElements, nElements, true)); + } + + return combinations; + } + + + @DataProvider(name = "NumAlignedBasesCountingSoftClips") + public Object[][] makeNumAlignedBasesCountingSoftClips() { + List tests = new ArrayList(); + + final EnumSet alignedToGenome = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S); + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) n += alignedToGenome.contains(elt.getOperator()) ? elt.getLength() : 0; + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumAlignedBasesCountingSoftClips") + public void testNumAlignedBasesCountingSoftClips(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumAlignedBasesCountingSoftClips(read), expected, "Cigar " + cigar + " failed NumAlignedBasesCountingSoftClips"); + } + + @DataProvider(name = "CigarHasZeroElement") + public Object[][] makeCigarHasZeroElement() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + boolean hasZero = false; + for ( final CigarElement elt : elements ) hasZero = hasZero || elt.getLength() == 0; + tests.add(new Object[]{new Cigar(elements), hasZero}); + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "CigarHasZeroElement") + public void testCigarHasZeroSize(final Cigar cigar, final boolean hasZero) { + Assert.assertEquals(AlignmentUtils.cigarHasZeroSizeElement(cigar), hasZero, "Cigar " + cigar.toString() + " failed cigarHasZeroSizeElement"); + } + + @DataProvider(name = "NumHardClipped") + public Object[][] makeNumHardClipped() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) n += elt.getOperator() == CigarOperator.H ? elt.getLength() : 0; + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumHardClipped") + public void testNumHardClipped(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumHardClippedBases(read), expected, "Cigar " + cigar + " failed num hard clips"); + } + + @DataProvider(name = "NumAlignedBlocks") + public Object[][] makeNumAlignedBlocks() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) { + switch ( elt.getOperator() ) { + case M:case X:case EQ: n++; break; + default: break; + } + } + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumAlignedBlocks") + public void testNumAlignedBlocks(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumAlignmentBlocks(read), expected, "Cigar " + cigar + " failed NumAlignedBlocks"); + } + @Test public void testConsolidateCigar() { { From 22f7fe0d52fddb8a354e4dba5f6bad42511c1265 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:26:22 -0500 Subject: [PATCH 173/188] Expanded unit tests for AlignmentUtils -- Added JIRA entries for the remaining capabilities to be fixed up and unit tested --- .../sting/gatk/walkers/annotator/ReadPosRankSumTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java index 95b31b732..ddca5e0b8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java @@ -107,7 +107,7 @@ public class ReadPosRankSumTest extends RankSumTest implements StandardAnnotatio final int offset = ReadUtils.getReadCoordinateForReferenceCoordinate( read.getSoftStart(), read.getCigar(), refLoc, ReadUtils.ClippingTail.RIGHT_TAIL, true ); if ( offset == ReadUtils.CLIPPING_GOAL_NOT_REACHED ) continue; - int readPos = AlignmentUtils.calcAlignmentByteArrayOffset( read.getCigar(), offset, false, false, 0, 0 ); + int readPos = AlignmentUtils.calcAlignmentByteArrayOffset( read.getCigar(), offset, false, 0, 0 ); final int numAlignedBases = AlignmentUtils.getNumAlignedBasesCountingSoftClips( read ); if (readPos > numAlignedBases / 2) readPos = numAlignedBases - (readPos + 1); From 6d9816f1a57df6db3c81c90bb704c07d7068c95d Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:46:18 -0500 Subject: [PATCH 174/188] Cleanup unused utils functions, and add unit test for one (append) --- .../org/broadinstitute/sting/utils/Utils.java | 212 +----------------- .../sting/utils/UtilsUnitTest.java | 22 +- 2 files changed, 27 insertions(+), 207 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/Utils.java b/public/java/src/org/broadinstitute/sting/utils/Utils.java index eb287abd8..39fcbb3d2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Utils.java +++ b/public/java/src/org/broadinstitute/sting/utils/Utils.java @@ -240,6 +240,13 @@ public class Utils { } } + /** + * Create a new list that contains the elements of left along with elements elts + * @param left a non-null list of elements + * @param elts a varargs vector for elts to append in order to left + * @param + * @return A newly allocated linked list containing left followed by elts + */ public static List append(final List left, T ... elts) { final List l = new LinkedList(left); l.addAll(Arrays.asList(elts)); @@ -329,15 +336,6 @@ public class Utils { return str.substring(start, end+1); } - public static byte listMaxByte(List quals) { - if (quals.size() == 0) return 0; - byte m = quals.get(0); - for (byte b : quals) { - m = b > m ? b : m; - } - return m; - } - /** * Splits expressions in command args by spaces and returns the array of expressions. * Expressions may use single or double quotes to group any individual expression, but not both. @@ -390,182 +388,6 @@ public class Utils { return C; } - /** - * Appends String(s) B to array A. - * @param A First array. - * @param B Strings to append. - * @return A with B(s) appended. - */ - public static String[] appendArray(String[] A, String... B) { - return concatArrays(A, B); - } - - /** - * Returns indices of all occurrences of the specified symbol in the string - * @param s Search string - * @param ch Character to search for - * @return Indices of all occurrences of the specified symbol - */ - public static int[] indexOfAll(String s, int ch) { - int[] pos = new int[64]; - int z = 0; - - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) == ch) pos[z++] = i; - } - return reallocate(pos, z); - } - - public static int countSetBits(boolean[] array) { - int counter = 0; - for ( int i = 0; i < array.length; i++ ) { - if ( array[i] ) - counter++; - } - return counter; - } - - /** - * Returns new (reallocated) integer array of the specified size, with content - * of the original array orig copied into it. If newSize is - * less than the size of the original array, only first newSize elements will be copied. - * If new size is greater than the size of the original array, the content of the original array will be padded - * with zeros up to the new size. Finally, if new size is the same as original size, no memory reallocation - * will be performed and the original array will be returned instead. - * - * @param orig Original size. - * @param newSize New Size. - * - * @return New array with length equal to newSize. - */ - public static int[] reallocate(int[] orig, int newSize) { - if (orig.length == newSize) return orig; - int[] new_array = new int[newSize]; - int L = (newSize > orig.length ? orig.length : newSize); - for (int i = 0; i < L; i++) new_array[i] = orig[i]; - return new_array; - } - - - /** - * Returns a copy of array a, extended with additional n elements to the right (if n > 0 ) or -n elements to the - * left (if n<0), copying the values form the original array. Newly added elements are filled with value v. Note that - * if array a is being padded to the left, first (-n) elements of the returned array are v's, followed by the content of - * array a. - * @param a original array - * @param n number of (v-filled) elements to append to a on the right (n>0) or on the left (n<0) - * @param v element value - * @return the extended copy of array a with additional n elements - */ - public static byte [] extend(final byte[] a, int n, byte v) { - - byte [] newA; - - if ( n > 0 ) { - newA = Arrays.copyOf(a, a.length+n); - if ( v != 0) { // java pads with 0's for us, so there is nothing to do if v==0 - for ( int i = a.length; i < newA.length ; i++ ) newA[i] = v; - } - return newA; - } - - // we are here only if n < 0: - n = (-n); - newA = new byte[ a.length + n ]; - int i; - if ( v!= 0 ) { - i = 0; - for( ; i < n; i++ ) newA[i] = v; - } else { - i = n; - } - for ( int j = 0 ; j < a.length ; i++, j++) newA[i]=a[j]; - return newA; - } - - - /** - * Returns a copy of array a, extended with additional n elements to the right (if n > 0 ) or -n elements to the - * left (if n<0), copying the values form the original array. Newly added elements are filled with value v. Note that - * if array a is padded to the left, first (-n) elements of the returned array are v's, followed by the content of - * array a. - * @param a original array - * @param n number of (v-filled) elements to append to a on the right (n>0) or on the left (n<0) - * @param v element value - * @return the extended copy of array a with additional n elements - */ - public static short [] extend(final short[] a, int n, short v) { - - short [] newA; - - if ( n > 0 ) { - newA = Arrays.copyOf(a, a.length+n); - if ( v != 0) { // java pads with 0's for us, so there is nothing to do if v==0 - for ( int i = a.length; i < newA.length ; i++ ) newA[i] = v; - } - return newA; - } - - // we are here only if n < 0: - n = (-n); - newA = new short[ a.length + n ]; - int i; - if ( v!= 0 ) { - i = 0; - for( ; i < n; i++ ) newA[i] = v; - } else { - i = n; - } - for ( int j = 0 ; j < a.length ; i++, j++) newA[i]=a[j]; - return newA; - } - - /* TEST ME - public static void main(String[] argv) { - List l1 = new LinkedList(); - List l2 = new ArrayList(); - - l1.add(1); - l1.add(5); - l1.add(3); - l1.add(10); - l1.add(4); - l1.add(2); - l2.add(1); - l2.add(5); - l2.add(3); - l2.add(10); - l2.add(4); - l2.add(2); - - Predicate p = new Predicate() { - public boolean apply(Integer i) { - return i > 2; - } - }; - filterInPlace(p, l1); - filterInPlace(p, l2); - - for ( int i = 0 ; i < l1.size(); i++ ) System.out.print(" "+l1.get(i)); - System.out.println(); - for ( int i = 0 ; i < l2.size(); i++ ) System.out.print(" " + l2.get(i)); - System.out.println(); - - } - - */ - - /** - * a helper method. Turns a single character string into a char. - * - * @param str the string - * - * @return a char - */ - public static char stringToChar(String str) { - if (str.length() != 1) throw new IllegalArgumentException("String length must be one"); - return str.charAt(0); - } public static > List sorted(Collection c) { return sorted(c, false); @@ -594,18 +416,6 @@ public class Utils { return l; } - public static , V> String sortedString(Map c) { - List t = new ArrayList(c.keySet()); - Collections.sort(t); - - List pairs = new ArrayList(); - for ( T k : t ) { - pairs.add(k + "=" + c.get(k)); - } - - return "{" + join(", ", pairs) + "}"; - } - /** * Reverse a byte array of bases * @@ -654,14 +464,6 @@ public class Utils { return new String( reverse( bases.getBytes() )) ; } - public static byte[] charSeq2byteSeq(char[] seqIn) { - byte[] seqOut = new byte[seqIn.length]; - for ( int i = 0; i < seqIn.length; i++ ) { - seqOut[i] = (byte)seqIn[i]; - } - return seqOut; - } - public static boolean isFlagSet(int value, int flag) { return ((value & flag) == flag); } diff --git a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java index 5d6ecd0f9..29c643153 100644 --- a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java @@ -32,8 +32,7 @@ import org.broadinstitute.sting.BaseTest; import org.testng.annotations.Test; import java.io.File; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; /** * Testing framework for general purpose utilities class. @@ -43,6 +42,25 @@ import java.util.Map; */ public class UtilsUnitTest extends BaseTest { + @Test + public void testAppend() { + for ( int leftSize : Arrays.asList(0, 1, 2, 3) ) { + for ( final int rightSize : Arrays.asList(0, 1, 2) ) { + final List left = new LinkedList(); + for ( int i = 0; i < leftSize; i++ ) left.add(i); + final List total = new LinkedList(); + for ( int i = 0; i < leftSize + rightSize; i++ ) total.add(i); + + if ( rightSize == 0 ) + Assert.assertEquals(Utils.append(left), total); + if ( rightSize == 1 ) + Assert.assertEquals(Utils.append(left, leftSize), total); + if ( rightSize == 2 ) + Assert.assertEquals(Utils.append(left, leftSize, leftSize + 1), total); + } + } + + } @Test public void testDupStringNoChars() { From 1fb182d951c848341254ef454f576fa7a91b804e Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 01:18:51 -0500 Subject: [PATCH 175/188] Restore Utils.appendArray() This utility method was used by the PipelineTest class, and deleting it was causing tests to not compile. --- .../java/src/org/broadinstitute/sting/utils/Utils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/java/src/org/broadinstitute/sting/utils/Utils.java b/public/java/src/org/broadinstitute/sting/utils/Utils.java index 39fcbb3d2..77f3a84c3 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Utils.java +++ b/public/java/src/org/broadinstitute/sting/utils/Utils.java @@ -388,6 +388,15 @@ public class Utils { return C; } + /** + * Appends String(s) B to array A. + * @param A First array. + * @param B Strings to append. + * @return A with B(s) appended. + */ + public static String[] appendArray(String[] A, String... B) { + return concatArrays(A, B); + } public static > List sorted(Collection c) { return sorted(c, false); From a520058ef6e95292275979cebc85440f0b4243c3 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Fri, 1 Feb 2013 11:13:10 -0500 Subject: [PATCH 176/188] Add option to specify maximum STR length to RepeatCovariates from command line to ease testing --- .../bqsr/RecalibrationArgumentCollection.java | 12 ++++++++++++ .../recalibration/covariates/RepeatCovariate.java | 6 ++++-- .../recalibration/RepeatCovariatesUnitTest.java | 6 +++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java index 4c98a70a0..95b54102f 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java @@ -223,6 +223,18 @@ public class RecalibrationArgumentCollection { @Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only") public PrintStream RECAL_TABLE_UPDATE_LOG = null; + /** + * The repeat covariate will use a context of this size to calculate it's covariate value for base insertions and deletions + */ + @Hidden + @Argument(fullName = "max_str_unit_length", shortName = "maxstr", doc = "Max size of the k-mer context to be used for repeat covariates", required = false) + public int MAX_STR_UNIT_LENGTH = 8; + + @Hidden + @Argument(fullName = "max_repeat_length", shortName = "maxrep", doc = "Max number of repetitions to be used for repeat covariates", required = false) + public int MAX_REPEAT_LENGTH = 20; + + public File existingRecalibrationReport = null; public GATKReportTable generateReportTable(final String covariateNames) { diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java index 0eeb18251..9672bc5f3 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -61,8 +61,8 @@ import java.util.Map; import java.util.Set; public abstract class RepeatCovariate implements ExperimentalCovariate { - public static final int MAX_REPEAT_LENGTH = 20; - public static final int MAX_STR_UNIT_LENGTH = 8; + protected int MAX_REPEAT_LENGTH; + protected int MAX_STR_UNIT_LENGTH; private final HashMap repeatLookupTable = new HashMap(); private final HashMap repeatReverseLookupTable = new HashMap(); private int nextId = 0; @@ -70,6 +70,8 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { // Initialize any member variables using the command-line arguments passed to the walkers @Override public void initialize(final RecalibrationArgumentCollection RAC) { + MAX_STR_UNIT_LENGTH = RAC.MAX_STR_UNIT_LENGTH; + MAX_REPEAT_LENGTH = RAC.MAX_REPEAT_LENGTH; } @Override diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java index 6d13fe96c..ea70deeea 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java @@ -139,8 +139,8 @@ public class RepeatCovariatesUnitTest { @Test(enabled = true) public void testManyObservations() { final int NUM_UNITS = 10; - final int MAX_REPEAT_UNIT_LENGTH = RepeatCovariate.MAX_STR_UNIT_LENGTH; - final int MAX_NUM_REPETITIONS = RepeatCovariate.MAX_REPEAT_LENGTH; + final int MAX_REPEAT_UNIT_LENGTH = RAC.MAX_STR_UNIT_LENGTH; + final int MAX_NUM_REPETITIONS = RAC.MAX_REPEAT_LENGTH; final int NUM_TEST_CASES = 100; Random random = new Random(); @@ -207,7 +207,7 @@ public class RepeatCovariatesUnitTest { int fw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(offset+1,readLength).getBytes(),true); int bw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(0,offset+1).getBytes(),false); - Assert.assertEquals(Math.min(fw+bw,RepeatCovariate.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); + Assert.assertEquals(Math.min(fw+bw,RAC.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); } } From c4b0ba4d45c102ed4eb0c2d52fa51950b424c4fb Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 00:36:54 -0500 Subject: [PATCH 177/188] Temporarily back out the Picard team's patches to GATKBAMIndex from December These patches to GATKBAMIndex are causing massive BAM index reading errors in combination with the latest version of Picard. The bug is either in the patches themselves or in the underlying SeekableBufferedStream class they rely on. Until the cause can be identified, we are temporarily backing out these changes so that we can continue to run with the latest Picard/Tribble. This reverts commits: 81483ec21e528790dfa719d18cdee27d577ca98e 68cf0309db490b79eecdabb4034987ff825ffea8 54bb68f28ad5fe1b3df01702e9c5e108106a0176 --- .../gatk/datasources/reads/GATKBAMIndex.java | 51 ++++++------------- .../qc/PileupWalkerIntegrationTest.java | 30 ----------- 2 files changed, 15 insertions(+), 66 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java index 1cfb527cd..aec41e340 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java @@ -25,17 +25,17 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import net.sf.samtools.seekablestream.SeekableBufferedStream; -import net.sf.samtools.seekablestream.SeekableFileStream; - import net.sf.samtools.*; - +import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -70,9 +70,6 @@ public class GATKBAMIndex { private final File mFile; - //TODO: figure out a good value for this buffer size - private final int BUFFERED_STREAM_BUFFER_SIZE=8192; - /** * Number of sequences stored in this index. */ @@ -83,8 +80,8 @@ public class GATKBAMIndex { */ private final long[] sequenceStartCache; - private SeekableFileStream fileStream; - private SeekableBufferedStream bufferedStream; + private FileInputStream fileStream; + private FileChannel fileChannel; public GATKBAMIndex(final File file) { mFile = file; @@ -282,6 +279,7 @@ public class GATKBAMIndex { for (int i = sequenceIndex; i < referenceSequence; i++) { sequenceStartCache[i] = position(); + // System.out.println("# Sequence TID: " + i); final int nBins = readInteger(); // System.out.println("# nBins: " + nBins); @@ -294,18 +292,15 @@ public class GATKBAMIndex { final int nLinearBins = readInteger(); // System.out.println("# nLinearBins: " + nLinearBins); skipBytes(8 * nLinearBins); - } sequenceStartCache[referenceSequence] = position(); } - - private void openIndexFile() { try { - fileStream = new SeekableFileStream(mFile); - bufferedStream = new SeekableBufferedStream(fileStream,BUFFERED_STREAM_BUFFER_SIZE); + fileStream = new FileInputStream(mFile); + fileChannel = fileStream.getChannel(); } catch (IOException exc) { throw new ReviewedStingException("Unable to open index file (" + exc.getMessage() +")" + mFile, exc); @@ -314,7 +309,7 @@ public class GATKBAMIndex { private void closeIndexFile() { try { - bufferedStream.close(); + fileChannel.close(); fileStream.close(); } catch (IOException exc) { @@ -359,12 +354,7 @@ public class GATKBAMIndex { private void read(final ByteBuffer buffer) { try { int bytesExpected = buffer.limit(); - //BufferedInputStream cannot read directly into a byte buffer, so we read into an array - //and put the result into the bytebuffer after the if statement. - - //SeekableBufferedStream is evil, it will "read" beyond the end of the file if you let it! - final int bytesToRead = (int) Math.min(bufferedStream.length() - bufferedStream.position(), bytesExpected); //min of int and long will definitely be castable to an int. - int bytesRead = bufferedStream.read(byteArray,0,bytesToRead); + int bytesRead = fileChannel.read(buffer); // We have a rigid expectation here to read in exactly the number of bytes we've limited // our buffer to -- if we read in fewer bytes than this, or encounter EOF (-1), the index @@ -375,7 +365,6 @@ public class GATKBAMIndex { "Please try re-indexing the corresponding BAM file.", mFile)); } - buffer.put(byteArray,0,bytesRead); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to read bytes from index file " + mFile); @@ -389,13 +378,10 @@ public class GATKBAMIndex { */ private ByteBuffer buffer = null; - //BufferedStream don't read into ByteBuffers, so we need this temporary array - private byte[] byteArray=null; private ByteBuffer getBuffer(final int size) { if(buffer == null || buffer.capacity() < size) { // Allocate a new byte buffer. For now, make it indirect to make sure it winds up on the heap for easier debugging. buffer = ByteBuffer.allocate(size); - byteArray = new byte[size]; buffer.order(ByteOrder.LITTLE_ENDIAN); } buffer.clear(); @@ -405,13 +391,7 @@ public class GATKBAMIndex { private void skipBytes(final int count) { try { - - //try to skip forward the requested amount. - long skipped = bufferedStream.skip(count); - - if( skipped != count ) { //if not managed to skip the requested amount - throw new ReviewedStingException("Index: unable to reposition file channel of index file " + mFile); - } + fileChannel.position(fileChannel.position() + count); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to reposition file channel of index file " + mFile); @@ -420,8 +400,7 @@ public class GATKBAMIndex { private void seek(final long position) { try { - //to seek a new position, move the fileChannel, and reposition the bufferedStream - bufferedStream.seek(position); + fileChannel.position(position); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to reposition of file channel of index file " + mFile); @@ -434,7 +413,7 @@ public class GATKBAMIndex { */ private long position() { try { - return bufferedStream.position(); + return fileChannel.position(); } catch (IOException exc) { throw new ReviewedStingException("Unable to read position from index file " + mFile, exc); diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java index 76654fb74..a6191802b 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java @@ -31,9 +31,6 @@ import org.testng.annotations.Test; import java.util.Arrays; public class PileupWalkerIntegrationTest extends WalkerTest { - String gatkSpeedupArgs="-T Pileup -I " + validationDataLocation + "NA12878.HiSeq.WGS.bwa.cleaned.recal.hg19.20.bam " - + "-R " + hg19Reference + " -o %s "; - @Test public void testGnarleyFHSPileup() { String gatk_args = "-T Pileup -I " + validationDataLocation + "FHS_Pileup_Test.bam " @@ -67,31 +64,4 @@ public class PileupWalkerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(SingleReadAligningOffChromosome1MD5)); executeTest("Testing single read spanning off chromosome 1 unindexed", spec); } - - /************************/ - - //testing speedup to GATKBAMIndex - - - @Test - public void testPileupOnLargeBamChr20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:1-76,050", 1, Arrays.asList("8702701350de11a6d28204acefdc4775")); - executeTest("Testing single on big BAM at start of chromosome 20", spec); - } - @Test - public void testPileupOnLargeBamMid20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:10,000,000-10,001,100", 1, Arrays.asList("818cf5a8229efe6f89fc1cd8145ccbe3")); - executeTest("Testing single on big BAM somewhere in chromosome 20", spec); - } - @Test - public void testPileupOnLargeBamEnd20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:62,954,114-63,025,520", 1, Arrays.asList("22471ea4a12e5139aef62bf8ff2a5b63")); - executeTest("Testing single at end of chromosome 20", spec); - } - @Test - public void testPileupOnLargeBam20Many(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:1-76,050 -L 20:20,000,000-20,000,100 -L 20:40,000,000-40,000,100 -L 20:30,000,000-30,000,100 -L 20:50,000,000-50,000,100 -L 20:62,954,114-63,025,520 ", - 1, Arrays.asList("08d899ed7c5a76ef3947bf67338acda1")); - executeTest("Testing single on big BAM many places", spec); - } } From c6581e49537d9422ef414f6278d9098ae3830f4f Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 12:14:31 -0500 Subject: [PATCH 178/188] Update MD5s to reflect version number change in the BAM header I've confirmed via a script that all of these differences only involve the version number bump in the BAM headers and nothing else: < @HD VN:1.0 GO:none SO:coordinate --- > @HD VN:1.4 GO:none SO:coordinate --- .../walkers/bqsr/BQSRIntegrationTest.java | 8 +++--- .../indels/IndelRealignerIntegrationTest.java | 12 ++++----- .../gatk/walkers/BAQIntegrationTest.java | 4 +-- .../ClipReadsWalkersIntegrationTest.java | 26 +++++++++---------- .../readutils/PrintReadsIntegrationTest.java | 20 +++++++------- .../utils/crypt/GATKKeyIntegrationTest.java | 2 +- .../interval/IntervalIntegrationTest.java | 4 +-- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java index 1f4875298..f7907649d 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java @@ -188,12 +188,12 @@ public class BQSRIntegrationTest extends WalkerTest { public Object[][] createPRTestData() { List tests = new ArrayList(); - tests.add(new Object[]{1, new PRTest(" -qq -1", "b8d296fb78adc5cff7ce12073a69d985")}); - tests.add(new Object[]{1, new PRTest(" -qq 6", "2ee0cedf84c1a33a807438172bc36c11")}); - tests.add(new Object[]{1, new PRTest(" -DIQ", "46cf74900bf8b13438e6a195b3085c48")}); + tests.add(new Object[]{1, new PRTest(" -qq -1", "fcc136b877fbde38791533b0f1ae39e4")}); + tests.add(new Object[]{1, new PRTest(" -qq 6", "f21b537c1689b8051b878ea5cc9b61a0")}); + tests.add(new Object[]{1, new PRTest(" -DIQ", "1d04a242bf825177d6a45eff9fbed647")}); for ( final int nct : Arrays.asList(1, 2, 4) ) { - tests.add(new Object[]{nct, new PRTest("", "88b88f006ebb1aade85089bfba5a9e8d")}); + tests.add(new Object[]{nct, new PRTest("", "b6f343ac69c63cdb49205c13e67297fc")}); } return tests.toArray(new Object[][]{}); diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java index eba9c7780..275ababda 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java @@ -60,8 +60,8 @@ public class IndelRealignerIntegrationTest extends WalkerTest { private static final String knownIndels = validationDataLocation + "indelRealignerTest.pilot1.ceu.vcf"; private static final String baseCommandPrefix = "-T IndelRealigner -noPG -R " + b36KGReference + " -I " + mainTestBam + " -targetIntervals " + mainTestIntervals + " -compress 0 -L 20:49,500-55,500 "; private static final String baseCommand = baseCommandPrefix + "-o %s "; - private static final String base_md5 = "7574ab7d0b1ee5d44a0b3f85b6e944e6"; - private static final String base_md5_with_SW_or_VCF = "a918d69d26d3c87b29002ed31f428c48"; + private static final String base_md5 = "a102dd55451799e5f053c784b762087e"; + private static final String base_md5_with_SW_or_VCF = "06b8eefcbd785e929027feaa22bb060d"; @Test public void testDefaults() { @@ -84,7 +84,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec1 = new WalkerTestSpec( baseCommand + "--consensusDeterminationModel KNOWNS_ONLY -known " + knownIndels, 1, - Arrays.asList("36718f10d523dfb0fa2a709480f24bd4")); + Arrays.asList("1b24b0f2a20aed1adc726d1b296a3192")); executeTest("realigner known indels only from VCF", spec1); } @@ -101,7 +101,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { public void testLods() { HashMap e = new HashMap(); e.put( "-LOD 60", base_md5 ); - e.put( "-LOD 1 --consensusDeterminationModel USE_SW", "9a75a0f7ad0442c78d0f8df260e733a4" ); + e.put( "-LOD 1 --consensusDeterminationModel USE_SW", "4bf28d3c0337682d439257874377a681" ); for ( Map.Entry entry : e.entrySet() ) { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( @@ -117,7 +117,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec( "-T IndelRealigner -noPG -R " + b36KGReference + " -I " + validationDataLocation + "NA12878.chrom1.SLX.SRP000032.2009_06.bam -L 1:10,000,000-11,000,000 -targetIntervals " + validationDataLocation + "indelRealignerTest.NA12878.chrom1.intervals -compress 0 -o %s", 1, - Arrays.asList("e98f51d71f0a82141b36a7e9f94db237")); + Arrays.asList("f4f6c3b2a2be0306a0ecd3def334bafe")); executeTest("realigner long run", spec); } @@ -126,7 +126,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec( baseCommand + "--noOriginalAlignmentTags --consensusDeterminationModel USE_SW", 1, - Arrays.asList("58ac675d0699eb236d469b8e84513d11")); + Arrays.asList("71fb521f8febfe2dc683fc636e28ae7d")); executeTest("realigner no output tags", spec); } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java index 13cd2be73..6b0422c6a 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java @@ -43,13 +43,13 @@ public class BAQIntegrationTest extends WalkerTest { // -------------------------------------------------------------------------------------------------------------- @Test public void testPrintReadsNoBAQ() { - WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq OFF", 1, Arrays.asList("d97340a2bba2c6320d1ebeb86024a27c")); + WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq OFF", 1, Arrays.asList("11af64ba020262d06b490bae2c5e08f8")); executeTest(String.format("testPrintReadsNoBAQ"), spec); } @Test public void testPrintReadsRecalBAQ() { - WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq RECALCULATE", 1, Arrays.asList("4ac691bde1ba1301a59857694fda6ae2")); + WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq RECALCULATE", 1, Arrays.asList("96ec97cf92f1f660bd5244c6b44539b3")); executeTest(String.format("testPrintReadsRecalBAQ"), spec); } } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java index ae4bce81b..b3d583ef1 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java @@ -47,22 +47,22 @@ public class ClipReadsWalkersIntegrationTest extends WalkerTest { } final static String Q10ClipOutput = "b29c5bc1cb9006ed9306d826a11d444f"; - @Test public void testQClip0() { testClipper("clipQSum0", "-QT 0", "117a4760b54308f81789c39b1c9de578", "33e781084379aae538954e30919e8fd3"); } - @Test public void testQClip2() { testClipper("clipQSum2", "-QT 2", Q10ClipOutput, "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testQClip10() { testClipper("clipQSum10", "-QT 10", "b29c5bc1cb9006ed9306d826a11d444f", "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testQClip20() { testClipper("clipQSum20", "-QT 20", "6c3434dce66ae5c9eeea502f10fb9bee", "67263a39d5127f2660a5b638ff32056a"); } + @Test public void testQClip0() { testClipper("clipQSum0", "-QT 0", "117a4760b54308f81789c39b1c9de578", "12be03c817d94bab88457e5afe74256a"); } + @Test public void testQClip2() { testClipper("clipQSum2", "-QT 2", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testQClip10() { testClipper("clipQSum10", "-QT 10", "b29c5bc1cb9006ed9306d826a11d444f", "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testQClip20() { testClipper("clipQSum20", "-QT 20", "6c3434dce66ae5c9eeea502f10fb9bee", "0bcfd177fe4be422898eda8e161ebd6c"); } - @Test public void testClipRange1() { testClipper("clipRange1", "-CT 1-5", "b5acd753226e25b1e088838c1aab9117", "764846d0592f346a33525af674fd7a10"); } - @Test public void testClipRange2() { testClipper("clipRange2", "-CT 1-5,11-15", "be4fcad5b666a5540028b774169cbad7", "3061cf742f9e5526a61130128ae761a3"); } + @Test public void testClipRange1() { testClipper("clipRange1", "-CT 1-5", "b5acd753226e25b1e088838c1aab9117", "aed836c97c6383dd80e39a093cc25e08"); } + @Test public void testClipRange2() { testClipper("clipRange2", "-CT 1-5,11-15", "be4fcad5b666a5540028b774169cbad7", "5f6e08bd44d6faf5b85cde5d4ec1a36f"); } - @Test public void testClipSeq() { testClipper("clipSeqX", "-X CCCCC", "db199bd06561c9f2122f6ffb07941fbc", "b89459f373e40f0b835c1faff2208839"); } - @Test public void testClipSeqFile() { testClipper("clipSeqXF", "-XF " + privateTestDir + "seqsToClip.fasta", "d011a3152b31822475afbe0281491f8d", "24e19116ef16a37a6d095ed5c22c2466"); } + @Test public void testClipSeq() { testClipper("clipSeqX", "-X CCCCC", "db199bd06561c9f2122f6ffb07941fbc", "f3cb42759428df80d06e9789f9f9f762"); } + @Test public void testClipSeqFile() { testClipper("clipSeqXF", "-XF " + privateTestDir + "seqsToClip.fasta", "d011a3152b31822475afbe0281491f8d", "44658c018378467f809b443d047d5778"); } - @Test public void testClipMulti() { testClipper("clipSeqMulti", "-QT 10 -CT 1-5 -XF " + privateTestDir + "seqsToClip.fasta -X CCCCC", "a23187bd9bfb06557f799706d98441de", "ad8d30300cb43d5e300fcc4d2450da8e"); } + @Test public void testClipMulti() { testClipper("clipSeqMulti", "-QT 10 -CT 1-5 -XF " + privateTestDir + "seqsToClip.fasta -X CCCCC", "a23187bd9bfb06557f799706d98441de", "bae38f83eb9b63857f5e6e3c6e62f80c"); } - @Test public void testClipNs() { testClipper("testClipNs", "-QT 10 -CR WRITE_NS", Q10ClipOutput, "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testClipQ0s() { testClipper("testClipQs", "-QT 10 -CR WRITE_Q0S", Q10ClipOutput, "2a1a3153e0942ab355fd8a6e082b30e0"); } - @Test public void testClipSoft() { testClipper("testClipSoft", "-QT 10 -CR SOFTCLIP_BASES", Q10ClipOutput, "50d43d63d8e39f67a87a6359963c6f52"); } + @Test public void testClipNs() { testClipper("testClipNs", "-QT 10 -CR WRITE_NS", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testClipQ0s() { testClipper("testClipQs", "-QT 10 -CR WRITE_Q0S", Q10ClipOutput, "3b32da2eaab7a2d4729fdb486cedbb2f"); } + @Test public void testClipSoft() { testClipper("testClipSoft", "-QT 10 -CR SOFTCLIP_BASES", Q10ClipOutput, "9d355b0f6d2076178e92bd7fcd8f5adb"); } @Test public void testUseOriginalQuals() { @@ -74,7 +74,7 @@ public class ClipReadsWalkersIntegrationTest extends WalkerTest { " -OQ -QT 4 -CR WRITE_Q0S" + " -o %s -os %s", 2, - Arrays.asList("22db22749f811d30216215e047461621", "55c01ccc2e84481b22d3632cdb06c8ba")); + Arrays.asList("c83b4e2ade8654a2818fe9d405f07662", "55c01ccc2e84481b22d3632cdb06c8ba")); executeTest("clipOriginalQuals", spec); } } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java index 83f801a98..b509fc1df 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java @@ -54,17 +54,17 @@ public class PrintReadsIntegrationTest extends WalkerTest { @DataProvider(name = "PRTest") public Object[][] createPrintReadsTestData() { return new Object[][]{ - {new PRTest(hg18Reference, "HiSeq.1mb.bam", "", "dc8e5451dd29757c336013146010f73a")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -compress 0", "fde82269c78c9e91e57286433531b4af")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -simplifyBAM", "0531717b32a7e21c0de70b1526b0751f")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -n 10", "cdc4ddf9ee1d2ecf37168da8ef23c270")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", "", "fa9c66f66299fe5405512ac36ec9d0f2")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -compress 0", "488eb22abc31c6af7cbb1a3d41da1507")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -simplifyBAM", "1510dc4429f3ed49caf96da41e8ed396")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -n 10", "0e3d1748ad1cb523e3295cab9d09d8fc")}, // See: GATKBAMIndex.getStartOfLastLinearBin(), BAMScheduler.advance(), IntervalOverlapFilteringIterator.advance() - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", "", "0a9ce949d07a84cb33a1a8e3358bf679")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1", "6e920b8505e7e95d67634b0905237dbc")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L unmapped", "13bb9a91b1d4dd2425f73302b8a1ac1c")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1 -L unmapped", "6e920b8505e7e95d67634b0905237dbc")}, - {new PRTest(b37KGReference, "oneReadAllInsertion.bam", "", "6caec4f8a25befb6aba562955401af93")}, - {new PRTest(b37KGReference, "NA12878.1_10mb_2_10mb.bam", "", "c43380ac39b98853af457b90e52f8427")} + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", "", "e1cac555f3d720f611c47eec93e84bd9")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1", "6e2558317d409195eab3006dc9e5524c")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L unmapped", "2d32440e47e8d9d329902fe573ad94ce")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1 -L unmapped", "6e2558317d409195eab3006dc9e5524c")}, + {new PRTest(b37KGReference, "oneReadAllInsertion.bam", "", "349650b6aa9e574b48a2a62627f37c7d")}, + {new PRTest(b37KGReference, "NA12878.1_10mb_2_10mb.bam", "", "0c1cbe67296637a85e80e7a182f828ab")} }; } diff --git a/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java b/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java index 7421767c7..9c9248669 100644 --- a/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java @@ -38,7 +38,7 @@ public class GATKKeyIntegrationTest extends WalkerTest { public static final String BASE_COMMAND = String.format("-T PrintReads -R %s -I %s -o %%s", publicTestDir + "exampleFASTA.fasta", publicTestDir + "exampleBAM.bam"); - public static final String MD5_UPON_SUCCESSFUL_RUN = "b9dc5bf6753ca2819e70b056eaf61258"; + public static final String MD5_UPON_SUCCESSFUL_RUN = "e7b4a5b62f9d4badef1cd07040011b2b"; private void runGATKKeyTest ( String testName, String etArg, String keyArg, Class expectedException, String md5 ) { diff --git a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java index dc8a31945..98ecd0f43 100644 --- a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java @@ -78,7 +78,7 @@ public class IntervalIntegrationTest extends WalkerTest { // our base file File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam"); spec.setOutputFileLocation(baseOutputFile); - spec.addAuxFile("748a38ed5eb0a043dfc7b82f0d1e8063",createTempFileFromBase(baseOutputFile.getAbsolutePath())); + spec.addAuxFile("95e98192e5b90cf80eaa87a4ace263da",createTempFileFromBase(baseOutputFile.getAbsolutePath())); spec.addAuxFile("fadcdf88597b9609c5f2a17f4c6eb455", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai")); executeTest("testUnmappedReadInclusion",spec); @@ -99,7 +99,7 @@ public class IntervalIntegrationTest extends WalkerTest { // our base file File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam"); spec.setOutputFileLocation(baseOutputFile); - spec.addAuxFile("083ef1e9ded868e0d12c05a1354c0319",createTempFileFromBase(baseOutputFile.getAbsolutePath())); + spec.addAuxFile("3944b5a6bfc06277ed3afb928a20d588",createTempFileFromBase(baseOutputFile.getAbsolutePath())); spec.addAuxFile("fa90ff91ac0cc689c71a3460a3530b8b", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai")); executeTest("testUnmappedReadInclusion",spec); From 2fee000dba7978ce5d89e4e0d2e40486b57c108d Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Fri, 1 Feb 2013 13:50:38 -0500 Subject: [PATCH 179/188] Adding unit tests for KBestPaths class and fixing edge case bugs. --- .../walkers/haplotypecaller/DeBruijnEdge.java | 2 + .../haplotypecaller/DeBruijnVertex.java | 6 + .../walkers/haplotypecaller/KBestPaths.java | 72 ++--- .../haplotypecaller/KBestPathsUnitTest.java | 246 ++++++++++++++++++ .../SimpleDeBruijnAssemblerUnitTest.java | 26 +- 5 files changed, 309 insertions(+), 43 deletions(-) create mode 100644 protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPathsUnitTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java index 881fe4204..8d7732a87 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnEdge.java @@ -94,10 +94,12 @@ public class DeBruijnEdge { this.isRef = isRef; } + // For use when comparing edges pulled from the same graph public boolean equals( final DefaultDirectedGraph graph, final DeBruijnEdge edge ) { return (graph.getEdgeSource(this).equals(graph.getEdgeSource(edge))) && (graph.getEdgeTarget(this).equals(graph.getEdgeTarget(edge))); } + // For use when comparing edges across graphs! public boolean equals( final DefaultDirectedGraph graph, final DeBruijnEdge edge, final DefaultDirectedGraph graph2 ) { return (graph.getEdgeSource(this).equals(graph2.getEdgeSource(edge))) && (graph.getEdgeTarget(this).equals(graph2.getEdgeTarget(edge))); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnVertex.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnVertex.java index 0b898ee8d..c6f23359b 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnVertex.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/DeBruijnVertex.java @@ -46,6 +46,9 @@ package org.broadinstitute.sting.gatk.walkers.haplotypecaller; +import com.google.java.contract.Ensures; +import com.google.java.contract.Invariant; + import java.util.Arrays; /** @@ -54,6 +57,7 @@ import java.util.Arrays; * Date: Mar 23, 2011 */ // simple node class for storing kmer sequences +@Invariant("kmer > 0") public class DeBruijnVertex { protected final byte[] sequence; @@ -82,10 +86,12 @@ public class DeBruijnVertex { return new String( getSuffix() ); } + @Ensures("result != null") public byte[] getSequence() { return sequence.clone(); } + @Ensures("result != null") public byte[] getSuffix() { return Arrays.copyOfRange( sequence, kmer - 1, sequence.length ); } diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java index edfe8254d..49e926e32 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPaths.java @@ -47,6 +47,7 @@ package org.broadinstitute.sting.gatk.walkers.haplotypecaller; import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; @@ -85,7 +86,6 @@ public class KBestPaths { // the scores for the path private final int totalScore; - private final int lowestEdge; // the graph from which this path originated private final DefaultDirectedGraph graph; @@ -100,17 +100,17 @@ public class KBestPaths { lastVertex = initialVertex; edges = new ArrayList(0); totalScore = 0; - lowestEdge = -1; this.graph = graph; } public Path( final Path p, final DeBruijnEdge edge ) { + if( !p.graph.getEdgeSource(edge).equals(p.lastVertex) ) { throw new IllegalStateException("Edges added to path must be contiguous."); } + graph = p.graph; lastVertex = p.graph.getEdgeTarget(edge); edges = new ArrayList(p.edges); edges.add(edge); totalScore = p.totalScore + edge.getMultiplicity(); - lowestEdge = ( p.lowestEdge == -1 ) ? edge.getMultiplicity() : Math.min(p.lowestEdge, edge.getMultiplicity()); } /** @@ -119,22 +119,37 @@ public class KBestPaths { * @return true if the edge is found in this path */ public boolean containsEdge( final DeBruijnEdge edge ) { - final DeBruijnVertex targetVertex = graph.getEdgeTarget(edge); for( final DeBruijnEdge e : edges ) { - if( e.equals(graph, edge) || graph.getEdgeTarget(e).equals(targetVertex) ) { + if( e.equals(graph, edge) ) { return true; } } - + return false; } + public int numInPath( final DefaultDirectedGraph graph, final DeBruijnEdge edge ) { + int numInPath = 0; + for( final DeBruijnEdge e : edges ) { + if( e.equals(graph, edge) ) { + numInPath++; + } + } + + return numInPath; + } + + + public boolean containsRefEdge() { + for( final DeBruijnEdge e : edges ) { + if( e.isRef() ) { return true; } + } + return false; + } public List getEdges() { return edges; } public int getScore() { return totalScore; } - public int getLowestEdge() { return lowestEdge; } - public DeBruijnVertex getLastVertexInPath() { return lastVertex; } /** @@ -152,6 +167,17 @@ public class KBestPaths { return bases; } + /** + * Pull the added base sequence implied by visiting this node in a path + * @param graph the graph from which the vertex originated + * @param v the vertex whose sequence to grab + * @return non-null sequence of bases corresponding to this node in the graph + */ + @Ensures({"result != null"}) + public byte[] getAdditionalSequence( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { + return ( edges.size()==0 || graph.getEdgeSource(edges.get(0)).equals(v) ? v.getSequence() : v.getSuffix() ); + } + /** * Calculate the cigar string for this path using a bubble traversal of the assembly graph and running a Smith-Waterman alignment on each bubble */ @@ -190,6 +216,7 @@ public class KBestPaths { return AlignmentUtils.consolidateCigar(bsm.cigar); } + @Requires({"bsm != null", "graph != null", "node != null"}) private void advanceBubbleStateMachine( final BubbleStateMachine bsm, final DefaultDirectedGraph graph, final DeBruijnVertex node, final DeBruijnEdge e ) { if( isReferenceNode( graph, node ) ) { if( !bsm.inBubble ) { // just add the ref bases as M's in the Cigar string, and don't do anything else @@ -233,8 +260,11 @@ public class KBestPaths { } } + @Requires({"graph != null"}) + @Ensures({"result != null", "result.getReadLength() == bubbleBytes.length"}) private Cigar calculateCigarForCompleteBubble( final DefaultDirectedGraph graph, final byte[] bubbleBytes, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex ) { - final byte[] refBytes = getReferenceBytes(graph, fromVertex, toVertex); + final byte[] refBytes = getReferenceBytes(this, graph, fromVertex, toVertex); + final Cigar cigar = new Cigar(); // add padding to anchor ref/alt bases in the SW matrix @@ -296,13 +326,6 @@ public class KBestPaths { } } - protected static class PathComparatorLowestEdge implements Comparator, Serializable { - @Override - public int compare(final Path path1, final Path path2) { - return path2.lowestEdge - path1.lowestEdge; - } - } - public static List getKBestPaths( final DefaultDirectedGraph graph, final int k ) { if( k > MAX_PATHS_TO_HOLD/2 ) { throw new ReviewedStingException("Asked for more paths than MAX_PATHS_TO_HOLD!"); } final ArrayList bestPaths = new ArrayList(); @@ -399,17 +422,6 @@ public class KBestPaths { return graph.inDegreeOf(v) == 0; } - /** - * Pull the added base sequence implied by visiting this node in a path - * @param graph the graph from which the vertex originated - * @param v the vertex whose sequence to grab - * @return non-null sequence of bases corresponding to this node in the graph - */ - @Ensures({"result != null"}) - public static byte[] getAdditionalSequence( final DefaultDirectedGraph graph, final DeBruijnVertex v ) { - return ( isSource(graph, v) ? v.getSequence() : v.getSuffix() ); - } - /** * Is this edge both a reference edge and a source edge for the reference path * @param graph the graph from which the edge originated @@ -569,7 +581,7 @@ public class KBestPaths { } // fromVertex (exclusive) -> toVertex (exclusive) - public static byte[] getReferenceBytes( final DefaultDirectedGraph graph, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex ) { + public static byte[] getReferenceBytes( final Path path, final DefaultDirectedGraph graph, final DeBruijnVertex fromVertex, final DeBruijnVertex toVertex ) { byte[] bytes = null; if( fromVertex != null && toVertex != null && !referencePathExists(graph, fromVertex, toVertex) ) { throw new ReviewedStingException("Asked for a reference path which doesn't exist. " + fromVertex + " --> " + toVertex); @@ -577,11 +589,11 @@ public class KBestPaths { DeBruijnVertex v = fromVertex; if( v == null ) { v = getReferenceSourceVertex(graph); - bytes = ArrayUtils.addAll( bytes, getAdditionalSequence(graph, v) ); + bytes = ArrayUtils.addAll( bytes, path.getAdditionalSequence(graph, v) ); } v = getNextReferenceVertex(graph, v); while( (toVertex != null && !v.equals(toVertex)) || (toVertex == null && v != null) ) { - bytes = ArrayUtils.addAll( bytes, getAdditionalSequence(graph, v) ); + bytes = ArrayUtils.addAll( bytes, path.getAdditionalSequence(graph, v) ); // advance along the reference path v = getNextReferenceVertex(graph, v); } diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPathsUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPathsUnitTest.java new file mode 100644 index 000000000..a39ca23e3 --- /dev/null +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/KBestPathsUnitTest.java @@ -0,0 +1,246 @@ +/* +* By downloading the PROGRAM you agree to the following terms of use: +* +* BROAD INSTITUTE - SOFTWARE LICENSE AGREEMENT - FOR ACADEMIC NON-COMMERCIAL RESEARCH PURPOSES ONLY +* +* This Agreement is made between the Broad Institute, Inc. with a principal address at 7 Cambridge Center, Cambridge, MA 02142 (BROAD) and the LICENSEE and is effective at the date the downloading is completed (EFFECTIVE DATE). +* +* WHEREAS, LICENSEE desires to license the PROGRAM, as defined hereinafter, and BROAD wishes to have this PROGRAM utilized in the public interest, subject only to the royalty-free, nonexclusive, nontransferable license rights of the United States Government pursuant to 48 CFR 52.227-14; and +* WHEREAS, LICENSEE desires to license the PROGRAM and BROAD desires to grant a license on the following terms and conditions. +* NOW, THEREFORE, in consideration of the promises and covenants made herein, the parties hereto agree as follows: +* +* 1. DEFINITIONS +* 1.1 PROGRAM shall mean copyright in the object code and source code known as GATK2 and related documentation, if any, as they exist on the EFFECTIVE DATE and can be downloaded from http://www.broadinstitute/GATK on the EFFECTIVE DATE. +* +* 2. LICENSE +* 2.1 Grant. Subject to the terms of this Agreement, BROAD hereby grants to LICENSEE, solely for academic non-commercial research purposes, a non-exclusive, non-transferable license to: (a) download, execute and display the PROGRAM and (b) create bug fixes and modify the PROGRAM. +* The LICENSEE may apply the PROGRAM in a pipeline to data owned by users other than the LICENSEE and provide these users the results of the PROGRAM provided LICENSEE does so for academic non-commercial purposes only. For clarification purposes, academic sponsored research is not a commercial use under the terms of this Agreement. +* 2.2 No Sublicensing or Additional Rights. LICENSEE shall not sublicense or distribute the PROGRAM, in whole or in part, without prior written permission from BROAD. LICENSEE shall ensure that all of its users agree to the terms of this Agreement. LICENSEE further agrees that it shall not put the PROGRAM on a network, server, or other similar technology that may be accessed by anyone other than the LICENSEE and its employees and users who have agreed to the terms of this agreement. +* 2.3 License Limitations. Nothing in this Agreement shall be construed to confer any rights upon LICENSEE by implication, estoppel, or otherwise to any computer software, trademark, intellectual property, or patent rights of BROAD, or of any other entity, except as expressly granted herein. LICENSEE agrees that the PROGRAM, in whole or part, shall not be used for any commercial purpose, including without limitation, as the basis of a commercial software or hardware product or to provide services. LICENSEE further agrees that the PROGRAM shall not be copied or otherwise adapted in order to circumvent the need for obtaining a license for use of the PROGRAM. +* +* 3. OWNERSHIP OF INTELLECTUAL PROPERTY +* LICENSEE acknowledges that title to the PROGRAM shall remain with BROAD. The PROGRAM is marked with the following BROAD copyright notice and notice of attribution to contributors. LICENSEE shall retain such notice on all copies. LICENSEE agrees to include appropriate attribution if any results obtained from use of the PROGRAM are included in any publication. +* Copyright 2012 Broad Institute, Inc. +* Notice of attribution: The GATK2 program was made available through the generosity of Medical and Population Genetics program at the Broad Institute, Inc. +* LICENSEE shall not use any trademark or trade name of BROAD, or any variation, adaptation, or abbreviation, of such marks or trade names, or any names of officers, faculty, students, employees, or agents of BROAD except as states above for attribution purposes. +* +* 4. INDEMNIFICATION +* LICENSEE shall indemnify, defend, and hold harmless BROAD, and their respective officers, faculty, students, employees, associated investigators and agents, and their respective successors, heirs and assigns, (Indemnitees), against any liability, damage, loss, or expense (including reasonable attorneys fees and expenses) incurred by or imposed upon any of the Indemnitees in connection with any claims, suits, actions, demands or judgments arising out of any theory of liability (including, without limitation, actions in the form of tort, warranty, or strict liability and regardless of whether such action has any factual basis) pursuant to any right or license granted under this Agreement. +* +* 5. NO REPRESENTATIONS OR WARRANTIES +* THE PROGRAM IS DELIVERED AS IS. BROAD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE PROGRAM OR THE COPYRIGHT, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. BROAD EXTENDS NO WARRANTIES OF ANY KIND AS TO PROGRAM CONFORMITY WITH WHATEVER USER MANUALS OR OTHER LITERATURE MAY BE ISSUED FROM TIME TO TIME. +* IN NO EVENT SHALL BROAD OR ITS RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AFFILIATED INVESTIGATORS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER BROAD SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. +* +* 6. ASSIGNMENT +* This Agreement is personal to LICENSEE and any rights or obligations assigned by LICENSEE without the prior written consent of BROAD shall be null and void. +* +* 7. MISCELLANEOUS +* 7.1 Export Control. LICENSEE gives assurance that it will comply with all United States export control laws and regulations controlling the export of the PROGRAM, including, without limitation, all Export Administration Regulations of the United States Department of Commerce. Among other things, these laws and regulations prohibit, or require a license for, the export of certain types of software to specified countries. +* 7.2 Termination. LICENSEE shall have the right to terminate this Agreement for any reason upon prior written notice to BROAD. If LICENSEE breaches any provision hereunder, and fails to cure such breach within thirty (30) days, BROAD may terminate this Agreement immediately. Upon termination, LICENSEE shall provide BROAD with written assurance that the original and all copies of the PROGRAM have been destroyed, except that, upon prior written authorization from BROAD, LICENSEE may retain a copy for archive purposes. +* 7.3 Survival. The following provisions shall survive the expiration or termination of this Agreement: Articles 1, 3, 4, 5 and Sections 2.2, 2.3, 7.3, and 7.4. +* 7.4 Notice. Any notices under this Agreement shall be in writing, shall specifically refer to this Agreement, and shall be sent by hand, recognized national overnight courier, confirmed facsimile transmission, confirmed electronic mail, or registered or certified mail, postage prepaid, return receipt requested. All notices under this Agreement shall be deemed effective upon receipt. +* 7.5 Amendment and Waiver; Entire Agreement. This Agreement may be amended, supplemented, or otherwise modified only by means of a written instrument signed by all parties. Any waiver of any rights or failure to act in a specific instance shall relate only to such instance and shall not be construed as an agreement to waive any rights or fail to act in any other instance, whether or not similar. This Agreement constitutes the entire agreement among the parties with respect to its subject matter and supersedes prior agreements or understandings between the parties relating to its subject matter. +* 7.6 Binding Effect; Headings. This Agreement shall be binding upon and inure to the benefit of the parties and their respective permitted successors and assigns. All headings are for convenience only and shall not affect the meaning of any provision of this Agreement. +* 7.7 Governing Law. This Agreement shall be construed, governed, interpreted and applied in accordance with the internal laws of the Commonwealth of Massachusetts, U.S.A., without regard to conflict of laws principles. +*/ + +package org.broadinstitute.sting.gatk.walkers.haplotypecaller; + +import net.sf.samtools.Cigar; +import net.sf.samtools.CigarElement; +import net.sf.samtools.CigarOperator; +import org.apache.commons.lang.ArrayUtils; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.sam.AlignmentUtils; +import org.jgrapht.graph.DefaultDirectedGraph; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: rpoplin + * Date: 1/31/13 + */ + +public class KBestPathsUnitTest { + @DataProvider(name = "BasicBubbleDataProvider") + public Object[][] makeBasicBubbleDataProvider() { + List tests = new ArrayList(); + for ( final int refBubbleLength : Arrays.asList(1, 5, 10) ) { + for ( final int altBubbleLength : Arrays.asList(1, 5, 10) ) { + tests.add(new Object[]{refBubbleLength, altBubbleLength}); + } + } + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "BasicBubbleDataProvider") + public void testBasicBubbleData(final int refBubbleLength, final int altBubbleLength) { + // Construct the assembly graph + DefaultDirectedGraph graph = new DefaultDirectedGraph(DeBruijnEdge.class); + final int KMER_LENGTH = 3; + final String preRef = "ATGG"; + final String postRef = new String(Utils.dupBytes((byte) 'A', KMER_LENGTH-1)) + "GGGGC"; + + DeBruijnVertex v = new DeBruijnVertex(preRef.getBytes(), KMER_LENGTH); + DeBruijnVertex v2Ref = new DeBruijnVertex(Utils.dupBytes((byte) 'A', refBubbleLength+KMER_LENGTH-1), KMER_LENGTH); + DeBruijnVertex v2Alt = new DeBruijnVertex(ArrayUtils.addAll(Utils.dupBytes((byte) 'A', altBubbleLength + KMER_LENGTH - 1 - 1), Utils.dupBytes((byte) 'T',1)), KMER_LENGTH); + DeBruijnVertex v3 = new DeBruijnVertex(postRef.getBytes(), KMER_LENGTH); + + graph.addVertex(v); + graph.addVertex(v2Ref); + graph.addVertex(v2Alt); + graph.addVertex(v3); + graph.addEdge(v, v2Ref, new DeBruijnEdge(true, 10)); + graph.addEdge(v2Ref, v3, new DeBruijnEdge(true, 10)); + graph.addEdge(v, v2Alt, new DeBruijnEdge(false, 5)); + graph.addEdge(v2Alt, v3, new DeBruijnEdge(false, 5)); + + // Construct the test path + KBestPaths.Path path = new KBestPaths.Path(v, graph); + path = new KBestPaths.Path(path, graph.getEdge(v, v2Alt)); + path = new KBestPaths.Path(path, graph.getEdge(v2Alt, v3)); + + // Construct the actual cigar string implied by the test path + Cigar expectedCigar = new Cigar(); + expectedCigar.add(new CigarElement(preRef.length(), CigarOperator.M)); + if( refBubbleLength > altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength - altBubbleLength, CigarOperator.D)); + expectedCigar.add(new CigarElement(altBubbleLength,CigarOperator.M)); + } else if ( refBubbleLength < altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength,CigarOperator.M)); + expectedCigar.add(new CigarElement(altBubbleLength - refBubbleLength,CigarOperator.I)); + } else { + expectedCigar.add(new CigarElement(refBubbleLength, CigarOperator.M)); + } + expectedCigar.add(new CigarElement(postRef.length() - (KMER_LENGTH - 1), CigarOperator.M)); + + Assert.assertEquals(path.calculateCigar().toString(), AlignmentUtils.consolidateCigar(expectedCigar).toString(), "Cigar string mismatch"); + } + + + @DataProvider(name = "TripleBubbleDataProvider") + public Object[][] makeTripleBubbleDataProvider() { + List tests = new ArrayList(); + for ( final int refBubbleLength : Arrays.asList(1, 5, 10) ) { + for ( final int altBubbleLength : Arrays.asList(1, 5, 10) ) { + for ( final boolean offRefBeginning : Arrays.asList(false) ) { + for ( final boolean offRefEnding : Arrays.asList(true, false) ) { + tests.add(new Object[]{refBubbleLength, altBubbleLength, offRefBeginning, offRefEnding}); + } + } + } + } + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "TripleBubbleDataProvider") + public void testTripleBubbleData(final int refBubbleLength, final int altBubbleLength, final boolean offRefBeginning, final boolean offRefEnding) { + // Construct the assembly graph + DefaultDirectedGraph graph = new DefaultDirectedGraph(DeBruijnEdge.class); + final int KMER_LENGTH = 3; + final String preAltOption = "ATCGATCGATCGATCGATCG"; + final String postAltOption = "CCCC"; + final String preRef = "ATGG"; + final String postRef = new String(Utils.dupBytes((byte) 'A', KMER_LENGTH-1)) + "GGCCG"; + final String midRef1 = new String(Utils.dupBytes((byte) 'A', KMER_LENGTH-1)) + "TTCCT"; + final String midRef2 = new String(Utils.dupBytes((byte) 'A', KMER_LENGTH-1)) + "CCCAAAAAAAAAAAA"; + + DeBruijnVertex preV = new DeBruijnVertex(preAltOption.getBytes(), KMER_LENGTH); + DeBruijnVertex v = new DeBruijnVertex(preRef.getBytes(), KMER_LENGTH); + DeBruijnVertex v2Ref = new DeBruijnVertex(Utils.dupBytes((byte) 'A', refBubbleLength+KMER_LENGTH-1), KMER_LENGTH); + DeBruijnVertex v2Alt = new DeBruijnVertex(ArrayUtils.addAll(Utils.dupBytes((byte) 'A', altBubbleLength + KMER_LENGTH - 1 - 1), Utils.dupBytes((byte) 'T',1)), KMER_LENGTH); + DeBruijnVertex v4Ref = new DeBruijnVertex(Utils.dupBytes((byte) 'C', refBubbleLength+KMER_LENGTH-1), KMER_LENGTH); + DeBruijnVertex v4Alt = new DeBruijnVertex(ArrayUtils.addAll(Utils.dupBytes((byte) 'C', altBubbleLength + KMER_LENGTH - 1 - 1), Utils.dupBytes((byte) 'T',1)), KMER_LENGTH); + DeBruijnVertex v6Ref = new DeBruijnVertex(Utils.dupBytes((byte) 'G', refBubbleLength+KMER_LENGTH-1), KMER_LENGTH); + DeBruijnVertex v6Alt = new DeBruijnVertex(ArrayUtils.addAll(Utils.dupBytes((byte) 'G', altBubbleLength + KMER_LENGTH - 1 - 1), Utils.dupBytes((byte) 'T',1)), KMER_LENGTH); + DeBruijnVertex v3 = new DeBruijnVertex(midRef1.getBytes(), KMER_LENGTH); + DeBruijnVertex v5 = new DeBruijnVertex(midRef2.getBytes(), KMER_LENGTH); + DeBruijnVertex v7 = new DeBruijnVertex(postRef.getBytes(), KMER_LENGTH); + DeBruijnVertex postV = new DeBruijnVertex(postAltOption.getBytes(), KMER_LENGTH); + + graph.addVertex(preV); + graph.addVertex(v); + graph.addVertex(v2Ref); + graph.addVertex(v2Alt); + graph.addVertex(v3); + graph.addVertex(v4Ref); + graph.addVertex(v4Alt); + graph.addVertex(v5); + graph.addVertex(v6Ref); + graph.addVertex(v6Alt); + graph.addVertex(v7); + graph.addVertex(postV); + graph.addEdge(preV, v, new DeBruijnEdge(false, 1)); + graph.addEdge(v, v2Ref, new DeBruijnEdge(true, 10)); + graph.addEdge(v2Ref, v3, new DeBruijnEdge(true, 10)); + graph.addEdge(v, v2Alt, new DeBruijnEdge(false, 5)); + graph.addEdge(v2Alt, v3, new DeBruijnEdge(false, 5)); + graph.addEdge(v3, v4Ref, new DeBruijnEdge(true, 10)); + graph.addEdge(v4Ref, v5, new DeBruijnEdge(true, 10)); + graph.addEdge(v3, v4Alt, new DeBruijnEdge(false, 5)); + graph.addEdge(v4Alt, v5, new DeBruijnEdge(false, 5)); + graph.addEdge(v5, v6Ref, new DeBruijnEdge(true, 11)); + graph.addEdge(v6Ref, v7, new DeBruijnEdge(true, 11)); + graph.addEdge(v5, v6Alt, new DeBruijnEdge(false, 55)); + graph.addEdge(v6Alt, v7, new DeBruijnEdge(false, 55)); + graph.addEdge(v7, postV, new DeBruijnEdge(false, 1)); + + // Construct the test path + KBestPaths.Path path = new KBestPaths.Path( (offRefBeginning ? preV : v), graph); + if( offRefBeginning ) { + path = new KBestPaths.Path(path, graph.getEdge(preV, v)); + } + path = new KBestPaths.Path(path, graph.getEdge(v, v2Alt)); + path = new KBestPaths.Path(path, graph.getEdge(v2Alt, v3)); + path = new KBestPaths.Path(path, graph.getEdge(v3, v4Ref)); + path = new KBestPaths.Path(path, graph.getEdge(v4Ref, v5)); + path = new KBestPaths.Path(path, graph.getEdge(v5, v6Alt)); + path = new KBestPaths.Path(path, graph.getEdge(v6Alt, v7)); + if( offRefEnding ) { + path = new KBestPaths.Path(path, graph.getEdge(v7,postV)); + } + + // Construct the actual cigar string implied by the test path + Cigar expectedCigar = new Cigar(); + if( offRefBeginning ) { + expectedCigar.add(new CigarElement(preAltOption.length(), CigarOperator.I)); + } + expectedCigar.add(new CigarElement(preRef.length() - ( offRefBeginning ? KMER_LENGTH - 1 : 0 ), CigarOperator.M)); + // first bubble + if( refBubbleLength > altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength - altBubbleLength, CigarOperator.D)); + expectedCigar.add(new CigarElement(altBubbleLength,CigarOperator.M)); + } else if ( refBubbleLength < altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength,CigarOperator.M)); + expectedCigar.add(new CigarElement(altBubbleLength - refBubbleLength,CigarOperator.I)); + } else { + expectedCigar.add(new CigarElement(refBubbleLength, CigarOperator.M)); + } + expectedCigar.add(new CigarElement(midRef1.length() - (KMER_LENGTH - 1), CigarOperator.M)); + // second bubble is ref path + expectedCigar.add(new CigarElement(refBubbleLength, CigarOperator.M)); + expectedCigar.add(new CigarElement(midRef2.length() - (KMER_LENGTH - 1), CigarOperator.M)); + // third bubble + if( refBubbleLength > altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength - altBubbleLength, CigarOperator.D)); + expectedCigar.add(new CigarElement(altBubbleLength,CigarOperator.M)); + } else if ( refBubbleLength < altBubbleLength ) { + expectedCigar.add(new CigarElement(refBubbleLength,CigarOperator.M)); + expectedCigar.add(new CigarElement(altBubbleLength - refBubbleLength,CigarOperator.I)); + } else { + expectedCigar.add(new CigarElement(refBubbleLength, CigarOperator.M)); + } + expectedCigar.add(new CigarElement(postRef.length() - (KMER_LENGTH - 1), CigarOperator.M)); + if( offRefEnding ) { + expectedCigar.add(new CigarElement(postAltOption.length() - (KMER_LENGTH - 1), CigarOperator.I)); + } + + Assert.assertEquals(path.calculateCigar().toString(), AlignmentUtils.consolidateCigar(expectedCigar).toString(), "Cigar string mismatch"); + } +} diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssemblerUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssemblerUnitTest.java index 5769a531e..24915d34b 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssemblerUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/haplotypecaller/SimpleDeBruijnAssemblerUnitTest.java @@ -78,7 +78,7 @@ public class SimpleDeBruijnAssemblerUnitTest extends BaseTest { } public DefaultDirectedGraph expectedGraph() { - DeBruijnVertex v = new DeBruijnVertex(sequence, 0); + DeBruijnVertex v = new DeBruijnVertex(sequence, KMER_LENGTH); DefaultDirectedGraph graph = new DefaultDirectedGraph(DeBruijnEdge.class); graph.addVertex(v); return graph; @@ -127,12 +127,12 @@ public class SimpleDeBruijnAssemblerUnitTest extends BaseTest { DefaultDirectedGraph graph = new DefaultDirectedGraph(DeBruijnEdge.class); DefaultDirectedGraph expectedGraph = new DefaultDirectedGraph(DeBruijnEdge.class); - DeBruijnVertex v = new DeBruijnVertex("ATGG".getBytes(), 0); - DeBruijnVertex v2 = new DeBruijnVertex("ATGGA".getBytes(), 0); - DeBruijnVertex v3 = new DeBruijnVertex("ATGGT".getBytes(), 0); - DeBruijnVertex v4 = new DeBruijnVertex("ATGGG".getBytes(), 0); - DeBruijnVertex v5 = new DeBruijnVertex("ATGGC".getBytes(), 0); - DeBruijnVertex v6 = new DeBruijnVertex("ATGGCCCCCC".getBytes(), 0); + DeBruijnVertex v = new DeBruijnVertex("ATGG".getBytes(), 1); + DeBruijnVertex v2 = new DeBruijnVertex("ATGGA".getBytes(), 1); + DeBruijnVertex v3 = new DeBruijnVertex("ATGGT".getBytes(), 1); + DeBruijnVertex v4 = new DeBruijnVertex("ATGGG".getBytes(), 1); + DeBruijnVertex v5 = new DeBruijnVertex("ATGGC".getBytes(), 1); + DeBruijnVertex v6 = new DeBruijnVertex("ATGGCCCCCC".getBytes(), 1); graph.addVertex(v); graph.addVertex(v2); @@ -192,12 +192,12 @@ public class SimpleDeBruijnAssemblerUnitTest extends BaseTest { DefaultDirectedGraph graph = new DefaultDirectedGraph(DeBruijnEdge.class); DefaultDirectedGraph expectedGraph = new DefaultDirectedGraph(DeBruijnEdge.class); - DeBruijnVertex v = new DeBruijnVertex("ATGG".getBytes(), 0); - DeBruijnVertex v2 = new DeBruijnVertex("ATGGA".getBytes(), 0); - DeBruijnVertex v3 = new DeBruijnVertex("ATGGT".getBytes(), 0); - DeBruijnVertex v4 = new DeBruijnVertex("ATGGG".getBytes(), 0); - DeBruijnVertex v5 = new DeBruijnVertex("ATGGC".getBytes(), 0); - DeBruijnVertex v6 = new DeBruijnVertex("ATGGCCCCCC".getBytes(), 0); + DeBruijnVertex v = new DeBruijnVertex("ATGG".getBytes(), 1); + DeBruijnVertex v2 = new DeBruijnVertex("ATGGA".getBytes(), 1); + DeBruijnVertex v3 = new DeBruijnVertex("ATGGT".getBytes(), 1); + DeBruijnVertex v4 = new DeBruijnVertex("ATGGG".getBytes(), 1); + DeBruijnVertex v5 = new DeBruijnVertex("ATGGC".getBytes(), 1); + DeBruijnVertex v6 = new DeBruijnVertex("ATGGCCCCCC".getBytes(), 1); graph.addVertex(v); graph.addVertex(v2); From 03df5e6ee6f30f18f87837029b01221afefc7729 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 1 Feb 2013 15:37:19 -0500 Subject: [PATCH 180/188] - Added more comprehensive tests for consensus creation to RR. Still need to add tests for I/D ops. - Added RR qual correctness tests (note that this is a case where we don't add code coverage but still need to test critical infrastructure). - Also added minor cleanup of BaseUtils --- .../reducereads/SlidingWindowUnitTest.java | 155 ++++++++++++++++-- .../broadinstitute/sting/utils/BaseUtils.java | 16 +- 2 files changed, 150 insertions(+), 21 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java index 91dfb94a9..ea3544351 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/compression/reducereads/SlidingWindowUnitTest.java @@ -48,6 +48,7 @@ package org.broadinstitute.sting.gatk.walkers.compression.reducereads; import net.sf.picard.reference.IndexedFastaSequenceFile; import net.sf.samtools.SAMFileHeader; +import org.apache.commons.lang.ArrayUtils; import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.UnvalidatingGenomeLoc; @@ -217,11 +218,13 @@ public class SlidingWindowUnitTest extends BaseTest { return count; } + ///////////////////////////////////////////////////////////////// //// This section tests the consensus creation functionality //// ///////////////////////////////////////////////////////////////// private static final int readLength = 100; + private static final int testRegionSize = 1000; private final List basicReads = new ArrayList(20); private IndexedFastaSequenceFile seq; private SAMFileHeader header; @@ -231,7 +234,6 @@ public class SlidingWindowUnitTest extends BaseTest { seq = new CachingIndexedFastaSequenceFile(new File(b37KGReference)); header = ArtificialSAMUtils.createArtificialSamHeader(seq.getSequenceDictionary()); - final int testRegionSize = 1000; final int readFrequency = 20; basicReads.clear(); @@ -239,7 +241,7 @@ public class SlidingWindowUnitTest extends BaseTest { final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "basicRead" + i, 0, globalStartPosition + i, readLength); read.setReadBases(Utils.dupBytes((byte) 'A', readLength)); read.setBaseQualities(Utils.dupBytes((byte)30, readLength)); - read.setMappingQuality((byte)30); + read.setMappingQuality(30); basicReads.add(read); } } @@ -248,7 +250,7 @@ public class SlidingWindowUnitTest extends BaseTest { public final int expectedNumberOfReads; public final List myReads = new ArrayList(20); - private ConsensusCreationTest(final List locs, final boolean readsShouldBeLowQuality, final int expectedNumberOfReads) { + private ConsensusCreationTest(final List locs, final boolean readsShouldBeLowQuality, final boolean variantBaseShouldBeLowQuality, final int expectedNumberOfReads) { this.expectedNumberOfReads = expectedNumberOfReads; // first, add the basic reads to the collection @@ -256,10 +258,10 @@ public class SlidingWindowUnitTest extends BaseTest { // then add the permuted reads for ( final GenomeLoc loc : locs ) - myReads.add(createVariantRead(loc, readsShouldBeLowQuality)); + myReads.add(createVariantRead(loc, readsShouldBeLowQuality, variantBaseShouldBeLowQuality)); } - private GATKSAMRecord createVariantRead(final GenomeLoc loc, final boolean baseShouldBeLowQuality) { + private GATKSAMRecord createVariantRead(final GenomeLoc loc, final boolean readShouldBeLowQuality, final boolean variantBaseShouldBeLowQuality) { final int startPos = loc.getStart() - 50; @@ -268,9 +270,12 @@ public class SlidingWindowUnitTest extends BaseTest { // create a mismatch bases[50] = 'C'; read.setReadBases(bases); - final byte qual = baseShouldBeLowQuality ? (byte)10 : (byte)30; - read.setBaseQualities(Utils.dupBytes(qual, readLength)); - read.setMappingQuality((byte)30); + final byte[] baseQuals = Utils.dupBytes((byte) 30, readLength); + if ( variantBaseShouldBeLowQuality ) + baseQuals[50] = (byte)10; + read.setBaseQualities(baseQuals); + final byte mappingQual = readShouldBeLowQuality ? (byte)10 : (byte)30; + read.setMappingQuality(mappingQual); return read; } } @@ -279,16 +284,36 @@ public class SlidingWindowUnitTest extends BaseTest { private static final GenomeLoc loc295 = new UnvalidatingGenomeLoc("1", 0, 1000295, 1000295); private static final GenomeLoc loc309 = new UnvalidatingGenomeLoc("1", 0, 1000309, 1000309); private static final GenomeLoc loc310 = new UnvalidatingGenomeLoc("1", 0, 1000310, 1000310); + private static final GenomeLoc loc1100 = new UnvalidatingGenomeLoc("1", 0, 1001100, 1001100); @DataProvider(name = "ConsensusCreation") public Object[][] createConsensusCreationTestData() { List tests = new ArrayList(); - tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(), false, 1)}); - tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290), false, 9)}); - tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc295), false, 10)}); - tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc309), false, 10)}); - tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc310), false, 11)}); + // test high quality reads and bases + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(), false, false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290), false, false, 9)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc295), false, false, 10)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc309), false, false, 10)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc310), false, false, 11)}); + + // test low quality reads + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(), true, false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290), true, false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc295), true, false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc309), true, false, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc310), true, false, 1)}); + + // test low quality bases + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(), false, true, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290), false, true, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc295), false, true, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc309), false, true, 1)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc290, loc310), false, true, 1)}); + + // test mixture + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc1100), true, false, 2)}); + tests.add(new Object[]{new ConsensusCreationTest(Arrays.asList(loc1100), false, true, 3)}); return tests.toArray(new Object[][]{}); } @@ -304,6 +329,110 @@ public class SlidingWindowUnitTest extends BaseTest { } + /////////////////////////////////////////////////////////// + //// This section tests the downsampling functionality //// + /////////////////////////////////////////////////////////// + + private class DSTest { + public final int dcov; + + private DSTest(final int dcov) { + this.dcov = dcov; + } + } + + @DataProvider(name = "Downsampling") + public Object[][] createDownsamplingTestData() { + List tests = new ArrayList(); + + for ( int i = 1; i < basicReads.size() + 10; i++ ) + tests.add(new Object[]{new DSTest(i)}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "Downsampling", enabled = true) + public void testDownsamplingTest(DSTest test) { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, 10, header, new GATKSAMReadGroupRecord("test"), 0, 0.05, 0.05, 20, 20, test.dcov, ReduceReads.DownsampleStrategy.Normal, false, 1, false); + final List result = slidingWindow.downsampleVariantRegion(basicReads); + + Assert.assertEquals(result.size(), Math.min(test.dcov, basicReads.size())); + } + + + ////////////////////////////////////////////////////////////// + //// This section tests the consensus base quals accuracy //// + ////////////////////////////////////////////////////////////// + + private class QualsTest { + public final List quals; + public final List myReads = new ArrayList(5); + + private QualsTest(final List quals) { + this.quals = quals; + for ( int i = 0; i < quals.size(); i++ ) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "basicRead" + i, 0, globalStartPosition, 1); + read.setReadBases(new byte[]{(byte)'A'}); + read.setBaseQualities(new byte[]{quals.get(i).byteValue()}); + read.setMappingQuality(30); + myReads.add(read); + } + } + } + + @DataProvider(name = "ConsensusQuals") + public Object[][] createConsensusQualsData() { + List tests = new ArrayList(); + + final int[] quals = new int[]{ 0, 5, 10, 15, 20, 30, 40, 50 }; + + for ( final int qual1 : quals ) { + for ( final int qual2 : quals ) { + for ( final int qual3 : quals ) { + tests.add(new Object[]{new QualsTest(Arrays.asList(qual1, qual2, qual3))}); + } + } + } + + return tests.toArray(new Object[][]{}); + } + + private static final byte minUsableConsensusQual = 10; + + @Test(dataProvider = "ConsensusQuals", enabled = true) + public void testConsensusQualsTest(QualsTest test) { + final SlidingWindow slidingWindow = new SlidingWindow("1", 0, 10, header, new GATKSAMReadGroupRecord("test"), 0, 0.05, 0.05, minUsableConsensusQual, 20, 100, ReduceReads.DownsampleStrategy.Normal, false, 1, false); + for ( final GATKSAMRecord read : test.myReads ) + slidingWindow.addRead(read); + final Pair, CompressionStash> result = slidingWindow.close(); + + Assert.assertEquals(result.getFirst().size(), 1); + final GATKSAMRecord read = result.getFirst().iterator().next(); + final int actualBaseQual = read.getReducedCount(0) * read.getBaseQualities()[0]; + final int expectedBaseQual = qualSum(test.quals); + Assert.assertEquals(actualBaseQual, expectedBaseQual); + } + + private static int qualSum(final List quals) { + int goodBases = 0; + int sum = 0; + for ( final int qual : quals ) { + if ( qual >= minUsableConsensusQual ) { + goodBases++; + sum += qual; + } + } + + // handle a low quality consensus + if ( sum == 0 ) { + for ( final int qual : quals ) { + goodBases++; + sum += qual; + } + } + + return sum - (sum % goodBases); + } diff --git a/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java index 61a558c09..46f8f2a84 100644 --- a/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/BaseUtils.java @@ -38,17 +38,17 @@ import java.util.Arrays; public class BaseUtils { public enum Base { - A ((byte)'A'), - C ((byte)'C'), - G ((byte)'G'), - T ((byte)'T'), - N ((byte)'N'), - D ((byte)'D'); + A ('A'), + C ('C'), + G ('G'), + T ('T'), + N ('N'), + D ('D'); public byte base; - private Base(final byte base) { - this.base = base; + private Base(final char base) { + this.base = (byte)base; } } From eb17230c2f293068792f72057112763cf7187f4a Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Fri, 1 Feb 2013 14:29:13 -0500 Subject: [PATCH 182/188] Update AWS access and private keys to the new GATK2LogUploader user -- Updated EncryptAWSKeys to write the key into the correct resources directory --- .../sting/gatk/phonehome/GATKRunReport.java | 4 ++-- .../phonehome/resources/GATK_AWS_access.key | Bin 256 -> 256 bytes .../phonehome/resources/GATK_AWS_secret.key | Bin 256 -> 256 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index 12e87f613..29251a5ae 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -73,8 +73,8 @@ import java.util.zip.GZIPOutputStream; * GATK run report database. */ public class GATKRunReport { - protected final static String AWS_ACCESS_KEY_MD5 = "c0f0afa1ff5ba41d9bf216cfcdbf26bf"; - protected final static String AWS_SECRET_KEY_MD5 = "db2f13b3a7c98ad24e28783733ec4a62"; + protected final static String AWS_ACCESS_KEY_MD5 = "43433e5488d60788042ed5de3dcf9b0a"; + protected final static String AWS_SECRET_KEY_MD5 = "0aa28b227ecacbdc9d2d5e8d82b10d32"; /** * The root file system directory where we keep common report data diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_access.key b/public/java/src/org/broadinstitute/sting/gatk/phonehome/resources/GATK_AWS_access.key index 45242c3cd4e342c95d6630421c2b950fe8e224d3..5b3e0c2ecfde37da2e3833cb48c8b6091077389a 100644 GIT binary patch literal 256 zcmV+b0ssCZ)s?=}0`w^+<0qS!+DM}|pdh>j1@V&k5>l{_|L=rQ{#|d%Q{rHhB+O)r6=owaRvqvpa3)+ z!B>N5s>o75BYAdysT&$AoCE*sWotupSnHe2n6!3{tZ_eyCe@o*w&0q7|bNf1A|!#Sf-siTB}$EC?6vh>0nWbFD9P zXEC+m*-V77gHao~nqfyJB)3xCitK-%djoj?aZq~KijEhQkV>ws27Q#_T)39BlzS+T z8_R=NzKpk9#dl1NlQSVt+-=9EfxiX}5Rb z8DygZ1zx4;d1WWDzVX{7=}(Tg%ImiBB^yg^N>7YDaKrq4^OW{Gh3X` zHBkxCQ?!iSxrmLJAahMkgp)oPdT0Z5Db~|1%%@xO1~AJZ@46$2)!r%6;%3~+(<&bE zGwj~P-hX;B!2}dRG5Zl<>bz)a6J!qzDB|_3i#wI{6&h#EL zNy%zD4$cZr3OHzad*T{?JVK|@Tkm)?rp1pN33JU-fi{b*XQH?g&z%d%(ha|KT`EjN zBSe){t0~(z%*aiOc6s(*c)DT0;m|PNz6Iq-NLK3b$Te4ViCd4fXKs%s(Pj` Date: Sat, 2 Feb 2013 15:05:13 -0500 Subject: [PATCH 183/188] Final cleanup and unit testing for GATKRunReport -- Bringing code up to document, style, and code coverage specs -- Move GATKRunReportUnitTest to private -- Fully expand GATKRunReportUnitTests to coverage writing and reading GATKRunReport to local disk, to standard out, to AWS. -- Move documentation URL from GATKRunReport to UserException -- Delete a few unused files from s3GATKReport -- Added capabilities to GATKRunReport to make testing easier -- Added capabilities to deserialize GATKRunReports from an InputStream --- .../sting/gatk/CommandLineExecutable.java | 2 +- .../arguments/GATKArgumentCollection.java | 5 +- .../sting/gatk/phonehome/GATKRunReport.java | 522 +++++++++++++----- .../phonehome/GATKRunReportException.java | 99 ++++ .../sting/utils/exceptions/UserException.java | 12 +- .../gatk/phonehome/GATKRunReportUnitTest.java | 52 -- 6 files changed, 500 insertions(+), 192 deletions(-) create mode 100644 public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReportException.java delete mode 100644 public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java diff --git a/public/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java b/public/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java index 1211d1982..111786e63 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java +++ b/public/java/src/org/broadinstitute/sting/gatk/CommandLineExecutable.java @@ -130,7 +130,7 @@ public abstract class CommandLineExecutable extends CommandLineProgram { getArgumentCollection().phoneHomeType == GATKRunReport.PhoneHomeOption.STDOUT ) { if ( getArgumentCollection().gatkKeyFile == null ) { throw new UserException("Running with the -et NO_ET or -et STDOUT option requires a GATK Key file. " + - "Please see " + GATKRunReport.PHONE_HOME_DOCS_URL + + "Please see " + UserException.PHONE_HOME_DOCS_URL + " for more information and instructions on how to obtain a key."); } else { diff --git a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index b4d6051d9..bcf3e7044 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/public/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.gatk.samples.PedigreeValidationType; import org.broadinstitute.sting.utils.QualityUtils; import org.broadinstitute.sting.utils.baq.BAQ; +import org.broadinstitute.sting.utils.exceptions.UserException; import java.io.File; import java.util.ArrayList; @@ -68,10 +69,10 @@ public class GATKArgumentCollection { // // -------------------------------------------------------------------------------------------------------------- - @Argument(fullName = "phone_home", shortName = "et", doc="What kind of GATK run report should we generate? STANDARD is the default, can be NO_ET so nothing is posted to the run repository. Please see " + GATKRunReport.PHONE_HOME_DOCS_URL + " for details.", required = false) + @Argument(fullName = "phone_home", shortName = "et", doc="What kind of GATK run report should we generate? STANDARD is the default, can be NO_ET so nothing is posted to the run repository. Please see " + UserException.PHONE_HOME_DOCS_URL + " for details.", required = false) public GATKRunReport.PhoneHomeOption phoneHomeType = GATKRunReport.PhoneHomeOption.STANDARD; - @Argument(fullName = "gatk_key", shortName = "K", doc="GATK Key file. Required if running with -et NO_ET. Please see " + GATKRunReport.PHONE_HOME_DOCS_URL + " for details.", required = false) + @Argument(fullName = "gatk_key", shortName = "K", doc="GATK Key file. Required if running with -et NO_ET. Please see " + UserException.PHONE_HOME_DOCS_URL + " for details.", required = false) public File gatkKeyFile = null; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index 29251a5ae..743136543 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -25,6 +25,8 @@ package org.broadinstitute.sting.gatk.phonehome; +import com.google.java.contract.Ensures; +import com.google.java.contract.Requires; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.broadinstitute.sting.gatk.CommandLineGATK; @@ -33,7 +35,6 @@ import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.crypt.CryptUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.io.IOUtils; import org.broadinstitute.sting.utils.io.Resource; import org.broadinstitute.sting.utils.threading.ThreadEfficiencyMonitor; @@ -43,99 +44,102 @@ import org.jets3t.service.impl.rest.httpclient.RestS3Service; import org.jets3t.service.model.S3Object; import org.jets3t.service.security.AWSCredentials; import org.simpleframework.xml.Element; -import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; -import org.simpleframework.xml.stream.Format; -import org.simpleframework.xml.stream.HyphenStyle; import java.io.*; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** - * @author depristo - * * A detailed description of a GATK run, and error if applicable. Simply create a GATKRunReport * with the constructor, providing the walker that was run and the fully instantiated GenomeAnalysisEngine * after the run finishes and the GATKRunReport will collect all of the report information * into this object. Call postReport to write out the report, as an XML document, to either STDOUT, * a file (in which case the output is gzipped), or with no arguments the report will be posted to the * GATK run report database. + * + * @author depristo + * @since 2010 */ public class GATKRunReport { + protected static final String REPORT_BUCKET_NAME = "GATK_Run_Reports"; + protected static final String TEST_REPORT_BUCKET_NAME = "GATK_Run_Reports_Test"; protected final static String AWS_ACCESS_KEY_MD5 = "43433e5488d60788042ed5de3dcf9b0a"; protected final static String AWS_SECRET_KEY_MD5 = "0aa28b227ecacbdc9d2d5e8d82b10d32"; + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH.mm.ss"); + + /** + * number of milliseconds before the S3 put operation is timed-out: + */ + private static final long S3_PUT_TIME_OUT = 10 * 1000; + /** * The root file system directory where we keep common report data */ - private static File REPORT_DIR = new File("/humgen/gsa-hpprojects/GATK/reports"); + private final static File REPORT_DIR = new File("/humgen/gsa-hpprojects/GATK/reports"); - private static final String REPORT_BUCKET_NAME = "GATK_Run_Reports"; /** * The full path to the direct where submitted (and uncharacterized) report files are written */ - private static File REPORT_SUBMIT_DIR = new File(REPORT_DIR.getAbsolutePath() + "/submitted"); + private final static File REPORT_SUBMIT_DIR = new File(REPORT_DIR.getAbsolutePath() + "/submitted"); /** * Full path to the sentinel file that controls whether reports are written out. If this file doesn't * exist, no long will be written */ - private static File REPORT_SENTINEL = new File(REPORT_DIR.getAbsolutePath() + "/ENABLE"); - - // number of milliseconds before the S3 put operation is timed-out: - private static final long S3PutTimeOut = 10 * 1000; - - public static final String PHONE_HOME_DOCS_URL = "http://gatkforums.broadinstitute.org/discussion/1250/what-is-phone-home-and-how-does-it-affect-me#latest"; + private final static File REPORT_SENTINEL = new File(REPORT_DIR.getAbsolutePath() + "/ENABLE"); /** * our log */ protected static final Logger logger = Logger.getLogger(GATKRunReport.class); + // ----------------------------------------------------------------- + // elements captured for the report + // ----------------------------------------------------------------- @Element(required = false, name = "id") - private final String id; + private String id; @Element(required = false, name = "exception") - private final ExceptionToXML mException; + private GATKRunReportException mException; - @Element(required = true, name = "start_time") + @Element(required = true, name = "start-time") private String startTime = "ND"; - @Element(required = true, name = "end_time") + @Element(required = true, name = "end-time") private String endTime; - @Element(required = true, name = "run_time") + @Element(required = true, name = "run-time") private long runTime = 0; - @Element(required = true, name = "walker_name") + @Element(required = true, name = "walker-name") private String walkerName; - @Element(required = true, name = "svn_version") + @Element(required = true, name = "svn-version") private String svnVersion; - @Element(required = true, name = "total_memory") + @Element(required = true, name = "total-memory") private long totalMemory; - @Element(required = true, name = "max_memory") + @Element(required = true, name = "max-memory") private long maxMemory; - @Element(required = true, name = "user_name") + @Element(required = true, name = "user-name") private String userName; - @Element(required = true, name = "host_name") + @Element(required = true, name = "host-name") private String hostName; @Element(required = true, name = "java") @@ -150,31 +154,75 @@ public class GATKRunReport { @Element(required = true, name = "tag") private String tag; - // ----------------------------------------------------------------- - // elements related to multi-threading and efficiency - // ----------------------------------------------------------------- - - @Element(required = true, name = "numThreads") + @Element(required = true, name = "num-threads") private int numThreads; - @Element(required = true, name = "percent_time_running") + @Element(required = true, name = "percent-time-running") private String percentTimeRunning; - @Element(required = true, name = "percent_time_waiting") + @Element(required = true, name = "percent-time-waiting") private String percentTimeWaiting; - @Element(required = true, name = "percent_time_blocking") + @Element(required = true, name = "percent-time-blocking") private String percentTimeBlocking; - @Element(required = true, name = "percent_time_waiting_for_io") + @Element(required = true, name = "percent-time-waiting-for-io") private String percentTimeWaitingForIO; + /** + * How should the GATK report its usage? + */ public enum PhoneHomeOption { /** Disable phone home */ NO_ET, /** Standard option. Writes to local repository if it can be found, or S3 otherwise */ STANDARD, + /** Forces the report to go to S3 */ + AWS, /** Force output to STDOUT. For debugging only */ STDOUT } - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH.mm.ss"); + /** + * To allow us to deserial reports from XML + */ + private GATKRunReport() { } + + /** + * Read a GATKRunReport from the serialized XML representation in String reportAsXML + * @param stream an input stream containing a serialized XML report + * @return a reconstituted GATKRunReport from reportAsXML + * @throws Exception if parsing fails for any reason + */ + @Ensures("result != null") + protected static GATKRunReport deserializeReport(final InputStream stream) throws Exception { + final Serializer serializer = new Persister(); + return serializer.read(GATKRunReport.class, stream); + } + + /** + * Create a new GATKRunReport from a report on S3 + * + * Assumes that s3Object has already been written to S3, and this function merely + * fetches it from S3 and deserializes it. The access keys must have permission to + * GetObject from S3. + * + * @param downloaderAccessKey AWS access key with permission to GetObject from bucketName + * @param downloaderSecretKey AWS secret key with permission to GetObject from bucketName + * @param bucketName the name of the bucket holding the report + * @param s3Object the s3Object we wrote to S3 in bucketName that we want to get back and decode + * @return a deserialized report derived from s3://bucketName/s3Object.getName() + * @throws Exception + */ + @Ensures("result != null") + protected static GATKRunReport deserializeReport(final String downloaderAccessKey, + final String downloaderSecretKey, + final String bucketName, + final S3Object s3Object) throws Exception { + final S3Service s3Service = initializeAWSService(downloaderAccessKey, downloaderSecretKey); + + // Retrieve the whole data object we created previously + final S3Object objectComplete = s3Service.getObject(bucketName, s3Object.getName()); + + // Read the data from the object's DataInputStream using a loop, and print it out. + return deserializeReport(new GZIPInputStream(objectComplete.getDataInputStream())); + } /** * Create a new RunReport and population all of the fields with values from the walker and engine @@ -196,9 +244,9 @@ public class GATKRunReport { // runtime performance metrics Date end = new java.util.Date(); - endTime = dateFormat.format(end); + endTime = DATE_FORMAT.format(end); if ( engine.getStartTime() != null ) { // made it this far during initialization - startTime = dateFormat.format(engine.getStartTime()); + startTime = DATE_FORMAT.format(engine.getStartTime()); runTime = (end.getTime() - engine.getStartTime().getTime()) / 1000L; // difference in seconds } @@ -224,7 +272,7 @@ public class GATKRunReport { machine = Utils.join("-", Arrays.asList(System.getProperty("os.name"), System.getProperty("os.arch"))); // if there was an exception, capture it - this.mException = e == null ? null : new ExceptionToXML(e); + this.mException = e == null ? null : new GATKRunReportException(e); numThreads = engine.getTotalNumberOfThreads(); percentTimeRunning = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.USER_CPU); @@ -233,6 +281,11 @@ public class GATKRunReport { percentTimeWaitingForIO = getThreadEfficiencyPercent(engine, ThreadEfficiencyMonitor.State.WAITING_FOR_IO); } + /** + * Get the random alpha-numeric ID of this GATKRunReport + * @return a non-null string ID + */ + @Ensures("result != null") public String getID() { return id; } @@ -244,62 +297,113 @@ public class GATKRunReport { * @param state the state whose occupancy we wish to know * @return a string representation of the percent occupancy of state, or NA is not possible */ + @Requires({"engine != null", "state != null"}) + @Ensures("result != null") private String getThreadEfficiencyPercent(final GenomeAnalysisEngine engine, final ThreadEfficiencyMonitor.State state) { final ThreadEfficiencyMonitor tem = engine.getThreadEfficiencyMonitor(); return tem == null ? "NA" : String.format("%.2f", tem.getStatePercent(state)); } + /** + * Get a filename (no path) appropriate for this report + * + * @return a non-null string filename + */ + @Ensures("result != null") + protected String getReportFileName() { + return getID() + ".report.xml.gz"; + } + + // --------------------------------------------------------------------------- + // + // Main public interface method for posting reports + // + // --------------------------------------------------------------------------- + + /** + * Post this GATK report to the destination implied by the PhoneHomeOption type + * + * Guaranteed to never throw an exception (exception noted below) and to return + * with a reasonable (~10 seconds) time regardless of successful writing of the report. + * + * @throws IllegalArgumentException if type == null + * @param type the type of phoning home we want to do + * @return true if a report was successfully written, false otherwise + */ + public boolean postReport(final PhoneHomeOption type) { + if ( type == null ) throw new IllegalArgumentException("type cannot be null"); - public void postReport(PhoneHomeOption type) { logger.debug("Posting report of type " + type); switch (type) { case NO_ET: // don't do anything - break; + return false; case STANDARD: - if ( repositoryIsOnline() ) { - postReportToLocalDisk(REPORT_SUBMIT_DIR); + case AWS: + if ( type == PhoneHomeOption.STANDARD && repositoryIsOnline() ) { + return postReportToLocalDisk(getLocalReportFullPath()) != null; } else { - postReportToAWSS3(); + wentToAWS = true; + return postReportToAWSS3() != null; } - break; case STDOUT: - postReportToStream(System.out); - break; + return postReportToStream(System.out); default: exceptDuringRunReport("BUG: unexpected PhoneHomeOption "); - break; + return false; } } + // --------------------------------------------------------------------------- + // + // Code for sending reports to local files + // + // --------------------------------------------------------------------------- + /** * Write an XML representation of this report to the stream, throwing a StingException if the marshalling * fails for any reason. * - * @param stream + * @param stream an output stream to write the report to */ - private void postReportToStream(OutputStream stream) { - Serializer serializer = new Persister(new Format(new HyphenStyle())); + @Requires("stream != null") + protected boolean postReportToStream(final OutputStream stream) { + final Serializer serializer = new Persister(); try { serializer.write(this, stream); - //throw new StingException("test"); + return true; } catch (Exception e) { - throw new ReviewedStingException("Failed to marshal the data to the file " + stream, e); + return false; } } - private final String getKey() { - return getID() + ".report.xml.gz"; + /** + * Get the full path as a file where we'll write this report to local disl + * @return a non-null File + */ + @Ensures("result != null") + protected File getLocalReportFullPath() { + return new File(REPORT_SUBMIT_DIR, getReportFileName()); } + /** + * Is the local GATKRunReport repository available for writing reports? + * + * @return true if and only if the common run report repository is available and online to receive reports + */ + private boolean repositoryIsOnline() { + return REPORT_SENTINEL.exists(); + } + + /** * Main entry point to writing reports to disk. Posts the XML report to the common GATK run report repository. * If this process fails for any reason, all exceptions are handled and this routine merely prints a warning. * That is, postReport() is guarenteed not to fail for any reason. + * + * @return the path where the file was written, or null if any failure occurred */ - private File postReportToLocalDisk(File rootDir) { - final String filename = getKey(); - final File destination = new File(rootDir, filename); - + @Requires("destination != null") + private File postReportToLocalDisk(final File destination) { try { final BufferedOutputStream out = new BufferedOutputStream( new GZIPOutputStream( @@ -316,18 +420,38 @@ public class GATKRunReport { } } + // --------------------------------------------------------------------------- + // + // Code for sending reports to s3 + // + // --------------------------------------------------------------------------- + + /** + * Get the name of the S3 bucket where we should upload this report + * + * @return the string name of the s3 bucket + */ + @Ensures("result != null") + protected String getS3ReportBucket() { + return s3ReportBucket; + } + /** * Decrypts encrypted AWS key from encryptedKeySource * @param encryptedKeySource a file containing an encrypted AWS key * @return a decrypted AWS key as a String */ + @Ensures("result != null") public static String decryptAWSKey(final File encryptedKeySource) throws FileNotFoundException { + if ( encryptedKeySource == null ) throw new IllegalArgumentException("encryptedKeySource cannot be null"); return decryptAWSKey(new FileInputStream(encryptedKeySource)); } /** * @see #decryptAWSKey(java.io.File) but with input from an inputstream */ + @Requires("encryptedKeySource != null") + @Ensures("result != null") private static String decryptAWSKey(final InputStream encryptedKeySource) { final PublicKey key = CryptUtils.loadGATKDistributedPublicKey(); final byte[] fromDisk = IOUtils.readStreamIntoByteArray(encryptedKeySource); @@ -340,6 +464,8 @@ public class GATKRunReport { * @param name the name of the file containing the needed AWS key * @return a non-null GATK */ + @Requires("name != null") + @Ensures("result != null") private static String getAWSKey(final String name) { final Resource resource = new Resource(name, GATKRunReport.class); return decryptAWSKey(resource.getResourceContentsAsStream()); @@ -349,7 +475,8 @@ public class GATKRunReport { * Get the AWS access key for the GATK user * @return a non-null AWS access key for the GATK user */ - protected static String getAWSAccessKey() { + @Ensures("result != null") + protected static String getAWSUploadAccessKey() { return getAWSKey("resources/GATK_AWS_access.key"); } @@ -357,7 +484,8 @@ public class GATKRunReport { * Get the AWS secret key for the GATK user * @return a non-null AWS secret key for the GATK user */ - protected static String getAWSSecretKey() { + @Ensures("result != null") + protected static String getAWSUploadSecretKey() { return getAWSKey("resources/GATK_AWS_secret.key"); } @@ -368,8 +496,8 @@ public class GATKRunReport { */ public static void checkAWSAreValid() { try { - final String accessKeyMD5 = Utils.calcMD5(getAWSAccessKey()); - final String secretKeyMD5 = Utils.calcMD5(getAWSSecretKey()); + final String accessKeyMD5 = Utils.calcMD5(getAWSUploadAccessKey()); + final String secretKeyMD5 = Utils.calcMD5(getAWSUploadSecretKey()); if ( ! AWS_ACCESS_KEY_MD5.equals(accessKeyMD5) ) { throw new ReviewedStingException("Invalid AWS access key found, expected MD5 " + AWS_ACCESS_KEY_MD5 + " but got " + accessKeyMD5); @@ -383,43 +511,77 @@ public class GATKRunReport { } } + /** + * Get an initialized S3Service for use in communicating with AWS/s3 + * + * @param awsAccessKey our AWS access key to use + * @param awsSecretKey our AWS secret key to use + * @return an initialized S3Service object that can be immediately used to interact with S3 + * @throws S3ServiceException + */ + @Requires({"awsAccessKey != null", "awsSecretKey != null"}) + @Ensures("result != null") + protected static S3Service initializeAWSService(final String awsAccessKey, final String awsSecretKey) throws S3ServiceException { + // To communicate with S3, create a class that implements an S3Service. We will use the REST/HTTP + // implementation based on HttpClient, as this is the most robust implementation provided with JetS3t. + final AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey); + return new RestS3Service(awsCredentials); + } + + /** + * A runnable that pushes this GATKReport up to s3. + * + * Should be run in a separate thread so we can time it out if something is taking too long + */ private class S3PutRunnable implements Runnable { + /** Was the upload operation successful? */ + public final AtomicBoolean isSuccess; + /** The name of this report */ + private final String filename; + /** The contents of this report */ + private final byte[] contents; - public AtomicBoolean isSuccess; - private final String key; - private final byte[] report; - + /** The s3Object that we created to upload, or null if it failed */ public S3Object s3Object; - public String errorMsg; + /** The error message, if one occurred, or null if none did */ + public String errorMsg = null; + /** The error that occurred, if one did, or null if none did */ public Throwable errorThrow; - public S3PutRunnable(String key, byte[] report){ - isSuccess = new AtomicBoolean(); - this.key = key; - this.report = report; + @Requires({"filename != null", "contents != null"}) + public S3PutRunnable(final String filename, final byte[] contents){ + this.isSuccess = new AtomicBoolean(); + this.filename = filename; + this.contents = contents; } public void run() { try { - // Your Amazon Web Services (AWS) login credentials are required to manage S3 accounts. These credentials - // are stored in an AWSCredentials object: + switch ( awsMode ) { + case FAIL_WITH_EXCEPTION: + throw new IllegalStateException("We are throwing an exception for testing purposes"); + case TIMEOUT: + try { + Thread.sleep(S3_PUT_TIME_OUT * 100); + } catch ( InterruptedException e ) { + // supposed to be empty + } + break; + case NORMAL: + // IAM GATK user credentials -- only right is to PutObject into GATK_Run_Report bucket + final S3Service s3Service = initializeAWSService(getAWSUploadAccessKey(), getAWSUploadSecretKey()); - // IAM GATK user credentials -- only right is to PutObject into GATK_Run_Report bucket - final String awsAccessKey = getAWSAccessKey(); // GATK AWS user - final String awsSecretKey = getAWSSecretKey(); // GATK AWS user - final AWSCredentials awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey); - - // To communicate with S3, create a class that implements an S3Service. We will use the REST/HTTP - // implementation based on HttpClient, as this is the most robust implementation provided with JetS3t. - final S3Service s3Service = new RestS3Service(awsCredentials); - - // Create an S3Object based on a file, with Content-Length set automatically and - // Content-Type set based on the file's extension (using the Mimetypes utility class) - final S3Object fileObject = new S3Object(key, report); - //logger.info("Created S3Object" + fileObject); - //logger.info("Uploading " + localFile + " to AWS bucket"); - s3Object = s3Service.putObject(REPORT_BUCKET_NAME, fileObject); - isSuccess.set(true); + // Create an S3Object based on a file, with Content-Length set automatically and + // Content-Type set based on the file's extension (using the Mimetypes utility class) + final S3Object fileObject = new S3Object(filename, contents); + //logger.info("Created S3Object" + fileObject); + //logger.info("Uploading " + localFile + " to AWS bucket"); + s3Object = s3Service.putObject(getS3ReportBucket(), fileObject); + isSuccess.set(true); + break; + default: + throw new IllegalStateException("Unexpected AWS exception"); + } } catch ( S3ServiceException e ) { setException("S3 exception occurred", e); } catch ( NoSuchAlgorithmException e ) { @@ -429,17 +591,29 @@ public class GATKRunReport { } } - private void setException(String msg, Throwable e){ + /** + * Set the error message and thrown exception, if one did occurred + * + * @param msg the error message + * @param e the exception that occurred + */ + private void setException(final String msg, final Throwable e){ errorMsg=msg; errorThrow=e; } } - private void postReportToAWSS3() { + /** + * Post this GATK report to the AWS s3 GATK_Run_Report log + * + * @return the s3Object pointing to our pushed report, or null if we failed to push + */ + protected S3Object postReportToAWSS3() { // modifying example code from http://jets3t.s3.amazonaws.com/toolkit/code-samples.html this.hostName = Utils.resolveHostname(); // we want to fill in the host name - final String key = getKey(); + final String key = getReportFileName(); logger.debug("Generating GATK report to AWS S3 with key " + key); + try { // create an byte output stream so we can capture the output as a byte[] final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(8096); @@ -449,17 +623,17 @@ public class GATKRunReport { final byte[] report = byteStream.toByteArray(); // stop us from printing the annoying, and meaningless, mime types warning - Logger mimeTypeLogger = Logger.getLogger(org.jets3t.service.utils.Mimetypes.class); + final Logger mimeTypeLogger = Logger.getLogger(org.jets3t.service.utils.Mimetypes.class); mimeTypeLogger.setLevel(Level.FATAL); // Set the S3 upload on its own thread with timeout: - S3PutRunnable s3run = new S3PutRunnable(key,report); - Thread s3thread = new Thread(s3run); + final S3PutRunnable s3run = new S3PutRunnable(key,report); + final Thread s3thread = new Thread(s3run); s3thread.setDaemon(true); s3thread.setName("S3Put-Thread"); s3thread.start(); - s3thread.join(S3PutTimeOut); + s3thread.join(S3_PUT_TIME_OUT); if(s3thread.isAlive()){ s3thread.interrupt(); @@ -467,6 +641,7 @@ public class GATKRunReport { } else if(s3run.isSuccess.get()) { logger.info("Uploaded run statistics report to AWS S3"); logger.debug("Uploaded to AWS: " + s3run.s3Object); + return s3run.s3Object; } else { if((s3run.errorMsg != null) && (s3run.errorThrow != null)){ exceptDuringRunReport(s3run.errorMsg,s3run.errorThrow); @@ -479,57 +654,138 @@ public class GATKRunReport { } catch ( InterruptedException e) { exceptDuringRunReport("Run statistics report upload interrupted", e); } + + return null; } + /** + * Note that an exception occurred during creating or writing this report + * @param msg the message to print + * @param e the exception that occurred + */ private void exceptDuringRunReport(String msg, Throwable e) { logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***]. Message is: " + msg + ". Error message is: " + e.getMessage()); - //e.printStackTrace(); } + /** + * Note that an exception occurred during creating or writing this report + * @param msg the message to print + */ private void exceptDuringRunReport(String msg) { logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***]. Message is " + msg); } + // --------------------------------------------------------------------------- + // + // Equals and hashcode -- purely for comparing reports for testing + // + // --------------------------------------------------------------------------- + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GATKRunReport that = (GATKRunReport) o; + + if (maxMemory != that.maxMemory) return false; + if (nIterations != that.nIterations) return false; + if (numThreads != that.numThreads) return false; + if (runTime != that.runTime) return false; + if (totalMemory != that.totalMemory) return false; + if (endTime != null ? !endTime.equals(that.endTime) : that.endTime != null) return false; + if (hostName != null ? !hostName.equals(that.hostName) : that.hostName != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (javaVersion != null ? !javaVersion.equals(that.javaVersion) : that.javaVersion != null) return false; + if (mException != null ? !mException.equals(that.mException) : that.mException != null) return false; + if (machine != null ? !machine.equals(that.machine) : that.machine != null) return false; + if (percentTimeBlocking != null ? !percentTimeBlocking.equals(that.percentTimeBlocking) : that.percentTimeBlocking != null) + return false; + if (percentTimeRunning != null ? !percentTimeRunning.equals(that.percentTimeRunning) : that.percentTimeRunning != null) + return false; + if (percentTimeWaiting != null ? !percentTimeWaiting.equals(that.percentTimeWaiting) : that.percentTimeWaiting != null) + return false; + if (percentTimeWaitingForIO != null ? !percentTimeWaitingForIO.equals(that.percentTimeWaitingForIO) : that.percentTimeWaitingForIO != null) + return false; + if (startTime != null ? !startTime.equals(that.startTime) : that.startTime != null) return false; + if (svnVersion != null ? !svnVersion.equals(that.svnVersion) : that.svnVersion != null) return false; + if (tag != null ? !tag.equals(that.tag) : that.tag != null) return false; + if (userName != null ? !userName.equals(that.userName) : that.userName != null) return false; + if (walkerName != null ? !walkerName.equals(that.walkerName) : that.walkerName != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (mException != null ? mException.hashCode() : 0); + result = 31 * result + (startTime != null ? startTime.hashCode() : 0); + result = 31 * result + (endTime != null ? endTime.hashCode() : 0); + result = 31 * result + (int) (runTime ^ (runTime >>> 32)); + result = 31 * result + (walkerName != null ? walkerName.hashCode() : 0); + result = 31 * result + (svnVersion != null ? svnVersion.hashCode() : 0); + result = 31 * result + (int) (totalMemory ^ (totalMemory >>> 32)); + result = 31 * result + (int) (maxMemory ^ (maxMemory >>> 32)); + result = 31 * result + (userName != null ? userName.hashCode() : 0); + result = 31 * result + (hostName != null ? hostName.hashCode() : 0); + result = 31 * result + (javaVersion != null ? javaVersion.hashCode() : 0); + result = 31 * result + (machine != null ? machine.hashCode() : 0); + result = 31 * result + (int) (nIterations ^ (nIterations >>> 32)); + result = 31 * result + (tag != null ? tag.hashCode() : 0); + result = 31 * result + numThreads; + result = 31 * result + (percentTimeRunning != null ? percentTimeRunning.hashCode() : 0); + result = 31 * result + (percentTimeWaiting != null ? percentTimeWaiting.hashCode() : 0); + result = 31 * result + (percentTimeBlocking != null ? percentTimeBlocking.hashCode() : 0); + result = 31 * result + (percentTimeWaitingForIO != null ? percentTimeWaitingForIO.hashCode() : 0); + return result; + } + + // --------------------------------------------------------------------------- + // + // Code specifically for testing the GATKRunReport + // + // --------------------------------------------------------------------------- /** - * Returns true if and only if the common run report repository is available and online to receive reports - * - * @return + * Enum specifying how the S3 uploader should behave. Must be normal by default. Purely for testing purposes */ - private boolean repositoryIsOnline() { - return REPORT_SENTINEL.exists(); + protected enum AWSMode { + NORMAL, // write normally to AWS + FAIL_WITH_EXCEPTION, // artificially fail during writing + TIMEOUT // sleep, so we time out + } + /** Our AWS mode */ + private AWSMode awsMode = AWSMode.NORMAL; + /** The bucket were we send the GATK report on AWS/s3 */ + private String s3ReportBucket = REPORT_BUCKET_NAME; + /** Did we send the report to AWS? */ + private boolean wentToAWS = false; + + /** + * Send the report to the AWS test bucket -- for testing only + */ + protected void sendAWSToTestBucket() { + s3ReportBucket = TEST_REPORT_BUCKET_NAME; } /** - * A helper class for formatting in XML the throwable chain starting at e. + * Has the report been written to AWS? + * + * Does not imply anything about the success of the send, just that it was attempted + * + * @return true if the report has been sent to AWS, false otherwise */ - private class ExceptionToXML { - @Element(required = false, name = "message") - String message = null; + protected boolean wentToAWS() { + return wentToAWS; + } - @ElementList(required = false, name = "stacktrace") - final List stackTrace = new ArrayList(); - - @Element(required = false, name = "cause") - ExceptionToXML cause = null; - - @Element(required = false, name = "is-user-exception") - Boolean isUserException; - - @Element(required = false, name = "exception-class") - Class exceptionClass; - - public ExceptionToXML(Throwable e) { - message = e.getMessage(); - exceptionClass = e.getClass(); - isUserException = e instanceof UserException; - for (StackTraceElement element : e.getStackTrace()) { - stackTrace.add(element.toString()); - } - - if ( e.getCause() != null ) { - cause = new ExceptionToXML(e.getCause()); - } - } + /** + * Purely for testing purposes. Tells the AWS uploader whether to actually upload or simulate errors + * @param mode what we want to do + */ + @Requires("mode != null") + protected void setAwsMode(final AWSMode mode) { + this.awsMode = mode; } } diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReportException.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReportException.java new file mode 100644 index 000000000..431d99867 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReportException.java @@ -0,0 +1,99 @@ +/* +* 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.phonehome; + +import org.broadinstitute.sting.utils.exceptions.UserException; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; + +import java.util.ArrayList; +import java.util.List; + +/** + * A helper class for formatting in XML the throwable chain starting at e. + */ +class GATKRunReportException { + @Element(required = false, name = "message") + String message = null; + + @ElementList(required = false, name = "stacktrace") + final List stackTrace = new ArrayList(); + + @Element(required = false, name = "cause") + GATKRunReportException cause = null; + + @Element(required = false, name = "is-user-exception") + Boolean isUserException; + + @Element(required = false, name = "exception-class") + Class exceptionClass; + + /** + * Allow us to deserialize from XML + */ + public GATKRunReportException() { } + + public GATKRunReportException(Throwable e) { + message = e.getMessage(); + exceptionClass = e.getClass(); + isUserException = e instanceof UserException; + for (StackTraceElement element : e.getStackTrace()) { + stackTrace.add(element.toString()); + } + + if ( e.getCause() != null ) { + cause = new GATKRunReportException(e.getCause()); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GATKRunReportException that = (GATKRunReportException) o; + + if (cause != null ? !cause.equals(that.cause) : that.cause != null) return false; + if (exceptionClass != null ? !exceptionClass.equals(that.exceptionClass) : that.exceptionClass != null) + return false; + if (isUserException != null ? !isUserException.equals(that.isUserException) : that.isUserException != null) + return false; + if (message != null ? !message.equals(that.message) : that.message != null) return false; + if (stackTrace != null ? !stackTrace.equals(that.stackTrace) : that.stackTrace != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = message != null ? message.hashCode() : 0; + result = 31 * result + (stackTrace != null ? stackTrace.hashCode() : 0); + result = 31 * result + (cause != null ? cause.hashCode() : 0); + result = 31 * result + (isUserException != null ? isUserException.hashCode() : 0); + result = 31 * result + (exceptionClass != null ? exceptionClass.hashCode() : 0); + return result; + } +} diff --git a/public/java/src/org/broadinstitute/sting/utils/exceptions/UserException.java b/public/java/src/org/broadinstitute/sting/utils/exceptions/UserException.java index 268ac6ca1..08d5882b1 100644 --- a/public/java/src/org/broadinstitute/sting/utils/exceptions/UserException.java +++ b/public/java/src/org/broadinstitute/sting/utils/exceptions/UserException.java @@ -28,7 +28,6 @@ package org.broadinstitute.sting.utils.exceptions; import net.sf.samtools.SAMFileHeader; import net.sf.samtools.SAMRecord; import net.sf.samtools.SAMSequenceDictionary; -import org.broadinstitute.sting.gatk.phonehome.GATKRunReport; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.help.HelpConstants; @@ -50,6 +49,11 @@ import java.io.File; groupName = "User exceptions", summary = "Exceptions caused by incorrect user behavior, such as bad files, bad arguments, etc." ) public class UserException extends ReviewedStingException { + /** + * The URL where people can get help messages. Printed when an error occurs + */ + public static final String PHONE_HOME_DOCS_URL = "http://gatkforums.broadinstitute.org/discussion/1250/what-is-phone-home-and-how-does-it-affect-me#latest"; + public UserException(String msg) { super(msg); } public UserException(String msg, Throwable e) { super(msg, e); } private UserException(Throwable e) { super("", e); } // cannot be called, private access @@ -407,7 +411,7 @@ public class UserException extends ReviewedStingException { public UnreadableKeyException ( File f, Exception e ) { super(String.format("Key file %s cannot be read (possibly the key file is corrupt?). Error was: %s. " + "Please see %s for help.", - f.getAbsolutePath(), getMessage(e), GATKRunReport.PHONE_HOME_DOCS_URL)); + f.getAbsolutePath(), getMessage(e), PHONE_HOME_DOCS_URL)); } public UnreadableKeyException ( String message, Exception e ) { @@ -417,7 +421,7 @@ public class UserException extends ReviewedStingException { public UnreadableKeyException ( String message ) { super(String.format("Key file cannot be read (possibly the key file is corrupt?): %s. " + "Please see %s for help.", - message, GATKRunReport.PHONE_HOME_DOCS_URL)); + message, PHONE_HOME_DOCS_URL)); } } @@ -426,7 +430,7 @@ public class UserException extends ReviewedStingException { super(String.format("The signature in key file %s failed cryptographic verification. " + "If this key was valid in the past, it's likely been revoked. " + "Please see %s for help.", - f.getAbsolutePath(), GATKRunReport.PHONE_HOME_DOCS_URL)); + f.getAbsolutePath(), PHONE_HOME_DOCS_URL)); } } } diff --git a/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java deleted file mode 100644 index be2065b17..000000000 --- a/public/java/test/org/broadinstitute/sting/gatk/phonehome/GATKRunReportUnitTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -* 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.phonehome; - -import junit.framework.Assert; -import org.broadinstitute.sting.BaseTest; -import org.broadinstitute.sting.utils.Utils; -import org.testng.annotations.Test; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class GATKRunReportUnitTest extends BaseTest { - @Test - public void testAccessKey() throws Exception { - testAWSKey(GATKRunReport.getAWSAccessKey(), GATKRunReport.AWS_ACCESS_KEY_MD5); - } - - @Test - public void testSecretKey() throws Exception { - testAWSKey(GATKRunReport.getAWSSecretKey(), GATKRunReport.AWS_SECRET_KEY_MD5); - } - - private void testAWSKey(final String accessKey, final String expectedMD5) throws Exception { - Assert.assertNotNull(accessKey, "AccessKey should not be null"); - final String actualmd5 = Utils.calcMD5(accessKey); - Assert.assertEquals(actualmd5, expectedMD5); - } -} From 8d087805826a13a7f232c800a9eca21b59790769 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 2 Feb 2013 19:24:31 -0500 Subject: [PATCH 184/188] GATKRunReport now tracks the errorMessage and errorThrown during post for later analysis -- This is primarily useful in the unit tests, as I now print out additional information on why a test might have failed, if it in fact did. --- .../sting/gatk/phonehome/GATKRunReport.java | 91 +++++++++++++------ 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java index 743136543..277ffc082 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java +++ b/public/java/src/org/broadinstitute/sting/gatk/phonehome/GATKRunReport.java @@ -165,6 +165,11 @@ public class GATKRunReport { @Element(required = true, name = "percent-time-waiting-for-io") private String percentTimeWaitingForIO; + /** The error message, if one occurred, or null if none did */ + public String errorMessage = null; + /** The error that occurred, if one did, or null if none did */ + public Throwable errorThrown = null; + /** * How should the GATK report its usage? */ @@ -542,11 +547,7 @@ public class GATKRunReport { private final byte[] contents; /** The s3Object that we created to upload, or null if it failed */ - public S3Object s3Object; - /** The error message, if one occurred, or null if none did */ - public String errorMsg = null; - /** The error that occurred, if one did, or null if none did */ - public Throwable errorThrow; + public S3Object s3Object = null; @Requires({"filename != null", "contents != null"}) public S3PutRunnable(final String filename, final byte[] contents){ @@ -583,24 +584,15 @@ public class GATKRunReport { throw new IllegalStateException("Unexpected AWS exception"); } } catch ( S3ServiceException e ) { - setException("S3 exception occurred", e); + exceptDuringRunReport("S3 exception occurred", e); } catch ( NoSuchAlgorithmException e ) { - setException("Couldn't calculate MD5", e); + exceptDuringRunReport("Couldn't calculate MD5", e); } catch ( IOException e ) { - setException("Couldn't read report file", e); + exceptDuringRunReport("Couldn't read report file", e); + } catch ( Exception e ) { + exceptDuringRunReport("An unexpected exception occurred during posting", e); } } - - /** - * Set the error message and thrown exception, if one did occurred - * - * @param msg the error message - * @param e the exception that occurred - */ - private void setException(final String msg, final Throwable e){ - errorMsg=msg; - errorThrow=e; - } } /** @@ -643,11 +635,7 @@ public class GATKRunReport { logger.debug("Uploaded to AWS: " + s3run.s3Object); return s3run.s3Object; } else { - if((s3run.errorMsg != null) && (s3run.errorThrow != null)){ - exceptDuringRunReport(s3run.errorMsg,s3run.errorThrow); - } else { - exceptDuringRunReport("Run statistics report upload to AWS S3 failed"); - } + // an exception occurred, the thread should have already invoked the exceptDuringRunReport function } } catch ( IOException e ) { exceptDuringRunReport("Couldn't read report file", e); @@ -658,12 +646,21 @@ public class GATKRunReport { return null; } + // --------------------------------------------------------------------------- + // + // Error handling code + // + // --------------------------------------------------------------------------- + /** * Note that an exception occurred during creating or writing this report * @param msg the message to print * @param e the exception that occurred */ - private void exceptDuringRunReport(String msg, Throwable e) { + @Ensures("exceptionOccurredDuringPost()") + private void exceptDuringRunReport(final String msg, final Throwable e) { + this.errorMessage = msg; + this.errorThrown = e; logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***]. Message is: " + msg + ". Error message is: " + e.getMessage()); } @@ -671,10 +668,52 @@ public class GATKRunReport { * Note that an exception occurred during creating or writing this report * @param msg the message to print */ - private void exceptDuringRunReport(String msg) { + @Ensures("exceptionOccurredDuringPost()") + private void exceptDuringRunReport(final String msg) { + this.errorMessage = msg; logger.debug("A problem occurred during GATK run reporting [*** everything is fine, but no report could be generated; please do not post this to the support forum ***]. Message is " + msg); } + /** + * Did an error occur during the posting of this run report? + * @return true if so, false if not + */ + public boolean exceptionOccurredDuringPost() { + return getErrorMessage() != null; + } + + /** + * If an error occurred during posting of this report, retrieve the message of the error that occurred, or null if + * no error occurred + * @return a string describing the error that occurred, or null if none did + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Get the throwable that caused the exception during posting of this message, or null if none was available + * + * Note that getting a null valuable from this function doesn't not imply that no error occurred. Some + * errors that occurred many not have generated a throwable. + * + * @return the Throwable that caused the error, or null if no error occurred or was not caused by a throwable + */ + public Throwable getErrorThrown() { + return errorThrown; + } + + /** + * Helper method to format the exception that occurred during posting, or a string saying none occurred + * @return a non-null string + */ + @Ensures("result != null") + protected String formatError() { + return exceptionOccurredDuringPost() + ? String.format("Exception message=%s with cause=%s", getErrorMessage(), getErrorThrown()) + : "No exception occurred"; + } + // --------------------------------------------------------------------------- // // Equals and hashcode -- purely for comparing reports for testing From f31bf37a6fd1f2ae3c0755e3c1ce4071a6e29310 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Sun, 3 Feb 2013 15:31:30 -0500 Subject: [PATCH 186/188] First step in better BQSR unit tests for covariates (not done yet): more test coverage in basic covariates, test logging several read groups/read lengths and more combinations simultaneously. Add basic Javadocs headers for PerReadAlleleLikehoodMap. --- .../recalibration/ReadCovariatesUnitTest.java | 75 +++++++++++-------- .../genotyper/PerReadAlleleLikelihoodMap.java | 40 ++++++++++ 2 files changed, 84 insertions(+), 31 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java index 8d94c4c4a..58e143fc2 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java @@ -54,6 +54,8 @@ import org.broadinstitute.sting.utils.sam.ReadUtils; import org.testng.Assert; import org.testng.annotations.Test; +import java.util.Random; + /** * @author carneiro * @since 4/21/12 @@ -62,16 +64,8 @@ public class ReadCovariatesUnitTest { @Test(enabled = false) public void testCovariateGeneration() { + final RecalibrationArgumentCollection RAC = new RecalibrationArgumentCollection(); final String RGID = "id"; - final int length = 10; - final RecalibrationArgumentCollection RAC = new RecalibrationArgumentCollection(); - GATKSAMRecord read = ReadUtils.createRandomRead(length, false); - GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord(RGID); - rg.setPlatform("illumina"); - read.setReadGroup(rg); - final byte[] mQuals = read.getBaseQualities(EventType.BASE_SUBSTITUTION); - final byte[] iQuals = read.getBaseQualities(EventType.BASE_INSERTION); - final byte[] dQuals = read.getBaseQualities(EventType.BASE_DELETION); ReadGroupCovariate rgCov = new ReadGroupCovariate(); QualityScoreCovariate qsCov = new QualityScoreCovariate(); @@ -89,33 +83,52 @@ public class ReadCovariatesUnitTest { requestedCovariates[2] = coCov; requestedCovariates[3] = cyCov; - ReadCovariates rc = RecalUtils.computeCovariates(read, requestedCovariates); + final int NUM_READS = 100; + final Random rnd = new Random(); - // check that the length is correct - Assert.assertEquals(rc.getMismatchesKeySet().length, length); - Assert.assertEquals(rc.getInsertionsKeySet().length, length); - Assert.assertEquals(rc.getDeletionsKeySet().length, length); + final String[] readGroups = {"RG1", "RG2", "RGbla"}; + for (int idx = 0; idx < NUM_READS; idx++) { + for (final String rgs : readGroups) { + final int length = 10 + rnd.nextInt(100); // random read length, at least 10 bp long + final GATKSAMRecord read = ReadUtils.createRandomRead(length, false); + final GATKSAMReadGroupRecord rg = new GATKSAMReadGroupRecord(rgs); + rg.setPlatform("illumina"); + read.setReadGroup(rg); + read.setReadNegativeStrandFlag(rnd.nextBoolean()); + final byte[] mQuals = read.getBaseQualities(EventType.BASE_SUBSTITUTION); + final byte[] iQuals = read.getBaseQualities(EventType.BASE_INSERTION); + final byte[] dQuals = read.getBaseQualities(EventType.BASE_DELETION); + ReadCovariates rc = RecalUtils.computeCovariates(read, requestedCovariates); - for (int i = 0; i < length; i++) { - // check that read group is always the same - Assert.assertEquals(rgCov.formatKey(rc.getMismatchesKeySet(i)[0]), RGID); - Assert.assertEquals(rgCov.formatKey(rc.getInsertionsKeySet(i)[0]), RGID); - Assert.assertEquals(rgCov.formatKey(rc.getDeletionsKeySet(i)[0]), RGID); + // check that the length is correct + Assert.assertEquals(rc.getMismatchesKeySet().length, length); + Assert.assertEquals(rc.getInsertionsKeySet().length, length); + Assert.assertEquals(rc.getDeletionsKeySet().length, length); - // check quality score - Assert.assertEquals(qsCov.formatKey(rc.getMismatchesKeySet(i)[1]), "" + mQuals[i]); - Assert.assertEquals(qsCov.formatKey(rc.getInsertionsKeySet(i)[1]), "" + iQuals[i]); - Assert.assertEquals(qsCov.formatKey(rc.getDeletionsKeySet(i)[1]), "" + dQuals[i]); + for (int i = 0; i < length; i++) { + // check that read group is always the same + Assert.assertEquals(rgCov.formatKey(rc.getMismatchesKeySet(i)[0]), rgs); + Assert.assertEquals(rgCov.formatKey(rc.getInsertionsKeySet(i)[0]), rgs); + Assert.assertEquals(rgCov.formatKey(rc.getDeletionsKeySet(i)[0]), rgs); - // check context - Assert.assertEquals(coCov.formatKey(rc.getMismatchesKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.MISMATCHES_CONTEXT_SIZE)); - Assert.assertEquals(coCov.formatKey(rc.getInsertionsKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.INDELS_CONTEXT_SIZE)); - Assert.assertEquals(coCov.formatKey(rc.getDeletionsKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.INDELS_CONTEXT_SIZE)); + // check quality score + Assert.assertEquals(qsCov.formatKey(rc.getMismatchesKeySet(i)[1]), "" + mQuals[i]); + Assert.assertEquals(qsCov.formatKey(rc.getInsertionsKeySet(i)[1]), "" + iQuals[i]); + Assert.assertEquals(qsCov.formatKey(rc.getDeletionsKeySet(i)[1]), "" + dQuals[i]); + + // check context + Assert.assertEquals(coCov.formatKey(rc.getMismatchesKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.MISMATCHES_CONTEXT_SIZE)); + Assert.assertEquals(coCov.formatKey(rc.getInsertionsKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.INDELS_CONTEXT_SIZE)); + Assert.assertEquals(coCov.formatKey(rc.getDeletionsKeySet(i)[2]), ContextCovariateUnitTest.expectedContext(read, i, RAC.INDELS_CONTEXT_SIZE)); + + // check cycle + Assert.assertEquals(cyCov.formatKey(rc.getMismatchesKeySet(i)[3]), "" + (i+1)); + Assert.assertEquals(cyCov.formatKey(rc.getInsertionsKeySet(i)[3]), "" + (i+1)); + Assert.assertEquals(cyCov.formatKey(rc.getDeletionsKeySet(i)[3]), "" + (i+1)); + } + + } - // check cycle - Assert.assertEquals(cyCov.formatKey(rc.getMismatchesKeySet(i)[3]), "" + (i+1)); - Assert.assertEquals(cyCov.formatKey(rc.getInsertionsKeySet(i)[3]), "" + (i+1)); - Assert.assertEquals(cyCov.formatKey(rc.getDeletionsKeySet(i)[3]), "" + (i+1)); } } diff --git a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java index 46a3f58d0..85d77d946 100644 --- a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java +++ b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java @@ -26,6 +26,7 @@ package org.broadinstitute.sting.utils.genotyper; +import com.google.java.contract.Ensures; import org.broadinstitute.sting.gatk.downsampling.AlleleBiasedDownsamplingUtils; import org.broadinstitute.sting.utils.pileup.PileupElement; import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; @@ -35,8 +36,13 @@ import org.broadinstitute.variant.variantcontext.Allele; import java.io.PrintStream; import java.util.*; +/** + * Wrapper class that holds a set of maps of the form (Read -> Map(Allele->Double)) + * For each read, this holds underlying alleles represented by an aligned read, and corresponding relative likelihood. + */ public class PerReadAlleleLikelihoodMap { + public static final double INFORMATIVE_LIKELIHOOD_THRESHOLD = 0.2; protected List alleles; @@ -47,6 +53,12 @@ public class PerReadAlleleLikelihoodMap { alleles = new ArrayList(); } + /** + * Adds a read, allele and corresponding likelihood to map + * @param read SAM record to add + * @param a corresponding allele + * @param likelihood corresponding likelihood + */ public void add(GATKSAMRecord read, Allele a, Double likelihood) { Map likelihoodMap; if (likelihoodReadMap.containsKey(read)){ @@ -97,15 +109,33 @@ public class PerReadAlleleLikelihoodMap { likelihoodReadMap.remove(read); } + @Ensures("result >=0") public int size() { return likelihoodReadMap.size(); } + /** + * Helper function to add the read underneath a pileup element to the map + * @param p Pileup element + * @param a Corresponding allele + * @param likelihood Allele likelihood + */ public void add(PileupElement p, Allele a, Double likelihood) { + if (p==null || p.getRead()==null || a == null ) + throw new IllegalArgumentException("Invalid parameters passed to PerReadAlleleLikelihoodMap.add"); add(p.getRead(), a, likelihood); } + /** + * Does the current map contain the key associated with a particular SAM record in pileup? + * @param p Pileup element + * @return + */ + @Ensures("result != null") public boolean containsPileupElement(PileupElement p) { + if (p==null ) + throw new IllegalArgumentException("Invalid pileup element"); + return likelihoodReadMap.containsKey(p.getRead()); } @@ -140,11 +170,21 @@ public class PerReadAlleleLikelihoodMap { return likelihoodReadMap.get(p.getRead()); } + + /** + * For a given alleleMap, return most likely allele, i.e. the one with highest associated likelihood + * @param alleleMap Underlying allele map + * @return Most likely allele. If all alleles are equally likely, returns a no-call allele. + */ + @Ensures("result != null") public static Allele getMostLikelyAllele( final Map alleleMap ) { double maxLike = Double.NEGATIVE_INFINITY; double prevMaxLike = Double.NEGATIVE_INFINITY; Allele mostLikelyAllele = Allele.NO_CALL; + if (alleleMap==null) + throw new IllegalArgumentException("alleleMap in getMostLikelyAllele() method can't be null"); + for (final Map.Entry el : alleleMap.entrySet()) { if (el.getValue() > maxLike) { prevMaxLike = maxLike; From 5521bf3dd7a391004b0376ea074bf46744ea8d68 Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Sun, 3 Feb 2013 16:15:14 -0500 Subject: [PATCH 187/188] Fix bad contract implementation --- .../sting/utils/genotyper/PerReadAlleleLikelihoodMap.java | 1 - 1 file changed, 1 deletion(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java index 85d77d946..9cfa20b8f 100644 --- a/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java +++ b/public/java/src/org/broadinstitute/sting/utils/genotyper/PerReadAlleleLikelihoodMap.java @@ -131,7 +131,6 @@ public class PerReadAlleleLikelihoodMap { * @param p Pileup element * @return */ - @Ensures("result != null") public boolean containsPileupElement(PileupElement p) { if (p==null ) throw new IllegalArgumentException("Invalid pileup element"); From 971ded341b74849192291084b1ae12e48abed4ad Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Mon, 4 Feb 2013 10:57:34 -0500 Subject: [PATCH 188/188] Swap java Random generator for GATK one to ensure test determinism --- .../sting/utils/recalibration/ReadCovariatesUnitTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java index 58e143fc2..f20d6116b 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/ReadCovariatesUnitTest.java @@ -46,6 +46,7 @@ package org.broadinstitute.sting.utils.recalibration; +import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.walkers.bqsr.RecalibrationArgumentCollection; import org.broadinstitute.sting.utils.recalibration.covariates.*; import org.broadinstitute.sting.utils.sam.GATKSAMReadGroupRecord; @@ -84,7 +85,7 @@ public class ReadCovariatesUnitTest { requestedCovariates[3] = cyCov; final int NUM_READS = 100; - final Random rnd = new Random(); + final Random rnd = GenomeAnalysisEngine.getRandomGenerator(); final String[] readGroups = {"RG1", "RG2", "RGbla"}; for (int idx = 0; idx < NUM_READS; idx++) {

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 + + diff --git a/settings/repository/org.broad/tribble-119.xml b/settings/repository/org.broad/tribble-119.xml deleted file mode 100644 index 08037b20e..000000000 --- a/settings/repository/org.broad/tribble-119.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - From 63e68a725ffccf391e4dddbd9035373f78782c6a Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:26:22 -0500 Subject: [PATCH 163/188] Expanded unit tests for AlignmentUtils -- Added JIRA entries for the remaining capabilities to be fixed up and unit tested --- .../sting/utils/sam/AlignmentUtils.java | 225 ++++++------------ .../utils/sam/AlignmentUtilsUnitTest.java | 112 ++++++++- 2 files changed, 188 insertions(+), 149 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index d270f251d..1607db8af 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -40,9 +40,16 @@ import org.broadinstitute.sting.utils.recalibration.EventType; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; -public class AlignmentUtils { +public final class AlignmentUtils { + private final static EnumSet ALIGNED_TO_GENOME_OPERATORS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X); + private final static EnumSet ALIGNED_TO_GENOME_PLUS_SOFTCLIPS = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S); + + // cannot be instantiated + private AlignmentUtils() { } public static class MismatchCount { public int numMismatches = 0; @@ -118,103 +125,6 @@ public class AlignmentUtils { return mc; } - /** - * Returns the number of mismatches in the pileup within the given reference context. - * - * @param pileup the pileup with reads - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(ReadBackedPileup pileup, ReferenceContext ref, boolean ignoreTargetSite) { - int mismatches = 0; - for (PileupElement p : pileup) - mismatches += mismatchesInRefWindow(p, ref, ignoreTargetSite); - return mismatches; - } - - /** - * Returns the number of mismatches in the pileup element within the given reference context. - * - * @param p the pileup element - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(PileupElement p, ReferenceContext ref, boolean ignoreTargetSite) { - return mismatchesInRefWindow(p, ref, ignoreTargetSite, false); - } - - /** - * Returns the number of mismatches in the pileup element within the given reference context. - * - * @param p the pileup element - * @param ref the reference context - * @param ignoreTargetSite if true, ignore mismatches at the target locus (i.e. the center of the window) - * @param qualitySumInsteadOfMismatchCount - * if true, return the quality score sum of the mismatches rather than the count - * @return the number of mismatches - */ - public static int mismatchesInRefWindow(PileupElement p, ReferenceContext ref, boolean ignoreTargetSite, boolean qualitySumInsteadOfMismatchCount) { - int sum = 0; - - int windowStart = ref.getWindow().getStart(); - int windowStop = ref.getWindow().getStop(); - byte[] refBases = ref.getBases(); - byte[] readBases = p.getRead().getReadBases(); - byte[] readQualities = p.getRead().getBaseQualities(); - Cigar c = p.getRead().getCigar(); - - int readIndex = 0; - int currentPos = p.getRead().getAlignmentStart(); - int refIndex = Math.max(0, currentPos - windowStart); - - for (int i = 0; i < c.numCigarElements(); i++) { - CigarElement ce = c.getCigarElement(i); - int cigarElementLength = ce.getLength(); - switch (ce.getOperator()) { - case EQ: - case X: - case M: - for (int j = 0; j < cigarElementLength; j++, readIndex++, currentPos++) { - // are we past the ref window? - if (currentPos > windowStop) - break; - - // are we before the ref window? - if (currentPos < windowStart) - continue; - - byte refChr = refBases[refIndex++]; - - // do we need to skip the target site? - if (ignoreTargetSite && ref.getLocus().getStart() == currentPos) - continue; - - byte readChr = readBases[readIndex]; - if (readChr != refChr) - sum += (qualitySumInsteadOfMismatchCount) ? readQualities[readIndex] : 1; - } - break; - case I: - case S: - readIndex += cigarElementLength; - break; - case D: - case N: - currentPos += cigarElementLength; - if (currentPos > windowStart) - refIndex += Math.min(cigarElementLength, currentPos - windowStart); - break; - case H: - case P: - break; - } - } - - return sum; - } - /** * Returns number of alignment blocks (continuous stretches of aligned bases) in the specified alignment. * This method follows closely the SAMRecord::getAlignmentBlocks() implemented in samtools library, but @@ -225,31 +135,54 @@ public class AlignmentUtils { * @param r alignment * @return number of continuous alignment blocks (i.e. 'M' elements of the cigar; all indel and clipping elements are ignored). */ + @Ensures("result >= 0") public static int getNumAlignmentBlocks(final SAMRecord r) { - int n = 0; + if ( r == null ) throw new IllegalArgumentException("read cannot be null"); final Cigar cigar = r.getCigar(); if (cigar == null) return 0; + int n = 0; for (final CigarElement e : cigar.getCigarElements()) { - if (e.getOperator() == CigarOperator.M) n++; + if (ALIGNED_TO_GENOME_OPERATORS.contains(e.getOperator())) + n++; } return n; } - public static int getNumAlignedBasesCountingSoftClips(final SAMRecord r) { + + /** + * Get the number of bases aligned to the genome, including soft clips + * + * If read is not mapped (i.e., doesn't have a cigar) returns 0 + * + * @param r a non-null GATKSAMRecord + * @return the number of bases aligned to the genome in R, including soft clipped bases + */ + public static int getNumAlignedBasesCountingSoftClips(final GATKSAMRecord r) { int n = 0; final Cigar cigar = r.getCigar(); if (cigar == null) return 0; for (final CigarElement e : cigar.getCigarElements()) - if (e.getOperator() == CigarOperator.M || e.getOperator() == CigarOperator.S) + if (ALIGNED_TO_GENOME_PLUS_SOFTCLIPS.contains(e.getOperator())) n += e.getLength(); return n; } + /** + * Count the number of bases hard clipped from read + * + * If read's cigar is null, return 0 + * + * @param r a non-null read + * @return a positive integer + */ + @Ensures("result >= 0") public static int getNumHardClippedBases(final SAMRecord r) { + if ( r == null ) throw new IllegalArgumentException("Read cannot be null"); + int n = 0; final Cigar cigar = r.getCigar(); if (cigar == null) return 0; @@ -264,7 +197,9 @@ public class AlignmentUtils { /** * Calculate the number of bases that are soft clipped in read with quality score greater than threshold * - * @param read a non-null GATKSAMRecord + * Handles the case where the cigar is null (i.e., the read is unmapped), returning 0 + * + * @param read a non-null GATKSAMRecord. * @param qualThreshold consider bases with quals > this value as high quality. Must be >= 0 * @return positive integer */ @@ -273,6 +208,9 @@ public class AlignmentUtils { if ( read == null ) throw new IllegalArgumentException("Read cannot be null"); if ( qualThreshold < 0 ) throw new IllegalArgumentException("Expected qualThreshold to be a positive byte but saw " + qualThreshold); + if ( read.getCigar() == null ) // the read is unmapped + return 0; + final byte[] qual = read.getBaseQualities( EventType.BASE_SUBSTITUTION ); int numHQSoftClips = 0; @@ -300,16 +238,12 @@ public class AlignmentUtils { } public static int calcAlignmentByteArrayOffset(final Cigar cigar, final PileupElement pileupElement, final int alignmentStart, final int refLocus) { - return calcAlignmentByteArrayOffset( cigar, pileupElement.getOffset(), false, pileupElement.isDeletion(), alignmentStart, refLocus ); + return calcAlignmentByteArrayOffset( cigar, pileupElement.getOffset(), pileupElement.isDeletion(), alignmentStart, refLocus ); } - public static int calcAlignmentByteArrayOffset(final Cigar cigar, final int offset, final boolean isInsertionAtBeginningOfRead, final boolean isDeletion, final int alignmentStart, final int refLocus) { + public static int calcAlignmentByteArrayOffset(final Cigar cigar, final int offset, final boolean isDeletion, final int alignmentStart, final int refLocus) { int pileupOffset = offset; - // Special case for reads starting with insertion - if (isInsertionAtBeginningOfRead) - return 0; - // Reassign the offset if we are in the middle of a deletion because of the modified representation of the read bases if (isDeletion) { pileupOffset = refLocus - alignmentStart; @@ -462,47 +396,27 @@ public class AlignmentUtils { * specification, one may need this convenience shortcut. Checks both 'read unmapped' flag and * alignment reference index/start. * - * @param r record + * Our life would be so much easier if all sam files followed the specs. In reality, + * sam files (including those generated by maq or bwa) miss headers altogether. When + * reading such a SAM file, reference name is set, but since there is no sequence dictionary, + * null is always returned for referenceIndex. Let's be paranoid here, and make sure that + * we do not call the read "unmapped" when it has only reference name set with ref. index missing + * or vice versa. + * + * @param r a non-null record * @return true if read is unmapped */ public static boolean isReadUnmapped(final SAMRecord r) { + if ( r == null ) throw new IllegalArgumentException("Read cannot be null"); + if (r.getReadUnmappedFlag()) return true; - // our life would be so much easier if all sam files followed the specs. In reality, - // sam files (including those generated by maq or bwa) miss headers altogether. When - // reading such a SAM file, reference name is set, but since there is no sequence dictionary, - // null is always returned for referenceIndex. Let's be paranoid here, and make sure that - // we do not call the read "unmapped" when it has only reference name set with ref. index missing - // or vice versa. if ((r.getReferenceIndex() != null && r.getReferenceIndex() != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX || r.getReferenceName() != null && !r.getReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME)) && r.getAlignmentStart() != SAMRecord.NO_ALIGNMENT_START) return false; return true; } - /** - * Due to (unfortunate) multiple ways to indicate that read/mate is unmapped allowed by SAM format - * specification, one may need this convenience shortcut. Checks both 'mate unmapped' flag and - * alignment reference index/start of the mate. - * - * @param r sam record for the read - * @return true if read's mate is unmapped - */ - public static boolean isMateUnmapped(final SAMRecord r) { - if (r.getMateUnmappedFlag()) return true; - - // our life would be so much easier if all sam files followed the specs. In reality, - // sam files (including those generated by maq or bwa) miss headers altogether. When - // reading such a SAM file, reference name is set, but since there is no sequence dictionary, - // null is always returned for referenceIndex. Let's be paranoid here, and make sure that - // we do not call the read "unmapped" when it has only reference name set with ref. index missing - // or vice versa. - if ((r.getMateReferenceIndex() != null && r.getMateReferenceIndex() != SAMRecord.NO_ALIGNMENT_REFERENCE_INDEX - || r.getMateReferenceName() != null && !r.getMateReferenceName().equals(SAMRecord.NO_ALIGNMENT_REFERENCE_NAME)) - && r.getMateAlignmentStart() != SAMRecord.NO_ALIGNMENT_START) return false; - return true; - } - /** * Need a well-formed, consolidated Cigar string so that the left aligning code works properly. * For example, 1M1M1M1D2M1M --> 3M1D3M @@ -592,22 +506,41 @@ public class AlignmentUtils { return cigar; } - private static boolean cigarHasZeroSizeElement(Cigar c) { - for (CigarElement ce : c.getCigarElements()) { + /** + * Does one of the elements in cigar have a 0 length? + * + * @param c a non-null cigar + * @return true if any element has 0 size + */ + @Requires("c != null") + protected static boolean cigarHasZeroSizeElement(final Cigar c) { + for (final CigarElement ce : c.getCigarElements()) { if (ce.getLength() == 0) return true; } return false; } - private static Cigar cleanUpCigar(Cigar c) { - ArrayList elements = new ArrayList(c.numCigarElements() - 1); - for (CigarElement ce : c.getCigarElements()) { - if (ce.getLength() != 0 && - (elements.size() != 0 || ce.getOperator() != CigarOperator.D)) { + /** + * Clean up the incoming cigar + * + * Removes elements with zero size + * Clips away beginning deletion operators + * + * @param c the cigar string we want to clean up + * @return a newly allocated, cleaned up Cigar + */ + @Requires("c != null") + @Ensures("result != null") + private static Cigar cleanUpCigar(final Cigar c) { + final List elements = new ArrayList(c.numCigarElements() - 1); + + for (final CigarElement ce : c.getCigarElements()) { + if (ce.getLength() != 0 && (! elements.isEmpty() || ce.getOperator() != CigarOperator.D)) { elements.add(ce); } } + return new Cigar(elements); } diff --git a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java index ea3e2bdbb..d9f514593 100644 --- a/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/sam/AlignmentUtilsUnitTest.java @@ -33,9 +33,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class AlignmentUtilsUnitTest { private SAMFileHeader header; @@ -127,6 +125,114 @@ public class AlignmentUtilsUnitTest { ArtificialSAMUtils.DEFAULT_READ_LENGTH); } + private final List> makeCigarElementCombinations() { + // this functionality can be adapted to provide input data for whatever you might want in your data + final List cigarElements = new LinkedList(); + for ( final int size : Arrays.asList(0, 10) ) { + for ( final CigarOperator op : CigarOperator.values() ) { + cigarElements.add(new CigarElement(size, op)); + } + } + + final List> combinations = new LinkedList>(); + for ( final int nElements : Arrays.asList(1, 2, 3) ) { + combinations.addAll(Utils.makePermutations(cigarElements, nElements, true)); + } + + return combinations; + } + + + @DataProvider(name = "NumAlignedBasesCountingSoftClips") + public Object[][] makeNumAlignedBasesCountingSoftClips() { + List tests = new ArrayList(); + + final EnumSet alignedToGenome = EnumSet.of(CigarOperator.M, CigarOperator.EQ, CigarOperator.X, CigarOperator.S); + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) n += alignedToGenome.contains(elt.getOperator()) ? elt.getLength() : 0; + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumAlignedBasesCountingSoftClips") + public void testNumAlignedBasesCountingSoftClips(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumAlignedBasesCountingSoftClips(read), expected, "Cigar " + cigar + " failed NumAlignedBasesCountingSoftClips"); + } + + @DataProvider(name = "CigarHasZeroElement") + public Object[][] makeCigarHasZeroElement() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + boolean hasZero = false; + for ( final CigarElement elt : elements ) hasZero = hasZero || elt.getLength() == 0; + tests.add(new Object[]{new Cigar(elements), hasZero}); + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "CigarHasZeroElement") + public void testCigarHasZeroSize(final Cigar cigar, final boolean hasZero) { + Assert.assertEquals(AlignmentUtils.cigarHasZeroSizeElement(cigar), hasZero, "Cigar " + cigar.toString() + " failed cigarHasZeroSizeElement"); + } + + @DataProvider(name = "NumHardClipped") + public Object[][] makeNumHardClipped() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) n += elt.getOperator() == CigarOperator.H ? elt.getLength() : 0; + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumHardClipped") + public void testNumHardClipped(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumHardClippedBases(read), expected, "Cigar " + cigar + " failed num hard clips"); + } + + @DataProvider(name = "NumAlignedBlocks") + public Object[][] makeNumAlignedBlocks() { + List tests = new ArrayList(); + + for ( final List elements : makeCigarElementCombinations() ) { + int n = 0; + for ( final CigarElement elt : elements ) { + switch ( elt.getOperator() ) { + case M:case X:case EQ: n++; break; + default: break; + } + } + tests.add(new Object[]{new Cigar(elements), n}); + } + + tests.add(new Object[]{null, 0}); + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "NumAlignedBlocks") + public void testNumAlignedBlocks(final Cigar cigar, final int expected) { + final GATKSAMRecord read = ArtificialSAMUtils.createArtificialRead(header, "myRead", 0, 1, cigar == null ? 10 : cigar.getReadLength()); + read.setCigar(cigar); + Assert.assertEquals(AlignmentUtils.getNumAlignmentBlocks(read), expected, "Cigar " + cigar + " failed NumAlignedBlocks"); + } + @Test public void testConsolidateCigar() { { From 59028fe6f34dfb0b42f97d91dc3743757bd969f0 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:26:22 -0500 Subject: [PATCH 164/188] Expanded unit tests for AlignmentUtils -- Added JIRA entries for the remaining capabilities to be fixed up and unit tested --- .../sting/gatk/walkers/annotator/ReadPosRankSumTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java index 95b31b732..ddca5e0b8 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/annotator/ReadPosRankSumTest.java @@ -107,7 +107,7 @@ public class ReadPosRankSumTest extends RankSumTest implements StandardAnnotatio final int offset = ReadUtils.getReadCoordinateForReferenceCoordinate( read.getSoftStart(), read.getCigar(), refLoc, ReadUtils.ClippingTail.RIGHT_TAIL, true ); if ( offset == ReadUtils.CLIPPING_GOAL_NOT_REACHED ) continue; - int readPos = AlignmentUtils.calcAlignmentByteArrayOffset( read.getCigar(), offset, false, false, 0, 0 ); + int readPos = AlignmentUtils.calcAlignmentByteArrayOffset( read.getCigar(), offset, false, 0, 0 ); final int numAlignedBases = AlignmentUtils.getNumAlignedBasesCountingSoftClips( read ); if (readPos > numAlignedBases / 2) readPos = numAlignedBases - (readPos + 1); From 110f0d4e826c5287ac7ef4796d936a3e62ff6938 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 31 Jan 2013 17:46:18 -0500 Subject: [PATCH 165/188] Cleanup unused utils functions, and add unit test for one (append) --- .../org/broadinstitute/sting/utils/Utils.java | 212 +----------------- .../sting/utils/UtilsUnitTest.java | 22 +- 2 files changed, 27 insertions(+), 207 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/Utils.java b/public/java/src/org/broadinstitute/sting/utils/Utils.java index eb287abd8..39fcbb3d2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Utils.java +++ b/public/java/src/org/broadinstitute/sting/utils/Utils.java @@ -240,6 +240,13 @@ public class Utils { } } + /** + * Create a new list that contains the elements of left along with elements elts + * @param left a non-null list of elements + * @param elts a varargs vector for elts to append in order to left + * @param + * @return A newly allocated linked list containing left followed by elts + */ public static List append(final List left, T ... elts) { final List l = new LinkedList(left); l.addAll(Arrays.asList(elts)); @@ -329,15 +336,6 @@ public class Utils { return str.substring(start, end+1); } - public static byte listMaxByte(List quals) { - if (quals.size() == 0) return 0; - byte m = quals.get(0); - for (byte b : quals) { - m = b > m ? b : m; - } - return m; - } - /** * Splits expressions in command args by spaces and returns the array of expressions. * Expressions may use single or double quotes to group any individual expression, but not both. @@ -390,182 +388,6 @@ public class Utils { return C; } - /** - * Appends String(s) B to array A. - * @param A First array. - * @param B Strings to append. - * @return A with B(s) appended. - */ - public static String[] appendArray(String[] A, String... B) { - return concatArrays(A, B); - } - - /** - * Returns indices of all occurrences of the specified symbol in the string - * @param s Search string - * @param ch Character to search for - * @return Indices of all occurrences of the specified symbol - */ - public static int[] indexOfAll(String s, int ch) { - int[] pos = new int[64]; - int z = 0; - - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) == ch) pos[z++] = i; - } - return reallocate(pos, z); - } - - public static int countSetBits(boolean[] array) { - int counter = 0; - for ( int i = 0; i < array.length; i++ ) { - if ( array[i] ) - counter++; - } - return counter; - } - - /** - * Returns new (reallocated) integer array of the specified size, with content - * of the original array orig copied into it. If newSize is - * less than the size of the original array, only first newSize elements will be copied. - * If new size is greater than the size of the original array, the content of the original array will be padded - * with zeros up to the new size. Finally, if new size is the same as original size, no memory reallocation - * will be performed and the original array will be returned instead. - * - * @param orig Original size. - * @param newSize New Size. - * - * @return New array with length equal to newSize. - */ - public static int[] reallocate(int[] orig, int newSize) { - if (orig.length == newSize) return orig; - int[] new_array = new int[newSize]; - int L = (newSize > orig.length ? orig.length : newSize); - for (int i = 0; i < L; i++) new_array[i] = orig[i]; - return new_array; - } - - - /** - * Returns a copy of array a, extended with additional n elements to the right (if n > 0 ) or -n elements to the - * left (if n<0), copying the values form the original array. Newly added elements are filled with value v. Note that - * if array a is being padded to the left, first (-n) elements of the returned array are v's, followed by the content of - * array a. - * @param a original array - * @param n number of (v-filled) elements to append to a on the right (n>0) or on the left (n<0) - * @param v element value - * @return the extended copy of array a with additional n elements - */ - public static byte [] extend(final byte[] a, int n, byte v) { - - byte [] newA; - - if ( n > 0 ) { - newA = Arrays.copyOf(a, a.length+n); - if ( v != 0) { // java pads with 0's for us, so there is nothing to do if v==0 - for ( int i = a.length; i < newA.length ; i++ ) newA[i] = v; - } - return newA; - } - - // we are here only if n < 0: - n = (-n); - newA = new byte[ a.length + n ]; - int i; - if ( v!= 0 ) { - i = 0; - for( ; i < n; i++ ) newA[i] = v; - } else { - i = n; - } - for ( int j = 0 ; j < a.length ; i++, j++) newA[i]=a[j]; - return newA; - } - - - /** - * Returns a copy of array a, extended with additional n elements to the right (if n > 0 ) or -n elements to the - * left (if n<0), copying the values form the original array. Newly added elements are filled with value v. Note that - * if array a is padded to the left, first (-n) elements of the returned array are v's, followed by the content of - * array a. - * @param a original array - * @param n number of (v-filled) elements to append to a on the right (n>0) or on the left (n<0) - * @param v element value - * @return the extended copy of array a with additional n elements - */ - public static short [] extend(final short[] a, int n, short v) { - - short [] newA; - - if ( n > 0 ) { - newA = Arrays.copyOf(a, a.length+n); - if ( v != 0) { // java pads with 0's for us, so there is nothing to do if v==0 - for ( int i = a.length; i < newA.length ; i++ ) newA[i] = v; - } - return newA; - } - - // we are here only if n < 0: - n = (-n); - newA = new short[ a.length + n ]; - int i; - if ( v!= 0 ) { - i = 0; - for( ; i < n; i++ ) newA[i] = v; - } else { - i = n; - } - for ( int j = 0 ; j < a.length ; i++, j++) newA[i]=a[j]; - return newA; - } - - /* TEST ME - public static void main(String[] argv) { - List l1 = new LinkedList(); - List l2 = new ArrayList(); - - l1.add(1); - l1.add(5); - l1.add(3); - l1.add(10); - l1.add(4); - l1.add(2); - l2.add(1); - l2.add(5); - l2.add(3); - l2.add(10); - l2.add(4); - l2.add(2); - - Predicate p = new Predicate() { - public boolean apply(Integer i) { - return i > 2; - } - }; - filterInPlace(p, l1); - filterInPlace(p, l2); - - for ( int i = 0 ; i < l1.size(); i++ ) System.out.print(" "+l1.get(i)); - System.out.println(); - for ( int i = 0 ; i < l2.size(); i++ ) System.out.print(" " + l2.get(i)); - System.out.println(); - - } - - */ - - /** - * a helper method. Turns a single character string into a char. - * - * @param str the string - * - * @return a char - */ - public static char stringToChar(String str) { - if (str.length() != 1) throw new IllegalArgumentException("String length must be one"); - return str.charAt(0); - } public static > List sorted(Collection c) { return sorted(c, false); @@ -594,18 +416,6 @@ public class Utils { return l; } - public static , V> String sortedString(Map c) { - List t = new ArrayList(c.keySet()); - Collections.sort(t); - - List pairs = new ArrayList(); - for ( T k : t ) { - pairs.add(k + "=" + c.get(k)); - } - - return "{" + join(", ", pairs) + "}"; - } - /** * Reverse a byte array of bases * @@ -654,14 +464,6 @@ public class Utils { return new String( reverse( bases.getBytes() )) ; } - public static byte[] charSeq2byteSeq(char[] seqIn) { - byte[] seqOut = new byte[seqIn.length]; - for ( int i = 0; i < seqIn.length; i++ ) { - seqOut[i] = (byte)seqIn[i]; - } - return seqOut; - } - public static boolean isFlagSet(int value, int flag) { return ((value & flag) == flag); } diff --git a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java index 5d6ecd0f9..29c643153 100644 --- a/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/UtilsUnitTest.java @@ -32,8 +32,7 @@ import org.broadinstitute.sting.BaseTest; import org.testng.annotations.Test; import java.io.File; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; /** * Testing framework for general purpose utilities class. @@ -43,6 +42,25 @@ import java.util.Map; */ public class UtilsUnitTest extends BaseTest { + @Test + public void testAppend() { + for ( int leftSize : Arrays.asList(0, 1, 2, 3) ) { + for ( final int rightSize : Arrays.asList(0, 1, 2) ) { + final List left = new LinkedList(); + for ( int i = 0; i < leftSize; i++ ) left.add(i); + final List total = new LinkedList(); + for ( int i = 0; i < leftSize + rightSize; i++ ) total.add(i); + + if ( rightSize == 0 ) + Assert.assertEquals(Utils.append(left), total); + if ( rightSize == 1 ) + Assert.assertEquals(Utils.append(left, leftSize), total); + if ( rightSize == 2 ) + Assert.assertEquals(Utils.append(left, leftSize, leftSize + 1), total); + } + } + + } @Test public void testDupStringNoChars() { From 48b08a01729cdcacef6c9b6a6db9cdecacfa849e Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 01:18:51 -0500 Subject: [PATCH 166/188] Restore Utils.appendArray() This utility method was used by the PipelineTest class, and deleting it was causing tests to not compile. --- .../java/src/org/broadinstitute/sting/utils/Utils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/java/src/org/broadinstitute/sting/utils/Utils.java b/public/java/src/org/broadinstitute/sting/utils/Utils.java index 39fcbb3d2..77f3a84c3 100644 --- a/public/java/src/org/broadinstitute/sting/utils/Utils.java +++ b/public/java/src/org/broadinstitute/sting/utils/Utils.java @@ -388,6 +388,15 @@ public class Utils { return C; } + /** + * Appends String(s) B to array A. + * @param A First array. + * @param B Strings to append. + * @return A with B(s) appended. + */ + public static String[] appendArray(String[] A, String... B) { + return concatArrays(A, B); + } public static > List sorted(Collection c) { return sorted(c, false); From baf2c4c338d49ce5321054dffa0318de25ccc47b Mon Sep 17 00:00:00 2001 From: Guillermo del Angel Date: Fri, 1 Feb 2013 11:13:10 -0500 Subject: [PATCH 167/188] Add option to specify maximum STR length to RepeatCovariates from command line to ease testing --- .../bqsr/RecalibrationArgumentCollection.java | 12 ++++++++++++ .../recalibration/covariates/RepeatCovariate.java | 6 ++++-- .../recalibration/RepeatCovariatesUnitTest.java | 6 +++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java index 4c98a70a0..95b54102f 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java @@ -223,6 +223,18 @@ public class RecalibrationArgumentCollection { @Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only") public PrintStream RECAL_TABLE_UPDATE_LOG = null; + /** + * The repeat covariate will use a context of this size to calculate it's covariate value for base insertions and deletions + */ + @Hidden + @Argument(fullName = "max_str_unit_length", shortName = "maxstr", doc = "Max size of the k-mer context to be used for repeat covariates", required = false) + public int MAX_STR_UNIT_LENGTH = 8; + + @Hidden + @Argument(fullName = "max_repeat_length", shortName = "maxrep", doc = "Max number of repetitions to be used for repeat covariates", required = false) + public int MAX_REPEAT_LENGTH = 20; + + public File existingRecalibrationReport = null; public GATKReportTable generateReportTable(final String covariateNames) { diff --git a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java index 0eeb18251..9672bc5f3 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java +++ b/protected/java/src/org/broadinstitute/sting/utils/recalibration/covariates/RepeatCovariate.java @@ -61,8 +61,8 @@ import java.util.Map; import java.util.Set; public abstract class RepeatCovariate implements ExperimentalCovariate { - public static final int MAX_REPEAT_LENGTH = 20; - public static final int MAX_STR_UNIT_LENGTH = 8; + protected int MAX_REPEAT_LENGTH; + protected int MAX_STR_UNIT_LENGTH; private final HashMap repeatLookupTable = new HashMap(); private final HashMap repeatReverseLookupTable = new HashMap(); private int nextId = 0; @@ -70,6 +70,8 @@ public abstract class RepeatCovariate implements ExperimentalCovariate { // Initialize any member variables using the command-line arguments passed to the walkers @Override public void initialize(final RecalibrationArgumentCollection RAC) { + MAX_STR_UNIT_LENGTH = RAC.MAX_STR_UNIT_LENGTH; + MAX_REPEAT_LENGTH = RAC.MAX_REPEAT_LENGTH; } @Override diff --git a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java index 6d13fe96c..ea70deeea 100644 --- a/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java +++ b/protected/java/test/org/broadinstitute/sting/utils/recalibration/RepeatCovariatesUnitTest.java @@ -139,8 +139,8 @@ public class RepeatCovariatesUnitTest { @Test(enabled = true) public void testManyObservations() { final int NUM_UNITS = 10; - final int MAX_REPEAT_UNIT_LENGTH = RepeatCovariate.MAX_STR_UNIT_LENGTH; - final int MAX_NUM_REPETITIONS = RepeatCovariate.MAX_REPEAT_LENGTH; + final int MAX_REPEAT_UNIT_LENGTH = RAC.MAX_STR_UNIT_LENGTH; + final int MAX_NUM_REPETITIONS = RAC.MAX_REPEAT_LENGTH; final int NUM_TEST_CASES = 100; Random random = new Random(); @@ -207,7 +207,7 @@ public class RepeatCovariatesUnitTest { int fw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(offset+1,readLength).getBytes(),true); int bw = GATKVariantContextUtils.findNumberofRepetitions(ruValM.getBytes(), readBases.substring(0,offset+1).getBytes(),false); - Assert.assertEquals(Math.min(fw+bw,RepeatCovariate.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); + Assert.assertEquals(Math.min(fw+bw,RAC.MAX_REPEAT_LENGTH),(int)Integer.valueOf(rlValM)); } } From 874913318ac22742185677095463ada75572cb0e Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 00:36:54 -0500 Subject: [PATCH 168/188] Temporarily back out the Picard team's patches to GATKBAMIndex from December These patches to GATKBAMIndex are causing massive BAM index reading errors in combination with the latest version of Picard. The bug is either in the patches themselves or in the underlying SeekableBufferedStream class they rely on. Until the cause can be identified, we are temporarily backing out these changes so that we can continue to run with the latest Picard/Tribble. This reverts commits: 81483ec21e528790dfa719d18cdee27d577ca98e 68cf0309db490b79eecdabb4034987ff825ffea8 54bb68f28ad5fe1b3df01702e9c5e108106a0176 --- .../gatk/datasources/reads/GATKBAMIndex.java | 51 ++++++------------- .../qc/PileupWalkerIntegrationTest.java | 30 ----------- 2 files changed, 15 insertions(+), 66 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java index 1cfb527cd..aec41e340 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java @@ -25,17 +25,17 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import net.sf.samtools.seekablestream.SeekableBufferedStream; -import net.sf.samtools.seekablestream.SeekableFileStream; - import net.sf.samtools.*; - +import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -70,9 +70,6 @@ public class GATKBAMIndex { private final File mFile; - //TODO: figure out a good value for this buffer size - private final int BUFFERED_STREAM_BUFFER_SIZE=8192; - /** * Number of sequences stored in this index. */ @@ -83,8 +80,8 @@ public class GATKBAMIndex { */ private final long[] sequenceStartCache; - private SeekableFileStream fileStream; - private SeekableBufferedStream bufferedStream; + private FileInputStream fileStream; + private FileChannel fileChannel; public GATKBAMIndex(final File file) { mFile = file; @@ -282,6 +279,7 @@ public class GATKBAMIndex { for (int i = sequenceIndex; i < referenceSequence; i++) { sequenceStartCache[i] = position(); + // System.out.println("# Sequence TID: " + i); final int nBins = readInteger(); // System.out.println("# nBins: " + nBins); @@ -294,18 +292,15 @@ public class GATKBAMIndex { final int nLinearBins = readInteger(); // System.out.println("# nLinearBins: " + nLinearBins); skipBytes(8 * nLinearBins); - } sequenceStartCache[referenceSequence] = position(); } - - private void openIndexFile() { try { - fileStream = new SeekableFileStream(mFile); - bufferedStream = new SeekableBufferedStream(fileStream,BUFFERED_STREAM_BUFFER_SIZE); + fileStream = new FileInputStream(mFile); + fileChannel = fileStream.getChannel(); } catch (IOException exc) { throw new ReviewedStingException("Unable to open index file (" + exc.getMessage() +")" + mFile, exc); @@ -314,7 +309,7 @@ public class GATKBAMIndex { private void closeIndexFile() { try { - bufferedStream.close(); + fileChannel.close(); fileStream.close(); } catch (IOException exc) { @@ -359,12 +354,7 @@ public class GATKBAMIndex { private void read(final ByteBuffer buffer) { try { int bytesExpected = buffer.limit(); - //BufferedInputStream cannot read directly into a byte buffer, so we read into an array - //and put the result into the bytebuffer after the if statement. - - //SeekableBufferedStream is evil, it will "read" beyond the end of the file if you let it! - final int bytesToRead = (int) Math.min(bufferedStream.length() - bufferedStream.position(), bytesExpected); //min of int and long will definitely be castable to an int. - int bytesRead = bufferedStream.read(byteArray,0,bytesToRead); + int bytesRead = fileChannel.read(buffer); // We have a rigid expectation here to read in exactly the number of bytes we've limited // our buffer to -- if we read in fewer bytes than this, or encounter EOF (-1), the index @@ -375,7 +365,6 @@ public class GATKBAMIndex { "Please try re-indexing the corresponding BAM file.", mFile)); } - buffer.put(byteArray,0,bytesRead); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to read bytes from index file " + mFile); @@ -389,13 +378,10 @@ public class GATKBAMIndex { */ private ByteBuffer buffer = null; - //BufferedStream don't read into ByteBuffers, so we need this temporary array - private byte[] byteArray=null; private ByteBuffer getBuffer(final int size) { if(buffer == null || buffer.capacity() < size) { // Allocate a new byte buffer. For now, make it indirect to make sure it winds up on the heap for easier debugging. buffer = ByteBuffer.allocate(size); - byteArray = new byte[size]; buffer.order(ByteOrder.LITTLE_ENDIAN); } buffer.clear(); @@ -405,13 +391,7 @@ public class GATKBAMIndex { private void skipBytes(final int count) { try { - - //try to skip forward the requested amount. - long skipped = bufferedStream.skip(count); - - if( skipped != count ) { //if not managed to skip the requested amount - throw new ReviewedStingException("Index: unable to reposition file channel of index file " + mFile); - } + fileChannel.position(fileChannel.position() + count); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to reposition file channel of index file " + mFile); @@ -420,8 +400,7 @@ public class GATKBAMIndex { private void seek(final long position) { try { - //to seek a new position, move the fileChannel, and reposition the bufferedStream - bufferedStream.seek(position); + fileChannel.position(position); } catch(IOException ex) { throw new ReviewedStingException("Index: unable to reposition of file channel of index file " + mFile); @@ -434,7 +413,7 @@ public class GATKBAMIndex { */ private long position() { try { - return bufferedStream.position(); + return fileChannel.position(); } catch (IOException exc) { throw new ReviewedStingException("Unable to read position from index file " + mFile, exc); diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java index 76654fb74..a6191802b 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/qc/PileupWalkerIntegrationTest.java @@ -31,9 +31,6 @@ import org.testng.annotations.Test; import java.util.Arrays; public class PileupWalkerIntegrationTest extends WalkerTest { - String gatkSpeedupArgs="-T Pileup -I " + validationDataLocation + "NA12878.HiSeq.WGS.bwa.cleaned.recal.hg19.20.bam " - + "-R " + hg19Reference + " -o %s "; - @Test public void testGnarleyFHSPileup() { String gatk_args = "-T Pileup -I " + validationDataLocation + "FHS_Pileup_Test.bam " @@ -67,31 +64,4 @@ public class PileupWalkerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec(gatk_args, 1, Arrays.asList(SingleReadAligningOffChromosome1MD5)); executeTest("Testing single read spanning off chromosome 1 unindexed", spec); } - - /************************/ - - //testing speedup to GATKBAMIndex - - - @Test - public void testPileupOnLargeBamChr20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:1-76,050", 1, Arrays.asList("8702701350de11a6d28204acefdc4775")); - executeTest("Testing single on big BAM at start of chromosome 20", spec); - } - @Test - public void testPileupOnLargeBamMid20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:10,000,000-10,001,100", 1, Arrays.asList("818cf5a8229efe6f89fc1cd8145ccbe3")); - executeTest("Testing single on big BAM somewhere in chromosome 20", spec); - } - @Test - public void testPileupOnLargeBamEnd20(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:62,954,114-63,025,520", 1, Arrays.asList("22471ea4a12e5139aef62bf8ff2a5b63")); - executeTest("Testing single at end of chromosome 20", spec); - } - @Test - public void testPileupOnLargeBam20Many(){ - WalkerTestSpec spec = new WalkerTestSpec(gatkSpeedupArgs + "-L 20:1-76,050 -L 20:20,000,000-20,000,100 -L 20:40,000,000-40,000,100 -L 20:30,000,000-30,000,100 -L 20:50,000,000-50,000,100 -L 20:62,954,114-63,025,520 ", - 1, Arrays.asList("08d899ed7c5a76ef3947bf67338acda1")); - executeTest("Testing single on big BAM many places", spec); - } } From 4c0a3b182e2fa7454713f5070c5bfd78d3447380 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Fri, 1 Feb 2013 12:14:31 -0500 Subject: [PATCH 169/188] Update MD5s to reflect version number change in the BAM header I've confirmed via a script that all of these differences only involve the version number bump in the BAM headers and nothing else: < @HD VN:1.0 GO:none SO:coordinate --- > @HD VN:1.4 GO:none SO:coordinate --- .../walkers/bqsr/BQSRIntegrationTest.java | 8 +++--- .../indels/IndelRealignerIntegrationTest.java | 12 ++++----- .../gatk/walkers/BAQIntegrationTest.java | 4 +-- .../ClipReadsWalkersIntegrationTest.java | 26 +++++++++---------- .../readutils/PrintReadsIntegrationTest.java | 20 +++++++------- .../utils/crypt/GATKKeyIntegrationTest.java | 2 +- .../interval/IntervalIntegrationTest.java | 4 +-- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java index 1f4875298..f7907649d 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRIntegrationTest.java @@ -188,12 +188,12 @@ public class BQSRIntegrationTest extends WalkerTest { public Object[][] createPRTestData() { List tests = new ArrayList(); - tests.add(new Object[]{1, new PRTest(" -qq -1", "b8d296fb78adc5cff7ce12073a69d985")}); - tests.add(new Object[]{1, new PRTest(" -qq 6", "2ee0cedf84c1a33a807438172bc36c11")}); - tests.add(new Object[]{1, new PRTest(" -DIQ", "46cf74900bf8b13438e6a195b3085c48")}); + tests.add(new Object[]{1, new PRTest(" -qq -1", "fcc136b877fbde38791533b0f1ae39e4")}); + tests.add(new Object[]{1, new PRTest(" -qq 6", "f21b537c1689b8051b878ea5cc9b61a0")}); + tests.add(new Object[]{1, new PRTest(" -DIQ", "1d04a242bf825177d6a45eff9fbed647")}); for ( final int nct : Arrays.asList(1, 2, 4) ) { - tests.add(new Object[]{nct, new PRTest("", "88b88f006ebb1aade85089bfba5a9e8d")}); + tests.add(new Object[]{nct, new PRTest("", "b6f343ac69c63cdb49205c13e67297fc")}); } return tests.toArray(new Object[][]{}); diff --git a/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java b/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java index eba9c7780..275ababda 100644 --- a/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java +++ b/protected/java/test/org/broadinstitute/sting/gatk/walkers/indels/IndelRealignerIntegrationTest.java @@ -60,8 +60,8 @@ public class IndelRealignerIntegrationTest extends WalkerTest { private static final String knownIndels = validationDataLocation + "indelRealignerTest.pilot1.ceu.vcf"; private static final String baseCommandPrefix = "-T IndelRealigner -noPG -R " + b36KGReference + " -I " + mainTestBam + " -targetIntervals " + mainTestIntervals + " -compress 0 -L 20:49,500-55,500 "; private static final String baseCommand = baseCommandPrefix + "-o %s "; - private static final String base_md5 = "7574ab7d0b1ee5d44a0b3f85b6e944e6"; - private static final String base_md5_with_SW_or_VCF = "a918d69d26d3c87b29002ed31f428c48"; + private static final String base_md5 = "a102dd55451799e5f053c784b762087e"; + private static final String base_md5_with_SW_or_VCF = "06b8eefcbd785e929027feaa22bb060d"; @Test public void testDefaults() { @@ -84,7 +84,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec1 = new WalkerTestSpec( baseCommand + "--consensusDeterminationModel KNOWNS_ONLY -known " + knownIndels, 1, - Arrays.asList("36718f10d523dfb0fa2a709480f24bd4")); + Arrays.asList("1b24b0f2a20aed1adc726d1b296a3192")); executeTest("realigner known indels only from VCF", spec1); } @@ -101,7 +101,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { public void testLods() { HashMap e = new HashMap(); e.put( "-LOD 60", base_md5 ); - e.put( "-LOD 1 --consensusDeterminationModel USE_SW", "9a75a0f7ad0442c78d0f8df260e733a4" ); + e.put( "-LOD 1 --consensusDeterminationModel USE_SW", "4bf28d3c0337682d439257874377a681" ); for ( Map.Entry entry : e.entrySet() ) { WalkerTest.WalkerTestSpec spec = new WalkerTest.WalkerTestSpec( @@ -117,7 +117,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec( "-T IndelRealigner -noPG -R " + b36KGReference + " -I " + validationDataLocation + "NA12878.chrom1.SLX.SRP000032.2009_06.bam -L 1:10,000,000-11,000,000 -targetIntervals " + validationDataLocation + "indelRealignerTest.NA12878.chrom1.intervals -compress 0 -o %s", 1, - Arrays.asList("e98f51d71f0a82141b36a7e9f94db237")); + Arrays.asList("f4f6c3b2a2be0306a0ecd3def334bafe")); executeTest("realigner long run", spec); } @@ -126,7 +126,7 @@ public class IndelRealignerIntegrationTest extends WalkerTest { WalkerTestSpec spec = new WalkerTestSpec( baseCommand + "--noOriginalAlignmentTags --consensusDeterminationModel USE_SW", 1, - Arrays.asList("58ac675d0699eb236d469b8e84513d11")); + Arrays.asList("71fb521f8febfe2dc683fc636e28ae7d")); executeTest("realigner no output tags", spec); } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java index 13cd2be73..6b0422c6a 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/BAQIntegrationTest.java @@ -43,13 +43,13 @@ public class BAQIntegrationTest extends WalkerTest { // -------------------------------------------------------------------------------------------------------------- @Test public void testPrintReadsNoBAQ() { - WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq OFF", 1, Arrays.asList("d97340a2bba2c6320d1ebeb86024a27c")); + WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq OFF", 1, Arrays.asList("11af64ba020262d06b490bae2c5e08f8")); executeTest(String.format("testPrintReadsNoBAQ"), spec); } @Test public void testPrintReadsRecalBAQ() { - WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq RECALCULATE", 1, Arrays.asList("4ac691bde1ba1301a59857694fda6ae2")); + WalkerTestSpec spec = new WalkerTestSpec( baseCommand +" -baq RECALCULATE", 1, Arrays.asList("96ec97cf92f1f660bd5244c6b44539b3")); executeTest(String.format("testPrintReadsRecalBAQ"), spec); } } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java index ae4bce81b..b3d583ef1 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/ClipReadsWalkersIntegrationTest.java @@ -47,22 +47,22 @@ public class ClipReadsWalkersIntegrationTest extends WalkerTest { } final static String Q10ClipOutput = "b29c5bc1cb9006ed9306d826a11d444f"; - @Test public void testQClip0() { testClipper("clipQSum0", "-QT 0", "117a4760b54308f81789c39b1c9de578", "33e781084379aae538954e30919e8fd3"); } - @Test public void testQClip2() { testClipper("clipQSum2", "-QT 2", Q10ClipOutput, "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testQClip10() { testClipper("clipQSum10", "-QT 10", "b29c5bc1cb9006ed9306d826a11d444f", "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testQClip20() { testClipper("clipQSum20", "-QT 20", "6c3434dce66ae5c9eeea502f10fb9bee", "67263a39d5127f2660a5b638ff32056a"); } + @Test public void testQClip0() { testClipper("clipQSum0", "-QT 0", "117a4760b54308f81789c39b1c9de578", "12be03c817d94bab88457e5afe74256a"); } + @Test public void testQClip2() { testClipper("clipQSum2", "-QT 2", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testQClip10() { testClipper("clipQSum10", "-QT 10", "b29c5bc1cb9006ed9306d826a11d444f", "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testQClip20() { testClipper("clipQSum20", "-QT 20", "6c3434dce66ae5c9eeea502f10fb9bee", "0bcfd177fe4be422898eda8e161ebd6c"); } - @Test public void testClipRange1() { testClipper("clipRange1", "-CT 1-5", "b5acd753226e25b1e088838c1aab9117", "764846d0592f346a33525af674fd7a10"); } - @Test public void testClipRange2() { testClipper("clipRange2", "-CT 1-5,11-15", "be4fcad5b666a5540028b774169cbad7", "3061cf742f9e5526a61130128ae761a3"); } + @Test public void testClipRange1() { testClipper("clipRange1", "-CT 1-5", "b5acd753226e25b1e088838c1aab9117", "aed836c97c6383dd80e39a093cc25e08"); } + @Test public void testClipRange2() { testClipper("clipRange2", "-CT 1-5,11-15", "be4fcad5b666a5540028b774169cbad7", "5f6e08bd44d6faf5b85cde5d4ec1a36f"); } - @Test public void testClipSeq() { testClipper("clipSeqX", "-X CCCCC", "db199bd06561c9f2122f6ffb07941fbc", "b89459f373e40f0b835c1faff2208839"); } - @Test public void testClipSeqFile() { testClipper("clipSeqXF", "-XF " + privateTestDir + "seqsToClip.fasta", "d011a3152b31822475afbe0281491f8d", "24e19116ef16a37a6d095ed5c22c2466"); } + @Test public void testClipSeq() { testClipper("clipSeqX", "-X CCCCC", "db199bd06561c9f2122f6ffb07941fbc", "f3cb42759428df80d06e9789f9f9f762"); } + @Test public void testClipSeqFile() { testClipper("clipSeqXF", "-XF " + privateTestDir + "seqsToClip.fasta", "d011a3152b31822475afbe0281491f8d", "44658c018378467f809b443d047d5778"); } - @Test public void testClipMulti() { testClipper("clipSeqMulti", "-QT 10 -CT 1-5 -XF " + privateTestDir + "seqsToClip.fasta -X CCCCC", "a23187bd9bfb06557f799706d98441de", "ad8d30300cb43d5e300fcc4d2450da8e"); } + @Test public void testClipMulti() { testClipper("clipSeqMulti", "-QT 10 -CT 1-5 -XF " + privateTestDir + "seqsToClip.fasta -X CCCCC", "a23187bd9bfb06557f799706d98441de", "bae38f83eb9b63857f5e6e3c6e62f80c"); } - @Test public void testClipNs() { testClipper("testClipNs", "-QT 10 -CR WRITE_NS", Q10ClipOutput, "57c05b6241db7110148a91fde2d431d0"); } - @Test public void testClipQ0s() { testClipper("testClipQs", "-QT 10 -CR WRITE_Q0S", Q10ClipOutput, "2a1a3153e0942ab355fd8a6e082b30e0"); } - @Test public void testClipSoft() { testClipper("testClipSoft", "-QT 10 -CR SOFTCLIP_BASES", Q10ClipOutput, "50d43d63d8e39f67a87a6359963c6f52"); } + @Test public void testClipNs() { testClipper("testClipNs", "-QT 10 -CR WRITE_NS", Q10ClipOutput, "1cfc9da4867765c1e5b5bd6326984634"); } + @Test public void testClipQ0s() { testClipper("testClipQs", "-QT 10 -CR WRITE_Q0S", Q10ClipOutput, "3b32da2eaab7a2d4729fdb486cedbb2f"); } + @Test public void testClipSoft() { testClipper("testClipSoft", "-QT 10 -CR SOFTCLIP_BASES", Q10ClipOutput, "9d355b0f6d2076178e92bd7fcd8f5adb"); } @Test public void testUseOriginalQuals() { @@ -74,7 +74,7 @@ public class ClipReadsWalkersIntegrationTest extends WalkerTest { " -OQ -QT 4 -CR WRITE_Q0S" + " -o %s -os %s", 2, - Arrays.asList("22db22749f811d30216215e047461621", "55c01ccc2e84481b22d3632cdb06c8ba")); + Arrays.asList("c83b4e2ade8654a2818fe9d405f07662", "55c01ccc2e84481b22d3632cdb06c8ba")); executeTest("clipOriginalQuals", spec); } } diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java index 83f801a98..b509fc1df 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/readutils/PrintReadsIntegrationTest.java @@ -54,17 +54,17 @@ public class PrintReadsIntegrationTest extends WalkerTest { @DataProvider(name = "PRTest") public Object[][] createPrintReadsTestData() { return new Object[][]{ - {new PRTest(hg18Reference, "HiSeq.1mb.bam", "", "dc8e5451dd29757c336013146010f73a")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -compress 0", "fde82269c78c9e91e57286433531b4af")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -simplifyBAM", "0531717b32a7e21c0de70b1526b0751f")}, - {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -n 10", "cdc4ddf9ee1d2ecf37168da8ef23c270")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", "", "fa9c66f66299fe5405512ac36ec9d0f2")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -compress 0", "488eb22abc31c6af7cbb1a3d41da1507")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -simplifyBAM", "1510dc4429f3ed49caf96da41e8ed396")}, + {new PRTest(hg18Reference, "HiSeq.1mb.bam", " -n 10", "0e3d1748ad1cb523e3295cab9d09d8fc")}, // See: GATKBAMIndex.getStartOfLastLinearBin(), BAMScheduler.advance(), IntervalOverlapFilteringIterator.advance() - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", "", "0a9ce949d07a84cb33a1a8e3358bf679")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1", "6e920b8505e7e95d67634b0905237dbc")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L unmapped", "13bb9a91b1d4dd2425f73302b8a1ac1c")}, - {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1 -L unmapped", "6e920b8505e7e95d67634b0905237dbc")}, - {new PRTest(b37KGReference, "oneReadAllInsertion.bam", "", "6caec4f8a25befb6aba562955401af93")}, - {new PRTest(b37KGReference, "NA12878.1_10mb_2_10mb.bam", "", "c43380ac39b98853af457b90e52f8427")} + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", "", "e1cac555f3d720f611c47eec93e84bd9")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1", "6e2558317d409195eab3006dc9e5524c")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L unmapped", "2d32440e47e8d9d329902fe573ad94ce")}, + {new PRTest(b37KGReference, "unmappedFlagReadsInLastLinearBin.bam", " -L 1 -L unmapped", "6e2558317d409195eab3006dc9e5524c")}, + {new PRTest(b37KGReference, "oneReadAllInsertion.bam", "", "349650b6aa9e574b48a2a62627f37c7d")}, + {new PRTest(b37KGReference, "NA12878.1_10mb_2_10mb.bam", "", "0c1cbe67296637a85e80e7a182f828ab")} }; } diff --git a/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java b/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java index 7421767c7..9c9248669 100644 --- a/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/crypt/GATKKeyIntegrationTest.java @@ -38,7 +38,7 @@ public class GATKKeyIntegrationTest extends WalkerTest { public static final String BASE_COMMAND = String.format("-T PrintReads -R %s -I %s -o %%s", publicTestDir + "exampleFASTA.fasta", publicTestDir + "exampleBAM.bam"); - public static final String MD5_UPON_SUCCESSFUL_RUN = "b9dc5bf6753ca2819e70b056eaf61258"; + public static final String MD5_UPON_SUCCESSFUL_RUN = "e7b4a5b62f9d4badef1cd07040011b2b"; private void runGATKKeyTest ( String testName, String etArg, String keyArg, Class expectedException, String md5 ) { diff --git a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java index dc8a31945..98ecd0f43 100644 --- a/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/interval/IntervalIntegrationTest.java @@ -78,7 +78,7 @@ public class IntervalIntegrationTest extends WalkerTest { // our base file File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam"); spec.setOutputFileLocation(baseOutputFile); - spec.addAuxFile("748a38ed5eb0a043dfc7b82f0d1e8063",createTempFileFromBase(baseOutputFile.getAbsolutePath())); + spec.addAuxFile("95e98192e5b90cf80eaa87a4ace263da",createTempFileFromBase(baseOutputFile.getAbsolutePath())); spec.addAuxFile("fadcdf88597b9609c5f2a17f4c6eb455", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai")); executeTest("testUnmappedReadInclusion",spec); @@ -99,7 +99,7 @@ public class IntervalIntegrationTest extends WalkerTest { // our base file File baseOutputFile = createTempFile("testUnmappedReadInclusion",".bam"); spec.setOutputFileLocation(baseOutputFile); - spec.addAuxFile("083ef1e9ded868e0d12c05a1354c0319",createTempFileFromBase(baseOutputFile.getAbsolutePath())); + spec.addAuxFile("3944b5a6bfc06277ed3afb928a20d588",createTempFileFromBase(baseOutputFile.getAbsolutePath())); spec.addAuxFile("fa90ff91ac0cc689c71a3460a3530b8b", createTempFileFromBase(baseOutputFile.getAbsolutePath().substring(0,baseOutputFile.getAbsolutePath().indexOf(".bam"))+".bai")); executeTest("testUnmappedReadInclusion",spec); From e07cefb058c25ce2cc5391a62b65ba968b29faa2 Mon Sep 17 00:00:00 2001 From: Ryan Poplin Date: Thu, 31 Jan 2013 15:57:48 -0500 Subject: [PATCH 170/188] Updating AlignmentUtils.consolidateCigar() to the GATK coding standards. --- .../org/broadinstitute/sting/utils/sam/AlignmentUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java index d270f251d..8c6059d08 100644 --- a/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/sam/AlignmentUtils.java @@ -508,12 +508,13 @@ public class AlignmentUtils { * For example, 1M1M1M1D2M1M --> 3M1D3M * If the given cigar is empty then the returned cigar will also be empty * @param c the cigar to consolidate - * @return a cigar with consecutive matching operators merged into single operators. + * @return a non-null cigar with consecutive matching operators merged into single operators. */ - @Requires({"c != null"}) @Ensures({"result != null"}) public static Cigar consolidateCigar( final Cigar c ) { + if( c == null ) { throw new IllegalArgumentException("Cigar cannot be null"); } if( c.isEmpty() ) { return c; } + final Cigar returnCigar = new Cigar(); int sumLength = 0; for( int iii = 0; iii < c.numCigarElements(); iii++ ) { From 292037dfda88fc379b2c1f8db54028dc8bd116a3 Mon Sep 17 00:00:00 2001 From: David Roazen Date: Thu, 31 Jan 2013 16:00:13 -0500 Subject: [PATCH 171/188] Rev picard, sam-jdk, and tribble This is a necessary prerequisite for the org.broadinstitute.variant migration. -Picard and sam-jdk go from version 1.67.1197 to 1.84.1337 -Picard-private goes from version 2375 to 2662 -Tribble goes from version 119 to 1.84.1337 -RADICALLY trimmed down the list of classes we extract from Picard-private (jar goes from 326993 bytes to 6445 bytes!) --- .../gatk/datasources/reads/BlockLoader.java | 2 +- .../gatk/datasources/reads/GATKBAMIndex.java | 4 ++-- .../variant/vcf/AbstractVCFCodec.java | 2 +- public/packages/PicardPrivate.xml | 17 ----------------- .../picard-private-parts-2375.jar | Bin 326993 -> 0 bytes .../picard-private-parts-2662.jar | Bin 0 -> 6445 bytes ...2375.xml => picard-private-parts-2662.xml} | 2 +- .../repository/net.sf/picard-1.67.1197.xml | 3 --- ...ard-1.67.1197.jar => picard-1.84.1337.jar} | Bin 1373399 -> 1525728 bytes .../repository/net.sf/picard-1.84.1337.xml | 3 +++ settings/repository/net.sf/sam-1.67.1197.xml | 3 --- .../{sam-1.67.1197.jar => sam-1.84.1337.jar} | Bin 573202 -> 615411 bytes settings/repository/net.sf/sam-1.84.1337.xml | 3 +++ ...{tribble-119.jar => tribble-1.84.1337.jar} | Bin 319935 -> 259515 bytes .../org.broad/tribble-1.84.1337.xml | 3 +++ settings/repository/org.broad/tribble-119.xml | 3 --- 16 files changed, 14 insertions(+), 31 deletions(-) delete mode 100644 settings/repository/edu.mit.broad/picard-private-parts-2375.jar create mode 100644 settings/repository/edu.mit.broad/picard-private-parts-2662.jar rename settings/repository/edu.mit.broad/{picard-private-parts-2375.xml => picard-private-parts-2662.xml} (58%) delete mode 100644 settings/repository/net.sf/picard-1.67.1197.xml rename settings/repository/net.sf/{picard-1.67.1197.jar => picard-1.84.1337.jar} (61%) create mode 100644 settings/repository/net.sf/picard-1.84.1337.xml delete mode 100644 settings/repository/net.sf/sam-1.67.1197.xml rename settings/repository/net.sf/{sam-1.67.1197.jar => sam-1.84.1337.jar} (67%) create mode 100644 settings/repository/net.sf/sam-1.84.1337.xml rename settings/repository/org.broad/{tribble-119.jar => tribble-1.84.1337.jar} (51%) create mode 100644 settings/repository/org.broad/tribble-1.84.1337.xml delete mode 100644 settings/repository/org.broad/tribble-119.xml diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java index 428b7355c..72b778ec9 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/BlockLoader.java @@ -25,7 +25,7 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import org.broad.tribble.util.BlockCompressedStreamConstants; +import net.sf.samtools.util.BlockCompressedStreamConstants; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.FileInputStream; diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java index 9cf0a9493..1cfb527cd 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java +++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/GATKBAMIndex.java @@ -25,8 +25,8 @@ package org.broadinstitute.sting.gatk.datasources.reads; -import org.broad.tribble.util.SeekableBufferedStream; -import org.broad.tribble.util.SeekableFileStream; +import net.sf.samtools.seekablestream.SeekableBufferedStream; +import net.sf.samtools.seekablestream.SeekableFileStream; import net.sf.samtools.*; diff --git a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java index 11d152e65..a4ccd050a 100644 --- a/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java +++ b/public/java/src/org/broadinstitute/variant/vcf/AbstractVCFCodec.java @@ -30,7 +30,7 @@ import org.broad.tribble.Feature; import org.broad.tribble.NameAwareCodec; import org.broad.tribble.TribbleException; import org.broad.tribble.readers.LineReader; -import org.broad.tribble.util.BlockCompressedInputStream; +import net.sf.samtools.util.BlockCompressedInputStream; import org.broad.tribble.util.ParsingUtils; import org.broadinstitute.variant.utils.GeneralUtils; import org.broadinstitute.variant.variantcontext.*; diff --git a/public/packages/PicardPrivate.xml b/public/packages/PicardPrivate.xml index a800294d6..d898a5d07 100644 --- a/public/packages/PicardPrivate.xml +++ b/public/packages/PicardPrivate.xml @@ -2,26 +2,9 @@ - - - - - - - - - - - - - - - - - diff --git a/settings/repository/edu.mit.broad/picard-private-parts-2375.jar b/settings/repository/edu.mit.broad/picard-private-parts-2375.jar deleted file mode 100644 index bfa2f65ad9fd5539fa8fe4a4dcdbed2e42a87d5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326993 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 z 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%0Ai~p#U{}s@ulF!pR#9wA)xE8EOKFi=xo^qSM2r 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 I2Xye}&;S4c literal 0 HcmV?d00001 diff --git a/settings/repository/edu.mit.broad/picard-private-parts-2375.xml b/settings/repository/edu.mit.broad/picard-private-parts-2662.xml similarity index 58% rename from settings/repository/edu.mit.broad/picard-private-parts-2375.xml rename to settings/repository/edu.mit.broad/picard-private-parts-2662.xml index b467f934a..119255e8d 100644 --- a/settings/repository/edu.mit.broad/picard-private-parts-2375.xml +++ b/settings/repository/edu.mit.broad/picard-private-parts-2662.xml @@ -1,3 +1,3 @@ - + diff --git a/settings/repository/net.sf/picard-1.67.1197.xml b/settings/repository/net.sf/picard-1.67.1197.xml deleted file mode 100644 index 7d9042d6b..000000000 --- a/settings/repository/net.sf/picard-1.67.1197.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/settings/repository/net.sf/picard-1.67.1197.jar b/settings/repository/net.sf/picard-1.84.1337.jar similarity index 61% rename from settings/repository/net.sf/picard-1.67.1197.jar rename to settings/repository/net.sf/picard-1.84.1337.jar index 9243c02df6a34d312e1ae1673ee6e938b0113ac8..68db4184822193ef73c7859b80e9c17982343b4c 100644 GIT binary patch delta 323680 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