Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/AbstractFeatureCorrelationView.cs @ 8689

Last change on this file since 8689 was 8689, checked in by sforsten, 10 years ago

#1292:

  • NaN values are used, if the calculation is invalid (e.g. missing values, infinity etc.)
  • Variables can now be filtered. Initially allowed input variables and target variable are shown, but with a right click a dialog can be opened to select variables, which shall be shown
File size: 14.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Text;
28using System.Windows.Forms;
29using HeuristicLab.Analysis;
30using HeuristicLab.Common;
31using HeuristicLab.Data.Views;
32using HeuristicLab.DataAnalysis.Views;
33using HeuristicLab.MainForm;
34using HeuristicLab.MainForm.WindowsForms;
35using FCE = HeuristicLab.Problems.DataAnalysis.FeatureCorrelationEnums;
36
37namespace HeuristicLab.Problems.DataAnalysis.Views {
38  [View("Feature Correlation View")]
39  [Content(typeof(DataAnalysisProblemData), false)]
40  public abstract partial class AbstractFeatureCorrelationView : AsynchronousContentView {
41
42    private int[] virtualRowIndices;
43    private VariableVisibilityDialog variableVisibility;
44    private List<KeyValuePair<int, SortOrder>> sortedColumnIndices;
45    private StringConvertibleMatrixView.RowComparer rowComparer;
46
47    protected FeatureCorrelationCalculator fcc;
48    protected HeatMap currentCorrelation;
49
50    public new DataAnalysisProblemData Content {
51      get { return (DataAnalysisProblemData)base.Content; }
52      set { base.Content = value; }
53    }
54
55    public AbstractFeatureCorrelationView() {
56      InitializeComponent();
57      sortedColumnIndices = new List<KeyValuePair<int, SortOrder>>();
58      rowComparer = new StringConvertibleMatrixView.RowComparer();
59      fcc = new FeatureCorrelationCalculator();
60      var calculatorList = FCE.EnumToList<FCE.CorrelationCalculators>().Select(x => new KeyValuePair<FCE.CorrelationCalculators, string>(x, FCE.GetEnumDescription(x))).ToList();
61      CorrelationCalcComboBox.ValueMember = "Key";
62      CorrelationCalcComboBox.DisplayMember = "Value";
63      CorrelationCalcComboBox.DataSource = new BindingList<KeyValuePair<FCE.CorrelationCalculators, string>>(calculatorList);
64      var partitionList = FCE.EnumToList<FCE.Partitions>().Select(x => new KeyValuePair<FCE.Partitions, string>(x, FCE.GetEnumDescription(x))).ToList();
65      PartitionComboBox.ValueMember = "Key";
66      PartitionComboBox.DisplayMember = "Value";
67      PartitionComboBox.DataSource = new BindingList<KeyValuePair<FCE.Partitions, string>>(partitionList);
68    }
69
70    protected override void RegisterContentEvents() {
71      base.RegisterContentEvents();
72      fcc.ProgressCalculation += new DataAnalysis.FeatureCorrelationCalculator.ProgressCalculationHandler(Content_ProgressCalculation);
73      fcc.CorrelationCalculationFinished += new DataAnalysis.FeatureCorrelationCalculator.CorrelationCalculationFinishedHandler(Content_CorrelationCalculationFinished);
74    }
75
76    protected override void DeregisterContentEvents() {
77      fcc.CorrelationCalculationFinished += new DataAnalysis.FeatureCorrelationCalculator.CorrelationCalculationFinishedHandler(Content_CorrelationCalculationFinished);
78      fcc.ProgressCalculation += new DataAnalysis.FeatureCorrelationCalculator.ProgressCalculationHandler(Content_ProgressCalculation);
79      base.DeregisterContentEvents();
80    }
81
82    protected override void OnContentChanged() {
83      base.OnContentChanged();
84      if (Content != null) {
85        fcc.ProblemData = Content;
86        bool[] initialVisibility = SetInitialVisibilityOfColumns();
87
88        variableVisibility = new VariableVisibilityDialog(Content.Dataset.DoubleVariables, initialVisibility);
89        variableVisibility.VariableVisibilityChanged += new ItemCheckEventHandler(variableVisibility_VariableVisibilityChanged);
90        CalculateCorrelation();
91      } else {
92        DataGridView.Columns.Clear();
93        DataGridView.Rows.Clear();
94      }
95    }
96
97    protected virtual bool[] SetInitialVisibilityOfColumns() {
98      bool[] initialVisibility = new bool[Content.Dataset.DoubleVariables.Count()];
99      int i = 0;
100      foreach (var variable in Content.Dataset.DoubleVariables) {
101        initialVisibility[i] = Content.AllowedInputVariables.Contains(variable);
102        i++;
103      }
104      return initialVisibility;
105    }
106
107    protected abstract void variableVisibility_VariableVisibilityChanged(object sender, ItemCheckEventArgs e);
108
109    protected void CorrelationMeasureComboBox_SelectedChangeCommitted(object sender, System.EventArgs e) {
110      CalculateCorrelation();
111    }
112    protected void PartitionComboBox_SelectedChangeCommitted(object sender, System.EventArgs e) {
113      CalculateCorrelation();
114    }
115
116    protected abstract void CalculateCorrelation();
117
118    protected void UpdateDataGrid() {
119      virtualRowIndices = Enumerable.Range(0, currentCorrelation.Rows).ToArray();
120      DataGridViewColumn[] columns = new DataGridViewColumn[currentCorrelation.Columns];
121      for (int i = 0; i < columns.Length; ++i) {
122        var column = new DataGridViewTextBoxColumn();
123        column.FillWeight = 1;
124        columns[i] = column;
125      }
126
127      DataGridView.Columns.Clear();
128      DataGridView.Columns.AddRange(columns);
129
130      DataGridView.RowCount = currentCorrelation.Rows;
131
132      ClearSorting();
133      UpdateColumnHeaders();
134      UpdateRowHeaders();
135
136      maximumLabel.Text = currentCorrelation.Maximum.ToString();
137      minimumLabel.Text = currentCorrelation.Minimum.ToString();
138
139      DataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader);
140      DataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders);
141      DataGridView.Enabled = true;
142    }
143
144    protected virtual void UpdateColumnHeaders() {
145      for (int i = 0; i < DataGridView.ColumnCount; i++) {
146        DataGridView.Columns[i].HeaderText = currentCorrelation.ColumnNames.ElementAt(i);
147        DataGridView.Columns[i].Visible = variableVisibility.Visibility[i];
148      }
149    }
150    protected virtual void UpdateRowHeaders() {
151      for (int i = 0; i < DataGridView.RowCount; i++) {
152        DataGridView.Rows[i].HeaderCell.Value = currentCorrelation.RowNames.ElementAt(virtualRowIndices[i]);
153        DataGridView.Rows[i].Visible = variableVisibility.Visibility[virtualRowIndices[i]];
154      }
155    }
156
157    protected void Content_ProgressCalculation(object sender, ProgressChangedEventArgs e) {
158      if (!CalculatingPanel.Visible && e.ProgressPercentage != HeatMapProgressBar.Maximum) {
159        CalculatingPanel.Show();
160      } else if (e.ProgressPercentage == HeatMapProgressBar.Maximum) {
161        CalculatingPanel.Hide();
162      }
163      HeatMapProgressBar.Value = e.ProgressPercentage;
164    }
165
166    protected abstract void Content_CorrelationCalculationFinished(object sender, FeatureCorrelationCalculator.CorrelationCalculationFinishedArgs e);
167
168    protected void DataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
169      if (Content == null) return;
170      int rowIndex = virtualRowIndices[e.RowIndex];
171      e.Value = currentCorrelation[rowIndex, e.ColumnIndex];
172    }
173
174    protected void DataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {
175      if (Content == null) return;
176      if (e.RowIndex < 0) return;
177      if (e.ColumnIndex < 0) return;
178      if (e.State.HasFlag(DataGridViewElementStates.Selected)) return;
179      if (!e.PaintParts.HasFlag(DataGridViewPaintParts.Background)) return;
180
181      int rowIndex = virtualRowIndices[e.RowIndex];
182      Color backColor = GetDataPointColor(currentCorrelation[rowIndex, e.ColumnIndex], currentCorrelation.Minimum, currentCorrelation.Maximum);
183      using (Brush backColorBrush = new SolidBrush(backColor)) {
184        e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
185      }
186      e.PaintContent(e.CellBounds);
187      e.Handled = true;
188    }
189
190    protected virtual Color GetDataPointColor(double value, double min, double max) {
191      if (double.IsNaN(value)) {
192        return Color.DarkGray;
193      }
194      IList<Color> colors = ColorGradient.Colors;
195      int index = (int)((colors.Count - 1) * (value - min) / (max - min));
196      if (index >= colors.Count) index = colors.Count - 1;
197      if (index < 0) index = 0;
198      return colors[index];
199    }
200
201    #region sort
202    protected void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
203      if (Content != null) {
204        if (e.Button == MouseButtons.Left) {
205          bool addToSortedIndices = (Control.ModifierKeys & Keys.Control) == Keys.Control;
206          SortOrder newSortOrder = SortOrder.Ascending;
207          if (sortedColumnIndices.Any(x => x.Key == e.ColumnIndex)) {
208            SortOrder oldSortOrder = sortedColumnIndices.Where(x => x.Key == e.ColumnIndex).First().Value;
209            int enumLength = Enum.GetValues(typeof(SortOrder)).Length;
210            newSortOrder = oldSortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), ((((int)oldSortOrder) + 1) % enumLength).ToString());
211          }
212
213          if (!addToSortedIndices)
214            sortedColumnIndices.Clear();
215
216          if (sortedColumnIndices.Any(x => x.Key == e.ColumnIndex)) {
217            int sortedIndex = sortedColumnIndices.FindIndex(x => x.Key == e.ColumnIndex);
218            if (newSortOrder != SortOrder.None)
219              sortedColumnIndices[sortedIndex] = new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder);
220            else
221              sortedColumnIndices.RemoveAt(sortedIndex);
222          } else
223            if (newSortOrder != SortOrder.None)
224              sortedColumnIndices.Add(new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder));
225          Sort();
226        }
227      }
228    }
229
230    protected virtual void ClearSorting() {
231      virtualRowIndices = Enumerable.Range(0, currentCorrelation.Rows).ToArray();
232      sortedColumnIndices.Clear();
233      UpdateSortGlyph();
234    }
235
236    private void Sort() {
237      virtualRowIndices = Sort(sortedColumnIndices);
238      UpdateSortGlyph();
239      UpdateRowHeaders();
240      DataGridView.Invalidate();
241    }
242
243    protected virtual int[] Sort(IEnumerable<KeyValuePair<int, SortOrder>> sortedColumns) {
244      int[] newSortedIndex = Enumerable.Range(0, currentCorrelation.Rows).ToArray();
245      if (sortedColumns.Count() != 0) {
246        rowComparer.SortedIndices = sortedColumns;
247        rowComparer.Matrix = currentCorrelation;
248        Array.Sort(newSortedIndex, rowComparer);
249      }
250      return newSortedIndex;
251    }
252    private void UpdateSortGlyph() {
253      foreach (DataGridViewColumn col in this.DataGridView.Columns)
254        col.HeaderCell.SortGlyphDirection = SortOrder.None;
255      foreach (KeyValuePair<int, SortOrder> p in sortedColumnIndices)
256        this.DataGridView.Columns[p.Key].HeaderCell.SortGlyphDirection = p.Value;
257    }
258    #endregion
259
260    #region copy
261    protected void DataGridView_KeyDown(object sender, KeyEventArgs e) {
262      if (e.Control && e.KeyCode == Keys.C)
263        CopyValuesFromDataGridView();
264    }
265
266    private void CopyValuesFromDataGridView() {
267      if (DataGridView.SelectedCells.Count == 0) return;
268      StringBuilder s = new StringBuilder();
269      int minRowIndex = DataGridView.SelectedCells[0].RowIndex;
270      int maxRowIndex = DataGridView.SelectedCells[DataGridView.SelectedCells.Count - 1].RowIndex;
271      int minColIndex = DataGridView.SelectedCells[0].ColumnIndex;
272      int maxColIndex = DataGridView.SelectedCells[DataGridView.SelectedCells.Count - 1].ColumnIndex;
273
274      if (minRowIndex > maxRowIndex) {
275        int temp = minRowIndex;
276        minRowIndex = maxRowIndex;
277        maxRowIndex = temp;
278      }
279      if (minColIndex > maxColIndex) {
280        int temp = minColIndex;
281        minColIndex = maxColIndex;
282        maxColIndex = temp;
283      }
284
285      bool addRowNames = DataGridView.AreAllCellsSelected(false) && currentCorrelation.RowNames.Count() > 0;
286      bool addColumnNames = DataGridView.AreAllCellsSelected(false) && currentCorrelation.ColumnNames.Count() > 0;
287
288      //add colum names
289      if (addColumnNames) {
290        if (addRowNames)
291          s.Append('\t');
292
293        DataGridViewColumn column = DataGridView.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
294        while (column != null) {
295          s.Append(column.HeaderText);
296          s.Append('\t');
297          column = DataGridView.Columns.GetNextColumn(column, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
298        }
299        s.Remove(s.Length - 1, 1); //remove last tab
300        s.Append(Environment.NewLine);
301      }
302
303      for (int i = minRowIndex; i <= maxRowIndex; i++) {
304        int rowIndex = this.virtualRowIndices[i];
305        if (addRowNames) {
306          s.Append(currentCorrelation.RowNames.ElementAt(rowIndex));
307          s.Append('\t');
308        }
309
310        DataGridViewColumn column = DataGridView.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
311        while (column != null) {
312          DataGridViewCell cell = DataGridView[column.Index, i];
313          if (cell.Selected) {
314            s.Append(currentCorrelation[rowIndex, column.Index]);
315            s.Append('\t');
316          }
317
318          column = DataGridView.Columns.GetNextColumn(column, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
319        }
320        s.Remove(s.Length - 1, 1); //remove last tab
321        s.Append(Environment.NewLine);
322      }
323      Clipboard.SetText(s.ToString());
324    }
325    #endregion
326
327    protected void ShowHideColumns_Click(object sender, EventArgs e) {
328      variableVisibility.ShowDialog();
329    }
330
331    protected void DataGridView_MouseClick(object sender, MouseEventArgs e) {
332      if (Content == null) return;
333      if (e.Button == MouseButtons.Right && DataGridView.Columns.Count != 0)
334        contextMenu.Show(MousePosition);
335    }
336
337    protected int GetRowIndexOfVirtualindex(int virtualIndex) {
338      if (virtualIndex < 0 || virtualIndex >= virtualRowIndices.Length) {
339        throw new ArgumentException("Virtual index is out of bounds");
340      }
341
342      for (int i = 0; i < virtualRowIndices.Length; i++) {
343        if (virtualRowIndices[i] == virtualIndex) {
344          return i;
345        }
346      }
347      throw new ArgumentException("Virtual index was not found!");
348    }
349  }
350}
Note: See TracBrowser for help on using the repository browser.