/** * @param tree * @param node * @return and array of the total amount of time spent in each of the discrete states along the * branch above the given node. */ private double[] getProcessValues(final Tree tree, final NodeRef node) { double[] processValues = null; double branchTime = tree.getBranchLength(node); if (mode == Mode.MARKOV_JUMP_PROCESS) { processValues = (double[]) trait.getTrait(tree, node); } else if (mode == Mode.PARSIMONY) { // an approximation to dwell times using parsimony, assuming // the state changes midpoint on the tree. Does a weighted // average of the equally parsimonious state reconstructions // at the top and bottom of each branch. if (treeChanged) { fitchParsimony.initialize(tree); // Debugging test to count work // treeInitializeCounter += 1; // if (treeInitializeCounter % 10 == 0) { // System.err.println("Cnt: "+treeInitializeCounter); // } treeChanged = false; } int[] states = fitchParsimony.getStates(tree, node); int[] parentStates = fitchParsimony.getStates(tree, tree.getParent(node)); processValues = new double[fitchParsimony.getPatterns().getStateCount()]; for (int state : states) { processValues[state] += branchTime / 2; } for (int state : parentStates) { processValues[state] += branchTime / 2; } for (int i = 0; i < processValues.length; i++) { // normalize by the number of equally parsimonious states at each end of the branch // processValues should add up to the total branch length processValues[i] /= (states.length + parentStates.length) / 2; } } else if (mode == Mode.NODE_STATES) { processValues = new double[dataType.getStateCount()]; // if (indicatorParameter != null) { // // this array should be size #states NOT #rates // processValues = new double[indicatorParameter.getDimension()]; // } else { // // this array should be size #states NOT #rates // processValues = new double[rateParameter.getDimension()]; // } // if the states are being sampled - then there is only one possible state at each // end of the branch. int state = ((int[]) trait.getTrait(tree, node))[traitIndex]; processValues[state] += branchTime / 2; int parentState = ((int[]) trait.getTrait(tree, tree.getParent(node)))[traitIndex]; processValues[parentState] += branchTime / 2; } return processValues; }
/** * A constructor for a node-sampled discrete trait * * @param treeModel * @param trait * @param traitIndex * @param rateParameter * @param relativeRatesParameter * @param indicatorParameter */ public DiscreteTraitBranchRateModel( TreeTraitProvider traitProvider, DataType dataType, TreeModel treeModel, TreeTrait trait, int traitIndex, Parameter rateParameter, Parameter relativeRatesParameter, Parameter indicatorParameter) { this(treeModel, traitIndex, rateParameter, relativeRatesParameter, indicatorParameter); // if (trait.getTreeModel() != treeModel) // throw new IllegalArgumentException("Tree Models for ancestral state tree // likelihood and target model of these rates must match!"); this.trait = trait; this.dataType = dataType; if (trait.getTraitName().equals("states")) { // Assume the trait is one or more discrete traits reconstructed at nodes mode = Mode.NODE_STATES; } else /*if (double[].class.isAssignableFrom(trait.getClass()))*/ { // Assume the trait itself is the dwell times for the individual states on the branch above // the node mode = Mode.MARKOV_JUMP_PROCESS; } /* else { throw new IllegalArgumentException("The trait class type is not suitable for use in this class."); } */ if (traitProvider instanceof Model) { addModel((Model) traitProvider); } if (trait instanceof Model) { addModel((Model) trait); // MAS: Does this ever occur? } }