source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionVariableImpactsView.cs @ 15673

Last change on this file since 15673 was 15673, checked in by fholzing, 3 years ago

#2871: Implemented review-issues

File size: 8.0 KB
RevLine 
[14348]1#region License Information
2/* HeuristicLab
[15583]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[14348]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
[15665]21
[14348]22using System;
[15626]23using System.Collections.Generic;
[14348]24using System.Linq;
25using System.Threading.Tasks;
[15637]26using HeuristicLab.Common;
[14348]27using HeuristicLab.Data;
28using HeuristicLab.MainForm;
29
30namespace HeuristicLab.Problems.DataAnalysis.Views {
31  [View("Variable Impacts")]
32  [Content(typeof(IRegressionSolution))]
33  public partial class RegressionSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
[15673]34    private enum SortingCriteria {
35      ImpactValue,
36      Occurrence,
37      VariableName
38    }
39
[15626]40    private Dictionary<string, double> rawVariableImpacts = new Dictionary<string, double>();
41
[14348]42    public new IRegressionSolution Content {
43      get { return (IRegressionSolution)base.Content; }
44      set {
45        base.Content = value;
46      }
47    }
48
49    public RegressionSolutionVariableImpactsView()
50      : base() {
51      InitializeComponent();
[15665]52
53      //Little workaround. If you fill the ComboBox-Items in the other partial class, the UI-Designer will moan.
[15673]54      this.sortByComboBox.Items.AddRange(Enum.GetValues(typeof(SortingCriteria)).Cast<object>().ToArray());
55      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
[15665]56
[14348]57      this.dataPartitionComboBox.SelectedIndex = 0;
58      this.replacementComboBox.SelectedIndex = 0;
[14826]59      this.factorVarReplComboBox.SelectedIndex = 0;
[14348]60    }
61
62    #region events
63    protected override void RegisterContentEvents() {
64      base.RegisterContentEvents();
65      Content.ModelChanged += new EventHandler(Content_ModelChanged);
66      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
67    }
68
69    protected override void DeregisterContentEvents() {
70      base.DeregisterContentEvents();
71      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
72      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
73    }
74
75    protected virtual void Content_ProblemDataChanged(object sender, EventArgs e) {
76      OnContentChanged();
77    }
78
79    protected virtual void Content_ModelChanged(object sender, EventArgs e) {
80      OnContentChanged();
81    }
82
83    protected override void OnContentChanged() {
84      base.OnContentChanged();
85      if (Content == null) {
86        variableImactsArrayView.Content = null;
87      } else {
88        UpdateVariableImpacts();
89      }
90    }
91
[15665]92
93    private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
94      UpdateVariableImpacts();
95    }
96
97    private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
98      UpdateVariableImpacts();
99    }
100
101    private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
102      //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
103      ascendingCheckBox.CheckedChanged -= ascendingCheckBox_CheckedChanged;
[15673]104      switch ((SortingCriteria)sortByComboBox.SelectedItem) {
105        case SortingCriteria.ImpactValue:
[15665]106          ascendingCheckBox.Checked = false;
107          break;
[15673]108        case SortingCriteria.Occurrence:
[15665]109          ascendingCheckBox.Checked = true;
110          break;
[15673]111        case SortingCriteria.VariableName:
[15665]112          ascendingCheckBox.Checked = true;
113          break;
114        default:
[15673]115          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
[15665]116      }
117      ascendingCheckBox.CheckedChanged += ascendingCheckBox_CheckedChanged;
118
119      UpdateDataOrdering();
120    }
121
122    private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
123      UpdateDataOrdering();
124    }
125    #endregion
126
127    #region Helper Methods         
[14348]128    private void UpdateVariableImpacts() {
[15673]129      if (Content == null) { return; }
130      if (replacementComboBox.SelectedIndex < 0) { return; }
131      if (dataPartitionComboBox.SelectedIndex < 0) { return; }
132      if (factorVarReplComboBox.SelectedIndex < 0) { return; }
133
[14348]134      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
135
[15673]136      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
137      var replMethod = (RegressionSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
138      var factorReplMethod = (RegressionSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
139      var dataPartition = (RegressionSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
140
[14348]141      Task.Factory.StartNew(() => {
142        try {
143          mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
144
[15665]145          //Remember the original ordering of the variables
[14826]146          var impacts = RegressionSolutionVariableImpactsCalculator.CalculateImpacts(Content, dataPartition, replMethod, factorReplMethod);
[15626]147          var problemData = Content.ProblemData;
148          var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
149          var originalVariableOrdering = problemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).Where(problemData.Dataset.VariableHasType<double>).ToList();
150          rawVariableImpacts.Clear();
151          originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(v, impacts.First(vv => vv.Item1 == v).Item2));
[15673]152          UpdateDataOrdering();
[14348]153        } finally {
154          mainForm.RemoveOperationProgressFromView(this);
155        }
156      });
157    }
158
[15626]159    /// <summary>
160    /// Updates the <see cref="variableImactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
161    /// The default is "Descending" by "VariableImpact" (as in previous versions)
162    /// </summary>
163    private void UpdateDataOrdering() {
[15665]164      //Check if valid sortingCriteria is selected and data exists
[15673]165      if (sortByComboBox.SelectedIndex == -1) { return; }
166      if (rawVariableImpacts == null) { return; }
167      if (!rawVariableImpacts.Any()) { return; }
[15665]168
[15673]169      var selectedItem = (SortingCriteria)sortByComboBox.SelectedItem;
[15626]170      bool ascending = ascendingCheckBox.Checked;
171
[15665]172      IEnumerable<KeyValuePair<string, double>> orderedEntries = null;
[15626]173
[15665]174      //Sort accordingly
175      switch (selectedItem) {
[15673]176        case SortingCriteria.ImpactValue:
177          orderedEntries = rawVariableImpacts.OrderBy(v => v.Value);
[15665]178          break;
[15673]179        case SortingCriteria.Occurrence:
180          orderedEntries = rawVariableImpacts;
[15665]181          break;
[15673]182        case SortingCriteria.VariableName:
183          orderedEntries = rawVariableImpacts.OrderBy(v => v.Key, new NaturalStringComparer());
[15665]184          break;
185        default:
[15673]186          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
[15626]187      }
188
[15673]189      if (!ascending) { orderedEntries = orderedEntries.Reverse(); }
190
[15665]191      //Write the data back
192      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Value).ToArray()) {
193        ElementNames = orderedEntries.Select(i => i.Key)
194      };
195      variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
[15626]196    }
197    #endregion
[14348]198  }
199}
Note: See TracBrowser for help on using the repository browser.