public double logPdf(double[] x) {
    Matrix W = new Matrix(x, dim, dim);
    double logDensity = 0;

    //	    System.err.println("here");
    //	    double det = 0;
    //	    try {
    //	        det = W.determinant();
    //	    }   catch (IllegalDimension illegalDimension) {
    //            illegalDimension.printStackTrace();
    //        }
    //	    if( det < 0 ) {
    //		    System.err.println("not positive definite");
    //		    return Double.NEGATIVE_INFINITY;
    //	    }

    try {
      logDensity = Math.log(W.determinant());

      logDensity *= -0.5;
      logDensity *= df + dim + 1;

      Matrix product = S.product(W.inverse());

      for (int i = 0; i < dim; i++) logDensity -= 0.5 * product.component(i, i);

    } catch (IllegalDimension illegalDimension) {
      illegalDimension.printStackTrace();
    }

    logDensity += logNormalizationConstant;
    return logDensity;
  }
  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);
    }
  }