Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Views/3.4/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionLineChartView.cs @ 7154

Last change on this file since 7154 was 7154, checked in by gkronber, 12 years ago

#1081: worked on multi-variate time series prognosis

File size: 13.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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
21using System;
22using System.Collections.Generic;
23using System.Drawing;
24using System.Linq;
25using System.Windows.Forms;
26using System.Windows.Forms.DataVisualization.Charting;
27using HeuristicLab.MainForm;
28using HeuristicLab.MainForm.WindowsForms;
29
30namespace HeuristicLab.Problems.DataAnalysis.Views {
31  [View("Line Chart")]
32  [Content(typeof(ITimeSeriesPrognosisSolution))]
33  public partial class TimeSeriesPrognosisSolutionLineChartView : DataAnalysisSolutionEvaluationView {
34    private const string TARGETVARIABLE_SERIES_NAME = "Target Variable";
35    private const string PROGNOSEDVALUES_TRAINING_SERIES_NAME = "Prognosed Values (training)";
36    private const string PROGNOSEDVALUES_TEST_SERIES_NAME = "Prognosed Values (test)";
37    private const string PROGNOSEDVALUES_ALL_SERIES_NAME = "Prognosed Values (all samples)";
38    private string prevTargetVariable;
39
40    public new ITimeSeriesPrognosisSolution Content {
41      get { return (ITimeSeriesPrognosisSolution)base.Content; }
42      set { base.Content = value; }
43    }
44
45    public TimeSeriesPrognosisSolutionLineChartView()
46      : base() {
47      InitializeComponent();
48      //configure axis
49      this.chart.CustomizeAllChartAreas();
50      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
51      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
52      this.chart.ChartAreas[0].AxisX.IsStartedFromZero = true;
53      this.chart.ChartAreas[0].CursorX.Interval = 1;
54
55      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
56      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
57      this.chart.ChartAreas[0].CursorY.Interval = 0;
58    }
59
60    private void UpdateTargetVariables() {
61      // populate combobox
62      targetVariableComboBox.Items.Clear();
63      if (Content != null) {
64        foreach (var targetVariable in Content.ProblemData.TargetVariables)
65          targetVariableComboBox.Items.Add(targetVariable);
66
67        targetVariableComboBox.SelectedIndex = 0;
68      }
69    }
70
71
72
73    private void RedrawChart() {
74      this.chart.Series.Clear();
75      if (Content != null) {
76        this.chart.ChartAreas[0].AxisX.Minimum = 0;
77        this.chart.ChartAreas[0].AxisX.Maximum = Content.ProblemData.Dataset.Rows - 1;
78        string targetVariable = (string)targetVariableComboBox.SelectedItem;
79        int varIndex = Content.ProblemData.TargetVariables.ToList().IndexOf(targetVariable);
80
81        this.chart.Series.Add(TARGETVARIABLE_SERIES_NAME);
82        this.chart.Series[TARGETVARIABLE_SERIES_NAME].LegendText = targetVariable;
83        this.chart.Series[TARGETVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
84        this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.DataBindXY(Enumerable.Range(0, Content.ProblemData.Dataset.Rows).ToArray(),
85          Content.ProblemData.Dataset.GetDoubleValues(targetVariable).ToArray());
86
87        this.chart.Series.Add(PROGNOSEDVALUES_TRAINING_SERIES_NAME);
88        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].LegendText = PROGNOSEDVALUES_TRAINING_SERIES_NAME;
89        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].ChartType = SeriesChartType.FastLine;
90        if (prognosedValuesCheckbox.Checked) {
91          this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
92            .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
93                        Content.PrognosedTrainingValues.SelectMany(x => x).Skip(varIndex).TakeEvery(Content.ProblemData.TargetVariables.Count()).ToArray());
94        } else {
95          this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points
96            .DataBindXY(Content.ProblemData.TrainingIndizes.ToArray(),
97                        Content.GetPrognosedValues(Content.ProblemData.TrainingIndizes, 1).SelectMany(x => x.Single()).Skip(varIndex).TakeEvery(Content.ProblemData.TargetVariables.Count()).ToArray());
98        }
99        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Tag = Content;
100        this.chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, PROGNOSEDVALUES_TRAINING_SERIES_NAME);
101        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.BorderWidth = 0;
102        this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].EmptyPointStyle.MarkerStyle = MarkerStyle.None;
103
104
105        this.chart.Series.Add(PROGNOSEDVALUES_TEST_SERIES_NAME);
106        this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].LegendText = PROGNOSEDVALUES_TEST_SERIES_NAME;
107        this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].ChartType = SeriesChartType.FastLine;
108        if (prognosedValuesCheckbox.Checked) {
109          this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
110            .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
111                        Content.PrognosedTestValues.SelectMany(x => x).Skip(varIndex).TakeEvery(Content.ProblemData.TargetVariables.Count()).ToArray());
112        } else {
113          this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points
114            .DataBindXY(Content.ProblemData.TestIndizes.ToArray(),
115                        Content.GetPrognosedValues(Content.ProblemData.TestIndizes, 1).SelectMany(x => x.Single()).Skip(varIndex).TakeEvery(Content.ProblemData.TargetVariables.Count()).ToArray());
116        }
117        this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Tag = Content;
118
119        UpdateCursorInterval();
120        this.UpdateStripLines();
121      }
122    }
123
124    private void UpdateCursorInterval() {
125      var estimatedValues = this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
126      var targetValues = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
127      double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
128      double targetValuesRange = targetValues.Max() - targetValues.Min();
129      double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
130      double digits = (int)Math.Log10(interestingValuesRange) - 3;
131      double yZoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
132      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
133    }
134
135    #region events
136    protected override void RegisterContentEvents() {
137      base.RegisterContentEvents();
138      Content.ModelChanged += new EventHandler(Content_ModelChanged);
139      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
140    }
141    protected override void DeregisterContentEvents() {
142      base.DeregisterContentEvents();
143      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
144      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
145    }
146
147    protected override void OnContentChanged() {
148      base.OnContentChanged();
149      UpdateTargetVariables();
150    }
151
152    private void Content_ProblemDataChanged(object sender, EventArgs e) {
153      UpdateTargetVariables();
154    }
155    private void Content_ModelChanged(object sender, EventArgs e) {
156      RedrawChart();
157    }
158
159    private void targetVariableComboBox_SelectedIndexChanged(object sender, EventArgs e) {
160      RedrawChart();
161    }
162    private void prognosedValuesCheckbox_CheckedChanged(object sender, EventArgs e) {
163      RedrawChart();
164    }
165
166
167
168    private void Chart_MouseDoubleClick(object sender, MouseEventArgs e) {
169      HitTestResult result = chart.HitTest(e.X, e.Y);
170      if (result.ChartArea != null && (result.ChartElementType == ChartElementType.PlottingArea ||
171                                       result.ChartElementType == ChartElementType.Gridlines) ||
172                                       result.ChartElementType == ChartElementType.StripLines) {
173        foreach (var axis in result.ChartArea.Axes)
174          axis.ScaleView.ZoomReset(int.MaxValue);
175      }
176    }
177    #endregion
178
179    private void UpdateStripLines() {
180      this.chart.ChartAreas[0].AxisX.StripLines.Clear();
181
182      int[] attr = new int[Content.ProblemData.Dataset.Rows + 1]; // add a virtual last row that is again empty to simplify loop further down
183      foreach (var row in Content.ProblemData.TrainingIndizes) {
184        attr[row] += 1;
185      }
186      foreach (var row in Content.ProblemData.TestIndizes) {
187        attr[row] += 2;
188      }
189      int start = 0;
190      int curAttr = attr[start];
191      for (int row = 0; row < attr.Length; row++) {
192        if (attr[row] != curAttr) {
193          switch (curAttr) {
194            case 0: break;
195            case 1:
196              this.CreateAndAddStripLine("Training", start, row, Color.FromArgb(40, Color.Green), Color.Transparent);
197              break;
198            case 2:
199              this.CreateAndAddStripLine("Test", start, row, Color.FromArgb(40, Color.Red), Color.Transparent);
200              break;
201            case 3:
202              this.CreateAndAddStripLine("Training and Test", start, row, Color.FromArgb(40, Color.Green), Color.FromArgb(40, Color.Red), ChartHatchStyle.WideUpwardDiagonal);
203              break;
204            default:
205              // should not happen
206              break;
207          }
208          curAttr = attr[row];
209          start = row;
210        }
211      }
212    }
213
214    private void CreateAndAddStripLine(string title, int start, int end, Color color, Color secondColor, ChartHatchStyle hatchStyle = ChartHatchStyle.None) {
215      StripLine stripLine = new StripLine();
216      stripLine.BackColor = color;
217      stripLine.BackSecondaryColor = secondColor;
218      stripLine.BackHatchStyle = hatchStyle;
219      stripLine.Text = title;
220      stripLine.Font = new Font("Times New Roman", 12, FontStyle.Bold);
221      // strip range is [start .. end] inclusive, but we evaluate [start..end[ (end is exclusive)
222      // the strip should be by one longer (starting at start - 0.5 and ending at end + 0.5)
223      stripLine.StripWidth = end - start;
224      stripLine.IntervalOffset = start - 0.5; // start slightly to the left of the first point to clearly indicate the first point in the partition
225      this.chart.ChartAreas[0].AxisX.StripLines.Add(stripLine);
226    }
227
228    private void ToggleSeriesData(Series series) {
229      if (series.Points.Count > 0) {  //checks if series is shown
230        if (this.chart.Series.Any(s => s != series && s.Points.Count > 0)) {
231          series.Points.Clear();
232        }
233      } else if (Content != null) {
234        string targetVariable = (string)targetVariableComboBox.SelectedItem;
235        int varIndex = Content.ProblemData.TargetVariables.ToList().IndexOf(targetVariable);
236
237
238        IEnumerable<int> indizes = null;
239        IEnumerable<double> predictedValues = null;
240        switch (series.Name) {
241          case PROGNOSEDVALUES_TRAINING_SERIES_NAME:
242            indizes = Content.ProblemData.TrainingIndizes.ToArray();
243            predictedValues =
244              Content.PrognosedTrainingValues.SelectMany(x => x).Skip(varIndex).TakeEvery(
245                Content.ProblemData.TargetVariables.Count()).ToArray();
246            break;
247          case PROGNOSEDVALUES_TEST_SERIES_NAME:
248            indizes = Content.ProblemData.TestIndizes.ToArray();
249            Content.PrognosedTestValues.SelectMany(x => x).Skip(varIndex).TakeEvery(
250              Content.ProblemData.TargetVariables.Count()).ToArray();
251            break;
252        }
253        series.Points.DataBindXY(indizes, predictedValues);
254        chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, series.Name);
255        chart.Legends[series.Legend].ForeColor = Color.Black;
256        UpdateCursorInterval();
257        chart.Refresh();
258      }
259    }
260
261    private void chart_MouseMove(object sender, MouseEventArgs e) {
262      HitTestResult result = chart.HitTest(e.X, e.Y);
263      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME)
264        Cursor = Cursors.Hand;
265      else
266        Cursor = Cursors.Default;
267    }
268    private void chart_MouseDown(object sender, MouseEventArgs e) {
269      HitTestResult result = chart.HitTest(e.X, e.Y);
270      if (result.ChartElementType == ChartElementType.LegendItem && result.Series.Name != TARGETVARIABLE_SERIES_NAME) {
271        ToggleSeriesData(result.Series);
272      }
273    }
274
275    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
276      if (chart.Series.Count != 4) return;
277      e.LegendItems[0].Cells[1].ForeColor = this.chart.Series[TARGETVARIABLE_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
278      e.LegendItems[1].Cells[1].ForeColor = this.chart.Series[PROGNOSEDVALUES_TRAINING_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
279      e.LegendItems[2].Cells[1].ForeColor = this.chart.Series[PROGNOSEDVALUES_TEST_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
280      e.LegendItems[3].Cells[1].ForeColor = this.chart.Series[PROGNOSEDVALUES_ALL_SERIES_NAME].Points.Count == 0 ? Color.Gray : Color.Black;
281    }
282
283  }
284}
Note: See TracBrowser for help on using the repository browser.