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 java.io.Serializable; 026import java.util.HashMap; 027import java.util.Iterator; 028import java.util.Map; 029 030import org.biojava.bio.BioError; 031import org.biojava.bio.symbol.Alphabet; 032import org.biojava.bio.symbol.AtomicSymbol; 033import org.biojava.bio.symbol.FiniteAlphabet; 034import org.biojava.bio.symbol.IllegalAlphabetException; 035import org.biojava.bio.symbol.IllegalSymbolException; 036import org.biojava.bio.symbol.Symbol; 037import org.biojava.utils.ChangeVetoException; 038 039/** 040 * A simple implemenation of a distribution trainer. 041 * <p> 042 * This requires the distribuiton being trained to have a working setWeight 043 * method that doesn't throw an UnsupportedOperationExcepiton. 044 * </p> 045 * 046 * @author Matthew Pocock 047 * @deprecated Distribution impls should be providing custom trainers. 048 */ 049 050public final class SimpleDistributionTrainer 051implements DistributionTrainer, Serializable { 052 private final Distribution dis; 053 private final Map c; 054 055 { 056 this.c = new HashMap(); 057 } 058 059 public void addCount( 060 DistributionTrainerContext dtc, 061 AtomicSymbol sym, 062 double count 063 ) throws IllegalSymbolException { 064 Double d = (Double) c.get(sym); 065 if (d == null) { 066 throw new IllegalSymbolException( 067 "Symbol " + sym.getName() + 068 " not found in " + dis.getAlphabet().getName() 069 ); 070 } 071 if(count < 0) { 072 throw new Error( 073 "Can't add a negative count for " + sym.getName() + 074 " of " + count 075 ); 076 } 077 c.put(sym, new Double(d.doubleValue() + count)); 078 } 079 080 public double getCount( 081 DistributionTrainerContext dtc, 082 AtomicSymbol sym 083 ) throws IllegalSymbolException { 084 Double d = (Double) c.get(sym); 085 if (d == null) { 086 throw new IllegalSymbolException( 087 "Symbol " + sym.getName() + 088 " not found in " + dis.getAlphabet().getName() 089 ); 090 } 091 return ((Double) c.get(sym)).doubleValue(); 092 } 093 094 public void train(DistributionTrainerContext dtc, double weight) 095 throws ChangeVetoException { 096 Distribution nullModel = dis.getNullModel(); 097 double sum = 0.0; 098 try { 099 for( 100 Iterator i = ((FiniteAlphabet) dis.getAlphabet()).iterator(); 101 i.hasNext(); 102 ) { 103 Symbol s = (Symbol) i.next(); 104 Double d = (Double) c.get(s); 105 sum += d.doubleValue() + 106 nullModel.getWeight(s) * weight; 107 // System.out.println(s.getName() + ": sum=" + sum); 108 } 109 for( 110 Iterator i = ((FiniteAlphabet) dis.getAlphabet()).iterator(); 111 i.hasNext(); 112 ) { 113 Symbol sym = (Symbol) i.next(); 114 Double d = (Double) c.get(sym); 115 dis.setWeight( 116 sym, 117 (d.doubleValue() + nullModel.getWeight(sym) * weight) / sum 118 ); 119 } 120 } catch (IllegalSymbolException ise) { 121 throw new BioError( 122 "The alphabet for this distribution is not self-consistent" 123 ); 124 } 125 } 126 127 public void clearCounts(DistributionTrainerContext dtc) { 128 for( 129 Iterator i = ((FiniteAlphabet) dis.getAlphabet()).iterator(); 130 i.hasNext(); 131 ) { 132 c.put(i.next(), new Double(0.0)); 133 } 134 } 135 136 public SimpleDistributionTrainer(Distribution dis) 137 throws IllegalAlphabetException { 138 Alphabet a = dis.getAlphabet(); 139 if(! (a instanceof FiniteAlphabet)) { 140 throw new IllegalAlphabetException( 141 "Can't create a SimpleDistributionTrainer for non-finite alphabet " + 142 a.getName() + " of type " + a.getClass() 143 ); 144 } 145 this.dis = dis; 146 } 147}