source: branches/HeuristicLab.DatastreamAnalysis/HeuristicLab.DatastreamAnalysis.Views/3.4/DataBarSetView.cs @ 14710

Last change on this file since 14710 was 14710, checked in by jzenisek, 5 years ago

#2719 implemented ensemble model rating by introducing the new type RatedEnsembleModel; introduced performance indicator calculation in results;

File size: 12.3 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using System.Windows.Forms.DataVisualization.Charting;
29using HeuristicLab.Core.Views;
30using HeuristicLab.MainForm;
31
32namespace HeuristicLab.DatastreamAnalysis.Views {
33  [View("DataBarSet")]
34  [Content(typeof(DataBarSet), true)]
35  public partial class DataBarSetView : ItemView {
36    private bool updateInProgress;
37    private string seriesName = "Ensembles";
38
39    public virtual Image ViewImage {
40      get { return HeuristicLab.Common.Resources.VSImageLibrary.Graph; }
41    }
42
43    public new DataBarSet Content {
44      get { return (DataBarSet) base.Content; }
45      set { base.Content = value; }
46    }
47
48    public DataBarSetView() : base() {
49      InitializeComponent();
50      updateInProgress = false;
51
52      this.chart.CustomizeAllChartAreas();
53      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
54      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
55      this.chart.ChartAreas[0].AxisX.Title = "Ensembles";
56      //this.chart.ChartAreas[0].AxisX.Maximum = 0.0;
57      //this.chart.ChartAreas[0].AxisX.Maximum = (Content != null && Content.Bars != null) ? Content.Bars.Count : 0.0;
58      //AddCustomLabelsToAxis(this.chart.ChartAreas[0].AxisX);
59
60      this.chart.ChartAreas[0].AxisY.Title = "Estimation Quality";
61      this.chart.ChartAreas[0].AxisY.IsStartedFromZero = true;
62      this.chart.ChartAreas[0].AxisY.Minimum = 0.0;
63      this.chart.ChartAreas[0].AxisY.Maximum = 1.0;
64      this.chart.ChartAreas[0].AxisY.Interval = 0.1;
65      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
66      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
67    }
68
69    private void AddCustomLabelsToAxis(Axis axis) {
70      axis.CustomLabels.Clear();
71
72      var bars = Content.Bars.ToList();
73      for(int i = 0; i < Content.Bars.Count; i++) {
74        CustomLabel barLabel = new CustomLabel();
75        barLabel.Text = bars[i].Name;
76        barLabel.FromPosition = i;
77        barLabel.ToPosition = i + 1;
78        axis.CustomLabels.Add(barLabel);
79      }
80    }
81
82    protected override void RegisterContentEvents() {
83      base.RegisterContentEvents();
84      Content.BarsPropertyChanged += new EventHandler(Content_BarsChanged);
85      Content.BarValueChanged += new EventHandler(Content_BarValuesChanged);
86      Content.ThresholdsPropertyChanged += new EventHandler(Content_ThresholdsChanged);
87    }
88
89    protected override void DeregisterContentEvents() {
90      base.DeregisterContentEvents();
91      Content.BarsPropertyChanged -= new EventHandler(Content_BarsChanged);
92      Content.BarValueChanged -= new EventHandler(Content_BarValuesChanged);
93      Content.ThresholdsPropertyChanged -= new EventHandler(Content_ThresholdsChanged);
94    }
95
96    private void Content_BarsChanged(object sender, EventArgs e) {
97      UpdateChart();
98    }
99
100    private void Content_BarValuesChanged(object sender, EventArgs e) {
101      UpdateChartValues();
102    }
103
104    private void Content_ThresholdsChanged(object sender, EventArgs e) {
105      UpdateChart();
106    }
107
108    protected override void OnContentChanged() {
109      base.OnContentChanged();
110      UpdateChart();
111    }
112    private void UpdateChart() {
113      if (InvokeRequired) {
114        Invoke((Action) UpdateChart);
115      } else if(!updateInProgress) {
116        if (Content == null) return;
117
118        updateInProgress = true;
119
120        chart.Series.Clear();
121       
122        Series series = chart.Series.Add(seriesName);
123        series.IsVisibleInLegend = false;
124        series.ChartType = SeriesChartType.Column;
125        int i = 0;
126        foreach (var bar in Content.Bars) {
127          var dp = new DataPoint(i, bar.Value) {
128            AxisLabel = bar.Name,
129            ToolTip = bar.Name,
130            Color = bar.BarColor,
131            BorderWidth = 5
132          };
133          series.Points.Add(dp);
134          i++;
135        }
136
137        //chart.ChartAreas[0].RecalculateAxesScale();
138        AddThresholds();
139        CheckThresholds();
140
141        chart.Refresh();
142        updateInProgress = false;
143      }
144    }
145
146    private void UpdateChartValues() {
147      if (InvokeRequired) {
148        Invoke((Action) UpdateChartValues);
149      } else if(!updateInProgress) {
150        if (Content == null) return;
151
152        updateInProgress = true;
153
154        //chart.Series[seriesName].Points.Clear();
155        //foreach (var bar in Content.Bars) {
156        //  chart.Series[seriesName].Points.AddXY(bar.Name, bar.Value);
157        //}
158
159        var bars = Content.Bars.ToList();
160
161        for (int i = 0; i < bars.Count; i++) {
162          chart.Series[seriesName].Points.ElementAt(i).SetValueY(bars[i].Value);
163          chart.Series[seriesName].Points.ElementAt(i).ToolTip = bars[i].Name + " = " + bars[i].Value;
164        }
165
166        CheckThresholds();
167        //chart.ChartAreas[0].RecalculateAxesScale();
168        chart.Refresh();
169        updateInProgress = false;
170      }
171    }
172
173    public static Color DefaultColor = Color.FromArgb(65, 140, 240);
174    public static Color HighlightColor1 = Color.FromArgb(37, 105, 175);
175    public static Color HighlightColor2 = Color.FromArgb(247, 150, 70);
176    public static Color HighlightColor3 = Color.FromArgb(228, 108, 10);
177    //public static Color HighlightColor1 = Color.FromArgb(45, 120, 200);
178    //public static Color HighlightColor2 = Color.FromArgb(15, 90, 160);
179    //public static Color HighlightColor3 = Color.FromArgb(10, 60, 110);
180    private void CheckThresholds() {
181      var bars = Content.Bars.ToList();
182      var winner =
183        !bars.Any() ? -1 :
184        bars
185        .Select((value, index) => new {Value = value, Index = index})
186        .Aggregate((a, b) => ((a.Value.Value - a.Value.ThresholdUpperBound) > (b.Value.Value - b.Value.ThresholdUpperBound)) ? a : b)
187        .Index;
188
189      // color bars depending on the threshold boundaries they exceed
190      for (int i = 0; i < bars.Count; i++) {
191        var bar = bars[i];
192        if (bar.Value > bar.ThresholdUpperBound) {
193          chart.Series[seriesName].Points[i].Color = HighlightColor2;
194          chart.Series[seriesName].Points[i].BorderColor = HighlightColor2;
195        } else if (bar.Value > bar.ThresholdLowerBound) {
196          chart.Series[seriesName].Points[i].Color = HighlightColor1;
197          chart.Series[seriesName].Points[i].BorderColor = HighlightColor1;
198        } else {
199          chart.Series[seriesName].Points[i].Color = bar.BarColor;
200          chart.Series[seriesName].Points[i].BorderColor = bar.BarColor;
201        }
202      }
203
204      // color the winner's border
205      if (winner != -1 && bars[winner].Value > bars[winner].ThresholdUpperBound) {
206        chart.Series[seriesName].Points[winner].BorderColor = HighlightColor3;
207      }
208    }
209
210
211
212    private void AddThresholds() {
213      Series series = chart.Series.Add("Thresholds");
214      series.IsVisibleInLegend = false;
215      series.ChartType = SeriesChartType.ErrorBar;
216
217      int i = 0;
218      foreach (var bar in Content.Bars) {
219        string desc = string.Format("{0} - Threshold [{1},{2}]", bar.Name, bar.ThresholdLowerBound,bar.ThresholdUpperBound);
220        var threshold = new DataPoint(i, new[]
221              {(bar.ThresholdLowerBound + bar.ThresholdUpperBound)/2, bar.ThresholdLowerBound, bar.ThresholdUpperBound}) {
222                AxisLabel = desc,
223                ToolTip = desc,
224                Color = bar.ThresholdColor,
225                BorderWidth = 1
226        };
227        series.Points.Add(threshold);
228        i++;
229      }
230    }
231    private void AddThresholdsOld() {
232      Series series = chart.Series.Add("Thresholds");
233      series.IsVisibleInLegend = false;
234      series.ChartType = SeriesChartType.StackedColumn;
235
236      int i = 0;
237      foreach (var bar in Content.Bars) {
238        //series.Points.Add(new DataPoint(i, new [] { bar.Threshold, bar.Threshold + 0.05 }) { AxisLabel = bar.Name, Color = Color.Transparent, BorderWidth = 2, BorderColor = bar.ThresholdColor});
239        series.Points.Add(new DataPoint(i, new[] { bar.ThresholdLowerBound, bar.ThresholdUpperBound }) { AxisLabel = bar.Name, Color = bar.ThresholdColor });
240        i++;
241      }
242    }
243    private void AddThresholdsOld2() {
244      chart.Annotations.Clear();
245
246      var bars = Content.Bars.ToList();
247      for (int i = 0; i < bars.Count; i++) {
248        HorizontalLineAnnotation annotation = new HorizontalLineAnnotation();
249        annotation.AllowMoving = false;
250        annotation.AllowResizing = false;
251        annotation.LineWidth = 2;
252        annotation.LineColor = bars[i].ThresholdColor;
253        annotation.IsInfinitive = false;
254        annotation.ClipToChartArea = chart.ChartAreas[0].Name;
255        annotation.AxisX = chart.ChartAreas[0].AxisX;
256        annotation.AxisY = chart.ChartAreas[0].AxisY;
257        annotation.Y = bars[i].ThresholdLowerBound;
258
259        annotation.Alignment = ContentAlignment.MiddleCenter;
260        annotation.AnchorX = i;
261
262        annotation.X = i - 0.4;
263        annotation.Width = (46 - bars.Count) / bars.Count;
264        annotation.Name = bars[i].Name;
265        annotation.Tag = bars[i].Name;
266        annotation.BringToFront();
267
268       
269
270        chart.Annotations.Add(annotation);
271      }
272    }
273
274    private TextAnnotation CreateTextAnnotation(string name, int classIndex, Axis axisX, Axis axisY, double x, double y, ContentAlignment alignment) {
275      TextAnnotation annotation = new TextAnnotation();
276      annotation.Text = name;
277      annotation.AllowMoving = true;
278      annotation.AllowResizing = false;
279      annotation.AllowSelecting = false;
280      annotation.IsSizeAlwaysRelative = true;
281      annotation.ClipToChartArea = chart.ChartAreas[0].Name;
282      annotation.Tag = classIndex;
283      annotation.AxisX = axisX;
284      annotation.AxisY = axisY;
285      annotation.Alignment = alignment;
286      annotation.X = x;
287      annotation.Y = y;
288      return annotation;
289    }
290
291
292    #region user interaction events
293    private void chart_MouseMove(object sender, MouseEventArgs e) {
294      HitTestResult result = chart.HitTest(e.X, e.Y);
295      if (result.ChartElementType == ChartElementType.LegendItem)
296        this.Cursor = Cursors.Hand;
297      else
298        this.Cursor = Cursors.Default;
299    }
300
301    private void chart_MouseDown(object sender, MouseEventArgs e) {
302      HitTestResult result = chart.HitTest(e.X, e.Y);
303      if (result.ChartElementType == ChartElementType.LegendItem) {
304        if (result.Series != null) ToggleSeries(result.Series);
305      }
306    }
307
308    private void ToggleSeries(Series series) {
309      if (series.Points.Count == 0) {
310        // TODO
311      } else {
312        series.Points.Clear();
313      }
314    }
315
316    private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
317      int classIndex = (int)e.Annotation.Tag;
318      //double[] thresholds = Content.Model.Thresholds.ToArray();
319      //thresholds[classIndex] = e.NewLocationY;
320      //Array.Sort(thresholds);
321      //Content.Model.SetThresholdsAndClassValues(thresholds, Content.Model.ClassValues);
322    }
323
324    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
325      foreach (LegendItem legendItem in e.LegendItems) {
326        var series = chart.Series[legendItem.SeriesName];
327        if (series != null) {
328          bool seriesIsInvisible = series.Points.Count == 0;
329          foreach (LegendCell cell in legendItem.Cells)
330            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
331        }
332      }
333    }
334    #endregion
335  }
336}
Note: See TracBrowser for help on using the repository browser.