protected double getRawBranchRate(final Tree tree, final NodeRef node) {

    double rate = 0.0;
    double[] processValues = getProcessValues(tree, node);

    double totalTime = 0;
    if (indicatorParameter != null) {
      double absRate = rateParameter.getParameterValue(0);

      for (int i = 0; i < indicatorParameter.getDimension(); i++) {
        int index = (int) indicatorParameter.getParameterValue(i);
        if (index == 0) {
          rate += absRate * processValues[i];
        } else {
          rate +=
              (absRate * (1.0 + relativeRatesParameter.getParameterValue(index - 1)))
                  * processValues[i];
        }
        totalTime += processValues[i];
      }
    } else {
      for (int i = 0; i < rateParameter.getDimension(); i++) {
        rate += rateParameter.getParameterValue(i) * processValues[i];
        totalTime += processValues[i];
      }
    }
    rate /= totalTime;

    return rate;
  }
  /**
   * @param name the name of the covarion substitution model
   * @param dataType the data type
   * @param freqModel the equlibrium frequencies
   * @param hiddenClassRates the relative rates of the hidden categories (first hidden category has
   *     rate 1.0 so this parameter has dimension one less than number of hidden categories. each
   *     hidden category.
   * @param switchingRates rate of switching between hidden categories
   */
  public AbstractCovarionDNAModel(
      String name,
      HiddenNucleotides dataType,
      Parameter hiddenClassRates,
      Parameter switchingRates,
      FrequencyModel freqModel) {

    super(name, dataType, freqModel);

    hiddenClassCount = dataType.getHiddenClassCount();

    this.hiddenClassRates = hiddenClassRates;
    this.switchingRates = switchingRates;

    assert hiddenClassRates.getDimension() == hiddenClassCount - 1;

    int hiddenClassCount = getHiddenClassCount();

    int switchingClassCount = hiddenClassCount * (hiddenClassCount - 1) / 2;

    if (switchingRates.getDimension() != switchingClassCount) {
      throw new IllegalArgumentException(
          "switching rate parameter must have "
              + switchingClassCount
              + " rates for "
              + hiddenClassCount
              + " classes");
    }
    addVariable(switchingRates);
    addVariable(hiddenClassRates);
    constructRateMatrixMap();
  }
  private void printInformtion(Parameter par) {
    StringBuffer sb = new StringBuffer("parameter \n");
    for (int j = 0; j < par.getDimension(); j++) {
      sb.append(par.getParameterValue(j));
    }

    Logger.getLogger("dr.evomodel").info(sb.toString());
  };
  public Object parseXMLObject(XMLObject xo) throws XMLParseException {

    final boolean onLogitScale = xo.getAttribute(ON_LOGIT_SCALE, false);

    XMLObject cxo = xo.getChild(COUNTS);
    Parameter countsParam = (Parameter) cxo.getChild(Parameter.class);

    cxo = xo.getChild(PROPORTION);
    Parameter proportionParam = (Parameter) cxo.getChild(Parameter.class);

    if (proportionParam.getDimension() != 1
        && proportionParam.getDimension() != countsParam.getDimension()) {
      throw new XMLParseException(
          "Proportion dimension ("
              + proportionParam.getDimension()
              + ") "
              + "must equal 1 or counts dimension ("
              + countsParam.getDimension()
              + ")");
    }

    cxo = xo.getChild(TRIALS);
    Parameter trialsParam;
    if (cxo.hasAttribute(VALUES)) {
      int[] tmp = cxo.getIntegerArrayAttribute(VALUES);
      double[] v = new double[tmp.length];
      for (int i = 0; i < tmp.length; ++i) {
        v[i] = tmp[i];
      }
      trialsParam = new Parameter.Default(v);
    } else {
      trialsParam = (Parameter) cxo.getChild(Parameter.class);
    }

    if (trialsParam.getDimension() != countsParam.getDimension()) {
      throw new XMLParseException(
          "Trials dimension ("
              + trialsParam.getDimension()
              + ") must equal counts dimension ("
              + countsParam.getDimension()
              + ")");
    }

    return new BinomialLikelihood(trialsParam, proportionParam, countsParam, onLogitScale);
  }
 public MultivariateNormalIndependenceSampler(
     Parameter parameter,
     SelfControlledCaseSeries sccs,
     double setSizeMean,
     double weight,
     double scaleFactor,
     CoercionMode mode) {
   super(mode);
   this.scaleFactor = scaleFactor;
   this.parameter = parameter;
   setWeight(weight);
   dim = parameter.getDimension();
   setWeight(weight);
   this.sccs = sccs;
   this.setSizeMean = setSizeMean;
 }
  /** change the parameter and return the hastings ratio. */
  public double doOperation() throws OperatorFailedException {

    double[] mean = sccs.getMode();
    double[] currentValue = parameter.getParameterValues();
    double[] newValue = new double[dim];

    Set<Integer> updateSet = new HashSet<Integer>();

    if (setSizeMean != -1.0) {
      final int listLength = Poisson.nextPoisson(setSizeMean);
      while (updateSet.size() < listLength) {
        int newInt = MathUtils.nextInt(parameter.getDimension());
        if (!updateSet.contains(newInt)) {
          updateSet.add(newInt);
        }
      }
    } else {
      for (int i = 0; i < dim; ++i) {
        updateSet.add(i);
      }
    }

    double logq = 0;
    for (Integer i : updateSet) {
      newValue[i] = mean[i] + scaleFactor * MathUtils.nextGaussian();
      if (UPDATE_ALL) {
        parameter.setParameterValueQuietly(i, newValue[i]);
      } else {
        parameter.setParameterValue(i, newValue[i]);
      }

      logq +=
          (NormalDistribution.logPdf(currentValue[i], mean[i], scaleFactor)
              - NormalDistribution.logPdf(newValue[i], mean[i], scaleFactor));
    }

    //        for (Integer i : updateSet) {
    //            parameter.setParameterValueQuietly(i, newValue[i]);
    //        }

    if (UPDATE_ALL) {
      parameter.setParameterValueNotifyChangedAll(0, parameter.getParameterValue(0));
    }

    return logq;
  }
  public Object parseXMLObject(XMLObject xo) throws XMLParseException {

    // final int overSampling = xo.getAttribute(OVERSAMPLING, 1);
    final boolean normalize = xo.getAttribute(NORMALIZE, false);
    final double normalizeBranchRateTo = xo.getAttribute(NORMALIZE_BRANCH_RATE_TO, Double.NaN);

    TreeModel tree = (TreeModel) xo.getChild(TreeModel.class);
    ParametricDistributionModel distributionModel =
        (ParametricDistributionModel) xo.getElementFirstChild(DISTRIBUTION);

    // Parameter rateCategoryParameter = (Parameter) xo.getElementFirstChild(RATE_CATEGORIES);

    Parameter rateCategoryQuantilesParameter =
        (Parameter) xo.getElementFirstChild(RATE_CATEGORY_QUANTILES);

    Logger.getLogger("dr.evomodel").info("Using continuous relaxed clock model.");
    // Logger.getLogger("dr.evomodel").info("  over sampling = " + overSampling);
    Logger.getLogger("dr.evomodel")
        .info("  parametric model = " + distributionModel.getModelName());
    // Logger.getLogger("dr.evomodel").info("   rate categories = " +
    // rateCategoryParameter.getDimension());
    Logger.getLogger("dr.evomodel")
        .info("   rate categories = " + rateCategoryQuantilesParameter.getDimension());
    if (normalize) {
      Logger.getLogger("dr.evomodel")
          .info("   mean rate is normalized to " + normalizeBranchRateTo);
    }

    if (xo.hasAttribute(SINGLE_ROOT_RATE)) {
      // singleRootRate = xo.getBooleanAttribute(SINGLE_ROOT_RATE);
      Logger.getLogger("dr.evomodel").warning("   WARNING: single root rate is not implemented!");
    }

    /* if (xo.hasAttribute(NORMALIZED_MEAN)) {
        dbr.setNormalizedMean(xo.getDoubleAttribute(NORMALIZED_MEAN));
    }*/

    return new ContinuousBranchRates(
        tree, /*rateCategoryParameter, */
        rateCategoryQuantilesParameter,
        distributionModel, /*overSampling,*/
        normalize,
        normalizeBranchRateTo);
  }
  public int[] connected(int i, Parameter clusteringParameter) {
    int n = clusteringParameter.getDimension();
    int[] visited = new int[n + 1];
    visited[0] = i + 1;
    int tv = 1;

    for (int j = 0; j < n; j++) {
      if (visited[j] != 0) {
        int curr = visited[j] - 1;

        /*look forward
         */

        int forward = (int) clusteringParameter.getParameterValue(curr);
        visited[tv] = forward + 1;
        tv++;
        // Check to see if is isn't already on the list

        for (int ii = 0; ii < tv - 1; ii++) {
          if (visited[ii] == forward + 1) {
            tv--;
            visited[tv] = 0;
          }
        }

        /*look back
         */
        for (int jj = 0; jj < n; jj++) {
          if ((int) clusteringParameter.getParameterValue(jj) == curr) {
            visited[tv] = jj + 1;
            tv++;

            for (int ii = 0; ii < tv - 1; ii++) {
              if (visited[ii] == jj + 1) {
                tv--;
                visited[tv] = 0;
              }
            }
          }
        }
      }
    }
    return visited;
  }
  public DistanceDependentCRPGibbsOperator(
      Parameter links,
      Parameter assignments,
      Parameter chiParameter,
      NPAntigenicLikelihood Likelihood,
      double weight) {

    this.links = links;
    this.assignments = assignments;
    this.modelLikelihood = Likelihood;
    this.chiParameter = chiParameter;
    this.depMatrix = Likelihood.getLogDepMatrix();

    for (int i = 0; i < links.getDimension(); i++) {
      links.setParameterValue(i, i);
    }

    setWeight(weight);

    // double[][] x=modelLikelihood.getData();
    // modelLikelihood.printInformtion(x[0][0]);

    this.m = new double[2];
    m[0] = modelLikelihood.priorMean.getParameterValue(0);
    m[1] = modelLikelihood.priorMean.getParameterValue(1);

    this.v0 = 2;

    this.k0 =
        modelLikelihood.priorPrec.getParameterValue(0)
            / modelLikelihood.clusterPrec.getParameterValue(0);

    this.T0Inv = new double[2][2];
    T0Inv[0][0] = v0 / modelLikelihood.clusterPrec.getParameterValue(0);
    T0Inv[1][1] = v0 / modelLikelihood.clusterPrec.getParameterValue(0);
    T0Inv[1][0] = 0.0;
    T0Inv[0][1] = 0.0;

    this.logDetT0 = -Math.log(T0Inv[0][0] * T0Inv[1][1]);
  }
