#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using HeuristicLab.MainForm;
using HeuristicLab.MainForm.WindowsForms;
using System.Collections.Generic;
using HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Symbolic;
namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.TimeSeriesPrognosis.Views {
[View("Symbolic Time Series Prognosis Line Chart View")]
[Content(typeof(SymbolicTimeSeriesPrognosisSolution))]
public partial class TimeSeriesPrognosisLineChartView : AsynchronousContentView {
private const string TARGETVARIABLE_SERIES_NAME = "(target)";
private const string ESTIMATEDVALUES_SERIES_NAME = "(estimated)";
public new SymbolicTimeSeriesPrognosisSolution Content {
get { return (SymbolicTimeSeriesPrognosisSolution)base.Content; }
set { base.Content = value; }
}
public TimeSeriesPrognosisLineChartView()
: base() {
InitializeComponent();
//configure axis
this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
this.chart.ChartAreas[0].CursorX.Interval = 1;
this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
this.chart.ChartAreas[0].CursorY.Interval = 0;
}
private void RedrawChart() {
this.chart.Series.Clear();
if (Content != null) {
int selectedHorizonValue = Math.Min(Content.Horizon, Math.Max(1, (int)numericUpDown.Value));
numericUpDown.Minimum = 1;
numericUpDown.Maximum = Content.Horizon;
numericUpDown.Value = selectedHorizonValue;
List targetVariables = Content.ProblemData.TargetVariables.CheckedItems.Select(x => x.Value.Value).ToList();
// horizon=1 (t+0) => 0 .. 10
// horizon=2 (t+0..1) => -1 .. 9
// horizon=3 (t+0..2) => -2 .. 8
// ...
// horizon=10 (t+0..9) => -9 .. 1
int firstIndex = 1 - selectedHorizonValue;
int lastIndex = Content.ProblemData.Dataset.Rows ;
double[] nanVector =
targetVariables
.Select(x => double.NaN)
.ToArray();
IEnumerable rows = Enumerable.Range(firstIndex, lastIndex );
IEnumerable> values = from row in rows
let evaluate = string.IsNullOrEmpty(Content.ConditionalEvaluationVariable) ||
(row > 0 && row < lastIndex &&
Content.ProblemData.Dataset[Content.ConditionalEvaluationVariable, row + selectedHorizonValue - 1] > 0)
select evaluate ? Content.GetPrognosis(row) : Enumerable.Repeat(nanVector, Content.Horizon);
for (int col = 0; col < targetVariables.Count; col++) {
string targetVariable = targetVariables[col];
this.chart.Series.Add(targetVariable + " " + TARGETVARIABLE_SERIES_NAME);
this.chart.Series[targetVariable + " " + TARGETVARIABLE_SERIES_NAME].LegendText = targetVariable;
this.chart.Series[targetVariable + " " + TARGETVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
this.chart.Series[targetVariable + " " + TARGETVARIABLE_SERIES_NAME].Points.DataBindY(Content.ProblemData.Dataset.GetVariableValues(targetVariable));
this.chart.Series.Add(targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME);
this.chart.Series[targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME].LegendText = targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME;
this.chart.Series[targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME].ChartType = SeriesChartType.FastLine;
this.chart.Series[targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME].Points.DataBindY(values.Select(x => x.ElementAt(selectedHorizonValue - 1)[col]).ToArray());
this.chart.Series[targetVariable + " " + ESTIMATEDVALUES_SERIES_NAME].Tag = Content;
}
this.UpdateStripLines();
UpdateCursorInterval();
}
}
private void UpdateCursorInterval() {
var allValues = (from series in this.chart.Series
from point in series.Points
select point.YValues[0])
.DefaultIfEmpty(1.0);
double range = allValues.Max() - allValues.Min();
double interestingValuesRange = Math.Min(Math.Max(range, 1.0), Math.Max(range, 1.0));
double digits = (int)Math.Log10(interestingValuesRange) - 3;
double yZoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
}
#region events
protected override void RegisterContentEvents() {
base.RegisterContentEvents();
Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
}
protected override void DeregisterContentEvents() {
base.DeregisterContentEvents();
Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
}
private void Content_ProblemDataChanged(object sender, EventArgs e) {
RedrawChart();
}
protected override void OnContentChanged() {
base.OnContentChanged();
RedrawChart();
}
#endregion
private void UpdateStripLines() {
this.chart.ChartAreas[0].AxisX.StripLines.Clear();
this.CreateAndAddStripLine("Training", Color.FromArgb(20, Color.Green),
Content.ProblemData.TrainingSamplesStart.Value,
Content.ProblemData.TrainingSamplesEnd.Value);
this.CreateAndAddStripLine("Test", Color.FromArgb(20, Color.Red),
Content.ProblemData.TestSamplesStart.Value,
Content.ProblemData.TestSamplesEnd.Value);
}
private void CreateAndAddStripLine(string title, Color c, int start, int end) {
StripLine stripLine = new StripLine();
stripLine.BackColor = c;
stripLine.Text = title;
stripLine.Font = new Font("Times New Roman", 12, FontStyle.Bold);
stripLine.StripWidth = end - start;
stripLine.IntervalOffset = start;
this.chart.ChartAreas[0].AxisX.StripLines.Add(stripLine);
}
private void numericUpDown_ValueChanged(object sender, EventArgs e) {
RedrawChart();
}
}
}