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.dp; 024 025import java.io.Serializable; 026import java.util.HashMap; 027import java.util.Map; 028 029import org.biojava.bio.Annotation; 030import org.biojava.bio.BioError; 031import org.biojava.bio.BioException; 032import org.biojava.bio.dist.Distribution; 033import org.biojava.bio.dist.UniformDistribution; 034import org.biojava.bio.symbol.Alphabet; 035import org.biojava.bio.symbol.FiniteAlphabet; 036import org.biojava.bio.symbol.IllegalSymbolException; 037import org.biojava.bio.symbol.SimpleAlphabet; 038import org.biojava.utils.AbstractChangeable; 039import org.biojava.utils.ChangeForwarder; 040import org.biojava.utils.ChangeSupport; 041import org.biojava.utils.ChangeType; 042import org.biojava.utils.ChangeVetoException; 043 044/** 045 * Wraps a weight matrix up so that it appears to be a very simple HMM. 046 * 047 * @author Matthew Pocock 048 */ 049 050public class WMAsMM 051 extends 052 AbstractChangeable 053 implements 054 MarkovModel, 055 Serializable 056{ 057 private static final int [] advance = {1}; 058 059 private final WeightMatrix wm; 060 private final FiniteAlphabet stateAlpha; 061 private final MagicalState magicalState; 062 private final EmissionState [] states; 063 064 private final Map transFrom; 065 private final Map transTo; 066 private final Map transWeights; 067 068 private final transient ChangeForwarder distForwarder; 069 070 public int[] advance() { 071 return new int[] { 1 }; // fixme: this should be cleverer:x 072 } 073 074 public Alphabet emissionAlphabet() { 075 return wm.getAlphabet(); 076 } 077 078 public FiniteAlphabet stateAlphabet() { 079 return stateAlpha; 080 } 081 082 public int heads() { 083 return 1; 084 } 085 086 public MagicalState magicalState() { 087 return magicalState; 088 } 089 090 public Distribution getWeights(State source) 091 throws IllegalSymbolException { 092 stateAlpha.validate(source); 093 return (Distribution) transWeights.get(source); 094 } 095 096 public void setWeights(State source, Distribution dist) 097 throws ChangeVetoException { 098 throw new ChangeVetoException( 099 "Can't replace distribution in immutable model" 100 ); 101 } 102 103 public FiniteAlphabet transitionsFrom(State from) 104 throws IllegalSymbolException { 105 Alphabet sAlpha = stateAlphabet(); 106 sAlpha.validate(from); 107 108 return (FiniteAlphabet) transFrom.get(from); 109 } 110 111 public FiniteAlphabet transitionsTo(State to) 112 throws IllegalSymbolException { 113 Alphabet sAlpha = stateAlphabet(); 114 sAlpha.validate(to); 115 116 return (FiniteAlphabet) transTo.get(to); 117 } 118 119 public void registerWithTrainer(ModelTrainer modelTrainer) 120 throws BioException { 121/* for(Iterator i = stateAlphabet().iterator(); i.hasNext(); ) { 122 EmissionState s = (EmissionState) i.next(); 123 s.registerWithTrainer(modelTrainer); 124 }*/ 125 } 126 127 public void createTransition(State from, State to) 128 throws ChangeVetoException { 129 throw new ChangeVetoException( 130 "destroyTransition not supported by " + getClass()); 131 } 132 133 public void destroyTransition(State from, State to) 134 throws ChangeVetoException { 135 throw new ChangeVetoException( 136 "destroyTransition not supported by " + getClass()); 137 } 138 139 public void addState(State toAdd) 140 throws IllegalSymbolException, ChangeVetoException { 141 if(stateAlphabet().contains(toAdd)) { 142 throw new IllegalSymbolException( 143 toAdd, 144 "Can't add a state to a model that already contains it" 145 ); 146 } 147 148 throw new ChangeVetoException("addState not supported by " + getClass()); 149 } 150 151 public void removeState(State toAdd) 152 throws IllegalSymbolException, ChangeVetoException { 153 stateAlphabet().validate(toAdd); 154 155 throw new ChangeVetoException("removeState not supported by " + getClass()); 156 } 157 158 public boolean containsTransition(State from, State to) 159 throws IllegalSymbolException { 160 Alphabet sAlpha = stateAlphabet(); 161 sAlpha.validate(from); 162 sAlpha.validate(to); 163 164 return transitionsFrom(from).contains(to); 165 } 166 167 protected int index(State s) { 168 for(int i = 0; i < states.length; i++) { 169 if(s == states[i]) { 170 return i; 171 } 172 } 173 174 return -1; 175 } 176 177 public WMAsMM(WeightMatrix wm) throws IllegalSymbolException { 178 try { 179 ChangeSupport changeSupport = getChangeSupport(ChangeType.UNKNOWN); 180 distForwarder = new ChangeForwarder.Retyper(this, changeSupport, MarkovModel.PARAMETER); 181 transFrom = new HashMap(); 182 transTo = new HashMap(); 183 transWeights = new HashMap(); 184 this.wm = wm; 185 this.magicalState = MagicalState.getMagicalState(wm.getAlphabet(), 1); 186 SimpleAlphabet sa = new SimpleAlphabet(); 187 sa.addSymbol(magicalState); 188 this.stateAlpha = sa; 189 this.states = new EmissionState[wm.columns()]; 190 for(int i = 0; i <= wm.columns(); i++) { 191 if(i < wm.columns()) { 192 sa.addSymbol( 193 this.states[i] = new SimpleEmissionState( 194 i + "", 195 Annotation.EMPTY_ANNOTATION, 196 WMAsMM.advance, 197 wm.getColumn(i) 198 ) 199 ); 200 wm.getColumn(i).addChangeListener(distForwarder); 201 } 202 State prev = (i == 0) ? magicalState : states[i-1]; 203 State current = (i == wm.columns()) ? magicalState : states[i]; 204 FiniteAlphabet fa = (FiniteAlphabet) prev.getMatches(); 205 transFrom.put(prev, current.getMatches()); 206 transTo.put(current, fa); 207 Distribution dist = new UniformDistribution(fa); 208 transWeights.put(prev, dist); 209 } 210 sa.setName("Weight Matrix columns"); 211 } catch (ChangeVetoException cve) { 212 throw new BioError( 213 214 "Assertion Failure: Should be able to manipulate my state alphabet.", cve 215 ); 216 } catch (IllegalSymbolException ise) { 217 throw new BioError( 218 219 "Assertion Failure: Should be able to manipulate my state alphabet.", ise 220 ); 221 } 222 } 223}