Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.3/ScatterPlotView.cs @ 3707

Last change on this file since 3707 was 3707, checked in by gkronber, 14 years ago

Added adjustment of cursor interval based on range of displayed values in the RunCollectionBubbleChartView ScatterPlotView and LineChartView. #893

File size: 10.3 KB
Line 
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
21using System;
22using System.Collections.Generic;
23using System.ComponentModel;
24using System.Drawing;
25using System.Data;
26using System.Linq;
27using System.Text;
28using System.Windows.Forms;
29using System.Windows.Forms.DataVisualization.Charting;
30using HeuristicLab.Common;
31using System.Collections.Specialized;
32using HeuristicLab.MainForm;
33using HeuristicLab.Problems.DataAnalysis;
34using HeuristicLab.MainForm.WindowsForms;
35
36namespace HeuristicLab.Problems.DataAnalysis.Views {
37  [View("Scatter Plot View")]
38  [Content(typeof(DataAnalysisSolution), true)]
39  public partial class ScatterPlotView : AsynchronousContentView {
40    private const string DEFAULT_CAPTION = "Scatter Plot";
41    private const string ALL_SERIES = "All Samples";
42    private const string TRAINING_SERIES = "Training Samples";
43    private const string TEST_SERIES = "Test Samples";
44
45    public new DataAnalysisSolution Content {
46      get { return (DataAnalysisSolution)base.Content; }
47      set { base.Content = value; }
48    }
49
50    public ScatterPlotView()
51      : base() {
52      InitializeComponent();
53      this.Caption = DEFAULT_CAPTION;
54
55      this.chart.Series.Add(ALL_SERIES);
56      this.chart.Series[ALL_SERIES].LegendText = ALL_SERIES;
57      this.chart.Series[ALL_SERIES].ChartType = SeriesChartType.FastPoint;
58
59      this.chart.Series.Add(TRAINING_SERIES);
60      this.chart.Series[TRAINING_SERIES].LegendText = TRAINING_SERIES;
61      this.chart.Series[TRAINING_SERIES].ChartType = SeriesChartType.FastPoint;
62
63      this.chart.Series.Add(TEST_SERIES);
64      this.chart.Series[TEST_SERIES].LegendText = TEST_SERIES;
65      this.chart.Series[TEST_SERIES].ChartType = SeriesChartType.FastPoint;
66
67      this.chart.TextAntiAliasingQuality = TextAntiAliasingQuality.High;
68      this.chart.AxisViewChanged += new EventHandler<System.Windows.Forms.DataVisualization.Charting.ViewEventArgs>(chart_AxisViewChanged);
69
70      //configure axis                 
71      this.chart.ChartAreas[0].AxisX.Title = "Estimated Values";
72      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
73      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
74      this.chart.ChartAreas[0].CursorX.Interval = 1;
75      this.chart.ChartAreas[0].CursorY.Interval = 1;
76
77      this.chart.ChartAreas[0].AxisY.Title = "Target Values";
78      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
79      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
80      this.chart.ChartAreas[0].AxisY.IsStartedFromZero = true;
81    }
82
83    protected override void RegisterContentEvents() {
84      base.RegisterContentEvents();
85      Content.EstimatedValuesChanged += new EventHandler(Content_EstimatedValuesChanged);
86      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
87    }
88    protected override void DeregisterContentEvents() {
89      base.DeregisterContentEvents();
90      Content.EstimatedValuesChanged -= new EventHandler(Content_EstimatedValuesChanged);
91      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
92    }
93
94
95    void Content_ProblemDataChanged(object sender, EventArgs e) {
96      UpdateChart();
97    }
98
99    void Content_EstimatedValuesChanged(object sender, EventArgs e) {
100      UpdateSeries();
101    }
102
103    protected override void OnContentChanged() {
104      base.OnContentChanged();
105      UpdateChart();
106    }
107
108    private void UpdateChart() {
109      if (InvokeRequired) Invoke((Action)UpdateChart);
110      else {
111        if (Content != null) {
112          this.Caption = Content.ItemName + " " + DEFAULT_CAPTION;
113          this.UpdateSeries();
114          if (!this.chart.Series.Any(s => s.Points.Count > 0))
115            this.ToggleSeriesData(this.chart.Series[TRAINING_SERIES]);
116        } else {
117          this.Caption = DEFAULT_CAPTION;
118          this.ClearChart();
119        }
120      }
121    }
122
123    private void UpdateCursorInterval() {
124      var estimatedValues = this.chart.Series[ALL_SERIES].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
125      var targetValues = this.chart.Series[ALL_SERIES].Points.Select(x => x.YValues[1]).DefaultIfEmpty(1.0);
126      double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
127      double targetValuesRange = targetValues.Max() - targetValues.Min();
128      double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
129      double digits = (int)Math.Log10(interestingValuesRange) - 3;
130      double zoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
131      this.chart.ChartAreas[0].CursorX.Interval = zoomInterval;
132      this.chart.ChartAreas[0].CursorY.Interval = zoomInterval;
133    }
134
135
136    private void UpdateSeries() {
137      if (InvokeRequired) Invoke((Action)UpdateSeries);
138      else {
139        string targetVariableName = Content.ProblemData.TargetVariable.Value;
140        Dataset dataset = Content.ProblemData.Dataset;
141        int trainingStart = Content.ProblemData.TrainingSamplesStart.Value;
142        int trainingEnd = Content.ProblemData.TrainingSamplesEnd.Value;
143        int testStart = Content.ProblemData.TestSamplesStart.Value;
144        int testEnd = Content.ProblemData.TestSamplesEnd.Value;
145        if (this.chart.Series[ALL_SERIES].Points.Count > 0)
146          this.chart.Series[ALL_SERIES].Points.DataBindXY(Content.EstimatedValues.ToArray(), "",
147            dataset[targetVariableName], "");
148        if (this.chart.Series[TRAINING_SERIES].Points.Count > 0)
149          this.chart.Series[TRAINING_SERIES].Points.DataBindXY(Content.EstimatedTrainingValues.ToArray(), "",
150            dataset.GetVariableValues(targetVariableName, trainingStart, trainingEnd), "");
151        if (this.chart.Series[TEST_SERIES].Points.Count > 0)
152          this.chart.Series[TEST_SERIES].Points.DataBindXY(Content.EstimatedTestValues.ToArray(), "",
153            dataset.GetVariableValues(targetVariableName, testStart, testEnd), "");
154
155        double max = Math.Max(Content.EstimatedValues.Max(), dataset.GetMax(targetVariableName));
156        double min = Math.Min(Content.EstimatedValues.Min(), dataset.GetMin(targetVariableName));
157
158        max = Math.Ceiling(max) * 1.2;
159        min = Math.Floor(min) * 0.8;
160
161        this.chart.ChartAreas[0].AxisX.Maximum = max;
162        this.chart.ChartAreas[0].AxisX.Minimum = min;
163        this.chart.ChartAreas[0].AxisY.Maximum = max;
164        this.chart.ChartAreas[0].AxisY.Minimum = min;
165        UpdateCursorInterval();
166      }
167    }
168
169    private void ClearChart() {
170      this.chart.Series[ALL_SERIES].Points.Clear();
171      this.chart.Series[TRAINING_SERIES].Points.Clear();
172      this.chart.Series[TEST_SERIES].Points.Clear();     
173    }
174
175    private void ToggleSeriesData(Series series) {
176      if (series.Points.Count > 0) {  //checks if series is shown
177        if (this.chart.Series.Any(s => s != series && s.Points.Count > 0)) {
178          series.Points.Clear();
179        }
180      } else if (Content != null) {
181        string targetVariableName = Content.ProblemData.TargetVariable.Value;
182        Dataset dataset = Content.ProblemData.Dataset;
183        int trainingStart = Content.ProblemData.TrainingSamplesStart.Value;
184        int trainingEnd = Content.ProblemData.TrainingSamplesEnd.Value;
185        int testStart = Content.ProblemData.TestSamplesStart.Value;
186        int testEnd = Content.ProblemData.TestSamplesEnd.Value;
187
188        IEnumerable<double> predictedValues = null;
189        IEnumerable<double> targetValues = null;
190        switch (series.Name) {
191          case ALL_SERIES:
192            predictedValues = Content.EstimatedValues;
193            targetValues = dataset[targetVariableName];
194            break;
195          case TRAINING_SERIES:
196            predictedValues = Content.EstimatedTrainingValues;
197            targetValues = dataset.GetVariableValues(targetVariableName, trainingStart, trainingEnd);
198            break;
199          case TEST_SERIES:
200            predictedValues = Content.EstimatedTestValues;
201            targetValues = dataset.GetVariableValues(targetVariableName, testStart, testEnd);
202            break;
203        }
204        series.Points.DataBindXY(predictedValues, "", targetValues, "");
205        this.chart.Legends[series.Legend].ForeColor = Color.Black;
206        UpdateCursorInterval();
207      }
208    }
209
210    private void chart_MouseDown(object sender, MouseEventArgs e) {
211      HitTestResult result = chart.HitTest(e.X, e.Y);
212      if (result.ChartElementType == ChartElementType.LegendItem) {
213        this.ToggleSeriesData(result.Series);
214      }
215    }
216
217    private void chart_MouseMove(object sender, MouseEventArgs e) {
218      HitTestResult result = chart.HitTest(e.X, e.Y);
219      if (result.ChartElementType == ChartElementType.LegendItem)
220        this.Cursor = Cursors.Hand;
221      else
222        this.Cursor = Cursors.Default;
223    }
224
225    private void chart_AxisViewChanged(object sender, System.Windows.Forms.DataVisualization.Charting.ViewEventArgs e) {
226      this.chart.ChartAreas[0].AxisX.ScaleView.Size = e.NewSize;
227      this.chart.ChartAreas[0].AxisY.ScaleView.Size = e.NewSize;
228    }
229
230    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
231      e.LegendItems[0].Cells[1].ForeColor = this.chart.Series[ALL_SERIES].Points.Count == 0 ? Color.Gray : Color.Black;
232      e.LegendItems[1].Cells[1].ForeColor = this.chart.Series[TRAINING_SERIES].Points.Count == 0 ? Color.Gray : Color.Black;
233      e.LegendItems[2].Cells[1].ForeColor = this.chart.Series[TEST_SERIES].Points.Count == 0 ? Color.Gray : Color.Black;
234    }
235  }
236}
Note: See TracBrowser for help on using the repository browser.