Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/04/16 15:00:49 (8 years ago)
Author:
pfleck
Message:

#2597:

  • merged recent trunk changes for GetUsedVariablesForPrediction method.
  • Merged chart from RegressionSolutionGradientView and existing GradientChart.
  • Used the GradientChart in the RegressionSolutionGradientView.
File:
1 edited

Legend:

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

    r13830 r13831  
    2222using System;
    2323using System.Collections.Generic;
    24 using System.Drawing;
    2524using System.Globalization;
    2625using System.Linq;
     
    3130
    3231namespace HeuristicLab.Problems.DataAnalysis.Views {
    33   public partial class GradientChart : EnhancedChart {
    34     private ModifiableDataset sharedDataset; // used for syncronising variable values between charts
     32  public partial class GradientChart : UserControl {
     33    private ModifiableDataset sharedFixedVariables; // used for syncronising variable values between charts
    3534    private ModifiableDataset internalDataset; // used to cache values and speed up calculations
    3635
    37     public bool ShowLegend { get; set; }
    38     public bool ShowXAxisLabel { get; set; }
    39     public bool ShowYAxisLabel { get; set; }
    40     public bool ShowCursor { get; set; }
    41 
    42     private bool useMedianValues;
    43     public bool UseMedianValues {
    44       get { return useMedianValues; }
     36    public bool ShowLegend {
     37      get { return chart.Legends[0].Enabled; }
     38      set { chart.Legends[0].Enabled = value; }
     39    }
     40    public bool ShowXAxisLabel {
     41      get { return chart.ChartAreas[0].AxisX.Enabled == AxisEnabled.True; }
     42      set { chart.ChartAreas[0].AxisX.Enabled = value ? AxisEnabled.True : AxisEnabled.False; }
     43    }
     44    public bool ShowYAxisLabel {
     45      get { return chart.ChartAreas[0].AxisY.Enabled == AxisEnabled.True; }
     46      set { chart.ChartAreas[0].AxisY.Enabled = value ? AxisEnabled.True : AxisEnabled.False; }
     47    }
     48    public bool ShowCursor {
     49      get { return chart.Annotations[0].Visible; }
     50      set { chart.Annotations[0].Visible = value; }
     51    }
     52
     53    private int xAxisTicks = 5;
     54    public int XAxisTicks {
     55      get { return xAxisTicks; }
     56      set { if (xAxisTicks != value) { xAxisTicks = value; UpdateChart(); } }
     57    }
     58    private int yAxisTicks = 5;
     59    public int YXAxisTicks {
     60      get { return yAxisTicks; }
     61      set { if (yAxisTicks != value) { yAxisTicks = value; UpdateChart(); } }
     62    }
     63
     64    private double trainingMin = double.MinValue;
     65    public double TrainingMin {
     66      get { return trainingMin; }
     67      set { if (!value.IsAlmost(trainingMin)) { trainingMin = value; UpdateChart(); } }
     68    }
     69    private double trainingMax = double.MaxValue;
     70    public double TrainingMax {
     71      get { return trainingMax; }
     72      set { if (!value.IsAlmost(trainingMax)) { trainingMax = value; UpdateChart(); } }
     73    }
     74
     75    private int drawingSteps = 1000;
     76    public int DrawingSteps {
     77      get { return drawingSteps; }
     78      set { if (value != drawingSteps) { drawingSteps = value; UpdateChart(); } }
     79    }
     80
     81    private string freeVariable;
     82    public string FreeVariable {
     83      get { return freeVariable; }
    4584      set {
    46         if (value == useMedianValues) return;
    47         useMedianValues = value;
    48         OnChartPropertyChanged(this, EventArgs.Empty);
     85        if (value == freeVariable) return;
     86        if (solutions.Any(s => !s.ProblemData.Dataset.DoubleVariables.Contains(value))) {
     87          throw new ArgumentException("Variable does not exist in the ProblemData of the Solutions.");
     88        }
     89        freeVariable = value;
     90        RecalculateInternalDataset();
    4991        UpdateChart();
    5092      }
    5193    }
    5294
    53     private int row;
    54     public int Row {
    55       get { return row; }
    56       set {
    57         if (row == value) return;
    58         row = value;
    59         OnChartPropertyChanged(this, EventArgs.Empty);
    60         UpdateChart();
    61       }
    62     }
    63 
    64     private double min;
    65     public double Min {
    66       get { return min; }
    67       set {
    68         if (value.IsAlmost(min)) return;
    69         min = value;
    70         OnChartPropertyChanged(this, EventArgs.Empty);
    71         UpdateChart();
    72       }
    73     }
    74 
    75     private double max;
    76     public double Max {
    77       get { return max; }
    78       set {
    79         if (value.IsAlmost(max)) return;
    80         max = value;
    81         OnChartPropertyChanged(this, EventArgs.Empty);
    82         UpdateChart();
    83       }
    84     }
    85 
    86     private int points;
    87     public int Points {
    88       get { return points; }
    89       set {
    90         if (value == points) return;
    91         points = value;
    92         OnChartPropertyChanged(this, EventArgs.Empty);
    93         UpdateChart();
    94       }
    95     }
    96 
    97     private IRegressionProblemData problemData;
    98     public IRegressionProblemData ProblemData {
    99       get { return problemData; }
    100       set {
    101         if (!SolutionsCompatibleWithProblemData(value, solutionList))
    102           throw new ArgumentException("The problem data provided does not contain all the variables required by the solutions.");
    103         problemData = value;
    104         UpdateDataset();
    105         UpdateChart();
    106       }
    107     }
    108 
    109     public string Target {
    110       get { return Solutions.First().ProblemData.TargetVariable; }
    111     }
    112 
    113     private string variable;
    114     public string Variable {
    115       get { return variable; }
    116       set {
    117         if (variable == value) return;
    118         if (!ProblemData.Dataset.DoubleVariables.Contains(value))
    119           throw new ArgumentException("The variable must be present in the problem dataset.");
    120         OnChartPropertyChanged(this, EventArgs.Empty);
    121         variable = value;
    122         var values = ProblemData.Dataset.GetReadOnlyDoubleValues(variable);
    123         min = values.Min();
    124         max = values.Max();
    125         UpdateChart();
    126       }
    127     }
    128 
    129     private List<IRegressionSolution> solutionList;
     95    private bool updateChartAutomatically = false;
     96    public bool UpdateChartAutomatically {
     97      get { return updateChartAutomatically; }
     98      set { updateChartAutomatically = value; if (updateChartAutomatically) UpdateChart(); }
     99    }
     100
     101    private readonly List<IRegressionSolution> solutions = new List<IRegressionSolution>();
    130102    public IEnumerable<IRegressionSolution> Solutions {
    131       get { return solutionList; }
    132       set {
    133         if (!value.Any())
    134           throw new ArgumentException("At least one solution must be provided.");
    135         if (SolutionsCompatibleWithProblemData(problemData, value))
    136           solutionList = new List<IRegressionSolution>(value);
    137         else
    138           throw new ArgumentException("The provided solution collection is not compatible with the existing problem data.");
    139         UpdateChart();
    140       }
    141     }
    142 
    143     public VerticalLineAnnotation VerticalLineAnnotation {
    144       get { return (VerticalLineAnnotation)Annotations.SingleOrDefault(x => x is VerticalLineAnnotation); }
     103      get { return solutions; }
     104    }
     105
     106    private VerticalLineAnnotation VerticalLineAnnotation {
     107      get { return (VerticalLineAnnotation)chart.Annotations.SingleOrDefault(x => x is VerticalLineAnnotation); }
    145108    }
    146109
    147110    public GradientChart() {
    148111      InitializeComponent();
    149       RegisterEvents();
    150     }
    151 
    152     public void AddSolution(IRegressionSolution solution) {
    153       if (!SolutionsCompatibleWithProblemData(problemData, new[] { solution })) {
    154         throw new ArgumentException("The solution is not compatible with the problem data.");
    155       }
    156       solutionList.Add(solution);
    157       UpdateChart();
    158     }
    159 
    160     public void RemoveSolution(IRegressionSolution solution) {
    161       var removed = solutionList.RemoveAll(x => x == solution);
    162       if (removed > 0)
    163         UpdateChart();
    164     }
    165 
    166     private static bool SolutionsCompatibleWithProblemData(IRegressionProblemData pd, IEnumerable<IRegressionSolution> solutions) {
    167       if (pd == null || !solutions.Any()) return true;
    168       if (solutions.Any(x => x.ProblemData.TargetVariable != pd.TargetVariable)) return false;
    169       var variables = new HashSet<string>(pd.Dataset.DoubleVariables);
    170       return solutions.SelectMany(x => x.ProblemData.Dataset.DoubleVariables).All(variables.Contains);
    171     }
    172 
    173     public void Configure(IEnumerable<IRegressionSolution> solutions, IRegressionProblemData pd, ModifiableDataset dataset, string variable, double min, double max, int points) {
    174       if (!SolutionsCompatibleWithProblemData(pd, solutions))
     112    }
     113
     114    public void Configure(IEnumerable<IRegressionSolution> solutions, ModifiableDataset sharedFixedVariables, string freeVariable, int drawingSteps) {
     115      if (!SolutionsCompatible(solutions))
    175116        throw new ArgumentException("Solutions are not compatible with the problem data.");
    176       this.solutionList = new List<IRegressionSolution>(solutions);
    177       this.problemData = pd;
    178       this.variable = variable;
    179       this.sharedDataset = dataset;
    180       this.min = min;
    181       this.max = max;
    182       this.points = points;
     117      this.solutions.Clear();
     118      this.solutions.AddRange(solutions);
     119      this.freeVariable = freeVariable;
     120      this.drawingSteps = drawingSteps;
    183121
    184122      // add an event such that whenever a value is changed in the shared dataset,
    185123      // this change is reflected in the internal dataset (where the value becomes a whole column)
    186       var variables = sharedDataset.DoubleVariables.ToList();
    187       sharedDataset.ItemChanged += (o, e) => {
    188         var rowIndex = e.Value;
    189         var columnIndex = e.Value2;
    190         var ds = (ModifiableDataset)o;
    191         var variableName = variables[columnIndex];
    192         if (variableName == Variable) return;
    193         var v = ds.GetDoubleValue(variableName, rowIndex);
    194         var values = new List<double>(Enumerable.Repeat(v, Points));
    195         internalDataset.ReplaceVariable(variableName, values);
    196       };
    197 
    198       // configure internal dataset. we also expand the range in order to get nice tick intervals on the x axis
    199       const int tics = 5;
     124      if (this.sharedFixedVariables != null)
     125        this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged;
     126      this.sharedFixedVariables = sharedFixedVariables;
     127      this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged;
     128
     129      trainingMin = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Min()).Max();
     130      trainingMax = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Max()).Min();
     131
     132      RecalculateInternalDataset();
     133    }
     134
     135    private void sharedFixedVariables_ItemChanged(object o, EventArgs<int, int> e) {
     136      var sender = (ModifiableDataset)o;
     137      var variables = sharedFixedVariables.DoubleVariables.ToList();
     138      var rowIndex = e.Value;
     139      var columnIndex = e.Value2;
     140
     141      var variableName = variables[columnIndex];
     142      if (variableName == FreeVariable) return;
     143      var v = sender.GetDoubleValue(variableName, rowIndex);
     144      var values = new List<double>(Enumerable.Repeat(v, DrawingSteps));
     145      internalDataset.ReplaceVariable(variableName, values);
     146
     147      if (UpdateChartAutomatically)
     148        UpdateChart();
     149    }
     150
     151    private void RecalculateInternalDataset() {
     152      // we expand the range in order to get nice tick intervals on the x axis
    200153      double xmin, xmax, xinterval;
    201       ChartUtil.CalculateAxisInterval(min, max, tics, out xmin, out xmax, out xinterval);
    202       var step = (xmax - xmin) / points;
     154      ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
     155      double step = (xmax - xmin) / drawingSteps;
     156
    203157      var xvalues = new List<double>();
    204       for (int i = 0; i < points; ++i) { xvalues.Add(xmin + i * step); }
    205       internalDataset = new ModifiableDataset(variables, variables.Select(x => x == Variable ? xvalues : new List<double>(Enumerable.Repeat(sharedDataset.GetDoubleValue(x, 0), xvalues.Count))));
     158      for (int i = 0; i < drawingSteps; i++)
     159        xvalues.Add(xmin + i * step);
     160
     161      var variables = sharedFixedVariables.DoubleVariables.ToList();
     162      internalDataset = new ModifiableDataset(variables,
     163        variables.Select(x => x == FreeVariable
     164          ? xvalues
     165          : Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(x, 0), xvalues.Count).ToList()
     166        )
     167      );
    206168    }
    207169
    208170    public void UpdateChart() {
    209171      // throw exceptions?
    210       if (sharedDataset == null || solutionList == null || !solutionList.Any())
     172      if (sharedFixedVariables == null || solutions == null || !solutions.Any())
    211173        return;
    212       if (min.IsAlmost(max) || min > max || points == 0)
     174      if (trainingMin.IsAlmost(trainingMax) || trainingMin > trainingMax || drawingSteps == 0)
    213175        return;
    214       Series.Clear();
    215       var vla = VerticalLineAnnotation;
    216       Annotations.Clear();
    217       var defaultValue = sharedDataset.GetDoubleValue(variable, 0);
    218       vla.Visible = ShowCursor;
    219       Annotations.Add(vla);
    220       vla.X = defaultValue;
    221 
     176
     177      // Set cursor
     178      var defaultValue = sharedFixedVariables.GetDoubleValue(freeVariable, 0);
     179      VerticalLineAnnotation.X = defaultValue;
     180
     181      // Calculate X-axis interval
    222182      double axisMin, axisMax, axisInterval;
    223       // calculate X-axis interval
    224       ChartUtil.CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
    225       var axis = ChartAreas[0].AxisX;
     183      ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out axisMin, out axisMax, out axisInterval);
     184      var axis = chart.ChartAreas[0].AxisX;
    226185      axis.Minimum = axisMin;
    227186      axis.Maximum = axisMax;
    228187      axis.Interval = axisInterval;
    229188
    230       for (int i = 0; i < solutionList.Count; ++i) {
    231         var solution = solutionList[i];
    232         var series = PlotSeries(solution);
    233         series.Name = Target + " " + i;
    234         Series.Add(series);
    235       }
    236       // calculate Y-axis interval
    237       double ymin = 0, ymax = 0;
    238       foreach (var v in Series[0].Points.Select(x => x.YValues[0])) {
    239         if (ymin > v) ymin = v;
    240         if (ymax < v) ymax = v;
    241       }
    242       ChartUtil.CalculateAxisInterval(ymin, ymax, 5, out axisMin, out axisMax, out axisInterval);
    243       axis = ChartAreas[0].AxisY;
    244       axis.Minimum = axisMin;
    245       axis.Maximum = axisMax;
    246       axis.Interval = axisInterval;
    247 
    248       if (ShowXAxisLabel) {
    249         ChartAreas[0].AxisX.Title = Variable + " : " + defaultValue.ToString("N3", CultureInfo.CurrentCulture); // set axis title
    250       }
    251 
    252       AddStripLines(); // add strip lines
    253       if (ShowLegend)
    254         AddLegends();
    255     }
    256 
    257     private void UpdateDataset() {
    258       var variables = ProblemData.Dataset.DoubleVariables.ToList();
    259       var variableValues = new List<double>[variables.Count];
    260 
    261       if (UseMedianValues) {
    262         for (int i = 0; i < variables.Count; ++i) {
    263           var median = ProblemData.Dataset.GetDoubleValues(variables[i], ProblemData.TrainingIndices).Median();
    264           variableValues[i] = new List<double> { median };
     189      // Create series
     190      chart.Series.Clear();
     191      for (int i = 0; i < solutions.Count; ++i) {
     192        var solution = solutions[i];
     193        Series confidenceIntervalPlotSeries;
     194        var series = CreateSeries(solution, out confidenceIntervalPlotSeries);
     195        series.Name = Solutions.First().ProblemData.TargetVariable + " " + i;
     196        if (confidenceIntervalPlotSeries != null)
     197          chart.Series.Add(confidenceIntervalPlotSeries);
     198        chart.Series.Add(series);
     199      }
     200      //// calculate Y-axis interval
     201      //double ymin = 0, ymax = 0;
     202      //foreach (var v in chart.Series[0].Points.Select(x => x.YValues[0])) {
     203      //  if (ymin > v) ymin = v;
     204      //  if (ymax < v) ymax = v;
     205      //}
     206      //ChartUtil.CalculateAxisInterval(ymin, ymax, YXAxisTicks, out axisMin, out axisMax, out axisInterval);
     207      //axis = chart.ChartAreas[0].AxisY;
     208      //axis.Minimum = axisMin;
     209      //axis.Maximum = axisMax;
     210      //axis.Interval = axisInterval;
     211
     212      // set axis title
     213      chart.ChartAreas[0].AxisX.Title = FreeVariable + " : " + defaultValue.ToString("N3", CultureInfo.CurrentCulture);
     214
     215      UpdateStripLines();
     216    }
     217
     218    private Series CreateSeries(IRegressionSolution solution, out Series confidenceIntervalPlotSeries) {
     219      var series = new Series {
     220        ChartType = SeriesChartType.Line
     221      };
     222
     223      var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList();
     224      var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
     225      series.Points.DataBindXY(xvalues, yvalues);
     226
     227      var confidenceBoundSolution = solution as IConfidenceBoundRegressionSolution;
     228      if (confidenceBoundSolution != null) {
     229        var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();
     230
     231        var lower = yvalues.Zip(variances, (m, s2) => m - 1.96 * Math.Sqrt(s2)).ToList();
     232        var upper = yvalues.Zip(variances, (m, s2) => m + 1.96 * Math.Sqrt(s2)).ToList();
     233
     234        confidenceIntervalPlotSeries = new Series {
     235          ChartType = SeriesChartType.Range,
     236          YValuesPerPoint = 2
     237        };
     238        confidenceIntervalPlotSeries.Points.DataBindXY(xvalues, lower, upper);
     239      } else {
     240        confidenceIntervalPlotSeries = null;
     241      }
     242
     243      return series;
     244    }
     245
     246    public void AddSolution(IRegressionSolution solution) {
     247      if (!SolutionsCompatible(solutions.Concat(new[] { solution })))
     248        throw new ArgumentException("The solution is not compatible with the problem data.");
     249      if (solutions.Contains(solution)) return;
     250      solutions.Add(solution);
     251      UpdateChart();
     252    }
     253    public void RemoveSolution(IRegressionSolution solution) {
     254      bool removed = solutions.Remove(solution);
     255      if (removed)
     256        UpdateChart();
     257    }
     258
     259    private static bool SolutionsCompatible(IEnumerable<IRegressionSolution> solutions) {
     260      foreach (var solution1 in solutions) {
     261        var variables1 = solution1.ProblemData.Dataset.DoubleVariables;
     262        foreach (var solution2 in solutions) {
     263          if (solution1 == solution2)
     264            continue;
     265          var variables2 = solution2.ProblemData.Dataset.DoubleVariables;
     266          if (!variables1.All(variables2.Contains))
     267            return false;
    265268        }
    266       } else {
    267         for (int i = 0; i < variables.Count; ++i) {
    268           var variableValue = ProblemData.Dataset.GetDoubleValue(variables[i], Row);
    269           variableValues[i] = new List<double> { variableValue };
    270         }
    271       }
    272       sharedDataset = new ModifiableDataset(variables, variableValues);
    273     }
    274 
    275     private Series PlotSeries(IRegressionSolution solution) {
    276       var v = sharedDataset.GetDoubleValue(variable, 0);
    277       var series = new Series { ChartType = SeriesChartType.Point };
    278       // get values from series
    279       var xvalues = internalDataset.GetReadOnlyDoubleValues(Variable);
    280       var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows));
    281       int i = 0;
    282       foreach (var y in yvalues) {
    283         var x = xvalues[i++];
    284         series.Points.Add(new DataPoint(x, y) { MarkerSize = 2, MarkerColor = Color.DodgerBlue });
    285       }
    286       if (ShowCursor) {
    287         var y = solution.Model.GetEstimatedValues(sharedDataset, new[] { 0 }).Single();
    288         series.Points.Add(new DataPoint(v, y) { MarkerSize = 5, MarkerColor = Color.Red });
    289       }
    290       if (ShowLegend) {
    291         series.IsVisibleInLegend = true;
    292       }
    293       return series;
    294     }
    295 
    296     private void AddLegends() {
    297       Legends.Clear();
    298       var legend = new Legend();
    299       legend.Alignment = StringAlignment.Center;
    300       legend.LegendStyle = LegendStyle.Row;
    301       legend.Docking = Docking.Top;
    302       Legends.Add(legend);
    303       foreach (var s in Series) {
    304         s.Legend = legend.Name;
    305       }
    306     }
    307 
    308     private void AddStripLines() {
    309       var axisX = ChartAreas[0].AxisX;
    310       axisX.StripLines.Clear();
    311       axisX.StripLines.Add(new StripLine { BackColor = Color.FromArgb(30, Color.Green), IntervalOffset = axisX.Minimum, StripWidth = min - axisX.Minimum });
    312       axisX.StripLines.Add(new StripLine { BackColor = Color.FromArgb(30, Color.Green), IntervalOffset = max, StripWidth = axisX.Maximum - max });
    313     }
    314 
    315     private void RegisterEvents() {
    316       AnnotationPositionChanging += chart_AnnotationPositionChanging;
    317       MouseMove += chart_MouseMove;
    318       FormatNumber += chart_FormatNumber;
     269      }
     270      return true;
     271    }
     272
     273    private void UpdateStripLines() {
     274      var axisX = chart.ChartAreas[0].AxisX;
     275      var lowerStripLine = axisX.StripLines[0];
     276      var upperStripLine = axisX.StripLines[1];
     277
     278      lowerStripLine.IntervalOffset = axisX.Minimum;
     279      lowerStripLine.StripWidth = trainingMin - axisX.Minimum;
     280
     281      upperStripLine.IntervalOffset = trainingMax;
     282      upperStripLine.StripWidth = axisX.Maximum - trainingMax;
    319283    }
    320284
     
    327291    }
    328292
    329     public event EventHandler ChartPropertyChanged;
    330     public void OnChartPropertyChanged(object sender, EventArgs args) {
    331       var changed = ChartPropertyChanged;
    332       if (changed == null) return;
    333       changed(sender, args);
    334     }
    335 
    336293    private void chart_AnnotationPositionChanged(object sender, EventArgs e) {
    337294      var annotation = VerticalLineAnnotation;
    338295      var x = annotation.X;
    339       sharedDataset.SetVariableValue(x, Variable, 0);
    340       for (int i = 0; i < solutionList.Count; ++i) {
    341         var y = solutionList[i].Model.GetEstimatedValues(sharedDataset, new[] { 0 }).Single();
    342         var s = Series[i];
    343         var n = s.Points.Count;
    344         s.Points[n - 1] = new DataPoint(x, y) { MarkerColor = Color.Red, MarkerSize = 5 };
    345       }
    346       if (ShowXAxisLabel) {
    347         ChartAreas[0].AxisX.Title = Variable + " : " + x.ToString("N3", CultureInfo.CurrentCulture);
    348       }
    349       Update();
     296      sharedFixedVariables.SetVariableValue(x, FreeVariable, 0);
     297
     298      chart.ChartAreas[0].AxisX.Title = FreeVariable + " : " + x.ToString("N3", CultureInfo.CurrentCulture);
     299      chart.Update();
     300
    350301      OnVariableValueChanged(this, EventArgs.Empty);
    351302    }
    352303
    353304    private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
    354       var step = (max - min) / points;
    355       e.NewLocationX = step * (long)Math.Round(e.NewLocationX / step);
    356       var axisX = ChartAreas[0].AxisX;
    357       if (e.NewLocationX > axisX.Maximum)
    358         e.NewLocationX = axisX.Maximum;
    359       if (e.NewLocationX < axisX.Minimum)
    360         e.NewLocationX = axisX.Minimum;
     305      //var step = (trainingMax - trainingMin) / drawingSteps;
     306      //e.NewLocationX = step * (long)Math.Round(e.NewLocationX / step);
     307      //var axisX = chart.ChartAreas[0].AxisX;
     308      //if (e.NewLocationX > axisX.Maximum)
     309      //  e.NewLocationX = axisX.Maximum;
     310      //if (e.NewLocationX < axisX.Minimum)
     311      //  e.NewLocationX = axisX.Minimum;
     312
     313      var annotation = VerticalLineAnnotation;
     314      var x = annotation.X;
     315      sharedFixedVariables.SetVariableValue(x, FreeVariable, 0);
     316
     317      chart.ChartAreas[0].AxisX.Title = FreeVariable + " : " + x.ToString("N3", CultureInfo.CurrentCulture);
     318      chart.Update();
     319
     320      OnVariableValueChanged(this, EventArgs.Empty);
    361321    }
    362322
    363323    private void chart_MouseMove(object sender, MouseEventArgs e) {
    364       this.Cursor = HitTest(e.X, e.Y).ChartElementType == ChartElementType.Annotation ? Cursors.VSplit : Cursors.Default;
     324      chart.Cursor = chart.HitTest(e.X, e.Y).ChartElementType == ChartElementType.Annotation ? Cursors.VSplit : Cursors.Default;
    365325    }
    366326
     
    388348      }
    389349    }
    390 
    391350    private void GradientChart_DragEnter(object sender, DragEventArgs e) {
    392351      if (!e.Data.GetDataPresent(HeuristicLab.Common.Constants.DragDropDataFormat)) return;
Note: See TracChangeset for help on using the changeset viewer.