Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/03/12 15:09:52 (12 years ago)
Author:
bburlacu
Message:

#1772: Modified genealogy graph chart and view to reflect changes in the class hierarchy.

File:
1 edited

Legend:

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

    r8249 r8556  
    3232namespace HeuristicLab.EvolutionaryTracking.Views {
    3333  public partial class GenealogyGraphChart : ChartControl {
    34     private Dictionary<GenealogyGraphNode, List<VisualGenealogyGraphNode>> _visualNodeMap;
    35     private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> _visualArcMap;
     34    private Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode> visualNodeMap;
     35    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap;
    3636    private const int Diameter = 20; // node diameter
    3737    private int x, y; // coordinates for positioning each node
    3838    private const int Cx = 30, Cy = 30; // position increments
    39     private VisualGenealogyGraphNode _selectedGenealogyGraphNode;
    40     public VisualGenealogyGraphNode SelectedGenealogyGraphNode { get { return _selectedGenealogyGraphNode; } }
    41     private Visualization.Rectangle _targetRectangle; // provides a  rectangle mark of the currently selected genealogy graph node
    42 
    43     private SymbolicExpressionTreeGenealogyGraph _graph;
     39    private VisualGenealogyGraphNode selectedGenealogyGraphNode;
     40    public VisualGenealogyGraphNode SelectedGenealogyGraphNode { get { return selectedGenealogyGraphNode; } }
     41    private Visualization.Rectangle targetRectangle; // provides a  rectangle mark of the currently selected genealogy graph node
     42
     43    private SymbolicExpressionTreeGenealogyGraph graph;
    4444    public SymbolicExpressionTreeGenealogyGraph Graph {
    45       get { return _graph; }
     45      get { return graph; }
    4646      internal set {
    47         _graph = value;
    48         _visualNodeMap = new Dictionary<GenealogyGraphNode, List<VisualGenealogyGraphNode>>();
    49         _visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
     47        graph = value;
     48        visualNodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>();
     49        visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
    5050        DrawGraph();
    5151      }
     
    6565
    6666    public void DrawGraph() {
    67       if (_graph == null) return;
     67      if (graph == null) return;
    6868      Chart.UpdateEnabled = false;
    6969
    70       var genealogyGraphNodes = Graph.Values.ToList();
    71       var layers = genealogyGraphNodes.GroupBy(n => Graph[n].Ranks[0]).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
    72       List<GenealogyGraphNode> currentLayer = null;
    73       List<GenealogyGraphNode> previousLayer = null;
    74 
    75       for (int i = 0; i != layers.Count(); ++i) {
    76         var layer = layers[i];
    77         double currentRank = layer.Rank;
    78         if (i > 0 && currentRank % 1 == 0) {
    79           previousLayer = currentLayer;
    80           currentLayer = layer.Nodes;
    81           int d = previousLayer.Count - currentLayer.Count;
    82           if (d > 0)
    83             currentLayer.AddRange(previousLayer.Take(d));
    84         } else {
    85           currentLayer = layer.Nodes;
    86         }
    87         currentLayer.Sort((b, a) => {
    88           if (Graph[a].Quality.Equals(Graph[b].Quality)) {
    89             if (Graph[a].IsElite) return 1;
    90             if (Graph[b].IsElite) return -1;
    91           }
    92           return Graph[a].Quality.CompareTo(Graph[b].Quality);
    93         }); // sort descending by quality (using comparison defined in GenealogyGraphNode class)
    94 
     70      var layers = Graph.Nodes.GroupBy(n => n.Ranks[0]).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
     71      for (int i = 0; i != layers.Count; ++i) {
     72        // sort descending by quality (using comparison defined in GenealogyGraphNode class)
     73        layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b));
    9574        x = 0; // reset horizontal coordinate
    9675        // start laying out visual nodes
    97         foreach (var node in currentLayer) {
     76        foreach (var node in layers[i].Nodes) {
    9877          var pen = new Pen(Color.LightGray);
    9978          var nl = Environment.NewLine;
     
    10180            Data = node,
    10281            ToolTipText = "Id: " + node.Label + nl +
    103                           "Ranks: " + string.Join(",", Graph[node].Ranks.Select(r => r.ToString())) + nl +
    104                           "Quality: " + String.Format("{0:0.0000}", Graph[node].Quality) + nl +
    105                           "IsElite: " + Graph[node].IsElite
     82                          "Ranks: " + string.Join(",", node.Ranks) + nl +
     83                          "Quality: " + String.Format("{0:0.0000}", node.Quality) + nl +
     84                          "IsElite: " + node.IsElite
    10685          };
    10786          Chart.Group.Add(visualNode);
    108           if (!_visualNodeMap.ContainsKey(node))
    109             _visualNodeMap[node] = new List<VisualGenealogyGraphNode>();
    110           _visualNodeMap[node].Add(visualNode);
     87          if (!visualNodeMap.ContainsKey(node))
     88            visualNodeMap[node] = visualNode;
    11189
    11290          x += Cx; // increment horizontal coordinate
     
    11492
    11593        y -= Cy; // decrement vertical coordinate (because the origin is upside down)
     94
     95        // 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            }
     106        }
    116107      }
    117108      // add arcs separately (to avoid some ordering problems)
    118       foreach (var node in _visualNodeMap.Keys) {
    119         var visualNode = _visualNodeMap[node][0];
     109      foreach (var node in visualNodeMap.Keys) {
     110        var visualNode = visualNodeMap[node];
    120111        if (node.InEdges == null) continue;
    121112
    122113        foreach (var arc in node.InEdges) {
    123           var visualParent = _visualNodeMap[arc.Target][0];
     114          var visualParent = visualNodeMap[arc.Target];
    124115          var pen = new Pen(Color.Transparent);
    125           _visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
    126         }
    127       }
    128       // connect visual nodes representing the same elite individual with a line
    129       foreach (var list in _visualNodeMap.Values.Where(l => l.Count > 1)) {
    130         for (int i = 1; i != list.Count; ++i) {
    131           var pen = new Pen(Color.LightGray);
    132           _visualArcMap[Tuple.Create(list[i - 1], list[i])] = AddArc(Chart, list[i - 1], list[i], pen);
     116          visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
    133117        }
    134118      }
     
    156140        var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList();
    157141        if (visualNodes.Count > 0) {
    158           if (_selectedGenealogyGraphNode == visualNodes[0]) return;
    159           _selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
    160           if (_selectedGenealogyGraphNode == null) return;
     142          if (selectedGenealogyGraphNode == visualNodes[0]) return;
     143          selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
     144          if (selectedGenealogyGraphNode == null) return;
    161145          // new node has been selected, clean up
    162146          Chart.UpdateEnabled = false;
     
    164148          ClearAllNodes();
    165149          // use a rectangle to highlight the currently selected genealogy graph node
    166           var center = _selectedGenealogyGraphNode.Center;
    167           var size = _selectedGenealogyGraphNode.Size;
     150          var center = selectedGenealogyGraphNode.Center;
     151          var size = selectedGenealogyGraphNode.Size;
    168152          double x1 = center.X - size.Width / 2;
    169153          double x2 = x1 + size.Width;
    170154          double y1 = center.Y - size.Height / 2;
    171155          double y2 = y1 + size.Height;
    172           if (_targetRectangle == null) {
    173             _targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
    174             Chart.Group.Add(_targetRectangle);
     156          if (targetRectangle == null) {
     157            targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
     158            Chart.Group.Add(targetRectangle);
    175159          } else {
    176             _targetRectangle.SetPosition(x1, y1, x2, y2);
    177           }
    178           var gNode = _selectedGenealogyGraphNode.Data; // genealogy graph node (representing an individual in the population)
    179           double rank = Graph[gNode].Ranks[0];
     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];
    180165          // ancestors
    181           var ancestors = gNode.Ancestors().Where(n => Graph[n].Ranks.Last() < rank).ToList();
     166          var ancestors = gNode.Ancestors().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() < rank).ToList();
    182167          ancestors.Add(gNode);
    183168          // descendants
    184           var descendants = gNode.Descendants().Where(n => Graph[n].Ranks.Last() > rank).ToList();
     169          var descendants = gNode.Descendants().Where(n => ((SymbolicExpressionGenealogyGraphNode)n).Ranks.Last() > rank).ToList();
    185170          descendants.Add(gNode);
    186171          // highlight ancestors
    187           foreach (var node in ancestors.Select(n => _visualNodeMap[n][0])) {
    188             node.Brush = new SolidBrush(Graph[node.Data].GetColor());
     172          foreach (var node in ancestors.Select(n => visualNodeMap[n])) {
     173            node.Brush = new SolidBrush(((SymbolicExpressionGenealogyGraphNode)node.Data).GetColor());
    189174            if (node.IncomingArcs != null)
    190175              foreach (var arc in node.IncomingArcs) {
    191                 // check if, in case of elites, the target node is the first visual representation of the elite
    192                 // (for purposes of display consistency)
    193                 bool isFirst = arc.Source == _visualNodeMap[arc.Source.Data][0];
    194                 if (arc.Source.Data == arc.Target.Data || !isFirst) continue;
    195176                var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    196177                var end = new Point((int)arc.End.X, (int)arc.End.Y);
    197                 arc.Pen.Brush = new LinearGradientBrush(start, end, Graph[arc.Source.Data].GetColor(), Graph[arc.Target.Data].GetColor());
     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());
    198181              }
    199182          }
    200183          // highlight descendants
    201           foreach (var node in descendants.Select(n => _visualNodeMap[n][0])) {
    202             node.Brush = new SolidBrush(Graph[node.Data].GetColor());
     184          foreach (var node in descendants.Select(n => visualNodeMap[n])) {
     185            node.Brush = new SolidBrush((node.Data as SymbolicExpressionGenealogyGraphNode).GetColor());
    203186            if (node.OutgoingArcs != null)
    204187              foreach (var arc in node.OutgoingArcs) {
    205                 // check if, in case of elites, the target node is the first visual representation of the elite
    206                 // (for purposes of display consistency)
    207                 bool isFirst = arc.Target == _visualNodeMap[arc.Target.Data][0];
    208                 if (arc.Source.Data == arc.Target.Data || !isFirst) continue;
    209188                var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    210189                var end = new Point((int)arc.End.X, (int)arc.End.Y);
    211                 arc.Pen.Brush = new LinearGradientBrush(start, end, Graph[arc.Source.Data].GetColor(), Graph[arc.Target.Data].GetColor());
     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());
    212193              }
    213194          }
    214195        } else {
    215           _selectedGenealogyGraphNode = null;
     196          selectedGenealogyGraphNode = null;
    216197        }
    217198        // update
    218199        Chart.UpdateEnabled = true;
    219200        Chart.EnforceUpdate();
    220         if (_selectedGenealogyGraphNode != null)
     201        if (selectedGenealogyGraphNode != null)
    221202          /* emit clicked event */
    222           OnGenealogyGraphNodeClicked(_selectedGenealogyGraphNode, e);
     203          OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e);
    223204      }
    224205    }
     
    226207    public void ClearAllNodes() {
    227208      foreach (var primitive in Chart.Group.Primitives) {
    228         primitive.Brush = null;
    229209        if (primitive is VisualGenealogyGraphArc) {
    230210          var arc = primitive as VisualGenealogyGraphArc;
    231           if (arc.Source.Data != arc.Target.Data && primitive.Pen.Brush != null)
     211          var sourceData = (arc.Source.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree;
     212          var targetData = (arc.Target.Data as SymbolicExpressionGenealogyGraphNode).SymbolicExpressionTree;
     213          if (sourceData != targetData) {
    232214            primitive.Pen.Brush = new SolidBrush(Color.Transparent);
     215          } else {
     216            primitive.Pen.Brush = new SolidBrush(Color.LightGray);
     217          }
     218        } else {
     219          primitive.Brush = null;
    233220        }
    234221      }
     
    236223
    237224    public void HighlightLineage(IEnumerable<GenealogyGraphNode> nodes) {
    238       foreach (var node in nodes.SelectMany(n => _visualNodeMap[n])) {
    239         node.Brush = new SolidBrush(Graph[node.Data].GetColor());
    240         if (node.IncomingArcs == null || node != _visualNodeMap[node.Data][0]) continue;
     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;
    241228        foreach (var arc in node.IncomingArcs) {
    242229          if (arc.Source.Data == node.Data) continue;
    243230          var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    244231          var end = new Point((int)arc.End.X, (int)arc.End.Y);
    245           arc.Pen.Brush = new LinearGradientBrush(start, end, Graph[arc.Source.Data].GetColor(), Graph[arc.Target.Data].GetColor());
    246         }
    247       }
    248     }
    249 
     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    // TODO: optimize and reduce complexity of this method
    250240    public void HighlightNodes(IEnumerable<ISymbolicExpressionTree> trees, Color color) {
    251       foreach (var visualNode in trees.Select(tree => _visualNodeMap[Graph.GetNode(tree)]).SelectMany(vList => vList))
    252         visualNode.Brush = new SolidBrush(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        }
     248    }
     249
     250    public void HighlightNode(SymbolicExpressionGenealogyGraphNode graphNode, Color color) {
     251      visualNodeMap[graphNode].Brush = new SolidBrush(color);
    253252    }
    254253
     
    256255      Chart.UpdateEnabled = false;
    257256      ClearAllNodes();
    258       var graphNodes = Graph.Values.ToList();
    259       double min = graphNodes.Min(x => x.InEdges == null ? 0 : x.InEdges.Count);
    260       double max = graphNodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
    261       foreach (var graphNode in graphNodes) {
    262         var visualNode = _visualNodeMap[graphNode][0];
     257      double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
     258      foreach (var graphNode in Graph.Nodes) {
     259        var visualNode = visualNodeMap[graphNode];
    263260        double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count;
    264         var color = Color.FromArgb((int)(1 - deg / max) * 255, (int)(deg / max * 255), 100);
     261        int index = (int)(deg / max * ColorGradient.Colors.Count);
     262        if (index == ColorGradient.Colors.Count) --index;
     263        var color = ColorGradient.Colors[index];
    265264        visualNode.Brush = new SolidBrush(color);
    266265      }
     
    272271      Chart.UpdateEnabled = false;
    273272      ClearAllNodes();
    274       var graphNodes = Graph.Values.ToList();
    275       double min = graphNodes.Min(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
     273      var graphNodes = Graph.Nodes;
    276274      double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
    277275      foreach (var graphNode in graphNodes) {
    278         var visualNode = _visualNodeMap[graphNode][0];
     276        var visualNode = visualNodeMap[graphNode];
    279277        double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count;
    280         int index = (int)(deg / max * ColorGradient.Colors.Count) - 1;
    281         if (index < 0) index = 0;
    282         visualNode.Brush = new SolidBrush(ColorGradient.Colors[index]);
     278        int index = (int)(deg / max * ColorGradient.Colors.Count);
     279        if (index == ColorGradient.Colors.Count) --index;
     280        var color = ColorGradient.Colors[index];
     281        visualNode.Brush = new SolidBrush(color);
    283282      }
    284283      Chart.UpdateEnabled = true;
     
    288287
    289288  internal static class Util {
    290     public static Color GetColor(this NodeMetadata nm) {
    291       var colorIndex = (int)(nm.Quality * ColorGradient.Colors.Count);
     289    public static Color GetColor(this SymbolicExpressionGenealogyGraphNode node) {
     290      var colorIndex = (int)(node.Quality * ColorGradient.Colors.Count);
    292291      if (colorIndex >= ColorGradient.Colors.Count) --colorIndex;
    293292      return ColorGradient.Colors[colorIndex];
Note: See TracChangeset for help on using the changeset viewer.