private static Triple<ClusterViewNode, RowKey, RowKey> buildNewTree( final Map<DendrogramNode, Map<Pair<RowKey, RowKey>, Number>> m, final DendrogramNode root, final Map<RowKey, Pair<DataRow, Integer>> rows, ExecutionContext exec) throws CanceledExecutionException { if (root.isLeaf()) { final Pair<DataRow, Integer> leafRow = rows.get(RowKeyHelper.getKey(root)); return Triple.apply( new ClusterViewNode(leafRow.getFirst().getKey()), leafRow.getFirst().getKey(), leafRow.getFirst().getKey()); } final Triple<ClusterViewNode, RowKey, RowKey> firstTree = buildNewTree(m, root.getFirstSubnode(), rows, exec); exec.checkCanceled(); final Triple<ClusterViewNode, RowKey, RowKey> secondTree = buildNewTree(m, root.getSecondSubnode(), rows, exec); final Map<Pair<RowKey, RowKey>, Number> map = m.get(root); Pair<RowKey, RowKey> pairNoChange = Pair.create(firstTree.getO3(), secondTree.getO2()); if (!map.containsKey(pairNoChange)) { pairNoChange = flip(pairNoChange); } Pair<RowKey, RowKey> pairChange = Pair.create(secondTree.getO3(), firstTree.getO2()); if (!map.containsKey(pairChange)) { pairChange = flip(pairChange); } assert map.containsKey(pairNoChange); assert map.containsKey(pairChange); final double noChangeValue = map.get(pairNoChange).doubleValue(); final double changeValue = map.get(pairChange).doubleValue(); if (noChangeValue > changeValue) { return Triple.apply( new ClusterViewNode(firstTree.getO1(), secondTree.getO1(), root.getDist()), firstTree.getO2(), secondTree.getO3()); } return Triple.apply( new ClusterViewNode(secondTree.getO1(), firstTree.getO1(), root.getDist()), secondTree.getO2(), firstTree.getO3()); }
@Override protected PortObject[] execute(final PortObject[] inObjects, final ExecutionContext exec) throws Exception { // Initialising exec.setMessage("initialising"); final ClusterTreeModel model = (ClusterTreeModel) inObjects[0]; final BufferedDataTable data = (BufferedDataTable) inObjects[1]; final int distanceColumnIdx = data.getDataTableSpec().findColumnIndex(distanceColumnModel.getColumnName()); final Map<RowKey, DistanceVectorDataValue> distanceMatrix = new HashMap<RowKey, DistanceVectorDataValue>(); for (final DataRow dataRow : data) { final DistanceVectorDataValue distanceVector = (DistanceVectorDataValue) dataRow.getCell(distanceColumnIdx); distanceMatrix.put(dataRow.getKey(), distanceVector); } exec.setMessage("computing"); final DendrogramNode origRoot = model.getRoot(); final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> m = visit( origRoot, new HashMap<Triple<DendrogramNode, RowKey, RowKey>, Number>(), distanceMatrix, model.getClusterDistances().length + 1, exec.createSilentSubExecutionContext(.9)); final Map<RowKey, Pair<DataRow, Integer>> rows = new HashMap<RowKey, Pair<DataRow, Integer>>(); int idx = 0; for (final DataRow dataRow : data) { rows.put(dataRow.getKey(), Pair.create(dataRow, Integer.valueOf(idx++))); } exec.setMessage("creating final tree"); final ClusterViewNode tree = buildNewTree(convertM(m), origRoot, rows, exec).getO1(); final ArrayList<DistanceVectorDataValue> origList = new ArrayList<DistanceVectorDataValue>(model.getClusterDistances().length + 1), newList = new ArrayList<DistanceVectorDataValue>(model.getClusterDistances().length + 1); flatten(origRoot, origList, distanceMatrix); exec.checkCanceled(); flatten(tree, newList, distanceMatrix); logger.info("Before: " + sumDistance(origList)); logger.info("After: " + sumDistance(newList)); final ClusterTreeModel clusterTreeModel = new ClusterTreeModel( (DataTableSpec) model.getSpec(), tree, model.getClusterDistances(), model.getClusterDistances().length + 1) { @Override public String getSummary() { return "Before: " + sumDistance(origList) + "\nAfter: " + sumDistance(newList); } }; return new PortObject[] {clusterTreeModel}; }
private Map<DendrogramNode, Map<Pair<RowKey, RowKey>, Number>> convertM( final Map<Triple<DendrogramNode, RowKey, RowKey>, Number> m) { final Map<DendrogramNode, Map<Pair<RowKey, RowKey>, Number>> ret = new HashMap<DendrogramNode, Map<Pair<RowKey, RowKey>, Number>>(); for (final Entry<Triple<DendrogramNode, RowKey, RowKey>, Number> entry : m.entrySet()) { final Triple<DendrogramNode, RowKey, RowKey> entryKey = entry.getKey(); final DendrogramNode key = entryKey.getO1(); if (!ret.containsKey(key)) { ret.put(key, new HashMap<Pair<RowKey, RowKey>, Number>()); } // ENH keep only the winner ret.get(key).put(Pair.create(entryKey.getO2(), entryKey.getO3()), entry.getValue()); } return ret; }
private static Pair<RowKey, RowKey> flip(Pair<RowKey, RowKey> pairNoChange) { return Pair.create(pairNoChange.getSecond(), pairNoChange.getFirst()); }