Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.cs @ 14724

Last change on this file since 14724 was 14724, checked in by mkommend, 7 years ago

#2709: Adapted data preprocessing scatter plot to allow grouping of string variables.

File size: 11.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core.Views;
29using HeuristicLab.MainForm;
30using HeuristicLab.MainForm.WindowsForms;
31using RegressionType = HeuristicLab.Analysis.ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType;
32
33namespace HeuristicLab.DataPreprocessing.Views {
34
35  [View("Scatter Plot Single View")]
36  [Content(typeof(SingleScatterPlotContent), true)]
37  public sealed partial class ScatterPlotSingleView : ItemView {
38    private const int MAX_DISTINCT_VALUES_FOR_GROUPING = 20;
39    private readonly string NoGroupItem = "";
40
41    public new SingleScatterPlotContent Content {
42      get { return (SingleScatterPlotContent)base.Content; }
43      set { base.Content = value; }
44    }
45
46    public ScatterPlotSingleView() {
47      InitializeComponent();
48
49      regressionTypeComboBox.DataSource = Enum.GetValues(typeof(RegressionType));
50      regressionTypeComboBox.SelectedItem = RegressionType.None;
51    }
52
53    protected override void SetEnabledStateOfControls() {
54      base.SetEnabledStateOfControls();
55      useGradientCheckBox.Enabled = (string)comboBoxGroup.SelectedItem != NoGroupItem;
56      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked; ;
57    }
58
59    protected override void OnContentChanged() {
60      base.OnContentChanged();
61      if (Content != null) {
62        InitData();
63      }
64    }
65
66    private void InitData() {
67      IEnumerable<string> variables = Content.PreprocessingData.GetDoubleVariableNames();
68
69      comboBoxXVariable.Items.Clear();
70      comboBoxYVariable.Items.Clear();
71      comboBoxGroup.Items.Clear();
72
73      comboBoxXVariable.Items.AddRange(variables.ToArray());
74      comboBoxYVariable.Items.AddRange(variables.ToArray());
75      comboBoxGroup.Items.Add(NoGroupItem);
76      foreach (string var in GetVariableNamesForGrouping(Content.PreprocessingData)) {
77        comboBoxGroup.Items.Add(var);
78      }
79      comboBoxGroup.SelectedItem = Content.SelectedGroupVariable;
80
81      // use x and y variable from content
82      if (Content.SelectedXVariable != null && Content.SelectedYVariable != null && Content.SelectedGroupVariable != null) {
83        comboBoxXVariable.SelectedItem = Content.SelectedXVariable;
84        comboBoxYVariable.SelectedItem = Content.SelectedYVariable;
85        comboBoxGroup.SelectedItem = Content.SelectedGroupVariable;
86      } else {
87        if (variables.Count() >= 2) {
88          comboBoxXVariable.SelectedIndex = 0;
89          comboBoxYVariable.SelectedIndex = 1;
90          comboBoxGroup.SelectedIndex = 0;
91          UpdateScatterPlot();
92        }
93      }
94    }
95
96    private void UpdateScatterPlot() {
97      if (comboBoxXVariable.SelectedItem != null && comboBoxYVariable.SelectedItem != null && comboBoxGroup.SelectedItem != null) {
98        var xVariable = (string)comboBoxXVariable.SelectedItem;
99        var yVariable = (string)comboBoxYVariable.SelectedItem;
100        var groupVariable = (string)comboBoxGroup.SelectedItem;
101
102        ScatterPlot scatterPlot = Content.CreateScatterPlot(xVariable, yVariable, groupVariable);
103        //rows are saved and removed to avoid firing of visual property changed events
104        var rows = scatterPlot.Rows.ToList();
105        scatterPlot.Rows.Clear();
106        var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
107        int order = (int)polynomialRegressionOrderNumericUpDown.Value;
108        foreach (var row in rows) {
109          row.VisualProperties.PointSize = 6;
110          row.VisualProperties.IsRegressionVisibleInLegend = false;
111          row.VisualProperties.RegressionType = regressionType;
112          row.VisualProperties.PolynomialRegressionOrder = order;
113          row.VisualProperties.IsVisibleInLegend = !useGradientCheckBox.Checked;
114        }
115        scatterPlot.Rows.AddRange(rows);
116        var vp = scatterPlot.VisualProperties;
117        vp.Title = string.Empty;
118        vp.XAxisTitle = xVariable;
119        vp.YAxisTitle = yVariable;
120
121        scatterPlotControl.Content = scatterPlot;
122
123        //save selected x and y variable in content
124        this.Content.SelectedXVariable = (string)comboBoxXVariable.SelectedItem;
125        this.Content.SelectedYVariable = (string)comboBoxYVariable.SelectedItem;
126        this.Content.SelectedGroupVariable = (string)comboBoxGroup.SelectedItem;
127      }
128    }
129
130    private void comboBoxXVariable_SelectedIndexChanged(object sender, EventArgs e) {
131      var oldPlot = scatterPlotControl.Content;
132      UpdateScatterPlot();
133      var newPlot = scatterPlotControl.Content;
134
135      if (oldPlot == null || newPlot == null) return;
136      newPlot.VisualProperties.YAxisMinimumAuto = oldPlot.VisualProperties.YAxisMinimumAuto;
137      newPlot.VisualProperties.YAxisMaximumAuto = oldPlot.VisualProperties.YAxisMaximumAuto;
138      newPlot.VisualProperties.YAxisMinimumFixedValue = oldPlot.VisualProperties.YAxisMinimumFixedValue;
139      newPlot.VisualProperties.YAxisMaximumFixedValue = oldPlot.VisualProperties.YAxisMaximumFixedValue;
140
141      foreach (var x in newPlot.Rows.Zip(oldPlot.Rows, (nr, or) => new { nr, or })) {
142        var newVisuapProperties = (ScatterPlotDataRowVisualProperties)x.or.VisualProperties.Clone();
143        newVisuapProperties.DisplayName = x.nr.VisualProperties.DisplayName;
144        x.nr.VisualProperties = newVisuapProperties;
145      }
146    }
147
148    private void comboBoxYVariable_SelectedIndexChanged(object sender, EventArgs e) {
149      var oldPlot = scatterPlotControl.Content;
150      UpdateScatterPlot();
151      var newPlot = scatterPlotControl.Content;
152
153      if (oldPlot == null || newPlot == null) return;
154      newPlot.VisualProperties.XAxisMinimumAuto = oldPlot.VisualProperties.XAxisMinimumAuto;
155      newPlot.VisualProperties.XAxisMaximumAuto = oldPlot.VisualProperties.XAxisMaximumAuto;
156      newPlot.VisualProperties.XAxisMinimumFixedValue = oldPlot.VisualProperties.XAxisMinimumFixedValue;
157      newPlot.VisualProperties.XAxisMaximumFixedValue = oldPlot.VisualProperties.XAxisMaximumFixedValue;
158
159      foreach (var x in newPlot.Rows.Zip(oldPlot.Rows, (nr, or) => new { nr, or })) {
160        var newVisuapProperties = (ScatterPlotDataRowVisualProperties)x.or.VisualProperties.Clone();
161        newVisuapProperties.DisplayName = x.nr.VisualProperties.DisplayName;
162        x.nr.VisualProperties = newVisuapProperties;
163      }
164    }
165
166    private void comboBoxGroup_SelectedIndexChanged(object sender, EventArgs e) {
167      useGradientCheckBox.Enabled = (string)comboBoxGroup.SelectedItem != NoGroupItem && Content.PreprocessingData.GetDoubleVariableNames().Contains((string)comboBoxGroup.SelectedItem);
168      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked;
169      UpdateScatterPlot();
170    }
171
172    #region Regression Line
173    private void regressionTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) {
174      var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
175      polynomialRegressionOrderNumericUpDown.Enabled = regressionType == RegressionType.Polynomial;
176
177      UpdateRegressionLine();
178    }
179
180    private void polynomialRegressionOrderNumericUpDown_ValueChanged(object sender, EventArgs e) {
181      UpdateRegressionLine();
182    }
183
184    private void UpdateRegressionLine() {
185      if (Content == null) return;
186      scatterPlotControl.Content.Rows.Clear();
187
188      var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
189      int order = (int)polynomialRegressionOrderNumericUpDown.Value;
190
191      var rows = scatterPlotControl.Content.Rows.ToList();
192      foreach (var row in rows) {
193        row.VisualProperties.IsRegressionVisibleInLegend = false;
194        row.VisualProperties.RegressionType = regressionType;
195        row.VisualProperties.PolynomialRegressionOrder = order;
196      }
197      scatterPlotControl.Content.Rows.AddRange(rows);
198    }
199    #endregion
200
201    private void useGradientCheckBox_CheckedChanged(object sender, EventArgs e) {
202      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked;
203
204      // remove rows and re-add them later to avoid firing visual property changd events
205      var rows = scatterPlotControl.Content.Rows.ToDictionary(r => r.Name, r => r);
206      scatterPlotControl.Content.Rows.Clear();
207
208      if (useGradientCheckBox.Checked) {
209        var groupVariable = (string)comboBoxGroup.SelectedItem;
210        if (groupVariable == NoGroupItem) return;
211
212        var groupValues = Content.PreprocessingData.GetValues<double>(Content.PreprocessingData.GetColumnIndex(groupVariable))
213          .Distinct().OrderBy(x => x).ToList();
214        double min = groupValues.FirstOrDefault(x => !double.IsNaN(x)), max = groupValues.LastOrDefault(x => !double.IsNaN(x));
215        foreach (var group in groupValues) {
216          ScatterPlotDataRow row;
217          if (rows.TryGetValue(group.ToString("R"), out row)) {
218            row.VisualProperties.Color = GetColor(group, min, max);
219            row.VisualProperties.IsVisibleInLegend = false;
220          }
221        }
222        gradientMinimumLabel.Text = min.ToString("G5");
223        gradientMaximumLabel.Text = max.ToString("G5");
224      } else {
225        foreach (var row in rows.Values) {
226          row.VisualProperties.Color = Color.Empty;
227          row.VisualProperties.IsVisibleInLegend = true;
228        }
229      }
230      scatterPlotControl.Content.Rows.AddRange(rows.Values);
231    }
232
233    private static Color GetColor(double value, double min, double max) {
234      if (double.IsNaN(value)) {
235        return Color.Black;
236      }
237      var colors = ColorGradient.Colors;
238      int index = (int)((colors.Count - 1) * (value - min) / (max - min));
239      if (index >= colors.Count) index = colors.Count - 1;
240      if (index < 0) index = 0;
241      return colors[index];
242    }
243
244    private static IEnumerable<string> GetVariableNamesForGrouping(IPreprocessingData preprocessingData) {
245      var variableNames = new List<string>();
246
247      for (int i = 0; i < preprocessingData.Columns; ++i) {
248        int distinctValues = Int32.MaxValue;
249        if (preprocessingData.VariableHasType<double>(i))
250          distinctValues = preprocessingData.GetValues<double>(i).GroupBy(x => x).Count();
251        else if (preprocessingData.VariableHasType<string>(i))
252          distinctValues = preprocessingData.GetValues<string>(i).GroupBy(x => x).Count();
253        else if (preprocessingData.VariableHasType<DateTime>(i))
254          distinctValues = preprocessingData.GetValues<DateTime>(i).GroupBy(x => x).Count();
255
256        if (distinctValues <= MAX_DISTINCT_VALUES_FOR_GROUPING)
257          variableNames.Add(preprocessingData.GetVariableName(i));
258      }
259      return variableNames;
260    }
261  }
262}
263
Note: See TracBrowser for help on using the repository browser.