void postOrderTraverse( MultivariateTraitTree treeModel, NodeRef node, double[][] precisionMatrix, double logDetPrecisionMatrix, boolean cacheOuterProducts) { final int thisNumber = node.getNumber(); if (treeModel.isExternal(node)) { // Fill in precision scalar, traitValues already filled in if (missingTraits.isCompletelyMissing(thisNumber)) { upperPrecisionCache[thisNumber] = 0; lowerPrecisionCache[thisNumber] = 0; // Needed in the pre-order traversal } else { // not missing tip trait upperPrecisionCache[thisNumber] = (1.0 / getRescaledBranchLengthForPrecision(node)) * Math.pow(cacheHelper.getOUFactor(node), 2); lowerPrecisionCache[thisNumber] = Double.POSITIVE_INFINITY; } return; } final NodeRef childNode0 = treeModel.getChild(node, 0); final NodeRef childNode1 = treeModel.getChild(node, 1); postOrderTraverse( treeModel, childNode0, precisionMatrix, logDetPrecisionMatrix, cacheOuterProducts); postOrderTraverse( treeModel, childNode1, precisionMatrix, logDetPrecisionMatrix, cacheOuterProducts); final int childNumber0 = childNode0.getNumber(); final int childNumber1 = childNode1.getNumber(); final int meanOffset0 = dim * childNumber0; final int meanOffset1 = dim * childNumber1; final int meanThisOffset = dim * thisNumber; final double precision0 = upperPrecisionCache[childNumber0]; final double precision1 = upperPrecisionCache[childNumber1]; final double totalPrecision = precision0 + precision1; lowerPrecisionCache[thisNumber] = totalPrecision; // Multiply child0 and child1 densities // Delegate this! cacheHelper.computeMeanCaches( meanThisOffset, meanOffset0, meanOffset1, totalPrecision, precision0, precision1, missingTraits, node, childNode0, childNode1); // if (totalPrecision == 0) { // System.arraycopy(zeroDimVector, 0, meanCache, meanThisOffset, dim); // } else { // // Delegate in case either child is partially missing // // computeCorrectedWeightedAverage // missingTraits.computeWeightedAverage(meanCache, // meanOffset0, precision0, // meanOffset1, precision1, // meanThisOffset, dim); // } // In this delegation, you can call // getShiftForBranchLength(node); if (!treeModel.isRoot(node)) { // Integrate out trait value at this node double thisPrecision = 1.0 / getRescaledBranchLengthForPrecision(node); if (Double.isInfinite(thisPrecision)) { upperPrecisionCache[thisNumber] = totalPrecision; } else { upperPrecisionCache[thisNumber] = (totalPrecision * thisPrecision / (totalPrecision + thisPrecision)) * Math.pow(cacheHelper.getOUFactor(node), 2); } } // Compute logRemainderDensity logRemainderDensityCache[thisNumber] = 0; if (precision0 != 0 && precision1 != 0) { incrementRemainderDensities( precisionMatrix, logDetPrecisionMatrix, thisNumber, meanThisOffset, meanOffset0, meanOffset1, precision0, precision1, cacheHelper.getOUFactor(childNode0), cacheHelper.getOUFactor(childNode1), cacheOuterProducts); } }
private void preOrderTraverseSample( MultivariateTraitTree treeModel, NodeRef node, int parentIndex, double[][] treePrecision, double[][] treeVariance) { final int thisIndex = node.getNumber(); if (treeModel.isRoot(node)) { // draw root double[] rootMean = new double[dimTrait]; final int rootIndex = treeModel.getRoot().getNumber(); double rootPrecision = lowerPrecisionCache[rootIndex]; for (int datum = 0; datum < numData; datum++) { // System.arraycopy(meanCache, thisIndex * dim + datum * dimTrait, rootMean, 0, dimTrait); System.arraycopy( cacheHelper.getMeanCache(), thisIndex * dim + datum * dimTrait, rootMean, 0, dimTrait); double[][] variance = computeMarginalRootMeanAndVariance( rootMean, treePrecision, treeVariance, rootPrecision); double[] draw = MultivariateNormalDistribution.nextMultivariateNormalVariance(rootMean, variance); if (DEBUG_PREORDER) { Arrays.fill(draw, 1.0); } System.arraycopy(draw, 0, drawnStates, rootIndex * dim + datum * dimTrait, dimTrait); if (DEBUG) { System.err.println("Root mean: " + new Vector(rootMean)); System.err.println("Root var : " + new Matrix(variance)); System.err.println("Root draw: " + new Vector(draw)); } } } else { // draw conditional on parentState if (!missingTraits.isCompletelyMissing(thisIndex) && !missingTraits.isPartiallyMissing(thisIndex)) { // System.arraycopy(meanCache, thisIndex * dim, drawnStates, thisIndex * dim, dim); System.arraycopy( cacheHelper.getMeanCache(), thisIndex * dim, drawnStates, thisIndex * dim, dim); } else { if (missingTraits.isPartiallyMissing(thisIndex)) { throw new RuntimeException("Partially missing values are not yet implemented"); } // This code should work for sampling a missing tip trait as well, but needs testing // parent trait at drawnStates[parentOffset] double precisionToParent = 1.0 / getRescaledBranchLengthForPrecision(node); double precisionOfNode = lowerPrecisionCache[thisIndex]; double totalPrecision = precisionOfNode + precisionToParent; double[] mean = Ay; // temporary storage double[][] var = tmpM; // temporary storage for (int datum = 0; datum < numData; datum++) { int parentOffset = parentIndex * dim + datum * dimTrait; int thisOffset = thisIndex * dim + datum * dimTrait; if (DEBUG) { double[] parentValue = new double[dimTrait]; System.arraycopy(drawnStates, parentOffset, parentValue, 0, dimTrait); System.err.println("Parent draw: " + new Vector(parentValue)); if (parentValue[0] != drawnStates[parentOffset]) { throw new RuntimeException("Error in setting indices"); } } for (int i = 0; i < dimTrait; i++) { mean[i] = (drawnStates[parentOffset + i] * precisionToParent // + meanCache[thisOffset + i] * precisionOfNode) / totalPrecision; + cacheHelper.getMeanCache()[thisOffset + i] * precisionOfNode) / totalPrecision; for (int j = 0; j < dimTrait; j++) { var[i][j] = treeVariance[i][j] / totalPrecision; } } double[] draw = MultivariateNormalDistribution.nextMultivariateNormalVariance(mean, var); System.arraycopy(draw, 0, drawnStates, thisOffset, dimTrait); if (DEBUG) { System.err.println("Int prec: " + totalPrecision); System.err.println("Int mean: " + new Vector(mean)); System.err.println("Int var : " + new Matrix(var)); System.err.println("Int draw: " + new Vector(draw)); System.err.println(""); } } } } if (peel() && !treeModel.isExternal(node)) { preOrderTraverseSample( treeModel, treeModel.getChild(node, 0), thisIndex, treePrecision, treeVariance); preOrderTraverseSample( treeModel, treeModel.getChild(node, 1), thisIndex, treePrecision, treeVariance); } }
public IntegratedMultivariateTraitLikelihood( String traitName, MultivariateTraitTree treeModel, MultivariateDiffusionModel diffusionModel, CompoundParameter traitParameter, Parameter deltaParameter, List<Integer> missingIndices, boolean cacheBranches, boolean scaleByTime, boolean useTreeLength, BranchRateModel rateModel, List<BranchRateModel> optimalValues, BranchRateModel strengthOfSelection, Model samplingDensity, boolean reportAsMultivariate, boolean reciprocalRates) { super( traitName, treeModel, diffusionModel, traitParameter, deltaParameter, missingIndices, cacheBranches, scaleByTime, useTreeLength, rateModel, optimalValues, strengthOfSelection, samplingDensity, reportAsMultivariate, reciprocalRates); // Delegate caches to helper meanCache = new double[dim * treeModel.getNodeCount()]; if (optimalValues != null) { cacheHelper = new OUCacheHelper( dim * treeModel.getNodeCount(), cacheBranches); // new DriftCacheHelper .... } else { cacheHelper = new CacheHelper(dim * treeModel.getNodeCount(), cacheBranches); } drawnStates = new double[dim * treeModel.getNodeCount()]; upperPrecisionCache = new double[treeModel.getNodeCount()]; lowerPrecisionCache = new double[treeModel.getNodeCount()]; logRemainderDensityCache = new double[treeModel.getNodeCount()]; if (cacheBranches) { storedMeanCache = new double[dim * treeModel.getNodeCount()]; storedUpperPrecisionCache = new double[treeModel.getNodeCount()]; storedLowerPrecisionCache = new double[treeModel.getNodeCount()]; storedLogRemainderDensityCache = new double[treeModel.getNodeCount()]; } // Set up reusable temporary storage Ay = new double[dimTrait]; tmpM = new double[dimTrait][dimTrait]; tmp2 = new double[dimTrait]; zeroDimVector = new double[dim]; missingTraits = new MissingTraits.CompletelyMissing(treeModel, missingIndices, dim); setTipDataValuesForAllNodes(); }