Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Views/3.4/FeatureCorrelation/FeatureCorrelationCalculator.cs @ 8874

Last change on this file since 8874 was 8874, checked in by mkommend, 10 years ago

#1292: Minor code cleanup in feature correlation classes.

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