/* * 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/ * */ package org.biojava.bio.dist; import org.biojava.bio.symbol.Alphabet; import org.biojava.bio.symbol.IllegalAlphabetException; import org.biojava.bio.symbol.IllegalSymbolException; import org.biojava.bio.symbol.Symbol; import org.biojava.utils.ChangeEvent; import org.biojava.utils.ChangeForwarder; import org.biojava.utils.ChangeSupport; import org.biojava.utils.ChangeType; import org.biojava.utils.ChangeVetoException; import org.biojava.utils.Changeable; /** *
* An encapsulation of a probability distribution over the Symbols within an * alphabet. *
* ** A distribution can be implemented as a map from symbol to probability. It is * more correct to think of them as being integrals or sums over probability * dencity funcitons. In this world view, getWeight should look at the * getMatches of the symbol it is given and then perform the apropreate sum or * integral to return the probability of something within that set of symbols * being emitted. *
* ** This interface should handle the case of emitting an ambiguity symbol. * This should be just the sum of the probabiltiy of emitting each matching * symbol. It is up to the code using the Distribution instance to divide out * the null model appropreately. *
* * @author Matthew Pocock * @since 1.0 */ public interface Distribution extends Changeable { /** ** Whenever a distribution changes the values that would be returned by * getWeight, they should fire a ChangeEvent with this object as the type. *
* ** If the whole distribution changes, then the change and previous fields of * the ChangeEvent should be left null. If only a single weight is modified, * then change should be of the form Object[] { symbol, new Double(newVal) } * and previous should be of the form Object[] { symbol, new Double(oldVal) } *
*/ public static final ChangeType WEIGHTS = new ChangeType( "distribution weights changed", "org.biojava.bio.dist.Distribution", "WEIGHTS" ); /** ** Whenever the null model distribution changes the values that would be * returned by getWeight, either by being edited or by being replaced, a * ChangeEvent with this object as the type should be thrown. *
* ** If the null model has changed its weights, then the ChangeEvent should * refer back to the ChangeEvent from the null model. *
*/ public static final ChangeType NULL_MODEL = new ChangeType( "distribution null model changed", "org.biojava.bio.dist.Distribution", "NULL_MODEL" ); /** * The alphabet from which this spectrum emits symbols. * * @return the Alphabet associated with this spectrum */ Alphabet getAlphabet(); /** ** Return the probability that Symbol s is emitted by this spectrum. *
* ** If the symbol is ambiguou, then it is the sum of the probability that * each one of the matching symbols was emitted. *
* * @param s the Symbol emitted * @return the probability of emitting that symbol * @throws IllegalSymbolException if s is not from this state's alphabet */ double getWeight(Symbol s) throws IllegalSymbolException; /** * Set the probability or odds that Symbol s is emitted by this state. * * @param s the Symbol emitted * @param w the probability of emitting that symbol * @throws IllegalSymbolException if s is not from this state's alphabet, or * if it is an ambiguity symbol and the implementation can't handle * this case * @throws ChangeVetoException if this state does not allow weights * to be tampered with, or if one of the listeners vetoed this change */ void setWeight(Symbol s, double w) throws IllegalSymbolException, ChangeVetoException; /** * Sample a symbol from this state's probability distribution. * * @return the symbol sampled */ Symbol sampleSymbol(); /** * Retrieve the null model Distribution that this Distribution recognizes. * * @return the apropriate null model */ Distribution getNullModel(); /** * Set the null model Distribution that this Distribution recognizes. * * @param nullDist the new null model Distribution * @throws IllegalAlphabetException if the null model has the wrong alphabet * @throws ChangeVetoException if this Distirbution doesn't support setting * the null model, or if one of its listeners objects */ void setNullModel(Distribution nullDist) throws IllegalAlphabetException, ChangeVetoException; /** ** Register this distribution with a training context. *
* ** This should be invoked from within dtc.addDistribution(). This method * is responsible for constructing a suitable DistributionTrainer instance * and registering it by calling * dtc.registerDistributionTrainer(this, trainer). If the distribution is a * view onto another distribution, it can force the other to be registered by * calling dtc.addDistribution(other), and can then get on with registering * it's own trainer. *
* * @param dtc the DistributionTrainerContext with witch to register a trainer */ void registerWithTrainer(DistributionTrainerContext dtc); /** * This listens to the null model distribution events and converts them into * NULL_MODEL events. * * @author Matthew Pocock * @since 1.1 * @deprecated use *new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY)
* instead
*/
public class NullModelForwarder extends ChangeForwarder {
/**
* Create a new forwarder.
*
* @param source the Object who events are forwarded on behalf of
* @param cs the change support that manages the listeners
*/
public NullModelForwarder(Object source, ChangeSupport cs) {
super(source, cs);
}
protected ChangeEvent generateEvent(ChangeEvent ce) {
if(ce.getType() == WEIGHTS) {
return new ChangeEvent(
getSource(),
NULL_MODEL,
null, null,
ce
);
}
return null;
}
}
}