Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RefactorPluginInfrastructure-2522/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs @ 13338

Last change on this file since 13338 was 13338, checked in by gkronber, 8 years ago

#2522:

  • moved UI components out of HeuristicLab.PluginInfrastructure -> HeuristicLab.PluginInfrastructure.UI
  • moved ErrorDialog to HeuristicLab.MainForm.WindowsForms
  • moved ErrorHandling (for building an error message string) to HeuristicLab.Common
  • Changed exception handlers in Views to use MainForm.ShowError()
  • Changed usages for ErrorDialog in non-UI components to throw exceptions instead.
File size: 10.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.Linq;
26using HeuristicLab.MainForm;
27using HeuristicLab.PluginInfrastructure;
28
29namespace HeuristicLab.Problems.DataAnalysis.Views {
30  [NonDiscoverableType]
31  public class FeatureCorrelationCalculator : Object {
32
33    private BackgroundWorker bw;
34    private BackgroundWorkerInfo bwInfo;
35
36    private IDataAnalysisProblemData problemData;
37    public IDataAnalysisProblemData ProblemData {
38      set {
39        if (bw != null) {
40          bw.CancelAsync();
41        }
42        problemData = value;
43      }
44    }
45
46    public FeatureCorrelationCalculator()
47      : base() { }
48
49    public FeatureCorrelationCalculator(IDataAnalysisProblemData problemData)
50      : base() {
51      this.problemData = problemData;
52    }
53
54    public void CalculateElements(IDependencyCalculator calc, string partition) {
55      CalculateElements(problemData.Dataset, calc, partition);
56    }
57
58    // returns true if any calculation takes place
59    public bool CalculateTimeframeElements(IDependencyCalculator calc, string partition, string variable, int frames, double[,] correlation = null) {
60      if (correlation == null || correlation.GetLength(1) <= frames) {
61        CalculateElements(problemData.Dataset, calc, partition, variable, frames, correlation);
62        return true;
63      } else {
64        return false;
65      }
66    }
67
68    public void TryCancelCalculation() {
69      if (bw != null && bw.IsBusy) {
70        bwInfo = null;
71        bw.CancelAsync();
72      }
73    }
74
75    private void CalculateElements(IDataset dataset, IDependencyCalculator calc, string partition, string variable = null, int frames = 0, double[,] alreadyCalculated = null) {
76      var indices = GetRelevantIndices(problemData, partition);
77      bwInfo = new BackgroundWorkerInfo {
78        Dataset = dataset, Calculator = calc, Partition = partition, Indices = indices,
79        Variable = variable, Frames = frames, AlreadyCalculated = alreadyCalculated
80      };
81      if (bw == null) {
82        bw = new BackgroundWorker();
83        bw.WorkerReportsProgress = true;
84        bw.WorkerSupportsCancellation = true;
85        bw.DoWork += new DoWorkEventHandler(BwDoWork);
86        bw.ProgressChanged += new ProgressChangedEventHandler(BwProgressChanged);
87        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BwRunWorkerCompleted);
88      }
89      if (bw.IsBusy) {
90        bw.CancelAsync();
91      } else {
92        bw.RunWorkerAsync(bwInfo);
93      }
94    }
95
96    private IEnumerable<int> GetRelevantIndices(IDataAnalysisProblemData problemData, string partition) {
97      IEnumerable<int> var;
98      if (partition.Equals(AbstractFeatureCorrelationView.TRAININGSAMPLES))
99        var = problemData.TrainingIndices;
100      else if (partition.Equals(AbstractFeatureCorrelationView.TESTSAMPLES))
101        var = problemData.TestIndices;
102      else var = Enumerable.Range(0, problemData.Dataset.Rows);
103      return var;
104    }
105
106    #region backgroundworker
107    private void BwDoWork(object sender, DoWorkEventArgs e) {
108      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
109      if (bwInfo.Variable == null) {
110        BwCalculateCorrelation(sender, e);
111      } else {
112        BwCalculateTimeframeCorrelation(sender, e);
113      }
114    }
115
116    private void BwCalculateCorrelation(object sender, DoWorkEventArgs e) {
117      BackgroundWorker worker = sender as BackgroundWorker;
118
119      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
120      var dataset = bwInfo.Dataset;
121      IEnumerable<int> indices = bwInfo.Indices;
122      IDependencyCalculator calc = bwInfo.Calculator;
123
124      IList<string> doubleVariableNames = dataset.DoubleVariables.ToList();
125      OnlineCalculatorError error = OnlineCalculatorError.None;
126      int length = doubleVariableNames.Count;
127      double[,] elements = new double[length, length];
128      double calculations = (Math.Pow(length, 2) + length) / 2;
129
130      worker.ReportProgress(0);
131
132      for (int i = 0; i < length; i++) {
133        for (int j = 0; j < i + 1; j++) {
134          if (worker.CancellationPending) {
135            worker.ReportProgress(100);
136            e.Cancel = true;
137            return;
138          }
139          IEnumerable<double> var1 = problemData.Dataset.GetDoubleValues(doubleVariableNames[i], indices);
140          IEnumerable<double> var2 = problemData.Dataset.GetDoubleValues(doubleVariableNames[j], indices);
141
142          elements[i, j] = calc.Calculate(var1, var2, out error);
143
144          if (!error.Equals(OnlineCalculatorError.None)) {
145            elements[i, j] = double.NaN;
146          }
147          elements[j, i] = elements[i, j];
148          worker.ReportProgress((int)Math.Round((((Math.Pow(i, 2) + i) / 2 + j + 1.0) / calculations) * 100));
149        }
150      }
151      e.Result = elements;
152      worker.ReportProgress(100);
153    }
154
155    private void BwCalculateTimeframeCorrelation(object sender, DoWorkEventArgs e) {
156      BackgroundWorker worker = sender as BackgroundWorker;
157
158      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
159      var dataset = bwInfo.Dataset;
160      IEnumerable<int> indices = bwInfo.Indices;
161      IDependencyCalculator calc = bwInfo.Calculator;
162      string variable = bwInfo.Variable;
163      int frames = bwInfo.Frames;
164      double[,] alreadyCalculated = bwInfo.AlreadyCalculated;
165
166      IList<string> doubleVariableNames = dataset.DoubleVariables.ToList();
167      OnlineCalculatorError error = OnlineCalculatorError.None;
168      int length = doubleVariableNames.Count;
169      double[,] elements = new double[length, frames + 1];
170      double calculations = (frames + 1) * length;
171
172      worker.ReportProgress(0);
173
174      int start = 0;
175      if (alreadyCalculated != null) {
176        for (int i = 0; i < alreadyCalculated.GetLength(0); i++) {
177          Array.Copy(alreadyCalculated, i * alreadyCalculated.GetLength(1), elements, i * elements.GetLength(1), alreadyCalculated.GetLength(1));
178        }
179        start = alreadyCalculated.GetLength(1);
180      }
181
182      for (int i = 0; i < length; i++) {
183        for (int j = start; j <= frames; j++) {
184          if (worker.CancellationPending) {
185            worker.ReportProgress(100);
186            e.Cancel = true;
187            return;
188          }
189
190          IEnumerable<double> var1 = problemData.Dataset.GetDoubleValues(variable, indices);
191          IEnumerable<double> var2 = problemData.Dataset.GetDoubleValues(doubleVariableNames[i], indices);
192
193          var valuesInFrame = var1.Take(j);
194          var help = var1.Skip(j).ToList();
195          help.AddRange(valuesInFrame);
196          var1 = help;
197
198          elements[i, j] = calc.Calculate(var1, var2, out error);
199
200          if (!error.Equals(OnlineCalculatorError.None)) {
201            elements[i, j] = double.NaN;
202          }
203          worker.ReportProgress((int)((100.0 / calculations) * (i * (frames + 1) + j + 1)));
204        }
205      }
206      e.Result = elements;
207      worker.ReportProgress(100);
208    }
209
210    private void BwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
211      BackgroundWorker worker = sender as BackgroundWorker;
212      if (!e.Cancelled && !worker.CancellationPending) {
213        if (e.Error != null) {
214          MainFormManager.MainForm.ShowError(e.Error.Message, e.Error);
215        } else {
216          OnCorrelationCalculationFinished((double[,])e.Result, bwInfo.Calculator, bwInfo.Partition, bwInfo.Variable);
217        }
218      } else if (bwInfo != null) {
219        bw.RunWorkerAsync(bwInfo);
220      }
221    }
222    #endregion
223
224    #region events
225    public class CorrelationCalculationFinishedArgs : EventArgs {
226      public double[,] Correlation { get; private set; }
227      public IDependencyCalculator Calculcator { get; private set; }
228      public string Partition { get; private set; }
229      public string Variable { get; private set; }
230
231      public CorrelationCalculationFinishedArgs(double[,] correlation, IDependencyCalculator calculator, string partition, string variable = null) {
232        this.Correlation = correlation;
233        this.Calculcator = calculator;
234        this.Partition = partition;
235        this.Variable = variable;
236      }
237    }
238
239    public delegate void CorrelationCalculationFinishedHandler(object sender, CorrelationCalculationFinishedArgs e);
240    public event CorrelationCalculationFinishedHandler CorrelationCalculationFinished;
241    protected virtual void OnCorrelationCalculationFinished(double[,] correlation, IDependencyCalculator calculator, string partition, string variable = null) {
242      var handler = CorrelationCalculationFinished;
243      if (handler != null)
244        handler(this, new CorrelationCalculationFinishedArgs(correlation, calculator, partition, variable));
245    }
246
247    public delegate void ProgressCalculationHandler(object sender, ProgressChangedEventArgs e);
248    public event ProgressCalculationHandler ProgressCalculation;
249    protected void BwProgressChanged(object sender, ProgressChangedEventArgs e) {
250      BackgroundWorker worker = sender as BackgroundWorker;
251      if (ProgressCalculation != null) {
252        ProgressCalculation(sender, e);
253      }
254    }
255    #endregion
256
257    private class BackgroundWorkerInfo {
258      public IDataset Dataset { get; set; }
259      public IDependencyCalculator Calculator { get; set; }
260      public string Partition { get; set; }
261      public IEnumerable<int> Indices { get; set; }
262      public string Variable { get; set; }
263      public int Frames { get; set; }
264      public double[,] AlreadyCalculated { get; set; }
265    }
266  }
267}
Note: See TracBrowser for help on using the repository browser.