Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs @ 16147

Last change on this file since 16147 was 15753, checked in by fholzing, 7 years ago

#2884: Changed back to Task, abort Thread if any other View is shown

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