Beispiel #10
0
  public Object parseXMLObject(XMLObject xo) throws XMLParseException {

    Parameter kappaParam;
    Parameter switchingRates;
    Parameter hiddenClassRates;
    FrequencyModel freqModel;

    kappaParam = (Parameter) xo.getElementFirstChild(KAPPA);
    switchingRates = (Parameter) xo.getElementFirstChild(AbstractCovarionDNAModel.SWITCHING_RATES);
    hiddenClassRates =
        (Parameter) xo.getElementFirstChild(AbstractCovarionDNAModel.HIDDEN_CLASS_RATES);
    freqModel = (FrequencyModel) xo.getElementFirstChild(AbstractCovarionDNAModel.FREQUENCIES);

    if (!(freqModel.getDataType() instanceof HiddenNucleotides)) {
      throw new IllegalArgumentException("Datatype must be hidden nucleotides!!");
    }

    HiddenNucleotides dataType = (HiddenNucleotides) freqModel.getDataType();

    int hiddenStateCount = dataType.getHiddenClassCount();

    int switchingRatesCount = hiddenStateCount * (hiddenStateCount - 1) / 2;

    if (switchingRates.getDimension() != switchingRatesCount) {
      throw new IllegalArgumentException(
          "switching rates parameter must have "
              + switchingRatesCount
              + " dimensions, for "
              + hiddenStateCount
              + " hidden categories");
    }

    CovarionHKY model =
        new CovarionHKY(dataType, kappaParam, hiddenClassRates, switchingRates, freqModel);
    System.out.println(model);
    return model;
  }
  public GMRFSkyrideLikelihood(
      List<Tree> treeList,
      Parameter popParameter,
      Parameter groupParameter,
      Parameter precParameter,
      Parameter lambda,
      Parameter beta,
      MatrixParameter dMatrix,
      boolean timeAwareSmoothing,
      boolean rescaleByRootHeight) {

    super(GMRFSkyrideLikelihoodParser.SKYLINE_LIKELIHOOD);

    this.popSizeParameter = popParameter;
    this.groupSizeParameter = groupParameter;
    this.precisionParameter = precParameter;
    this.lambdaParameter = lambda;
    this.betaParameter = beta;
    this.dMatrix = dMatrix;
    this.timeAwareSmoothing = timeAwareSmoothing;
    this.rescaleByRootHeight = rescaleByRootHeight;

    addVariable(popSizeParameter);
    addVariable(precisionParameter);
    addVariable(lambdaParameter);
    if (betaParameter != null) {
      addVariable(betaParameter);
    }

    setTree(treeList);

    int correctFieldLength = getCorrectFieldLength();

    if (popSizeParameter.getDimension() <= 1) {
      // popSize dimension hasn't been set yet, set it here:
      popSizeParameter.setDimension(correctFieldLength);
    }

    fieldLength = popSizeParameter.getDimension();
    if (correctFieldLength != fieldLength) {
      throw new IllegalArgumentException(
          "Population size parameter should have length " + correctFieldLength);
    }

    // Field length must be set by this point
    wrapSetupIntervals();
    coalescentIntervals = new double[fieldLength];
    storedCoalescentIntervals = new double[fieldLength];
    sufficientStatistics = new double[fieldLength];
    storedSufficientStatistics = new double[fieldLength];

    setupGMRFWeights();

    addStatistic(new DeltaStatistic());

    initializationReport();

    /* Force all entries in groupSizeParameter = 1 for compatibility with Tracer */
    if (groupSizeParameter != null) {
      for (int i = 0; i < groupSizeParameter.getDimension(); i++)
        groupSizeParameter.setParameterValue(i, 1.0);
    }
  }
        public Object parseXMLObject(XMLObject xo) throws XMLParseException {

          XMLObject cxo = xo.getChild(MVN_MEAN);
          Parameter mean = (Parameter) cxo.getChild(Parameter.class);

          cxo = xo.getChild(MVN_PRECISION);
          MatrixParameter precision = (MatrixParameter) cxo.getChild(MatrixParameter.class);

          if (mean.getDimension() != precision.getRowDimension()
              || mean.getDimension() != precision.getColumnDimension())
            throw new XMLParseException(
                "Mean and precision have wrong dimensions in " + xo.getName() + " element");

          Transform[] transforms = parseListOfTransforms(xo, mean.getDimension());

          MultivariateDistributionLikelihood likelihood =
              new MultivariateDistributionLikelihood(
                  new MultivariateNormalDistribution(
                      mean.getParameterValues(), precision.getParameterAsMatrix()),
                  transforms);
          cxo = xo.getChild(DATA);
          if (cxo != null) {
            for (int j = 0; j < cxo.getChildCount(); j++) {
              if (cxo.getChild(j) instanceof Parameter) {
                Parameter data = (Parameter) cxo.getChild(j);
                if (data instanceof MatrixParameter) {
                  MatrixParameter matrix = (MatrixParameter) data;
                  if (matrix.getParameter(0).getDimension() != mean.getDimension())
                    throw new XMLParseException(
                        "dim("
                            + data.getStatisticName()
                            + ") = "
                            + matrix.getParameter(0).getDimension()
                            + " is not equal to dim("
                            + mean.getStatisticName()
                            + ") = "
                            + mean.getDimension()
                            + " in "
                            + xo.getName()
                            + "element");

                  for (int i = 0; i < matrix.getParameterCount(); i++) {
                    likelihood.addData(matrix.getParameter(i));
                  }
                } else {
                  if (data.getDimension() != mean.getDimension())
                    throw new XMLParseException(
                        "dim("
                            + data.getStatisticName()
                            + ") = "
                            + data.getDimension()
                            + " is not equal to dim("
                            + mean.getStatisticName()
                            + ") = "
                            + mean.getDimension()
                            + " in "
                            + xo.getName()
                            + "element");
                  likelihood.addData(data);
                }
              } else {
                throw new XMLParseException("illegal element in " + xo.getName() + " element");
              }
            }
          }

          return likelihood;
        }
        public Object parseXMLObject(XMLObject xo) throws XMLParseException {

          XMLObject cxo = xo.getChild(DistributionLikelihoodParser.DISTRIBUTION);
          ParametricMultivariateDistributionModel distribution =
              (ParametricMultivariateDistributionModel)
                  cxo.getChild(ParametricMultivariateDistributionModel.class);

          // Parse transforms here
          int maxDim = distribution.getMean().length;
          Transform[] transforms = parseListOfTransforms(xo, maxDim);

          MultivariateDistributionLikelihood likelihood =
              new MultivariateDistributionLikelihood(xo.getId(), distribution, transforms);

          boolean dataAsMatrix = xo.getAttribute(DATA_AS_MATRIX, false);

          cxo = xo.getChild(DATA);
          if (cxo != null) {
            for (int j = 0; j < cxo.getChildCount(); j++) {
              if (cxo.getChild(j) instanceof Parameter) {
                Parameter data = (Parameter) cxo.getChild(j);
                if (data instanceof MatrixParameter) {
                  MatrixParameter matrix = (MatrixParameter) data;
                  if (dataAsMatrix) {
                    likelihood.addData(matrix);
                  } else {
                    if (matrix.getParameter(0).getDimension() != distribution.getMean().length)
                      throw new XMLParseException(
                          "dim("
                              + data.getStatisticName()
                              + ") = "
                              + matrix.getParameter(0).getDimension()
                              + " is not equal to dim("
                              + distribution.getType()
                              + ") = "
                              + distribution.getMean().length
                              + " in "
                              + xo.getName()
                              + "element");

                    for (int i = 0; i < matrix.getParameterCount(); i++) {
                      likelihood.addData(matrix.getParameter(i));
                    }
                  }
                } else {
                  if (data.getDimension() != distribution.getMean().length)
                    throw new XMLParseException(
                        "dim("
                            + data.getStatisticName()
                            + ") = "
                            + data.getDimension()
                            + " is not equal to dim("
                            + distribution.getType()
                            + ") = "
                            + distribution.getMean().length
                            + " in "
                            + xo.getName()
                            + "element");
                  likelihood.addData(data);
                }
              } else {
                throw new XMLParseException("illegal element in " + xo.getName() + " element");
              }
            }
          }

          return likelihood;
        }
  /** change the parameter and return the hastings ratio. */
  public final double doOperation() {

    int index = MathUtils.nextInt(links.getDimension());

    int oldGroup = (int) assignments.getParameterValue(index);

    /*
     * Set index customer link to index and all connected to it to a new assignment (min value empty)
     */
    int minEmp = minEmpty(modelLikelihood.getLogLikelihoodsVector());
    links.setParameterValue(index, index);
    int[] visited = connected(index, links);

    int ii = 0;
    while (visited[ii] != 0) {
      assignments.setParameterValue(visited[ii] - 1, minEmp);
      ii++;
    }

    /*
     * Adjust likvector for group separated
     */

    modelLikelihood.setLogLikelihoodsVector(oldGroup, getLogLikGroup(oldGroup));

    modelLikelihood.setLogLikelihoodsVector(minEmp, getLogLikGroup(minEmp));

    int maxFull = maxFull(modelLikelihood.getLogLikelihoodsVector());

    double[] liks = modelLikelihood.getLogLikelihoodsVector();
    /*
     * computing likelihoods of joint groups
     */

    double[] crossedLiks = new double[maxFull + 1];

    for (int ll = 0; ll < maxFull + 1; ll++) {
      if (ll != minEmp) {
        crossedLiks[ll] = getLogLik2Group(ll, minEmp);
      }
    }

    /*
     * Add logPrior
     */
    double[] logP = new double[links.getDimension()];

    for (int jj = 0; jj < links.getDimension(); jj++) {
      logP[jj] += depMatrix[index][jj];

      int n = (int) assignments.getParameterValue(jj);
      if (n != minEmp) {
        logP[jj] += crossedLiks[n] - liks[n] - liks[minEmp];
      }
    }

    logP[index] = Math.log(chiParameter.getParameterValue(0));

    /*
     * possibilidade de mandar p zero as probs muito pequenas
     */

    /*
     *  Gibbs sampling
     */

    this.rescale(logP); // Improve numerical stability
    this.exp(logP); // Transform back to probability-scale

    int k = MathUtils.randomChoicePDF(logP);

    links.setParameterValue(index, k);

    int newGroup = (int) assignments.getParameterValue(k);
    ii = 0;
    while (visited[ii] != 0) {
      assignments.setParameterValue(visited[ii] - 1, newGroup);
      ii++;
    }

    /*
     * updating conditional likelihood vector
     */
    modelLikelihood.setLogLikelihoodsVector(newGroup, getLogLikGroup(newGroup));
    if (newGroup != minEmp) {
      modelLikelihood.setLogLikelihoodsVector(minEmp, 0);
    }

    sampleMeans(maxFull);

    return 0.0;
  }
  public void sampleMeans(int maxFull) {

    double[][] means = new double[maxFull + 2][2];

    // sample mean vector for each cluster

    for (int i = 0; i < maxFull + 1; i++) {

      // Find all elements in cluster

      int ngroup = 0;
      for (int ii = 0; ii < assignments.getDimension(); ii++) {
        if ((int) assignments.getParameterValue(ii) == i) {
          ngroup++;
        }
      }

      if (ngroup != 0) {
        double[][] group = new double[ngroup][2];
        double[] groupMean = new double[2];

        int count = 0;
        for (int ii = 0; ii < assignments.getDimension(); ii++) {
          if ((int) assignments.getParameterValue(ii) == i) {
            group[count][0] = modelLikelihood.getData()[ii][0];
            group[count][1] = modelLikelihood.getData()[ii][1];
            groupMean[0] += group[count][0];
            groupMean[1] += group[count][1];
            count += 1;
          }
        }

        groupMean[0] /= ngroup;
        groupMean[1] /= ngroup;

        double kn = k0 + ngroup;
        double vn = v0 + ngroup;

        double[][] sumdif = new double[2][2];

        for (int jj = 0; jj < ngroup; jj++) {
          sumdif[0][0] += (group[jj][0] - groupMean[0]) * (group[jj][0] - groupMean[0]);
          sumdif[0][1] += (group[jj][0] - groupMean[0]) * (group[jj][1] - groupMean[1]);
          sumdif[1][0] += (group[jj][0] - groupMean[0]) * (group[jj][1] - groupMean[1]);
          sumdif[1][1] += (group[jj][1] - groupMean[1]) * (group[jj][1] - groupMean[1]);
        }

        double[][] TnInv = new double[2][2];
        TnInv[0][0] =
            T0Inv[0][0]
                + ngroup * (k0 / kn) * (groupMean[0] - m[0]) * (groupMean[0] - m[0])
                + sumdif[0][0];
        TnInv[0][1] =
            T0Inv[0][1]
                + ngroup * (k0 / kn) * (groupMean[1] - m[1]) * (groupMean[0] - m[0])
                + sumdif[0][1];
        TnInv[1][0] =
            T0Inv[1][0]
                + ngroup * (k0 / kn) * (groupMean[0] - m[0]) * (groupMean[1] - m[1])
                + sumdif[1][0];
        TnInv[1][1] =
            T0Inv[1][1]
                + ngroup * (k0 / kn) * (groupMean[1] - m[1]) * (groupMean[1] - m[1])
                + sumdif[1][1];

        Matrix Tn = new SymmetricMatrix(TnInv).inverse();

        double[] posteriorMean = new double[2];
        // compute posterior mean

        posteriorMean[0] = (k0 * m[0] + ngroup * groupMean[0]) / (k0 + ngroup);
        posteriorMean[1] = (k0 * m[1] + ngroup * groupMean[1]) / (k0 + ngroup);

        // compute posterior Precision
        double[][] posteriorPrecision =
            new WishartDistribution(vn, Tn.toComponents()).nextWishart();
        posteriorPrecision[0][0] *= kn;
        posteriorPrecision[1][0] *= kn;
        posteriorPrecision[0][1] *= kn;
        posteriorPrecision[1][1] *= kn;

        double[] sample =
            new MultivariateNormalDistribution(posteriorMean, posteriorPrecision)
                .nextMultivariateNormal();
        means[i][0] = sample[0];
        means[i][1] = sample[1];
      }
    }

    // Fill in cluster means for each observation

    for (int j = 0; j < assignments.getDimension(); j++) {
      double[] group = new double[2];
      group[0] = means[(int) assignments.getParameterValue(j)][0];
      group[1] = means[(int) assignments.getParameterValue(j)][1];

      modelLikelihood.setMeans(j, group);
    }
  }
  public double getLogLik2Group(int group1, int group2) {
    double L = 0.0;

    int ngroup1 = 0;
    for (int i = 0; i < assignments.getDimension(); i++) {
      if ((int) assignments.getParameterValue(i) == group1) {
        ngroup1++;
      }
    }

    int ngroup2 = 0;
    for (int i = 0; i < assignments.getDimension(); i++) {
      if ((int) assignments.getParameterValue(i) == group2) {
        ngroup2++;
      }
    }

    int ngroup = (ngroup1 + ngroup2);

    if (ngroup != 0) {
      double[][] group = new double[ngroup][2];

      double mean[] = new double[2];

      int count = 0;
      for (int i = 0; i < assignments.getDimension(); i++) {
        if ((int) assignments.getParameterValue(i) == group1) {
          group[count][0] = modelLikelihood.getData()[i][0];
          group[count][1] = modelLikelihood.getData()[i][1];
          mean[0] += group[count][0];
          mean[1] += group[count][1];
          count += 1;
        }
      }

      for (int i = 0; i < assignments.getDimension(); i++) {
        if ((int) assignments.getParameterValue(i) == group2) {
          group[count][0] = modelLikelihood.getData()[i][0];
          group[count][1] = modelLikelihood.getData()[i][1];
          mean[0] += group[count][0];
          mean[1] += group[count][1];
          count += 1;
        }
      }

      mean[0] /= ngroup;
      mean[1] /= ngroup;

      double kn = k0 + ngroup;
      double vn = v0 + ngroup;

      double[][] sumdif = new double[2][2];

      for (int i = 0; i < ngroup; i++) {
        sumdif[0][0] += (group[i][0] - mean[0]) * (group[i][0] - mean[0]);
        sumdif[0][1] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]);
        sumdif[1][0] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]);
        sumdif[1][1] += (group[i][1] - mean[1]) * (group[i][1] - mean[1]);
      }

      double[][] TnInv = new double[2][2];
      TnInv[0][0] =
          T0Inv[0][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[0] - m[0]) + sumdif[0][0];
      TnInv[0][1] =
          T0Inv[0][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[0] - m[0]) + sumdif[0][1];
      TnInv[1][0] =
          T0Inv[1][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[1] - m[1]) + sumdif[1][0];
      TnInv[1][1] =
          T0Inv[1][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[1] - m[1]) + sumdif[1][1];

      double logDetTn = -Math.log(TnInv[0][0] * TnInv[1][1] - TnInv[0][1] * TnInv[1][0]);

      L += -(ngroup) * Math.log(Math.PI);
      L += Math.log(k0) - Math.log(kn);
      L += (vn / 2) * logDetTn - (v0 / 2) * logDetT0;
      L += GammaFunction.lnGamma(vn / 2) + GammaFunction.lnGamma((vn / 2) - 0.5);
      L += -GammaFunction.lnGamma(v0 / 2) - GammaFunction.lnGamma((v0 / 2) - 0.5);
    }

    return L;
  }
  public Object parseXMLObject(XMLObject xo) throws XMLParseException {

    Parameter ratesParameter = null;
    FrequencyModel freqModel = null;

    if (xo.hasChildNamed(FREQUENCIES)) {
      XMLObject cxo = xo.getChild(FREQUENCIES);
      freqModel = (FrequencyModel) cxo.getChild(FrequencyModel.class);
    }

    DataType dataType = DataTypeUtils.getDataType(xo);

    if (dataType == null) dataType = (DataType) xo.getChild(DataType.class);

    //        if (xo.hasAttribute(DataType.DATA_TYPE)) {
    //            String dataTypeStr = xo.getStringAttribute(DataType.DATA_TYPE);
    //            if (dataTypeStr.equals(Nucleotides.DESCRIPTION)) {
    //                dataType = Nucleotides.INSTANCE;
    //            } else if (dataTypeStr.equals(AminoAcids.DESCRIPTION)) {
    //                dataType = AminoAcids.INSTANCE;
    //            } else if (dataTypeStr.equals(Codons.DESCRIPTION)) {
    //                dataType = Codons.UNIVERSAL;
    //            } else if (dataTypeStr.equals(TwoStates.DESCRIPTION)) {
    //                dataType = TwoStates.INSTANCE;
    //            }
    //        }

    if (dataType == null) dataType = freqModel.getDataType();

    if (dataType != freqModel.getDataType()) {
      throw new XMLParseException(
          "Data type of "
              + getParserName()
              + " element does not match that of its frequencyModel.");
    }

    XMLObject cxo = xo.getChild(RATES);
    ratesParameter = (Parameter) cxo.getChild(Parameter.class);

    int states = dataType.getStateCount();
    Logger.getLogger("dr.evomodel")
        .info("  General Substitution Model (stateCount=" + states + ")");

    boolean hasRelativeRates =
        cxo.hasChildNamed(RELATIVE_TO)
            || (cxo.hasAttribute(RELATIVE_TO) && cxo.getIntegerAttribute(RELATIVE_TO) > 0);

    int nonReversibleRateCount = ((dataType.getStateCount() - 1) * dataType.getStateCount());
    int reversibleRateCount = (nonReversibleRateCount / 2);

    boolean isNonReversible = ratesParameter.getDimension() == nonReversibleRateCount;
    boolean hasIndicator = xo.hasChildNamed(INDICATOR);

    if (!hasRelativeRates) {
      Parameter indicatorParameter = null;

      if (ratesParameter.getDimension() != reversibleRateCount
          && ratesParameter.getDimension() != nonReversibleRateCount) {
        throw new XMLParseException(
            "Rates parameter in "
                + getParserName()
                + " element should have "
                + (reversibleRateCount)
                + " dimensions for reversible model or "
                + nonReversibleRateCount
                + " dimensions for non-reversible. "
                + "However parameter dimension is "
                + ratesParameter.getDimension());
      }

      if (hasIndicator) { // this is using BSSVS
        cxo = xo.getChild(INDICATOR);
        indicatorParameter = (Parameter) cxo.getChild(Parameter.class);

        if (indicatorParameter.getDimension() != ratesParameter.getDimension()) {
          throw new XMLParseException(
              "Rates and indicator parameters in "
                  + getParserName()
                  + " element must be the same dimension.");
        }

        boolean randomize =
            xo.getAttribute(
                dr.evomodelxml.substmodel.ComplexSubstitutionModelParser.RANDOMIZE, false);
        if (randomize) {
          BayesianStochasticSearchVariableSelection.Utils.randomize(
              indicatorParameter, dataType.getStateCount(), !isNonReversible);
        }
      }

      if (isNonReversible) {
        //                if (xo.hasChildNamed(ROOT_FREQ)) {
        //                    cxo = xo.getChild(ROOT_FREQ);
        //                    FrequencyModel rootFreq = (FrequencyModel)
        // cxo.getChild(FrequencyModel.class);
        //
        //                    if (dataType != rootFreq.getDataType()) {
        //                        throw new XMLParseException("Data type of " + getParserName() + "
        // element does not match that of its rootFrequencyModel.");
        //                    }
        //
        //                    Logger.getLogger("dr.evomodel").info("  Using BSSVS Complex
        // Substitution Model");
        //                    return new SVSComplexSubstitutionModel(getParserName(), dataType,
        // freqModel, ratesParameter, indicatorParameter);
        //
        //                } else {
        //                    throw new XMLParseException("Non-reversible model missing " +
        // ROOT_FREQ + " element");
        //                }
        Logger.getLogger("dr.evomodel").info("  Using BSSVS Complex Substitution Model");
        return new SVSComplexSubstitutionModel(
            getParserName(), dataType, freqModel, ratesParameter, indicatorParameter);
      } else {
        Logger.getLogger("dr.evomodel").info("  Using BSSVS General Substitution Model");
        return new SVSGeneralSubstitutionModel(
            getParserName(), dataType, freqModel, ratesParameter, indicatorParameter);
      }

    } else {
      // if we have relativeTo attribute then we use the old GeneralSubstitutionModel

      if (ratesParameter.getDimension() != reversibleRateCount - 1) {
        throw new XMLParseException(
            "Rates parameter in "
                + getParserName()
                + " element should have "
                + (reversibleRateCount - 1)
                + " dimensions. However parameter dimension is "
                + ratesParameter.getDimension());
      }

      int relativeTo = 0;
      if (hasRelativeRates) {
        relativeTo = cxo.getIntegerAttribute(RELATIVE_TO) - 1;
      }

      if (relativeTo < 0 || relativeTo >= reversibleRateCount) {
        throw new XMLParseException(RELATIVE_TO + " must be 1 or greater");
      } else {
        int t = relativeTo;
        int s = states - 1;
        int row = 0;
        while (t >= s) {
          t -= s;
          s -= 1;
          row += 1;
        }
        int col = t + row + 1;

        Logger.getLogger("dr.evomodel")
            .info("  Rates relative to " + dataType.getCode(row) + "<->" + dataType.getCode(col));
      }

      if (ratesParameter == null) {
        if (reversibleRateCount == 1) {
          // simplest model for binary traits...
        } else {
          throw new XMLParseException("No rates parameter found in " + getParserName());
        }
      }

      return new GeneralSubstitutionModel(
          getParserName(), dataType, freqModel, ratesParameter, relativeTo);
    }
  }
        public Object parseXMLObject(XMLObject xo) throws XMLParseException {

          double[] shape;
          double[] scale;

          if (xo.hasChildNamed(MVGAMMA_SHAPE)) {

            XMLObject cxo = xo.getChild(MVGAMMA_SHAPE);
            shape = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues();

            cxo = xo.getChild(MVGAMMA_SCALE);
            scale = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues();

            if (shape.length != scale.length)
              throw new XMLParseException(
                  "Shape and scale have wrong dimensions in " + xo.getName() + " element");

          } else {

            XMLObject cxo = xo.getChild(MVN_MEAN);
            double[] mean = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues();

            cxo = xo.getChild(MVN_CV);
            double[] cv = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues();

            if (mean.length != cv.length)
              throw new XMLParseException(
                  "Mean and CV have wrong dimensions in " + xo.getName() + " element");

            final int dim = mean.length;
            shape = new double[dim];
            scale = new double[dim];

            for (int i = 0; i < dim; i++) {
              double c2 = cv[i] * cv[i];
              shape[i] = 1.0 / c2;
              scale[i] = c2 * mean[i];
            }
          }

          MultivariateDistributionLikelihood likelihood =
              new MultivariateDistributionLikelihood(
                  new MultivariateGammaDistribution(shape, scale));
          XMLObject cxo = xo.getChild(DATA);
          for (int j = 0; j < cxo.getChildCount(); j++) {
            if (cxo.getChild(j) instanceof Parameter) {
              Parameter data = (Parameter) cxo.getChild(j);
              likelihood.addData(data);
              if (data.getDimension() != shape.length)
                throw new XMLParseException(
                    "dim("
                        + data.getStatisticName()
                        + ") != "
                        + shape.length
                        + " in "
                        + xo.getName()
                        + "element");
            } else {
              throw new XMLParseException("illegal element in " + xo.getName() + " element");
            }
          }
          return likelihood;
        }
 public void initializationReport() {
   System.out.println("Creating a GMRF smoothed skyride model:");
   System.out.println("\tPopulation sizes: " + popSizeParameter.getDimension());
   System.out.println(
       "\tIf you publish results using this model, please reference: Minin, Bloomquist and Suchard (2008) Molecular Biology and Evolution, 25, 1459-1471.");
 }
  public MixtureModelBranchRates(
      TreeModel tree,
      Parameter rateCategoryQuantilesParameter,
      ParametricDistributionModel[] models,
      Parameter distributionIndexParameter,
      boolean useQuantilesForRates,
      boolean normalize,
      double normalizeBranchRateTo) {
    super(MixtureModelBranchRatesParser.MIXTURE_MODEL_BRANCH_RATES);

    this.useQuantilesForRates = useQuantilesForRates;

    this.rateCategoryQuantiles =
        new TreeParameterModel(tree, rateCategoryQuantilesParameter, false);

    rates = new double[tree.getNodeCount()];

    this.normalize = normalize;

    this.treeModel = tree;
    this.distributionModels = models;
    this.normalizeBranchRateTo = normalizeBranchRateTo;

    this.tree = new SimpleTree(tree);

    this.distributionIndexParameter = distributionIndexParameter;
    addVariable(this.distributionIndexParameter);

    // Force the boundaries of rateCategoryParameter to match the category count
    // d Parameter.DefaultBounds bound = new Parameter.DefaultBounds(categoryCount - 1, 0,
    // rateCategoryParameter.getDimension());
    // d rateCategoryParameter.addBounds(bound);
    // rateCategoryQuantilesParameter.;

    Parameter.DefaultBounds bound =
        new Parameter.DefaultBounds(1.0, 0.0, rateCategoryQuantilesParameter.getDimension());
    rateCategoryQuantilesParameter.addBounds(bound);

    Parameter.DefaultBounds bound2 = new Parameter.DefaultBounds(models.length, 0.0, 1);
    distributionIndexParameter.addBounds(bound2);
    distributionIndexParameter.setParameterValue(0, 0);

    // Parameter distributionIndexParameter;

    for (ParametricDistributionModel distributionModel : distributionModels) {
      addModel(distributionModel);
    }
    // AR - commented out: changes to the tree are handled by model changed events fired by
    // rateCategories
    //        addModel(tree);
    // d addModel(rateCategories);

    addModel(rateCategoryQuantiles);

    // addModel(treeModel); // Maybe
    // AR - commented out: changes to rateCategoryParameter are handled by model changed events
    // fired by rateCategories
    //        addVariable(rateCategoryParameter);

    if (normalize) {
      tree.addModelListener(
          new ModelListener() {

            public void modelChangedEvent(Model model, Object object, int index) {
              computeFactor();
            }

            public void modelRestored(Model model) {
              computeFactor();
            }
          });
    }

    setupRates();
  }