Added support for HangingLocusIterator
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@43 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
04befb942e
commit
7c7d4b3a95
|
|
@ -0,0 +1,189 @@
|
||||||
|
package org.broadinstitute.sting.atk;
|
||||||
|
|
||||||
|
import net.sf.samtools.util.CloseableIterator;
|
||||||
|
import net.sf.samtools.SAMRecord;
|
||||||
|
import net.sf.samtools.AlignmentBlock;
|
||||||
|
import org.broadinstitute.sting.utils.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.broadinstitute.sting.utils.RefHanger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator that traverses a SAM File, accumulating information on a per-locus basis
|
||||||
|
*/
|
||||||
|
public class LocusIteratorByHanger extends LocusIterator {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// member fields
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
private final PushbackIterator<SAMRecord> it;
|
||||||
|
|
||||||
|
private RefHanger<SAMRecord> readHanger = new RefHanger<SAMRecord>();
|
||||||
|
private RefHanger<Integer> offsetHanger = new RefHanger<Integer>();
|
||||||
|
final int INCREMENT_SIZE = 100;
|
||||||
|
final boolean DEBUG = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful class for forwarding on locusContext data from this iterator
|
||||||
|
*/
|
||||||
|
public class MyLocusContext implements LocusContext {
|
||||||
|
GenomeLoc loc = null;
|
||||||
|
private List<SAMRecord> reads = null;
|
||||||
|
private List<Integer> offsets = null;
|
||||||
|
|
||||||
|
private MyLocusContext(GenomeLoc loc, List<SAMRecord> reads, List<Integer> offsets) {
|
||||||
|
this.loc = loc;
|
||||||
|
this.reads = reads;
|
||||||
|
this.offsets = offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContig() { return getLocation().getContig(); }
|
||||||
|
public long getPosition() { return getLocation().getStart(); }
|
||||||
|
public GenomeLoc getLocation() { return loc; }
|
||||||
|
|
||||||
|
public List<SAMRecord> getReads() { return reads; }
|
||||||
|
public List<Integer> getOffsets() { return offsets; }
|
||||||
|
public int numReads() { return readHanger.getLeft().data.size(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// constructors and other basic operations
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public LocusIteratorByHanger(final CloseableIterator<SAMRecord> samIterator) {
|
||||||
|
this.it = new PushbackIterator<SAMRecord>(samIterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<LocusContext> iterator() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
//this.it.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return readHanger.hasHangers() || it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printState() {
|
||||||
|
for ( int i = 0; i < readHanger.size(); i++ ) {
|
||||||
|
RefHanger.Hanger rhanger = readHanger.getHanger(i);
|
||||||
|
RefHanger.Hanger ohanger = offsetHanger.getHanger(i);
|
||||||
|
|
||||||
|
System.out.printf(" -> %s:", rhanger.loc);
|
||||||
|
for ( int j = 0; j < rhanger.size(); j++ ) {
|
||||||
|
SAMRecord read = (SAMRecord)rhanger.get(j);
|
||||||
|
int offset = (Integer)ohanger.get(j);
|
||||||
|
System.out.printf(" %s(%d)=%s", read.getReadName(), offset, read.getReadString().charAt(offset) );
|
||||||
|
}
|
||||||
|
System.out.printf("%n");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// next() routine and associated collection operations
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public MyLocusContext next() {
|
||||||
|
if ( ! currentPositionIsFullyCovered() )
|
||||||
|
expandWindow(INCREMENT_SIZE);
|
||||||
|
|
||||||
|
if ( DEBUG ) {
|
||||||
|
System.out.printf("in Next:%n");
|
||||||
|
printState();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefHanger.Hanger rhanger = readHanger.popLeft();
|
||||||
|
RefHanger.Hanger ohanger = offsetHanger.popLeft();
|
||||||
|
|
||||||
|
return new MyLocusContext(rhanger.loc, rhanger.data, ohanger.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void hangRead(final SAMRecord read) {
|
||||||
|
GenomeLoc readLoc = new GenomeLoc(read.getReferenceName(), read.getAlignmentStart());
|
||||||
|
//System.out.printf("Adding read %s at %d%n", read.getReadName(), read.getAlignmentStart());
|
||||||
|
/*
|
||||||
|
for ( int i = 0; i < read.getReadLength(); i++ ) {
|
||||||
|
GenomeLoc offset = new GenomeLoc(readLoc.getContig(), readLoc.getStart() + i);
|
||||||
|
readHanger.expandingPut(offset, read);
|
||||||
|
offsetHanger.expandingPut(offset, i);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
for ( AlignmentBlock block : read.getAlignmentBlocks() ) {
|
||||||
|
if ( DEBUG )
|
||||||
|
System.out.printf("Processing block %s len=%d%n", block, block.getLength());
|
||||||
|
for ( int i = 0; i < block.getLength(); i++ ) {
|
||||||
|
GenomeLoc offset = new GenomeLoc(readLoc.getContig(), block.getReferenceStart() + i);
|
||||||
|
readHanger.expandingPut(offset, read);
|
||||||
|
offsetHanger.expandingPut(offset, block.getReadStart() + i - 1);
|
||||||
|
if ( DEBUG )
|
||||||
|
System.out.printf(" # Added %s%n", offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean currentPositionIsFullyCovered(final GenomeLoc nextReadInStreamLoc) {
|
||||||
|
if ( readHanger.isEmpty() )
|
||||||
|
// If the buffer is empty, we're definitely not done
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( nextReadInStreamLoc.compareTo(readHanger.getLeftLoc()) == 1 )
|
||||||
|
// the next read in the stream is beyond the left most position, so it's fully covered
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
// not fully covered
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean currentPositionIsFullyCovered() {
|
||||||
|
final SAMRecord read = it.next();
|
||||||
|
GenomeLoc readLoc = new GenomeLoc(read.getReferenceName(), read.getAlignmentStart());
|
||||||
|
final boolean coveredP = currentPositionIsFullyCovered(readLoc);
|
||||||
|
if ( coveredP )
|
||||||
|
it.pushback(read);
|
||||||
|
return coveredP;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void expandWindow(final int incrementSize) {
|
||||||
|
while ( it.hasNext() ) {
|
||||||
|
if ( DEBUG ) {
|
||||||
|
System.out.printf("Expanding window%n");
|
||||||
|
printState();
|
||||||
|
}
|
||||||
|
|
||||||
|
SAMRecord read = it.next();
|
||||||
|
|
||||||
|
GenomeLoc readLoc = new GenomeLoc(read.getReferenceName(), read.getAlignmentStart());
|
||||||
|
if ( DEBUG ) {
|
||||||
|
System.out.printf(" Expanding window sizes %d with %d : left=%s, right=%s, readLoc = %s, cmp=%d%n",
|
||||||
|
readHanger.size(), incrementSize,
|
||||||
|
readHanger.hasHangers() ? readHanger.getLeftLoc() : "NA",
|
||||||
|
readHanger.hasHangers() ? readHanger.getRightLoc() : "NA",
|
||||||
|
readLoc,
|
||||||
|
readHanger.hasHangers() ? readLoc.compareTo(readHanger.getLeftLoc()) : -100);
|
||||||
|
}
|
||||||
|
//if ( readHanger.size() >= incrementSize ) {
|
||||||
|
//if ( readHanger.hasHangers() && readLoc.compareTo(readHanger.getLeftLoc()) == 1) {
|
||||||
|
if ( readHanger.hasHangers() && readLoc.distance(readHanger.getLeftLoc()) >= incrementSize ) {
|
||||||
|
// We've collected up enough reads
|
||||||
|
it.pushback(read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hangRead(read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
package org.broadinstitute.sting.atk;
|
||||||
|
|
||||||
|
import net.sf.samtools.util.CloseableIterator;
|
||||||
|
import net.sf.samtools.SAMRecord;
|
||||||
|
import org.broadinstitute.sting.utils.PushbackIterator;
|
||||||
|
import org.broadinstitute.sting.utils.Utils;
|
||||||
|
import org.broadinstitute.sting.utils.Predicate;
|
||||||
|
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import edu.mit.broad.picard.filter.SamRecordFilter;
|
||||||
|
import edu.mit.broad.picard.filter.FilteringIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator that traverses a SAM File, accumulating information on a per-locus basis
|
||||||
|
*/
|
||||||
|
public class SingleLocusIterator extends LocusIterator implements LocusContext {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// member fields
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
private final PushbackIterator<SAMRecord> it;
|
||||||
|
private String contig = null;
|
||||||
|
private int position = -1;
|
||||||
|
private List<SAMRecord> reads = new ArrayList<SAMRecord>(100);
|
||||||
|
private List<Integer> offsets = new ArrayList<Integer>(100);
|
||||||
|
|
||||||
|
public String getContig() { return contig; }
|
||||||
|
public long getPosition() { return position; }
|
||||||
|
public GenomeLoc getLocation() { return new GenomeLoc(contig, position); }
|
||||||
|
|
||||||
|
public List<SAMRecord> getReads() { return reads; }
|
||||||
|
public List<Integer> getOffsets() { return offsets; }
|
||||||
|
public int numReads() { return reads.size(); }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// constructors and other basic operations
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public SingleLocusIterator(final CloseableIterator<SAMRecord> samIterator) {
|
||||||
|
FilteringIterator filterIter = new FilteringIterator(samIterator, new locusStreamFilterFunc());
|
||||||
|
this.it = new PushbackIterator<SAMRecord>(filterIter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to filter out un-handle-able reads from the stream.
|
||||||
|
*/
|
||||||
|
class locusStreamFilterFunc implements SamRecordFilter {
|
||||||
|
public boolean filterOut(SAMRecord rec) {
|
||||||
|
return rec.getCigar().numCigarElements() > 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<LocusContext> iterator() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
//this.it.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// next() routine and associated collection operations
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public LocusContext next() {
|
||||||
|
position += 1;
|
||||||
|
|
||||||
|
if ( position != -1 ) {
|
||||||
|
cleanReads();
|
||||||
|
expandReads();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( reads.isEmpty() ) {
|
||||||
|
// the window is empty, we need to jump to the first pos of the first read in the stream
|
||||||
|
SAMRecord read = it.next();
|
||||||
|
pushRead(read);
|
||||||
|
contig = read.getReferenceName();
|
||||||
|
position = read.getAlignmentStart() - 1;
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// at this point, window contains all reads covering the pos, we need to return them
|
||||||
|
// and the offsets into each read for this loci
|
||||||
|
calcOffsetsOfWindow(position);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushRead(SAMRecord read) {
|
||||||
|
//System.out.printf(" -> Adding read %s %d-%d flags %s%n", read.getReadName(), read.getAlignmentStart(), read.getAlignmentEnd(), Utils.readFlagsAsString(read));
|
||||||
|
reads.add(read);
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeepReadPFunc implements Predicate<SAMRecord> {
|
||||||
|
public boolean apply(SAMRecord read) {
|
||||||
|
return position >= read.getAlignmentStart() &&
|
||||||
|
position < read.getAlignmentEnd() &&
|
||||||
|
read.getReferenceName().equals(contig); // should be index for efficiency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Predicate KeepReadP = new SingleLocusIterator.KeepReadPFunc();
|
||||||
|
|
||||||
|
private void calcOffsetsOfWindow(final int position) {
|
||||||
|
offsets.clear();
|
||||||
|
for ( SAMRecord read : reads ) {
|
||||||
|
// def calcOffset( read ):
|
||||||
|
// offset = self.pos - read.start
|
||||||
|
// return offset
|
||||||
|
//
|
||||||
|
// offsets = map(calcOffset, self.window)
|
||||||
|
final int offset = position - read.getAlignmentStart();
|
||||||
|
assert(offset < read.getReadLength() );
|
||||||
|
offsets.add(offset);
|
||||||
|
//System.out.printf("offsets [%d] %s%n", read.getAlignmentStart(), offsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanReads() {
|
||||||
|
// def keepReadP( read ):
|
||||||
|
// return read.chr == chr and pos >= read.start and pos <= read.end
|
||||||
|
// self.window = filter( keepReadP, self.window )
|
||||||
|
reads = Utils.filter(KeepReadP, reads);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expandReads() {
|
||||||
|
// for read in self.rs:
|
||||||
|
// #print 'read', read, pos
|
||||||
|
// if read.chr == chr and read.start <= pos and read.end >= pos:
|
||||||
|
// self.pushRead(read)
|
||||||
|
// else:
|
||||||
|
// self.rs.unget( read )
|
||||||
|
// #self.rs = chain( [read], self.rs )
|
||||||
|
// break
|
||||||
|
while ( it.hasNext() ) {
|
||||||
|
SAMRecord read = it.next();
|
||||||
|
if ( KeepReadP.apply( read ) ) {
|
||||||
|
pushRead(read);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it.pushback(read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("Can not remove records from a SAM file via an iterator!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.broadinstitute.sting.atk.modules;
|
||||||
|
|
||||||
|
import org.broadinstitute.sting.atk.LocusContext;
|
||||||
|
import org.broadinstitute.sting.utils.ReferenceOrderedDatum;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.samtools.SAMRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by IntelliJ IDEA.
|
||||||
|
* User: mdepristo
|
||||||
|
* Date: Feb 22, 2009
|
||||||
|
* Time: 3:22:14 PM
|
||||||
|
* To change this template use File | Settings | File Templates.
|
||||||
|
*/
|
||||||
|
public class DepthOfCoverageWalker extends BasicLociWalker<Integer, Integer> {
|
||||||
|
public Integer map(List<ReferenceOrderedDatum> rodData, char ref, LocusContext context) {
|
||||||
|
System.out.printf("%s: %d%n", context.getLocation(), context.getReads().size() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer reduceInit() { return 0; }
|
||||||
|
|
||||||
|
public Integer reduce(Integer value, Integer sum) {
|
||||||
|
return value + sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
package org.broadinstitute.sting.utils;
|
||||||
|
|
||||||
|
import org.broadinstitute.sting.utils.GenomeLoc;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hanging data off the reference sequence
|
||||||
|
*
|
||||||
|
* Supports in effect the following data structure
|
||||||
|
*
|
||||||
|
* <-- reference bases: A T G C -->
|
||||||
|
* d d d d
|
||||||
|
* d d d d
|
||||||
|
* d d d d
|
||||||
|
* d d d
|
||||||
|
* d d
|
||||||
|
* d
|
||||||
|
*
|
||||||
|
* Where the little d's are data associated with each position in the reference.
|
||||||
|
* Supports adding and removing data to either side of the data structure, as well as
|
||||||
|
* randomly accessing data anywhere within window.
|
||||||
|
*/
|
||||||
|
public class RefHanger<T> {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// member fields
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
ArrayList<Hanger> hangers;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Info structure
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public class Hanger {
|
||||||
|
public GenomeLoc loc = null;
|
||||||
|
public ArrayList<T> data = null;
|
||||||
|
|
||||||
|
public Hanger(GenomeLoc loc, ArrayList<T> data) {
|
||||||
|
this.loc = loc;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ArrayList<T> getData() { return data; }
|
||||||
|
public final int size() { return this.data.size(); }
|
||||||
|
public final T get(int i) { return this.data.get(i); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// constructors and other basic operations
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
public RefHanger() {
|
||||||
|
hangers = new ArrayList<Hanger>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getLeftOffset() { return 0; }
|
||||||
|
protected int getRightOffset() { return hangers.size() - 1; }
|
||||||
|
protected int getOffset(GenomeLoc loc) {
|
||||||
|
return loc.minus(getLeftLoc());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenomeLoc getLeftLoc() { return hangers.get(getLeftOffset()).loc; }
|
||||||
|
public GenomeLoc getRightLoc() { return hangers.get(getRightOffset()).loc; }
|
||||||
|
|
||||||
|
public boolean hasLocation(GenomeLoc loc) {
|
||||||
|
return ! isEmpty() && loc.isBetween(getLeftLoc(), getRightLoc());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return hangers.isEmpty();
|
||||||
|
}
|
||||||
|
public boolean hasHangers() {
|
||||||
|
return ! isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops off the left most data from the structure
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Hanger popLeft() {
|
||||||
|
assert(hasHangers());
|
||||||
|
return hangers.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropLeft() {
|
||||||
|
popLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks at the left most data from the structure
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Hanger getLeft() {
|
||||||
|
assert(hasHangers());
|
||||||
|
return getHanger(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data at offset relativePos
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Hanger getHanger(int relativePos) {
|
||||||
|
assert( hangers.contains(relativePos) );
|
||||||
|
return hangers.get(relativePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data at GenomeLoc
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Hanger getHanger(GenomeLoc pos) {
|
||||||
|
return getHanger(getOffset(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return hangers.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Adding data to the left and right
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void pushLeft(GenomeLoc pos) {
|
||||||
|
pushLeft(pos, new ArrayList<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushLeft(GenomeLoc pos, T datum) {
|
||||||
|
pushLeft(pos, new ArrayList<T>(Arrays.asList(datum)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushLeft(GenomeLoc pos, ArrayList<T> data) {
|
||||||
|
hangers.add(0, new Hanger(pos, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushRight(GenomeLoc pos) {
|
||||||
|
pushRight(pos, new ArrayList<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushRight(GenomeLoc pos, T datum) {
|
||||||
|
pushRight(pos, new ArrayList<T>(Arrays.asList(datum)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushRight(GenomeLoc pos, ArrayList<T> data) {
|
||||||
|
hangers.add(new Hanger(pos, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ensurePos(GenomeLoc pos) {
|
||||||
|
if ( hasLocation(pos) )
|
||||||
|
return true;
|
||||||
|
else {
|
||||||
|
pushRight(pos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void extendData(GenomeLoc pos, T datum) {
|
||||||
|
getHanger(pos).data.add(datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addData(List<GenomeLoc> positions, List<T> dataByPos) {
|
||||||
|
assert( positions.size() == dataByPos.size() );
|
||||||
|
|
||||||
|
for ( int i = 0; i < positions.size(); i++ ) {
|
||||||
|
GenomeLoc pos = positions.get(i);
|
||||||
|
T datum = dataByPos.get(i);
|
||||||
|
expandingPut1(pos, datum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expandingPut1(final GenomeLoc loc, T datum) {
|
||||||
|
ensurePos(loc);
|
||||||
|
extendData(loc, datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printState() {
|
||||||
|
System.out.printf("Hanger:%n");
|
||||||
|
for ( Hanger hanger : hangers ) {
|
||||||
|
System.out.printf(" -> %s => %s:%n", hanger.loc, Utils.join("/", hanger.data) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes locations on the right until we reach the expected position for pos.
|
||||||
|
*
|
||||||
|
* For example, if we have chr1:1 and 2 in the hanger, and we push 4 into the hangers
|
||||||
|
* this function will add 3 -> {} to the hanger too
|
||||||
|
*
|
||||||
|
* @param pos
|
||||||
|
* @param datum
|
||||||
|
*/
|
||||||
|
public void expandingPut(GenomeLoc pos, T datum) {
|
||||||
|
//System.out.printf("expandingPut(%s, %s)%n", pos, datum);
|
||||||
|
//printState();
|
||||||
|
if ( isEmpty() )
|
||||||
|
// we have nothing, just push right
|
||||||
|
pushRight(pos, datum);
|
||||||
|
else {
|
||||||
|
assert( pos.compareTo(getRightLoc()) == 1 );
|
||||||
|
|
||||||
|
GenomeLoc nextRight = getRightLoc().nextLoc();
|
||||||
|
while ( pos.compareTo(nextRight) == 1 ) {
|
||||||
|
//printState();
|
||||||
|
//System.out.printf(" *** Extending %s, heading for %s%n", nextRight, pos);
|
||||||
|
ensurePos(nextRight);
|
||||||
|
nextRight = nextRight.nextLoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
ensurePos(pos);
|
||||||
|
extendData(pos, datum);
|
||||||
|
}
|
||||||
|
//printState();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue