/*
* 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.maf;
import java.util.ArrayList;
import java.util.List;
/**
* @author jrobinso
* Date: 2/18/13
* Time: 9:49 AM
*/
public class MultipleAlignmentBlock {
private String chr;
private int start;
private int end;
private int[] gapAdjustedIndex;
private double score;
private List<Sequence> sequences;
private List<Gap> gaps;
private String key;
public MultipleAlignmentBlock() {
sequences = new ArrayList<Sequence>();
gaps = new ArrayList<Gap>();
}
/**
* Return a key to uniquely identify this alignment.
*
* @return
*/
public String getKey() {
if (key == null) {
StringBuilder b = new StringBuilder();
b.append(chr);
b.append(":");
b.append(start);
b.append("-");
b.append(end);
for (Sequence seq : sequences) {
b.append("_");
b.append(seq.getSpecies());
}
key = b.toString();
}
return key;
}
public String getChr() {
return chr;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public double getScore() {
return score;
}
public List<Sequence> getSequences() {
return sequences;
}
public int getGapAdjustedIndex(int position) {
return gapAdjustedIndex[position - start];
}
public Sequence getRefSequence() {
return sequences.get(0);
}
public List<Gap> getGaps() {
return gaps;
}
public void addSequence(Sequence sequence) {
if (sequences.isEmpty()) {
// First sequence is the reference
chr = sequence.chr;
start = sequence.start;
end = start + sequence.size;
findGaps(sequence.text);
}
sequences.add(sequence);
}
private void findGaps(String referenceText) {
byte[] bytes = referenceText.getBytes();
// Maps genomic position -> text position.
gapAdjustedIndex = new int[end - start];
int refPosition = 0;
byte dash = (byte) '-';
Gap gap = null;
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] == dash) {
if (gap == null) {
// Start a new gap.
double gapPosition = start + refPosition;
gap = new Gap(gapPosition, i);
} else {
// Increment existing gap
gap.incSize();
}
} else {
if (gap != null) {
// End in-progress gap
gaps.add(gap);
gap = null;
}
gapAdjustedIndex[refPosition] = i;
refPosition++;
}
}
if (gap != null) {
gaps.add(gap);
}
}
public Sequence getSequence(String sp) {
// TODO -- use a map
for(Sequence seq : sequences) {
if(seq.getSpecies().equals(sp)) return seq;
}
return null;
}
/**
* Class to represent a gap in the reference sequence.
*/
public static class Gap {
double position;
int startIdx;
int size;
public Gap(double position, int startIdx) {
this.position = position;
this.startIdx = startIdx;
this.size = 1;
}
public void incSize() {
size++;
}
}
public static class Sequence {
private String species;
private String chr;
private int start;
private int size;
private char strand;
private int srcSize;
private String text;
public Sequence(String species, String chr, int start, int size, char strand, int srcSize, String text) {
this.species = species;
this.chr = chr;
this.start = start;
this.size = size;
this.strand = strand;
this.srcSize = srcSize;
this.text = text;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
public String getChr() {
return chr;
}
public void setChr(String chr) {
this.chr = chr;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public char getStrand() {
return strand;
}
public void setStrand(char strand) {
this.strand = strand;
}
public int getSrcSize() {
return srcSize;
}
public void setSrcSize(int srcSize) {
this.srcSize = srcSize;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
}