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.HashSet;
027import java.util.IdentityHashMap;
028import java.util.Iterator;
029import java.util.Map;
030import java.util.Set;
031
032import org.biojava.bio.symbol.AtomicSymbol;
033import org.biojava.bio.symbol.FiniteAlphabet;
034import org.biojava.bio.symbol.IllegalSymbolException;
035import org.biojava.bio.symbol.Symbol;
036import org.biojava.utils.ChangeVetoException;
037
038/**
039 * A no-frills implementation of DistributionTrainerContext.
040 *
041 * @author Matthew Pocock
042 * @since 1.0
043 */
044public class SimpleDistributionTrainerContext
045implements DistributionTrainerContext, Serializable {
046  private final Map distToTrainer;
047  private final Set trainers;
048  
049  private double nullModelWeight;
050  
051  public double getNullModelWeight() {
052    return this.nullModelWeight;
053  }
054
055  public void setNullModelWeight(double nullModelWeight) {
056    this.nullModelWeight = nullModelWeight;
057  }
058  
059  public void registerDistribution(Distribution dist) {
060    if(!distToTrainer.keySet().contains(dist)) {
061      dist.registerWithTrainer(this);
062    }
063  }
064  
065  public void registerTrainer(
066    Distribution dist, DistributionTrainer trainer
067  ) {
068    distToTrainer.put(dist, trainer);
069    trainers.add(trainer);
070  }
071  
072  public DistributionTrainer getTrainer(Distribution dist) {
073    return (DistributionTrainer) distToTrainer.get(dist);
074  }
075
076  public void addCount(Distribution dist, Symbol sym, double times)
077  throws IllegalSymbolException {
078    DistributionTrainer dt = getTrainer(dist);
079    if(dt == null) {
080      throw new NullPointerException(
081        "No trainer associated with distribution " + dist
082      );
083    }
084    if (sym instanceof AtomicSymbol) {
085      dt.addCount(this, (AtomicSymbol) sym, times);
086    } else {
087//      Distribution nullModel = dist.getNullModel();
088//      double totWeight = nullModel.getWeight(sym);
089      for (
090        Iterator asi = ((FiniteAlphabet) sym.getMatches()).iterator();
091        asi.hasNext();
092      ) {
093        AtomicSymbol as = (AtomicSymbol) asi.next();
094        //dt.addCount(this, as, times * (nullModel.getWeight(as) / totWeight));
095        dt.addCount(this, as, times);
096      }
097    }
098  }
099  
100  public double getCount(Distribution dist, Symbol sym)
101  throws IllegalSymbolException {
102    DistributionTrainer dt = getTrainer(dist);
103    if(dt == null) {
104      throw new NullPointerException(
105        "No trainer associated with distribution " + dist
106      );
107    }
108    if (sym instanceof AtomicSymbol) {
109      return dt.getCount(this, (AtomicSymbol) sym);
110    } else {
111      double totWeight = 0.0;
112      for (
113        Iterator asi = ((FiniteAlphabet) sym.getMatches()).iterator();
114        asi.hasNext();
115      ) {
116        AtomicSymbol as = (AtomicSymbol) asi.next();
117        totWeight += dt.getCount(this, as);
118      }
119      return totWeight;
120    }
121  }
122  
123  public void train()
124  throws ChangeVetoException {
125    for(Iterator i = trainers.iterator(); i.hasNext(); ) {
126      ((DistributionTrainer) i.next()).train(this, getNullModelWeight());
127    }
128  }
129  
130  public void clearCounts() {
131    for(Iterator i = trainers.iterator(); i.hasNext(); ) {
132      ((DistributionTrainer) i.next()).clearCounts(this);
133    }
134  }
135
136  /**
137   * Create a new context with no initial distributions or trainers.
138   */
139  public SimpleDistributionTrainerContext() {
140    this.distToTrainer = new IdentityHashMap();
141    this.trainers = new HashSet();
142  }
143}