Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/20/12 16:27:58 (11 years ago)
Author:
bburlacu
Message:

#1772: HeuristicLab.EvolutionaryTracking.Views: refactored the GenealogyGraphChart and the GenealogyGraphView. Fixed lineage display bug.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.EvolutionaryTracking/HeuristicLab.EvolutionaryTracking.Views/3.4/GenealogyGraphChart.cs

    r8556 r9084  
    2828using HeuristicLab.Common;
    2929using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
     30using HeuristicLab.Problems.DataAnalysis.Symbolic;
    3031using HeuristicLab.Visualization;
    3132
    3233namespace HeuristicLab.EvolutionaryTracking.Views {
    3334  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)
    3536    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap;
    3637    private const int Diameter = 20; // node diameter
     
    4647      internal set {
    4748        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>();
    4956        visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
     57
     58        Chart.Group.Clear();
    5059        DrawGraph();
    5160      }
     61    }
     62
     63    private VisualGenealogyGraphNode GetVisualGenealogyGraphNode(IVertex node) {
     64      VisualGenealogyGraphNode visualNode;
     65      visualNodeMap.TryGetValue(node.Id, out visualNode);
     66      return visualNode;
    5267    }
    5368
     
    6883      Chart.UpdateEnabled = false;
    6984
    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
    7187      for (int i = 0; i != layers.Count; ++i) {
    7288        // sort descending by quality (using comparison defined in GenealogyGraphNode class)
    7389        layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b));
    7490        x = 0; // reset horizontal coordinate
    75         // start laying out visual nodes
    7691        foreach (var node in layers[i].Nodes) {
    7792          var pen = new Pen(Color.LightGray);
     
    8095            Data = node,
    8196            ToolTipText = "Id: " + node.Label + nl +
    82                           "Ranks: " + string.Join(",", node.Ranks) + nl +
     97                          "Rank: " + node.Rank + nl +
    8398                          "Quality: " + String.Format("{0:0.0000}", node.Quality) + nl +
    8499                          "IsElite: " + node.IsElite
    85100          };
    86101          Chart.Group.Add(visualNode);
    87           if (!visualNodeMap.ContainsKey(node))
    88             visualNodeMap[node] = visualNode;
     102          visualNodeMap.Add(node.Id, visualNode);
    89103
    90104          x += Cx; // increment horizontal coordinate
     
    94108
    95109        // 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          }
    106122        }
    107123      }
    108124      // 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);
    111127        if (node.InEdges == null) continue;
    112128
    113         foreach (var arc in node.InEdges) {
    114           var visualParent = visualNodeMap[arc.Target];
     129        foreach (Arc arc in node.InEdges) {
     130          var visualParent = GetVisualGenealogyGraphNode(arc.Source);
    115131          var pen = new Pen(Color.Transparent);
    116132          visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
     
    134150
    135151    protected override void pictureBox_MouseUp(object sender, MouseEventArgs e) {
    136       if (Chart.Mode != ChartMode.Select)
     152      if (Chart.Mode != ChartMode.Select) {
    137153        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);
    204212      }
    205213    }
     
    209217        if (primitive is VisualGenealogyGraphArc) {
    210218          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);
    218222        } else {
    219223          primitive.Brush = null;
     
    222226    }
    223227
    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 
    239228    // TODO: optimize and reduce complexity of this method
    240229    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      }
    248236    }
    249237
    250238    public void HighlightNode(SymbolicExpressionGenealogyGraphNode graphNode, Color color) {
    251       visualNodeMap[graphNode].Brush = new SolidBrush(color);
     239      GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color);
    252240    }
    253241
     
    257245      double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
    258246      foreach (var graphNode in Graph.Nodes) {
    259         var visualNode = visualNodeMap[graphNode];
     247        var visualNode = GetVisualGenealogyGraphNode(graphNode);
    260248        double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count;
    261249        int index = (int)(deg / max * ColorGradient.Colors.Count);
     
    274262      double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
    275263      foreach (var graphNode in graphNodes) {
    276         var visualNode = visualNodeMap[graphNode];
     264        var visualNode = GetVisualGenealogyGraphNode(graphNode);
    277265        double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count;
    278266        int index = (int)(deg / max * ColorGradient.Colors.Count);
Note: See TracChangeset for help on using the changeset viewer.