source: branches/2971_named_intervals/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.cs @ 16638

Last change on this file since 16638 was 16638, checked in by gkronber, 7 months ago

#2971: merged r16527:16625 from trunk/HeuristicLab.Problems.DataAnalysis.Views to branch/HeuristicLab.Problems.DataAnalysis.Views

File size: 8.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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.Linq;
25using System.Windows.Forms;
26using HeuristicLab.Collections;
27using HeuristicLab.Core.Views;
28using HeuristicLab.MainForm;
29using HeuristicLab.MainForm.WindowsForms;
30using HeuristicLab.Problems.DataAnalysis;
31using HeuristicLab.Visualization.ChartControlsExtensions;
32
33namespace HeuristicLab.Algorithms.DataAnalysis.Views {
34  [View("Gradient View")]
35  [Content(typeof(IRegressionSolution))]
36  public partial class RegressionSolutionGradientView : ItemView {
37    private const int DrawingSteps = 1000;
38
39    private readonly List<string> variableNames;
40    private readonly ObservableList<DensityTrackbar> trackbars;
41    private ModifiableDataset sharedFixedVariables;
42
43    private int ActiveDimension {
44      get { return trackbars.FindIndex(tb => tb.Checked); }
45    }
46
47    public new IRegressionSolution Content {
48      get { return (IRegressionSolution)base.Content; }
49      set { base.Content = value; }
50    }
51
52    public RegressionSolutionGradientView()
53      : base() {
54      variableNames = new List<string>();
55
56      trackbars = new ObservableList<DensityTrackbar>();
57      trackbars.ItemsAdded += (sender, args) => {
58        args.Items.Select(i => i.Value).ForEach(RegisterEvents);
59      };
60      trackbars.ItemsRemoved += (sender, args) => {
61        args.Items.Select(i => i.Value).ForEach(DeregisterEvents);
62      };
63      trackbars.CollectionReset += (sender, args) => {
64        args.OldItems.Select(i => i.Value).ForEach(DeregisterEvents);
65        args.Items.Select(i => i.Value).ForEach(RegisterEvents);
66      };
67
68      InitializeComponent();
69
70      // Avoid additional horizontal scrollbar
71      var vertScrollWidth = SystemInformation.VerticalScrollBarWidth;
72      tableLayoutPanel.Padding = new Padding(0, 0, vertScrollWidth, 0);
73    }
74
75    private async void UpdateConfigurationControls() {
76      variableNames.Clear();
77      trackbars.Clear();
78
79      tableLayoutPanel.SuspendRepaint();
80      tableLayoutPanel.SuspendLayout();
81
82      tableLayoutPanel.RowCount = 0;
83      tableLayoutPanel.Controls.Clear();
84
85      if (Content == null) {
86        tableLayoutPanel.ResumeLayout(false);
87        tableLayoutPanel.ResumeRepaint(false);
88        return;
89      }
90
91      variableNames.AddRange(Content.ProblemData.AllowedInputVariables);
92
93      var newTrackbars = CreateConfiguration();
94
95      sharedFixedVariables = new ModifiableDataset(variableNames, newTrackbars.Select(tb => new List<double>(1) { (double)tb.Value }));
96      _partialDependencePlot.Configure(new[] { Content }, sharedFixedVariables, variableNames.First(), DrawingSteps);
97      await _partialDependencePlot.RecalculateAsync();
98
99      // Add to table and observable lists
100      tableLayoutPanel.RowCount = variableNames.Count;
101      while (tableLayoutPanel.RowStyles.Count < variableNames.Count)
102        tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
103      for (int i = 0; i < newTrackbars.Count; i++) {
104        // events registered automatically
105        trackbars.Add(newTrackbars[i]);
106        tableLayoutPanel.Controls.Add(newTrackbars[i], 0, i);
107      }
108
109      tableLayoutPanel.ResumeLayout(true);
110      tableLayoutPanel.ResumeRepaint(true);
111
112      // Init Y-axis range
113      var problemData = Content.ProblemData;
114      double min = double.MaxValue, max = double.MinValue;
115      var trainingTarget = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
116      foreach (var t in trainingTarget) {
117        if (t < min) min = t;
118        if (t > max) max = t;
119      }
120      double range = max - min;
121      const double scale = 1.0 / 3.0;
122      double axisMin, axisMax, axisInterval;
123      ChartUtil.CalculateAxisInterval(min - scale * range, max + scale * range, 5, out axisMin, out axisMax, out axisInterval);
124      _partialDependencePlot.FixedYAxisMin = axisMin;
125      _partialDependencePlot.FixedYAxisMax = axisMax;
126
127      trackbars.First().Checked = true;
128    }
129
130    private IList<DensityTrackbar> CreateConfiguration() {
131      var ranges = new List<DoubleLimit>();
132      foreach (string variableName in variableNames) {
133        var values = Content.ProblemData.Dataset.GetDoubleValues(variableName, Content.ProblemData.AllIndices);
134        double min, max, interval;
135        ChartUtil.CalculateAxisInterval(values.Min(), values.Max(), 10, out min, out max, out interval);
136        ranges.Add(new DoubleLimit(min, max));
137      }
138
139      var newTrackbars = new List<DensityTrackbar>();
140      for (int i = 0; i < variableNames.Count; i++) {
141        var name = variableNames[i];
142        var trainingData = Content.ProblemData.Dataset.GetDoubleValues(name, Content.ProblemData.TrainingIndices).ToList();
143
144        var dimensionTrackbar = new DensityTrackbar(name, ranges[i], trainingData) {
145          Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
146        };
147        newTrackbars.Add(dimensionTrackbar);
148      }
149
150      return newTrackbars;
151    }
152
153    private void RegisterEvents(DensityTrackbar trackbar) {
154      trackbar.CheckedChanged += trackbar_CheckedChanged;
155      trackbar.ValueChanged += trackbar_ValueChanged;
156      trackbar.LimitsChanged += trackbar_LimitsChanged;
157    }
158    private void DeregisterEvents(DensityTrackbar trackbar) {
159      trackbar.CheckedChanged -= trackbar_CheckedChanged;
160      trackbar.ValueChanged -= trackbar_ValueChanged;
161      trackbar.LimitsChanged -= trackbar_LimitsChanged;
162    }
163
164    private async void trackbar_CheckedChanged(object sender, EventArgs e) {
165      var trackBar = sender as DensityTrackbar;
166      if (trackBar == null || !trackBar.Checked) return;
167      // Uncheck all others
168      foreach (var tb in trackbars.Except(new[] { trackBar }))
169        tb.Checked = false;
170      _partialDependencePlot.FreeVariable = variableNames[trackbars.IndexOf(trackBar)];
171      await _partialDependencePlot.RecalculateAsync();
172    }
173
174    private async void trackbar_LimitsChanged(object sender, EventArgs e) {
175      var trackBar = sender as DensityTrackbar;
176      if (trackBar == null || !trackBar.Checked) return;
177      _partialDependencePlot.FixedXAxisMin = trackBar.Limits.Lower;
178      _partialDependencePlot.FixedXAxisMax = trackBar.Limits.Upper;
179      await _partialDependencePlot.RecalculateAsync();
180    }
181
182    private async void trackbar_ValueChanged(object sender, EventArgs e) {
183      var trackBar = sender as DensityTrackbar;
184      if (trackBar == null) return;
185      sharedFixedVariables.SetVariableValue((double)trackBar.Value, variableNames[trackbars.IndexOf(trackBar)], 0);
186      await _partialDependencePlot.RecalculateAsync();
187    }
188
189    #region Events
190    protected override void RegisterContentEvents() {
191      base.RegisterContentEvents();
192      Content.ModelChanged += Content_ModelChanged;
193      Content.ProblemDataChanged += Content_ProblemDataChanged;
194    }
195
196    protected override void DeregisterContentEvents() {
197      base.DeregisterContentEvents();
198      Content.ModelChanged -= Content_ModelChanged;
199      Content.ProblemDataChanged -= Content_ProblemDataChanged;
200    }
201
202    protected override void OnContentChanged() {
203      base.OnContentChanged();
204      UpdateConfigurationControls();
205    }
206
207    private void Content_ModelChanged(object sender, EventArgs e) {
208      UpdateConfigurationControls();
209    }
210
211    private void Content_ProblemDataChanged(object sender, EventArgs e) {
212      UpdateConfigurationControls();
213    }
214    #endregion
215  }
216
217  internal static class Extensions {
218    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
219      foreach (T item in source)
220        action(item);
221    }
222  }
223}
Note: See TracBrowser for help on using the repository browser.