Changeset 9084 for branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/GenealogyGraphChart.cs
- Timestamp:
- 12/20/12 16:27:58 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/GenealogyGraphChart.cs
r8556 r9084 28 28 using HeuristicLab.Common; 29 29 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 30 using HeuristicLab.Problems.DataAnalysis.Symbolic; 30 31 using HeuristicLab.Visualization; 31 32 32 33 namespace HeuristicLab.EvolutionaryTracking.Views { 33 34 public partial class GenealogyGraphChart : ChartControl { 34 private Dictionary< IGenealogyGraphNode, VisualGenealogyGraphNode> visualNodeMap;35 private Dictionary<string, VisualGenealogyGraphNode> visualNodeMap; // map the uid of the genealogy graph vertex with a visual node (in this way each node is uniquely determined) 35 36 private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap; 36 37 private const int Diameter = 20; // node diameter … … 46 47 internal set { 47 48 graph = value; 48 visualNodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>(); 49 // TODO: should move the subtree sorting code out of here and int the view 50 var canonicalSorter = new SymbolicExpressionTreeCanonicalSorter(); 51 // sort subtrees in order to improve matching 52 foreach (var tree in graph.Nodes.Select(n => n.SymbolicExpressionTree)) 53 canonicalSorter.SortSubtrees(tree); 54 55 visualNodeMap = new Dictionary<string, VisualGenealogyGraphNode>(); 49 56 visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>(); 57 58 Chart.Group.Clear(); 50 59 DrawGraph(); 51 60 } 61 } 62 63 private VisualGenealogyGraphNode GetVisualGenealogyGraphNode(IVertex node) { 64 VisualGenealogyGraphNode visualNode; 65 visualNodeMap.TryGetValue(node.Id, out visualNode); 66 return visualNode; 52 67 } 53 68 … … 68 83 Chart.UpdateEnabled = false; 69 84 70 var layers = Graph.Nodes.GroupBy(n => n.Ranks[0]).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList(); 85 var layers = Graph.Nodes.GroupBy(n => n.Rank).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList(); 86 71 87 for (int i = 0; i != layers.Count; ++i) { 72 88 // sort descending by quality (using comparison defined in GenealogyGraphNode class) 73 89 layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b)); 74 90 x = 0; // reset horizontal coordinate 75 // start laying out visual nodes76 91 foreach (var node in layers[i].Nodes) { 77 92 var pen = new Pen(Color.LightGray); … … 80 95 Data = node, 81 96 ToolTipText = "Id: " + node.Label + nl + 82 "Rank s: " + string.Join(",", node.Ranks)+ nl +97 "Rank: " + node.Rank + nl + 83 98 "Quality: " + String.Format("{0:0.0000}", node.Quality) + nl + 84 99 "IsElite: " + node.IsElite 85 100 }; 86 101 Chart.Group.Add(visualNode); 87 if (!visualNodeMap.ContainsKey(node)) 88 visualNodeMap[node] = visualNode; 102 visualNodeMap.Add(node.Id, visualNode); 89 103 90 104 x += Cx; // increment horizontal coordinate … … 94 108 95 109 // connect elites from successive layers with visual arcs 96 if (i > 0) { 97 for (int m = 0; m != layers[i].Nodes.Count; ++m) 98 for (int n = 0; n != layers[i - 1].Nodes.Count; ++n) { 99 if (layers[i].Nodes[m].SymbolicExpressionTree == layers[i - 1].Nodes[n].SymbolicExpressionTree) { 100 var v1 = visualNodeMap[layers[i].Nodes[m]]; 101 var v2 = visualNodeMap[layers[i - 1].Nodes[n]]; 102 var pen = new Pen(Color.LightGray); 103 visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen); 104 } 105 } 110 if (i == 0) continue; 111 var currLayer = layers[i].Nodes; 112 var prevLayer = layers[i - 1].Nodes; 113 foreach (var n in currLayer) { 114 foreach (var m in prevLayer) { 115 if (n.SymbolicExpressionTree != m.SymbolicExpressionTree) continue; 116 var v1 = GetVisualGenealogyGraphNode(n); 117 var v2 = GetVisualGenealogyGraphNode(m); 118 119 var pen = new Pen(Color.LightGray); 120 visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen); 121 } 106 122 } 107 123 } 108 124 // add arcs separately (to avoid some ordering problems) 109 foreach ( var node in visualNodeMap.Keys) {110 var visualNode = visualNodeMap[node];125 foreach (SymbolicExpressionGenealogyGraphNode node in Graph.Nodes) { 126 VisualGenealogyGraphNode visualNode = GetVisualGenealogyGraphNode(node); 111 127 if (node.InEdges == null) continue; 112 128 113 foreach ( vararc in node.InEdges) {114 var visualParent = visualNodeMap[arc.Target];129 foreach (Arc arc in node.InEdges) { 130 var visualParent = GetVisualGenealogyGraphNode(arc.Source); 115 131 var pen = new Pen(Color.Transparent); 116 132 visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen); … … 134 150 135 151 protected override void pictureBox_MouseUp(object sender, MouseEventArgs e) { 136 if (Chart.Mode != ChartMode.Select) 152 if (Chart.Mode != ChartMode.Select) { 137 153 base.pictureBox_MouseUp(sender, e); 138 else { // select mode 139 // get selected node 140 var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList(); 141 if (visualNodes.Count > 0) { 142 if (selectedGenealogyGraphNode == visualNodes[0]) return; 143 selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode; 144 if (selectedGenealogyGraphNode == null) return; 145 // new node has been selected, clean up 146 Chart.UpdateEnabled = false; 147 // clear colors 148 ClearAllNodes(); 149 // use a rectangle to highlight the currently selected genealogy graph node 150 var center = selectedGenealogyGraphNode.Center; 151 var size = selectedGenealogyGraphNode.Size; 152 double x1 = center.X - size.Width / 2; 153 double x2 = x1 + size.Width; 154 double y1 = center.Y - size.Height / 2; 155 double y2 = y1 + size.Height; 156 if (targetRectangle == null) { 157 targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null); 158 Chart.Group.Add(targetRectangle); 159 } else { 160 targetRectangle.SetPosition(x1, y1, x2, y2); 161 } 162 var gNode = selectedGenealogyGraphNode.Data; // genealogy graph node (representing an individual in the population) 163 // double rank = Graph[gNode].Ranks[0]; 164 double rank = ((SymbolicExpressionGenealogyGraphNode)gNode).Ranks[0]; 165 // ancestors 166 var ancestors = gNode.Ancestors().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() < rank).ToList(); 167 ancestors.Add(gNode); 168 // descendants 169 var descendants = gNode.Descendants().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() > rank).ToList(); 170 descendants.Add(gNode); 171 // highlight ancestors 172 foreach (var node in ancestors.Select(n => visualNodeMap[n])) { 173 node.Brush = new SolidBrush(((SymbolicExpressionGenealogyGraphNode)node.Data).GetColor()); 174 if (node.IncomingArcs != null) 175 foreach (var arc in node.IncomingArcs) { 176 var start = new Point((int)arc.Start.X, (int)arc.Start.Y); 177 var end = new Point((int)arc.End.X, (int)arc.End.Y); 178 var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode; 179 var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode; 180 arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor()); 181 } 182 } 183 // highlight descendants 184 foreach (var node in descendants.Select(n => visualNodeMap[n])) { 185 node.Brush = new SolidBrush((node.Data as SymbolicExpressionGenealogyGraphNode).GetColor()); 186 if (node.OutgoingArcs != null) 187 foreach (var arc in node.OutgoingArcs) { 188 var start = new Point((int)arc.Start.X, (int)arc.Start.Y); 189 var end = new Point((int)arc.End.X, (int)arc.End.Y); 190 var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode; 191 var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode; 192 arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor()); 193 } 194 } 195 } else { 196 selectedGenealogyGraphNode = null; 197 } 198 // update 199 Chart.UpdateEnabled = true; 200 Chart.EnforceUpdate(); 201 if (selectedGenealogyGraphNode != null) 202 /* emit clicked event */ 203 OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e); 154 return; 155 } 156 var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList(); 157 if (visualNodes.Count <= 0) { 158 selectedGenealogyGraphNode = null; 159 return; 160 } 161 if (selectedGenealogyGraphNode == visualNodes[0]) return; 162 selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode; 163 if (selectedGenealogyGraphNode == null) return; 164 // new node has been selected, clean up 165 Chart.UpdateEnabled = false; 166 // clear colors 167 ClearAllNodes(); 168 // use a rectangle to highlight the currently selected genealogy graph node 169 MarkSelectedNode(); 170 var gNode = selectedGenealogyGraphNode.Data; 171 var visualNode = GetVisualGenealogyGraphNode(gNode); 172 173 DrawLineage(visualNode, n => n.IncomingArcs, a => a.Source); 174 DrawLineage(visualNode, n => n.OutgoingArcs, a => a.Target); 175 176 // update 177 Chart.UpdateEnabled = true; 178 Chart.EnforceUpdate(); 179 180 if (selectedGenealogyGraphNode != null) 181 /* emit clicked event */ 182 OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e); 183 } 184 185 private void DrawLineage(VisualGenealogyGraphNode node, 186 Func<VisualGenealogyGraphNode, IEnumerable<VisualGenealogyGraphArc>> arcSelector, 187 Func<VisualGenealogyGraphArc, VisualGenealogyGraphNode> nodeSelector) { 188 node.Brush = new SolidBrush(node.Data.GetColor()); 189 var arcs = arcSelector(node); 190 foreach (var arc in arcs) { 191 var source = arc.Source.Data; 192 var target = arc.Target.Data; 193 var start = new Point((int)arc.Start.X, (int)arc.Start.Y); 194 var end = new Point((int)arc.End.X, (int)arc.End.Y); 195 arc.Pen.Brush = new LinearGradientBrush(start, end, source.GetColor(), target.GetColor()); 196 DrawLineage(nodeSelector(arc), arcSelector, nodeSelector); 197 } 198 } 199 200 void MarkSelectedNode() { 201 var center = selectedGenealogyGraphNode.Center; 202 var size = selectedGenealogyGraphNode.Size; 203 double x1 = center.X - size.Width / 2; 204 double x2 = x1 + size.Width; 205 double y1 = center.Y - size.Height / 2; 206 double y2 = y1 + size.Height; 207 if (targetRectangle == null) { 208 targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null); 209 Chart.Group.Add(targetRectangle); 210 } else { 211 targetRectangle.SetPosition(x1, y1, x2, y2); 204 212 } 205 213 } … … 209 217 if (primitive is VisualGenealogyGraphArc) { 210 218 var arc = primitive as VisualGenealogyGraphArc; 211 var sourceData = (arc.Source.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree; 212 var targetData = (arc.Target.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree; 213 if (sourceData != targetData) { 214 primitive.Pen.Brush = new SolidBrush(Color.Transparent); 215 } else { 216 primitive.Pen.Brush = new SolidBrush(Color.LightGray); 217 } 219 var sourceData = arc.Source.Data.SymbolicExpressionTree; 220 var targetData = arc.Target.Data.SymbolicExpressionTree; 221 primitive.Pen.Brush = sourceData != targetData ? new SolidBrush(Color.Transparent) : new SolidBrush(Color.LightGray); 218 222 } else { 219 223 primitive.Brush = null; … … 222 226 } 223 227 224 public void HighlightLineage(IEnumerable<GenealogyGraphNode> nodes) {225 foreach (var node in nodes.Select(n => visualNodeMap[n])) {226 node.Brush = new SolidBrush((node.Data as SymbolicExpressionGenealogyGraphNode).GetColor());227 if (node.IncomingArcs == null || node != visualNodeMap[node.Data]) continue;228 foreach (var arc in node.IncomingArcs) {229 if (arc.Source.Data == node.Data) continue;230 var start = new Point((int)arc.Start.X, (int)arc.Start.Y);231 var end = new Point((int)arc.End.X, (int)arc.End.Y);232 var srcNode = arc.Source.Data as SymbolicExpressionGenealogyGraphNode;233 var destNode = arc.Target.Data as SymbolicExpressionGenealogyGraphNode;234 arc.Pen.Brush = new LinearGradientBrush(start, end, srcNode.GetColor(), destNode.GetColor());235 }236 }237 }238 239 228 // TODO: optimize and reduce complexity of this method 240 229 public void HighlightNodes(IEnumerable<ISymbolicExpressionTree> trees, Color color) { 241 foreach (var tree in trees) 242 foreach (var graphNode in Graph.Nodes) { 243 if (graphNode.SymbolicExpressionTree == tree) { 244 var visualNode = visualNodeMap[graphNode]; 245 visualNode.Brush = new SolidBrush(color); 246 } 247 } 230 foreach (var tree in trees) { 231 var graphNodes = graph.GetGraphNodes(tree); 232 foreach (var graphNode in graphNodes) { 233 GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color); 234 } 235 } 248 236 } 249 237 250 238 public void HighlightNode(SymbolicExpressionGenealogyGraphNode graphNode, Color color) { 251 visualNodeMap[graphNode].Brush = new SolidBrush(color);239 GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color); 252 240 } 253 241 … … 257 245 double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count); 258 246 foreach (var graphNode in Graph.Nodes) { 259 var visualNode = visualNodeMap[graphNode];247 var visualNode = GetVisualGenealogyGraphNode(graphNode); 260 248 double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count; 261 249 int index = (int)(deg / max * ColorGradient.Colors.Count); … … 274 262 double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count); 275 263 foreach (var graphNode in graphNodes) { 276 var visualNode = visualNodeMap[graphNode];264 var visualNode = GetVisualGenealogyGraphNode(graphNode); 277 265 double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count; 278 266 int index = (int)(deg / max * ColorGradient.Colors.Count);
Note: See TracChangeset
for help on using the changeset viewer.