예제 #1
0
  /**
   * Creates an object to simulate data for a given set of models, a tree, parameters and unobserved
   * states. A different model can be given for each rate class.
   *
   * @param m Map from site class to model
   * @param t The tree
   * @param p The parameters
   * @param unobserved The unobserved states
   * @throws Models.RateCategory.RateException Thrown if there is an issue with a rate category in
   *     the model (e.g. a badly formatted rate).
   * @throws Models.Model.ModelException Thrown if there is a problem with the model (e.g. the rate
   *     categories differ in their states)
   * @throws TreeException Thrown if there is a problem with the tree.
   * @throws Parameters.Parameters.ParameterException Thrown if there is a problem with the
   *     parameters (e.g. a required parameter is not present)
   */
  public Simulate(Map<String, Model> m, Tree t, Parameters p, Alignment unobserved)
      throws RateException, ModelException, TreeException, ParameterException {
    P = new HashMap<>();
    for (Entry<String, Model> e : m.entrySet()) {
      P.put(e.getKey(), new Probabilities(e.getValue(), t, p));
    }
    this.missing = unobserved;

    this.t = new HashMap<>();
    for (String s : m.keySet()) {
      this.t.put(s, t);
    }

    random = new Random();

    // If the parameters setting doesn't include branch lengths parameters then
    // add them from the tree.  The paramter / branch length interaction is a
    // bit counter-inutative and probably needs changing but in the mean time
    // this is here to make errors less likely.
    for (Branch b : t) {
      if (!p.hasParam(b.getChild())) {
        p.addParameter(Parameter.newFixedParameter(b.getChild(), b.getLength()));
      }
    }
  }
예제 #2
0
  /**
   * Gets a simulated site. Recodes the simulated data before returning. For example if both "A" and
   * "B" are unobserved states representing an observed state of "0" then this can be used to change
   * "A" and "B" to zero. This is necessary as the simulator generates unobserved states by default.
   * The returned site will have ambiguous data set as appropriate.
   *
   * @param recode Map of recodings
   * @param internal Whether to return the state of the internal nodes
   * @param siteClass The site class to simulate for
   * @return The simulated site
   * @throws Simulations.Simulate.SimulationException Thrown if there is a problem with the
   *     simulation (currently only if attempting to simulate for a site class we don't have a model
   *     for)
   * @throws Models.RateCategory.RateException if a rate category uses the FitzJohn method at the
   *     root as this method requires likelihoods to calculate the frequency and we don't have the
   *     likelihoods when simulating.
   */
  public Site getSite(boolean internal, Map<String, String> recode, String siteClass)
      throws SimulationException, RateException {
    if (!P.containsKey(siteClass)) {
      throw new SimulationException("No model defined for requested class");
    }
    if (!t.containsKey(siteClass)) {
      throw new SimulationException("No tree defined for requested class");
    }
    Site site, loSite;
    do {
      HashMap<String, String> assign = new HashMap<>();

      RateCategory r = getRandomRate(P.get(siteClass).getRateCategory(), siteClass);

      // Assign the root
      assign.put(t.get(siteClass).getRoot(), getRandomStart(r, siteClass));

      // Traverse the tree, assign values to nodes
      for (Branch b : t.get(siteClass).getBranchesReversed()) {
        assign.put(b.getChild(), getRandomChar(r, b, assign.get(b.getParent()), siteClass));
      }

      // Done like this so things are in a sensible order if written out
      // Keeps a leaf only and all nodes copy.
      LinkedHashMap<String, String> all = new LinkedHashMap<>();
      LinkedHashMap<String, String> lo = new LinkedHashMap<>();

      for (String l : t.get(siteClass).getLeaves()) {
        all.put(l, assign.get(l));
        lo.put(l, assign.get(l));
      }
      for (String i : t.get(siteClass).getInternal()) {
        all.put(i, assign.get(i));
      }

      // This deals with recoding as discussed in the javadoc.  If there
      // is none simply ceate the site
      if (recode == null) {
        site = new Site(all, siteClass);
        loSite = new Site(lo, siteClass);
      } else {
        // Else make an ambiguous data structure
        Map<String, Set<String>> ambig = new HashMap<>();
        // Step through the recodings and add the apropiate date to
        // ambig
        for (Entry<String, String> e : recode.entrySet()) {
          if (!ambig.containsKey(e.getValue())) {
            ambig.put(e.getValue(), new HashSet<String>());
          }
          ambig.get(e.getValue()).add(e.getKey());
        }

        // Create the sites
        site = new Site(all, new Ambiguous(ambig), siteClass);
        loSite = new Site(lo, new Ambiguous(ambig), siteClass);

        // Now recode them
        site = site.recode(recode);
        loSite = loSite.recode(recode);
      }
    }
    // While the site is missing generate another site
    while (isMissing(loSite));

    if (internal) {
      return site;
    } else {
      return loSite;
    }
  }