001package org.biojava.bio.dp;
002
003import java.io.Serializable;
004
005import org.biojava.bio.BioException;
006import org.biojava.bio.SimpleAnnotation;
007import org.biojava.bio.seq.Feature;
008import org.biojava.bio.seq.Sequence;
009import org.biojava.bio.seq.SequenceAnnotator;
010import org.biojava.bio.seq.impl.ViewSequence;
011import org.biojava.bio.symbol.IllegalAlphabetException;
012import org.biojava.bio.symbol.RangeLocation;
013import org.biojava.utils.ChangeVetoException;
014
015/**
016 * Annotates a sequence with hits to a weight-matrix.
017 *
018 * <p>
019 * This SequenceAnnotator implementation returns a new
020 * ViewSequence wrapping the underlying Sequence
021 * </p>
022 *
023 * @author Matthew Pocock
024 * @author Thomas Down
025 * @author Tanya Vavouri
026 */
027public class WeightMatrixAnnotator implements SequenceAnnotator,
028    Serializable {
029  private WeightMatrix matrix;
030  private double threshold;
031  private final ScoreType scoreType;
032  private String wmID;
033
034  public Sequence annotate(Sequence seq) throws IllegalAlphabetException,
035      BioException, ChangeVetoException {
036    seq = new ViewSequence(seq);
037
038    int cols = matrix.columns();
039    Feature.Template template = new Feature.Template();
040    template.source = "WeightMatrixAnnotator";
041    template.type = wmID;
042    for (int offset = 1;
043         offset <= seq.length() - cols + 1;
044         offset++) {
045      double score = DP.scoreWeightMatrix(matrix, seq, scoreType, offset);
046      double q = Math.exp(score);
047      if (q >= threshold) {
048        template.location = new RangeLocation(offset, offset + cols - 1);
049        SimpleAnnotation ann = new SimpleAnnotation();
050        ann.setProperty("score", new Double(q));
051        ann.setProperty("weightMatrix", matrix);
052        template.annotation = ann;
053        seq.createFeature(template);
054      }
055    }
056    return seq;
057  }
058
059  /**
060   * Create a new annotator that uses the PROBABILITY score type and an ID
061   for the weight matrix.
062   *
063   * @param wm        the weight matrix
064   * @param threshold the threshold
065   * @param wmID the weight matrix ID
066   */
067  public WeightMatrixAnnotator(WeightMatrix wm, ScoreType scoreType,
068                               double threshold, String wmID) {
069    this.matrix = wm;
070    this.threshold = threshold;
071    this.scoreType = ScoreType.PROBABILITY;
072    this.wmID = wmID;
073  }
074
075  /**
076   * Create a new annotator that uses PROBABILITY score type.
077   *
078   * @param wm a <code>WeightMatrix</code> value
079   * @param threshold a <code>double</code> value
080   */
081  public WeightMatrixAnnotator(WeightMatrix wm, double threshold) {
082    this(wm, ScoreType.PROBABILITY, threshold, "hit");
083  }
084
085  /**
086   * Create a new annotator that uses a specific score type.
087   *
088   * @param wm        the weigth matrix
089   * @param scoreType the score type
090   * @param threshold the threshold
091   * @since 1.4
092   */
093  public WeightMatrixAnnotator(WeightMatrix wm, ScoreType scoreType,
094                               double threshold) {
095    this.matrix = wm;
096    this.scoreType = scoreType;
097    this.threshold = threshold;
098    this.wmID = "hit";
099  }
100
101  /**
102   * Get the value of the weight matrix id.
103   * @return value of the weight matrix id.
104   */
105  public String getWeightMatrixID() {
106    return wmID;
107  }
108
109  /**
110   * Set the weight matrix id.
111   * @param id  Value to assign to the weight matrix id.
112   */
113  public void setWeightMatrixID(String id) {
114    this.wmID = id;
115  }
116
117}