001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022 023package org.biojava.bio.dist; 024 025import org.biojava.bio.symbol.Alphabet; 026import org.biojava.bio.symbol.IllegalAlphabetException; 027import org.biojava.bio.symbol.IllegalSymbolException; 028import org.biojava.bio.symbol.Symbol; 029import org.biojava.utils.ChangeEvent; 030import org.biojava.utils.ChangeForwarder; 031import org.biojava.utils.ChangeSupport; 032import org.biojava.utils.ChangeType; 033import org.biojava.utils.ChangeVetoException; 034import org.biojava.utils.Changeable; 035 036/** 037 * <p> 038 * An encapsulation of a probability distribution over the Symbols within an 039 * alphabet. 040 * </p> 041 * 042 * <p> 043 * A distribution can be implemented as a map from symbol to probability. It is 044 * more correct to think of them as being integrals or sums over probability 045 * dencity funcitons. In this world view, getWeight should look at the 046 * getMatches of the symbol it is given and then perform the apropreate sum or 047 * integral to return the probability of something within that set of symbols 048 * being emitted. 049 * </p> 050 * 051 * <p> 052 * This interface should handle the case of emitting an ambiguity symbol. 053 * This should be just the sum of the probabiltiy of emitting each matching 054 * symbol. It is up to the code using the Distribution instance to divide out 055 * the null model appropreately. 056 * </p> 057 * 058 * @author Matthew Pocock 059 * @since 1.0 060 */ 061public interface Distribution extends Changeable { 062 /** 063 * <p> 064 * Whenever a distribution changes the values that would be returned by 065 * getWeight, they should fire a ChangeEvent with this object as the type. 066 * </p> 067 * 068 * <p> 069 * If the whole distribution changes, then the change and previous fields of 070 * the ChangeEvent should be left null. If only a single weight is modified, 071 * then change should be of the form Object[] { symbol, new Double(newVal) } 072 * and previous should be of the form Object[] { symbol, new Double(oldVal) } 073 * </p> 074 */ 075 public static final ChangeType WEIGHTS = new ChangeType( 076 "distribution weights changed", 077 "org.biojava.bio.dist.Distribution", 078 "WEIGHTS" 079 ); 080 081 /** 082 * <p> 083 * Whenever the null model distribution changes the values that would be 084 * returned by getWeight, either by being edited or by being replaced, a 085 * ChangeEvent with this object as the type should be thrown. 086 * </p> 087 * 088 * <p> 089 * If the null model has changed its weights, then the ChangeEvent should 090 * refer back to the ChangeEvent from the null model. 091 * </p> 092 */ 093 public static final ChangeType NULL_MODEL = new ChangeType( 094 "distribution null model changed", 095 "org.biojava.bio.dist.Distribution", 096 "NULL_MODEL" 097 ); 098 099 /** 100 * The alphabet from which this spectrum emits symbols. 101 * 102 * @return the Alphabet associated with this spectrum 103 */ 104 Alphabet getAlphabet(); 105 106 /** 107 * <p> 108 * Return the probability that Symbol s is emitted by this spectrum. 109 * </p> 110 * 111 * <p> 112 * If the symbol is ambiguou, then it is the sum of the probability that 113 * each one of the matching symbols was emitted. 114 * </p> 115 * 116 * @param s the Symbol emitted 117 * @return the probability of emitting that symbol 118 * @throws IllegalSymbolException if s is not from this state's alphabet 119 */ 120 double getWeight(Symbol s) throws IllegalSymbolException; 121 122 /** 123 * Set the probability or odds that Symbol s is emitted by this state. 124 * 125 * @param s the Symbol emitted 126 * @param w the probability of emitting that symbol 127 * @throws IllegalSymbolException if s is not from this state's alphabet, or 128 * if it is an ambiguity symbol and the implementation can't handle 129 * this case 130 * @throws ChangeVetoException if this state does not allow weights 131 * to be tampered with, or if one of the listeners vetoed this change 132 */ 133 void setWeight(Symbol s, double w) 134 throws IllegalSymbolException, ChangeVetoException; 135 136 /** 137 * Sample a symbol from this state's probability distribution. 138 * 139 * @return the symbol sampled 140 */ 141 Symbol sampleSymbol(); 142 143 /** 144 * Retrieve the null model Distribution that this Distribution recognizes. 145 * 146 * @return the apropriate null model 147 */ 148 Distribution getNullModel(); 149 150 /** 151 * Set the null model Distribution that this Distribution recognizes. 152 * 153 * @param nullDist the new null model Distribution 154 * @throws IllegalAlphabetException if the null model has the wrong alphabet 155 * @throws ChangeVetoException if this Distirbution doesn't support setting 156 * the null model, or if one of its listeners objects 157 */ 158 void setNullModel(Distribution nullDist) 159 throws IllegalAlphabetException, ChangeVetoException; 160 161 /** 162 * <p> 163 * Register this distribution with a training context. 164 * </p> 165 * 166 * <p> 167 * This should be invoked from within dtc.addDistribution(). This method 168 * is responsible for constructing a suitable DistributionTrainer instance 169 * and registering it by calling 170 * dtc.registerDistributionTrainer(this, trainer). If the distribution is a 171 * view onto another distribution, it can force the other to be registered by 172 * calling dtc.addDistribution(other), and can then get on with registering 173 * it's own trainer. 174 * </p> 175 * 176 * @param dtc the DistributionTrainerContext with witch to register a trainer 177 */ 178 void registerWithTrainer(DistributionTrainerContext dtc); 179 180 /** 181 * This listens to the null model distribution events and converts them into 182 * NULL_MODEL events. 183 * 184 * @author Matthew Pocock 185 * @since 1.1 186 * @deprecated use 187 * <code>new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY)</code> 188 * instead 189 */ 190 public class NullModelForwarder extends ChangeForwarder { 191 /** 192 * Create a new forwarder. 193 * 194 * @param source the Object who events are forwarded on behalf of 195 * @param cs the change support that manages the listeners 196 */ 197 public NullModelForwarder(Object source, ChangeSupport cs) { 198 super(source, cs); 199 } 200 201 protected ChangeEvent generateEvent(ChangeEvent ce) { 202 if(ce.getType() == WEIGHTS) { 203 return new ChangeEvent( 204 getSource(), 205 NULL_MODEL, 206 null, null, 207 ce 208 ); 209 } 210 return null; 211 } 212 } 213}