Changeset 14161


Ignore:
Timestamp:
07/21/16 16:57:58 (8 months ago)
Author:
mkommend
Message:

#2594: Merged r13764, r13765, r13807, r14007, r14008, r14014, r14152, r14155, r14156, r14159 to stable.

Location:
stable
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Views

  • stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionLineChartView.cs

    r12009 r14161  
    2626using System.Windows.Forms.DataVisualization.Charting;
    2727using HeuristicLab.MainForm;
     28using HeuristicLab.Visualization.ChartControlsExtensions;
    2829
    2930namespace HeuristicLab.Problems.DataAnalysis.Views {
     
    9697        this.ToggleSeriesData(this.chart.Series[ESTIMATEDVALUES_ALL_SERIES_NAME]);
    9798
     99        // set the y-axis bounds
     100        var axisY = this.chart.ChartAreas[0].AxisY;
     101        double min = double.MaxValue, max = double.MinValue;
     102        foreach (var point in chart.Series.SelectMany(x => x.Points)) {
     103          if (!point.YValues.Any() || double.IsInfinity(point.YValues[0]) || double.IsNaN(point.YValues[0]))
     104            continue;
     105          var y = point.YValues[0];
     106          if (y < min)
     107            min = y;
     108          if (y > max)
     109            max = y;
     110        }
     111
     112        double axisMin, axisMax, axisInterval;
     113        ChartUtil.CalculateOptimalAxisInterval(min, max, out axisMin, out axisMax, out axisInterval);
     114        axisY.Minimum = axisMin;
     115        axisY.Maximum = axisMax;
     116        axisY.Interval = axisInterval;
     117
    98118        UpdateCursorInterval();
    99119        this.UpdateStripLines();
  • stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionScatterPlotView.cs

    r14112 r14161  
    2626using HeuristicLab.MainForm;
    2727using HeuristicLab.MainForm.WindowsForms;
     28using HeuristicLab.Visualization.ChartControlsExtensions;
    2829
    2930namespace HeuristicLab.Problems.DataAnalysis.Views {
     
    169170        double min = Content.EstimatedTrainingValues.Concat(Content.EstimatedTestValues.Concat(Content.EstimatedValues.Concat(dataset.GetDoubleValues(targetVariableName)))).Min();
    170171
    171         max = max + 0.2 * Math.Abs(max);
    172         min = min - 0.2 * Math.Abs(min);
    173 
    174         double interestingValuesRange = max - min;
    175         int digits = Math.Max(0, 3 - (int)Math.Log10(interestingValuesRange));
    176 
    177         max = Math.Round(max, digits);
    178         min = Math.Round(min, digits);
    179 
    180         this.chart.ChartAreas[0].AxisX.Maximum = max;
    181         this.chart.ChartAreas[0].AxisX.Minimum = min;
    182         this.chart.ChartAreas[0].AxisY.Maximum = max;
    183         this.chart.ChartAreas[0].AxisY.Minimum = min;
     172        double axisMin, axisMax, axisInterval;
     173        ChartUtil.CalculateOptimalAxisInterval(min, max, out axisMin, out axisMax, out axisInterval);
     174        this.chart.ChartAreas[0].AxisX.Maximum = axisMax;
     175        this.chart.ChartAreas[0].AxisX.Minimum = axisMin;
     176        this.chart.ChartAreas[0].AxisX.Interval = axisInterval;
     177        this.chart.ChartAreas[0].AxisY.Maximum = axisMax;
     178        this.chart.ChartAreas[0].AxisY.Minimum = axisMin;
     179        this.chart.ChartAreas[0].AxisY.Interval = axisInterval;
     180
    184181        UpdateCursorInterval();
    185182      }
  • stable/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ChartUtil.cs

    r13765 r14161  
    2727  public static class ChartUtil {
    2828    public static void CalculateAxisInterval(double min, double max, int ticks, out double axisMin, out double axisMax, out double axisInterval) {
    29       var dmin = min.Decimals();
    30       axisMin = min.Floor(dmin);
    31       var range = max - axisMin;
    32       var slice = range / ticks;
    33       var dslice = slice.Decimals();
    34       var floor = slice.Floor(dslice);
    35       var ceil = slice.Ceil(dslice);
    36       var axisRange = floor * ticks;
    37       axisInterval = floor;
    38       if (axisRange < max - axisMin) {
    39         axisRange = ceil * ticks;
    40         axisInterval = ceil;
     29      if (double.IsInfinity(min) || double.IsNaN(min) || double.IsInfinity(max) || double.IsNaN(max) || (min >= max))
     30        throw new ArgumentOutOfRangeException("Invalid range provided.");
     31
     32      var range = max - min;
     33      var dRange = (int)Math.Round(Math.Log10(range));
     34      int decimalRank = dRange - 1;
     35      var aMin = min.RoundDown(decimalRank);
     36      var aMax = max.RoundUp(decimalRank);
     37
     38      // if one of the interval ends is a multiple of 5 or 10, change the other interval end to be a multiple as well
     39      if ((aMin.Mod(5).IsAlmost(0) || aMin.Mod(10).IsAlmost(0)) && Math.Abs(aMax) >= 5 && !(aMax.Mod(5).IsAlmost(0) || aMax.Mod(10).IsAlmost(0))) {
     40        aMax = Math.Min(aMax + 5 - aMax % 5, aMax + 10 - aMax % 10);
     41      } else if ((aMax.Mod(5).IsAlmost(0) || aMax.Mod(10).IsAlmost(0)) && Math.Abs(aMin) >= 5 && !(aMin.Mod(5).IsAlmost(0) || aMin.Mod(10).IsAlmost(0))) {
     42        aMin = Math.Max(aMin - aMin.Mod(5), aMin - aMin.Mod(10));
    4143      }
    42       axisMax = axisMin + axisRange;
     44
     45      axisMin = aMin;
     46      axisMax = aMax;
     47      axisInterval = (aMax - aMin) / ticks;
    4348    }
    4449
     50    /// <summary>
     51    /// Tries to find an axis interval with as few fractional digits as possible (because it looks nicer).  we only try between 3 and 5 ticks (inclusive) because it wouldn't make sense to exceed this interval.
     52    /// </summary>
     53    public static void CalculateOptimalAxisInterval(double min, double max, out double axisMin, out double axisMax, out double axisInterval) {
     54      CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
     55      int bestLsp = int.MaxValue;
     56      for (int ticks = 3; ticks <= 5; ++ticks) {
     57        double aMin, aMax, aInterval;
     58        CalculateAxisInterval(min, max, ticks, out aMin, out aMax, out aInterval);
     59        var x = aInterval;
     60        int lsp = 0; // position of the least significant fractional digit
     61        while (x - Math.Floor(x) > 0) {
     62          ++lsp;
     63          x *= 10;
     64        }
     65        if (lsp <= bestLsp) {
     66          axisMin = aMin;
     67          axisMax = aMax;
     68          axisInterval = aInterval;
     69          bestLsp = lsp;
     70        }
     71      }
     72    }
     73
     74    // find the number of decimals needed to represent the value
    4575    private static int Decimals(this double x) {
    46       if (double.IsInfinity(x) || double.IsNaN(x))
     76      if (x.IsAlmost(0) || double.IsInfinity(x) || double.IsNaN(x))
    4777        return 0;
    4878
    4979      var v = Math.Abs(x);
    50       int d = 0;
     80      int d = 1;
    5181      while (v < 1) {
    5282        v *= 10;
     
    5484      }
    5585      return d;
     86    }
     87
     88    private static double RoundDown(this double value, int decimalRank) {
     89      if (decimalRank > 0) {
     90        var floor = (int)Math.Floor(value);
     91        var pow = (int)Math.Pow(10, decimalRank);
     92        var mod = Mod(floor, pow);
     93        return floor - mod;
     94      }
     95      return value.Floor(Math.Abs(decimalRank));
     96    }
     97
     98    private static double RoundUp(this double value, int decimalRank) {
     99      if (decimalRank > 0) {
     100        var ceil = (int)Math.Ceiling(value);
     101        var pow = (int)Math.Pow(10, decimalRank);
     102        var mod = Mod(ceil, pow);
     103        return ceil - mod + pow;
     104      }
     105      return value.Ceil(Math.Abs(decimalRank));
     106    }
     107
     108    private static double RoundNearest(this double value, int decimalRank) {
     109      var nearestDown = value.RoundDown(decimalRank);
     110      var nearestUp = value.RoundUp(decimalRank);
     111
     112      if (nearestUp - value > value - nearestDown)
     113        return nearestDown;
     114
     115      return nearestUp;
    56116    }
    57117
     
    62122    }
    63123
     124    // rounds up to the nearest value according to the given number of decimal precision
    64125    private static double Ceil(this double value, int precision) {
    65126      var n = Math.Pow(10, precision);
     
    67128    }
    68129
    69     private static double Round(this double value, int precision) {
    70       var n = Math.Pow(10, precision);
    71       return Math.Round(Math.Round(value * n) / n, precision);
     130    private static bool IsAlmost(this double value, double other, double eps = 1e-12) {
     131      return Math.Abs(value - other) < eps;
     132    }
     133
     134    private static double Mod(this double a, double b) {
     135      return a - b * Math.Floor(a / b);
    72136    }
    73137  }
  • stable/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLab.Visualization.ChartControlsExtensions-3.3.csproj

    r11920 r14161  
    121121  </ItemGroup>
    122122  <ItemGroup>
     123    <Compile Include="ChartUtil.cs" />
    123124    <Compile Include="EnhancedChart.cs">
    124125      <SubType>Component</SubType>
Note: See TracChangeset for help on using the changeset viewer.