/** * Places into Color array the colors at the node, and returns the number of colors. Uses passed * stateColors as color key. If null is passed, uses color system of parent data (using maxState * of this StsOfCharcter) or, if there is not parent data object, the default colors. */ public int getColorsAtNode( int node, ColorDistribution colors, MesquiteColorTable stateColors, boolean showWeights) { int numBinBoundaries = 10; double[] binBoundaries = stateColors.getPreferredBinBoundaries(); if (binBoundaries != null) numBinBoundaries = binBoundaries.length; for (int i = 0; i < 10; i++) colors.initialize(); if (getNumItems() == 1) { double s = firstItem.getValue(node); colors.setWeight(0, 1.0); if (!MesquiteDouble.isCombinable(s)) colors.setColor(0, ColorDistribution.unassigned); else { int place = getPlace(s, stateColors); // (int)(((s-minState)/(maxState-minState))*numBinBoundaries); colors.setColor(0, stateColors.getColor(numBinBoundaries, place)); } } else { for (int i = 0; i < getNumItems(); i++) { double s = getState(node, i); colors.setWeight(i, 1.0 / getNumItems()); if (!MesquiteDouble.isCombinable(s)) colors.setColor(0, ColorDistribution.unassigned); else { int place = getPlace( s, stateColors); // (int)(((s-minState)/(maxState-minState))*numBinBoundaries); colors.setColor(i, stateColors.getColor(numBinBoundaries, place)); } } } return getNumItems(); }
/*..........................................ContinuousHistory................*/ public void calcMinMaxStates(Tree tree, int node) { for (int i = 0; i < getNumItems(); i++) { double s = getState(node, i); maxState = MesquiteDouble.maximum(maxState, s); minState = MesquiteDouble.minimum(minState, s); } for (int d = tree.firstDaughterOfNode(node); tree.nodeExists(d); d = tree.nextSisterOfNode(d)) calcMinMaxStates(tree, d); }
/*..........................................MContinuousStates................*/ public boolean allCombinable(int item) { for (int ic = 0; ic < getNumChars(); ic++) for (int it = 0; it < getNumNodes(); it++) { if (!MesquiteDouble.isCombinable(getState(ic, it, item))) return false; } return true; }
double sumSqFILTERED(double[][] m, double mean) { double sumSq = 0; for (int i = 0; i < m.length; i++) for (int j = 0; j < i; j++) { double d = m[i][j]; if (d >= -0.0000000001 && MesquiteDouble.isCombinable(d)) sumSq += (d - mean) * (d - mean); } return sumSq; }
void reinterpret(MesquiteTree tree, int node) { if (tree.nodeIsInternal(node)) { if (tree.nodeHasLabel(node)) { String label = tree.getNodeLabel(node); if (isNumber) { double d = MesquiteDouble.fromString(label); if (MesquiteDouble.isCombinable(d)) tree.setAssociatedDouble(nameRef, node, d, appliesToBranch); } else { tree.setAssociatedObject(nameRef, node, label, appliesToBranch); } if (deleteAfter) tree.setNodeLabel(null, node); } for (int daughter = tree.firstDaughterOfNode(node); tree.nodeExists(daughter); daughter = tree.nextSisterOfNode(daughter)) { reinterpret(tree, daughter); } } }
/** * places into the already instantiated ColorDistribution the colors corresponding to the * CharacterState, and returns the number of colors. Uses default colors. Mode is * MesquiteColorTable.GRAYSCALE, COLORS, COLORS_NO_BW, or DEFAULT (default depends on subclass) */ public int getColorsOfState( CharacterState state, ColorDistribution colors, MesquiteColorTable colorTable) { if (colors == null || state == null || !(state instanceof ContinuousState)) return 0; int numBinBoundaries = 10; double[] binBoundaries = colorTable.getPreferredBinBoundaries(); if (binBoundaries != null) numBinBoundaries = binBoundaries.length; colors.initialize(); ContinuousState cState = (ContinuousState) state; if (cState.getNumItems() == 1) { double s = cState.getValue(0); colors.setWeight(0, 1.0); if (!MesquiteDouble.isCombinable(s)) colors.setColor(0, Color.white); else { int place = getPlace(s, colorTable); // (int)(((s-minState)/(maxState-minState))*numBinBoundaries); colors.setColor( 0, colorTable.getColor( numBinBoundaries, place)); // bug fixed in 1. 12 that had been introduced in 1. 10 // colors.setColor(0, colorTable.getColor(s, minState, maxState)); 1.10 to 1.11 } } else { for (int i = 0; i < cState.getNumItems(); i++) { double s = cState.getValue(i); colors.setWeight(i, 1.0 / cState.getNumItems()); if (!MesquiteDouble.isCombinable(s)) colors.setColor(0, Color.white); else { int place = getPlace( s, colorTable); // (int)(((s-minState)/(maxState-minState))*numBinBoundaries); colors.setColor( i, colorTable.getColor( numBinBoundaries, place)); // bug fixed in 1. 12 that had been introduced in 1. 10 // colors.setColor(i, colorTable.getColor(s, minState, maxState)); 1.10 to 1.11 } } } return cState.getNumItems(); }
/*.......................................... ContinuousHistory ..................................................*/ public int getPlace(double d, MesquiteColorTable colorTable) { int numBinBoundaries = 10; double[] binBoundaries = colorTable.getPreferredBinBoundaries(); if (binBoundaries != null) numBinBoundaries = binBoundaries.length; else return (int) (((d - minState) / (maxState - minState)) * numBinBoundaries); for (int e = 0; e <= numBinBoundaries; e++) { double localMin, localMax; int localE; int localNumBoundaries; // here look for closest defined bin boundaries localMin = minState; localMax = MesquiteDouble.unassigned; int localMinK = -1; int localMaxK = numBinBoundaries; for (int k = 0; k < numBinBoundaries; k++) { if (MesquiteDouble.isCombinable(binBoundaries[k])) { if (k < e) { localMin = binBoundaries[k]; localMinK = k; } else if (!MesquiteDouble.isCombinable(localMax)) { localMax = binBoundaries[k]; localMaxK = k; } } } if (!MesquiteDouble.isCombinable(localMax)) localMax = maxState; if (localMax < localMin) localMax = localMin; localE = e - localMinK - 1; localNumBoundaries = localMaxK - localMinK; double rangeUnit = (localMax - localMin) * 1.0; if (localNumBoundaries != 0) rangeUnit = rangeUnit / localNumBoundaries; if (d <= localMin + rangeUnit * (localE + 1)) // d > localMin + rangeUnit*localE && return e; } return numBinBoundaries; }
/** * Must be called before a tree is shaded. Goes through all nodes to find states present, to set * minima and maxima. */ public void prepareColors(Tree tree, int drawnRoot) { minState = MesquiteDouble.unassigned; maxState = MesquiteDouble.unassigned; calcMinMaxStates(tree, drawnRoot); if (getParentData() != null && getParentCharacter() >= 0) { int ic = getParentCharacter(); ContinuousData data = ((ContinuousData) getParentData()); for (int it = 0; it < data.getNumTaxa(); it++) { double s = data.getState(ic, it, 0); maxState = MesquiteDouble.maximum(maxState, s); minState = MesquiteDouble.minimum(minState, s); } } else if (getObservedStates() != null) { int ic = getParentCharacter(); ContinuousDistribution data = (ContinuousDistribution) getObservedStates(); for (int it = 0; it < data.getNumNodes(); it++) { double s = data.getState(it); maxState = MesquiteDouble.maximum(maxState, s); minState = MesquiteDouble.minimum(minState, s); } } }
/*.......................................... ContinuousHistory ..................................................*/ public double getBinBoundary(int i, MesquiteColorTable colorTable) { // the boundary after bin i int numBinBoundaries = 10; double[] binBoundaries = colorTable.getPreferredBinBoundaries(); if (binBoundaries != null) numBinBoundaries = binBoundaries.length; else return minState + (i + 1) * (maxState - minState) / numBinBoundaries; double localMin, localMax; int localE; localMin = minState; localMax = MesquiteDouble.unassigned; int localNumBoundaries; int localMinK = -1; int localMaxK = numBinBoundaries; for (int k = 0; k < numBinBoundaries; k++) { // what are the defined boundaries on either side of i? if (MesquiteDouble.isCombinable(binBoundaries[k])) { if (k < i) { localMin = binBoundaries[k]; localMinK = k; } else if (!MesquiteDouble.isCombinable(localMax)) { localMax = binBoundaries[k]; localMaxK = k; } } } if (!MesquiteDouble.isCombinable(localMax)) localMax = maxState; if (localMax < localMin) localMax = localMin; localE = i - localMinK - 1; localNumBoundaries = localMaxK - localMinK; double rangeUnit = (localMax - localMin) * 1.0; if (localNumBoundaries > 0) rangeUnit = rangeUnit / localNumBoundaries; return localMin + rangeUnit * (localE + 1); }
double meanFILTERED(double[][] m) { double sum = 0; int n = 0; for (int i = 0; i < m.length; i++) for (int j = 0; j < i; j++) { double d = m[i][j]; if (d >= -0.0000000001 && MesquiteDouble.isCombinable(d)) { sum += d; n++; } } if (n == 0) return MesquiteDouble.unassigned; return sum / n; }
// by filtered means -ve and uncombinable numbers excluded double offDiagonalPMCorrelationFILTERED(double[][] m1, double[][] m2) { if (m1 == null || m2 == null) return MesquiteDouble.unassigned; double mean1 = meanFILTERED(m1); double mean2 = meanFILTERED(m2); if (!MesquiteDouble.isCombinable(mean1) || !MesquiteDouble.isCombinable(mean2)) return MesquiteDouble.unassigned; double sumSq1 = sumSqFILTERED(m1, mean1); double sumSq2 = sumSqFILTERED(m2, mean2); double sumProd = 0; for (int i = 0; i < m1.length; i++) for (int j = 0; j < i; j++) { double d1 = m1[i][j]; double d2 = m2[i][j]; if (d1 >= -0.0000000001 && MesquiteDouble.isCombinable(d1) && d2 >= -0.0000000001 && MesquiteDouble.isCombinable(d2)) sumProd += (d1 - mean1) * (d2 - mean2); } if (sumSq1 == 0 || sumSq2 == 0) return MesquiteDouble.unassigned; return sumProd / Math.sqrt(sumSq1 * sumSq2); }
/*..........................................ContinuousHistory................*/ public int getLegendStates( Color[] cs, String[] stateNames, Point[] tableMappings, MesquiteColorTable stateColors) { int colorCount = 0; int numBinBoundaries = 10; double[] binBoundaries = stateColors.getPreferredBinBoundaries(); if (binBoundaries != null) numBinBoundaries = binBoundaries.length; for (int e = 0; e <= numBinBoundaries; e++) { if (binBoundaries == null) { double rangeUnit = (maxState - minState) * 1.0 / numBinBoundaries; cs[colorCount] = stateColors.getColor(numBinBoundaries, e); if (tableMappings != null) tableMappings[colorCount] = new Point(numBinBoundaries, e); stateNames[colorCount++] = MesquiteDouble.toString(minState + rangeUnit * e) + " to " + MesquiteDouble.toString(minState + rangeUnit * (e + 1)); } else { double localMin, localMax; int localE; int localNumBoundaries; // here look for closest defined bin boundaries localMin = minState; localMax = MesquiteDouble.unassigned; int localMinK = -1; int localMaxK = numBinBoundaries; for (int k = 0; k < numBinBoundaries; k++) { if (MesquiteDouble.isCombinable(binBoundaries[k])) { if (k < e) { localMin = binBoundaries[k]; localMinK = k; } else if (!MesquiteDouble.isCombinable(localMax)) { localMax = binBoundaries[k]; localMaxK = k; } } } if (!MesquiteDouble.isCombinable(localMax)) localMax = maxState; if (localMax < localMin) localMax = localMin; localE = e - localMinK - 1; localNumBoundaries = localMaxK - localMinK; double rangeUnit = (localMax - localMin) * 1.0; if (localNumBoundaries != 0) rangeUnit = rangeUnit / localNumBoundaries; cs[colorCount] = stateColors.getColor(numBinBoundaries, e); if (tableMappings != null) tableMappings[colorCount] = new Point(numBinBoundaries, e); stateNames[colorCount++] = MesquiteDouble.toString(localMin + rangeUnit * localE) + " to " + MesquiteDouble.toString(localMin + rangeUnit * (localE + 1)); } } return colorCount; }
/*.................................................................................................................*/ public void calculateNumber( Tree tree1, Tree tree2, MesquiteNumber result, MesquiteString resultString) { if (result == null) return; clearResultAndLastResult(result); if (tree1 == null) return; if (tree2 == null) return; int numTaxa = tree1.getTaxa().getNumTaxa(); double[][] patristic1 = null; patristic1 = p1.calculatePatristic( tree1, numTaxa, patristic1); // for this tree calculate patristic distances (number of nodes separating // terminals; no branch lengths) double[][] patristic2 = null; patristic2 = p2.calculatePatristic( tree2, numTaxa, patristic2); // for this tree calculate patristic distances (number of nodes separating // terminals; no branch lengths) double correl = offDiagonalPMCorrelationFILTERED(patristic1, patristic2); if (isDistance && (MesquiteDouble.isCombinable(correl))) correl = -correl + 1.0; // shifting 1 to -1 to be 0 to 2 to act as distance result.setValue(correl); if (resultString != null) { if (isDistance) resultString.setValue( "Patristic correlation (converted to distance): " + result.toString()); else resultString.setValue("Patristic correlation: " + result.toString()); } saveLastResult(result); saveLastResultString(resultString); }
/*.................................................................................................................*/ public Object doCommand(String commandName, String arguments, CommandChecker checker) { Tree trt = treeDisplay.getTree(); MesquiteTree t = null; if (trt instanceof MesquiteTree) t = (MesquiteTree) trt; if (checker.compare( this.getClass(), "Adjust tool has touched branch", "[branch number][x coordinate touched][y coordinate touched][modifiers]", commandName, "touchedPositionAdjust")) { if (t == null) return null; MesquiteInteger io = new MesquiteInteger(0); int node = MesquiteInteger.fromString(arguments, io); int x = MesquiteInteger.fromString(arguments, io); int y = MesquiteInteger.fromString(arguments, io); String mod = ParseUtil.getRemaining(arguments, io); Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y); originalX = newOnLine.x; originalY = newOnLine.y; // lastX= newOnLine.x; // lastY = newOnLine.y; Graphics g = null; if (GraphicsUtil.useXORMode(null, false)) { g = treeDisplay.getGraphics(); g.setXORMode(Color.white); g.setColor(Color.red); } // double bX = treeDisplay.getTreeDrawing().lineBaseX[node]; // double bY = treeDisplay.getTreeDrawing().lineBaseY[node]; // Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX)); lastBL = tree.getBranchLength(node); double shortestAbove = MesquiteDouble.unassigned; for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter)) shortestAbove = MesquiteDouble.minimum(shortestAbove, tree.getBranchLength(daughter)); if (shortestAbove == MesquiteDouble.unassigned) upperLimit = MesquiteDouble.infinite; else if (MesquiteDouble.isCombinable(lastBL)) upperLimit = shortestAbove + lastBL; else upperLimit = shortestAbove + 1.0; int ibX = treeDisplay.getTreeDrawing().lineBaseX[node]; int ibY = treeDisplay.getTreeDrawing().lineBaseY[node]; lastX = treeDisplay.getTreeDrawing().lineTipX[node]; lastY = treeDisplay.getTreeDrawing().lineTipY[node]; if (GraphicsUtil.useXORMode(null, false)) { drawThickLine(g, ibX, ibY, lastX, lastY); for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter)) drawThickLine( g, treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], lastX, lastY); g.fillOval( lastX - ovalRadius, lastY - ovalRadius, ovalRadius + ovalRadius, ovalRadius + ovalRadius); try { g.drawString(MesquiteDouble.toString(lastBL), lastX + 10, lastY); } catch (InternalError e) { // workaround for bug on windows java 1.7. } catch (Throwable e) { } lineOn = true; g.dispose(); } } else if (checker.compare( this.getClass(), "Adjust tool has been dropped", "[branch number][x coordinate dropped][y coordinate dropped]", commandName, "droppedPositionAdjust")) { if (t == null) return null; if (editorOn) return null; MesquiteInteger io = new MesquiteInteger(0); int node = MesquiteInteger.fromString(arguments, io); int x = MesquiteInteger.fromString(arguments, io); int y = MesquiteInteger.fromString(arguments, io); if (lineOn) { Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y); double bX = treeDisplay.getTreeDrawing().lineBaseX[node]; double bY = treeDisplay.getTreeDrawing().lineBaseY[node]; double tX = treeDisplay.getTreeDrawing().lineTipX[node]; double tY = treeDisplay.getTreeDrawing().lineTipY[node]; double lengthLine = Math.sqrt((originalY - bY) * (originalY - bY) + (originalX - bX) * (originalX - bX)); double bL; if (lengthLine != 0) { double extension = Math.sqrt( (newOnLine.y - bY) * (newOnLine.y - bY) + (newOnLine.x - bX) * (newOnLine.x - bX)) / lengthLine; if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) bL = extension; else bL = t.getBranchLength(node) * extension; } else bL = 1; if (bL > upperLimit) bL = upperLimit; else if (bL < lowerLimit) bL = lowerLimit; double oldBL = t.getBranchLength(node); if (!MesquiteDouble.isCombinable(oldBL)) oldBL = 1.0; t.setBranchLength(node, bL, false); double difference = oldBL - t.getBranchLength(node); for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter)) if (MesquiteDouble.isCombinable(t.getBranchLength(daughter))) t.setBranchLength(daughter, t.getBranchLength(daughter) + difference, false); t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED)); Graphics g = treeDisplay.getGraphics(); g.setPaintMode(); g.dispose(); treeDisplay.pleaseUpdate(true); lineOn = false; } } else if (checker.compare( this.getClass(), "Adjust tool is being dragged", "[branch number][x coordinate][y coordinate]", commandName, "draggedPositionAdjust")) { if (t == null) return null; if (editorOn) return null; MesquiteInteger io = new MesquiteInteger(0); int node = MesquiteInteger.fromString(arguments, io); int x = MesquiteInteger.fromString(arguments, io); int y = MesquiteInteger.fromString(arguments, io); if (lineOn) { Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y); // WARNING": This shouldn't result in length increase if simple click and release with no // drag; must subtract original X, Y Graphics g = null; if (GraphicsUtil.useXORMode(null, false)) { g = treeDisplay.getGraphics(); g.setXORMode(Color.white); g.setColor(Color.red); } // g.fillOval(lastX-ovalRadius, lastY-ovalRadius, ovalRadius + ovalRadius, ovalRadius + // ovalRadius); // g.fillOval(newOnLine.x-ovalRadius, newOnLine.y -ovalRadius, ovalRadius + ovalRadius, // ovalRadius + ovalRadius); // g.drawLine(originalX, originalY, lastX, lastY); // g.drawLine(originalX, originalY, newOnLine.x, newOnLine.y); // if decreasing, & unassigned involved: push unassigned down and assign values to // unassigned above; if increasing, push unassigne up int ibX = treeDisplay.getTreeDrawing().lineBaseX[node]; int ibY = treeDisplay.getTreeDrawing().lineBaseY[node]; int itX = treeDisplay.getTreeDrawing().lineTipX[node]; int itY = treeDisplay.getTreeDrawing().lineTipY[node]; double bX = ibX; double bY = ibY; double tX = itX; double tY = itY; double lengthLine = Math.sqrt((originalY - bY) * (originalY - bY) + (originalX - bX) * (originalX - bX)); if (lengthLine != 0) { if (GraphicsUtil.useXORMode(null, false)) { if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble() >= 1.5 && MesquiteTrunk.getJavaVersionAsDouble() < 1.6) // due to a JVM bug g.fillRect(lastX, lastY - 20, 100, 20); g.drawString(MesquiteDouble.toString(lastBL), lastX + 10, lastY); if (MesquiteTrunk.isMacOSX() && MesquiteTrunk.getJavaVersionAsDouble() >= 1.5 && MesquiteTrunk.getJavaVersionAsDouble() < 1.6) // due to a JVM bug g.fillRect(lastX, lastY - 20, 100, 20); } double extension = Math.sqrt( (newOnLine.y - bY) * (newOnLine.y - bY) + (newOnLine.x - bX) * (newOnLine.x - bX)) / lengthLine; double bL; if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) bL = extension; else bL = t.getBranchLength(node) * extension; if (bL > upperLimit) { bL = upperLimit; if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) extension = upperLimit; else extension = upperLimit / t.getBranchLength(node); } else if (bL < lowerLimit) { bL = lowerLimit; if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) extension = lowerLimit; else extension = lowerLimit / t.getBranchLength(node); } lastBL = bL; if (GraphicsUtil.useXORMode(null, false)) { drawThickLine(g, ibX, ibY, lastX, lastY); for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter)) drawThickLine( g, treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], lastX, lastY); g.fillOval( lastX - ovalRadius, lastY - ovalRadius, ovalRadius + ovalRadius, ovalRadius + ovalRadius); } int newX = ibX + (int) (extension * (tX - bX)); int newY = ibY + (int) (extension * (tY - bY)); if (GraphicsUtil.useXORMode(null, false)) { g.drawString(MesquiteDouble.toString(bL), newX + 10, newY); drawThickLine(g, ibX, ibY, newX, newY); for (int daughter = t.firstDaughterOfNode(node); t.nodeExists(daughter); daughter = t.nextSisterOfNode(daughter)) drawThickLine( g, treeDisplay.getTreeDrawing().lineTipX[daughter], treeDisplay.getTreeDrawing().lineTipY[daughter], newX, newY); g.fillOval( newX - ovalRadius, newY - ovalRadius, ovalRadius + ovalRadius, ovalRadius + ovalRadius); } lastX = newX; lastY = newY; } // lastX= newOnLine.x; // lastY = newOnLine.y; } } return null; }
/*.......................................... ..................................................*/ public boolean legalValue(int ic, double states) { return !MesquiteDouble.isCombinable(states) || ((ic == LATITUDE && states >= -90.0 && states <= 90.0) || (ic == LONGITUDE && states >= -180.0 && states <= 180.0)); }