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;
            }
        }
예제 #2
0
        private IList <DensityTrackbar> CreateConfiguration()
        {
            var ranges = new List <DoubleLimit>();

            foreach (string variableName in variableNames)
            {
                var    values = Content.ProblemData.Dataset.GetDoubleValues(variableName, Content.ProblemData.AllIndices);
                double min, max, interval;
                ChartUtil.CalculateAxisInterval(values.Min(), values.Max(), 10, out min, out max, out interval);
                ranges.Add(new DoubleLimit(min, max));
            }

            var newTrackbars = new List <DensityTrackbar>();

            for (int i = 0; i < variableNames.Count; i++)
            {
                var name         = variableNames[i];
                var trainingData = Content.ProblemData.Dataset.GetDoubleValues(name, Content.ProblemData.TrainingIndices).ToList();

                var dimensionTrackbar = new DensityTrackbar(name, ranges[i], trainingData)
                {
                    Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
                };
                newTrackbars.Add(dimensionTrackbar);
            }

            return(newTrackbars);
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        private static void SetupAxis(EnhancedChart chart, Axis axis, double minValue, double maxValue, int ticks, double?fixedAxisMin, double?fixedAxisMax)
        {
            //guard if only one distinct value is present
            if (minValue.IsAlmost(maxValue))
            {
                minValue = minValue - 0.5;
                maxValue = minValue + 0.5;
            }

            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;

            chart.ChartAreas[0].RecalculateAxesScale();
        }
예제 #5
0
        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
            }
        }
예제 #6
0
        private void RecalculateTrainingLimits(bool initializeAxisRanges)
        {
            trainingMin = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Where(x => !double.IsNaN(x)).Min()).Max();
            trainingMax = solutions.Select(s => s.ProblemData.Dataset.GetDoubleValues(freeVariable, s.ProblemData.TrainingIndices).Where(x => !double.IsNaN(x)).Max()).Min();

            if (initializeAxisRanges)
            {
                double xmin, xmax, xinterval;
                //guard if only one distinct value is present
                if (trainingMin.IsAlmost(trainingMax))
                {
                    ChartUtil.CalculateAxisInterval(trainingMin - 0.5, trainingMax + 0.5, XAxisTicks, out xmin, out xmax, out xinterval);
                }
                else
                {
                    ChartUtil.CalculateAxisInterval(trainingMin, trainingMax, XAxisTicks, out xmin, out xmax, out xinterval);
                }

                FixedXAxisMin = xmin;
                FixedXAxisMax = xmax;
            }
        }
예제 #7
0
        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 <double>();

            for (int i = 0; i < drawingSteps; i++)
            {
                xvalues.Add(xmin + i * step);
            }

            var variables = sharedFixedVariables.DoubleVariables.ToList();

            internalDataset = new ModifiableDataset(variables,
                                                    variables.Select(x => x == FreeVariable
          ? xvalues
          : Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(x, 0), xvalues.Count).ToList()
                                                                     )
                                                    );
        }
예제 #8
0
        private async void UpdateConfigurationControls()
        {
            variableNames.Clear();
            trackbars.Clear();

            tableLayoutPanel.SuspendRepaint();
            tableLayoutPanel.SuspendLayout();

            tableLayoutPanel.RowCount = 0;
            tableLayoutPanel.Controls.Clear();

            if (Content == null)
            {
                tableLayoutPanel.ResumeLayout(false);
                tableLayoutPanel.ResumeRepaint(false);
                return;
            }

            variableNames.AddRange(Content.ProblemData.AllowedInputVariables);

            var newTrackbars = CreateConfiguration();

            sharedFixedVariables = new ModifiableDataset(variableNames, newTrackbars.Select(tb => new List <double>(1)
            {
                (double)tb.Value
            }));
            _partialDependencePlot.Configure(new[] { Content }, sharedFixedVariables, variableNames.First(), DrawingSteps);
            await _partialDependencePlot.RecalculateAsync();

            // Add to table and observable lists
            tableLayoutPanel.RowCount = variableNames.Count;
            while (tableLayoutPanel.RowStyles.Count < variableNames.Count)
            {
                tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            }
            for (int i = 0; i < newTrackbars.Count; i++)
            {
                // events registered automatically
                trackbars.Add(newTrackbars[i]);
                tableLayoutPanel.Controls.Add(newTrackbars[i], 0, i);
            }

            tableLayoutPanel.ResumeLayout(true);
            tableLayoutPanel.ResumeRepaint(true);

            // Init Y-axis range
            var    problemData = Content.ProblemData;
            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);
            _partialDependencePlot.FixedYAxisMin = axisMin;
            _partialDependencePlot.FixedYAxisMax = axisMax;

            trackbars.First().Checked = true;
        }
