Merge branch 'master' of ssh://nickel.broadinstitute.org/humgen/gsa-scr1/gsa-engineering/git/unstable
This commit is contained in:
commit
44f905b5e5
|
|
@ -27,13 +27,16 @@ package org.broadinstitute.sting.gatk.walkers.genotyper;
|
||||||
|
|
||||||
import net.sf.samtools.SAMUtils;
|
import net.sf.samtools.SAMUtils;
|
||||||
import org.broadinstitute.sting.utils.BaseUtils;
|
import org.broadinstitute.sting.utils.BaseUtils;
|
||||||
|
import org.broadinstitute.sting.utils.fragments.FragmentCollection;
|
||||||
|
import org.broadinstitute.sting.utils.fragments.FragmentUtils;
|
||||||
import org.broadinstitute.sting.utils.MathUtils;
|
import org.broadinstitute.sting.utils.MathUtils;
|
||||||
import org.broadinstitute.sting.utils.QualityUtils;
|
import org.broadinstitute.sting.utils.QualityUtils;
|
||||||
import org.broadinstitute.sting.utils.exceptions.UserException;
|
import org.broadinstitute.sting.utils.exceptions.UserException;
|
||||||
import org.broadinstitute.sting.utils.pileup.FragmentPileup;
|
|
||||||
import org.broadinstitute.sting.utils.pileup.PileupElement;
|
import org.broadinstitute.sting.utils.pileup.PileupElement;
|
||||||
import org.broadinstitute.sting.utils.pileup.ReadBackedPileup;
|
import org.broadinstitute.sting.utils.pileup.ReadBackedPileup;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.Math.log10;
|
import static java.lang.Math.log10;
|
||||||
import static java.lang.Math.pow;
|
import static java.lang.Math.pow;
|
||||||
|
|
||||||
|
|
@ -259,16 +262,17 @@ public class DiploidSNPGenotypeLikelihoods implements Cloneable {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
// for each fragment, add to the likelihoods
|
// for each fragment, add to the likelihoods
|
||||||
FragmentPileup fpile = new FragmentPileup(pileup);
|
FragmentCollection<PileupElement> fpile = pileup.toFragments();
|
||||||
|
|
||||||
for ( PileupElement p : fpile.getOneReadPileup() )
|
for ( PileupElement p : fpile.getSingletonReads() )
|
||||||
n += add(p, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
n += add(p, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
||||||
|
|
||||||
for ( FragmentPileup.TwoReadPileupElement twoRead : fpile.getTwoReadPileup() )
|
for ( List<PileupElement> overlappingPair : fpile.getOverlappingPairs() )
|
||||||
n += add(twoRead, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
n += add(overlappingPair, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int add(PileupElement elt, boolean ignoreBadBases, boolean capBaseQualsAtMappingQual, int minBaseQual) {
|
public int add(PileupElement elt, boolean ignoreBadBases, boolean capBaseQualsAtMappingQual, int minBaseQual) {
|
||||||
byte obsBase = elt.getBase();
|
byte obsBase = elt.getBase();
|
||||||
|
|
||||||
|
|
@ -286,11 +290,14 @@ public class DiploidSNPGenotypeLikelihoods implements Cloneable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int add(FragmentPileup.TwoReadPileupElement twoRead, boolean ignoreBadBases, boolean capBaseQualsAtMappingQual, int minBaseQual) {
|
public int add(List<PileupElement> overlappingPair, boolean ignoreBadBases, boolean capBaseQualsAtMappingQual, int minBaseQual) {
|
||||||
final byte observedBase1 = twoRead.getFirst().getBase();
|
final PileupElement p1 = overlappingPair.get(0);
|
||||||
final byte qualityScore1 = qualToUse(twoRead.getFirst(), ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
final PileupElement p2 = overlappingPair.get(1);
|
||||||
final byte observedBase2 = twoRead.getSecond().getBase();
|
|
||||||
final byte qualityScore2 = qualToUse(twoRead.getSecond(), ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
final byte observedBase1 = p1.getBase();
|
||||||
|
final byte qualityScore1 = qualToUse(p1, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
||||||
|
final byte observedBase2 = p2.getBase();
|
||||||
|
final byte qualityScore2 = qualToUse(p2, ignoreBadBases, capBaseQualsAtMappingQual, minBaseQual);
|
||||||
|
|
||||||
if ( qualityScore1 == 0 ) {
|
if ( qualityScore1 == 0 ) {
|
||||||
if ( qualityScore2 == 0 ) // abort early if we didn't see any good bases
|
if ( qualityScore2 == 0 ) // abort early if we didn't see any good bases
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,9 @@ public class CountCovariatesWalker extends LocusWalker<CountCovariatesWalker.Cou
|
||||||
*/
|
*/
|
||||||
public void onTraversalDone( CountedData sum ) {
|
public void onTraversalDone( CountedData sum ) {
|
||||||
logger.info( "Writing raw recalibration data..." );
|
logger.info( "Writing raw recalibration data..." );
|
||||||
|
if( sum.countedBases == 0L ) {
|
||||||
|
throw new UserException.BadInput("Could not find any usable data in the input BAM file(s).");
|
||||||
|
}
|
||||||
outputToCSV( sum, RECAL_FILE );
|
outputToCSV( sum, RECAL_FILE );
|
||||||
logger.info( "...done!" );
|
logger.info( "...done!" );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ import org.broadinstitute.sting.commandline.RodBinding;
|
||||||
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
|
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
|
||||||
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
||||||
import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
|
import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
|
||||||
|
import org.broadinstitute.sting.gatk.walkers.PartitionBy;
|
||||||
|
import org.broadinstitute.sting.gatk.walkers.PartitionType;
|
||||||
import org.broadinstitute.sting.gatk.walkers.RodWalker;
|
import org.broadinstitute.sting.gatk.walkers.RodWalker;
|
||||||
import org.broadinstitute.sting.utils.SampleUtils;
|
import org.broadinstitute.sting.utils.SampleUtils;
|
||||||
import org.broadinstitute.sting.utils.codecs.vcf.*;
|
import org.broadinstitute.sting.utils.codecs.vcf.*;
|
||||||
|
|
@ -84,6 +86,7 @@ import java.util.*;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@PartitionBy(PartitionType.NONE)
|
||||||
public class ApplyRecalibration extends RodWalker<Integer, Integer> {
|
public class ApplyRecalibration extends RodWalker<Integer, Integer> {
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ import org.broadinstitute.sting.commandline.*;
|
||||||
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
|
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
|
||||||
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
||||||
import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
|
import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
|
||||||
|
import org.broadinstitute.sting.gatk.walkers.PartitionBy;
|
||||||
|
import org.broadinstitute.sting.gatk.walkers.PartitionType;
|
||||||
import org.broadinstitute.sting.gatk.walkers.RodWalker;
|
import org.broadinstitute.sting.gatk.walkers.RodWalker;
|
||||||
import org.broadinstitute.sting.gatk.walkers.TreeReducible;
|
import org.broadinstitute.sting.gatk.walkers.TreeReducible;
|
||||||
import org.broadinstitute.sting.utils.MathUtils;
|
import org.broadinstitute.sting.utils.MathUtils;
|
||||||
|
|
@ -94,6 +96,7 @@ import java.util.*;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@PartitionBy(PartitionType.NONE)
|
||||||
public class VariantRecalibrator extends RodWalker<ExpandingArrayList<VariantDatum>, ExpandingArrayList<VariantDatum>> implements TreeReducible<ExpandingArrayList<VariantDatum>> {
|
public class VariantRecalibrator extends RodWalker<ExpandingArrayList<VariantDatum>, ExpandingArrayList<VariantDatum>> implements TreeReducible<ExpandingArrayList<VariantDatum>> {
|
||||||
|
|
||||||
public static final String VQS_LOD_KEY = "VQSLOD"; // Log odds ratio of being a true variant versus being false under the trained gaussian mixture model
|
public static final String VQS_LOD_KEY = "VQSLOD"; // Log odds ratio of being a true variant versus being false under the trained gaussian mixture model
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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.fragments;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful helper class to represent the results of the reads -> fragment calculation.
|
||||||
|
*
|
||||||
|
* Contains singleton -- objects whose underlying reads do not overlap their mate pair
|
||||||
|
* Contains overlappingPairs -- objects whose underlying reads do overlap their mate pair
|
||||||
|
*
|
||||||
|
* User: ebanks, depristo
|
||||||
|
* Date: Jan 10, 2011
|
||||||
|
*/
|
||||||
|
public class FragmentCollection<T> {
|
||||||
|
Collection<T> singletons;
|
||||||
|
Collection<List<T>> overlappingPairs;
|
||||||
|
|
||||||
|
public FragmentCollection(final Collection<T> singletons, final Collection<List<T>> overlappingPairs) {
|
||||||
|
this.singletons = singletons == null ? Collections.<T>emptyList() : singletons;
|
||||||
|
this.overlappingPairs = overlappingPairs == null ? Collections.<List<T>>emptyList() : overlappingPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the T elements not containing overlapping elements, in no particular order
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Collection<T> getSingletonReads() {
|
||||||
|
return singletons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the T elements containing overlapping elements, in no particular order
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Collection<List<T>> getOverlappingPairs() {
|
||||||
|
return overlappingPairs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package org.broadinstitute.sting.utils.fragments;
|
||||||
|
|
||||||
|
import net.sf.samtools.SAMRecord;
|
||||||
|
import org.broadinstitute.sting.utils.pileup.PileupElement;
|
||||||
|
import org.broadinstitute.sting.utils.pileup.ReadBackedPileup;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An easy to access fragment-based pileup, which contains two separate pileups. The first
|
||||||
|
* is a regular collection of PileupElements containing all of the reads in the original RBP
|
||||||
|
* that uniquely info about a fragment. The second are TwoReadPileupElements that, as the
|
||||||
|
* name suggests, contain two reads that are sequenced from the same underlying fragment.
|
||||||
|
*
|
||||||
|
* Based on the original code by E. Banks
|
||||||
|
*
|
||||||
|
* Oct 21: note that the order of the oneReadPileup and twoReadPileups are not
|
||||||
|
* defined. The algorithms that produce these lists are in fact producing
|
||||||
|
* lists of Pileup elements *NOT* sorted by alignment start position of the underlying
|
||||||
|
* reads.
|
||||||
|
*
|
||||||
|
* User: depristo
|
||||||
|
* Date: 3/26/11
|
||||||
|
* Time: 10:09 PM
|
||||||
|
*/
|
||||||
|
public class FragmentUtils {
|
||||||
|
private FragmentUtils() {} // private constructor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A getter function that takes an Object of type T and returns its associated SAMRecord.
|
||||||
|
*
|
||||||
|
* Allows us to write a generic T -> Fragment algorithm that works with any object containing
|
||||||
|
* a read.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public interface ReadGetter<T> {
|
||||||
|
public SAMRecord get(T object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Identify getter for SAMRecords themselves */
|
||||||
|
private final static ReadGetter<SAMRecord> SamRecordGetter = new ReadGetter<SAMRecord>() {
|
||||||
|
@Override public SAMRecord get(final SAMRecord object) { return object; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Gets the SAMRecord in a PileupElement */
|
||||||
|
private final static ReadGetter<PileupElement> PileupElementGetter = new ReadGetter<PileupElement>() {
|
||||||
|
@Override public SAMRecord get(final PileupElement object) { return object.getRead(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic algorithm that takes an iterable over T objects, a getter routine to extract the reads in T,
|
||||||
|
* and returns a FragmentCollection that contains the T objects whose underlying reads either overlap (or
|
||||||
|
* not) with their mate pairs.
|
||||||
|
*
|
||||||
|
* @param readContainingObjects
|
||||||
|
* @param nElements
|
||||||
|
* @param getter
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private final static <T> FragmentCollection<T> create(Iterable<T> readContainingObjects, int nElements, ReadGetter<T> getter) {
|
||||||
|
Collection<T> singletons = null;
|
||||||
|
Collection<List<T>> overlapping = null;
|
||||||
|
Map<String, T> nameMap = null;
|
||||||
|
|
||||||
|
int lastStart = -1;
|
||||||
|
|
||||||
|
// build an initial map, grabbing all of the multi-read fragments
|
||||||
|
for ( final T p : readContainingObjects ) {
|
||||||
|
final SAMRecord read = getter.get(p);
|
||||||
|
|
||||||
|
if ( read.getAlignmentStart() < lastStart ) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"FragmentUtils.create assumes that the incoming objects are ordered by " +
|
||||||
|
"SAMRecord alignment start, but saw a read %s with alignment start " +
|
||||||
|
"%d before the previous start %d", read.getSAMString(), read.getAlignmentStart(), lastStart));
|
||||||
|
}
|
||||||
|
lastStart = read.getAlignmentStart();
|
||||||
|
|
||||||
|
final int mateStart = read.getMateAlignmentStart();
|
||||||
|
if ( mateStart == 0 || mateStart > read.getAlignmentEnd() ) {
|
||||||
|
// if we know that this read won't overlap its mate, or doesn't have one, jump out early
|
||||||
|
if ( singletons == null ) singletons = new ArrayList<T>(nElements); // lazy init
|
||||||
|
singletons.add(p);
|
||||||
|
} else {
|
||||||
|
// the read might overlap it's mate, or is the rightmost read of a pair
|
||||||
|
final String readName = read.getReadName();
|
||||||
|
final T pe1 = nameMap == null ? null : nameMap.get(readName);
|
||||||
|
if ( pe1 != null ) {
|
||||||
|
// assumes we have at most 2 reads per fragment
|
||||||
|
if ( overlapping == null ) overlapping = new ArrayList<List<T>>(); // lazy init
|
||||||
|
overlapping.add(Arrays.asList(pe1, p));
|
||||||
|
nameMap.remove(readName);
|
||||||
|
} else {
|
||||||
|
if ( nameMap == null ) nameMap = new HashMap<String, T>(nElements); // lazy init
|
||||||
|
nameMap.put(readName, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add all of the reads that are potentially overlapping but whose mate never showed
|
||||||
|
// up to the oneReadPile
|
||||||
|
if ( nameMap != null && ! nameMap.isEmpty() ) {
|
||||||
|
if ( singletons == null )
|
||||||
|
singletons = nameMap.values();
|
||||||
|
else
|
||||||
|
singletons.addAll(nameMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FragmentCollection<T>(singletons, overlapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static FragmentCollection<PileupElement> create(ReadBackedPileup rbp) {
|
||||||
|
return create(rbp, rbp.size(), PileupElementGetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static FragmentCollection<SAMRecord> create(List<SAMRecord> reads) {
|
||||||
|
return create(reads, reads.size(), SamRecordGetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,8 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine;
|
||||||
import org.broadinstitute.sting.utils.BaseUtils;
|
import org.broadinstitute.sting.utils.BaseUtils;
|
||||||
import org.broadinstitute.sting.utils.GenomeLoc;
|
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||||
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
|
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
|
||||||
|
import org.broadinstitute.sting.utils.fragments.FragmentCollection;
|
||||||
|
import org.broadinstitute.sting.utils.fragments.FragmentUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
@ -871,5 +873,10 @@ public abstract class AbstractReadBackedPileup<RBP extends AbstractReadBackedPil
|
||||||
return quals2String(getQuals());
|
return quals2String(getQuals());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentCollection<PileupElement> toFragments() {
|
||||||
|
return FragmentUtils.create(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
package org.broadinstitute.sting.utils.pileup;
|
|
||||||
|
|
||||||
import net.sf.samtools.SAMRecord;
|
|
||||||
import org.broadinstitute.sting.utils.sam.GATKSAMRecord;
|
|
||||||
import org.broadinstitute.sting.utils.sam.ReadUtils;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An easy to access fragment-based pileup, which contains two separate pileups. The first
|
|
||||||
* is a regular collection of PileupElements containing all of the reads in the original RBP
|
|
||||||
* that uniquely info about a fragment. The second are TwoReadPileupElements that, as the
|
|
||||||
* name suggests, contain two reads that are sequenced from the same underlying fragment.
|
|
||||||
*
|
|
||||||
* Based on the original code by E. Banks
|
|
||||||
*
|
|
||||||
* Oct 21: note that the order of the oneReadPileup and twoReadPileups are not
|
|
||||||
* defined. The algorithms that produce these lists are in fact producing
|
|
||||||
* lists of Pileup elements *NOT* sorted by alignment start position of the underlying
|
|
||||||
* reads.
|
|
||||||
*
|
|
||||||
* User: depristo
|
|
||||||
* Date: 3/26/11
|
|
||||||
* Time: 10:09 PM
|
|
||||||
*/
|
|
||||||
public class FragmentPileup {
|
|
||||||
Collection<PileupElement> oneReadPile = null;
|
|
||||||
Collection<TwoReadPileupElement> twoReadPile = null;
|
|
||||||
|
|
||||||
protected enum FragmentMatchingAlgorithm {
|
|
||||||
ORIGINAL,
|
|
||||||
skipNonOverlapping,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Fragment-based pileup from the standard read-based pileup
|
|
||||||
* @param pileup
|
|
||||||
*/
|
|
||||||
public FragmentPileup(ReadBackedPileup pileup) {
|
|
||||||
skipNonOverlapping(pileup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For performance testing only */
|
|
||||||
protected FragmentPileup(ReadBackedPileup pileup, FragmentMatchingAlgorithm algorithm) {
|
|
||||||
switch ( algorithm ) {
|
|
||||||
case ORIGINAL: oldSlowCalculation(pileup); break;
|
|
||||||
case skipNonOverlapping: skipNonOverlapping(pileup); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void oldSlowCalculation(final ReadBackedPileup pileup) {
|
|
||||||
final Map<String, PileupElement> nameMap = new HashMap<String, PileupElement>(pileup.size());
|
|
||||||
|
|
||||||
// build an initial map, grabbing all of the multi-read fragments
|
|
||||||
for ( final PileupElement p : pileup ) {
|
|
||||||
final String readName = p.getRead().getReadName();
|
|
||||||
|
|
||||||
final PileupElement pe1 = nameMap.get(readName);
|
|
||||||
if ( pe1 != null ) {
|
|
||||||
// assumes we have at most 2 reads per fragment
|
|
||||||
if ( twoReadPile == null ) twoReadPile = new ArrayList<TwoReadPileupElement>();
|
|
||||||
twoReadPile.add(new TwoReadPileupElement(pe1, p));
|
|
||||||
nameMap.remove(readName);
|
|
||||||
} else {
|
|
||||||
nameMap.put(readName, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
oneReadPile = nameMap.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void skipNonOverlapping(final ReadBackedPileup pileup) {
|
|
||||||
Map<String, PileupElement> nameMap = null;
|
|
||||||
|
|
||||||
// build an initial map, grabbing all of the multi-read fragments
|
|
||||||
for ( final PileupElement p : pileup ) {
|
|
||||||
final SAMRecord read = p.getRead();
|
|
||||||
final int mateStart = read.getMateAlignmentStart();
|
|
||||||
|
|
||||||
if ( mateStart == 0 || mateStart > read.getAlignmentEnd() ) {
|
|
||||||
// if we know that this read won't overlap its mate, or doesn't have one, jump out early
|
|
||||||
if ( oneReadPile == null ) oneReadPile = new ArrayList<PileupElement>(pileup.size()); // lazy init
|
|
||||||
oneReadPile.add(p);
|
|
||||||
} else {
|
|
||||||
// the read might overlap it's mate, or is the rightmost read of a pair
|
|
||||||
final String readName = p.getRead().getReadName();
|
|
||||||
final PileupElement pe1 = nameMap == null ? null : nameMap.get(readName);
|
|
||||||
if ( pe1 != null ) {
|
|
||||||
// assumes we have at most 2 reads per fragment
|
|
||||||
if ( twoReadPile == null ) twoReadPile = new ArrayList<TwoReadPileupElement>(); // lazy init
|
|
||||||
twoReadPile.add(new TwoReadPileupElement(pe1, p));
|
|
||||||
nameMap.remove(readName);
|
|
||||||
} else {
|
|
||||||
if ( nameMap == null ) nameMap = new HashMap<String, PileupElement>(pileup.size()); // lazy init
|
|
||||||
nameMap.put(readName, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add all of the reads that are potentially overlapping but whose mate never showed
|
|
||||||
// up to the oneReadPile
|
|
||||||
if ( nameMap != null && ! nameMap.isEmpty() ) {
|
|
||||||
if ( oneReadPile == null )
|
|
||||||
oneReadPile = nameMap.values();
|
|
||||||
else
|
|
||||||
oneReadPile.addAll(nameMap.values());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the pileup elements containing two reads, in no particular order
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<TwoReadPileupElement> getTwoReadPileup() {
|
|
||||||
return twoReadPile == null ? Collections.<TwoReadPileupElement>emptyList() : twoReadPile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the pileup elements containing one read, in no particular order
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<PileupElement> getOneReadPileup() {
|
|
||||||
return oneReadPile == null ? Collections.<PileupElement>emptyList() : oneReadPile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Useful helper class to represent a full read pair at a position
|
|
||||||
*
|
|
||||||
* User: ebanks, depristo
|
|
||||||
* Date: Jan 10, 2011
|
|
||||||
*/
|
|
||||||
public static class TwoReadPileupElement {
|
|
||||||
final protected PileupElement PE1, PE2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a fragment element that contains both ends of a paired end read
|
|
||||||
* @param PE1
|
|
||||||
* @param PE2
|
|
||||||
*/
|
|
||||||
public TwoReadPileupElement(PileupElement PE1, PileupElement PE2) {
|
|
||||||
this.PE1 = PE1;
|
|
||||||
this.PE2 = PE2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the first pileup element -- never null */
|
|
||||||
public PileupElement getFirst() { return PE1; }
|
|
||||||
|
|
||||||
/** Returns the second read in this fragment element. May be null */
|
|
||||||
public PileupElement getSecond() { return PE2; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -27,6 +27,7 @@ package org.broadinstitute.sting.utils.pileup;
|
||||||
import net.sf.samtools.SAMRecord;
|
import net.sf.samtools.SAMRecord;
|
||||||
import org.broadinstitute.sting.utils.GenomeLoc;
|
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||||
import org.broadinstitute.sting.utils.HasGenomeLocation;
|
import org.broadinstitute.sting.utils.HasGenomeLocation;
|
||||||
|
import org.broadinstitute.sting.utils.fragments.FragmentCollection;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -222,4 +223,9 @@ public interface ReadBackedPileup extends Iterable<PileupElement>, HasGenomeLoca
|
||||||
*/
|
*/
|
||||||
public byte[] getMappingQuals();
|
public byte[] getMappingQuals();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this pileup into a FragmentCollection (see FragmentUtils for documentation)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public FragmentCollection<PileupElement> toFragments();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,15 @@
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.broadinstitute.sting.utils.pileup;
|
package org.broadinstitute.sting.utils.fragments;
|
||||||
|
|
||||||
import com.google.caliper.Param;
|
import com.google.caliper.Param;
|
||||||
import com.google.caliper.SimpleBenchmark;
|
import com.google.caliper.SimpleBenchmark;
|
||||||
import com.google.caliper.runner.CaliperMain;
|
import com.google.caliper.runner.CaliperMain;
|
||||||
import net.sf.samtools.SAMFileHeader;
|
import net.sf.samtools.SAMFileHeader;
|
||||||
import net.sf.samtools.SAMRecord;
|
|
||||||
import org.broadinstitute.sting.utils.GenomeLoc;
|
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||||
import org.broadinstitute.sting.utils.GenomeLocParser;
|
import org.broadinstitute.sting.utils.GenomeLocParser;
|
||||||
|
import org.broadinstitute.sting.utils.pileup.ReadBackedPileup;
|
||||||
import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils;
|
import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
@ -38,7 +38,7 @@ import java.util.*;
|
||||||
/**
|
/**
|
||||||
* Caliper microbenchmark of fragment pileup
|
* Caliper microbenchmark of fragment pileup
|
||||||
*/
|
*/
|
||||||
public class FragmentPileupBenchmark extends SimpleBenchmark {
|
public class FragmentUtilsBenchmark extends SimpleBenchmark {
|
||||||
List<ReadBackedPileup> pileups;
|
List<ReadBackedPileup> pileups;
|
||||||
|
|
||||||
@Param({"0", "4", "30", "150", "1000"})
|
@Param({"0", "4", "30", "150", "1000"})
|
||||||
|
|
@ -62,23 +62,19 @@ public class FragmentPileupBenchmark extends SimpleBenchmark {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(int rep, FragmentPileup.FragmentMatchingAlgorithm algorithm) {
|
// public void timeOriginal(int rep) {
|
||||||
|
// run(rep, FragmentUtils.FragmentMatchingAlgorithm.ORIGINAL);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void timeSkipNonOverlapping(int rep) {
|
||||||
int nFrags = 0;
|
int nFrags = 0;
|
||||||
for ( int i = 0; i < rep; i++ ) {
|
for ( int i = 0; i < rep; i++ ) {
|
||||||
for ( ReadBackedPileup rbp : pileups )
|
for ( ReadBackedPileup rbp : pileups )
|
||||||
nFrags += new FragmentPileup(rbp, algorithm).getTwoReadPileup().size();
|
nFrags += FragmentUtils.create(rbp).getOverlappingPairs().size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void timeOriginal(int rep) {
|
|
||||||
run(rep, FragmentPileup.FragmentMatchingAlgorithm.ORIGINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void timeSkipNonOverlapping(int rep) {
|
|
||||||
run(rep, FragmentPileup.FragmentMatchingAlgorithm.skipNonOverlapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
CaliperMain.main(FragmentPileupBenchmark.class, args);
|
CaliperMain.main(FragmentUtilsBenchmark.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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.fragments;
|
||||||
|
|
||||||
|
import net.sf.samtools.SAMFileHeader;
|
||||||
|
import net.sf.samtools.SAMRecord;
|
||||||
|
import org.broadinstitute.sting.BaseTest;
|
||||||
|
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.ArtificialSAMUtils;
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.BeforeTest;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test routines for read-backed pileup.
|
||||||
|
*/
|
||||||
|
public class FragmentUtilsUnitTest extends BaseTest {
|
||||||
|
private static SAMFileHeader header;
|
||||||
|
|
||||||
|
private class FragmentUtilsTest extends TestDataProvider {
|
||||||
|
List<TestState> statesForPileup = new ArrayList<TestState>();
|
||||||
|
List<TestState> statesForReads = new ArrayList<TestState>();
|
||||||
|
|
||||||
|
private FragmentUtilsTest(String name, int readLen, int leftStart, int rightStart,
|
||||||
|
boolean leftIsFirst, boolean leftIsNegative) {
|
||||||
|
super(FragmentUtilsTest.class, String.format("%s-leftIsFirst:%b-leftIsNegative:%b", name, leftIsFirst, leftIsNegative));
|
||||||
|
|
||||||
|
List<SAMRecord> pair = ArtificialSAMUtils.createPair(header, "readpair", readLen, leftStart, rightStart, leftIsFirst, leftIsNegative);
|
||||||
|
SAMRecord left = pair.get(0);
|
||||||
|
SAMRecord right = pair.get(1);
|
||||||
|
|
||||||
|
for ( int pos = leftStart; pos < rightStart + readLen; pos++) {
|
||||||
|
boolean posCoveredByLeft = pos >= left.getAlignmentStart() && pos <= left.getAlignmentEnd();
|
||||||
|
boolean posCoveredByRight = pos >= right.getAlignmentStart() && pos <= right.getAlignmentEnd();
|
||||||
|
|
||||||
|
if ( posCoveredByLeft || posCoveredByRight ) {
|
||||||
|
List<SAMRecord> reads = new ArrayList<SAMRecord>();
|
||||||
|
List<Integer> offsets = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
if ( posCoveredByLeft ) {
|
||||||
|
reads.add(left);
|
||||||
|
offsets.add(pos - left.getAlignmentStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( posCoveredByRight ) {
|
||||||
|
reads.add(right);
|
||||||
|
offsets.add(pos - right.getAlignmentStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean shouldBeFragment = posCoveredByLeft && posCoveredByRight;
|
||||||
|
ReadBackedPileup pileup = new ReadBackedPileupImpl(null, reads, offsets);
|
||||||
|
TestState testState = new TestState(shouldBeFragment ? 0 : 1, shouldBeFragment ? 1 : 0, pileup, null);
|
||||||
|
statesForPileup.add(testState);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestState testState = left.getAlignmentEnd() >= right.getAlignmentStart() ? new TestState(0, 1, null, pair) : new TestState(2, 0, null, pair);
|
||||||
|
statesForReads.add(testState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestState {
|
||||||
|
int expectedSingletons, expectedPairs;
|
||||||
|
ReadBackedPileup pileup;
|
||||||
|
List<SAMRecord> rawReads;
|
||||||
|
|
||||||
|
private TestState(final int expectedSingletons, final int expectedPairs, final ReadBackedPileup pileup, final List<SAMRecord> rawReads) {
|
||||||
|
this.expectedSingletons = expectedSingletons;
|
||||||
|
this.expectedPairs = expectedPairs;
|
||||||
|
this.pileup = pileup;
|
||||||
|
this.rawReads = rawReads;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider(name = "fragmentUtilsTest")
|
||||||
|
public Object[][] createTests() {
|
||||||
|
for ( boolean leftIsFirst : Arrays.asList(true, false) ) {
|
||||||
|
for ( boolean leftIsNegative : Arrays.asList(true, false) ) {
|
||||||
|
// Overlapping pair
|
||||||
|
// ----> [first]
|
||||||
|
// <--- [second]
|
||||||
|
new FragmentUtilsTest("overlapping-pair", 10, 1, 5, leftIsFirst, leftIsNegative);
|
||||||
|
|
||||||
|
// Non-overlapping pair
|
||||||
|
// ---->
|
||||||
|
// <----
|
||||||
|
new FragmentUtilsTest("nonoverlapping-pair", 10, 1, 15, leftIsFirst, leftIsNegative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FragmentUtilsTest.getTests(FragmentUtilsTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true, dataProvider = "fragmentUtilsTest")
|
||||||
|
public void testAsPileup(FragmentUtilsTest test) {
|
||||||
|
for ( TestState testState : test.statesForPileup ) {
|
||||||
|
ReadBackedPileup rbp = testState.pileup;
|
||||||
|
FragmentCollection<PileupElement> fp = FragmentUtils.create(rbp);
|
||||||
|
Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
|
||||||
|
Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true, dataProvider = "fragmentUtilsTest")
|
||||||
|
public void testAsListOfReadsFromPileup(FragmentUtilsTest test) {
|
||||||
|
for ( TestState testState : test.statesForPileup ) {
|
||||||
|
FragmentCollection<SAMRecord> fp = FragmentUtils.create(testState.pileup.getReads());
|
||||||
|
Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
|
||||||
|
Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true, dataProvider = "fragmentUtilsTest")
|
||||||
|
public void testAsListOfReads(FragmentUtilsTest test) {
|
||||||
|
for ( TestState testState : test.statesForReads ) {
|
||||||
|
FragmentCollection<SAMRecord> fp = FragmentUtils.create(testState.rawReads);
|
||||||
|
Assert.assertEquals(fp.getOverlappingPairs().size(), testState.expectedPairs);
|
||||||
|
Assert.assertEquals(fp.getSingletonReads().size(), testState.expectedSingletons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = true, expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testOutOfOrder() {
|
||||||
|
final List<SAMRecord> pair = ArtificialSAMUtils.createPair(header, "readpair", 100, 1, 50, true, true);
|
||||||
|
final SAMRecord left = pair.get(0);
|
||||||
|
final SAMRecord right = pair.get(1);
|
||||||
|
final List<SAMRecord> reads = Arrays.asList(right, left); // OUT OF ORDER!
|
||||||
|
final List<Integer> offsets = Arrays.asList(0, 50);
|
||||||
|
final ReadBackedPileup pileup = new ReadBackedPileupImpl(null, reads, offsets);
|
||||||
|
FragmentUtils.create(pileup); // should throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
public void setup() {
|
||||||
|
header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2011, 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;
|
|
||||||
|
|
||||||
import net.sf.samtools.SAMFileHeader;
|
|
||||||
import net.sf.samtools.SAMReadGroupRecord;
|
|
||||||
import net.sf.samtools.SAMRecord;
|
|
||||||
import org.broadinstitute.sting.BaseTest;
|
|
||||||
import org.broadinstitute.sting.utils.collections.Pair;
|
|
||||||
import org.broadinstitute.sting.utils.sam.ArtificialSAMUtils;
|
|
||||||
import org.testng.Assert;
|
|
||||||
import org.testng.annotations.BeforeTest;
|
|
||||||
import org.testng.annotations.DataProvider;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test routines for read-backed pileup.
|
|
||||||
*/
|
|
||||||
public class FragmentPileupUnitTest extends BaseTest {
|
|
||||||
private static SAMFileHeader header;
|
|
||||||
|
|
||||||
private class FragmentPileupTest extends TestDataProvider {
|
|
||||||
List<TestState> states = new ArrayList<TestState>();
|
|
||||||
|
|
||||||
private FragmentPileupTest(String name, int readLen, int leftStart, int rightStart, boolean leftIsFirst, boolean leftIsNegative) {
|
|
||||||
super(FragmentPileupTest.class, String.format("%s-leftIsFirst:%b-leftIsNegative:%b", name, leftIsFirst, leftIsNegative));
|
|
||||||
|
|
||||||
List<SAMRecord> pair = ArtificialSAMUtils.createPair(header, "readpair", readLen, leftStart, rightStart, leftIsFirst, leftIsNegative);
|
|
||||||
SAMRecord left = pair.get(0);
|
|
||||||
SAMRecord right = pair.get(1);
|
|
||||||
|
|
||||||
for ( int pos = leftStart; pos < rightStart + readLen; pos++) {
|
|
||||||
boolean posCoveredByLeft = pos >= left.getAlignmentStart() && pos <= left.getAlignmentEnd();
|
|
||||||
boolean posCoveredByRight = pos >= right.getAlignmentStart() && pos <= right.getAlignmentEnd();
|
|
||||||
|
|
||||||
if ( posCoveredByLeft || posCoveredByRight ) {
|
|
||||||
List<SAMRecord> reads = new ArrayList<SAMRecord>();
|
|
||||||
List<Integer> offsets = new ArrayList<Integer>();
|
|
||||||
|
|
||||||
if ( posCoveredByLeft ) {
|
|
||||||
reads.add(left);
|
|
||||||
offsets.add(pos - left.getAlignmentStart());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( posCoveredByRight ) {
|
|
||||||
reads.add(right);
|
|
||||||
offsets.add(pos - right.getAlignmentStart());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean shouldBeFragment = posCoveredByLeft && posCoveredByRight;
|
|
||||||
ReadBackedPileup pileup = new ReadBackedPileupImpl(null, reads, offsets);
|
|
||||||
TestState testState = new TestState(shouldBeFragment, pileup);
|
|
||||||
states.add(testState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestState {
|
|
||||||
boolean shouldBeFragment;
|
|
||||||
ReadBackedPileup pileup;
|
|
||||||
|
|
||||||
private TestState(final boolean shouldBeFragment, final ReadBackedPileup pileup) {
|
|
||||||
this.shouldBeFragment = shouldBeFragment;
|
|
||||||
this.pileup = pileup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DataProvider(name = "fragmentPileupTest")
|
|
||||||
public Object[][] createTests() {
|
|
||||||
for ( boolean leftIsFirst : Arrays.asList(true, false) ) {
|
|
||||||
for ( boolean leftIsNegative : Arrays.asList(true, false) ) {
|
|
||||||
// Overlapping pair
|
|
||||||
// ----> [first]
|
|
||||||
// <--- [second]
|
|
||||||
new FragmentPileupTest("overlapping-pair", 10, 1, 5, leftIsFirst, leftIsNegative);
|
|
||||||
|
|
||||||
// Non-overlapping pair
|
|
||||||
// ---->
|
|
||||||
// <----
|
|
||||||
new FragmentPileupTest("nonoverlapping-pair", 10, 1, 15, leftIsFirst, leftIsNegative);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FragmentPileupTest.getTests(FragmentPileupTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(enabled = true, dataProvider = "fragmentPileupTest")
|
|
||||||
public void testMe(FragmentPileupTest test) {
|
|
||||||
for ( TestState testState : test.states ) {
|
|
||||||
ReadBackedPileup rbp = testState.pileup;
|
|
||||||
FragmentPileup fp = new FragmentPileup(rbp);
|
|
||||||
Assert.assertEquals(fp.getTwoReadPileup().size(), testState.shouldBeFragment ? 1 : 0);
|
|
||||||
Assert.assertEquals(fp.getOneReadPileup().size(), testState.shouldBeFragment ? 0 : 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeTest
|
|
||||||
public void setup() {
|
|
||||||
header = ArtificialSAMUtils.createArtificialSamHeader(1,1,1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue