Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/23/13 11:42:24 (11 years ago)
Author:
bburlacu
Message:

#1772: Added HeuristicLab.Problems.DataAnalysis.Symbolic and HeuristicLab.Problems.DataAnalysis.Symbolic.Views and integrated some modifications from the old branch.

File:
1 edited

Legend:

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

    r10264 r10269  
    1 #region License Information
    2 /* HeuristicLab
    3  * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    4  *
    5  * This file is part of HeuristicLab.
    6  *
    7  * HeuristicLab is free software: you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation, either version 3 of the License, or
    10  * (at your option) any later version.
    11  *
    12  * HeuristicLab is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
    19  */
    20 #endregion
    21 
    22 using System;
     1using System;
    232using System.Collections.Generic;
    243using System.Drawing;
     
    276using System.Windows.Forms;
    287using HeuristicLab.Common;
    29 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    308using HeuristicLab.Visualization;
    319
    3210namespace HeuristicLab.EvolutionaryTracking.Views {
    3311  public partial class GenealogyGraphChart : ChartControl {
    34     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     private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap;
    36     private const int Diameter = 20; // node diameter
    37     private int x, y; // coordinates for positioning each node
    38     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
     12    private GenealogyGraph genealogyGraph;
     13
     14    private const double XIncrement = 30;
     15    private const double YIncrement = 30;
     16    private const double Diameter = 20;
     17
     18    public GenealogyGraph GenealogyGraph {
     19      get { return genealogyGraph; }
     20      set {
     21        if (value == null) return;
     22        genealogyGraph = value;
     23        Clear();
     24        DrawGraph(XIncrement, YIncrement, Diameter);
     25      }
     26    }
     27
     28    private void Clear() {
     29      if (nodeMap == null)
     30        nodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>();
     31      else nodeMap.Clear();
     32
     33      if (arcMap == null)
     34        arcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
     35      else arcMap.Clear();
     36
     37      Chart.Group.Clear();
     38    }
     39
     40    private Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode> nodeMap;
     41    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> arcMap;
    4242
    4343    public bool SimpleLineages { get; set; }
    4444    public bool LockGenealogy { get; set; }
    45 
    46     private bool drawing;
    47 
    48     private SymbolicExpressionTreeGenealogyGraph graph;
    49     public SymbolicExpressionTreeGenealogyGraph Graph {
    50       get { return graph; }
    51       internal set {
    52         graph = value;
    53         if (graph == null) return;
    54 
    55         visualNodeMap = new Dictionary<string, VisualGenealogyGraphNode>();
    56         visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
    57 
    58         Chart.Group.Clear();
    59         DrawGraph();
    60       }
    61     }
    62 
    63     private VisualGenealogyGraphNode GetVisualGenealogyGraphNode(IVertex node) {
    64       VisualGenealogyGraphNode visualNode;
    65       visualNodeMap.TryGetValue(node.Id, out visualNode);
    66       return visualNode;
    67     }
    68 
    69     private VisualGenealogyGraphArc GetVisualGenealogyGraphArc(IVertex source, IVertex target) {
    70       VisualGenealogyGraphNode visualSource;
    71       VisualGenealogyGraphNode visualTarget;
    72       visualNodeMap.TryGetValue(source.Id, out visualSource);
    73       visualNodeMap.TryGetValue(target.Id, out visualTarget);
    74       if (visualSource != null && visualTarget != null) {
    75         VisualGenealogyGraphArc visualArc;
    76         visualArcMap.TryGetValue(
    77           new Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>(visualSource, visualTarget), out visualArc);
    78         if (visualArc != null) return visualArc;
    79       }
    80       return null;
    81     }
     45    private Visualization.Rectangle TargetRectangle { get; set; }
     46
     47    private VisualGenealogyGraphNode GetMappedNode(IGenealogyGraphNode node) {
     48      VisualGenealogyGraphNode v;
     49      nodeMap.TryGetValue(node, out v);
     50      return v;
     51    }
     52
     53    private VisualGenealogyGraphArc GetMappedArc(IGenealogyGraphNode source, IGenealogyGraphNode target) {
     54      VisualGenealogyGraphNode visualSource, visualTarget;
     55      nodeMap.TryGetValue(source, out visualSource);
     56      nodeMap.TryGetValue(target, out visualTarget);
     57
     58      if (visualSource == null || visualTarget == null) return null;
     59
     60      VisualGenealogyGraphArc arc;
     61      arcMap.TryGetValue(new Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>(visualSource, visualTarget), out arc);
     62      return arc;
     63    }
     64
     65    private bool DrawInProgress { get; set; } // do not try to update the chart while the drawing is not finished
     66    private VisualGenealogyGraphNode SelectedVisualNode { get; set; }
    8267
    8368    public event MouseEventHandler GenealogyGraphNodeClicked;
     
    8873
    8974    public GenealogyGraphChart() {
    90       //      InitializeComponent();
    91       Chart = new Chart(0, 0, PreferredSize.Width, PreferredSize.Height);
    92       x = 0;
    93       y = PreferredSize.Height + Cx + 2 * Diameter;
    94       Chart.Mode = ChartMode.Select;
    95     }
    96 
    97     public void DrawGraph() {
    98       if (graph == null) return;
     75      InitializeComponent();
     76    }
     77
     78    protected virtual void DrawGraph(double xIncrement, double yIncrement, double diameter) {
    9979      Chart.UpdateEnabled = false;
    100 
    101       drawing = true;
    102 
    103       var layers = Graph.Nodes.GroupBy(n => n.Rank).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
    104 
    105       y = PreferredSize.Height + Cx + 2 * Diameter;
    106 
    107       for (int i = 0; i != layers.Count; ++i) {
    108         x = 0;
    109         layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b));
    110         double rank = Math.Floor(layers[i].Rank);
    111         if (layers[i].Rank.IsAlmost(rank)) {
    112           var visualTextNode = new VisualGenealogyGraphTextLabel(Chart, x, y + 2, x + Diameter, y + Diameter) {
    113             FontBrush = new SolidBrush(Color.Black),
    114             Font = new Font("Arial", Diameter - 4, FontStyle.Regular, GraphicsUnit.Pixel),
    115             Text = String.Format("{0:0}", rank)
    116           };
    117           Chart.Group.Add(visualTextNode);
    118         }
    119 
    120         // sort descending by quality (using comparison defined in GenealogyGraphNode class)
    121         x += (int)Math.Floor(1.5 * Cx); // reset horizontal coordinate
    122 
    123         foreach (var node in layers[i].Nodes) {
     80      DrawInProgress = true;
     81
     82      var ranks = GenealogyGraph.Ranks.Select(t => new { Rank = t.Key, Nodes = t.Value }).OrderBy(p => p.Rank).ToList();
     83      double x = 0;
     84      double y = PreferredSize.Height + yIncrement + 2 * diameter;
     85
     86      foreach (var rank in ranks) {
     87        var nodes = rank.Nodes.ToList();
     88        nodes.Sort((a, b) => b.CompareTo(a)); // sort descending by quality
     89        var nl = Environment.NewLine;
     90
     91        foreach (var node in nodes) {
    12492          var pen = new Pen(Color.LightGray);
    125           var nl = Environment.NewLine;
    126           var visualNode = new VisualGenealogyGraphNode(Chart, x, y, x + Diameter, y + Diameter, pen, null) {
     93
     94          var visualNode = new VisualGenealogyGraphNode(Chart, x, y, x + diameter, y + diameter, pen, null) {
    12795            Data = node,
    12896            ToolTipText = "Rank: " + node.Rank + nl +
     
    13199          };
    132100          Chart.Group.Add(visualNode);
    133           visualNodeMap.Add(node.Id, visualNode);
    134 
    135           x += Cx; // increment horizontal coordinate
    136         }
    137 
    138         y -= Cy; // decrement vertical coordinate (because the origin is upside down)
    139 
    140         // connect elites from successive layers with visual arcs
    141         if (i == 0) continue;
    142         var currLayer = layers[i].Nodes;
    143         var prevLayer = layers[i - 1].Nodes;
    144         foreach (var n in currLayer) {
    145           foreach (var m in prevLayer) {
    146             if (n.SymbolicExpressionTree != m.SymbolicExpressionTree) continue;
    147             var v1 = GetVisualGenealogyGraphNode(n);
    148             var v2 = GetVisualGenealogyGraphNode(m);
    149 
    150             var pen = new Pen(Color.LightGray);
    151             visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen);
    152           }
    153         }
    154       }
    155       // add arcs separately (to avoid some ordering problems)
    156       foreach (SymbolicExpressionTreeGenealogyGraphNode node in Graph.Nodes) {
    157         VisualGenealogyGraphNode visualNode = GetVisualGenealogyGraphNode(node);
    158         if (node.InEdges == null) continue;
    159 
    160         foreach (Arc arc in node.InEdges) {
    161           var visualParent = GetVisualGenealogyGraphNode(arc.Source);
     101          nodeMap.Add(node, visualNode);
     102
     103          x += xIncrement;
     104        }
     105        y -= yIncrement;
     106      }
     107      // add arcs
     108      foreach (var node in GenealogyGraph.Nodes) {
     109        if (node.InArcs == null) continue;
     110        var visualNode = nodeMap[node];
     111        if (visualNode == null) continue;
     112        foreach (var arc in node.InArcs) {
     113          var parent = arc.Source;
     114          var visualParent = GetMappedNode(parent);
     115          if (visualParent == null) continue;
    162116          var pen = new Pen(Color.Transparent);
    163           visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
    164         }
    165       }
    166 
    167       // highlight the most recent common ancestor ("eve" individual)
    168       //      var eve = graph.MostRecentCommonAncestor();
    169       //      if (eve != null) {
    170       //        var visualGraphNode = GetVisualGenealogyGraphNode(eve);
    171 
    172       //        var brush = new SolidBrush(Color.BlueViolet);
    173       //        visualGraphNode.FontBrush = brush;
    174       //      }
    175 
    176       Chart.UpdateEnabled = true;
    177       Chart.EnforceUpdate();
    178 
    179       drawing = false;
    180     }
    181 
    182     // add an arc between the source and the target nodes, using the specified pen color
    183     // adds the arc to the arc lists of both nodes and to the primitive group of the chart
    184     private static VisualGenealogyGraphArc AddArc(IChart chart, VisualGenealogyGraphNode source, VisualGenealogyGraphNode target, Pen pen, Brush brush = null) {
    185       var arc = new VisualGenealogyGraphArc(chart, source, target, pen) { Brush = brush };
    186       arc.UpdatePosition();
    187       source.OutgoingArcs.Add(arc);
    188       target.IncomingArcs.Add(arc);
    189       chart.Group.Add(arc);
    190       return arc;
    191     }
    192 
    193     protected override void pictureBox_MouseMove(object sender, MouseEventArgs e) {
    194       if (!drawing) {
     117          var visualArc = AddArc(Chart, visualParent, visualNode, pen);
     118          arcMap.Add(Tuple.Create(visualParent, visualNode), visualArc);
     119        }
     120      }
     121      // TODO: connect elites
     122
     123      Chart.UpdateEnabled = true;
     124      Chart.EnforceUpdate();
     125
     126      DrawInProgress = false;
     127    }
     128
     129    protected override void pictureBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
     130      if (!DrawInProgress) {
    195131        switch (e.Button) {
    196132          case MouseButtons.Left:
     
    203139            break;
    204140        }
    205         base.pictureBox_MouseMove(sender, e);
    206       }
     141      }
     142      base.pictureBox_MouseMove(sender, e);
    207143    }
    208144
     
    213149        return;
    214150      }
    215 
    216151      if (Chart.Mode != ChartMode.Select) {
    217152        base.pictureBox_MouseUp(sender, e);
    218153        return;
    219154      }
    220 
    221155      var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList();
    222156      if (visualNodes.Count <= 0) {
    223         selectedGenealogyGraphNode = null;
     157        SelectedVisualNode = null;
    224158        return;
    225159      }
    226       if (selectedGenealogyGraphNode == visualNodes[0]) return;
    227       selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
    228       if (selectedGenealogyGraphNode == null) return;
     160      if (SelectedVisualNode == visualNodes[0]) return;
     161      SelectedVisualNode = visualNodes[0] as VisualGenealogyGraphNode;
     162      if (SelectedVisualNode == null) return;
    229163
    230164      if (!LockGenealogy) {
     
    233167        if (ModifierKeys != Keys.Shift)
    234168          // clear colors
    235           ClearAllNodes();
     169          ClearPrimitives();
    236170        // use a rectangle to highlight the currently selected genealogy graph node
    237         var gNode = selectedGenealogyGraphNode.Data;
    238         var visualNode = GetVisualGenealogyGraphNode(gNode);
     171        var gNode = SelectedVisualNode.Data;
     172        var visualNode = GetMappedNode(gNode);
    239173
    240174        DrawLineage(visualNode, n => SimpleLineages ? n.IncomingArcs.Take(1) : n.IncomingArcs, a => a.Source);
     
    249183      Chart.EnforceUpdate();
    250184
    251       if (selectedGenealogyGraphNode != null)
     185      if (SelectedVisualNode != null)
    252186        /* emit clicked event */
    253         OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e);
     187        OnGenealogyGraphNodeClicked(SelectedVisualNode, e);
     188
     189      base.pictureBox_MouseUp(sender, e);
    254190    }
    255191
     
    273209
    274210    void MarkSelectedNode() {
    275       var center = selectedGenealogyGraphNode.Center;
    276       var size = selectedGenealogyGraphNode.Size;
     211      var center = SelectedVisualNode.Center;
     212      var size = SelectedVisualNode.Size;
    277213      double x1 = center.X - size.Width / 2;
    278214      double x2 = x1 + size.Width;
    279215      double y1 = center.Y - size.Height / 2;
    280216      double y2 = y1 + size.Height;
    281       if (targetRectangle == null) {
    282         targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
    283         Chart.Group.Add(targetRectangle);
     217      if (TargetRectangle == null) {
     218        TargetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
     219        Chart.Group.Add(TargetRectangle);
    284220      } else {
    285         targetRectangle.SetPosition(x1, y1, x2, y2);
    286       }
    287     }
    288 
    289     public void ClearAllNodes() {
     221        TargetRectangle.SetPosition(x1, y1, x2, y2);
     222      }
     223    }
     224
     225
     226    private static VisualGenealogyGraphArc AddArc(IChart chart, VisualGenealogyGraphNode source, VisualGenealogyGraphNode target, Pen pen, Brush brush = null) {
     227      var arc = new VisualGenealogyGraphArc(chart, source, target, pen) { Brush = brush };
     228      arc.UpdatePosition();
     229      source.OutgoingArcs.Add(arc);
     230      target.IncomingArcs.Add(arc);
     231      chart.Group.Add(arc);
     232      return arc;
     233    }
     234
     235    public virtual void ClearPrimitives() {
    290236      foreach (var primitive in Chart.Group.Primitives) {
    291237        if (primitive is VisualGenealogyGraphArc) {
    292           var arc = primitive as VisualGenealogyGraphArc;
    293           var sourceData = arc.Source.Data.SymbolicExpressionTree;
    294           var targetData = arc.Target.Data.SymbolicExpressionTree;
    295           primitive.Pen.Brush = sourceData != targetData ? new SolidBrush(Color.Transparent) : new SolidBrush(Color.LightGray);
     238          primitive.Pen.Brush = new SolidBrush(Color.Transparent);
    296239        } else {
    297240          primitive.Brush = null;
     
    299242      }
    300243    }
    301 
    302     public void HighlightNodes(IEnumerable<SymbolicExpressionTreeGenealogyGraphNode> nodes) {
     244    public void HighlightNodes(IEnumerable<IGenealogyGraphNode> nodes) {
    303245      Chart.UpdateEnabled = false;
    304       ClearAllNodes();
     246      ClearPrimitives();
    305247      foreach (var node in nodes) {
    306         GetVisualGenealogyGraphNode(node).Brush = new SolidBrush(node.GetColor());
    307       }
    308       Chart.UpdateEnabled = true;
    309       Chart.EnforceUpdate();
    310     }
    311 
    312     // TODO: optimize and reduce complexity of this method
    313     public void HighlightNodes(IEnumerable<ISymbolicExpressionTree> trees) {
    314       foreach (var tree in trees) {
    315         var graphNodes = graph.GetGraphNodes(tree);
    316         foreach (var graphNode in graphNodes) {
    317           GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(graphNode.GetColor());
    318         }
    319       }
    320     }
    321 
    322     public void HighlightArcs(IEnumerable<IEdge> arcs, Color color) {
    323       foreach (var a in arcs) {
    324         var arc = GetVisualGenealogyGraphArc(a.Source, a.Target);
    325         if (arc != null) {
    326           var source = arc.Source.Data;
    327           var target = arc.Target.Data;
    328           var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
    329           var end = new Point((int)arc.End.X, (int)arc.End.Y);
    330           arc.Pen.Brush = new LinearGradientBrush(start, end, source.GetColor(), target.GetColor());
    331         }
    332       }
    333     }
    334 
    335     public void HighlightNode(SymbolicExpressionTreeGenealogyGraphNode graphNode, Color color) {
    336       GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color);
    337     }
    338 
     248        GetMappedNode(node).Brush = new SolidBrush(node.GetColor());
     249      }
     250      Chart.UpdateEnabled = true;
     251      Chart.EnforceUpdate();
     252    }
    339253    public void HighlightAll() {
    340254      Chart.UpdateEnabled = false;
    341       foreach (var visualNode in visualNodeMap.Values) {
     255      foreach (var visualNode in nodeMap.Values) {
    342256        visualNode.Brush = new SolidBrush(visualNode.Data.GetColor());
    343257      }
    344       foreach (var arc in visualArcMap.Values) {
     258      foreach (var arc in arcMap.Values) {
    345259        var source = arc.Source.Data;
    346260        var target = arc.Target.Data;
     
    352266      Chart.EnforceUpdate();
    353267    }
    354 
    355     public void HighlightInDegree() {
    356       Chart.UpdateEnabled = false;
    357       ClearAllNodes();
    358       double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
    359       foreach (var graphNode in Graph.Nodes) {
    360         var visualNode = GetVisualGenealogyGraphNode(graphNode);
    361         double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count;
    362         int index = (int)(deg / max * ColorGradient.Colors.Count);
    363         if (index == ColorGradient.Colors.Count) --index;
    364         var color = ColorGradient.Colors[index];
    365         visualNode.Brush = new SolidBrush(color);
    366       }
    367       Chart.UpdateEnabled = true;
    368       Chart.EnforceUpdate();
    369     }
    370 
    371     public void HighlightOutDegree() {
    372       Chart.UpdateEnabled = false;
    373       ClearAllNodes();
    374       var graphNodes = Graph.Nodes;
    375       double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
    376       foreach (var graphNode in graphNodes) {
    377         var visualNode = GetVisualGenealogyGraphNode(graphNode);
    378         double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count;
    379         int index = (int)(deg / max * ColorGradient.Colors.Count);
    380         if (index == ColorGradient.Colors.Count) --index;
    381         var color = ColorGradient.Colors[index];
    382         visualNode.Brush = new SolidBrush(color);
    383       }
    384       Chart.UpdateEnabled = true;
    385       Chart.EnforceUpdate();
    386     }
    387268  }
    388269
    389270  internal static class Util {
    390     public static Color GetColor(this SymbolicExpressionTreeGenealogyGraphNode node) {
     271    public static Color GetColor(this IGenealogyGraphNode node) {
    391272      var colorIndex = (int)(node.Quality * ColorGradient.Colors.Count);
    392273      if (colorIndex >= ColorGradient.Colors.Count) --colorIndex;
Note: See TracChangeset for help on using the changeset viewer.