예제 #9
0
        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;

            //guard if only one distinct value is present
            if (trainingMin.IsAlmost(trainingMax))
            {
                ChartUtil.CalculateAxisInterval(trainingMin - 0.5, trainingMin + 0.5, XAxisTicks, out xmin, out xmax, out xinterval);
            }
            else
            {
                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 <double>();

            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 <IList>();

            foreach (var varName in variables)
            {
                if (varName == FreeVariable)
                {
                    values.Add(xvalues);
                }
                else if (sharedFixedVariables.VariableHasType <double>(varName))
                {
                    values.Add(Enumerable.Repeat(sharedFixedVariables.GetDoubleValue(varName, 0), xvalues.Count).ToList());
                }
                else if (sharedFixedVariables.VariableHasType <string>(varName))
                {
                    values.Add(Enumerable.Repeat(sharedFixedVariables.GetStringValue(varName, 0), xvalues.Count).ToList());
                }
            }

            internalDataset = new ModifiableDataset(variables, values);
        }
        protected override void OnContentChanged()
        {
            base.OnContentChanged();
            if (Content == null)
            {
                return;
            }
            var problemData = Content.ProblemData;

            if (sharedFixedVariables != null)
            {
                sharedFixedVariables.ItemChanged -= SharedFixedVariables_ItemChanged;
                sharedFixedVariables.Reset       -= SharedFixedVariables_Reset;
            }

            // 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 <string>(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 <double>);
            var doubleVariableValues = (IEnumerable <IList>)doubleVariables.Select(x => new List <double> {
                problemData.Dataset.GetDoubleValue(x, 0)
            });

            var factorVariables      = allowedInputVariables.Where(problemData.Dataset.VariableHasType <string>);
            var factorVariableValues = (IEnumerable <IList>)factorVariables.Select(x => new List <string> {
                problemData.Dataset.GetStringValue(x, 0)
            });

            sharedFixedVariables = new ModifiableDataset(doubleVariables.Concat(factorVariables), doubleVariableValues.Concat(factorVariableValues));
            variableValuesModeComboBox.SelectedItem = "Median"; // triggers UpdateVariableValue and changes shardFixedVariables

            // 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 (scrollpanel, ...)
                // 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 (scrollpanel, ...)
                // 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;
            sharedFixedVariables.Reset       += SharedFixedVariables_Reset;

            rowNrNumericUpDown.Maximum = Content.ProblemData.Dataset.Rows - 1;

            RecalculateAndRelayoutCharts();
        }
예제 #11
0
        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
            var allowedInputVariables = Content.ProblemData.AllowedInputVariables;
            var variableValues        = allowedInputVariables.Select(x => new List <double> {
                problemData.Dataset.GetDoubleValues(x, problemData.TrainingIndices).Median()
            });
            var sharedFixedVariables = new ModifiableDataset(allowedInputVariables, variableValues);

            // create controls
            gradientCharts.Clear();
            densityCharts.Clear();
            groupingPanels.Clear();
            foreach (var variableName in allowedInputVariables)
            {
                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 += OnGradientChartOnChartPostPaint;

                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;

            RecalculateAndRelayoutCharts();
        }