From 6868ce988fdc1ab7450af1db7ddc618690b4be3a Mon Sep 17 00:00:00 2001 From: hanna Date: Tue, 11 May 2010 17:31:19 +0000 Subject: [PATCH] Fix hanging bug reported by Susanne Pfeifer (tiffy @ get satisfaction) where, if the last read(s) in a shard all have an indel in roughly the same location and that indel isn't covered by any other reads, LocusIteratorByState goes into an infinite loop. git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3348 348d0f76-0448-11de-a6fe-93d51630548a --- .../gatk/iterators/LocusIteratorByState.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/java/src/org/broadinstitute/sting/gatk/iterators/LocusIteratorByState.java b/java/src/org/broadinstitute/sting/gatk/iterators/LocusIteratorByState.java index f43616c71..e98ca7ba5 100755 --- a/java/src/org/broadinstitute/sting/gatk/iterators/LocusIteratorByState.java +++ b/java/src/org/broadinstitute/sting/gatk/iterators/LocusIteratorByState.java @@ -250,6 +250,7 @@ public class LocusIteratorByState extends LocusIterator { //final boolean DEBUG = false; //final boolean DEBUG2 = false && DEBUG; private Reads readInfo; + private AlignmentContext nextAlignmentContext; // ----------------------------------------------------------------------------------------------------------------- // @@ -271,7 +272,8 @@ public class LocusIteratorByState extends LocusIterator { } public boolean hasNext() { - boolean r = ! readStates.isEmpty() || it.hasNext(); + lazyLoadNextAlignmentContext(); + boolean r = (nextAlignmentContext != null); //if ( DEBUG ) System.out.printf("hasNext() = %b%n", r); // if we don't have a next record, make sure we clean the warning queue @@ -303,12 +305,20 @@ public class LocusIteratorByState extends LocusIterator { // // ----------------------------------------------------------------------------------------------------------------- public AlignmentContext next() { - // keep iterating forward until we encounter a reference position that has something "real" hanging over it - // (i.e. either a real base, or a real base or a deletion if includeReadsWithDeletion is true) - - - while(true) { + lazyLoadNextAlignmentContext(); + if(!hasNext()) + throw new NoSuchElementException("LocusIteratorByState: out of elements."); + AlignmentContext currentAlignmentContext = nextAlignmentContext; + nextAlignmentContext = null; + return currentAlignmentContext; + } + /** + * Creates the next alignment context from the given state. Note that this is implemented as a lazy load method. + * nextAlignmentContext MUST BE null in order for this method to advance to the next entry. + */ + private void lazyLoadNextAlignmentContext() { + while(nextAlignmentContext == null && (!readStates.isEmpty() || it.hasNext())) { // this call will set hasExtendedEvents to true if it picks up a read with indel right before the current position on the ref: collectPendingReads(readInfo.getMaxReadsAtLocus()); @@ -318,12 +328,12 @@ public class LocusIteratorByState extends LocusIterator { int nMQ0Reads = 0; - // if extended events are requested, and if previous traversal step brought us over an indel in + // if extended events are requested, and if previous traversal step brought us over an indel in // at least one read, we emit extended pileup (making sure that it is associated with the previous base, // i.e. the one right *before* the indel) and do NOT shift the current position on the ref. // In this case, the subsequent call to next() will emit the normal pileup at the current base // and shift the position. - if ( readInfo.generateExtendedEvents() && hasExtendedEvents ) { + if (readInfo.generateExtendedEvents() && hasExtendedEvents) { ArrayList indelPile = new ArrayList(readStates.size()); int maxDeletionLength = 0; @@ -370,12 +380,10 @@ public class LocusIteratorByState extends LocusIterator { GenomeLoc loc = GenomeLocParser.incPos(our1stState.getLocation(),-1); // System.out.println("Indel(s) at "+loc); // for ( ExtendedEventPileupElement pe : indelPile ) { if ( pe.isIndel() ) System.out.println(" "+pe.toString()); } - return new AlignmentContext(loc, new ReadBackedExtendedEventPileup(loc, indelPile, size, maxDeletionLength, nInsertions, nDeletions, nMQ0Reads)); + nextAlignmentContext = new AlignmentContext(loc, new ReadBackedExtendedEventPileup(loc, indelPile, size, maxDeletionLength, nInsertions, nDeletions, nMQ0Reads)); } else { - ArrayList pile = new ArrayList(readStates.size()); - // todo -- performance problem -- should be lazy, really for ( SAMRecordState state : readStates ) { if ( state.getCurrentCigarOperator() != CigarOperator.D && state.getCurrentCigarOperator() != CigarOperator.N ) { @@ -398,9 +406,8 @@ public class LocusIteratorByState extends LocusIterator { GenomeLoc loc = getLocation(); updateReadStates(); // critical - must be called after we get the current state offsets and location // if we got reads with non-D/N over the current position, we are done - if ( pile.size() != 0 ) return new AlignmentContext(loc, new ReadBackedPileup(loc, pile, size, nDeletions, nMQ0Reads)); + if ( pile.size() != 0 ) nextAlignmentContext = new AlignmentContext(loc, new ReadBackedPileup(loc, pile, size, nDeletions, nMQ0Reads)); } - } }