Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorGradientChart.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorGradientChart.Designer.cs (revision 15136)
+++ (revision )
@@ -1,159 +1,0 @@
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- partial class FactorGradientChart {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
- System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
- System.Windows.Forms.DataVisualization.Charting.StripLine stripLine1 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
- System.Windows.Forms.DataVisualization.Charting.StripLine stripLine2 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
- System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
- System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
- System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
- System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
- System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
- System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
- this.calculationPendingLabel = new System.Windows.Forms.Label();
- this.calculationPendingTimer = new System.Windows.Forms.Timer(this.components);
- this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
- this.toolTip = new System.Windows.Forms.ToolTip(this.components);
- ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
- this.SuspendLayout();
- //
- // calculationPendingLabel
- //
- this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
- this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
- this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
- this.calculationPendingLabel.Margin = new System.Windows.Forms.Padding(0);
- this.calculationPendingLabel.Name = "calculationPendingLabel";
- this.calculationPendingLabel.Size = new System.Drawing.Size(17, 17);
- this.calculationPendingLabel.TabIndex = 1;
- this.calculationPendingLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.calculationPendingLabel.Visible = false;
- //
- // calculationPendingTimer
- //
- this.calculationPendingTimer.Tick += new System.EventHandler(this.calculationPendingTimer_Tick);
- //
- // chart
- //
- this.chart.AllowDrop = true;
- verticalLineAnnotation1.AllowMoving = true;
- verticalLineAnnotation1.AxisXName = "ChartArea\\rX";
- verticalLineAnnotation1.ClipToChartArea = "ChartArea";
- verticalLineAnnotation1.IsInfinitive = true;
- verticalLineAnnotation1.LineColor = System.Drawing.Color.Red;
- verticalLineAnnotation1.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
- verticalLineAnnotation1.Name = "VerticalLineAnnotation";
- verticalLineAnnotation1.YAxisName = "ChartArea\\rY";
- this.chart.Annotations.Add(verticalLineAnnotation1);
- chartArea1.AxisX.IsMarginVisible = false;
- stripLine1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
- stripLine2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
- chartArea1.AxisX.StripLines.Add(stripLine1);
- chartArea1.AxisX.StripLines.Add(stripLine2);
- chartArea1.Name = "ChartArea";
- chartArea1.Position.Auto = false;
- chartArea1.Position.Height = 90F;
- chartArea1.Position.Width = 100F;
- chartArea1.Position.Y = 10F;
- this.chart.ChartAreas.Add(chartArea1);
- this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
- legend1.Alignment = System.Drawing.StringAlignment.Center;
- legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
- legend1.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.ReversedSeriesOrder;
- legend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
- legend1.Name = "Default";
- this.chart.Legends.Add(legend1);
- this.chart.Location = new System.Drawing.Point(0, 0);
- this.chart.Name = "chart";
- series1.BorderColor = System.Drawing.Color.Red;
- series1.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
- series1.ChartArea = "ChartArea";
- series1.IsVisibleInLegend = false;
- series1.Legend = "Default";
- series1.Name = "Series1";
- series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
- series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
- series2.ChartArea = "ChartArea";
- series2.IsVisibleInLegend = false;
- series2.Legend = "Default";
- series2.Name = "Series2";
- series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
- series3.ChartArea = "ChartArea";
- series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.BoxPlot;
- series3.Color = System.Drawing.Color.Black;
- series3.Legend = "Default";
- series3.Name = "Series3";
- series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
- series3.YValuesPerPoint = 6;
- series4.ChartArea = "ChartArea";
- series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.BoxPlot;
- series4.Legend = "Default";
- series4.Name = "Series4";
- series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
- series4.YValuesPerPoint = 6;
- this.chart.Series.Add(series1);
- this.chart.Series.Add(series2);
- this.chart.Series.Add(series3);
- this.chart.Series.Add(series4);
- this.chart.Size = new System.Drawing.Size(453, 308);
- this.chart.TabIndex = 0;
- title1.Alignment = System.Drawing.ContentAlignment.TopCenter;
- title1.DockedToChartArea = "ChartArea";
- title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- title1.IsDockedInsideChartArea = false;
- title1.Name = "Title";
- title1.Text = "[Title]";
- this.chart.Titles.Add(title1);
- this.chart.SelectionRangeChanged += new System.EventHandler(this.chart_SelectionRangeChanged);
- this.chart.PostPaint += new System.EventHandler(this.chart_PostPaint);
- this.chart.DragDrop += new System.Windows.Forms.DragEventHandler(this.chart_DragDrop);
- this.chart.DragEnter += new System.Windows.Forms.DragEventHandler(this.chart_DragEnter);
- this.chart.MouseClick += new System.Windows.Forms.MouseEventHandler(this.chart_MouseClick);
- this.chart.Resize += new System.EventHandler(this.chart_Resize);
- //
- // FactorGradientChart
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.calculationPendingLabel);
- this.Controls.Add(this.chart);
- this.Name = "FactorGradientChart";
- this.Size = new System.Drawing.Size(453, 308);
- ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
- private System.Windows.Forms.Label calculationPendingLabel;
- private System.Windows.Forms.Timer calculationPendingTimer;
- private System.Windows.Forms.ToolTip toolTip;
- }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorGradientChart.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorGradientChart.cs (revision 15136)
+++ (revision )
@@ -1,565 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Collections;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Forms.DataVisualization.Charting;
-using HeuristicLab.Common;
-using HeuristicLab.MainForm.WindowsForms;
-using HeuristicLab.Visualization.ChartControlsExtensions;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- public partial class FactorGradientChart : UserControl, IGradientChart {
- private ModifiableDataset sharedFixedVariables; // used for syncronising variable values between charts
- private ModifiableDataset internalDataset; // holds the x values for each point drawn
-
- private CancellationTokenSource cancelCurrentRecalculateSource;
-
- private readonly List solutions;
- private readonly Dictionary seriesCache;
- private readonly Dictionary ciSeriesCache;
-
- #region Properties
- public string XAxisTitle {
- get { return chart.ChartAreas[0].AxisX.Title; }
- set { chart.ChartAreas[0].AxisX.Title = value; }
- }
-
- public string YAxisTitle {
- get { return chart.ChartAreas[0].AxisY.Title; }
- set { chart.ChartAreas[0].AxisY.Title = value; }
- }
-
- public bool ShowLegend {
- get { return chart.Legends[0].Enabled; }
- set { chart.Legends[0].Enabled = value; }
- }
- public bool ShowCursor {
- get { return chart.Annotations[0].Visible; }
- set {
- chart.Annotations[0].Visible = value;
- if (!value) chart.Titles[0].Text = string.Empty;
- }
- }
-
- private int yAxisTicks = 5;
- public int YAxisTicks {
- get { return yAxisTicks; }
- set {
- if (value != yAxisTicks) {
- yAxisTicks = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- RecalculateInternalDataset();
- }
- }
- }
- private double? fixedYAxisMin;
- public double? FixedYAxisMin {
- get { return fixedYAxisMin; }
- set {
- if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
- fixedYAxisMin = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- }
- }
- }
- private double? fixedYAxisMax;
- public double? FixedYAxisMax {
- get { return fixedYAxisMax; }
- set {
- if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
- fixedYAxisMax = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- }
- }
- }
-
- private string freeVariable;
- public string FreeVariable {
- get { return freeVariable; }
- set {
- if (value == freeVariable) return;
- if (solutions.Any(s => !s.ProblemData.Dataset.StringVariables.Contains(value))) {
- throw new ArgumentException("Variable does not exist in the ProblemData of the Solutions.");
- }
- freeVariable = value;
- RecalculateInternalDataset();
- }
- }
-
- private double yMin;
- public double YMin {
- get { return yMin; }
- }
- private double yMax;
- public double YMax {
- get { return yMax; }
- }
-
- public bool IsZoomed {
- get { return chart.ChartAreas[0].AxisX.ScaleView.IsZoomed; }
- }
-
- internal ElementPosition InnerPlotPosition {
- get { return chart.ChartAreas[0].InnerPlotPosition; }
- }
- #endregion
-
- private List variableValues;
-
- public event EventHandler ChartPostPaint;
-
- public FactorGradientChart() {
- InitializeComponent();
-
- solutions = new List();
- seriesCache = new Dictionary();
- ciSeriesCache = new Dictionary();
-
- // Configure axis
- chart.CustomizeAllChartAreas();
- chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
- chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
- chart.ChartAreas[0].CursorX.Interval = 0;
-
- chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
- chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
- chart.ChartAreas[0].CursorY.Interval = 0;
-
- Disposed += GradientChart_Disposed;
- }
-
- private void GradientChart_Disposed(object sender, EventArgs e) {
- if (cancelCurrentRecalculateSource != null)
- cancelCurrentRecalculateSource.Cancel();
- }
-
- public void Configure(IEnumerable solutions, ModifiableDataset sharedFixedVariables, string freeVariable, IList variableValues, bool initializeAxisRanges = true) {
- if (!SolutionsCompatible(solutions))
- throw new ArgumentException("Solutions are not compatible with the problem data.");
- this.freeVariable = freeVariable;
- this.variableValues = new List(variableValues);
-
- this.solutions.Clear();
- this.solutions.AddRange(solutions);
-
- // add an event such that whenever a value is changed in the shared dataset,
- // this change is reflected in the internal dataset (where the value becomes a whole column)
- if (this.sharedFixedVariables != null)
- this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged;
- this.sharedFixedVariables = sharedFixedVariables;
- this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged;
-
- RecalculateInternalDataset();
-
- chart.Series.Clear();
- seriesCache.Clear();
- ciSeriesCache.Clear();
- foreach (var solution in this.solutions) {
- var series = CreateSeries(solution);
- seriesCache.Add(solution, series.Item1);
- if (series.Item2 != null)
- ciSeriesCache.Add(solution, series.Item2);
- }
-
- InitSeriesData();
- OrderAndColorSeries();
-
- }
-
- public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) {
- if (IsDisposed
- || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable)
- || !variableValues.Any())
- return;
-
- calculationPendingTimer.Start();
-
- // cancel previous recalculate call
- if (cancelCurrentRecalculateSource != null)
- cancelCurrentRecalculateSource.Cancel();
- cancelCurrentRecalculateSource = new CancellationTokenSource();
- var cancellationToken = cancelCurrentRecalculateSource.Token;
-
- // Update series
- try {
- var limits = await UpdateAllSeriesDataAsync(cancellationToken);
-
- yMin = limits.Lower;
- yMax = limits.Upper;
- // Set y-axis
- if (resetYAxis)
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
-
- calculationPendingTimer.Stop();
- calculationPendingLabel.Visible = false;
- if (updateOnFinish)
- Update();
- } catch (OperationCanceledException) { } catch (AggregateException ae) {
- if (!ae.InnerExceptions.Any(e => e is OperationCanceledException))
- throw;
- }
- }
-
- public void UpdateTitlePosition() {
- var title = chart.Titles[0];
- var plotArea = InnerPlotPosition;
-
- title.Visible = plotArea.Width != 0;
-
- title.Position.X = plotArea.X + (plotArea.Width / 2);
- }
-
- private void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
- if (minValue < maxValue) {
- double axisMin, axisMax, axisInterval;
- ChartUtil.CalculateAxisInterval(minValue, maxValue, ticks, out axisMin, out axisMax, out axisInterval);
- axis.Minimum = fixedAxisMin ?? axisMin;
- axis.Maximum = fixedAxisMax ?? axisMax;
- axis.Interval = (axis.Maximum - axis.Minimum) / ticks;
- }
-
- try {
- chart.ChartAreas[0].RecalculateAxesScale();
- } catch (InvalidOperationException) {
- // Can occur if eg. axis min == axis max
- }
- }
-
-
- private void RecalculateInternalDataset() {
- if (sharedFixedVariables == null)
- return;
-
- var factorValues = new List(variableValues);
-
- var variables = sharedFixedVariables.VariableNames.ToList();
- var values = new List();
- foreach (var varName in variables) {
- if (varName == FreeVariable) {
- values.Add(factorValues);
- } else if (sharedFixedVariables.VariableHasType(varName)) {
- values.Add(Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(varName, 0), factorValues.Count).ToList());
- } else if (sharedFixedVariables.VariableHasType(varName)) {
- values.Add(Enumerable.Repeat(sharedFixedVariables.GetStringValue(varName, 0), factorValues.Count).ToList());
- }
- }
-
- internalDataset = new ModifiableDataset(variables, values);
- }
-
- private Tuple CreateSeries(IRegressionSolution solution) {
- var series = new Series {
- ChartType = SeriesChartType.Column,
- Name = solution.ProblemData.TargetVariable + " " + solutions.IndexOf(solution),
- XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String
- };
- series.LegendText = series.Name;
-
- Series confidenceIntervalSeries = null;
- confidenceIntervalSeries = new Series {
- ChartType = SeriesChartType.BoxPlot,
- XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String,
- Color = Color.Black,
- YValuesPerPoint = 5,
- Name = "95% Conf. Interval " + series.Name,
- IsVisibleInLegend = false
- };
- return Tuple.Create(series, confidenceIntervalSeries);
- }
-
- private void OrderAndColorSeries() {
- chart.SuspendRepaint();
-
- chart.Series.Clear();
- // Add mean series for applying palette colors
- foreach (var solution in solutions) {
- chart.Series.Add(seriesCache[solution]);
- }
-
- chart.Palette = ChartColorPalette.BrightPastel;
- chart.ApplyPaletteColors();
- chart.Palette = ChartColorPalette.None;
-
- // Add confidence interval series after its coresponding series for correct z index
- foreach (var solution in solutions) {
- Series ciSeries;
- if (ciSeriesCache.TryGetValue(solution, out ciSeries)) {
- int idx = chart.Series.IndexOf(seriesCache[solution]);
- chart.Series.Insert(idx + 1, ciSeries);
- }
- }
-
- chart.ResumeRepaint(true);
- }
-
- private async Task UpdateAllSeriesDataAsync(CancellationToken cancellationToken) {
- var updateTasks = solutions.Select(solution => UpdateSeriesDataAsync(solution, cancellationToken));
-
- double min = double.MaxValue, max = double.MinValue;
- foreach (var update in updateTasks) {
- var limit = await update;
- if (limit.Lower < min) min = limit.Lower;
- if (limit.Upper > max) max = limit.Upper;
- }
-
- return new DoubleLimit(min, max);
- }
-
- private Task UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) {
- return Task.Run(() => {
- var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
-
- double min = double.MaxValue, max = double.MinValue;
-
- var series = seriesCache[solution];
- for (int i = 0; i < variableValues.Count; i++) {
- series.Points[i].SetValueXY(variableValues[i], yvalues[i]);
- if (yvalues[i] < min) min = yvalues[i];
- if (yvalues[i] > max) max = yvalues[i];
- }
- chart.Invalidate();
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
- if (confidenceBoundSolution != null) {
- var confidenceIntervalSeries = ciSeriesCache[solution];
- var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
- for (int i = 0; i < variableValues.Count; i++) {
- var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
- var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
- confidenceIntervalSeries.Points[i].SetValueXY(variableValues[i], lower, upper, yvalues[i], yvalues[i], yvalues[i]);
- if (lower < min) min = lower;
- if (upper > max) max = upper;
- }
- chart.Invalidate();
- }
-
- cancellationToken.ThrowIfCancellationRequested();
- return new DoubleLimit(min, max);
- }, cancellationToken);
- }
-
- private void InitSeriesData() {
- if (internalDataset == null)
- return;
-
- foreach (var solution in solutions)
- InitSeriesData(solution, variableValues);
- }
-
- private void InitSeriesData(IRegressionSolution solution, IList values) {
-
- var series = seriesCache[solution];
- series.Points.SuspendUpdates();
- series.Points.Clear();
- for (int i = 0; i < values.Count; i++) {
- series.Points.AddXY(values[i], 0.0);
- series.Points.Last().ToolTip = values[i];
- }
-
- UpdateAllSeriesStyles(variableValues.IndexOf(sharedFixedVariables.GetStringValue(FreeVariable, 0)));
- series.Points.ResumeUpdates();
-
- Series confidenceIntervalSeries;
- if (ciSeriesCache.TryGetValue(solution, out confidenceIntervalSeries)) {
- confidenceIntervalSeries.Points.SuspendUpdates();
- confidenceIntervalSeries.Points.Clear();
- for (int i = 0; i < values.Count; i++)
- confidenceIntervalSeries.Points.AddXY(values[i], 0.0, 0.0, 0.0, 0.0, 0.0);
- confidenceIntervalSeries.Points.ResumeUpdates();
- }
- }
-
- public async Task AddSolutionAsync(IRegressionSolution solution) {
- if (!SolutionsCompatible(solutions.Concat(new[] { solution })))
- throw new ArgumentException("The solution is not compatible with the problem data.");
- if (solutions.Contains(solution))
- return;
-
- solutions.Add(solution);
-
- var series = CreateSeries(solution);
- seriesCache.Add(solution, series.Item1);
- if (series.Item2 != null)
- ciSeriesCache.Add(solution, series.Item2);
-
- InitSeriesData(solution, variableValues);
- OrderAndColorSeries();
-
- await RecalculateAsync();
- var args = new EventArgs(solution);
- OnSolutionAdded(this, args);
- }
-
- public async Task RemoveSolutionAsync(IRegressionSolution solution) {
- throw new NotSupportedException();
- }
-
- private static bool SolutionsCompatible(IEnumerable solutions) {
- var refSolution = solutions.First();
- var refSolVars = refSolution.ProblemData.Dataset.VariableNames;
- foreach (var solution in solutions.Skip(1)) {
- var variables1 = solution.ProblemData.Dataset.VariableNames;
- if (!variables1.All(refSolVars.Contains))
- return false;
-
- foreach (var factorVar in variables1.Where(solution.ProblemData.Dataset.VariableHasType)) {
- var distinctVals = refSolution.ProblemData.Dataset.GetStringValues(factorVar).Distinct();
- if (solution.ProblemData.Dataset.GetStringValues(factorVar).Any(val => !distinctVals.Contains(val))) return false;
- }
- }
- return true;
- }
-
- #region Events
- public event EventHandler> SolutionAdded;
- public void OnSolutionAdded(object sender, EventArgs args) {
- var added = SolutionAdded;
- if (added == null) return;
- added(sender, args);
- }
-
- public event EventHandler> SolutionRemoved;
- public void OnSolutionRemoved(object sender, EventArgs args) {
- var removed = SolutionRemoved;
- if (removed == null) return;
- removed(sender, args);
- }
-
- public event EventHandler VariableValueChanged;
- public void OnVariableValueChanged(object sender, EventArgs args) {
- var changed = VariableValueChanged;
- if (changed == null) return;
- changed(sender, args);
- }
-
- public event EventHandler ZoomChanged;
- public void OnZoomChanged(object sender, EventArgs args) {
- var changed = ZoomChanged;
- if (changed == null) return;
- changed(sender, args);
- }
-
- private void sharedFixedVariables_ItemChanged(object o, EventArgs e) {
- if (o != sharedFixedVariables) return;
- var variables = sharedFixedVariables.VariableNames.ToList();
- var rowIndex = e.Value;
- var columnIndex = e.Value2;
-
- var variableName = variables[columnIndex];
- if (variableName == FreeVariable) return;
- if (internalDataset.VariableHasType(variableName)) {
- var v = sharedFixedVariables.GetDoubleValue(variableName, rowIndex);
- var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
- internalDataset.ReplaceVariable(variableName, values);
- } else if (internalDataset.VariableHasType(variableName)) {
- var v = sharedFixedVariables.GetStringValue(variableName, rowIndex);
- var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
- internalDataset.ReplaceVariable(variableName, values);
- } else {
- // unsupported type
- throw new NotSupportedException();
- }
- }
-
- private async void chart_DragDrop(object sender, DragEventArgs e) {
- var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
- if (data != null) {
- var solution = data as IRegressionSolution;
- if (!solutions.Contains(solution))
- await AddSolutionAsync(solution);
- }
- }
- private void chart_DragEnter(object sender, DragEventArgs e) {
- if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) return;
- e.Effect = DragDropEffects.None;
-
- var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
- var regressionSolution = data as IRegressionSolution;
- if (regressionSolution != null) {
- e.Effect = DragDropEffects.Copy;
- }
- }
-
- private void calculationPendingTimer_Tick(object sender, EventArgs e) {
- calculationPendingLabel.Visible = true;
- Update();
- }
-
- private void chart_SelectionRangeChanged(object sender, CursorEventArgs e) {
- OnZoomChanged(this, EventArgs.Empty);
- }
-
- private void chart_Resize(object sender, EventArgs e) {
- UpdateTitlePosition();
- }
-
- private void chart_PostPaint(object sender, ChartPaintEventArgs e) {
- if (ChartPostPaint != null)
- ChartPostPaint(this, EventArgs.Empty);
- }
- #endregion
-
- private void chart_MouseClick(object sender, MouseEventArgs e) {
- var hitTestResult = chart.HitTest(e.X, e.Y, ChartElementType.DataPoint);
- if (hitTestResult != null && hitTestResult.ChartElementType == ChartElementType.DataPoint) {
- var series = hitTestResult.Series;
- var dataPoint = (DataPoint)hitTestResult.Object;
- var idx = series.Points.IndexOf(dataPoint);
- UpdateSelectedValue(variableValues[idx]);
-
- UpdateAllSeriesStyles(idx);
- }
- }
-
- private void UpdateAllSeriesStyles(int selectedValueIndex) {
- if (ShowCursor) {
- chart.Titles[0].Text = FreeVariable + " : " + variableValues[selectedValueIndex];
- chart.Update();
- }
- foreach (var s in seriesCache.Values) {
- if (s.ChartType == SeriesChartType.Column)
- for (int i = 0; i < s.Points.Count; i++) {
- if (i != selectedValueIndex) {
- s.Points[i].BorderDashStyle = ChartDashStyle.NotSet;
- } else {
- s.Points[i].BorderDashStyle = ChartDashStyle.Dash;
- s.Points[i].BorderColor = Color.Red;
- }
- }
- }
- }
-
- private void UpdateSelectedValue(string variableValue) {
- sharedFixedVariables.SetVariableValue(variableValue, FreeVariable, 0);
- OnVariableValueChanged(this, EventArgs.Empty);
- }
- }
-}
-
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.Designer.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.Designer.cs (revision 15137)
@@ -0,0 +1,159 @@
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ partial class FactorPartialDependencePlot {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
+ System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+ System.Windows.Forms.DataVisualization.Charting.StripLine stripLine1 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
+ System.Windows.Forms.DataVisualization.Charting.StripLine stripLine2 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
+ System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+ System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+ System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+ System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
+ System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
+ System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+ this.calculationPendingLabel = new System.Windows.Forms.Label();
+ this.calculationPendingTimer = new System.Windows.Forms.Timer(this.components);
+ this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+ this.SuspendLayout();
+ //
+ // calculationPendingLabel
+ //
+ this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
+ this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
+ this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
+ this.calculationPendingLabel.Margin = new System.Windows.Forms.Padding(0);
+ this.calculationPendingLabel.Name = "calculationPendingLabel";
+ this.calculationPendingLabel.Size = new System.Drawing.Size(17, 17);
+ this.calculationPendingLabel.TabIndex = 1;
+ this.calculationPendingLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.calculationPendingLabel.Visible = false;
+ //
+ // calculationPendingTimer
+ //
+ this.calculationPendingTimer.Tick += new System.EventHandler(this.calculationPendingTimer_Tick);
+ //
+ // chart
+ //
+ this.chart.AllowDrop = true;
+ verticalLineAnnotation1.AllowMoving = true;
+ verticalLineAnnotation1.AxisXName = "ChartArea\\rX";
+ verticalLineAnnotation1.ClipToChartArea = "ChartArea";
+ verticalLineAnnotation1.IsInfinitive = true;
+ verticalLineAnnotation1.LineColor = System.Drawing.Color.Red;
+ verticalLineAnnotation1.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
+ verticalLineAnnotation1.Name = "VerticalLineAnnotation";
+ verticalLineAnnotation1.YAxisName = "ChartArea\\rY";
+ this.chart.Annotations.Add(verticalLineAnnotation1);
+ chartArea1.AxisX.IsMarginVisible = false;
+ stripLine1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
+ stripLine2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
+ chartArea1.AxisX.StripLines.Add(stripLine1);
+ chartArea1.AxisX.StripLines.Add(stripLine2);
+ chartArea1.Name = "ChartArea";
+ chartArea1.Position.Auto = false;
+ chartArea1.Position.Height = 90F;
+ chartArea1.Position.Width = 100F;
+ chartArea1.Position.Y = 10F;
+ this.chart.ChartAreas.Add(chartArea1);
+ this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
+ legend1.Alignment = System.Drawing.StringAlignment.Center;
+ legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+ legend1.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.ReversedSeriesOrder;
+ legend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
+ legend1.Name = "Default";
+ this.chart.Legends.Add(legend1);
+ this.chart.Location = new System.Drawing.Point(0, 0);
+ this.chart.Name = "chart";
+ series1.BorderColor = System.Drawing.Color.Red;
+ series1.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
+ series1.ChartArea = "ChartArea";
+ series1.IsVisibleInLegend = false;
+ series1.Legend = "Default";
+ series1.Name = "Series1";
+ series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
+ series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
+ series2.ChartArea = "ChartArea";
+ series2.IsVisibleInLegend = false;
+ series2.Legend = "Default";
+ series2.Name = "Series2";
+ series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
+ series3.ChartArea = "ChartArea";
+ series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.BoxPlot;
+ series3.Color = System.Drawing.Color.Black;
+ series3.Legend = "Default";
+ series3.Name = "Series3";
+ series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
+ series3.YValuesPerPoint = 6;
+ series4.ChartArea = "ChartArea";
+ series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.BoxPlot;
+ series4.Legend = "Default";
+ series4.Name = "Series4";
+ series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String;
+ series4.YValuesPerPoint = 6;
+ this.chart.Series.Add(series1);
+ this.chart.Series.Add(series2);
+ this.chart.Series.Add(series3);
+ this.chart.Series.Add(series4);
+ this.chart.Size = new System.Drawing.Size(453, 308);
+ this.chart.TabIndex = 0;
+ title1.Alignment = System.Drawing.ContentAlignment.TopCenter;
+ title1.DockedToChartArea = "ChartArea";
+ title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ title1.IsDockedInsideChartArea = false;
+ title1.Name = "Title";
+ title1.Text = "[Title]";
+ this.chart.Titles.Add(title1);
+ this.chart.SelectionRangeChanged += new System.EventHandler(this.chart_SelectionRangeChanged);
+ this.chart.PostPaint += new System.EventHandler(this.chart_PostPaint);
+ this.chart.DragDrop += new System.Windows.Forms.DragEventHandler(this.chart_DragDrop);
+ this.chart.DragEnter += new System.Windows.Forms.DragEventHandler(this.chart_DragEnter);
+ this.chart.MouseClick += new System.Windows.Forms.MouseEventHandler(this.chart_MouseClick);
+ this.chart.Resize += new System.EventHandler(this.chart_Resize);
+ //
+ // FactorPartialDependencePlot
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.calculationPendingLabel);
+ this.Controls.Add(this.chart);
+ this.Name = "FactorPartialDependencePlot";
+ this.Size = new System.Drawing.Size(453, 308);
+ ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+ private System.Windows.Forms.Label calculationPendingLabel;
+ private System.Windows.Forms.Timer calculationPendingTimer;
+ private System.Windows.Forms.ToolTip toolTip;
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorPartialDependencePlot.cs (revision 15137)
@@ -0,0 +1,565 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm.WindowsForms;
+using HeuristicLab.Visualization.ChartControlsExtensions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ public partial class FactorPartialDependencePlot : UserControl, IPartialDependencePlot {
+ private ModifiableDataset sharedFixedVariables; // used for synchronising variable values between charts
+ private ModifiableDataset internalDataset; // holds the x values for each point drawn
+
+ private CancellationTokenSource cancelCurrentRecalculateSource;
+
+ private readonly List solutions;
+ private readonly Dictionary seriesCache;
+ private readonly Dictionary ciSeriesCache;
+
+ #region Properties
+ public string XAxisTitle {
+ get { return chart.ChartAreas[0].AxisX.Title; }
+ set { chart.ChartAreas[0].AxisX.Title = value; }
+ }
+
+ public string YAxisTitle {
+ get { return chart.ChartAreas[0].AxisY.Title; }
+ set { chart.ChartAreas[0].AxisY.Title = value; }
+ }
+
+ public bool ShowLegend {
+ get { return chart.Legends[0].Enabled; }
+ set { chart.Legends[0].Enabled = value; }
+ }
+ public bool ShowCursor {
+ get { return chart.Annotations[0].Visible; }
+ set {
+ chart.Annotations[0].Visible = value;
+ if (!value) chart.Titles[0].Text = string.Empty;
+ }
+ }
+
+ private int yAxisTicks = 5;
+ public int YAxisTicks {
+ get { return yAxisTicks; }
+ set {
+ if (value != yAxisTicks) {
+ yAxisTicks = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ RecalculateInternalDataset();
+ }
+ }
+ }
+ private double? fixedYAxisMin;
+ public double? FixedYAxisMin {
+ get { return fixedYAxisMin; }
+ set {
+ if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
+ fixedYAxisMin = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ }
+ }
+ }
+ private double? fixedYAxisMax;
+ public double? FixedYAxisMax {
+ get { return fixedYAxisMax; }
+ set {
+ if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
+ fixedYAxisMax = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ }
+ }
+ }
+
+ private string freeVariable;
+ public string FreeVariable {
+ get { return freeVariable; }
+ set {
+ if (value == freeVariable) return;
+ if (solutions.Any(s => !s.ProblemData.Dataset.StringVariables.Contains(value))) {
+ throw new ArgumentException("Variable does not exist in the ProblemData of the Solutions.");
+ }
+ freeVariable = value;
+ RecalculateInternalDataset();
+ }
+ }
+
+ private double yMin;
+ public double YMin {
+ get { return yMin; }
+ }
+ private double yMax;
+ public double YMax {
+ get { return yMax; }
+ }
+
+ public bool IsZoomed {
+ get { return chart.ChartAreas[0].AxisX.ScaleView.IsZoomed; }
+ }
+
+ internal ElementPosition InnerPlotPosition {
+ get { return chart.ChartAreas[0].InnerPlotPosition; }
+ }
+ #endregion
+
+ private List variableValues;
+
+ public event EventHandler ChartPostPaint;
+
+ public FactorPartialDependencePlot() {
+ InitializeComponent();
+
+ solutions = new List();
+ seriesCache = new Dictionary();
+ ciSeriesCache = new Dictionary();
+
+ // Configure axis
+ chart.CustomizeAllChartAreas();
+ chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
+ chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
+ chart.ChartAreas[0].CursorX.Interval = 0;
+
+ chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
+ chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
+ chart.ChartAreas[0].CursorY.Interval = 0;
+
+ Disposed += Control_Disposed;
+ }
+
+ private void Control_Disposed(object sender, EventArgs e) {
+ if (cancelCurrentRecalculateSource != null)
+ cancelCurrentRecalculateSource.Cancel();
+ }
+
+ public void Configure(IEnumerable solutions, ModifiableDataset sharedFixedVariables, string freeVariable, IList variableValues, bool initializeAxisRanges = true) {
+ if (!SolutionsCompatible(solutions))
+ throw new ArgumentException("Solutions are not compatible with the problem data.");
+ this.freeVariable = freeVariable;
+ this.variableValues = new List(variableValues);
+
+ this.solutions.Clear();
+ this.solutions.AddRange(solutions);
+
+ // add an event such that whenever a value is changed in the shared dataset,
+ // this change is reflected in the internal dataset (where the value becomes a whole column)
+ if (this.sharedFixedVariables != null)
+ this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged;
+ this.sharedFixedVariables = sharedFixedVariables;
+ this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged;
+
+ RecalculateInternalDataset();
+
+ chart.Series.Clear();
+ seriesCache.Clear();
+ ciSeriesCache.Clear();
+ foreach (var solution in this.solutions) {
+ var series = CreateSeries(solution);
+ seriesCache.Add(solution, series.Item1);
+ if (series.Item2 != null)
+ ciSeriesCache.Add(solution, series.Item2);
+ }
+
+ InitSeriesData();
+ OrderAndColorSeries();
+
+ }
+
+ public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) {
+ if (IsDisposed
+ || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable)
+ || !variableValues.Any())
+ return;
+
+ calculationPendingTimer.Start();
+
+ // cancel previous recalculate call
+ if (cancelCurrentRecalculateSource != null)
+ cancelCurrentRecalculateSource.Cancel();
+ cancelCurrentRecalculateSource = new CancellationTokenSource();
+ var cancellationToken = cancelCurrentRecalculateSource.Token;
+
+ // Update series
+ try {
+ var limits = await UpdateAllSeriesDataAsync(cancellationToken);
+
+ yMin = limits.Lower;
+ yMax = limits.Upper;
+ // Set y-axis
+ if (resetYAxis)
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+
+ calculationPendingTimer.Stop();
+ calculationPendingLabel.Visible = false;
+ if (updateOnFinish)
+ Update();
+ } catch (OperationCanceledException) { } catch (AggregateException ae) {
+ if (!ae.InnerExceptions.Any(e => e is OperationCanceledException))
+ throw;
+ }
+ }
+
+ public void UpdateTitlePosition() {
+ var title = chart.Titles[0];
+ var plotArea = InnerPlotPosition;
+
+ title.Visible = plotArea.Width != 0;
+
+ title.Position.X = plotArea.X + (plotArea.Width / 2);
+ }
+
+ private void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
+ if (minValue < maxValue) {
+ double axisMin, axisMax, axisInterval;
+ ChartUtil.CalculateAxisInterval(minValue, maxValue, ticks, out axisMin, out axisMax, out axisInterval);
+ axis.Minimum = fixedAxisMin ?? axisMin;
+ axis.Maximum = fixedAxisMax ?? axisMax;
+ axis.Interval = (axis.Maximum - axis.Minimum) / ticks;
+ }
+
+ try {
+ chart.ChartAreas[0].RecalculateAxesScale();
+ } catch (InvalidOperationException) {
+ // Can occur if eg. axis min == axis max
+ }
+ }
+
+
+ private void RecalculateInternalDataset() {
+ if (sharedFixedVariables == null)
+ return;
+
+ var factorValues = new List(variableValues);
+
+ var variables = sharedFixedVariables.VariableNames.ToList();
+ var values = new List();
+ foreach (var varName in variables) {
+ if (varName == FreeVariable) {
+ values.Add(factorValues);
+ } else if (sharedFixedVariables.VariableHasType(varName)) {
+ values.Add(Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(varName, 0), factorValues.Count).ToList());
+ } else if (sharedFixedVariables.VariableHasType(varName)) {
+ values.Add(Enumerable.Repeat(sharedFixedVariables.GetStringValue(varName, 0), factorValues.Count).ToList());
+ }
+ }
+
+ internalDataset = new ModifiableDataset(variables, values);
+ }
+
+ private Tuple CreateSeries(IRegressionSolution solution) {
+ var series = new Series {
+ ChartType = SeriesChartType.Column,
+ Name = solution.ProblemData.TargetVariable + " " + solutions.IndexOf(solution),
+ XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String
+ };
+ series.LegendText = series.Name;
+
+ Series confidenceIntervalSeries = null;
+ confidenceIntervalSeries = new Series {
+ ChartType = SeriesChartType.BoxPlot,
+ XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.String,
+ Color = Color.Black,
+ YValuesPerPoint = 5,
+ Name = "95% Conf. Interval " + series.Name,
+ IsVisibleInLegend = false
+ };
+ return Tuple.Create(series, confidenceIntervalSeries);
+ }
+
+ private void OrderAndColorSeries() {
+ chart.SuspendRepaint();
+
+ chart.Series.Clear();
+ // Add mean series for applying palette colors
+ foreach (var solution in solutions) {
+ chart.Series.Add(seriesCache[solution]);
+ }
+
+ chart.Palette = ChartColorPalette.BrightPastel;
+ chart.ApplyPaletteColors();
+ chart.Palette = ChartColorPalette.None;
+
+ // Add confidence interval series after its coresponding series for correct z index
+ foreach (var solution in solutions) {
+ Series ciSeries;
+ if (ciSeriesCache.TryGetValue(solution, out ciSeries)) {
+ int idx = chart.Series.IndexOf(seriesCache[solution]);
+ chart.Series.Insert(idx + 1, ciSeries);
+ }
+ }
+
+ chart.ResumeRepaint(true);
+ }
+
+ private async Task UpdateAllSeriesDataAsync(CancellationToken cancellationToken) {
+ var updateTasks = solutions.Select(solution => UpdateSeriesDataAsync(solution, cancellationToken));
+
+ double min = double.MaxValue, max = double.MinValue;
+ foreach (var update in updateTasks) {
+ var limit = await update;
+ if (limit.Lower < min) min = limit.Lower;
+ if (limit.Upper > max) max = limit.Upper;
+ }
+
+ return new DoubleLimit(min, max);
+ }
+
+ private Task UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) {
+ return Task.Run(() => {
+ var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
+
+ double min = double.MaxValue, max = double.MinValue;
+
+ var series = seriesCache[solution];
+ for (int i = 0; i < variableValues.Count; i++) {
+ series.Points[i].SetValueXY(variableValues[i], yvalues[i]);
+ if (yvalues[i] < min) min = yvalues[i];
+ if (yvalues[i] > max) max = yvalues[i];
+ }
+ chart.Invalidate();
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
+ if (confidenceBoundSolution != null) {
+ var confidenceIntervalSeries = ciSeriesCache[solution];
+ var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
+ for (int i = 0; i < variableValues.Count; i++) {
+ var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
+ var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
+ confidenceIntervalSeries.Points[i].SetValueXY(variableValues[i], lower, upper, yvalues[i], yvalues[i], yvalues[i]);
+ if (lower < min) min = lower;
+ if (upper > max) max = upper;
+ }
+ chart.Invalidate();
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+ return new DoubleLimit(min, max);
+ }, cancellationToken);
+ }
+
+ private void InitSeriesData() {
+ if (internalDataset == null)
+ return;
+
+ foreach (var solution in solutions)
+ InitSeriesData(solution, variableValues);
+ }
+
+ private void InitSeriesData(IRegressionSolution solution, IList values) {
+
+ var series = seriesCache[solution];
+ series.Points.SuspendUpdates();
+ series.Points.Clear();
+ for (int i = 0; i < values.Count; i++) {
+ series.Points.AddXY(values[i], 0.0);
+ series.Points.Last().ToolTip = values[i];
+ }
+
+ UpdateAllSeriesStyles(variableValues.IndexOf(sharedFixedVariables.GetStringValue(FreeVariable, 0)));
+ series.Points.ResumeUpdates();
+
+ Series confidenceIntervalSeries;
+ if (ciSeriesCache.TryGetValue(solution, out confidenceIntervalSeries)) {
+ confidenceIntervalSeries.Points.SuspendUpdates();
+ confidenceIntervalSeries.Points.Clear();
+ for (int i = 0; i < values.Count; i++)
+ confidenceIntervalSeries.Points.AddXY(values[i], 0.0, 0.0, 0.0, 0.0, 0.0);
+ confidenceIntervalSeries.Points.ResumeUpdates();
+ }
+ }
+
+ public async Task AddSolutionAsync(IRegressionSolution solution) {
+ if (!SolutionsCompatible(solutions.Concat(new[] { solution })))
+ throw new ArgumentException("The solution is not compatible with the problem data.");
+ if (solutions.Contains(solution))
+ return;
+
+ solutions.Add(solution);
+
+ var series = CreateSeries(solution);
+ seriesCache.Add(solution, series.Item1);
+ if (series.Item2 != null)
+ ciSeriesCache.Add(solution, series.Item2);
+
+ InitSeriesData(solution, variableValues);
+ OrderAndColorSeries();
+
+ await RecalculateAsync();
+ var args = new EventArgs(solution);
+ OnSolutionAdded(this, args);
+ }
+
+ public async Task RemoveSolutionAsync(IRegressionSolution solution) {
+ throw new NotSupportedException();
+ }
+
+ private static bool SolutionsCompatible(IEnumerable solutions) {
+ var refSolution = solutions.First();
+ var refSolVars = refSolution.ProblemData.Dataset.VariableNames;
+ foreach (var solution in solutions.Skip(1)) {
+ var variables1 = solution.ProblemData.Dataset.VariableNames;
+ if (!variables1.All(refSolVars.Contains))
+ return false;
+
+ foreach (var factorVar in variables1.Where(solution.ProblemData.Dataset.VariableHasType)) {
+ var distinctVals = refSolution.ProblemData.Dataset.GetStringValues(factorVar).Distinct();
+ if (solution.ProblemData.Dataset.GetStringValues(factorVar).Any(val => !distinctVals.Contains(val))) return false;
+ }
+ }
+ return true;
+ }
+
+ #region Events
+ public event EventHandler> SolutionAdded;
+ public void OnSolutionAdded(object sender, EventArgs args) {
+ var added = SolutionAdded;
+ if (added == null) return;
+ added(sender, args);
+ }
+
+ public event EventHandler> SolutionRemoved;
+ public void OnSolutionRemoved(object sender, EventArgs args) {
+ var removed = SolutionRemoved;
+ if (removed == null) return;
+ removed(sender, args);
+ }
+
+ public event EventHandler VariableValueChanged;
+ public void OnVariableValueChanged(object sender, EventArgs args) {
+ var changed = VariableValueChanged;
+ if (changed == null) return;
+ changed(sender, args);
+ }
+
+ public event EventHandler ZoomChanged;
+ public void OnZoomChanged(object sender, EventArgs args) {
+ var changed = ZoomChanged;
+ if (changed == null) return;
+ changed(sender, args);
+ }
+
+ private void sharedFixedVariables_ItemChanged(object o, EventArgs e) {
+ if (o != sharedFixedVariables) return;
+ var variables = sharedFixedVariables.VariableNames.ToList();
+ var rowIndex = e.Value;
+ var columnIndex = e.Value2;
+
+ var variableName = variables[columnIndex];
+ if (variableName == FreeVariable) return;
+ if (internalDataset.VariableHasType(variableName)) {
+ var v = sharedFixedVariables.GetDoubleValue(variableName, rowIndex);
+ var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
+ internalDataset.ReplaceVariable(variableName, values);
+ } else if (internalDataset.VariableHasType(variableName)) {
+ var v = sharedFixedVariables.GetStringValue(variableName, rowIndex);
+ var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
+ internalDataset.ReplaceVariable(variableName, values);
+ } else {
+ // unsupported type
+ throw new NotSupportedException();
+ }
+ }
+
+ private async void chart_DragDrop(object sender, DragEventArgs e) {
+ var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+ if (data != null) {
+ var solution = data as IRegressionSolution;
+ if (!solutions.Contains(solution))
+ await AddSolutionAsync(solution);
+ }
+ }
+ private void chart_DragEnter(object sender, DragEventArgs e) {
+ if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) return;
+ e.Effect = DragDropEffects.None;
+
+ var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+ var regressionSolution = data as IRegressionSolution;
+ if (regressionSolution != null) {
+ e.Effect = DragDropEffects.Copy;
+ }
+ }
+
+ private void calculationPendingTimer_Tick(object sender, EventArgs e) {
+ calculationPendingLabel.Visible = true;
+ Update();
+ }
+
+ private void chart_SelectionRangeChanged(object sender, CursorEventArgs e) {
+ OnZoomChanged(this, EventArgs.Empty);
+ }
+
+ private void chart_Resize(object sender, EventArgs e) {
+ UpdateTitlePosition();
+ }
+
+ private void chart_PostPaint(object sender, ChartPaintEventArgs e) {
+ if (ChartPostPaint != null)
+ ChartPostPaint(this, EventArgs.Empty);
+ }
+ #endregion
+
+ private void chart_MouseClick(object sender, MouseEventArgs e) {
+ var hitTestResult = chart.HitTest(e.X, e.Y, ChartElementType.DataPoint);
+ if (hitTestResult != null && hitTestResult.ChartElementType == ChartElementType.DataPoint) {
+ var series = hitTestResult.Series;
+ var dataPoint = (DataPoint)hitTestResult.Object;
+ var idx = series.Points.IndexOf(dataPoint);
+ UpdateSelectedValue(variableValues[idx]);
+
+ UpdateAllSeriesStyles(idx);
+ }
+ }
+
+ private void UpdateAllSeriesStyles(int selectedValueIndex) {
+ if (ShowCursor) {
+ chart.Titles[0].Text = FreeVariable + " : " + variableValues[selectedValueIndex];
+ chart.Update();
+ }
+ foreach (var s in seriesCache.Values) {
+ if (s.ChartType == SeriesChartType.Column)
+ for (int i = 0; i < s.Points.Count; i++) {
+ if (i != selectedValueIndex) {
+ s.Points[i].BorderDashStyle = ChartDashStyle.NotSet;
+ } else {
+ s.Points[i].BorderDashStyle = ChartDashStyle.Dash;
+ s.Points[i].BorderColor = Color.Red;
+ }
+ }
+ }
+ }
+
+ private void UpdateSelectedValue(string variableValue) {
+ sharedFixedVariables.SetVariableValue(variableValue, FreeVariable, 0);
+ OnVariableValueChanged(this, EventArgs.Empty);
+ }
+ }
+}
+
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChart.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChart.Designer.cs (revision 15136)
+++ (revision )
@@ -1,144 +1,0 @@
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- partial class GradientChart {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
- System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
- System.Windows.Forms.DataVisualization.Charting.StripLine stripLine1 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
- System.Windows.Forms.DataVisualization.Charting.StripLine stripLine2 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
- System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
- System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
- this.calculationPendingLabel = new System.Windows.Forms.Label();
- this.calculationPendingTimer = new System.Windows.Forms.Timer(this.components);
- this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
- this.configurationButton = new System.Windows.Forms.Button();
- this.toolTip = new System.Windows.Forms.ToolTip(this.components);
- ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
- this.SuspendLayout();
- //
- // calculationPendingLabel
- //
- this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
- this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
- this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
- this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
- this.calculationPendingLabel.Margin = new System.Windows.Forms.Padding(0);
- this.calculationPendingLabel.Name = "calculationPendingLabel";
- this.calculationPendingLabel.Size = new System.Drawing.Size(17, 17);
- this.calculationPendingLabel.TabIndex = 1;
- this.calculationPendingLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.calculationPendingLabel.Visible = false;
- //
- // calculationPendingTimer
- //
- this.calculationPendingTimer.Tick += new System.EventHandler(this.calculationPendingTimer_Tick);
- //
- // chart
- //
- this.chart.AllowDrop = true;
- verticalLineAnnotation1.AllowMoving = true;
- verticalLineAnnotation1.AxisXName = "ChartArea\\rX";
- verticalLineAnnotation1.ClipToChartArea = "ChartArea";
- verticalLineAnnotation1.IsInfinitive = true;
- verticalLineAnnotation1.LineColor = System.Drawing.Color.Red;
- verticalLineAnnotation1.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
- verticalLineAnnotation1.Name = "VerticalLineAnnotation";
- verticalLineAnnotation1.YAxisName = "ChartArea\\rY";
- this.chart.Annotations.Add(verticalLineAnnotation1);
- stripLine1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
- stripLine2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
- chartArea1.AxisX.StripLines.Add(stripLine1);
- chartArea1.AxisX.StripLines.Add(stripLine2);
- chartArea1.Name = "ChartArea";
- chartArea1.Position.Auto = false;
- chartArea1.Position.Height = 90F;
- chartArea1.Position.Width = 100F;
- chartArea1.Position.Y = 10F;
- this.chart.ChartAreas.Add(chartArea1);
- this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
- legend1.Alignment = System.Drawing.StringAlignment.Center;
- legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
- legend1.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.ReversedSeriesOrder;
- legend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
- legend1.Name = "Default";
- this.chart.Legends.Add(legend1);
- this.chart.Location = new System.Drawing.Point(0, 0);
- this.chart.Name = "chart";
- this.chart.Size = new System.Drawing.Size(453, 308);
- this.chart.TabIndex = 0;
- title1.Alignment = System.Drawing.ContentAlignment.TopCenter;
- title1.DockedToChartArea = "ChartArea";
- title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- title1.IsDockedInsideChartArea = false;
- title1.Name = "Title";
- title1.Text = "[Title]";
- this.chart.Titles.Add(title1);
- this.chart.SelectionRangeChanged += new System.EventHandler(this.chart_SelectionRangeChanged);
- this.chart.PostPaint += new System.EventHandler(this.chart_PostPaint);
- this.chart.AnnotationPositionChanged += new System.EventHandler(this.chart_AnnotationPositionChanged);
- this.chart.AnnotationPositionChanging += new System.EventHandler(this.chart_AnnotationPositionChanging);
- this.chart.DragDrop += new System.Windows.Forms.DragEventHandler(this.chart_DragDrop);
- this.chart.DragEnter += new System.Windows.Forms.DragEventHandler(this.chart_DragEnter);
- this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
- this.chart.Resize += new System.EventHandler(this.chart_Resize);
- //
- // configurationButton
- //
- this.configurationButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.configurationButton.AutoSize = true;
- this.configurationButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Properties;
- this.configurationButton.Location = new System.Drawing.Point(426, 3);
- this.configurationButton.Name = "configurationButton";
- this.configurationButton.Size = new System.Drawing.Size(24, 24);
- this.configurationButton.TabIndex = 2;
- this.configurationButton.TabStop = false;
- this.toolTip.SetToolTip(this.configurationButton, "Configuration");
- this.configurationButton.UseVisualStyleBackColor = true;
- this.configurationButton.Click += new System.EventHandler(this.config_Click);
- //
- // GradientChart
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.configurationButton);
- this.Controls.Add(this.calculationPendingLabel);
- this.Controls.Add(this.chart);
- this.Name = "GradientChart";
- this.Size = new System.Drawing.Size(453, 308);
- ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
- private System.Windows.Forms.Label calculationPendingLabel;
- private System.Windows.Forms.Timer calculationPendingTimer;
- private System.Windows.Forms.Button configurationButton;
- private System.Windows.Forms.ToolTip toolTip;
- }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChart.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChart.cs (revision 15136)
+++ (revision )
@@ -1,715 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Collections;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Forms.DataVisualization.Charting;
-using HeuristicLab.Common;
-using HeuristicLab.MainForm.WindowsForms;
-using HeuristicLab.Visualization.ChartControlsExtensions;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- public partial class GradientChart : UserControl, IGradientChart {
- private ModifiableDataset sharedFixedVariables; // used for syncronising variable values between charts
- private ModifiableDataset internalDataset; // holds the x values for each point drawn
-
- private CancellationTokenSource cancelCurrentRecalculateSource;
-
- private readonly List solutions;
- private readonly Dictionary seriesCache;
- private readonly Dictionary ciSeriesCache;
-
- private readonly ToolStripMenuItem configToolStripMenuItem;
- private readonly GradientChartConfigurationDialog configurationDialog;
-
- #region Properties
- public string XAxisTitle {
- get { return chart.ChartAreas[0].AxisX.Title; }
- set { chart.ChartAreas[0].AxisX.Title = value; }
- }
-
- public string YAxisTitle {
- get { return chart.ChartAreas[0].AxisY.Title; }
- set { chart.ChartAreas[0].AxisY.Title = value; }
- }
-
- public bool ShowLegend {
- get { return chart.Legends[0].Enabled; }
- set { chart.Legends[0].Enabled = value; }
- }
- public bool ShowCursor {
- get { return chart.Annotations[0].Visible; }
- set {
- chart.Annotations[0].Visible = value;
- if (!value) chart.Titles[0].Text = string.Empty;
- }
- }
-
- public bool ShowConfigButton {
- get { return configurationButton.Visible; }
- set { configurationButton.Visible = value; }
- }
-
- private int xAxisTicks = 5;
- public int XAxisTicks {
- get { return xAxisTicks; }
- set {
- if (value != xAxisTicks) {
- xAxisTicks = value;
- SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
- RecalculateInternalDataset();
- }
- }
- }
- private double? fixedXAxisMin;
- public double? FixedXAxisMin {
- get { return fixedXAxisMin; }
- set {
- if ((value.HasValue && fixedXAxisMin.HasValue && !value.Value.IsAlmost(fixedXAxisMin.Value)) || (value.HasValue != fixedXAxisMin.HasValue)) {
- fixedXAxisMin = value;
- if (trainingMin < trainingMax) {
- SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
- RecalculateInternalDataset();
- // set the vertical line position
- if (VerticalLineAnnotation.X <= fixedXAxisMin) {
- var axisX = chart.ChartAreas[0].AxisX;
- var step = (axisX.Maximum - axisX.Minimum) / drawingSteps;
- VerticalLineAnnotation.X = axisX.Minimum + step;
- }
- }
- }
- }
- }
- private double? fixedXAxisMax;
- public double? FixedXAxisMax {
- get { return fixedXAxisMax; }
- set {
- if ((value.HasValue && fixedXAxisMax.HasValue && !value.Value.IsAlmost(fixedXAxisMax.Value)) || (value.HasValue != fixedXAxisMax.HasValue)) {
- fixedXAxisMax = value;
- if (trainingMin < trainingMax) {
- SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
- RecalculateInternalDataset();
- // set the vertical line position
- if (VerticalLineAnnotation.X >= fixedXAxisMax) {
- var axisX = chart.ChartAreas[0].AxisX;
- var step = (axisX.Maximum - axisX.Minimum) / drawingSteps;
- VerticalLineAnnotation.X = axisX.Maximum - step;
- }
- }
- }
- }
- }
-
- private int yAxisTicks = 5;
- public int YAxisTicks {
- get { return yAxisTicks; }
- set {
- if (value != yAxisTicks) {
- yAxisTicks = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- RecalculateInternalDataset();
- }
- }
- }
- private double? fixedYAxisMin;
- public double? FixedYAxisMin {
- get { return fixedYAxisMin; }
- set {
- if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
- fixedYAxisMin = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- }
- }
- }
- private double? fixedYAxisMax;
- public double? FixedYAxisMax {
- get { return fixedYAxisMax; }
- set {
- if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
- fixedYAxisMax = value;
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
- }
- }
- }
-
- private double trainingMin = 1;
- private double trainingMax = -1;
-
- private int drawingSteps = 1000;
- public int DrawingSteps {
- get { return drawingSteps; }
- set {
- if (value != drawingSteps) {
- drawingSteps = value;
- RecalculateInternalDataset();
- ResizeAllSeriesData();
- }
- }
- }
-
- private string freeVariable;
- public string FreeVariable {
- get { return freeVariable; }
- set {
- if (value == freeVariable) return;
- if (solutions.Any(s => !s.ProblemData.Dataset.DoubleVariables.Contains(value))) {
- throw new ArgumentException("Variable does not exist in the ProblemData of the Solutions.");
- }
- freeVariable = value;
- RecalculateInternalDataset();
- }
- }
-
- private double yMin;
- public double YMin {
- get { return yMin; }
- }
- private double yMax;
- public double YMax {
- get { return yMax; }
- }
-
- public bool IsZoomed {
- get { return chart.ChartAreas[0].AxisX.ScaleView.IsZoomed; }
- }
-
- private VerticalLineAnnotation VerticalLineAnnotation {
- get { return (VerticalLineAnnotation)chart.Annotations.SingleOrDefault(x => x is VerticalLineAnnotation); }
- }
-
- internal ElementPosition InnerPlotPosition {
- get { return chart.ChartAreas[0].InnerPlotPosition; }
- }
- #endregion
-
- public event EventHandler ChartPostPaint;
-
- public GradientChart() {
- InitializeComponent();
-
- solutions = new List();
- seriesCache = new Dictionary();
- ciSeriesCache = new Dictionary();
-
- // Configure axis
- chart.CustomizeAllChartAreas();
- chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
- chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
- chart.ChartAreas[0].CursorX.Interval = 0;
-
- chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
- chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
- chart.ChartAreas[0].CursorY.Interval = 0;
-
- configToolStripMenuItem = new ToolStripMenuItem("Configuration");
- configToolStripMenuItem.Click += config_Click;
- chart.ContextMenuStrip.Items.Add(new ToolStripSeparator());
- chart.ContextMenuStrip.Items.Add(configToolStripMenuItem);
- configurationDialog = new GradientChartConfigurationDialog(this);
-
- Disposed += GradientChart_Disposed;
- }
-
- private void GradientChart_Disposed(object sender, EventArgs e) {
- if (cancelCurrentRecalculateSource != null)
- cancelCurrentRecalculateSource.Cancel();
- }
-
- public void Configure(IEnumerable solutions, ModifiableDataset sharedFixedVariables, string freeVariable, int drawingSteps, bool initializeAxisRanges = true) {
- if (!SolutionsCompatible(solutions))
- throw new ArgumentException("Solutions are not compatible with the problem data.");
- this.freeVariable = freeVariable;
- this.drawingSteps = drawingSteps;
-
- this.solutions.Clear();
- this.solutions.AddRange(solutions);
-
- // add an event such that whenever a value is changed in the shared dataset,
- // this change is reflected in the internal dataset (where the value becomes a whole column)
- if (this.sharedFixedVariables != null)
- this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged;
- this.sharedFixedVariables = sharedFixedVariables;
- this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged;
-
- RecalculateTrainingLimits(initializeAxisRanges);
- RecalculateInternalDataset();
-
- chart.Series.Clear();
- seriesCache.Clear();
- ciSeriesCache.Clear();
- foreach (var solution in this.solutions) {
- var series = CreateSeries(solution);
- seriesCache.Add(solution, series.Item1);
- if (series.Item2 != null)
- ciSeriesCache.Add(solution, series.Item2);
- }
-
- // Set cursor and x-axis
- // Make sure to allow a small offset to be able to distinguish the vertical line annotation from the axis
- var defaultValue = sharedFixedVariables.GetDoubleValue(freeVariable, 0);
- var step = (trainingMax - trainingMin) / drawingSteps;
- var minimum = chart.ChartAreas[0].AxisX.Minimum;
- var maximum = chart.ChartAreas[0].AxisX.Maximum;
- if (defaultValue <= minimum)
- VerticalLineAnnotation.X = minimum + step;
- else if (defaultValue >= maximum)
- VerticalLineAnnotation.X = maximum - step;
- else
- VerticalLineAnnotation.X = defaultValue;
-
- if (ShowCursor)
- chart.Titles[0].Text = FreeVariable + " : " + defaultValue.ToString("G5", CultureInfo.CurrentCulture);
-
- ResizeAllSeriesData();
- OrderAndColorSeries();
- }
-
- public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) {
- if (IsDisposed
- || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable)
- || trainingMin.IsAlmost(trainingMax) || trainingMin > trainingMax || drawingSteps == 0)
- return;
-
- calculationPendingTimer.Start();
-
- // cancel previous recalculate call
- if (cancelCurrentRecalculateSource != null)
- cancelCurrentRecalculateSource.Cancel();
- cancelCurrentRecalculateSource = new CancellationTokenSource();
- var cancellationToken = cancelCurrentRecalculateSource.Token;
-
- // Update series
- try {
- var limits = await UpdateAllSeriesDataAsync(cancellationToken);
-
- yMin = limits.Lower;
- yMax = limits.Upper;
- // Set y-axis
- if (resetYAxis)
- SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
-
- UpdateOutOfTrainingRangeStripLines();
-
- calculationPendingTimer.Stop();
- calculationPendingLabel.Visible = false;
- if (updateOnFinish)
- Update();
- } catch (OperationCanceledException) { } catch (AggregateException ae) {
- if (!ae.InnerExceptions.Any(e => e is OperationCanceledException))
- throw;
- }
- }
-
- public void UpdateTitlePosition() {
- var title = chart.Titles[0];
- var plotArea = InnerPlotPosition;
-
- title.Visible = plotArea.Width != 0;
-
- title.Position.X = plotArea.X + (plotArea.Width / 2);
- }
-
- private void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
- if (minValue < maxValue) {
- double axisMin, axisMax, axisInterval;
- ChartUtil.CalculateAxisInterval(minValue, maxValue, ticks, out axisMin, out axisMax, out axisInterval);
- axis.Minimum = fixedAxisMin ?? axisMin;
- axis.Maximum = fixedAxisMax ?? axisMax;
- axis.Interval = (axis.Maximum - axis.Minimum) / ticks;
- }
-
- try {
- chart.ChartAreas[0].RecalculateAxesScale();
- } catch (InvalidOperationException) {
- // Can occur if eg. axis min == axis max
- }
- }
-
- private void RecalculateTrainingLimits(bool initializeAxisRanges) {
- trainingMin = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Min()).Max();
- trainingMax = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Max()).Min();
-
- if (initializeAxisRanges) {
- double xmin, xmax, xinterval;
- ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
- FixedXAxisMin = xmin;
- FixedXAxisMax = xmax;
- }
- }
-
- private void RecalculateInternalDataset() {
- if (sharedFixedVariables == null)
- return;
-
- // we expand the range in order to get nice tick intervals on the x axis
- double xmin, xmax, xinterval;
- ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
-
- if (FixedXAxisMin.HasValue) xmin = FixedXAxisMin.Value;
- if (FixedXAxisMax.HasValue) xmax = FixedXAxisMax.Value;
- double step = (xmax - xmin) / drawingSteps;
-
- var xvalues = new List();
- for (int i = 0; i < drawingSteps; i++)
- xvalues.Add(xmin + i * step);
-
- if (sharedFixedVariables == null)
- return;
-
- var variables = sharedFixedVariables.VariableNames.ToList();
- var values = new List();
- foreach (var varName in variables) {
- if (varName == FreeVariable) {
- values.Add(xvalues);
- } else if (sharedFixedVariables.VariableHasType(varName)) {
- values.Add(Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(varName, 0), xvalues.Count).ToList());
- } else if (sharedFixedVariables.VariableHasType(varName)) {
- values.Add(Enumerable.Repeat(sharedFixedVariables.GetStringValue(varName, 0), xvalues.Count).ToList());
- }
- }
-
- internalDataset = new ModifiableDataset(variables, values);
- }
-
- private Tuple CreateSeries(IRegressionSolution solution) {
- var series = new Series {
- ChartType = SeriesChartType.Line,
- Name = solution.ProblemData.TargetVariable + " " + solutions.IndexOf(solution)
- };
- series.LegendText = series.Name;
-
- var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
- Series confidenceIntervalSeries = null;
- if (confidenceBoundSolution != null) {
- confidenceIntervalSeries = new Series {
- ChartType = SeriesChartType.Range,
- YValuesPerPoint = 2,
- Name = "95% Conf. Interval " + series.Name,
- IsVisibleInLegend = false
- };
- }
- return Tuple.Create(series, confidenceIntervalSeries);
- }
-
- private void OrderAndColorSeries() {
- chart.SuspendRepaint();
-
- chart.Series.Clear();
- // Add mean series for applying palette colors
- foreach (var solution in solutions) {
- chart.Series.Add(seriesCache[solution]);
- }
-
- chart.Palette = ChartColorPalette.BrightPastel;
- chart.ApplyPaletteColors();
- chart.Palette = ChartColorPalette.None;
-
- // Add confidence interval series before its coresponding series for correct z index
- foreach (var solution in solutions) {
- Series ciSeries;
- if (ciSeriesCache.TryGetValue(solution, out ciSeries)) {
- var series = seriesCache[solution];
- ciSeries.Color = Color.FromArgb(40, series.Color);
- int idx = chart.Series.IndexOf(seriesCache[solution]);
- chart.Series.Insert(idx, ciSeries);
- }
- }
-
- chart.ResumeRepaint(true);
- }
-
- private async Task UpdateAllSeriesDataAsync(CancellationToken cancellationToken) {
- var updateTasks = solutions.Select(solution => UpdateSeriesDataAsync(solution, cancellationToken));
-
- double min = double.MaxValue, max = double.MinValue;
- foreach (var update in updateTasks) {
- var limit = await update;
- if (limit.Lower < min) min = limit.Lower;
- if (limit.Upper > max) max = limit.Upper;
- }
-
- return new DoubleLimit(min, max);
- }
-
- private Task UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) {
- return Task.Run(() => {
- var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
- var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
-
- double min = double.MaxValue, max = double.MinValue;
-
- var series = seriesCache[solution];
- for (int i = 0; i < xvalues.Count; i++) {
- series.Points[i].SetValueXY(xvalues[i], yvalues[i]);
- if (yvalues[i] < min) min = yvalues[i];
- if (yvalues[i] > max) max = yvalues[i];
- }
- chart.Invalidate();
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
- if (confidenceBoundSolution != null) {
- var confidenceIntervalSeries = ciSeriesCache[solution];
- var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
- for (int i = 0; i < xvalues.Count; i++) {
- var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
- var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
- confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper);
- if (lower < min) min = lower;
- if (upper > max) max = upper;
- }
- chart.Invalidate();
- }
-
- cancellationToken.ThrowIfCancellationRequested();
- return new DoubleLimit(min, max);
- }, cancellationToken);
- }
-
- private void ResizeAllSeriesData() {
- if (internalDataset == null)
- return;
-
- var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
- foreach (var solution in solutions)
- ResizeSeriesData(solution, xvalues);
- }
- private void ResizeSeriesData(IRegressionSolution solution, IList xvalues = null) {
- if (xvalues == null)
- xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
-
- var series = seriesCache[solution];
- series.Points.SuspendUpdates();
- series.Points.Clear();
- for (int i = 0; i < xvalues.Count; i++)
- series.Points.Add(new DataPoint(xvalues[i], 0.0));
- series.Points.ResumeUpdates();
-
- Series confidenceIntervalSeries;
- if (ciSeriesCache.TryGetValue(solution, out confidenceIntervalSeries)) {
- confidenceIntervalSeries.Points.SuspendUpdates();
- confidenceIntervalSeries.Points.Clear();
- for (int i = 0; i < xvalues.Count; i++)
- confidenceIntervalSeries.Points.Add(new DataPoint(xvalues[i], new[] { -1.0, 1.0 }));
- confidenceIntervalSeries.Points.ResumeUpdates();
- }
- }
-
- public async Task AddSolutionAsync(IRegressionSolution solution) {
- if (!SolutionsCompatible(solutions.Concat(new[] { solution })))
- throw new ArgumentException("The solution is not compatible with the problem data.");
- if (solutions.Contains(solution))
- return;
-
- solutions.Add(solution);
- RecalculateTrainingLimits(true);
-
- var series = CreateSeries(solution);
- seriesCache.Add(solution, series.Item1);
- if (series.Item2 != null)
- ciSeriesCache.Add(solution, series.Item2);
-
- ResizeSeriesData(solution);
- OrderAndColorSeries();
-
- await RecalculateAsync();
- var args = new EventArgs(solution);
- OnSolutionAdded(this, args);
- }
-
- public async Task RemoveSolutionAsync(IRegressionSolution solution) {
- if (!solutions.Remove(solution))
- return;
-
- RecalculateTrainingLimits(true);
-
- seriesCache.Remove(solution);
- ciSeriesCache.Remove(solution);
-
- await RecalculateAsync();
- var args = new EventArgs(solution);
- OnSolutionRemoved(this, args);
- }
-
- private static bool SolutionsCompatible(IEnumerable solutions) {
- var refSolution = solutions.First();
- var refSolVars = refSolution.ProblemData.Dataset.VariableNames;
- foreach (var solution in solutions.Skip(1)) {
- var variables1 = solution.ProblemData.Dataset.VariableNames;
- if (!variables1.All(refSolVars.Contains))
- return false;
-
- foreach (var factorVar in variables1.Where(solution.ProblemData.Dataset.VariableHasType)) {
- var distinctVals = refSolution.ProblemData.Dataset.GetStringValues(factorVar).Distinct();
- if (solution.ProblemData.Dataset.GetStringValues(factorVar).Any(val => !distinctVals.Contains(val))) return false;
- }
- }
- return true;
- }
-
- private void UpdateOutOfTrainingRangeStripLines() {
- var axisX = chart.ChartAreas[0].AxisX;
- var lowerStripLine = axisX.StripLines[0];
- var upperStripLine = axisX.StripLines[1];
-
- lowerStripLine.IntervalOffset = axisX.Minimum;
- lowerStripLine.StripWidth = Math.Abs(trainingMin - axisX.Minimum);
-
- upperStripLine.IntervalOffset = trainingMax;
- upperStripLine.StripWidth = Math.Abs(axisX.Maximum - trainingMax);
- }
-
- #region Events
- public event EventHandler> SolutionAdded;
- public void OnSolutionAdded(object sender, EventArgs args) {
- var added = SolutionAdded;
- if (added == null) return;
- added(sender, args);
- }
-
- public event EventHandler> SolutionRemoved;
- public void OnSolutionRemoved(object sender, EventArgs args) {
- var removed = SolutionRemoved;
- if (removed == null) return;
- removed(sender, args);
- }
-
- public event EventHandler VariableValueChanged;
- public void OnVariableValueChanged(object sender, EventArgs args) {
- var changed = VariableValueChanged;
- if (changed == null) return;
- changed(sender, args);
- }
-
- public event EventHandler ZoomChanged;
- public void OnZoomChanged(object sender, EventArgs args) {
- var changed = ZoomChanged;
- if (changed == null) return;
- changed(sender, args);
- }
-
- private void sharedFixedVariables_ItemChanged(object o, EventArgs e) {
- if (o != sharedFixedVariables) return;
- var variables = sharedFixedVariables.VariableNames.ToList();
- var rowIndex = e.Value;
- var columnIndex = e.Value2;
-
- var variableName = variables[columnIndex];
- if (variableName == FreeVariable) return;
- if (internalDataset.VariableHasType(variableName)) {
- var v = sharedFixedVariables.GetDoubleValue(variableName, rowIndex);
- var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
- internalDataset.ReplaceVariable(variableName, values);
- } else if (internalDataset.VariableHasType(variableName)) {
- var v = sharedFixedVariables.GetStringValue(variableName, rowIndex);
- var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
- internalDataset.ReplaceVariable(variableName, values);
- } else {
- // unsupported type
- throw new NotSupportedException();
- }
- }
-
- private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
- var step = (trainingMax - trainingMin) / drawingSteps;
- double newLocation = step * (long)Math.Round(e.NewLocationX / step);
- var axisX = chart.ChartAreas[0].AxisX;
- if (newLocation >= axisX.Maximum)
- newLocation = axisX.Maximum - step;
- if (newLocation <= axisX.Minimum)
- newLocation = axisX.Minimum + step;
-
- e.NewLocationX = newLocation;
-
- UpdateCursor();
- }
- private void chart_AnnotationPositionChanged(object sender, EventArgs e) {
- UpdateCursor();
- }
- private void UpdateCursor() {
- var x = VerticalLineAnnotation.X;
- sharedFixedVariables.SetVariableValue(x, FreeVariable, 0);
-
- if (ShowCursor) {
- chart.Titles[0].Text = FreeVariable + " : " + x.ToString("G5", CultureInfo.CurrentCulture);
- chart.Update();
- }
-
- OnVariableValueChanged(this, EventArgs.Empty);
- }
-
- private void chart_MouseMove(object sender, MouseEventArgs e) {
- bool hitCursor = chart.HitTest(e.X, e.Y).ChartElementType == ChartElementType.Annotation;
- chart.Cursor = hitCursor ? Cursors.VSplit : Cursors.Default;
- }
-
- private async void chart_DragDrop(object sender, DragEventArgs e) {
- var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
- if (data != null) {
- var solution = data as IRegressionSolution;
- if (!solutions.Contains(solution))
- await AddSolutionAsync(solution);
- }
- }
- private void chart_DragEnter(object sender, DragEventArgs e) {
- if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) return;
- e.Effect = DragDropEffects.None;
-
- var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
- var regressionSolution = data as IRegressionSolution;
- if (regressionSolution != null) {
- e.Effect = DragDropEffects.Copy;
- }
- }
-
- private void calculationPendingTimer_Tick(object sender, EventArgs e) {
- calculationPendingLabel.Visible = true;
- Update();
- }
-
- private void config_Click(object sender, EventArgs e) {
- configurationDialog.ShowDialog(this);
- }
-
- private void chart_SelectionRangeChanged(object sender, CursorEventArgs e) {
- OnZoomChanged(this, EventArgs.Empty);
- }
-
- private void chart_Resize(object sender, EventArgs e) {
- UpdateTitlePosition();
- }
-
- private void chart_PostPaint(object sender, ChartPaintEventArgs e) {
- if (ChartPostPaint != null)
- ChartPostPaint(this, EventArgs.Empty);
- }
- #endregion
- }
-}
-
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChartConfigurationDialog.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChartConfigurationDialog.Designer.cs (revision 15136)
+++ (revision )
@@ -1,327 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- partial class GradientChartConfigurationDialog {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- this.xAxisGroupBox = new System.Windows.Forms.GroupBox();
- this.maxXTextBox = new System.Windows.Forms.TextBox();
- this.xAutomaticCheckBox = new System.Windows.Forms.CheckBox();
- this.minXTextBox = new System.Windows.Forms.TextBox();
- this.maxXLabel = new System.Windows.Forms.Label();
- this.minXLabel = new System.Windows.Forms.Label();
- this.yAxisGroupBox = new System.Windows.Forms.GroupBox();
- this.maxYTextBox = new System.Windows.Forms.TextBox();
- this.yAutomaticCheckBox = new System.Windows.Forms.CheckBox();
- this.minYTextBox = new System.Windows.Forms.TextBox();
- this.maxYLabel = new System.Windows.Forms.Label();
- this.minYLabel = new System.Windows.Forms.Label();
- this.miscGroupBox = new System.Windows.Forms.GroupBox();
- this.StepsNumericUpDown = new System.Windows.Forms.NumericUpDown();
- this.stepsLabel = new System.Windows.Forms.Label();
- this.applyButton = new System.Windows.Forms.Button();
- this.cancelButton = new System.Windows.Forms.Button();
- this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
- this.xAxisGroupBox.SuspendLayout();
- this.yAxisGroupBox.SuspendLayout();
- this.miscGroupBox.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.StepsNumericUpDown)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
- this.SuspendLayout();
- //
- // xAxisGroupBox
- //
- this.xAxisGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.xAxisGroupBox.Controls.Add(this.maxXTextBox);
- this.xAxisGroupBox.Controls.Add(this.xAutomaticCheckBox);
- this.xAxisGroupBox.Controls.Add(this.minXTextBox);
- this.xAxisGroupBox.Controls.Add(this.maxXLabel);
- this.xAxisGroupBox.Controls.Add(this.minXLabel);
- this.xAxisGroupBox.Location = new System.Drawing.Point(12, 12);
- this.xAxisGroupBox.Name = "xAxisGroupBox";
- this.xAxisGroupBox.Size = new System.Drawing.Size(234, 78);
- this.xAxisGroupBox.TabIndex = 1;
- this.xAxisGroupBox.TabStop = false;
- this.xAxisGroupBox.Text = "X-Axis";
- //
- // maxXTextBox
- //
- this.maxXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.maxXTextBox.Location = new System.Drawing.Point(61, 45);
- this.maxXTextBox.Name = "maxXTextBox";
- this.maxXTextBox.Size = new System.Drawing.Size(167, 20);
- this.maxXTextBox.TabIndex = 3;
- this.maxXTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
- this.maxXTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
- //
- // xAutomaticCheckBox
- //
- this.xAutomaticCheckBox.AutoSize = true;
- this.xAutomaticCheckBox.Location = new System.Drawing.Point(48, -1);
- this.xAutomaticCheckBox.Name = "xAutomaticCheckBox";
- this.xAutomaticCheckBox.Size = new System.Drawing.Size(73, 17);
- this.xAutomaticCheckBox.TabIndex = 1;
- this.xAutomaticCheckBox.Text = "Automatic";
- this.xAutomaticCheckBox.UseVisualStyleBackColor = true;
- this.xAutomaticCheckBox.CheckedChanged += new System.EventHandler(this.automaticCheckBox_CheckedChanged);
- //
- // minXTextBox
- //
- this.minXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.minXTextBox.Location = new System.Drawing.Point(61, 19);
- this.minXTextBox.Name = "minXTextBox";
- this.minXTextBox.Size = new System.Drawing.Size(167, 20);
- this.minXTextBox.TabIndex = 2;
- this.minXTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
- this.minXTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
- //
- // maxXLabel
- //
- this.maxXLabel.AutoSize = true;
- this.maxXLabel.Location = new System.Drawing.Point(7, 48);
- this.maxXLabel.Name = "maxXLabel";
- this.maxXLabel.Size = new System.Drawing.Size(27, 13);
- this.maxXLabel.TabIndex = 1;
- this.maxXLabel.Text = "Max";
- //
- // minXLabel
- //
- this.minXLabel.AutoSize = true;
- this.minXLabel.Location = new System.Drawing.Point(7, 22);
- this.minXLabel.Name = "minXLabel";
- this.minXLabel.Size = new System.Drawing.Size(24, 13);
- this.minXLabel.TabIndex = 0;
- this.minXLabel.Text = "Min";
- //
- // yAxisGroupBox
- //
- this.yAxisGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.yAxisGroupBox.Controls.Add(this.maxYTextBox);
- this.yAxisGroupBox.Controls.Add(this.yAutomaticCheckBox);
- this.yAxisGroupBox.Controls.Add(this.minYTextBox);
- this.yAxisGroupBox.Controls.Add(this.maxYLabel);
- this.yAxisGroupBox.Controls.Add(this.minYLabel);
- this.yAxisGroupBox.Location = new System.Drawing.Point(13, 96);
- this.yAxisGroupBox.Name = "yAxisGroupBox";
- this.yAxisGroupBox.Size = new System.Drawing.Size(234, 75);
- this.yAxisGroupBox.TabIndex = 2;
- this.yAxisGroupBox.TabStop = false;
- this.yAxisGroupBox.Text = "Y-Axis";
- //
- // maxYTextBox
- //
- this.maxYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.maxYTextBox.Location = new System.Drawing.Point(61, 45);
- this.maxYTextBox.Name = "maxYTextBox";
- this.maxYTextBox.Size = new System.Drawing.Size(167, 20);
- this.maxYTextBox.TabIndex = 3;
- this.maxYTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
- this.maxYTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
- //
- // yAutomaticCheckBox
- //
- this.yAutomaticCheckBox.AutoSize = true;
- this.yAutomaticCheckBox.Location = new System.Drawing.Point(47, -1);
- this.yAutomaticCheckBox.Name = "yAutomaticCheckBox";
- this.yAutomaticCheckBox.Size = new System.Drawing.Size(73, 17);
- this.yAutomaticCheckBox.TabIndex = 1;
- this.yAutomaticCheckBox.Text = "Automatic";
- this.yAutomaticCheckBox.UseVisualStyleBackColor = true;
- this.yAutomaticCheckBox.CheckedChanged += new System.EventHandler(this.automaticCheckBox_CheckedChanged);
- //
- // minYTextBox
- //
- this.minYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.minYTextBox.Location = new System.Drawing.Point(61, 19);
- this.minYTextBox.Name = "minYTextBox";
- this.minYTextBox.Size = new System.Drawing.Size(167, 20);
- this.minYTextBox.TabIndex = 2;
- this.minYTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
- this.minYTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
- //
- // maxYLabel
- //
- this.maxYLabel.AutoSize = true;
- this.maxYLabel.Location = new System.Drawing.Point(7, 48);
- this.maxYLabel.Name = "maxYLabel";
- this.maxYLabel.Size = new System.Drawing.Size(27, 13);
- this.maxYLabel.TabIndex = 1;
- this.maxYLabel.Text = "Max";
- //
- // minYLabel
- //
- this.minYLabel.AutoSize = true;
- this.minYLabel.Location = new System.Drawing.Point(7, 22);
- this.minYLabel.Name = "minYLabel";
- this.minYLabel.Size = new System.Drawing.Size(24, 13);
- this.minYLabel.TabIndex = 0;
- this.minYLabel.Text = "Min";
- //
- // miscGroupBox
- //
- this.miscGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.miscGroupBox.Controls.Add(this.StepsNumericUpDown);
- this.miscGroupBox.Controls.Add(this.stepsLabel);
- this.miscGroupBox.Location = new System.Drawing.Point(13, 177);
- this.miscGroupBox.Name = "miscGroupBox";
- this.miscGroupBox.Size = new System.Drawing.Size(233, 53);
- this.miscGroupBox.TabIndex = 4;
- this.miscGroupBox.TabStop = false;
- //
- // StepsNumericUpDown
- //
- this.StepsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.StepsNumericUpDown.Increment = new decimal(new int[] {
- 50,
- 0,
- 0,
- 0});
- this.StepsNumericUpDown.Location = new System.Drawing.Point(61, 20);
- this.StepsNumericUpDown.Maximum = new decimal(new int[] {
- 100000,
- 0,
- 0,
- 0});
- this.StepsNumericUpDown.Name = "StepsNumericUpDown";
- this.StepsNumericUpDown.Size = new System.Drawing.Size(166, 20);
- this.StepsNumericUpDown.TabIndex = 4;
- //
- // stepsLabel
- //
- this.stepsLabel.AutoSize = true;
- this.stepsLabel.Location = new System.Drawing.Point(6, 22);
- this.stepsLabel.Name = "stepsLabel";
- this.stepsLabel.Size = new System.Drawing.Size(34, 13);
- this.stepsLabel.TabIndex = 1;
- this.stepsLabel.Text = "Steps";
- //
- // applyButton
- //
- this.applyButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.applyButton.Location = new System.Drawing.Point(91, 239);
- this.applyButton.Name = "applyButton";
- this.applyButton.Size = new System.Drawing.Size(75, 23);
- this.applyButton.TabIndex = 5;
- this.applyButton.Text = "Apply";
- this.applyButton.UseVisualStyleBackColor = true;
- this.applyButton.Click += new System.EventHandler(this.okButton_Click);
- //
- // cancelButton
- //
- this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.cancelButton.Location = new System.Drawing.Point(172, 239);
- this.cancelButton.Name = "cancelButton";
- this.cancelButton.Size = new System.Drawing.Size(75, 23);
- this.cancelButton.TabIndex = 6;
- this.cancelButton.Text = "Cancel";
- this.cancelButton.UseVisualStyleBackColor = true;
- //
- // errorProvider
- //
- this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
- this.errorProvider.ContainerControl = this;
- //
- // GradientChartConfigurationDialog
- //
- this.AcceptButton = this.applyButton;
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
- this.CancelButton = this.cancelButton;
- this.ClientSize = new System.Drawing.Size(258, 272);
- this.Controls.Add(this.cancelButton);
- this.Controls.Add(this.applyButton);
- this.Controls.Add(this.miscGroupBox);
- this.Controls.Add(this.xAxisGroupBox);
- this.Controls.Add(this.yAxisGroupBox);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "GradientChartConfigurationDialog";
- this.ShowIcon = false;
- this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
- this.Text = "Configure Gradient Chart";
- this.TopMost = true;
- this.Shown += new System.EventHandler(this.GradientChartConfigurationDialog_Shown);
- this.xAxisGroupBox.ResumeLayout(false);
- this.xAxisGroupBox.PerformLayout();
- this.yAxisGroupBox.ResumeLayout(false);
- this.yAxisGroupBox.PerformLayout();
- this.miscGroupBox.ResumeLayout(false);
- this.miscGroupBox.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.StepsNumericUpDown)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.GroupBox xAxisGroupBox;
- private System.Windows.Forms.TextBox maxXTextBox;
- private System.Windows.Forms.TextBox minXTextBox;
- private System.Windows.Forms.Label maxXLabel;
- private System.Windows.Forms.Label minXLabel;
- private System.Windows.Forms.GroupBox yAxisGroupBox;
- private System.Windows.Forms.TextBox maxYTextBox;
- private System.Windows.Forms.CheckBox yAutomaticCheckBox;
- private System.Windows.Forms.TextBox minYTextBox;
- private System.Windows.Forms.Label maxYLabel;
- private System.Windows.Forms.Label minYLabel;
- private System.Windows.Forms.GroupBox miscGroupBox;
- private System.Windows.Forms.Label stepsLabel;
- private System.Windows.Forms.Button applyButton;
- private System.Windows.Forms.Button cancelButton;
- private System.Windows.Forms.CheckBox xAutomaticCheckBox;
- private System.Windows.Forms.NumericUpDown StepsNumericUpDown;
- private System.Windows.Forms.ErrorProvider errorProvider;
- }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChartConfigurationDialog.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChartConfigurationDialog.cs (revision 15136)
+++ (revision )
@@ -1,121 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.ComponentModel;
-using System.Globalization;
-using System.Windows.Forms;
-using HeuristicLab.MainForm.WindowsForms;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- public partial class GradientChartConfigurationDialog : Form {
- private readonly GradientChart chart;
-
- public GradientChartConfigurationDialog(GradientChart chart) {
- this.chart = chart;
- InitializeComponent();
- }
-
- private void GradientChartConfigurationDialog_Shown(object sender, EventArgs e) {
- if (chart.FixedXAxisMin.HasValue && chart.FixedXAxisMax.HasValue) {
- xAutomaticCheckBox.Checked = false;
- minXTextBox.Text = chart.FixedXAxisMin.Value.ToString(CultureInfo.CurrentUICulture);
- maxXTextBox.Text = chart.FixedXAxisMax.Value.ToString(CultureInfo.CurrentUICulture);
- } else xAutomaticCheckBox.Checked = true;
- if (chart.FixedYAxisMin.HasValue && chart.FixedYAxisMax.HasValue) {
- yAutomaticCheckBox.Checked = false;
- minYTextBox.Text = chart.FixedYAxisMin.Value.ToString(CultureInfo.CurrentUICulture);
- maxYTextBox.Text = chart.FixedYAxisMax.Value.ToString(CultureInfo.CurrentUICulture);
- } else yAutomaticCheckBox.Checked = true;
- StepsNumericUpDown.Value = chart.DrawingSteps;
- }
-
- private async void okButton_Click(object sender, System.EventArgs e) {
- try {
- Enabled = false;
- chart.SuspendRepaint();
- if (xAutomaticCheckBox.Checked) {
- chart.FixedXAxisMin = null;
- chart.FixedXAxisMax = null;
- } else {
- var min = double.Parse(minXTextBox.Text, CultureInfo.CurrentUICulture);
- var max = double.Parse(maxXTextBox.Text, CultureInfo.CurrentUICulture);
- chart.FixedXAxisMin = min;
- chart.FixedXAxisMax = max;
- }
-
- if (yAutomaticCheckBox.Checked) {
- chart.FixedYAxisMin = null;
- chart.FixedYAxisMax = null;
- } else {
- var min = double.Parse(minYTextBox.Text, CultureInfo.CurrentUICulture);
- var max = double.Parse(maxYTextBox.Text, CultureInfo.CurrentUICulture);
- chart.FixedYAxisMin = min;
- chart.FixedYAxisMax = max;
- }
-
- chart.DrawingSteps = (int)StepsNumericUpDown.Value;
-
- await chart.RecalculateAsync(resetYAxis: false);
-
- Close();
- }
- catch (FormatException) {
- MessageBox.Show(this, "Illegal number format", "Wrong format", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- finally {
- Enabled = true;
- chart.ResumeRepaint(true);
- }
- }
-
- private void automaticCheckBox_CheckedChanged(object sender, EventArgs e) {
- minXTextBox.Enabled = !xAutomaticCheckBox.Checked;
- maxXTextBox.Enabled = !xAutomaticCheckBox.Checked;
-
- minYTextBox.Enabled = !yAutomaticCheckBox.Checked;
- maxYTextBox.Enabled = !yAutomaticCheckBox.Checked;
- }
-
- private void numberTextBox_Validating(object sender, CancelEventArgs e) {
- var textBox = sender as TextBox;
- if (textBox != null) {
- double number;
- if (!double.TryParse(textBox.Text, NumberStyles.Any, CultureInfo.CurrentUICulture, out number)) {
- e.Cancel = true;
- applyButton.Enabled = false;
- errorProvider.SetIconAlignment(textBox, ErrorIconAlignment.MiddleLeft);
- errorProvider.SetIconPadding(textBox, 2);
- errorProvider.SetError(textBox, "Illegal number format");
- textBox.SelectAll();
- }
- }
- }
-
- private void numberTextBox_Validated(object sender, EventArgs e) {
- var textBox = sender as TextBox;
- if (textBox != null) {
- errorProvider.SetError(textBox, string.Empty);
- applyButton.Enabled = true;
- }
- }
- }
-}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.Designer.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.Designer.cs (revision 15137)
@@ -0,0 +1,144 @@
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ partial class PartialDependencePlot {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
+ System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+ System.Windows.Forms.DataVisualization.Charting.StripLine stripLine1 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
+ System.Windows.Forms.DataVisualization.Charting.StripLine stripLine2 = new System.Windows.Forms.DataVisualization.Charting.StripLine();
+ System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
+ System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+ this.calculationPendingLabel = new System.Windows.Forms.Label();
+ this.calculationPendingTimer = new System.Windows.Forms.Timer(this.components);
+ this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+ this.configurationButton = new System.Windows.Forms.Button();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+ this.SuspendLayout();
+ //
+ // calculationPendingLabel
+ //
+ this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
+ this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
+ this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
+ this.calculationPendingLabel.Margin = new System.Windows.Forms.Padding(0);
+ this.calculationPendingLabel.Name = "calculationPendingLabel";
+ this.calculationPendingLabel.Size = new System.Drawing.Size(17, 17);
+ this.calculationPendingLabel.TabIndex = 1;
+ this.calculationPendingLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.calculationPendingLabel.Visible = false;
+ //
+ // calculationPendingTimer
+ //
+ this.calculationPendingTimer.Tick += new System.EventHandler(this.calculationPendingTimer_Tick);
+ //
+ // chart
+ //
+ this.chart.AllowDrop = true;
+ verticalLineAnnotation1.AllowMoving = true;
+ verticalLineAnnotation1.AxisXName = "ChartArea\\rX";
+ verticalLineAnnotation1.ClipToChartArea = "ChartArea";
+ verticalLineAnnotation1.IsInfinitive = true;
+ verticalLineAnnotation1.LineColor = System.Drawing.Color.Red;
+ verticalLineAnnotation1.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
+ verticalLineAnnotation1.Name = "VerticalLineAnnotation";
+ verticalLineAnnotation1.YAxisName = "ChartArea\\rY";
+ this.chart.Annotations.Add(verticalLineAnnotation1);
+ stripLine1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
+ stripLine2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
+ chartArea1.AxisX.StripLines.Add(stripLine1);
+ chartArea1.AxisX.StripLines.Add(stripLine2);
+ chartArea1.Name = "ChartArea";
+ chartArea1.Position.Auto = false;
+ chartArea1.Position.Height = 90F;
+ chartArea1.Position.Width = 100F;
+ chartArea1.Position.Y = 10F;
+ this.chart.ChartAreas.Add(chartArea1);
+ this.chart.Dock = System.Windows.Forms.DockStyle.Fill;
+ legend1.Alignment = System.Drawing.StringAlignment.Center;
+ legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+ legend1.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.ReversedSeriesOrder;
+ legend1.LegendStyle = System.Windows.Forms.DataVisualization.Charting.LegendStyle.Row;
+ legend1.Name = "Default";
+ this.chart.Legends.Add(legend1);
+ this.chart.Location = new System.Drawing.Point(0, 0);
+ this.chart.Name = "chart";
+ this.chart.Size = new System.Drawing.Size(453, 308);
+ this.chart.TabIndex = 0;
+ title1.Alignment = System.Drawing.ContentAlignment.TopCenter;
+ title1.DockedToChartArea = "ChartArea";
+ title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ title1.IsDockedInsideChartArea = false;
+ title1.Name = "Title";
+ title1.Text = "[Title]";
+ this.chart.Titles.Add(title1);
+ this.chart.SelectionRangeChanged += new System.EventHandler(this.chart_SelectionRangeChanged);
+ this.chart.PostPaint += new System.EventHandler(this.chart_PostPaint);
+ this.chart.AnnotationPositionChanged += new System.EventHandler(this.chart_AnnotationPositionChanged);
+ this.chart.AnnotationPositionChanging += new System.EventHandler(this.chart_AnnotationPositionChanging);
+ this.chart.DragDrop += new System.Windows.Forms.DragEventHandler(this.chart_DragDrop);
+ this.chart.DragEnter += new System.Windows.Forms.DragEventHandler(this.chart_DragEnter);
+ this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+ this.chart.Resize += new System.EventHandler(this.chart_Resize);
+ //
+ // configurationButton
+ //
+ this.configurationButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.configurationButton.AutoSize = true;
+ this.configurationButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Properties;
+ this.configurationButton.Location = new System.Drawing.Point(426, 3);
+ this.configurationButton.Name = "configurationButton";
+ this.configurationButton.Size = new System.Drawing.Size(24, 24);
+ this.configurationButton.TabIndex = 2;
+ this.configurationButton.TabStop = false;
+ this.toolTip.SetToolTip(this.configurationButton, "Configuration");
+ this.configurationButton.UseVisualStyleBackColor = true;
+ this.configurationButton.Click += new System.EventHandler(this.config_Click);
+ //
+ // PartialDependencePlot
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.configurationButton);
+ this.Controls.Add(this.calculationPendingLabel);
+ this.Controls.Add(this.chart);
+ this.Name = "PartialDependencePlot";
+ this.Size = new System.Drawing.Size(453, 308);
+ ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+ private System.Windows.Forms.Label calculationPendingLabel;
+ private System.Windows.Forms.Timer calculationPendingTimer;
+ private System.Windows.Forms.Button configurationButton;
+ private System.Windows.Forms.ToolTip toolTip;
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlot.cs (revision 15137)
@@ -0,0 +1,715 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm.WindowsForms;
+using HeuristicLab.Visualization.ChartControlsExtensions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ public partial class PartialDependencePlot : UserControl, IPartialDependencePlot {
+ private ModifiableDataset sharedFixedVariables; // used for syncronising variable values between charts
+ private ModifiableDataset internalDataset; // holds the x values for each point drawn
+
+ private CancellationTokenSource cancelCurrentRecalculateSource;
+
+ private readonly List solutions;
+ private readonly Dictionary seriesCache;
+ private readonly Dictionary ciSeriesCache;
+
+ private readonly ToolStripMenuItem configToolStripMenuItem;
+ private readonly PartialDependencePlotConfigurationDialog configurationDialog;
+
+ #region Properties
+ public string XAxisTitle {
+ get { return chart.ChartAreas[0].AxisX.Title; }
+ set { chart.ChartAreas[0].AxisX.Title = value; }
+ }
+
+ public string YAxisTitle {
+ get { return chart.ChartAreas[0].AxisY.Title; }
+ set { chart.ChartAreas[0].AxisY.Title = value; }
+ }
+
+ public bool ShowLegend {
+ get { return chart.Legends[0].Enabled; }
+ set { chart.Legends[0].Enabled = value; }
+ }
+ public bool ShowCursor {
+ get { return chart.Annotations[0].Visible; }
+ set {
+ chart.Annotations[0].Visible = value;
+ if (!value) chart.Titles[0].Text = string.Empty;
+ }
+ }
+
+ public bool ShowConfigButton {
+ get { return configurationButton.Visible; }
+ set { configurationButton.Visible = value; }
+ }
+
+ private int xAxisTicks = 5;
+ public int XAxisTicks {
+ get { return xAxisTicks; }
+ set {
+ if (value != xAxisTicks) {
+ xAxisTicks = value;
+ SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
+ RecalculateInternalDataset();
+ }
+ }
+ }
+ private double? fixedXAxisMin;
+ public double? FixedXAxisMin {
+ get { return fixedXAxisMin; }
+ set {
+ if ((value.HasValue && fixedXAxisMin.HasValue && !value.Value.IsAlmost(fixedXAxisMin.Value)) || (value.HasValue != fixedXAxisMin.HasValue)) {
+ fixedXAxisMin = value;
+ if (trainingMin < trainingMax) {
+ SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
+ RecalculateInternalDataset();
+ // set the vertical line position
+ if (VerticalLineAnnotation.X <= fixedXAxisMin) {
+ var axisX = chart.ChartAreas[0].AxisX;
+ var step = (axisX.Maximum - axisX.Minimum) / drawingSteps;
+ VerticalLineAnnotation.X = axisX.Minimum + step;
+ }
+ }
+ }
+ }
+ }
+ private double? fixedXAxisMax;
+ public double? FixedXAxisMax {
+ get { return fixedXAxisMax; }
+ set {
+ if ((value.HasValue && fixedXAxisMax.HasValue && !value.Value.IsAlmost(fixedXAxisMax.Value)) || (value.HasValue != fixedXAxisMax.HasValue)) {
+ fixedXAxisMax = value;
+ if (trainingMin < trainingMax) {
+ SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
+ RecalculateInternalDataset();
+ // set the vertical line position
+ if (VerticalLineAnnotation.X >= fixedXAxisMax) {
+ var axisX = chart.ChartAreas[0].AxisX;
+ var step = (axisX.Maximum - axisX.Minimum) / drawingSteps;
+ VerticalLineAnnotation.X = axisX.Maximum - step;
+ }
+ }
+ }
+ }
+ }
+
+ private int yAxisTicks = 5;
+ public int YAxisTicks {
+ get { return yAxisTicks; }
+ set {
+ if (value != yAxisTicks) {
+ yAxisTicks = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ RecalculateInternalDataset();
+ }
+ }
+ }
+ private double? fixedYAxisMin;
+ public double? FixedYAxisMin {
+ get { return fixedYAxisMin; }
+ set {
+ if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
+ fixedYAxisMin = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ }
+ }
+ }
+ private double? fixedYAxisMax;
+ public double? FixedYAxisMax {
+ get { return fixedYAxisMax; }
+ set {
+ if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
+ fixedYAxisMax = value;
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+ }
+ }
+ }
+
+ private double trainingMin = 1;
+ private double trainingMax = -1;
+
+ private int drawingSteps = 1000;
+ public int DrawingSteps {
+ get { return drawingSteps; }
+ set {
+ if (value != drawingSteps) {
+ drawingSteps = value;
+ RecalculateInternalDataset();
+ ResizeAllSeriesData();
+ }
+ }
+ }
+
+ private string freeVariable;
+ public string FreeVariable {
+ get { return freeVariable; }
+ set {
+ if (value == freeVariable) return;
+ if (solutions.Any(s => !s.ProblemData.Dataset.DoubleVariables.Contains(value))) {
+ throw new ArgumentException("Variable does not exist in the ProblemData of the Solutions.");
+ }
+ freeVariable = value;
+ RecalculateInternalDataset();
+ }
+ }
+
+ private double yMin;
+ public double YMin {
+ get { return yMin; }
+ }
+ private double yMax;
+ public double YMax {
+ get { return yMax; }
+ }
+
+ public bool IsZoomed {
+ get { return chart.ChartAreas[0].AxisX.ScaleView.IsZoomed; }
+ }
+
+ private VerticalLineAnnotation VerticalLineAnnotation {
+ get { return (VerticalLineAnnotation)chart.Annotations.SingleOrDefault(x => x is VerticalLineAnnotation); }
+ }
+
+ internal ElementPosition InnerPlotPosition {
+ get { return chart.ChartAreas[0].InnerPlotPosition; }
+ }
+ #endregion
+
+ public event EventHandler ChartPostPaint;
+
+ public PartialDependencePlot() {
+ InitializeComponent();
+
+ solutions = new List();
+ seriesCache = new Dictionary();
+ ciSeriesCache = new Dictionary();
+
+ // Configure axis
+ chart.CustomizeAllChartAreas();
+ chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
+ chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
+ chart.ChartAreas[0].CursorX.Interval = 0;
+
+ chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
+ chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
+ chart.ChartAreas[0].CursorY.Interval = 0;
+
+ configToolStripMenuItem = new ToolStripMenuItem("Configuration");
+ configToolStripMenuItem.Click += config_Click;
+ chart.ContextMenuStrip.Items.Add(new ToolStripSeparator());
+ chart.ContextMenuStrip.Items.Add(configToolStripMenuItem);
+ configurationDialog = new PartialDependencePlotConfigurationDialog(this);
+
+ Disposed += Control_Disposed;
+ }
+
+ private void Control_Disposed(object sender, EventArgs e) {
+ if (cancelCurrentRecalculateSource != null)
+ cancelCurrentRecalculateSource.Cancel();
+ }
+
+ public void Configure(IEnumerable solutions, ModifiableDataset sharedFixedVariables, string freeVariable, int drawingSteps, bool initializeAxisRanges = true) {
+ if (!SolutionsCompatible(solutions))
+ throw new ArgumentException("Solutions are not compatible with the problem data.");
+ this.freeVariable = freeVariable;
+ this.drawingSteps = drawingSteps;
+
+ this.solutions.Clear();
+ this.solutions.AddRange(solutions);
+
+ // add an event such that whenever a value is changed in the shared dataset,
+ // this change is reflected in the internal dataset (where the value becomes a whole column)
+ if (this.sharedFixedVariables != null)
+ this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged;
+ this.sharedFixedVariables = sharedFixedVariables;
+ this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged;
+
+ RecalculateTrainingLimits(initializeAxisRanges);
+ RecalculateInternalDataset();
+
+ chart.Series.Clear();
+ seriesCache.Clear();
+ ciSeriesCache.Clear();
+ foreach (var solution in this.solutions) {
+ var series = CreateSeries(solution);
+ seriesCache.Add(solution, series.Item1);
+ if (series.Item2 != null)
+ ciSeriesCache.Add(solution, series.Item2);
+ }
+
+ // Set cursor and x-axis
+ // Make sure to allow a small offset to be able to distinguish the vertical line annotation from the axis
+ var defaultValue = sharedFixedVariables.GetDoubleValue(freeVariable, 0);
+ var step = (trainingMax - trainingMin) / drawingSteps;
+ var minimum = chart.ChartAreas[0].AxisX.Minimum;
+ var maximum = chart.ChartAreas[0].AxisX.Maximum;
+ if (defaultValue <= minimum)
+ VerticalLineAnnotation.X = minimum + step;
+ else if (defaultValue >= maximum)
+ VerticalLineAnnotation.X = maximum - step;
+ else
+ VerticalLineAnnotation.X = defaultValue;
+
+ if (ShowCursor)
+ chart.Titles[0].Text = FreeVariable + " : " + defaultValue.ToString("G5", CultureInfo.CurrentCulture);
+
+ ResizeAllSeriesData();
+ OrderAndColorSeries();
+ }
+
+ public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) {
+ if (IsDisposed
+ || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable)
+ || trainingMin.IsAlmost(trainingMax) || trainingMin > trainingMax || drawingSteps == 0)
+ return;
+
+ calculationPendingTimer.Start();
+
+ // cancel previous recalculate call
+ if (cancelCurrentRecalculateSource != null)
+ cancelCurrentRecalculateSource.Cancel();
+ cancelCurrentRecalculateSource = new CancellationTokenSource();
+ var cancellationToken = cancelCurrentRecalculateSource.Token;
+
+ // Update series
+ try {
+ var limits = await UpdateAllSeriesDataAsync(cancellationToken);
+
+ yMin = limits.Lower;
+ yMax = limits.Upper;
+ // Set y-axis
+ if (resetYAxis)
+ SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+
+ UpdateOutOfTrainingRangeStripLines();
+
+ calculationPendingTimer.Stop();
+ calculationPendingLabel.Visible = false;
+ if (updateOnFinish)
+ Update();
+ } catch (OperationCanceledException) { } catch (AggregateException ae) {
+ if (!ae.InnerExceptions.Any(e => e is OperationCanceledException))
+ throw;
+ }
+ }
+
+ public void UpdateTitlePosition() {
+ var title = chart.Titles[0];
+ var plotArea = InnerPlotPosition;
+
+ title.Visible = plotArea.Width != 0;
+
+ title.Position.X = plotArea.X + (plotArea.Width / 2);
+ }
+
+ private void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
+ if (minValue < maxValue) {
+ double axisMin, axisMax, axisInterval;
+ ChartUtil.CalculateAxisInterval(minValue, maxValue, ticks, out axisMin, out axisMax, out axisInterval);
+ axis.Minimum = fixedAxisMin ?? axisMin;
+ axis.Maximum = fixedAxisMax ?? axisMax;
+ axis.Interval = (axis.Maximum - axis.Minimum) / ticks;
+ }
+
+ try {
+ chart.ChartAreas[0].RecalculateAxesScale();
+ } catch (InvalidOperationException) {
+ // Can occur if eg. axis min == axis max
+ }
+ }
+
+ private void RecalculateTrainingLimits(bool initializeAxisRanges) {
+ trainingMin = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Min()).Max();
+ trainingMax = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Max()).Min();
+
+ if (initializeAxisRanges) {
+ double xmin, xmax, xinterval;
+ ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
+ FixedXAxisMin = xmin;
+ FixedXAxisMax = xmax;
+ }
+ }
+
+ private void RecalculateInternalDataset() {
+ if (sharedFixedVariables == null)
+ return;
+
+ // we expand the range in order to get nice tick intervals on the x axis
+ double xmin, xmax, xinterval;
+ ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
+
+ if (FixedXAxisMin.HasValue) xmin = FixedXAxisMin.Value;
+ if (FixedXAxisMax.HasValue) xmax = FixedXAxisMax.Value;
+ double step = (xmax - xmin) / drawingSteps;
+
+ var xvalues = new List();
+ for (int i = 0; i < drawingSteps; i++)
+ xvalues.Add(xmin + i * step);
+
+ if (sharedFixedVariables == null)
+ return;
+
+ var variables = sharedFixedVariables.VariableNames.ToList();
+ var values = new List();
+ foreach (var varName in variables) {
+ if (varName == FreeVariable) {
+ values.Add(xvalues);
+ } else if (sharedFixedVariables.VariableHasType(varName)) {
+ values.Add(Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(varName, 0), xvalues.Count).ToList());
+ } else if (sharedFixedVariables.VariableHasType(varName)) {
+ values.Add(Enumerable.Repeat(sharedFixedVariables.GetStringValue(varName, 0), xvalues.Count).ToList());
+ }
+ }
+
+ internalDataset = new ModifiableDataset(variables, values);
+ }
+
+ private Tuple CreateSeries(IRegressionSolution solution) {
+ var series = new Series {
+ ChartType = SeriesChartType.Line,
+ Name = solution.ProblemData.TargetVariable + " " + solutions.IndexOf(solution)
+ };
+ series.LegendText = series.Name;
+
+ var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
+ Series confidenceIntervalSeries = null;
+ if (confidenceBoundSolution != null) {
+ confidenceIntervalSeries = new Series {
+ ChartType = SeriesChartType.Range,
+ YValuesPerPoint = 2,
+ Name = "95% Conf. Interval " + series.Name,
+ IsVisibleInLegend = false
+ };
+ }
+ return Tuple.Create(series, confidenceIntervalSeries);
+ }
+
+ private void OrderAndColorSeries() {
+ chart.SuspendRepaint();
+
+ chart.Series.Clear();
+ // Add mean series for applying palette colors
+ foreach (var solution in solutions) {
+ chart.Series.Add(seriesCache[solution]);
+ }
+
+ chart.Palette = ChartColorPalette.BrightPastel;
+ chart.ApplyPaletteColors();
+ chart.Palette = ChartColorPalette.None;
+
+ // Add confidence interval series before its coresponding series for correct z index
+ foreach (var solution in solutions) {
+ Series ciSeries;
+ if (ciSeriesCache.TryGetValue(solution, out ciSeries)) {
+ var series = seriesCache[solution];
+ ciSeries.Color = Color.FromArgb(40, series.Color);
+ int idx = chart.Series.IndexOf(seriesCache[solution]);
+ chart.Series.Insert(idx, ciSeries);
+ }
+ }
+
+ chart.ResumeRepaint(true);
+ }
+
+ private async Task UpdateAllSeriesDataAsync(CancellationToken cancellationToken) {
+ var updateTasks = solutions.Select(solution => UpdateSeriesDataAsync(solution, cancellationToken));
+
+ double min = double.MaxValue, max = double.MinValue;
+ foreach (var update in updateTasks) {
+ var limit = await update;
+ if (limit.Lower < min) min = limit.Lower;
+ if (limit.Upper > max) max = limit.Upper;
+ }
+
+ return new DoubleLimit(min, max);
+ }
+
+ private Task UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) {
+ return Task.Run(() => {
+ var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
+ var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
+
+ double min = double.MaxValue, max = double.MinValue;
+
+ var series = seriesCache[solution];
+ for (int i = 0; i < xvalues.Count; i++) {
+ series.Points[i].SetValueXY(xvalues[i], yvalues[i]);
+ if (yvalues[i] < min) min = yvalues[i];
+ if (yvalues[i] > max) max = yvalues[i];
+ }
+ chart.Invalidate();
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var confidenceBoundSolution = solution as IConfidenceRegressionSolution;
+ if (confidenceBoundSolution != null) {
+ var confidenceIntervalSeries = ciSeriesCache[solution];
+ var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
+ for (int i = 0; i < xvalues.Count; i++) {
+ var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
+ var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
+ confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper);
+ if (lower < min) min = lower;
+ if (upper > max) max = upper;
+ }
+ chart.Invalidate();
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+ return new DoubleLimit(min, max);
+ }, cancellationToken);
+ }
+
+ private void ResizeAllSeriesData() {
+ if (internalDataset == null)
+ return;
+
+ var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
+ foreach (var solution in solutions)
+ ResizeSeriesData(solution, xvalues);
+ }
+ private void ResizeSeriesData(IRegressionSolution solution, IList xvalues = null) {
+ if (xvalues == null)
+ xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
+
+ var series = seriesCache[solution];
+ series.Points.SuspendUpdates();
+ series.Points.Clear();
+ for (int i = 0; i < xvalues.Count; i++)
+ series.Points.Add(new DataPoint(xvalues[i], 0.0));
+ series.Points.ResumeUpdates();
+
+ Series confidenceIntervalSeries;
+ if (ciSeriesCache.TryGetValue(solution, out confidenceIntervalSeries)) {
+ confidenceIntervalSeries.Points.SuspendUpdates();
+ confidenceIntervalSeries.Points.Clear();
+ for (int i = 0; i < xvalues.Count; i++)
+ confidenceIntervalSeries.Points.Add(new DataPoint(xvalues[i], new[] { -1.0, 1.0 }));
+ confidenceIntervalSeries.Points.ResumeUpdates();
+ }
+ }
+
+ public async Task AddSolutionAsync(IRegressionSolution solution) {
+ if (!SolutionsCompatible(solutions.Concat(new[] { solution })))
+ throw new ArgumentException("The solution is not compatible with the problem data.");
+ if (solutions.Contains(solution))
+ return;
+
+ solutions.Add(solution);
+ RecalculateTrainingLimits(true);
+
+ var series = CreateSeries(solution);
+ seriesCache.Add(solution, series.Item1);
+ if (series.Item2 != null)
+ ciSeriesCache.Add(solution, series.Item2);
+
+ ResizeSeriesData(solution);
+ OrderAndColorSeries();
+
+ await RecalculateAsync();
+ var args = new EventArgs(solution);
+ OnSolutionAdded(this, args);
+ }
+
+ public async Task RemoveSolutionAsync(IRegressionSolution solution) {
+ if (!solutions.Remove(solution))
+ return;
+
+ RecalculateTrainingLimits(true);
+
+ seriesCache.Remove(solution);
+ ciSeriesCache.Remove(solution);
+
+ await RecalculateAsync();
+ var args = new EventArgs(solution);
+ OnSolutionRemoved(this, args);
+ }
+
+ private static bool SolutionsCompatible(IEnumerable solutions) {
+ var refSolution = solutions.First();
+ var refSolVars = refSolution.ProblemData.Dataset.VariableNames;
+ foreach (var solution in solutions.Skip(1)) {
+ var variables1 = solution.ProblemData.Dataset.VariableNames;
+ if (!variables1.All(refSolVars.Contains))
+ return false;
+
+ foreach (var factorVar in variables1.Where(solution.ProblemData.Dataset.VariableHasType)) {
+ var distinctVals = refSolution.ProblemData.Dataset.GetStringValues(factorVar).Distinct();
+ if (solution.ProblemData.Dataset.GetStringValues(factorVar).Any(val => !distinctVals.Contains(val))) return false;
+ }
+ }
+ return true;
+ }
+
+ private void UpdateOutOfTrainingRangeStripLines() {
+ var axisX = chart.ChartAreas[0].AxisX;
+ var lowerStripLine = axisX.StripLines[0];
+ var upperStripLine = axisX.StripLines[1];
+
+ lowerStripLine.IntervalOffset = axisX.Minimum;
+ lowerStripLine.StripWidth = Math.Abs(trainingMin - axisX.Minimum);
+
+ upperStripLine.IntervalOffset = trainingMax;
+ upperStripLine.StripWidth = Math.Abs(axisX.Maximum - trainingMax);
+ }
+
+ #region Events
+ public event EventHandler> SolutionAdded;
+ public void OnSolutionAdded(object sender, EventArgs args) {
+ var added = SolutionAdded;
+ if (added == null) return;
+ added(sender, args);
+ }
+
+ public event EventHandler> SolutionRemoved;
+ public void OnSolutionRemoved(object sender, EventArgs args) {
+ var removed = SolutionRemoved;
+ if (removed == null) return;
+ removed(sender, args);
+ }
+
+ public event EventHandler VariableValueChanged;
+ public void OnVariableValueChanged(object sender, EventArgs args) {
+ var changed = VariableValueChanged;
+ if (changed == null) return;
+ changed(sender, args);
+ }
+
+ public event EventHandler ZoomChanged;
+ public void OnZoomChanged(object sender, EventArgs args) {
+ var changed = ZoomChanged;
+ if (changed == null) return;
+ changed(sender, args);
+ }
+
+ private void sharedFixedVariables_ItemChanged(object o, EventArgs e) {
+ if (o != sharedFixedVariables) return;
+ var variables = sharedFixedVariables.VariableNames.ToList();
+ var rowIndex = e.Value;
+ var columnIndex = e.Value2;
+
+ var variableName = variables[columnIndex];
+ if (variableName == FreeVariable) return;
+ if (internalDataset.VariableHasType(variableName)) {
+ var v = sharedFixedVariables.GetDoubleValue(variableName, rowIndex);
+ var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
+ internalDataset.ReplaceVariable(variableName, values);
+ } else if (internalDataset.VariableHasType(variableName)) {
+ var v = sharedFixedVariables.GetStringValue(variableName, rowIndex);
+ var values = new List(Enumerable.Repeat(v, internalDataset.Rows));
+ internalDataset.ReplaceVariable(variableName, values);
+ } else {
+ // unsupported type
+ throw new NotSupportedException();
+ }
+ }
+
+ private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
+ var step = (trainingMax - trainingMin) / drawingSteps;
+ double newLocation = step * (long)Math.Round(e.NewLocationX / step);
+ var axisX = chart.ChartAreas[0].AxisX;
+ if (newLocation >= axisX.Maximum)
+ newLocation = axisX.Maximum - step;
+ if (newLocation <= axisX.Minimum)
+ newLocation = axisX.Minimum + step;
+
+ e.NewLocationX = newLocation;
+
+ UpdateCursor();
+ }
+ private void chart_AnnotationPositionChanged(object sender, EventArgs e) {
+ UpdateCursor();
+ }
+ private void UpdateCursor() {
+ var x = VerticalLineAnnotation.X;
+ sharedFixedVariables.SetVariableValue(x, FreeVariable, 0);
+
+ if (ShowCursor) {
+ chart.Titles[0].Text = FreeVariable + " : " + x.ToString("G5", CultureInfo.CurrentCulture);
+ chart.Update();
+ }
+
+ OnVariableValueChanged(this, EventArgs.Empty);
+ }
+
+ private void chart_MouseMove(object sender, MouseEventArgs e) {
+ bool hitCursor = chart.HitTest(e.X, e.Y).ChartElementType == ChartElementType.Annotation;
+ chart.Cursor = hitCursor ? Cursors.VSplit : Cursors.Default;
+ }
+
+ private async void chart_DragDrop(object sender, DragEventArgs e) {
+ var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+ if (data != null) {
+ var solution = data as IRegressionSolution;
+ if (!solutions.Contains(solution))
+ await AddSolutionAsync(solution);
+ }
+ }
+ private void chart_DragEnter(object sender, DragEventArgs e) {
+ if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) return;
+ e.Effect = DragDropEffects.None;
+
+ var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
+ var regressionSolution = data as IRegressionSolution;
+ if (regressionSolution != null) {
+ e.Effect = DragDropEffects.Copy;
+ }
+ }
+
+ private void calculationPendingTimer_Tick(object sender, EventArgs e) {
+ calculationPendingLabel.Visible = true;
+ Update();
+ }
+
+ private void config_Click(object sender, EventArgs e) {
+ configurationDialog.ShowDialog(this);
+ }
+
+ private void chart_SelectionRangeChanged(object sender, CursorEventArgs e) {
+ OnZoomChanged(this, EventArgs.Empty);
+ }
+
+ private void chart_Resize(object sender, EventArgs e) {
+ UpdateTitlePosition();
+ }
+
+ private void chart_PostPaint(object sender, ChartPaintEventArgs e) {
+ if (ChartPostPaint != null)
+ ChartPostPaint(this, EventArgs.Empty);
+ }
+ #endregion
+ }
+}
+
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.Designer.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.Designer.cs (revision 15137)
@@ -0,0 +1,327 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ partial class PartialDependencePlotConfigurationDialog {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ this.xAxisGroupBox = new System.Windows.Forms.GroupBox();
+ this.maxXTextBox = new System.Windows.Forms.TextBox();
+ this.xAutomaticCheckBox = new System.Windows.Forms.CheckBox();
+ this.minXTextBox = new System.Windows.Forms.TextBox();
+ this.maxXLabel = new System.Windows.Forms.Label();
+ this.minXLabel = new System.Windows.Forms.Label();
+ this.yAxisGroupBox = new System.Windows.Forms.GroupBox();
+ this.maxYTextBox = new System.Windows.Forms.TextBox();
+ this.yAutomaticCheckBox = new System.Windows.Forms.CheckBox();
+ this.minYTextBox = new System.Windows.Forms.TextBox();
+ this.maxYLabel = new System.Windows.Forms.Label();
+ this.minYLabel = new System.Windows.Forms.Label();
+ this.miscGroupBox = new System.Windows.Forms.GroupBox();
+ this.StepsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.stepsLabel = new System.Windows.Forms.Label();
+ this.applyButton = new System.Windows.Forms.Button();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+ this.xAxisGroupBox.SuspendLayout();
+ this.yAxisGroupBox.SuspendLayout();
+ this.miscGroupBox.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.StepsNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+ this.SuspendLayout();
+ //
+ // xAxisGroupBox
+ //
+ this.xAxisGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.xAxisGroupBox.Controls.Add(this.maxXTextBox);
+ this.xAxisGroupBox.Controls.Add(this.xAutomaticCheckBox);
+ this.xAxisGroupBox.Controls.Add(this.minXTextBox);
+ this.xAxisGroupBox.Controls.Add(this.maxXLabel);
+ this.xAxisGroupBox.Controls.Add(this.minXLabel);
+ this.xAxisGroupBox.Location = new System.Drawing.Point(12, 12);
+ this.xAxisGroupBox.Name = "xAxisGroupBox";
+ this.xAxisGroupBox.Size = new System.Drawing.Size(234, 78);
+ this.xAxisGroupBox.TabIndex = 1;
+ this.xAxisGroupBox.TabStop = false;
+ this.xAxisGroupBox.Text = "X-Axis";
+ //
+ // maxXTextBox
+ //
+ this.maxXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.maxXTextBox.Location = new System.Drawing.Point(61, 45);
+ this.maxXTextBox.Name = "maxXTextBox";
+ this.maxXTextBox.Size = new System.Drawing.Size(167, 20);
+ this.maxXTextBox.TabIndex = 3;
+ this.maxXTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
+ this.maxXTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
+ //
+ // xAutomaticCheckBox
+ //
+ this.xAutomaticCheckBox.AutoSize = true;
+ this.xAutomaticCheckBox.Location = new System.Drawing.Point(48, -1);
+ this.xAutomaticCheckBox.Name = "xAutomaticCheckBox";
+ this.xAutomaticCheckBox.Size = new System.Drawing.Size(73, 17);
+ this.xAutomaticCheckBox.TabIndex = 1;
+ this.xAutomaticCheckBox.Text = "Automatic";
+ this.xAutomaticCheckBox.UseVisualStyleBackColor = true;
+ this.xAutomaticCheckBox.CheckedChanged += new System.EventHandler(this.automaticCheckBox_CheckedChanged);
+ //
+ // minXTextBox
+ //
+ this.minXTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.minXTextBox.Location = new System.Drawing.Point(61, 19);
+ this.minXTextBox.Name = "minXTextBox";
+ this.minXTextBox.Size = new System.Drawing.Size(167, 20);
+ this.minXTextBox.TabIndex = 2;
+ this.minXTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
+ this.minXTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
+ //
+ // maxXLabel
+ //
+ this.maxXLabel.AutoSize = true;
+ this.maxXLabel.Location = new System.Drawing.Point(7, 48);
+ this.maxXLabel.Name = "maxXLabel";
+ this.maxXLabel.Size = new System.Drawing.Size(27, 13);
+ this.maxXLabel.TabIndex = 1;
+ this.maxXLabel.Text = "Max";
+ //
+ // minXLabel
+ //
+ this.minXLabel.AutoSize = true;
+ this.minXLabel.Location = new System.Drawing.Point(7, 22);
+ this.minXLabel.Name = "minXLabel";
+ this.minXLabel.Size = new System.Drawing.Size(24, 13);
+ this.minXLabel.TabIndex = 0;
+ this.minXLabel.Text = "Min";
+ //
+ // yAxisGroupBox
+ //
+ this.yAxisGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.yAxisGroupBox.Controls.Add(this.maxYTextBox);
+ this.yAxisGroupBox.Controls.Add(this.yAutomaticCheckBox);
+ this.yAxisGroupBox.Controls.Add(this.minYTextBox);
+ this.yAxisGroupBox.Controls.Add(this.maxYLabel);
+ this.yAxisGroupBox.Controls.Add(this.minYLabel);
+ this.yAxisGroupBox.Location = new System.Drawing.Point(13, 96);
+ this.yAxisGroupBox.Name = "yAxisGroupBox";
+ this.yAxisGroupBox.Size = new System.Drawing.Size(234, 75);
+ this.yAxisGroupBox.TabIndex = 2;
+ this.yAxisGroupBox.TabStop = false;
+ this.yAxisGroupBox.Text = "Y-Axis";
+ //
+ // maxYTextBox
+ //
+ this.maxYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.maxYTextBox.Location = new System.Drawing.Point(61, 45);
+ this.maxYTextBox.Name = "maxYTextBox";
+ this.maxYTextBox.Size = new System.Drawing.Size(167, 20);
+ this.maxYTextBox.TabIndex = 3;
+ this.maxYTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
+ this.maxYTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
+ //
+ // yAutomaticCheckBox
+ //
+ this.yAutomaticCheckBox.AutoSize = true;
+ this.yAutomaticCheckBox.Location = new System.Drawing.Point(47, -1);
+ this.yAutomaticCheckBox.Name = "yAutomaticCheckBox";
+ this.yAutomaticCheckBox.Size = new System.Drawing.Size(73, 17);
+ this.yAutomaticCheckBox.TabIndex = 1;
+ this.yAutomaticCheckBox.Text = "Automatic";
+ this.yAutomaticCheckBox.UseVisualStyleBackColor = true;
+ this.yAutomaticCheckBox.CheckedChanged += new System.EventHandler(this.automaticCheckBox_CheckedChanged);
+ //
+ // minYTextBox
+ //
+ this.minYTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.minYTextBox.Location = new System.Drawing.Point(61, 19);
+ this.minYTextBox.Name = "minYTextBox";
+ this.minYTextBox.Size = new System.Drawing.Size(167, 20);
+ this.minYTextBox.TabIndex = 2;
+ this.minYTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.numberTextBox_Validating);
+ this.minYTextBox.Validated += new System.EventHandler(this.numberTextBox_Validated);
+ //
+ // maxYLabel
+ //
+ this.maxYLabel.AutoSize = true;
+ this.maxYLabel.Location = new System.Drawing.Point(7, 48);
+ this.maxYLabel.Name = "maxYLabel";
+ this.maxYLabel.Size = new System.Drawing.Size(27, 13);
+ this.maxYLabel.TabIndex = 1;
+ this.maxYLabel.Text = "Max";
+ //
+ // minYLabel
+ //
+ this.minYLabel.AutoSize = true;
+ this.minYLabel.Location = new System.Drawing.Point(7, 22);
+ this.minYLabel.Name = "minYLabel";
+ this.minYLabel.Size = new System.Drawing.Size(24, 13);
+ this.minYLabel.TabIndex = 0;
+ this.minYLabel.Text = "Min";
+ //
+ // miscGroupBox
+ //
+ this.miscGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.miscGroupBox.Controls.Add(this.StepsNumericUpDown);
+ this.miscGroupBox.Controls.Add(this.stepsLabel);
+ this.miscGroupBox.Location = new System.Drawing.Point(13, 177);
+ this.miscGroupBox.Name = "miscGroupBox";
+ this.miscGroupBox.Size = new System.Drawing.Size(233, 53);
+ this.miscGroupBox.TabIndex = 4;
+ this.miscGroupBox.TabStop = false;
+ //
+ // StepsNumericUpDown
+ //
+ this.StepsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.StepsNumericUpDown.Increment = new decimal(new int[] {
+ 50,
+ 0,
+ 0,
+ 0});
+ this.StepsNumericUpDown.Location = new System.Drawing.Point(61, 20);
+ this.StepsNumericUpDown.Maximum = new decimal(new int[] {
+ 100000,
+ 0,
+ 0,
+ 0});
+ this.StepsNumericUpDown.Name = "StepsNumericUpDown";
+ this.StepsNumericUpDown.Size = new System.Drawing.Size(166, 20);
+ this.StepsNumericUpDown.TabIndex = 4;
+ //
+ // stepsLabel
+ //
+ this.stepsLabel.AutoSize = true;
+ this.stepsLabel.Location = new System.Drawing.Point(6, 22);
+ this.stepsLabel.Name = "stepsLabel";
+ this.stepsLabel.Size = new System.Drawing.Size(34, 13);
+ this.stepsLabel.TabIndex = 1;
+ this.stepsLabel.Text = "Steps";
+ //
+ // applyButton
+ //
+ this.applyButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.applyButton.Location = new System.Drawing.Point(91, 239);
+ this.applyButton.Name = "applyButton";
+ this.applyButton.Size = new System.Drawing.Size(75, 23);
+ this.applyButton.TabIndex = 5;
+ this.applyButton.Text = "Apply";
+ this.applyButton.UseVisualStyleBackColor = true;
+ this.applyButton.Click += new System.EventHandler(this.okButton_Click);
+ //
+ // cancelButton
+ //
+ this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.cancelButton.Location = new System.Drawing.Point(172, 239);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(75, 23);
+ this.cancelButton.TabIndex = 6;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ //
+ // errorProvider
+ //
+ this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
+ this.errorProvider.ContainerControl = this;
+ //
+ // PartialDependencePlotConfigurationDialog
+ //
+ this.AcceptButton = this.applyButton;
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+ this.CancelButton = this.cancelButton;
+ this.ClientSize = new System.Drawing.Size(258, 272);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.applyButton);
+ this.Controls.Add(this.miscGroupBox);
+ this.Controls.Add(this.xAxisGroupBox);
+ this.Controls.Add(this.yAxisGroupBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "PartialDependencePlotConfigurationDialog";
+ this.ShowIcon = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.Text = "Configure Gradient Chart";
+ this.TopMost = true;
+ this.Shown += new System.EventHandler(this.PartialDependencePlotConfigurationDialog_Shown);
+ this.xAxisGroupBox.ResumeLayout(false);
+ this.xAxisGroupBox.PerformLayout();
+ this.yAxisGroupBox.ResumeLayout(false);
+ this.yAxisGroupBox.PerformLayout();
+ this.miscGroupBox.ResumeLayout(false);
+ this.miscGroupBox.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.StepsNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox xAxisGroupBox;
+ private System.Windows.Forms.TextBox maxXTextBox;
+ private System.Windows.Forms.TextBox minXTextBox;
+ private System.Windows.Forms.Label maxXLabel;
+ private System.Windows.Forms.Label minXLabel;
+ private System.Windows.Forms.GroupBox yAxisGroupBox;
+ private System.Windows.Forms.TextBox maxYTextBox;
+ private System.Windows.Forms.CheckBox yAutomaticCheckBox;
+ private System.Windows.Forms.TextBox minYTextBox;
+ private System.Windows.Forms.Label maxYLabel;
+ private System.Windows.Forms.Label minYLabel;
+ private System.Windows.Forms.GroupBox miscGroupBox;
+ private System.Windows.Forms.Label stepsLabel;
+ private System.Windows.Forms.Button applyButton;
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.CheckBox xAutomaticCheckBox;
+ private System.Windows.Forms.NumericUpDown StepsNumericUpDown;
+ private System.Windows.Forms.ErrorProvider errorProvider;
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/PartialDependencePlotConfigurationDialog.cs (revision 15137)
@@ -0,0 +1,121 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.ComponentModel;
+using System.Globalization;
+using System.Windows.Forms;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ public partial class PartialDependencePlotConfigurationDialog : Form {
+ private readonly PartialDependencePlot chart;
+
+ public PartialDependencePlotConfigurationDialog(PartialDependencePlot chart) {
+ this.chart = chart;
+ InitializeComponent();
+ }
+
+ private void PartialDependencePlotConfigurationDialog_Shown(object sender, EventArgs e) {
+ if (chart.FixedXAxisMin.HasValue && chart.FixedXAxisMax.HasValue) {
+ xAutomaticCheckBox.Checked = false;
+ minXTextBox.Text = chart.FixedXAxisMin.Value.ToString(CultureInfo.CurrentUICulture);
+ maxXTextBox.Text = chart.FixedXAxisMax.Value.ToString(CultureInfo.CurrentUICulture);
+ } else xAutomaticCheckBox.Checked = true;
+ if (chart.FixedYAxisMin.HasValue && chart.FixedYAxisMax.HasValue) {
+ yAutomaticCheckBox.Checked = false;
+ minYTextBox.Text = chart.FixedYAxisMin.Value.ToString(CultureInfo.CurrentUICulture);
+ maxYTextBox.Text = chart.FixedYAxisMax.Value.ToString(CultureInfo.CurrentUICulture);
+ } else yAutomaticCheckBox.Checked = true;
+ StepsNumericUpDown.Value = chart.DrawingSteps;
+ }
+
+ private async void okButton_Click(object sender, System.EventArgs e) {
+ try {
+ Enabled = false;
+ chart.SuspendRepaint();
+ if (xAutomaticCheckBox.Checked) {
+ chart.FixedXAxisMin = null;
+ chart.FixedXAxisMax = null;
+ } else {
+ var min = double.Parse(minXTextBox.Text, CultureInfo.CurrentUICulture);
+ var max = double.Parse(maxXTextBox.Text, CultureInfo.CurrentUICulture);
+ chart.FixedXAxisMin = min;
+ chart.FixedXAxisMax = max;
+ }
+
+ if (yAutomaticCheckBox.Checked) {
+ chart.FixedYAxisMin = null;
+ chart.FixedYAxisMax = null;
+ } else {
+ var min = double.Parse(minYTextBox.Text, CultureInfo.CurrentUICulture);
+ var max = double.Parse(maxYTextBox.Text, CultureInfo.CurrentUICulture);
+ chart.FixedYAxisMin = min;
+ chart.FixedYAxisMax = max;
+ }
+
+ chart.DrawingSteps = (int)StepsNumericUpDown.Value;
+
+ await chart.RecalculateAsync(resetYAxis: false);
+
+ Close();
+ }
+ catch (FormatException) {
+ MessageBox.Show(this, "Illegal number format", "Wrong format", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ finally {
+ Enabled = true;
+ chart.ResumeRepaint(true);
+ }
+ }
+
+ private void automaticCheckBox_CheckedChanged(object sender, EventArgs e) {
+ minXTextBox.Enabled = !xAutomaticCheckBox.Checked;
+ maxXTextBox.Enabled = !xAutomaticCheckBox.Checked;
+
+ minYTextBox.Enabled = !yAutomaticCheckBox.Checked;
+ maxYTextBox.Enabled = !yAutomaticCheckBox.Checked;
+ }
+
+ private void numberTextBox_Validating(object sender, CancelEventArgs e) {
+ var textBox = sender as TextBox;
+ if (textBox != null) {
+ double number;
+ if (!double.TryParse(textBox.Text, NumberStyles.Any, CultureInfo.CurrentUICulture, out number)) {
+ e.Cancel = true;
+ applyButton.Enabled = false;
+ errorProvider.SetIconAlignment(textBox, ErrorIconAlignment.MiddleLeft);
+ errorProvider.SetIconPadding(textBox, 2);
+ errorProvider.SetError(textBox, "Illegal number format");
+ textBox.SelectAll();
+ }
+ }
+ }
+
+ private void numberTextBox_Validated(object sender, EventArgs e) {
+ var textBox = sender as TextBox;
+ if (textBox != null) {
+ errorProvider.SetError(textBox, string.Empty);
+ applyButton.Enabled = true;
+ }
+ }
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj (revision 15136)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/HeuristicLab.Problems.DataAnalysis.Views-3.4.csproj (revision 15137)
@@ -132,9 +132,21 @@
DensityTrackbar.cs
-
- UserControl
-
-
- FactorGradientChart.cs
+
+ UserControl
+
+
+ FactorPartialDependencePlot.cs
+
+
+ UserControl
+
+
+ PartialDependencePlot.cs
+
+
+ Form
+
+
+ PartialDependencePlotConfigurationDialog.cs
@@ -201,18 +213,6 @@
FeatureCorrelationView.cs
-
- UserControl
-
-
- GradientChart.cs
-
-
- Form
-
-
- GradientChartConfigurationDialog.cs
-
-
+
@@ -260,4 +260,10 @@
RegressionSolutionLineChartViewBase.cs
+
+ UserControl
+
+
+ RegressionSolutionPartialDependencePlotView.cs
+
UserControl
@@ -277,10 +283,4 @@
RegressionSolutionGradientView.cs
-
-
- UserControl
-
-
- RegressionSolutionTargetResponseGradientView.cs
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Interfaces/IGradientChart.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Interfaces/IGradientChart.cs (revision 15136)
+++ (revision )
@@ -1,37 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Threading.Tasks;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- public interface IGradientChart {
- Task RecalculateAsync(bool updateOnFinish, bool resetYAxis);
- double YMin { get; }
- double YMax { get; }
- double? FixedYAxisMin { get; set; }
- double? FixedYAxisMax { get; set; }
- string YAxisTitle { get; set; }
- Task AddSolutionAsync(IRegressionSolution solution);
- Task RemoveSolutionAsync(IRegressionSolution solution);
- bool IsZoomed { get; }
- void Refresh();
- }
-}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Interfaces/IPartialDependencePlot.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Interfaces/IPartialDependencePlot.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Interfaces/IPartialDependencePlot.cs (revision 15137)
@@ -0,0 +1,37 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Threading.Tasks;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ public interface IPartialDependencePlot {
+ Task RecalculateAsync(bool updateOnFinish, bool resetYAxis);
+ double YMin { get; }
+ double YMax { get; }
+ double? FixedYAxisMin { get; set; }
+ double? FixedYAxisMax { get; set; }
+ string YAxisTitle { get; set; }
+ Task AddSolutionAsync(IRegressionSolution solution);
+ Task RemoveSolutionAsync(IRegressionSolution solution);
+ bool IsZoomed { get; }
+ void Refresh();
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.Designer.cs (revision 15136)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.Designer.cs (revision 15137)
@@ -46,5 +46,5 @@
private void InitializeComponent() {
this.splitContainer = new System.Windows.Forms.SplitContainer();
- this.gradientChart = new HeuristicLab.Problems.DataAnalysis.Views.GradientChart();
+ this._partialDependencePlot = new HeuristicLab.Problems.DataAnalysis.Views.PartialDependencePlot();
this.configurationGroupBox = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
@@ -65,5 +65,5 @@
// splitContainer.Panel1
//
- this.splitContainer.Panel1.Controls.Add(this.gradientChart);
+ this.splitContainer.Panel1.Controls.Add(this._partialDependencePlot);
//
// splitContainer.Panel2
@@ -74,16 +74,16 @@
this.splitContainer.TabIndex = 1;
//
- // gradientChart
+ // _partialDependencePlot
//
- this.gradientChart.Dock = System.Windows.Forms.DockStyle.Fill;
- this.gradientChart.DrawingSteps = 1000;
- this.gradientChart.Location = new System.Drawing.Point(0, 0);
- this.gradientChart.Name = "gradientChart";
- this.gradientChart.ShowCursor = false;
- this.gradientChart.ShowLegend = false;
- this.gradientChart.Size = new System.Drawing.Size(715, 376);
- this.gradientChart.TabIndex = 0;
- this.gradientChart.XAxisTicks = 10;
- this.gradientChart.YAxisTicks = 5;
+ this._partialDependencePlot.Dock = System.Windows.Forms.DockStyle.Fill;
+ this._partialDependencePlot.DrawingSteps = 1000;
+ this._partialDependencePlot.Location = new System.Drawing.Point(0, 0);
+ this._partialDependencePlot.Name = "_partialDependencePlot";
+ this._partialDependencePlot.ShowCursor = false;
+ this._partialDependencePlot.ShowLegend = false;
+ this._partialDependencePlot.Size = new System.Drawing.Size(715, 376);
+ this._partialDependencePlot.TabIndex = 0;
+ this._partialDependencePlot.XAxisTicks = 10;
+ this._partialDependencePlot.YAxisTicks = 5;
//
// configurationGroupBox
@@ -131,5 +131,5 @@
private System.Windows.Forms.GroupBox configurationGroupBox;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
- private Problems.DataAnalysis.Views.GradientChart gradientChart;
+ private Problems.DataAnalysis.Views.PartialDependencePlot _partialDependencePlot;
}
}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.cs (revision 15136)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionGradientView.cs (revision 15137)
@@ -94,6 +94,6 @@
sharedFixedVariables = new ModifiableDataset(variableNames, newTrackbars.Select(tb => new List(1) { (double)tb.Value }));
- gradientChart.Configure(new[] { Content }, sharedFixedVariables, variableNames.First(), DrawingSteps);
- await gradientChart.RecalculateAsync();
+ _partialDependencePlot.Configure(new[] { Content }, sharedFixedVariables, variableNames.First(), DrawingSteps);
+ await _partialDependencePlot.RecalculateAsync();
// Add to table and observable lists
@@ -122,6 +122,6 @@
double axisMin, axisMax, axisInterval;
ChartUtil.CalculateAxisInterval(min - scale * range, max + scale * range, 5, out axisMin, out axisMax, out axisInterval);
- gradientChart.FixedYAxisMin = axisMin;
- gradientChart.FixedYAxisMax = axisMax;
+ _partialDependencePlot.FixedYAxisMin = axisMin;
+ _partialDependencePlot.FixedYAxisMax = axisMax;
trackbars.First().Checked = true;
@@ -168,6 +168,6 @@
foreach (var tb in trackbars.Except(new[] { trackBar }))
tb.Checked = false;
- gradientChart.FreeVariable = variableNames[trackbars.IndexOf(trackBar)];
- await gradientChart.RecalculateAsync();
+ _partialDependencePlot.FreeVariable = variableNames[trackbars.IndexOf(trackBar)];
+ await _partialDependencePlot.RecalculateAsync();
}
@@ -175,7 +175,7 @@
var trackBar = sender as DensityTrackbar;
if (trackBar == null || !trackBar.Checked) return;
- gradientChart.FixedXAxisMin = trackBar.Limits.Lower;
- gradientChart.FixedXAxisMax = trackBar.Limits.Upper;
- await gradientChart.RecalculateAsync();
+ _partialDependencePlot.FixedXAxisMin = trackBar.Limits.Lower;
+ _partialDependencePlot.FixedXAxisMax = trackBar.Limits.Upper;
+ await _partialDependencePlot.RecalculateAsync();
}
@@ -184,5 +184,5 @@
if (trackBar == null) return;
sharedFixedVariables.SetVariableValue((double)trackBar.Value, variableNames[trackbars.IndexOf(trackBar)], 0);
- await gradientChart.RecalculateAsync();
+ await _partialDependencePlot.RecalculateAsync();
}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.Designer.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.Designer.cs (revision 15137)
@@ -0,0 +1,271 @@
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ partial class RegressionSolutionPartialDependencePlotView {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ this.variableListView = new System.Windows.Forms.ListView();
+ this.partialDependencePlotTableLayout = new System.Windows.Forms.TableLayoutPanel();
+ this.yAxisConfigGroupBox = new System.Windows.Forms.GroupBox();
+ this.limitView = new HeuristicLab.Problems.DataAnalysis.Views.DoubleLimitView();
+ this.automaticYAxisCheckBox = new System.Windows.Forms.CheckBox();
+ this.densityGroupBox = new System.Windows.Forms.GroupBox();
+ this.columnsLabel = new System.Windows.Forms.Label();
+ this.densityComboBox = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.configSplitContainer = new System.Windows.Forms.SplitContainer();
+ this.variableGroupBox = new System.Windows.Forms.GroupBox();
+ this.scrollPanel = new System.Windows.Forms.Panel();
+ this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+ this.columnsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.yAxisConfigGroupBox.SuspendLayout();
+ this.densityGroupBox.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).BeginInit();
+ this.configSplitContainer.Panel1.SuspendLayout();
+ this.configSplitContainer.Panel2.SuspendLayout();
+ this.configSplitContainer.SuspendLayout();
+ this.variableGroupBox.SuspendLayout();
+ this.scrollPanel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).BeginInit();
+ this.SuspendLayout();
+ //
+ // variableListView
+ //
+ this.variableListView.CheckBoxes = true;
+ this.variableListView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.variableListView.Location = new System.Drawing.Point(3, 16);
+ this.variableListView.Name = "variableListView";
+ this.variableListView.Size = new System.Drawing.Size(163, 478);
+ this.variableListView.TabIndex = 0;
+ this.variableListView.UseCompatibleStateImageBehavior = false;
+ this.variableListView.View = System.Windows.Forms.View.List;
+ this.variableListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.variableListView_ItemChecked);
+ //
+ // partialDependencePlotTableLayout
+ //
+ this.partialDependencePlotTableLayout.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.partialDependencePlotTableLayout.AutoSize = true;
+ this.partialDependencePlotTableLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.partialDependencePlotTableLayout.ColumnCount = 1;
+ this.partialDependencePlotTableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.partialDependencePlotTableLayout.Location = new System.Drawing.Point(0, 0);
+ this.partialDependencePlotTableLayout.Name = "partialDependencePlotTableLayout";
+ this.partialDependencePlotTableLayout.RowCount = 1;
+ this.partialDependencePlotTableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.partialDependencePlotTableLayout.Size = new System.Drawing.Size(542, 0);
+ this.partialDependencePlotTableLayout.TabIndex = 2;
+ //
+ // yAxisConfigGroupBox
+ //
+ this.yAxisConfigGroupBox.Controls.Add(this.limitView);
+ this.yAxisConfigGroupBox.Controls.Add(this.automaticYAxisCheckBox);
+ this.yAxisConfigGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
+ this.yAxisConfigGroupBox.Location = new System.Drawing.Point(0, 0);
+ this.yAxisConfigGroupBox.Name = "yAxisConfigGroupBox";
+ this.yAxisConfigGroupBox.Size = new System.Drawing.Size(169, 77);
+ this.yAxisConfigGroupBox.TabIndex = 2;
+ this.yAxisConfigGroupBox.TabStop = false;
+ this.yAxisConfigGroupBox.Text = "Y-Axis";
+ //
+ // limitView
+ //
+ this.limitView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.limitView.Caption = "DoubleLimit View";
+ this.limitView.Content = null;
+ this.limitView.Location = new System.Drawing.Point(6, 20);
+ this.limitView.Name = "limitView";
+ this.limitView.ReadOnly = false;
+ this.limitView.Size = new System.Drawing.Size(157, 47);
+ this.limitView.TabIndex = 1;
+ //
+ // automaticYAxisCheckBox
+ //
+ this.automaticYAxisCheckBox.AutoSize = true;
+ this.automaticYAxisCheckBox.Location = new System.Drawing.Point(49, -1);
+ this.automaticYAxisCheckBox.Name = "automaticYAxisCheckBox";
+ this.automaticYAxisCheckBox.Size = new System.Drawing.Size(73, 17);
+ this.automaticYAxisCheckBox.TabIndex = 0;
+ this.automaticYAxisCheckBox.Text = "Automatic";
+ this.automaticYAxisCheckBox.UseVisualStyleBackColor = true;
+ this.automaticYAxisCheckBox.CheckedChanged += new System.EventHandler(this.automaticYAxisCheckBox_CheckedChanged);
+ //
+ // densityGroupBox
+ //
+ this.densityGroupBox.Controls.Add(this.columnsNumericUpDown);
+ this.densityGroupBox.Controls.Add(this.columnsLabel);
+ this.densityGroupBox.Controls.Add(this.densityComboBox);
+ this.densityGroupBox.Controls.Add(this.label1);
+ this.densityGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
+ this.densityGroupBox.Location = new System.Drawing.Point(0, 77);
+ this.densityGroupBox.Name = "densityGroupBox";
+ this.densityGroupBox.Size = new System.Drawing.Size(169, 74);
+ this.densityGroupBox.TabIndex = 3;
+ this.densityGroupBox.TabStop = false;
+ this.densityGroupBox.Text = "Settings";
+ //
+ // columnsLabel
+ //
+ this.columnsLabel.AutoSize = true;
+ this.columnsLabel.Location = new System.Drawing.Point(7, 49);
+ this.columnsLabel.Name = "columnsLabel";
+ this.columnsLabel.Size = new System.Drawing.Size(50, 13);
+ this.columnsLabel.TabIndex = 0;
+ this.columnsLabel.Text = "Columns:";
+ //
+ // densityComboBox
+ //
+ this.densityComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.densityComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.densityComboBox.FormattingEnabled = true;
+ this.densityComboBox.Items.AddRange(new object[] {
+ "None",
+ "Training",
+ "Test",
+ "All"});
+ this.densityComboBox.Location = new System.Drawing.Point(66, 19);
+ this.densityComboBox.Name = "densityComboBox";
+ this.densityComboBox.Size = new System.Drawing.Size(94, 21);
+ this.densityComboBox.TabIndex = 0;
+ this.densityComboBox.SelectedIndexChanged += new System.EventHandler(this.densityComboBox_SelectedIndexChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(7, 22);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(45, 13);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Density:";
+ //
+ // configSplitContainer
+ //
+ this.configSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.configSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+ this.configSplitContainer.Location = new System.Drawing.Point(0, 0);
+ this.configSplitContainer.Name = "configSplitContainer";
+ //
+ // configSplitContainer.Panel1
+ //
+ this.configSplitContainer.Panel1.Controls.Add(this.variableGroupBox);
+ this.configSplitContainer.Panel1.Controls.Add(this.densityGroupBox);
+ this.configSplitContainer.Panel1.Controls.Add(this.yAxisConfigGroupBox);
+ //
+ // configSplitContainer.Panel2
+ //
+ this.configSplitContainer.Panel2.Controls.Add(this.scrollPanel);
+ this.configSplitContainer.Size = new System.Drawing.Size(715, 648);
+ this.configSplitContainer.SplitterDistance = 169;
+ this.configSplitContainer.TabIndex = 0;
+ this.configSplitContainer.TabStop = false;
+ //
+ // variableGroupBox
+ //
+ this.variableGroupBox.Controls.Add(this.variableListView);
+ this.variableGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.variableGroupBox.Location = new System.Drawing.Point(0, 151);
+ this.variableGroupBox.Name = "variableGroupBox";
+ this.variableGroupBox.Size = new System.Drawing.Size(169, 497);
+ this.variableGroupBox.TabIndex = 1;
+ this.variableGroupBox.TabStop = false;
+ this.variableGroupBox.Text = "Variables";
+ //
+ // scrollPanel
+ //
+ this.scrollPanel.Controls.Add(this.partialDependencePlotTableLayout);
+ this.scrollPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.scrollPanel.Location = new System.Drawing.Point(0, 0);
+ this.scrollPanel.Name = "scrollPanel";
+ this.scrollPanel.Size = new System.Drawing.Size(542, 648);
+ this.scrollPanel.TabIndex = 0;
+ //
+ // errorProvider
+ //
+ this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
+ this.errorProvider.ContainerControl = this;
+ //
+ // columnsNumericUpDown
+ //
+ this.columnsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.columnsNumericUpDown.Location = new System.Drawing.Point(66, 46);
+ this.columnsNumericUpDown.Minimum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.columnsNumericUpDown.Name = "columnsNumericUpDown";
+ this.columnsNumericUpDown.Size = new System.Drawing.Size(94, 20);
+ this.columnsNumericUpDown.TabIndex = 1;
+ this.columnsNumericUpDown.Value = new decimal(new int[] {
+ 4,
+ 0,
+ 0,
+ 0});
+ this.columnsNumericUpDown.ValueChanged += new System.EventHandler(this.columnsNumericUpDown_ValueChanged);
+ //
+ // RegressionSolutionPartialDependencePlotView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.configSplitContainer);
+ this.Name = "RegressionSolutionPartialDependencePlotView";
+ this.Size = new System.Drawing.Size(715, 648);
+ this.yAxisConfigGroupBox.ResumeLayout(false);
+ this.yAxisConfigGroupBox.PerformLayout();
+ this.densityGroupBox.ResumeLayout(false);
+ this.densityGroupBox.PerformLayout();
+ this.configSplitContainer.Panel1.ResumeLayout(false);
+ this.configSplitContainer.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).EndInit();
+ this.configSplitContainer.ResumeLayout(false);
+ this.variableGroupBox.ResumeLayout(false);
+ this.scrollPanel.ResumeLayout(false);
+ this.scrollPanel.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ListView variableListView;
+ private System.Windows.Forms.TableLayoutPanel partialDependencePlotTableLayout;
+ private System.Windows.Forms.GroupBox yAxisConfigGroupBox;
+ private System.Windows.Forms.CheckBox automaticYAxisCheckBox;
+ private DoubleLimitView limitView;
+ private System.Windows.Forms.GroupBox densityGroupBox;
+ private System.Windows.Forms.ComboBox densityComboBox;
+ private System.Windows.Forms.SplitContainer configSplitContainer;
+ private System.Windows.Forms.GroupBox variableGroupBox;
+ private System.Windows.Forms.Panel scrollPanel;
+ private System.Windows.Forms.Label columnsLabel;
+ private System.Windows.Forms.ErrorProvider errorProvider;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.NumericUpDown columnsNumericUpDown;
+ }
+}
Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.cs (revision 15137)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionPartialDependencePlotView.cs (revision 15137)
@@ -0,0 +1,567 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using HeuristicLab.Common;
+using HeuristicLab.MainForm;
+using HeuristicLab.Visualization.ChartControlsExtensions;
+
+namespace HeuristicLab.Problems.DataAnalysis.Views {
+ [View("Partial Dependence Plots")]
+ [Content(typeof(IRegressionSolution))]
+ public partial class RegressionSolutionPartialDependencePlotView : DataAnalysisSolutionEvaluationView {
+ private readonly Dictionary partialDependencePlots;
+ private readonly Dictionary densityCharts;
+ private readonly Dictionary groupingPanels;
+ private ModifiableDataset sharedFixedVariables;
+
+ private const int Points = 200;
+ private int MaxColumns = 4;
+
+ private IEnumerable VisibleVariables {
+ get {
+ foreach (ListViewItem item in variableListView.CheckedItems)
+ yield return item.Text;
+ }
+ }
+ private IEnumerable VisiblePartialDependencePlots {
+ get { return VisibleVariables.Select(v => partialDependencePlots[v]); }
+ }
+ private IEnumerable VisibleDensityCharts {
+ get { return VisibleVariables.Select(v => densityCharts[v]); }
+ }
+ private IEnumerable VisibleChartsPanels {
+ get { return VisibleVariables.Select(v => groupingPanels[v]); }
+ }
+
+ public RegressionSolutionPartialDependencePlotView() {
+ InitializeComponent();
+ partialDependencePlots = new Dictionary();
+ densityCharts = new Dictionary();
+ groupingPanels = new Dictionary();
+
+ limitView.Content = new DoubleLimit(0, 1);
+ limitView.Content.ValueChanged += limit_ValueChanged;
+
+ densityComboBox.SelectedIndex = 1; // select Training
+
+ // Avoid additional horizontal scrollbar
+ var vertScrollWidth = SystemInformation.VerticalScrollBarWidth;
+ scrollPanel.Padding = new Padding(0, 0, vertScrollWidth, 0);
+ scrollPanel.AutoScroll = true;
+ }
+
+ public new IRegressionSolution Content {
+ get { return (IRegressionSolution)base.Content; }
+ set { base.Content = value; }
+ }
+
+ protected override void RegisterContentEvents() {
+ base.RegisterContentEvents();
+ Content.ModelChanged += solution_ModelChanged;
+ }
+
+ protected override void DeregisterContentEvents() {
+ Content.ModelChanged -= solution_ModelChanged;
+ base.DeregisterContentEvents();
+ }
+
+ protected override void OnContentChanged() {
+ base.OnContentChanged();
+ if (Content == null) return;
+ var problemData = Content.ProblemData;
+
+ // Init Y-axis range
+ double min = double.MaxValue, max = double.MinValue;
+ var trainingTarget = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
+ foreach (var t in trainingTarget) {
+ if (t < min) min = t;
+ if (t > max) max = t;
+ }
+ double range = max - min;
+ const double scale = 1.0 / 3.0;
+ double axisMin, axisMax, axisInterval;
+ ChartUtil.CalculateAxisInterval(min - scale * range, max + scale * range, 5, out axisMin, out axisMax, out axisInterval);
+ automaticYAxisCheckBox.Checked = false;
+ limitView.ReadOnly = false;
+ limitView.Content.Lower = axisMin;
+ limitView.Content.Upper = axisMax;
+
+ // create dataset of problemData input variables and model input variables
+ // necessary workaround to have the variables in the occuring order
+ var inputvariables =
+ new HashSet(Content.ProblemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
+ var allowedInputVariables =
+ Content.ProblemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
+
+
+ var doubleVariables = allowedInputVariables.Where(problemData.Dataset.VariableHasType);
+ var doubleVariableValues = (IEnumerable)doubleVariables.Select(x => new List { problemData.Dataset.GetDoubleValues(x, problemData.TrainingIndices).Median() });
+
+ var factorVariables = allowedInputVariables.Where(problemData.Dataset.VariableHasType);
+ var factorVariableValues = (IEnumerable)factorVariables.Select(x => new List {
+ problemData.Dataset.GetStringValues(x, problemData.TrainingIndices)
+ .GroupBy(val => val).OrderByDescending(g => g.Count()).First().Key // most frequent value
+ });
+
+ if (sharedFixedVariables != null)
+ sharedFixedVariables.ItemChanged -= SharedFixedVariables_ItemChanged;
+
+ sharedFixedVariables = new ModifiableDataset(doubleVariables.Concat(factorVariables), doubleVariableValues.Concat(factorVariableValues));
+
+
+ // create controls
+ partialDependencePlots.Clear();
+ densityCharts.Clear();
+ groupingPanels.Clear();
+ foreach (var variableName in doubleVariables) {
+ var plot = CreatePartialDependencePlot(variableName, sharedFixedVariables);
+ partialDependencePlots.Add(variableName, plot);
+
+ var densityChart = new DensityChart() {
+ Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right,
+ Margin = Padding.Empty,
+ Height = 12,
+ Visible = false,
+ Top = (int)(plot.Height * 0.1),
+ };
+ densityCharts.Add(variableName, densityChart);
+
+ plot.ZoomChanged += (o, e) => {
+ var pdp = (PartialDependencePlot)o;
+ var density = densityCharts[pdp.FreeVariable];
+ density.Visible = densityComboBox.SelectedIndex != 0 && !pdp.IsZoomed;
+ if (density.Visible)
+ UpdateDensityChart(density, pdp.FreeVariable);
+ };
+ plot.SizeChanged += (o, e) => {
+ var pdp = (PartialDependencePlot)o;
+ var density = densityCharts[pdp.FreeVariable];
+ density.Top = (int)(pdp.Height * 0.1);
+ };
+
+ // Initially, the inner plot areas are not initialized for hidden charts (scollpanel, ...)
+ // This event handler listens for the paint event once (where everything is already initialized) to do some manual layouting.
+ plot.ChartPostPaint += OnPartialDependencePlotPostPaint;
+
+ var panel = new Panel() {
+ Dock = DockStyle.Fill,
+ Margin = Padding.Empty,
+ BackColor = Color.White
+ };
+
+ panel.Controls.Add(densityChart);
+ panel.Controls.Add(plot);
+ groupingPanels.Add(variableName, panel);
+ }
+ foreach (var variableName in factorVariables) {
+ var plot = CreateFactorPartialDependencePlot(variableName, sharedFixedVariables);
+ partialDependencePlots.Add(variableName, plot);
+
+ var densityChart = new DensityChart() {
+ Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right,
+ Margin = Padding.Empty,
+ Height = 12,
+ Visible = false,
+ Top = (int)(plot.Height * 0.1),
+ };
+ densityCharts.Add(variableName, densityChart);
+ plot.ZoomChanged += (o, e) => {
+ var pdp = (FactorPartialDependencePlot)o;
+ var density = densityCharts[pdp.FreeVariable];
+ density.Visible = densityComboBox.SelectedIndex != 0 && !pdp.IsZoomed;
+ if (density.Visible)
+ UpdateDensityChart(density, pdp.FreeVariable);
+ };
+ plot.SizeChanged += (o, e) => {
+ var pdp = (FactorPartialDependencePlot)o;
+ var density = densityCharts[pdp.FreeVariable];
+ density.Top = (int)(pdp.Height * 0.1);
+ };
+
+ // Initially, the inner plot areas are not initialized for hidden charts (scollpanel, ...)
+ // This event handler listens for the paint event once (where everything is already initialized) to do some manual layouting.
+ plot.ChartPostPaint += OnFactorPartialDependencePlotPostPaint;
+
+ var panel = new Panel() {
+ Dock = DockStyle.Fill,
+ Margin = Padding.Empty,
+ BackColor = Color.White
+ };
+
+ panel.Controls.Add(densityChart);
+ panel.Controls.Add(plot);
+ groupingPanels.Add(variableName, panel);
+ }
+ // update variable list
+ variableListView.ItemChecked -= variableListView_ItemChecked;
+ variableListView.Items.Clear();
+ foreach (var variable in allowedInputVariables)
+ variableListView.Items.Add(key: variable, text: variable, imageIndex: 0);
+
+ foreach (var variable in Content.Model.VariablesUsedForPrediction)
+ variableListView.Items[variable].Checked = true;
+ variableListView.ItemChecked += variableListView_ItemChecked;
+
+ sharedFixedVariables.ItemChanged += SharedFixedVariables_ItemChanged;
+
+ RecalculateAndRelayoutCharts();
+ }
+
+ private void SharedFixedVariables_ItemChanged(object sender, EventArgs e) {
+ double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single();
+ string title = Content.ProblemData.TargetVariable + ": " + yValue.ToString("G5", CultureInfo.CurrentCulture);
+ foreach (var chart in partialDependencePlots.Values) {
+ if (!string.IsNullOrEmpty(chart.YAxisTitle)) { // only show title for first column in grid
+ chart.YAxisTitle = title;
+ }
+ }
+ }
+
+
+ private void OnPartialDependencePlotPostPaint(object o, EventArgs e) {
+ var plot = (PartialDependencePlot)o;
+ var density = densityCharts[plot.FreeVariable];
+
+ density.Width = plot.Width;
+
+ var gcPlotPosition = plot.InnerPlotPosition;
+ density.Left = (int)(gcPlotPosition.X / 100.0 * plot.Width);
+ density.Width = (int)(gcPlotPosition.Width / 100.0 * plot.Width);
+ plot.UpdateTitlePosition();
+
+ // removed after succesful layouting due to performance reasons
+ if (gcPlotPosition.Width != 0)
+ plot.ChartPostPaint -= OnPartialDependencePlotPostPaint;
+ }
+
+ private void OnFactorPartialDependencePlotPostPaint(object o, EventArgs e) {
+ var plot = (FactorPartialDependencePlot)o;
+ var density = densityCharts[plot.FreeVariable];
+
+ density.Width = plot.Width;
+
+ var gcPlotPosition = plot.InnerPlotPosition;
+ density.Left = (int)(gcPlotPosition.X / 100.0 * plot.Width);
+ density.Width = (int)(gcPlotPosition.Width / 100.0 * plot.Width);
+ plot.UpdateTitlePosition();
+
+ // removed after succesful layouting due to performance reasons
+ if (gcPlotPosition.Width != 0)
+ plot.ChartPostPaint -= OnFactorPartialDependencePlotPostPaint;
+ }
+
+ private async void RecalculateAndRelayoutCharts() {
+ foreach (var variable in VisibleVariables) {
+ var plot = partialDependencePlots[variable];
+ await plot.RecalculateAsync(false, false);
+ }
+ partialDependencePlotTableLayout.SuspendLayout();
+ SetupYAxis();
+ ReOrderControls();
+ SetStyles();
+ partialDependencePlotTableLayout.ResumeLayout();
+ partialDependencePlotTableLayout.Refresh();
+ foreach (var variable in VisibleVariables) {
+ DensityChart densityChart;
+ if (densityCharts.TryGetValue(variable, out densityChart)) {
+ UpdateDensityChart(densityChart, variable);
+ }
+ }
+ }
+ private PartialDependencePlot CreatePartialDependencePlot(string variableName, ModifiableDataset sharedFixedVariables) {
+ var plot = new PartialDependencePlot {
+ Dock = DockStyle.Fill,
+ Margin = Padding.Empty,
+ ShowLegend = false,
+ ShowCursor = true,
+ ShowConfigButton = false,
+ YAxisTicks = 5,
+ };
+ plot.VariableValueChanged += async (o, e) => {
+ var recalculations = VisiblePartialDependencePlots
+ .Except(new[] { (IPartialDependencePlot)o })
+ .Select(async chart => {
+ await chart.RecalculateAsync(updateOnFinish: false, resetYAxis: false);
+ }).ToList();
+ await Task.WhenAll(recalculations);
+
+ if (recalculations.All(t => t.IsCompleted))
+ SetupYAxis();
+ };
+ plot.Configure(new[] { Content }, sharedFixedVariables, variableName, Points);
+ plot.SolutionAdded += partialDependencePlot_SolutionAdded;
+ plot.SolutionRemoved += partialDependencePlot_SolutionRemoved;
+ return plot;
+ }
+ private FactorPartialDependencePlot CreateFactorPartialDependencePlot(string variableName, ModifiableDataset sharedFixedVariables) {
+ var plot = new FactorPartialDependencePlot {
+ Dock = DockStyle.Fill,
+ Margin = Padding.Empty,
+ ShowLegend = false,
+ ShowCursor = true,
+ YAxisTicks = 5,
+ };
+ plot.VariableValueChanged += async (o, e) => {
+ var recalculations = VisiblePartialDependencePlots
+ .Except(new[] { (FactorPartialDependencePlot)o })
+ .Select(async chart => {
+ await chart.RecalculateAsync(updateOnFinish: false, resetYAxis: false);
+ }).ToList();
+ await Task.WhenAll(recalculations);
+
+ if (recalculations.All(t => t.IsCompleted))
+ SetupYAxis();
+ };
+ var variableValues = Content.ProblemData.Dataset.GetStringValues(variableName).Distinct().OrderBy(n => n).ToList();
+ plot.Configure(new[] { Content }, sharedFixedVariables, variableName, variableValues);
+ plot.SolutionAdded += partialDependencePlot_SolutionAdded;
+ plot.SolutionRemoved += partialDependencePlot_SolutionRemoved;
+ return plot;
+ }
+ private void SetupYAxis() {
+ double axisMin, axisMax;
+ if (automaticYAxisCheckBox.Checked) {
+ double min = double.MaxValue, max = double.MinValue;
+ foreach (var chart in VisiblePartialDependencePlots) {
+ if (chart.YMin < min) min = chart.YMin;
+ if (chart.YMax > max) max = chart.YMax;
+ }
+
+ double axisInterval;
+ ChartUtil.CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
+ } else {
+ axisMin = limitView.Content.Lower;
+ axisMax = limitView.Content.Upper;
+ }
+
+ foreach (var chart in VisiblePartialDependencePlots) {
+ chart.FixedYAxisMin = axisMin;
+ chart.FixedYAxisMax = axisMax;
+ }
+ }
+
+ // reorder chart controls so that they always appear in the same order as in the list view
+ // the table layout containing the controls should be suspended before calling this method
+ private void ReOrderControls() {
+ var tl = partialDependencePlotTableLayout;
+ tl.Controls.Clear();
+ int row = 0, column = 0;
+ double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single();
+ string title = Content.ProblemData.TargetVariable + ": " + yValue.ToString("G5", CultureInfo.CurrentCulture);
+
+ foreach (var v in VisibleVariables) {
+ var chartsPanel = groupingPanels[v];
+ tl.Controls.Add(chartsPanel, column, row);
+
+ var chart = partialDependencePlots[v];
+ chart.YAxisTitle = column == 0 ? title : string.Empty;
+ column++;
+
+ if (column == MaxColumns) {
+ row++;
+ column = 0;
+ }
+ }
+ }
+
+ private void SetStyles() {
+ var tl = partialDependencePlotTableLayout;
+ tl.RowStyles.Clear();
+ tl.ColumnStyles.Clear();
+ int numVariables = VisibleVariables.Count();
+ if (numVariables == 0)
+ return;
+
+ // set column styles
+ tl.ColumnCount = Math.Min(numVariables, MaxColumns);
+ for (int c = 0; c < tl.ColumnCount; c++)
+ tl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / tl.ColumnCount));
+
+ // set row styles
+ tl.RowCount = (int)Math.Ceiling((double)numVariables / tl.ColumnCount);
+ var columnWidth = tl.Width / tl.ColumnCount; // assume all columns have the same width
+ var rowHeight = (int)(0.8 * columnWidth);
+ for (int r = 0; r < tl.RowCount; r++)
+ tl.RowStyles.Add(new RowStyle(SizeType.Absolute, rowHeight));
+ }
+
+ private async void partialDependencePlot_SolutionAdded(object sender, EventArgs e) {
+ var solution = e.Value;
+ foreach (var chart in partialDependencePlots.Values) {
+ if (sender == chart) continue;
+ await chart.AddSolutionAsync(solution);
+ }
+ }
+
+ private async void partialDependencePlot_SolutionRemoved(object sender, EventArgs e) {
+ var solution = e.Value;
+ foreach (var chart in partialDependencePlots.Values) {
+ if (sender == chart) continue;
+ await chart.RemoveSolutionAsync(solution);
+ }
+ }
+
+ private async void variableListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
+ var item = e.Item;
+ var variable = item.Text;
+ var plot = partialDependencePlots[variable];
+ var chartsPanel = groupingPanels[variable];
+ var tl = partialDependencePlotTableLayout;
+
+ tl.SuspendLayout();
+ if (item.Checked) {
+ tl.Controls.Add(chartsPanel);
+ await plot.RecalculateAsync(false, false);
+ } else {
+ tl.Controls.Remove(chartsPanel);
+ }
+
+ if (tl.Controls.Count > 0) {
+ SetupYAxis();
+ ReOrderControls();
+ SetStyles();
+ }
+ tl.ResumeLayout();
+ tl.Refresh();
+ densityComboBox_SelectedIndexChanged(this, EventArgs.Empty);
+ }
+
+ private void automaticYAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
+ limitView.ReadOnly = automaticYAxisCheckBox.Checked;
+ SetupYAxis();
+ partialDependencePlotTableLayout.Refresh();
+ densityComboBox_SelectedIndexChanged(this, EventArgs.Empty); // necessary to realign the density plots
+ }
+
+ private void limit_ValueChanged(object sender, EventArgs e) {
+ if (automaticYAxisCheckBox.Checked)
+ return;
+ SetupYAxis();
+ partialDependencePlotTableLayout.Refresh();
+ densityComboBox_SelectedIndexChanged(this, EventArgs.Empty); // necessary to realign the density plots
+ }
+
+ private void densityComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (Content == null)
+ return;
+
+ int si = densityComboBox.SelectedIndex;
+ if (si == 0) {
+ foreach (var densityChart in densityCharts.Values)
+ densityChart.Visible = false;
+ } else {
+ var indices = GetDensityIndices(si).ToList();
+
+ foreach (var entry in densityCharts) {
+ var variableName = entry.Key;
+ var densityChart = entry.Value;
+ if (!VisibleVariables.Contains(variableName) || partialDependencePlots[variableName].IsZoomed)
+ continue;
+
+ UpdateDensityChart(densityChart, variableName, indices);
+ }
+ }
+ }
+ private IEnumerable GetDensityIndices(int selectedIndex) {
+ var problemData = Content.ProblemData;
+ return
+ selectedIndex == 1 ? problemData.TrainingIndices :
+ selectedIndex == 2 ? problemData.TestIndices :
+ problemData.AllIndices;
+ }
+ private void UpdateDensityChart(DensityChart densityChart, string variable, IList indices = null) {
+ if (densityComboBox.SelectedIndex == 0)
+ return;
+ if (indices == null) {
+ indices = GetDensityIndices(densityComboBox.SelectedIndex).ToList();
+ }
+ if (Content.ProblemData.Dataset.VariableHasType(variable)) {
+ var data = Content.ProblemData.Dataset.GetDoubleValues(variable, indices).ToList();
+ var plot = partialDependencePlots[variable] as PartialDependencePlot;
+ if (plot != null) {
+ var min = plot.FixedXAxisMin;
+ var max = plot.FixedXAxisMax;
+ var buckets = plot.DrawingSteps;
+ if (min.HasValue && max.HasValue) {
+ densityChart.UpdateChart(data, min.Value, max.Value, buckets);
+ densityChart.Width = plot.Width;
+
+ var gcPlotPosition = plot.InnerPlotPosition;
+ densityChart.Left = (int)(gcPlotPosition.X / 100.0 * plot.Width);
+ densityChart.Width = (int)(gcPlotPosition.Width / 100.0 * plot.Width);
+
+ densityChart.Visible = true;
+ }
+ plot.UpdateTitlePosition();
+ }
+ } else if (Content.ProblemData.Dataset.VariableHasType(variable)) {
+ var data = Content.ProblemData.Dataset.GetStringValues(variable).ToList();
+ var plot = partialDependencePlots[variable] as FactorPartialDependencePlot;
+ if (plot != null) {
+ densityChart.UpdateChart(data);
+ densityChart.Width = plot.Width;
+
+ var gcPlotPosition = plot.InnerPlotPosition;
+ densityChart.Left = (int)(gcPlotPosition.X / 100.0 * plot.Width);
+ densityChart.Width = (int)(gcPlotPosition.Width / 100.0 * plot.Width);
+
+ densityChart.Visible = true;
+
+ plot.UpdateTitlePosition();
+ }
+ }
+ }
+
+ private void columnsNumericUpDown_ValueChanged(object sender, EventArgs e) {
+ MaxColumns = (int)columnsNumericUpDown.Value;
+ int columns = Math.Min(VisibleVariables.Count(), MaxColumns);
+ if (columns > 0) {
+ var tl = partialDependencePlotTableLayout;
+ MaxColumns = columns;
+ tl.SuspendLayout();
+ ReOrderControls();
+ SetStyles();
+ tl.ResumeLayout();
+ tl.Refresh();
+ densityComboBox_SelectedIndexChanged(this, EventArgs.Empty);
+ }
+ }
+
+ private async void solution_ModelChanged(object sender, EventArgs e) {
+ foreach (var variable in VisibleVariables) {
+ var pdp = partialDependencePlots[variable];
+ var densityChart = densityCharts[variable];
+ // recalculate and refresh
+ await pdp.RecalculateAsync(false, false);
+ pdp.Refresh();
+ UpdateDensityChart(densityChart, variable);
+ }
+ }
+ }
+}
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.Designer.cs (revision 15136)
+++ (revision )
@@ -1,271 +1,0 @@
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- partial class RegressionSolutionTargetResponseGradientView {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- this.variableListView = new System.Windows.Forms.ListView();
- this.gradientChartTableLayout = new System.Windows.Forms.TableLayoutPanel();
- this.yAxisConfigGroupBox = new System.Windows.Forms.GroupBox();
- this.limitView = new HeuristicLab.Problems.DataAnalysis.Views.DoubleLimitView();
- this.automaticYAxisCheckBox = new System.Windows.Forms.CheckBox();
- this.densityGroupBox = new System.Windows.Forms.GroupBox();
- this.columnsLabel = new System.Windows.Forms.Label();
- this.densityComboBox = new System.Windows.Forms.ComboBox();
- this.label1 = new System.Windows.Forms.Label();
- this.configSplitContainer = new System.Windows.Forms.SplitContainer();
- this.variableGroupBox = new System.Windows.Forms.GroupBox();
- this.scrollPanel = new System.Windows.Forms.Panel();
- this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
- this.columnsNumericUpDown = new System.Windows.Forms.NumericUpDown();
- this.yAxisConfigGroupBox.SuspendLayout();
- this.densityGroupBox.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).BeginInit();
- this.configSplitContainer.Panel1.SuspendLayout();
- this.configSplitContainer.Panel2.SuspendLayout();
- this.configSplitContainer.SuspendLayout();
- this.variableGroupBox.SuspendLayout();
- this.scrollPanel.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).BeginInit();
- this.SuspendLayout();
- //
- // variableListView
- //
- this.variableListView.CheckBoxes = true;
- this.variableListView.Dock = System.Windows.Forms.DockStyle.Fill;
- this.variableListView.Location = new System.Drawing.Point(3, 16);
- this.variableListView.Name = "variableListView";
- this.variableListView.Size = new System.Drawing.Size(163, 478);
- this.variableListView.TabIndex = 0;
- this.variableListView.UseCompatibleStateImageBehavior = false;
- this.variableListView.View = System.Windows.Forms.View.List;
- this.variableListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.variableListView_ItemChecked);
- //
- // gradientChartTableLayout
- //
- this.gradientChartTableLayout.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.gradientChartTableLayout.AutoSize = true;
- this.gradientChartTableLayout.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
- this.gradientChartTableLayout.ColumnCount = 1;
- this.gradientChartTableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.gradientChartTableLayout.Location = new System.Drawing.Point(0, 0);
- this.gradientChartTableLayout.Name = "gradientChartTableLayout";
- this.gradientChartTableLayout.RowCount = 1;
- this.gradientChartTableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.gradientChartTableLayout.Size = new System.Drawing.Size(542, 0);
- this.gradientChartTableLayout.TabIndex = 2;
- //
- // yAxisConfigGroupBox
- //
- this.yAxisConfigGroupBox.Controls.Add(this.limitView);
- this.yAxisConfigGroupBox.Controls.Add(this.automaticYAxisCheckBox);
- this.yAxisConfigGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
- this.yAxisConfigGroupBox.Location = new System.Drawing.Point(0, 0);
- this.yAxisConfigGroupBox.Name = "yAxisConfigGroupBox";
- this.yAxisConfigGroupBox.Size = new System.Drawing.Size(169, 77);
- this.yAxisConfigGroupBox.TabIndex = 2;
- this.yAxisConfigGroupBox.TabStop = false;
- this.yAxisConfigGroupBox.Text = "Y-Axis";
- //
- // limitView
- //
- this.limitView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.limitView.Caption = "DoubleLimit View";
- this.limitView.Content = null;
- this.limitView.Location = new System.Drawing.Point(6, 20);
- this.limitView.Name = "limitView";
- this.limitView.ReadOnly = false;
- this.limitView.Size = new System.Drawing.Size(157, 47);
- this.limitView.TabIndex = 1;
- //
- // automaticYAxisCheckBox
- //
- this.automaticYAxisCheckBox.AutoSize = true;
- this.automaticYAxisCheckBox.Location = new System.Drawing.Point(49, -1);
- this.automaticYAxisCheckBox.Name = "automaticYAxisCheckBox";
- this.automaticYAxisCheckBox.Size = new System.Drawing.Size(73, 17);
- this.automaticYAxisCheckBox.TabIndex = 0;
- this.automaticYAxisCheckBox.Text = "Automatic";
- this.automaticYAxisCheckBox.UseVisualStyleBackColor = true;
- this.automaticYAxisCheckBox.CheckedChanged += new System.EventHandler(this.automaticYAxisCheckBox_CheckedChanged);
- //
- // densityGroupBox
- //
- this.densityGroupBox.Controls.Add(this.columnsNumericUpDown);
- this.densityGroupBox.Controls.Add(this.columnsLabel);
- this.densityGroupBox.Controls.Add(this.densityComboBox);
- this.densityGroupBox.Controls.Add(this.label1);
- this.densityGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
- this.densityGroupBox.Location = new System.Drawing.Point(0, 77);
- this.densityGroupBox.Name = "densityGroupBox";
- this.densityGroupBox.Size = new System.Drawing.Size(169, 74);
- this.densityGroupBox.TabIndex = 3;
- this.densityGroupBox.TabStop = false;
- this.densityGroupBox.Text = "Settings";
- //
- // columnsLabel
- //
- this.columnsLabel.AutoSize = true;
- this.columnsLabel.Location = new System.Drawing.Point(7, 49);
- this.columnsLabel.Name = "columnsLabel";
- this.columnsLabel.Size = new System.Drawing.Size(50, 13);
- this.columnsLabel.TabIndex = 0;
- this.columnsLabel.Text = "Columns:";
- //
- // densityComboBox
- //
- this.densityComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.densityComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.densityComboBox.FormattingEnabled = true;
- this.densityComboBox.Items.AddRange(new object[] {
- "None",
- "Training",
- "Test",
- "All"});
- this.densityComboBox.Location = new System.Drawing.Point(66, 19);
- this.densityComboBox.Name = "densityComboBox";
- this.densityComboBox.Size = new System.Drawing.Size(94, 21);
- this.densityComboBox.TabIndex = 0;
- this.densityComboBox.SelectedIndexChanged += new System.EventHandler(this.densityComboBox_SelectedIndexChanged);
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(7, 22);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(45, 13);
- this.label1.TabIndex = 0;
- this.label1.Text = "Density:";
- //
- // configSplitContainer
- //
- this.configSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
- this.configSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
- this.configSplitContainer.Location = new System.Drawing.Point(0, 0);
- this.configSplitContainer.Name = "configSplitContainer";
- //
- // configSplitContainer.Panel1
- //
- this.configSplitContainer.Panel1.Controls.Add(this.variableGroupBox);
- this.configSplitContainer.Panel1.Controls.Add(this.densityGroupBox);
- this.configSplitContainer.Panel1.Controls.Add(this.yAxisConfigGroupBox);
- //
- // configSplitContainer.Panel2
- //
- this.configSplitContainer.Panel2.Controls.Add(this.scrollPanel);
- this.configSplitContainer.Size = new System.Drawing.Size(715, 648);
- this.configSplitContainer.SplitterDistance = 169;
- this.configSplitContainer.TabIndex = 0;
- this.configSplitContainer.TabStop = false;
- //
- // variableGroupBox
- //
- this.variableGroupBox.Controls.Add(this.variableListView);
- this.variableGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
- this.variableGroupBox.Location = new System.Drawing.Point(0, 151);
- this.variableGroupBox.Name = "variableGroupBox";
- this.variableGroupBox.Size = new System.Drawing.Size(169, 497);
- this.variableGroupBox.TabIndex = 1;
- this.variableGroupBox.TabStop = false;
- this.variableGroupBox.Text = "Variables";
- //
- // scrollPanel
- //
- this.scrollPanel.Controls.Add(this.gradientChartTableLayout);
- this.scrollPanel.Dock = System.Windows.Forms.DockStyle.Fill;
- this.scrollPanel.Location = new System.Drawing.Point(0, 0);
- this.scrollPanel.Name = "scrollPanel";
- this.scrollPanel.Size = new System.Drawing.Size(542, 648);
- this.scrollPanel.TabIndex = 0;
- //
- // errorProvider
- //
- this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
- this.errorProvider.ContainerControl = this;
- //
- // columnsNumericUpDown
- //
- this.columnsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.columnsNumericUpDown.Location = new System.Drawing.Point(66, 46);
- this.columnsNumericUpDown.Minimum = new decimal(new int[] {
- 1,
- 0,
- 0,
- 0});
- this.columnsNumericUpDown.Name = "columnsNumericUpDown";
- this.columnsNumericUpDown.Size = new System.Drawing.Size(94, 20);
- this.columnsNumericUpDown.TabIndex = 1;
- this.columnsNumericUpDown.Value = new decimal(new int[] {
- 4,
- 0,
- 0,
- 0});
- this.columnsNumericUpDown.ValueChanged += new System.EventHandler(this.columnsNumericUpDown_ValueChanged);
- //
- // RegressionSolutionTargetResponseGradientView
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.Controls.Add(this.configSplitContainer);
- this.Name = "RegressionSolutionTargetResponseGradientView";
- this.Size = new System.Drawing.Size(715, 648);
- this.yAxisConfigGroupBox.ResumeLayout(false);
- this.yAxisConfigGroupBox.PerformLayout();
- this.densityGroupBox.ResumeLayout(false);
- this.densityGroupBox.PerformLayout();
- this.configSplitContainer.Panel1.ResumeLayout(false);
- this.configSplitContainer.Panel2.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).EndInit();
- this.configSplitContainer.ResumeLayout(false);
- this.variableGroupBox.ResumeLayout(false);
- this.scrollPanel.ResumeLayout(false);
- this.scrollPanel.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).EndInit();
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.ListView variableListView;
- private System.Windows.Forms.TableLayoutPanel gradientChartTableLayout;
- private System.Windows.Forms.GroupBox yAxisConfigGroupBox;
- private System.Windows.Forms.CheckBox automaticYAxisCheckBox;
- private DoubleLimitView limitView;
- private System.Windows.Forms.GroupBox densityGroupBox;
- private System.Windows.Forms.ComboBox densityComboBox;
- private System.Windows.Forms.SplitContainer configSplitContainer;
- private System.Windows.Forms.GroupBox variableGroupBox;
- private System.Windows.Forms.Panel scrollPanel;
- private System.Windows.Forms.Label columnsLabel;
- private System.Windows.Forms.ErrorProvider errorProvider;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.NumericUpDown columnsNumericUpDown;
- }
-}
Index: able/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs (revision 15136)
+++ (revision )
@@ -1,567 +1,0 @@
-#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 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.Collections;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Globalization;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using HeuristicLab.Common;
-using HeuristicLab.MainForm;
-using HeuristicLab.Visualization.ChartControlsExtensions;
-
-namespace HeuristicLab.Problems.DataAnalysis.Views {
- [View("Target Response Gradients")]
- [Content(typeof(IRegressionSolution))]
- public partial class RegressionSolutionTargetResponseGradientView : DataAnalysisSolutionEvaluationView {
- private readonly Dictionary gradientCharts;
- private readonly Dictionary densityCharts;
- private readonly Dictionary groupingPanels;
- private ModifiableDataset sharedFixedVariables;
-
- private const int Points = 200;
- private int MaxColumns = 4;
-
- private IEnumerable VisibleVariables {
- get {
- foreach (ListViewItem item in variableListView.CheckedItems)
- yield return item.Text;
- }
- }
- private IEnumerable VisibleGradientCharts {
- get { return VisibleVariables.Select(v => gradientCharts[v]); }
- }
- private IEnumerable VisibleDensityCharts {
- get { return VisibleVariables.Select(v => densityCharts[v]); }
- }
- private IEnumerable VisibleChartsPanels {
- get { return VisibleVariables.Select(v => groupingPanels[v]); }
- }
-
- public RegressionSolutionTargetResponseGradientView() {
- InitializeComponent();
- gradientCharts = new Dictionary();
- densityCharts = new Dictionary();
- groupingPanels = new Dictionary();
-
- limitView.Content = new DoubleLimit(0, 1);
- limitView.Content.ValueChanged += limit_ValueChanged;
-
- densityComboBox.SelectedIndex = 1; // select Training
-
- // Avoid additional horizontal scrollbar
- var vertScrollWidth = SystemInformation.VerticalScrollBarWidth;
- scrollPanel.Padding = new Padding(0, 0, vertScrollWidth, 0);
- scrollPanel.AutoScroll = true;
- }
-
- public new IRegressionSolution Content {
- get { return (IRegressionSolution)base.Content; }
- set { base.Content = value; }
- }
-
- protected override void RegisterContentEvents() {
- base.RegisterContentEvents();
- Content.ModelChanged += solution_ModelChanged;
- }
-
- protected override void DeregisterContentEvents() {
- Content.ModelChanged -= solution_ModelChanged;
- base.DeregisterContentEvents();
- }
-
- protected override void OnContentChanged() {
- base.OnContentChanged();
- if (Content == null) return;
- var problemData = Content.ProblemData;
-
- // Init Y-axis range
- double min = double.MaxValue, max = double.MinValue;
- var trainingTarget = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices);
- foreach (var t in trainingTarget) {
- if (t < min) min = t;
- if (t > max) max = t;
- }
- double range = max - min;
- const double scale = 1.0 / 3.0;
- double axisMin, axisMax, axisInterval;
- ChartUtil.CalculateAxisInterval(min - scale * range, max + scale * range, 5, out axisMin, out axisMax, out axisInterval);
- automaticYAxisCheckBox.Checked = false;
- limitView.ReadOnly = false;
- limitView.Content.Lower = axisMin;
- limitView.Content.Upper = axisMax;
-
- // create dataset of problemData input variables and model input variables
- // necessary workaround to have the variables in the occuring order
- var inputvariables =
- new HashSet(Content.ProblemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
- var allowedInputVariables =
- Content.ProblemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
-
-
- var doubleVariables = allowedInputVariables.Where(problemData.Dataset.VariableHasType);
- var doubleVariableValues = (IEnumerable)doubleVariables.Select(x => new List { problemData.Dataset.GetDoubleValues(x, problemData.TrainingIndices).Median() });
-
- var factorVariables = allowedInputVariables.Where(problemData.Dataset.VariableHasType);
- var factorVariableValues = (IEnumerable)factorVariables.Select(x => new List {
- problemData.Dataset.GetStringValues(x, problemData.TrainingIndices)
- .GroupBy(val => val).OrderByDescending(g => g.Count()).First().Key // most frequent value
- });
-
- if (sharedFixedVariables != null)
- sharedFixedVariables.ItemChanged -= SharedFixedVariables_ItemChanged;
-
- sharedFixedVariables = new ModifiableDataset(doubleVariables.Concat(factorVariables), doubleVariableValues.Concat(factorVariableValues));
-
-
- // create controls
- gradientCharts.Clear();
- densityCharts.Clear();
- groupingPanels.Clear();
- foreach (var variableName in doubleVariables) {
- var gradientChart = CreateGradientChart(variableName, sharedFixedVariables);
- gradientCharts.Add(variableName, gradientChart);
-
- var densityChart = new DensityChart() {
- Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right,
- Margin = Padding.Empty,
- Height = 12,
- Visible = false,
- Top = (int)(gradientChart.Height * 0.1),
- };
- densityCharts.Add(variableName, densityChart);
-
- gradientChart.ZoomChanged += (o, e) => {
- var gradient = (GradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
- density.Visible = densityComboBox.SelectedIndex != 0 && !gradient.IsZoomed;
- if (density.Visible)
- UpdateDensityChart(density, gradient.FreeVariable);
- };
- gradientChart.SizeChanged += (o, e) => {
- var gradient = (GradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
- density.Top = (int)(gradient.Height * 0.1);
- };
-
- // Initially, the inner plot areas are not initialized for hidden charts (scollpanel, ...)
- // This event handler listens for the paint event once (where everything is already initialized) to do some manual layouting.
- gradientChart.ChartPostPaint += OnGradientChartPostPaint;
-
- var panel = new Panel() {
- Dock = DockStyle.Fill,
- Margin = Padding.Empty,
- BackColor = Color.White
- };
-
- panel.Controls.Add(densityChart);
- panel.Controls.Add(gradientChart);
- groupingPanels.Add(variableName, panel);
- }
- foreach (var variableName in factorVariables) {
- var gradientChart = CreateFactorGradientChart(variableName, sharedFixedVariables);
- gradientCharts.Add(variableName, gradientChart);
-
- var densityChart = new DensityChart() {
- Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right,
- Margin = Padding.Empty,
- Height = 12,
- Visible = false,
- Top = (int)(gradientChart.Height * 0.1),
- };
- densityCharts.Add(variableName, densityChart);
- gradientChart.ZoomChanged += (o, e) => {
- var gradient = (FactorGradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
- density.Visible = densityComboBox.SelectedIndex != 0 && !gradient.IsZoomed;
- if (density.Visible)
- UpdateDensityChart(density, gradient.FreeVariable);
- };
- gradientChart.SizeChanged += (o, e) => {
- var gradient = (FactorGradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
- density.Top = (int)(gradient.Height * 0.1);
- };
-
- // Initially, the inner plot areas are not initialized for hidden charts (scollpanel, ...)
- // This event handler listens for the paint event once (where everything is already initialized) to do some manual layouting.
- gradientChart.ChartPostPaint += OnFactorGradientChartPostPaint;
-
- var panel = new Panel() {
- Dock = DockStyle.Fill,
- Margin = Padding.Empty,
- BackColor = Color.White
- };
-
- panel.Controls.Add(densityChart);
- panel.Controls.Add(gradientChart);
- groupingPanels.Add(variableName, panel);
- }
- // update variable list
- variableListView.ItemChecked -= variableListView_ItemChecked;
- variableListView.Items.Clear();
- foreach (var variable in allowedInputVariables)
- variableListView.Items.Add(key: variable, text: variable, imageIndex: 0);
-
- foreach (var variable in Content.Model.VariablesUsedForPrediction)
- variableListView.Items[variable].Checked = true;
- variableListView.ItemChecked += variableListView_ItemChecked;
-
- sharedFixedVariables.ItemChanged += SharedFixedVariables_ItemChanged;
-
- RecalculateAndRelayoutCharts();
- }
-
- private void SharedFixedVariables_ItemChanged(object sender, EventArgs e) {
- double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single();
- string title = Content.ProblemData.TargetVariable + ": " + yValue.ToString("G5", CultureInfo.CurrentCulture);
- foreach (var chart in gradientCharts.Values) {
- if (!string.IsNullOrEmpty(chart.YAxisTitle)) { // only show title for first column in grid
- chart.YAxisTitle = title;
- }
- }
- }
-
-
- private void OnGradientChartPostPaint(object o, EventArgs e) {
- var gradient = (GradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
-
- density.Width = gradient.Width;
-
- var gcPlotPosition = gradient.InnerPlotPosition;
- density.Left = (int)(gcPlotPosition.X / 100.0 * gradient.Width);
- density.Width = (int)(gcPlotPosition.Width / 100.0 * gradient.Width);
- gradient.UpdateTitlePosition();
-
- // removed after succesful layouting due to performance reasons
- if (gcPlotPosition.Width != 0)
- gradient.ChartPostPaint -= OnGradientChartPostPaint;
- }
-
- private void OnFactorGradientChartPostPaint(object o, EventArgs e) {
- var gradient = (FactorGradientChart)o;
- var density = densityCharts[gradient.FreeVariable];
-
- density.Width = gradient.Width;
-
- var gcPlotPosition = gradient.InnerPlotPosition;
- density.Left = (int)(gcPlotPosition.X / 100.0 * gradient.Width);
- density.Width = (int)(gcPlotPosition.Width / 100.0 * gradient.Width);
- gradient.UpdateTitlePosition();
-
- // removed after succesful layouting due to performance reasons
- if (gcPlotPosition.Width != 0)
- gradient.ChartPostPaint -= OnFactorGradientChartPostPaint;
- }
-
- private async void RecalculateAndRelayoutCharts() {
- foreach (var variable in VisibleVariables) {
- var gradientChart = gradientCharts[variable];
- await gradientChart.RecalculateAsync(false, false);
- }
- gradientChartTableLayout.SuspendLayout();
- SetupYAxis();
- ReOrderControls();
- SetStyles();
- gradientChartTableLayout.ResumeLayout();
- gradientChartTableLayout.Refresh();
- foreach (var variable in VisibleVariables) {
- DensityChart densityChart;
- if (densityCharts.TryGetValue(variable, out densityChart)) {
- UpdateDensityChart(densityChart, variable);
- }
- }
- }
- private GradientChart CreateGradientChart(string variableName, ModifiableDataset sharedFixedVariables) {
- var gradientChart = new GradientChart {
- Dock = DockStyle.Fill,
- Margin = Padding.Empty,
- ShowLegend = false,
- ShowCursor = true,
- ShowConfigButton = false,
- YAxisTicks = 5,
- };
- gradientChart.VariableValueChanged += async (o, e) => {
- var recalculations = VisibleGradientCharts
- .Except(new[] { (IGradientChart)o })
- .Select(async chart => {
- await chart.RecalculateAsync(updateOnFinish: false, resetYAxis: false);
- }).ToList();
- await Task.WhenAll(recalculations);
-
- if (recalculations.All(t => t.IsCompleted))
- SetupYAxis();
- };
- gradientChart.Configure(new[] { Content }, sharedFixedVariables, variableName, Points);
- gradientChart.SolutionAdded += gradientChart_SolutionAdded;
- gradientChart.SolutionRemoved += gradientChart_SolutionRemoved;
- return gradientChart;
- }
- private FactorGradientChart CreateFactorGradientChart(string variableName, ModifiableDataset sharedFixedVariables) {
- var gradientChart = new FactorGradientChart {
- Dock = DockStyle.Fill,
- Margin = Padding.Empty,
- ShowLegend = false,
- ShowCursor = true,
- YAxisTicks = 5,
- };
- gradientChart.VariableValueChanged += async (o, e) => {
- var recalculations = VisibleGradientCharts
- .Except(new[] { (FactorGradientChart)o })
- .Select(async chart => {
- await chart.RecalculateAsync(updateOnFinish: false, resetYAxis: false);
- }).ToList();
- await Task.WhenAll(recalculations);
-
- if (recalculations.All(t => t.IsCompleted))
- SetupYAxis();
- };
- var variableValues = Content.ProblemData.Dataset.GetStringValues(variableName).Distinct().OrderBy(n => n).ToList();
- gradientChart.Configure(new[] { Content }, sharedFixedVariables, variableName, variableValues);
- gradientChart.SolutionAdded += gradientChart_SolutionAdded;
- gradientChart.SolutionRemoved += gradientChart_SolutionRemoved;
- return gradientChart;
- }
- private void SetupYAxis() {
- double axisMin, axisMax;
- if (automaticYAxisCheckBox.Checked) {
- double min = double.MaxValue, max = double.MinValue;
- foreach (var chart in VisibleGradientCharts) {
- if (chart.YMin < min) min = chart.YMin;
- if (chart.YMax > max) max = chart.YMax;
- }
-
- double axisInterval;
- ChartUtil.CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
- } else {
- axisMin = limitView.Content.Lower;
- axisMax = limitView.Content.Upper;
- }
-
- foreach (var chart in VisibleGradientCharts) {
- chart.FixedYAxisMin = axisMin;
- chart.FixedYAxisMax = axisMax;
- }
- }
-
- // reorder chart controls so that they always appear in the same order as in the list view
- // the table layout containing the controls should be suspended before calling this method
- private void ReOrderControls() {
- var tl = gradientChartTableLayout;
- tl.Controls.Clear();
- int row = 0, column = 0;
- double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single();
- string title = Content.ProblemData.TargetVariable + ": " + yValue.ToString("G5", CultureInfo.CurrentCulture);
-
- foreach (var v in VisibleVariables) {
- var chartsPanel = groupingPanels[v];
- tl.Controls.Add(chartsPanel, column, row);
-
- var chart = gradientCharts[v];
- chart.YAxisTitle = column == 0 ? title : string.Empty;
- column++;
-
- if (column == MaxColumns) {
- row++;
- column = 0;
- }
- }
- }
-
- private void SetStyles() {
- var tl = gradientChartTableLayout;
- tl.RowStyles.Clear();
- tl.ColumnStyles.Clear();
- int numVariables = VisibleVariables.Count();
- if (numVariables == 0)
- return;
-
- // set column styles
- tl.ColumnCount = Math.Min(numVariables, MaxColumns);
- for (int c = 0; c < tl.ColumnCount; c++)
- tl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / tl.ColumnCount));
-
- // set row styles
- tl.RowCount = (int)Math.Ceiling((double)numVariables / tl.ColumnCount);
- var columnWidth = tl.Width / tl.ColumnCount; // assume all columns have the same width
- var rowHeight = (int)(0.8 * columnWidth);
- for (int r = 0; r < tl.RowCount; r++)
- tl.RowStyles.Add(new RowStyle(SizeType.Absolute, rowHeight));
- }
-
- private async void gradientChart_SolutionAdded(object sender, EventArgs e) {
- var solution = e.Value;
- foreach (var chart in gradientCharts.Values) {
- if (sender == chart) continue;
- await chart.AddSolutionAsync(solution);
- }
- }
-
- private async void gradientChart_SolutionRemoved(object sender, EventArgs e) {
- var solution = e.Value;
- foreach (var chart in gradientCharts.Values) {
- if (sender == chart) continue;
- await chart.RemoveSolutionAsync(solution);
- }
- }
-
- private async void variableListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
- var item = e.Item;
- var variable = item.Text;
- var gradientChart = gradientCharts[variable];
- var chartsPanel = groupingPanels[variable];
- var tl = gradientChartTableLayout;
-
- tl.SuspendLayout();
- if (item.Checked) {
- tl.Controls.Add(chartsPanel);
- await gradientChart.RecalculateAsync(false, false);
- } else {
- tl.Controls.Remove(chartsPanel);
- }
-
- if (tl.Controls.Count > 0) {
- SetupYAxis();
- ReOrderControls();
- SetStyles();
- }
- tl.ResumeLayout();
- tl.Refresh();
- densityComboBox_SelectedIndexChanged(this, EventArgs.Empty);
- }
-
- private void automaticYAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
- limitView.ReadOnly = automaticYAxisCheckBox.Checked;
- SetupYAxis();
- gradientChartTableLayout.Refresh();
- densityComboBox_SelectedIndexChanged(this, EventArgs.Empty); // necessary to realign the density plots
- }
-
- private void limit_ValueChanged(object sender, EventArgs e) {
- if (automaticYAxisCheckBox.Checked)
- return;
- SetupYAxis();
- gradientChartTableLayout.Refresh();
- densityComboBox_SelectedIndexChanged(this, EventArgs.Empty); // necessary to realign the density plots
- }
-
- private void densityComboBox_SelectedIndexChanged(object sender, EventArgs e) {
- if (Content == null)
- return;
-
- int si = densityComboBox.SelectedIndex;
- if (si == 0) {
- foreach (var densityChart in densityCharts.Values)
- densityChart.Visible = false;
- } else {
- var indices = GetDensityIndices(si).ToList();
-
- foreach (var entry in densityCharts) {
- var variableName = entry.Key;
- var densityChart = entry.Value;
- if (!VisibleVariables.Contains(variableName) || gradientCharts[variableName].IsZoomed)
- continue;
-
- UpdateDensityChart(densityChart, variableName, indices);
- }
- }
- }
- private IEnumerable GetDensityIndices(int selectedIndex) {
- var problemData = Content.ProblemData;
- return
- selectedIndex == 1 ? problemData.TrainingIndices :
- selectedIndex == 2 ? problemData.TestIndices :
- problemData.AllIndices;
- }
- private void UpdateDensityChart(DensityChart densityChart, string variable, IList indices = null) {
- if (densityComboBox.SelectedIndex == 0)
- return;
- if (indices == null) {
- indices = GetDensityIndices(densityComboBox.SelectedIndex).ToList();
- }
- if (Content.ProblemData.Dataset.VariableHasType(variable)) {
- var data = Content.ProblemData.Dataset.GetDoubleValues(variable, indices).ToList();
- var gradientChart = gradientCharts[variable] as GradientChart;
- if (gradientChart != null) {
- var min = gradientChart.FixedXAxisMin;
- var max = gradientChart.FixedXAxisMax;
- var buckets = gradientChart.DrawingSteps;
- if (min.HasValue && max.HasValue) {
- densityChart.UpdateChart(data, min.Value, max.Value, buckets);
- densityChart.Width = gradientChart.Width;
-
- var gcPlotPosition = gradientChart.InnerPlotPosition;
- densityChart.Left = (int)(gcPlotPosition.X / 100.0 * gradientChart.Width);
- densityChart.Width = (int)(gcPlotPosition.Width / 100.0 * gradientChart.Width);
-
- densityChart.Visible = true;
- }
- gradientChart.UpdateTitlePosition();
- }
- } else if (Content.ProblemData.Dataset.VariableHasType(variable)) {
- var data = Content.ProblemData.Dataset.GetStringValues(variable).ToList();
- var gradientChart = gradientCharts[variable] as FactorGradientChart;
- if (gradientChart != null) {
- densityChart.UpdateChart(data);
- densityChart.Width = gradientChart.Width;
-
- var gcPlotPosition = gradientChart.InnerPlotPosition;
- densityChart.Left = (int)(gcPlotPosition.X / 100.0 * gradientChart.Width);
- densityChart.Width = (int)(gcPlotPosition.Width / 100.0 * gradientChart.Width);
-
- densityChart.Visible = true;
-
- gradientChart.UpdateTitlePosition();
- }
- }
- }
-
- private void columnsNumericUpDown_ValueChanged(object sender, EventArgs e) {
- MaxColumns = (int)columnsNumericUpDown.Value;
- int columns = Math.Min(VisibleVariables.Count(), MaxColumns);
- if (columns > 0) {
- var tl = gradientChartTableLayout;
- MaxColumns = columns;
- tl.SuspendLayout();
- ReOrderControls();
- SetStyles();
- tl.ResumeLayout();
- tl.Refresh();
- densityComboBox_SelectedIndexChanged(this, EventArgs.Empty);
- }
- }
-
- private async void solution_ModelChanged(object sender, EventArgs e) {
- foreach (var variable in VisibleVariables) {
- var gradientChart = gradientCharts[variable];
- var densityChart = densityCharts[variable];
- // recalculate and refresh
- await gradientChart.RecalculateAsync(false, false);
- gradientChart.Refresh();
- UpdateDensityChart(densityChart, variable);
- }
- }
- }
-}