diff --git a/java/src/org/broadinstitute/sting/gatk/contexts/StratifiedAlignmentContext.java b/java/src/org/broadinstitute/sting/gatk/contexts/StratifiedAlignmentContext.java index afa03c600..24335a50e 100755 --- a/java/src/org/broadinstitute/sting/gatk/contexts/StratifiedAlignmentContext.java +++ b/java/src/org/broadinstitute/sting/gatk/contexts/StratifiedAlignmentContext.java @@ -29,14 +29,9 @@ import net.sf.samtools.SAMRecord; import net.sf.samtools.SAMReadGroupRecord; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.StingException; -import org.broadinstitute.sting.utils.pileup.ReadBackedPileup; -import org.broadinstitute.sting.utils.pileup.PileupElement; -import org.broadinstitute.sting.utils.pileup.ReadBackedExtendedEventPileup; +import org.broadinstitute.sting.utils.pileup.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Collection; +import java.util.*; /** * Useful class for storing different AlignmentContexts @@ -54,45 +49,97 @@ public class StratifiedAlignmentContext { private GenomeLoc loc; private AlignmentContext[] contexts = new AlignmentContext[StratifiedContextType.values().length]; + private boolean isExtended = false; // tells whether this alignment context is an extended event context // todo -- why are you storing reads separately each time? There's a ReadBackedPileup object that's supposed to handle this - private ArrayList[] reads = new ArrayList[StratifiedContextType.values().length]; - private ArrayList[] offsets = new ArrayList[StratifiedContextType.values().length]; +// private ArrayList[] reads = new ArrayList[StratifiedContextType.values().length]; +// private ArrayList[] offsets = new ArrayList[StratifiedContextType.values().length]; + private ArrayList[] pileupElems = new ArrayList[StratifiedContextType.values().length]; // // accessors // public GenomeLoc getLocation() { return loc; } - public ArrayList getReads(StratifiedContextType type) { return reads[type.ordinal()]; } - public ArrayList getOffsets(StratifiedContextType type) { return offsets[type.ordinal()]; } +// public ArrayList getReads(StratifiedContextType type) { return reads[type.ordinal()]; } +// public ArrayList getOffsets(StratifiedContextType type) { return offsets[type.ordinal()]; } + + public ArrayList getPileupElements(StratifiedContextType type) { + return pileupElems[type.ordinal()]; + } + +// public ArrayList getExtendedPileupElements(StratifiedContextType type) { +// if ( ! isExtended ) throw new StingException("Extended read backed pileups requested from StratifiedAlignmentContext that holds simple pileups"); +// +// return (ArrayList)(pileupElems[type.ordinal()]); +// } public StratifiedAlignmentContext(GenomeLoc loc) { + this(loc,false); + } + + public StratifiedAlignmentContext(GenomeLoc loc, boolean isExtended) { this.loc = loc; + this.isExtended = isExtended; for ( int i = 0; i < StratifiedContextType.values().length; i++) { - reads[i] = new ArrayList(); - offsets[i] = new ArrayList(); + if ( isExtended ) pileupElems[i] = new ArrayList(); + else pileupElems[i] = new ArrayList(); } } public AlignmentContext getContext(StratifiedContextType type) { int index = type.ordinal(); - if ( contexts[index] == null ) - contexts[index] = new AlignmentContext(loc, new ReadBackedPileup(loc, getReads(type), getOffsets(type))); + if ( contexts[index] == null ) { + if ( isExtended ) { + contexts[index] = new AlignmentContext(loc , new ReadBackedExtendedEventPileup(loc, (ArrayList)((ArrayList)getPileupElements(type)))); + } else { + contexts[index] = new AlignmentContext(loc, new ReadBackedPileup(loc, getPileupElements(type))); + } + } return contexts[index]; } public void add(SAMRecord read, int offset) { + if ( isExtended ) throw new StingException("Can not add read/offset without event type specified to the context holding extended events"); if ( read.getReadNegativeStrandFlag() ) { - reads[StratifiedContextType.REVERSE.ordinal()].add(read); - offsets[StratifiedContextType.REVERSE.ordinal()].add(offset); + pileupElems[StratifiedContextType.REVERSE.ordinal()].add(new PileupElement(read,offset)); } else { - reads[StratifiedContextType.FORWARD.ordinal()].add(read); - offsets[StratifiedContextType.FORWARD.ordinal()].add(offset); + pileupElems[StratifiedContextType.FORWARD.ordinal()].add(new PileupElement(read,offset)); } - reads[StratifiedContextType.COMPLETE.ordinal()].add(read); - offsets[StratifiedContextType.COMPLETE.ordinal()].add(offset); + pileupElems[StratifiedContextType.COMPLETE.ordinal()].add(new PileupElement(read,offset)); } + public void add(PileupElement p) { +// if ( isExtended ) throw new StingException("Can not add simple pileup element to the context holding extended events"); + SAMRecord read = p.getRead(); + if ( read.getReadNegativeStrandFlag() ) { + pileupElems[StratifiedContextType.REVERSE.ordinal()].add(p); + } else { + pileupElems[StratifiedContextType.FORWARD.ordinal()].add(p); + } + pileupElems[StratifiedContextType.COMPLETE.ordinal()].add(p); + } + + public void add(SAMRecord read, int offset, int length, byte [] bases) { + if ( ! isExtended ) throw new StingException("Can not add read/offset with event type specified to the context holding simple events"); + if ( read.getReadNegativeStrandFlag() ) { + pileupElems[StratifiedContextType.REVERSE.ordinal()].add(new ExtendedEventPileupElement(read,offset,length,bases)); + } else { + pileupElems[StratifiedContextType.FORWARD.ordinal()].add(new ExtendedEventPileupElement(read,offset,length,bases)); + } + pileupElems[StratifiedContextType.COMPLETE.ordinal()].add(new ExtendedEventPileupElement(read,offset,length,bases)); + } + +// public void add(ExtendedEventPileupElement p) { +// if ( ! isExtended ) throw new StingException("Can not add extended pileup element to the context holding simple events"); +// SAMRecord read = p.getRead(); +// if ( read.getReadNegativeStrandFlag() ) { +// pileupElems[StratifiedContextType.REVERSE.ordinal()].add(p); +// } else { +// pileupElems[StratifiedContextType.FORWARD.ordinal()].add(p); +// } +// pileupElems[StratifiedContextType.COMPLETE.ordinal()].add(p); +// } + /** * Splits the given AlignmentContext into a StratifiedAlignmentContext per sample. * @@ -154,12 +201,17 @@ public class StratifiedAlignmentContext { GenomeLoc loc = pileup.getLocation(); for (PileupElement p : pileup ) - addToContext(contexts, p, loc, assumedSingleSample, collapseToThisSample); + addToContext(contexts, p, loc, assumedSingleSample, collapseToThisSample,true); return contexts; } private static void addToContext(HashMap contexts, PileupElement p, GenomeLoc loc, String assumedSingleSample, String collapseToThisSample) { + addToContext(contexts, p, loc, assumedSingleSample, collapseToThisSample, false); + } + + private static void addToContext(HashMap contexts, PileupElement p, GenomeLoc loc, String assumedSingleSample, String collapseToThisSample, boolean isExtended) { + // get the read SAMRecord read = p.getRead(); @@ -181,13 +233,13 @@ public class StratifiedAlignmentContext { // create a new context object if this is the first time we're seeing a read for this sample StratifiedAlignmentContext myContext = contexts.get(sample); if ( myContext == null ) { - myContext = new StratifiedAlignmentContext(loc); + myContext = new StratifiedAlignmentContext(loc,isExtended); contexts.put(sample, myContext); } // add the read to this sample's context // note that bad bases are added to the context (for DoC calculations later) - myContext.add(read, p.getOffset()); + myContext.add(p); } /** @@ -218,25 +270,37 @@ public class StratifiedAlignmentContext { contexts.put(group,myContext); } - myContext.add(read,p.getOffset()); + myContext.add(p); } return contexts; } public static AlignmentContext joinContexts(Collection contexts, StratifiedContextType type) { - ArrayList reads = new ArrayList(); - ArrayList offsets = new ArrayList(); + ArrayList pe = new ArrayList(); - GenomeLoc loc = null; - for ( StratifiedAlignmentContext context : contexts ) { - loc = context.getLocation(); - reads.addAll(context.getReads(type)); - offsets.addAll(context.getOffsets(type)); + if ( contexts.size() == 0 ) + throw new StingException("BUG: joinContexts requires at least one context to join"); + + + Iterator it = contexts.iterator(); + StratifiedAlignmentContext context = it.next(); + boolean isExtended = context.isExtended; + GenomeLoc loc = context.getLocation(); + pe.addAll(context.getPileupElements(type)); + + while ( it.hasNext()) { + context = it.next(); + if ( ! loc.equals( context.getLocation() ) ) + throw new StingException("Illegal attempt to join contexts from different genomic locations"); + if ( context.isExtended != isExtended ) + throw new StingException("Illegal attempt to join simple and extended contexts"); + pe.addAll(context.getPileupElements(type)); } - if ( loc == null ) - throw new StingException("BUG: joinContexts requires at least one context to join"); - return new AlignmentContext(loc, new ReadBackedPileup(loc, reads, offsets)); + // dirty trick below. generics do not allow to cast pe (ArrayList) directly to ArrayList, + // so we first cast to "? extends" wildcard, then to what we actually need. + if ( isExtended ) return new AlignmentContext(loc, new ReadBackedExtendedEventPileup(loc, (ArrayList< ExtendedEventPileupElement>)((ArrayList)pe)) ); + else return new AlignmentContext(loc, new ReadBackedPileup(loc,pe)); } } \ No newline at end of file