Ignore:
Timestamp:
12/21/18 14:05:32 (5 months ago)
Author:
mkommend
Message:

#2884: Merged r15638, r15667, r15674, r15729, r15753, r16232 into stable.

Location:
stable
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Views

  • stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs

    r15638 r16432  
    1919 */
    2020#endregion
     21
    2122using System;
     23using System.Collections.Generic;
    2224using System.Linq;
     25using System.Threading;
    2326using System.Threading.Tasks;
     27using HeuristicLab.Common;
    2428using HeuristicLab.Data;
    2529using HeuristicLab.MainForm;
     
    2933  [Content(typeof(IClassificationSolution))]
    3034  public partial class ClassificationSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
    31 
     35    #region Nested Types
     36    private enum SortingCriteria {
     37      ImpactValue,
     38      Occurrence,
     39      VariableName
     40    }
     41    #endregion
     42
     43    #region Fields
     44    private Dictionary<string, double> rawVariableImpacts = new Dictionary<string, double>();
     45    private Thread thread;
     46    #endregion
     47
     48    #region Getter/Setter
    3249    public new IClassificationSolution Content {
    3350      get { return (IClassificationSolution)base.Content; }
     
    3653      }
    3754    }
    38 
     55    #endregion
     56
     57    #region Ctor
    3958    public ClassificationSolutionVariableImpactsView()
    4059      : base() {
    4160      InitializeComponent();
     61
     62      this.sortByComboBox.Items.AddRange(Enum.GetValues(typeof(SortingCriteria)).Cast<object>().ToArray());
     63      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
     64
     65      //Set the default values
    4266      this.dataPartitionComboBox.SelectedIndex = 0;
    4367      this.replacementComboBox.SelectedIndex = 0;
    4468      this.factorVarReplComboBox.SelectedIndex = 0;
    4569    }
    46 
    47     #region events
     70    #endregion
     71
     72    #region Events
    4873    protected override void RegisterContentEvents() {
    4974      base.RegisterContentEvents();
     
    7196        variableImactsArrayView.Content = null;
    7297      } else {
    73         UpdateVariableImpacts();
    74       }
    75     }
    76 
    77     private void UpdateVariableImpacts() {
    78       if (Content == null || replacementComboBox.SelectedIndex < 0
    79         || factorVarReplComboBox.SelectedIndex < 0
    80         || dataPartitionComboBox.SelectedIndex < 0) return;
     98        UpdateVariableImpact();
     99      }
     100    }
     101
     102    private void ClassificationSolutionVariableImpactsView_VisibleChanged(object sender, EventArgs e) {
     103      if (thread == null) { return; }
     104
     105      if (thread.IsAlive) { thread.Abort(); }
     106      thread = null;
     107    }
     108
     109
     110    private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
     111      UpdateVariableImpact();
     112    }
     113
     114    private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
     115      UpdateVariableImpact();
     116    }
     117
     118    private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
     119      //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
     120      ascendingCheckBox.CheckedChanged -= ascendingCheckBox_CheckedChanged;
     121      switch ((SortingCriteria)sortByComboBox.SelectedItem) {
     122        case SortingCriteria.ImpactValue:
     123          ascendingCheckBox.Checked = false;
     124          break;
     125        case SortingCriteria.Occurrence:
     126          ascendingCheckBox.Checked = true;
     127          break;
     128        case SortingCriteria.VariableName:
     129          ascendingCheckBox.Checked = true;
     130          break;
     131        default:
     132          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
     133      }
     134      ascendingCheckBox.CheckedChanged += ascendingCheckBox_CheckedChanged;
     135
     136      UpdateDataOrdering();
     137    }
     138
     139    private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
     140      UpdateDataOrdering();
     141    }
     142
     143    #endregion
     144
     145    #region Helper Methods   
     146    private void UpdateVariableImpact() {
     147      //Check if the selection is valid
     148      if (Content == null) { return; }
     149      if (replacementComboBox.SelectedIndex < 0) { return; }
     150      if (dataPartitionComboBox.SelectedIndex < 0) { return; }
     151      if (factorVarReplComboBox.SelectedIndex < 0) { return; }
     152
     153      //Prepare arguments
    81154      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
     155      var replMethod = (ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
     156      var factorReplMethod = (ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
     157      var dataPartition = (ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
     158
    82159      variableImactsArrayView.Caption = Content.Name + " Variable Impacts";
    83       var replMethod =
    84          (ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum)
    85            replacementComboBox.Items[replacementComboBox.SelectedIndex];
    86       var factorReplMethod =
    87         (ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)
    88           factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
    89       var dataPartition =
    90         (ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
     160
     161      mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
    91162
    92163      Task.Factory.StartNew(() => {
    93         try {
    94           mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
    95 
    96           var impacts = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(Content, dataPartition, replMethod, factorReplMethod);
    97           var impactArray = new DoubleArray(impacts.Select(i => i.Item2).ToArray());
    98           impactArray.ElementNames = impacts.Select(i => i.Item1);
    99           variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
    100         } finally {
    101           mainForm.RemoveOperationProgressFromView(this);
    102         }
    103       });
    104     }
    105 
    106     #endregion
    107 
    108     private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    109       UpdateVariableImpacts();
    110     }
    111 
    112     private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
    113       UpdateVariableImpacts();
    114     }
     164        thread = Thread.CurrentThread;
     165        //Remember the original ordering of the variables
     166        var impacts = ClassificationSolutionVariableImpactsCalculator.CalculateImpacts(Content, dataPartition, replMethod, factorReplMethod);
     167        var problemData = Content.ProblemData;
     168        var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
     169        var originalVariableOrdering = problemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).Where(problemData.Dataset.VariableHasType<double>).ToList();
     170
     171        rawVariableImpacts.Clear();
     172        originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(v, impacts.First(vv => vv.Item1 == v).Item2));
     173      }).ContinueWith((o) => {
     174        UpdateDataOrdering();
     175        mainForm.RemoveOperationProgressFromView(this);
     176        thread = null;
     177      }, TaskScheduler.FromCurrentSynchronizationContext());
     178    }
     179
     180    /// <summary>
     181    /// Updates the <see cref="variableImactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
     182    /// The default is "Descending" by "VariableImpact" (as in previous versions)
     183    /// </summary>
     184    private void UpdateDataOrdering() {
     185      //Check if valid sortingCriteria is selected and data exists
     186      if (sortByComboBox.SelectedIndex == -1) { return; }
     187      if (rawVariableImpacts == null) { return; }
     188      if (!rawVariableImpacts.Any()) { return; }
     189
     190      var selectedItem = (SortingCriteria)sortByComboBox.SelectedItem;
     191      bool ascending = ascendingCheckBox.Checked;
     192
     193      IEnumerable<KeyValuePair<string, double>> orderedEntries = null;
     194
     195      //Sort accordingly
     196      switch (selectedItem) {
     197        case SortingCriteria.ImpactValue:
     198          orderedEntries = rawVariableImpacts.OrderBy(v => v.Value);
     199          break;
     200        case SortingCriteria.Occurrence:
     201          orderedEntries = rawVariableImpacts;
     202          break;
     203        case SortingCriteria.VariableName:
     204          orderedEntries = rawVariableImpacts.OrderBy(v => v.Key, new NaturalStringComparer());
     205          break;
     206        default:
     207          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
     208      }
     209
     210      if (!ascending) { orderedEntries = orderedEntries.Reverse(); }
     211
     212      //Write the data back
     213      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Value).ToArray()) {
     214        ElementNames = orderedEntries.Select(i => i.Key)
     215      };
     216
     217      //Could be, if the View was closed
     218      if (!variableImactsArrayView.IsDisposed) {
     219        variableImactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
     220      }
     221    }
     222    #endregion 
    115223  }
    116224}
Note: See TracChangeset for help on using the changeset viewer.