/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2015 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.broad.igv.sam;
import org.apache.log4j.Logger;
import org.broad.igv.feature.Locus;
import org.broad.igv.feature.Range;
import org.broad.igv.feature.genome.Genome;
import org.broad.igv.feature.genome.GenomeManager;
import org.broad.igv.ui.panel.FrameManager;
import org.broad.igv.ui.panel.ReferenceFrame;
import java.util.*;
/**
* @author jrobinso
*/
public class AlignmentInterval extends Locus {
private static Logger log = Logger.getLogger(AlignmentInterval.class);
Genome genome;
private AlignmentCounts counts;
private List<Alignment> alignments;
private SpliceJunctionHelper spliceJunctionHelper;
private List<DownsampledInterval> downsampledIntervals;
private PackedAlignments packedAlignments;
public AlignmentInterval(String chr, int start, int end,
List<Alignment> alignments,
AlignmentCounts counts,
SpliceJunctionHelper spliceJunctionHelper,
List<DownsampledInterval> downsampledIntervals) {
super(chr, start, end);
this.alignments = alignments;
genome = GenomeManager.getInstance().getCurrentGenome();
this.counts = counts;
this.spliceJunctionHelper = spliceJunctionHelper;
this.downsampledIntervals = downsampledIntervals;
}
static Alignment getFeatureContaining(List<Alignment> features, int right) {
int leftBounds = 0;
int rightBounds = features.size() - 1;
int idx = features.size() / 2;
int lastIdx = -1;
while (idx != lastIdx) {
lastIdx = idx;
Alignment f = features.get(idx);
if (f.contains(right)) {
return f;
}
if (f.getStart() > right) {
rightBounds = idx;
idx = (leftBounds + idx) / 2;
} else {
leftBounds = idx;
idx = (rightBounds + idx) / 2;
}
}
// Check the extremes
if (features.get(0).contains(right)) {
return features.get(0);
}
if (features.get(rightBounds).contains(right)) {
return features.get(rightBounds);
}
return null;
}
public byte getReference(int pos) {
if (genome == null) {
return 0;
}
return genome.getReference(getChr(), pos);
}
public AlignmentCounts getCounts() {
return counts;
}
/**
* Return the count of the specified nucleotide
*
* @param pos genomic position
* @param b nucleotide
* @return
*/
public int getCount(int pos, byte b) {
AlignmentCounts c = counts;
if (pos >= c.getStart() && pos < c.getEnd()) {
return c.getCount(pos, b);
}
return 0;
}
public int getMaxCount(int origin, int end) {
return counts.getMaxCount(origin, end);
}
public int getTotalCount(int pos) {
AlignmentCounts c = counts;
if (pos >= c.getStart() && pos < c.getEnd()) {
return c.getTotalCount(pos);
}
return 0;
}
public int getDelCount(int pos) {
AlignmentCounts c = counts;
if (pos >= c.getStart() && pos < c.getEnd()) {
return c.getDelCount(pos);
}
return 0;
}
public List<Alignment> getAlignments() {
return alignments == null ? Collections.<Alignment>emptyList() : Collections.unmodifiableList(alignments);
}
public Iterator<Alignment> getAlignmentIterator() {
return alignments == null ? Collections.<Alignment>emptyList().iterator() : alignments.iterator();
}
public List<DownsampledInterval> getDownsampledIntervals() {
return downsampledIntervals;
}
public SpliceJunctionHelper getSpliceJunctionHelper() {
return this.spliceJunctionHelper;
}
public Range getRange() {
return new Range(getChr(), getStart(), getEnd());
}
public void packAlignments(AlignmentTrack.RenderOptions renderOptions) {
final AlignmentPacker alignmentPacker = new AlignmentPacker();
this.packedAlignments = alignmentPacker.packAlignments(this, renderOptions);
}
public PackedAlignments getPackedAlignments() {
return packedAlignments;
}
public void dumpAlignments() {
if (this.alignments != null) this.alignments.clear();
this.packedAlignments = null;
}
/**
* An alignment iterator that iterates over packed rows. Used for
* repacking. Using the iterator avoids the need to copy alignments
* from the rows
*/
static class AlignmentIterator implements Iterator<Alignment> {
PriorityQueue<Row> rows;
Alignment nextAlignment;
AlignmentIterator(Map<String, List<Row>> groupedAlignmentRows) {
rows = new PriorityQueue(5, new Comparator<Row>() {
public int compare(Row o1, Row o2) {
return o1.getNextStartPos() - o2.getNextStartPos();
}
});
for (List<Row> alignmentRows : groupedAlignmentRows.values()) {
for (Row r : alignmentRows) {
r.resetIdx();
rows.add(r);
}
}
advance();
}
public boolean hasNext() {
return nextAlignment != null;
}
public Alignment next() {
Alignment tmp = nextAlignment;
if (tmp != null) {
advance();
}
return tmp;
}
private void advance() {
nextAlignment = null;
Row nextRow = null;
while (nextAlignment == null && !rows.isEmpty()) {
while ((nextRow = rows.poll()) != null) {
if (nextRow.hasNext()) {
nextAlignment = nextRow.nextAlignment();
break;
}
}
}
if (nextRow != null && nextAlignment != null) {
rows.add(nextRow);
}
}
public void remove() {
// ignore
}
}
}