org.biojava.bio.alignment.AbstractULAlignment Maven / Gradle / Ivy
/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
*/
/**
* AbstractULAlignment is an abstract base class for alignments
* where the constituent sequences have unequal lengths.
*
* @author David Waring
* @author Mark Schreiber (docs and some minor changes)
*/
package org.biojava.bio.alignment;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;
import org.biojava.bio.BioError;
import org.biojava.bio.symbol.AbstractSymbolList;
import org.biojava.bio.symbol.Alphabet;
import org.biojava.bio.symbol.IllegalSymbolException;
import org.biojava.bio.symbol.Location;
import org.biojava.bio.symbol.LocationTools;
import org.biojava.bio.symbol.RangeLocation;
import org.biojava.bio.symbol.Symbol;
import org.biojava.bio.symbol.SymbolList;
public abstract class AbstractULAlignment extends AbstractSymbolList implements
UnequalLengthAlignment {
protected Alphabet alphabet;
/**
* this will return the ambiguity symbol associated with all symbols in that
* column
*/
public Symbol symbolAt(int index) {
try {
return alphabet.getSymbol(new ColAsList(index));
} catch (IllegalSymbolException ire) {
throw new BioError(
"Somehow my crossproduct alphabet is incompatible with column "
+ index, ire);
}
}
public List labelsAt(int column) {
return labelsInRange(new RangeLocation(column, column));
}
public List labelsInRange(Location loc) {
List labels = getLabels();
Location seqLoc;
String label;
List labelList = new Vector();
for (Iterator labelIterator = labels.iterator(); labelIterator
.hasNext();) {
label = labelIterator.next();
seqLoc = locInAlignment(label);
if (LocationTools.overlaps(loc, seqLoc)) {
labelList.add(label);
}
}
return labelList;
}
public Iterator symbolListIterator() {
return new Alignment.SymbolListIterator(this);
}
protected void debug(String s) {
System.out.println(s);
}
/**
* leftMost and rightMost return labels. If there are more than one that
* start at the same location it returns the longest, if they are the same
* length it returns the first one it found;
*/
public Object leftMost() {
List labels = getLabels();
Object leftMost = null;
Object label;
Location leftLoc = null;
Location loc = null;
for (Iterator labelIterator = labels.iterator(); labelIterator
.hasNext();) {
label = labelIterator.next();
loc = locInAlignment(label);
if (leftMost == null) {
leftMost = label;
leftLoc = loc;
// loc = loc;
}
if (loc.getMin() < leftLoc.getMin()) {
leftMost = label;
leftLoc = loc;
} else if (loc.getMin() == leftLoc.getMin()) {
if ((loc.getMax() - loc.getMin()) > (leftLoc.getMax() - leftLoc
.getMin())) {
leftMost = label;
leftLoc = loc;
}
}
}
return leftMost();
}
public Object rightMost() {
List labels = getLabels();
Object rightMost = null;
Object label;
Location rightLoc = null;
Location loc = null;
for (Iterator labelIterator = labels.iterator(); labelIterator
.hasNext();) {
label = labelIterator.next();
loc = locInAlignment(label);
if (rightMost == null) {
rightMost = label;
rightLoc = loc;
// loc= loc;
}
if (loc.getMin() > rightLoc.getMin()) {
rightMost = label;
rightLoc = loc;
} else if (loc.getMin() == rightLoc.getMin()) {
if ((loc.getMax() - loc.getMin()) > (rightLoc.getMax() - rightLoc
.getMin())) {
rightMost = label;
rightLoc = loc;
}
}
}
return rightMost();
}
/**
* Retrieves a subalignment specified by the location.
*
* WARNING: It is assumed that the location is contiguous. If the
* location is non-contiguous it may be preferable to use a block iterator
* to retrieve each sub location independently.
*
* @see #subAlignment(Set labels, int min, int max)
*/
public Alignment subAlignment(Set labels, Location loc)
throws IndexOutOfBoundsException {
return new SubULAlignment(labels, loc);
}
/**
* Retreives a subAlignment
*
* @param labels
* the labels of the SymbolLists to be in the
* Alignment
* @param min
* the left most coordinate
* @param max
* the right most coordinate
* @return an Alignment
* @throws NoSuchElementException
* if one of the values in labels is not in the
* parent alignment
*/
public Alignment subAlignment(Set labels, int min, int max)
throws NoSuchElementException {
return subAlignment(labels, LocationTools.makeLocation(min, max));
}
/**
*
* @param comp
* @return
*/
public SortedSet orderedLables(Comparator comp) {
TreeSet orderedSet = new TreeSet(comp);
orderedSet.addAll(getLabels());
return orderedSet;
}
// ////////////////////////////////////////////
// ////////////////////////////////////////////
// INNER CLASSES
// ////////////////////////////////////////////
// ////////////////////////////////////////////
private final class ColAsList extends AbstractList
implements Serializable {
/**
* Generated serial version identifier
*/
private static final long serialVersionUID = 4923954639110962683L;
private final int col;
private List labels;
/**
*
* @param col
*/
public ColAsList(int col) {
this.col = col;
labels = getLabels();
}
// protected ColAsList() {
// this.col = 0;
// }
@SuppressWarnings("unchecked")
public T get(int indx) {
return (T) symbolAt(labels.get(indx), col);
}
/*
* (non-Javadoc)
* @see java.util.AbstractCollection#size()
*/
public int size() {
return labels.size();
}
}
/**
* Orders by location left to right. If they both start at the same location
* (o1.getMin() == o2.getMin()) it the larger of the two considered to the
* Left
*/
public class LeftRightLocationComparator implements Comparator {
public int compare(Object o1, Object o2) {
int ret = 1;
Location loc1, loc2;
loc1 = locInAlignment(o1);
loc2 = locInAlignment(o2);
if (loc1.getMin() > loc2.getMin()) {
ret = 1;
} else if (loc1.getMin() < loc2.getMin()) {
ret = -1;
} else if (loc1.getMin() == loc2.getMin()) {
int s1 = (loc1.getMax() - loc1.getMin()) + 1;
int s2 = (loc2.getMax() - loc2.getMin()) + 1;
if (s1 == s2) {
ret = 1;
} else {
ret = s2 - s1;
}
}
// debug (" result " + ret);
return ret;
}
}
// /////////////
// This inner class should take care of all subAlignments
// /////////////
public class SubULAlignment extends AbstractSymbolList implements
UnequalLengthAlignment {
private int start, end;
private List subLabels; // will be left null if constructed with null
// Set of labels
// this allows labels added to underlying Alignment to be seen
// unless it was constructed with a Set of labels NOT
protected SubULAlignment(Set labels, Location loc)
throws IndexOutOfBoundsException {
this.start = loc.getMin();
this.end = loc.getMax();
if (start < 1 || end > AbstractULAlignment.this.length()) {
throw new IndexOutOfBoundsException();
}
if (labels != null) {
subLabels = new ArrayList();
subLabels.addAll(labels);
} else {
subLabels = AbstractULAlignment.this
.labelsInRange(new RangeLocation(start, end));
}
}
/**
* realPosition is the position in the underlying Alignment
* corresponding to a position in the subAlignment
*/
private int realPosition(int pos) {
return pos + start - 1;
}
// ///////////////////////
// methods from Interface UnequalLengthAlignment
// //////////////////////
public int length() {
return end - start + 1;
}
/**
* The location of an individual SymbolList relative to overall
* Alignment
*/
public Location locInAlignment(Object label) {
Location origLoc = AbstractULAlignment.this.locInAlignment(label);
int min = origLoc.getMin() - start + 1;
int max = origLoc.getMax() - start + 1;
return new RangeLocation(min, max);
}
public Alignment subAlignment(Set labels, Location loc)
throws NoSuchElementException {
int min = realPosition(loc.getMin());
int max = realPosition(loc.getMax());
// if the Subalignment has a limited subLabel we want to keep labels
// of the sub sub aligment limited to that list too
if (labels == null) {
labels = new TreeSet(subLabels);
} else {
Vector l = new Vector(labels);
labels = new TreeSet(listIntersection(l, subLabels));
}
// debug (" labels now " + labels);
return new SubULAlignment(labels, new RangeLocation(min, max));
}
protected List listIntersection(List s1, List s2) {
List common = new Vector(s1);
for (Iterator i = s1.iterator(); i.hasNext();) {
Object label = i.next();
if (!s2.contains(label)) {
common.remove(label);
}
}
return common;
}
public List labelsAt(int column) throws IndexOutOfBoundsException {
return labelsInRange(new RangeLocation(column, column));
}
public List labelsInRange(Location loc)
throws IndexOutOfBoundsException {
// debug ("looking for labelsInRange " + loc.getMin() + "-" +
// loc.getMax());
int min = realPosition(loc.getMin());
int max = realPosition(loc.getMax());
if (min < start || max > end) {
throw new IndexOutOfBoundsException();
}
return listIntersection(subLabels, AbstractULAlignment.this
.labelsInRange(new RangeLocation(min, max)));
// List aLabels = AbstractULAlignment.this.labelsInRange(new
// RangeLocation(min,max));
// List sLabels = AbstractULAlignment.this.labelsInRange(new
// RangeLocation(min,max));
// for (Iterator i = aLabels.iterator();i.hasNext();){
// Object label = i.next();
// if ( ! subLabels.contains(label)){
// sLabels.remove(label);
// }
// }
// return sLabels;
}
// ///////////////////////
// methods from Interface Alignment
// //////////////////////
public List getLabels() {
return subLabels;
}
/*
* (non-Javadoc)
* @see org.biojava.bio.alignment.Alignment#symbolAt(java.lang.String, int)
*/
public Symbol symbolAt(String label, int column)
throws NoSuchElementException {
return AbstractULAlignment.this.symbolAt(label,
realPosition(column));
}
/*
* (non-Javadoc)
* @see org.biojava.bio.symbol.SymbolList#symbolAt(int)
*/
public Symbol symbolAt(int column) throws NoSuchElementException {
return AbstractULAlignment.this.symbolAt(realPosition(column));
}
/*
* (non-Javadoc)
* @see org.biojava.bio.alignment.Alignment#symbolListForLabel(java.lang.String)
*/
public SymbolList symbolListForLabel(String label)
throws NoSuchElementException {
return AbstractULAlignment.this.symbolListForLabel(label);
}
/*
* (non-Javadoc)
* @see org.biojava.bio.symbol.SymbolList#getAlphabet()
*/
public Alphabet getAlphabet() {
return AbstractULAlignment.this.getAlphabet();
}
/*
* (non-Javadoc)
* @see org.biojava.bio.alignment.Alignment#symbolListIterator()
*/
public Iterator symbolListIterator() {
return new Alignment.SymbolListIterator(this);
}
}
}