Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/11/16 16:38:23 (8 years ago)
Author:
pfleck
Message:

#2597 Implemented "sync" y-axis for Target Response Gradient View.

Location:
branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.cs

    r13842 r13843  
    6565    public int XAxisTicks {
    6666      get { return xAxisTicks; }
    67       set { xAxisTicks = value; }
     67      set {
     68        if (value != xAxisTicks) {
     69          xAxisTicks = value;
     70          SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
     71          RecalculateInternalDataset();
     72        }
     73      }
    6874    }
    6975    private double? fixedXAxisMin;
     
    7379        if ((value.HasValue && fixedXAxisMin.HasValue && !value.Value.IsAlmost(fixedXAxisMin.Value)) || (value.HasValue != fixedXAxisMin.HasValue)) {
    7480          fixedXAxisMin = value;
     81          SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
    7582          RecalculateInternalDataset();
    7683        }
     
    8390        if ((value.HasValue && fixedXAxisMax.HasValue && !value.Value.IsAlmost(fixedXAxisMax.Value)) || (value.HasValue != fixedXAxisMax.HasValue)) {
    8491          fixedXAxisMax = value;
     92          SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, FixedXAxisMin, FixedXAxisMax);
    8593          RecalculateInternalDataset();
    8694        }
     
    9199    public int YAxisTicks {
    92100      get { return yAxisTicks; }
    93       set { yAxisTicks = value; }
     101      set {
     102        if (value != yAxisTicks) {
     103          yAxisTicks = value;
     104          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
     105          RecalculateInternalDataset();
     106        }
     107      }
    94108    }
    95109    private double? fixedYAxisMin;
     
    99113        if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
    100114          fixedYAxisMin = value;
     115          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
    101116        }
    102117      }
     
    108123        if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
    109124          fixedYAxisMax = value;
    110         }
    111       }
    112     }
    113 
    114     private double trainingMin = double.MinValue;
    115     public double TrainingMin {
    116       get { return trainingMin; }
    117       set { trainingMin = value; }
    118     }
    119     private double trainingMax = double.MaxValue;
    120     public double TrainingMax {
    121       get { return trainingMax; }
    122       set { trainingMax = value; }
    123     }
     125          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
     126        }
     127      }
     128    }
     129
     130    private double trainingMin = 1;
     131    private double trainingMax = -1;
    124132
    125133    private int drawingSteps = 1000;
     
    146154        RecalculateInternalDataset();
    147155      }
     156    }
     157
     158    private double yMin;
     159    public double YMin {
     160      get { return yMin; }
     161    }
     162    private double yMax;
     163    public double YMax {
     164      get { return yMax; }
    148165    }
    149166
     
    173190    }
    174191    private void GradientChart_Disposed(object sender, EventArgs e) {
    175       if (cancelCurrentRecalculateSource != null) {
    176         if (cancelCurrentRecalculateSource.IsCancellationRequested)
    177           cancelCurrentRecalculateSource.Cancel();
    178       }
     192      if (cancelCurrentRecalculateSource != null)
     193        cancelCurrentRecalculateSource.Cancel();
    179194    }
    180195
     
    212227    }
    213228
    214     public async Task RecalculateAsync() {
     229    public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) {
    215230      if (IsDisposed
    216231        || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable)
     
    230245      VerticalLineAnnotation.X = defaultValue;
    231246      chart.ChartAreas[0].AxisX.Title = FreeVariable + " : " + defaultValue.ToString("N3", CultureInfo.CurrentCulture);
    232       SetupAxis(chart.ChartAreas[0].AxisX, trainingMin, trainingMax, XAxisTicks, fixedXAxisMin, fixedXAxisMax);
    233247
    234248      // Update series
    235249      var cancellationToken = cancelCurrentRecalculateSource.Token;
    236250      try {
    237         await UpdateSeriesData(cancellationToken);
    238         chart.Update();
    239 
     251        var limits = await UpdateAllSeriesDataAsync(cancellationToken);
     252        //cancellationToken.ThrowIfCancellationRequested();
     253
     254        yMin = limits.Lower;
     255        yMax = limits.Upper;
    240256        // Set y-axis
    241         double ymin = 0, ymax = 0;
    242         foreach (var vs in chart.Series.SelectMany(series => series.Points.Select(s => s.YValues))) {
    243           for (int i = 0; i < vs.Length; i++) {
    244             var v = vs[i];
    245             if (ymin > v) ymin = v;
    246             if (ymax < v) ymax = v;
    247           }
    248         }
    249         SetupAxis(chart.ChartAreas[0].AxisY, ymin, ymax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
    250         chart.ChartAreas[0].RecalculateAxesScale();
     257        if (resetYAxis)
     258          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
    251259
    252260        UpdateOutOfTrainingRangeStripLines();
    253261
    254262        statusLabel.Visible = false;
    255         Update(); // immediately show
     263        if (updateOnFinish)
     264          Update();
    256265      }
    257266      catch (OperationCanceledException) { }
     
    262271    }
    263272
    264     private static void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
     273    private void SetupAxis(Axis axis, double minValue, double maxValue, int ticks, double? fixedAxisMin, double? fixedAxisMax) {
    265274      double axisMin, axisMax, axisInterval;
    266275      ChartUtil.CalculateAxisInterval(minValue, maxValue, ticks, out axisMin, out axisMax, out axisInterval);
    267276      axis.Minimum = fixedAxisMin ?? axisMin;
    268277      axis.Maximum = fixedAxisMax ?? axisMax;
    269       axis.Interval = (axisMax - axisMin) / ticks;
     278      axis.Interval = (axis.Maximum - axis.Minimum) / ticks;
     279
     280      chart.ChartAreas[0].RecalculateAxesScale();
    270281    }
    271282
     
    283294
    284295    private void RecalculateInternalDataset() {
     296      if (sharedFixedVariables == null)
     297        return;
     298
    285299      // we expand the range in order to get nice tick intervals on the x axis
    286300      double xmin, xmax, xinterval;
     
    351365    }
    352366
    353     private Task UpdateSeriesData(CancellationToken cancellationToken) {
     367    private async Task<DoubleLimit> UpdateAllSeriesDataAsync(CancellationToken cancellationToken) {
     368      var updateTasks = solutions.Select(solution => UpdateSeriesDataAsync(solution, cancellationToken));
     369
     370      double min = double.MaxValue, max = double.MinValue;
     371      foreach (var update in updateTasks) {
     372        var limit = await update;
     373        if (limit.Lower < min) min = limit.Lower;
     374        if (limit.Upper > max) max = limit.Upper;
     375      }
     376
     377      return new DoubleLimit(min, max);
     378    }
     379
     380    private Task<DoubleLimit> UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) {
    354381      return Task.Run(() => {
    355         Parallel.ForEach(solutions, new ParallelOptions { CancellationToken = cancellationToken }, solution => {
    356           var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
    357           var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
    358 
    359           var series = seriesCache[solution];
    360           for (int i = 0; i < xvalues.Count; i++)
    361             series.Points[i].SetValueXY(xvalues[i], yvalues[i]);
    362 
    363           var confidenceBoundSolution = solution as IConfidenceBoundRegressionSolution;
    364           if (confidenceBoundSolution != null) {
    365             var confidenceIntervalSeries = ciSeriesCache[solution];
    366 
    367             cancellationToken.ThrowIfCancellationRequested();
    368             var variances =
    369               confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset,
    370                 Enumerable.Range(0, internalDataset.Rows)).ToList();
    371             for (int i = 0; i < xvalues.Count; i++) {
    372               var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
    373               var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
    374               confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper);
    375             }
     382        var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
     383        var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
     384
     385        double min = double.MaxValue, max = double.MinValue;
     386
     387        var series = seriesCache[solution];
     388        for (int i = 0; i < xvalues.Count; i++) {
     389          series.Points[i].SetValueXY(xvalues[i], yvalues[i]);
     390          if (yvalues[i] < min) min = yvalues[i];
     391          if (yvalues[i] > max) max = yvalues[i];
     392        }
     393
     394        var confidenceBoundSolution = solution as IConfidenceBoundRegressionSolution;
     395        if (confidenceBoundSolution != null) {
     396          var confidenceIntervalSeries = ciSeriesCache[solution];
     397
     398          cancellationToken.ThrowIfCancellationRequested();
     399          var variances =
     400            confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset,
     401              Enumerable.Range(0, internalDataset.Rows)).ToList();
     402          for (int i = 0; i < xvalues.Count; i++) {
     403            var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]);
     404            var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]);
     405            confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper);
     406            if (lower < min) min = lower;
     407            if (upper > max) max = upper;
    376408          }
    377           cancellationToken.ThrowIfCancellationRequested();
    378         });
     409        }
     410
     411        cancellationToken.ThrowIfCancellationRequested();
     412        return new DoubleLimit(min, max);
    379413      }, cancellationToken);
    380414    }
    381415
    382416    private void ResizeAllSeriesData() {
     417      if (internalDataset == null)
     418        return;
     419
    383420      var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
    384421      foreach (var solution in solutions)
  • branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/RegressionSolutionGradientView.Designer.cs

    r13842 r13843  
    8282      this.gradientChart.ShowCursor = false;
    8383      this.gradientChart.ShowLegend = true;
    84       this.gradientChart.ShowXAxisLabel = true;
     84      this.gradientChart.ShowXAxisLabel = false;
    8585      this.gradientChart.ShowYAxisLabel = true;
    8686      this.gradientChart.Size = new System.Drawing.Size(715, 376);
    8787      this.gradientChart.TabIndex = 0;
    88       this.gradientChart.TrainingMax = 1.7976931348623157E+308D;
    89       this.gradientChart.TrainingMin = -1.7976931348623157E+308D;
    9088      this.gradientChart.XAxisTicks = 10;
    9189      this.gradientChart.YAxisTicks = 5;
  • branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/RegressionSolutionTargetResponseGradientView.cs

    r13842 r13843  
    2323using System.Collections.Generic;
    2424using System.Linq;
     25using System.Threading.Tasks;
    2526using System.Windows.Forms;
    2627using HeuristicLab.Common;
    2728using HeuristicLab.MainForm;
     29using HeuristicLab.Visualization.ChartControlsExtensions;
    2830
    2931namespace HeuristicLab.Problems.DataAnalysis.Views {
     
    3335    private readonly Dictionary<string, GradientChart> charts;
    3436    private const int Points = 200;
     37
     38    private IEnumerable<GradientChart> VisibleCharts {
     39      get { return gradientChartTableLayout.Controls.OfType<GradientChart>(); }
     40    }
    3541
    3642    public RegressionSolutionTargetResponseGradientView() {
     
    7278          ShowXAxisLabel = true,
    7379          ShowYAxisLabel = true,
     80          YAxisTicks = 5,
    7481        };
    75         gradientChart.VariableValueChanged += (o, e) => {
    76           foreach (var chart in gradientChartTableLayout.Controls.Cast<GradientChart>()) {
    77             if (chart == (GradientChart)o) continue;
    78             chart.RecalculateAsync();
    79           }
     82        gradientChart.VariableValueChanged += async (o, e) => {
     83          var recalculations = VisibleCharts.Except(new[] { (GradientChart)o }).Select(async chart => {
     84            await chart.RecalculateAsync(updateOnFinish: false, resetYAxis: false);
     85          }).ToList();
     86          await Task.WhenAll(recalculations);
     87
     88          if (recalculations.All(t => t.IsCompleted))
     89            SyncYAxis();
    8090        };
    8191        gradientChart.Configure(new[] { Content }, sharedFixedVariables, variableName, Points);
     
    8696      variableListView.Items.AddRange(variableNames.Select(x => new ListViewItem(x, 0)).ToArray());
    8797    }
     98
     99    private void SyncYAxis() {
     100      double min = double.MaxValue, max = double.MinValue;
     101      foreach (var chart in VisibleCharts) {
     102        if (chart.YMin < min) min = chart.YMin;
     103        if (chart.YMax > max) max = chart.YMax;
     104      }
     105      double axisMin, axisMax, axisInterval;
     106      ChartUtil.CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
     107
     108      foreach (var chart in VisibleCharts) {
     109        chart.FixedYAxisMin = axisMin;
     110        chart.FixedYAxisMax = axisMax;
     111        chart.Update();
     112      }
     113    }
     114
    88115    // sort chart controls so that they always appear in the same order as in the list view
    89116    // the gradient chart layout should be suspended before calling this method
     
    115142        tl.Controls.Remove(chart);
    116143      }
     144      SyncYAxis();
     145
    117146      var count = tl.Controls.Count;
    118147      SortControls();
Note: See TracChangeset for help on using the changeset viewer.