Exemplo n.º 1
0
        /// <summary>
        /// Retrieves the data points of the current active plot.
        /// </summary>
        /// <param name="ctrl">The graph controller which controls the graph from which the points are to retrieve.</param>
        /// <param name="xarr">The array of the data point's x values.</param>
        /// <param name="yarr">The array of the data point's y values.</param>
        /// <returns>Null if all is ok, or error message if not.</returns>
        public static string GetActivePlotPoints(Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl, out double[] xarr, out double[] yarr)
        {
            var xlist = new List <double>();
            var ylist = new List <double>();

            xarr = yarr = null;

            ctrl.EnsureValidityOfCurrentLayerNumber();
            ctrl.EnsureValidityOfCurrentPlotNumber();
            var xylayer = ctrl.ActiveLayer as XYPlotLayer;

            if (null == xylayer || ctrl.CurrentPlotNumber < 0)
            {
                return("No active plot available");
            }

            IGPlotItem plotItem = xylayer.PlotItems.Flattened[ctrl.CurrentPlotNumber];

            var xyPlotItem = plotItem as XYColumnPlotItem;

            if (xyPlotItem == null)
            {
                return("No active plot!");
            }

            XYColumnPlotData data = xyPlotItem.XYColumnPlotData;

            if (data == null)
            {
                return("Active plot item has no data");
            }

            if (!(data.XColumn is Altaxo.Data.INumericColumn) || !(data.YColumn is Altaxo.Data.INumericColumn))
            {
                return("X-Y values of plot data are not both numeric");
            }

            var xcol = (Altaxo.Data.INumericColumn)data.XColumn;
            var ycol = (Altaxo.Data.INumericColumn)data.YColumn;

            int maxRowIndex = data.GetMaximumRowIndexFromDataColumns();

            foreach (int i in data.DataRowSelection.GetSelectedRowIndicesFromTo(0, maxRowIndex, data.DataTable?.DataColumns, maxRowIndex))
            {
                double x = xcol[i];
                double y = ycol[i];

                if (double.IsNaN(x) || double.IsNaN(y))
                {
                    continue;
                }

                xlist.Add(x);
                ylist.Add(y);
            }

            xarr = xlist.ToArray();
            yarr = ylist.ToArray();
            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get the names of the x and y column of the active plot.
        /// </summary>
        /// <param name="ctrl">The current active graph controller.</param>
        /// <returns>An array of two strings. The first string is the name of the x-column, the second
        /// the name of the y-column.</returns>
        public static string[] GetActivePlotName(Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl)
        {
            string[] result = new string[2] {
                string.Empty, string.Empty
            };

            var xylayer = ctrl.ActiveLayer as XYPlotLayer;

            if (null == xylayer || ctrl.CurrentPlotNumber < 0)
            {
                return(result);
            }

            IGPlotItem plotItem = xylayer.PlotItems.Flattened[ctrl.CurrentPlotNumber];

            var xyPlotItem = plotItem as XYColumnPlotItem;

            if (xyPlotItem == null)
            {
                return(result);
            }

            XYColumnPlotData data = xyPlotItem.XYColumnPlotData;

            if (data == null)
            {
                return(result);
            }

            result[0] = data.XColumn.FullName;
            result[1] = data.YColumn.FullName;

            return(result);
        }
Exemplo n.º 3
0
        public static string ShowFitDialog(Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl)
        {
            var tuple = SelectFitDocument(ctrl);

            if (!string.IsNullOrEmpty(tuple.Item1))
            {
                return(tuple.Item1);
            }

            var fitDocument           = tuple.Item2;
            var fitDocumentIdentifier = tuple.Item3;
            var activeLayer           = tuple.Item4;

            // we assume we have a fit document by now
            if (null == tuple.Item2)
            {
                throw new InvalidProgramException("At this place, fit document should always be != null");
            }

            if (!string.IsNullOrEmpty(fitDocumentIdentifier))
            {
                var answer = Current.Gui.YesNoCancelMessageBox(
                    "At least one fit function plot item was found in the document from which the fit document could be retrieved.\r\n" +
                    "When changing the fit or the parameters, these fit function plot items would be changed, too.\r\n" +
                    "Sometimes, you might want to keep the previous fit function plot items, e.g. in order to compare them with the new ones.\r\n" +
                    "\r\n" +
                    "Do you want to keep the previous fit function plot item(s) ?",
                    "Keep previous fit function plot items?", false);

                if (null == answer)
                {
                    return(null);
                }
                if (true == answer)
                {
                    fitDocumentIdentifier = null; // by setting the identifier to null, we will keep the old fit functions
                }
            }

            var fitController = (Gui.IMVCANController)Current.Gui.GetControllerAndControl(new object[] { fitDocument, fitDocumentIdentifier, activeLayer }, typeof(Gui.IMVCANController));

            // before showing the fit dialog, deselect all objects selected
            if (!ctrl.SelectedObjects.IsReadOnly) // with some graph tools, this is a read-only collection, which can not be cleared
            {
                ctrl.SelectedObjects.Clear();
            }

            if (true == Current.Gui.ShowDialog(fitController, "Non-linear fitting"))
            {
                var localdoc = fitController.ModelObject as NonlinearFitDocument;
                // store the fit document in the graphs property
                ctrl.Doc.SetGraphProperty(FitDocumentPropertyName, localdoc);

                _lastFitDocument = (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)localdoc.Clone();
            }

            return(null);
        }
Exemplo n.º 4
0
        public static string Fit(Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl, int order, double fitCurveXmin, double fitCurveXmax, bool showFormulaOnGraph)
        {
            string error;

            error = GetActivePlotPoints(ctrl, out var xarr, out var yarr);
            int numberOfDataPoints = xarr.Length;

            if (null != error)
            {
                return(error);
            }

            string[] plotNames = GetActivePlotName(ctrl);

            int numberOfParameter = order + 1;

            double[] parameter = new double[numberOfParameter];

            var fit = LinearFitBySvd.FitPolymomialDestructive(order, xarr, yarr, null, numberOfDataPoints);

            // Output of results

            Current.Console.WriteLine("");
            Current.Console.WriteLine("---- " + DateTime.Now.ToString() + " -----------------------");
            Current.Console.WriteLine("Polynomial regression of order {0} of {1} over {2}", order, plotNames[1], plotNames[0]);

            Current.Console.WriteLine(
                "Name           Value               Error               F-Value             Prob>F");

            for (int i = 0; i < fit.Parameter.Length; i++)
            {
                Current.Console.WriteLine("A{0,-3} {1,20} {2,20} {3,20} {4,20}",
                                          i,
                                          fit.Parameter[i],
                                          fit.StandardErrorOfParameter(i),
                                          fit.TofParameter(i),
                                          1 - FDistribution.CDF(fit.TofParameter(i), numberOfParameter, numberOfDataPoints - 1)
                                          );
            }

            Current.Console.WriteLine("R²: {0}, Adjusted R²: {1}",
                                      fit.RSquared,
                                      fit.AdjustedRSquared);

            Current.Console.WriteLine("Condition number: {0}, Loss of precision (digits): {1}", fit.ConditionNumber, Math.Log10(fit.ConditionNumber));

            Current.Console.WriteLine("------------------------------------------------------------");
            Current.Console.WriteLine("Source of  Degrees of");
            Current.Console.WriteLine("variation  freedom          Sum of Squares          Mean Square          F0                   P value");

            double regressionmeansquare = fit.RegressionCorrectedSumOfSquares / numberOfParameter;
            double residualmeansquare   = fit.ResidualSumOfSquares / (numberOfDataPoints - numberOfParameter - 1);

            Current.Console.WriteLine("Regression {0,10} {1,20} {2,20} {3,20} {4,20}",
                                      numberOfParameter,
                                      fit.RegressionCorrectedSumOfSquares,
                                      fit.RegressionCorrectedSumOfSquares / numberOfParameter,
                                      regressionmeansquare / residualmeansquare,
                                      1 - FDistribution.CDF(regressionmeansquare / residualmeansquare, numberOfParameter, numberOfDataPoints - 1)
                                      );

            Current.Console.WriteLine("Residual   {0,10} {1,20} {2,20}",
                                      numberOfDataPoints - 1 - numberOfParameter,
                                      fit.ResidualSumOfSquares,
                                      residualmeansquare
                                      );

            Current.Console.WriteLine("Total      {0,10} {1,20}",
                                      numberOfDataPoints - 1,
                                      fit.TotalCorrectedSumOfSquares

                                      );

            Current.Console.WriteLine("------------------------------------------------------------");

            // add the fit curve to the graph
            IScalarFunctionDD plotfunction = new PolynomialFunction(fit.Parameter);
            var fittedCurve = new XYFunctionPlotItem(new XYFunctionPlotData(plotfunction), new G2DPlotStyleCollection(LineScatterPlotStyleKind.Line, ctrl.Doc.GetPropertyContext()));

            var xylayer = ctrl.ActiveLayer as XYPlotLayer;

            if (null != xylayer)
            {
                xylayer.PlotItems.Add(fittedCurve);
            }

            return(null);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Gets a new or recycled fit document for a given plot item <see cref="XYColumnPlotItem"/>.
        /// </summary>
        /// <param name="xyPlotItem">The xy plot item.</param>
        /// <param name="ctrl">The control.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">xyPlotItem</exception>
        private static Tuple <string, NonlinearFitDocument, string, XYPlotLayer> GetNewFitDocumentFor(XYColumnPlotItem xyPlotItem, Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl)
        {
            if (null == xyPlotItem)
            {
                throw new ArgumentNullException(nameof(xyPlotItem));
            }

            var activeLayer = Altaxo.Main.AbsoluteDocumentPath.GetRootNodeImplementing <XYPlotLayer>(xyPlotItem);
            var xColumn     = xyPlotItem.XYColumnPlotData.XColumn;
            var yColumn     = xyPlotItem.XYColumnPlotData.YColumn;

            if (xColumn == null || xColumn.ItemType != typeof(double))
            {
                return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>("The x-column is not numeric", null, null, activeLayer));
            }

            if (yColumn == null || yColumn.ItemType != typeof(double))
            {
                return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>("The y-column is not numeric", null, null, activeLayer));
            }

            var localdoc = (ctrl.Doc.GetGraphProperty(FitDocumentPropertyName) as Calc.Regression.Nonlinear.NonlinearFitDocument) ??
                           (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)_lastFitDocument?.Clone() ??
                           new Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument();

            if (localdoc.FitEnsemble.Count == 0) // if there was no fit before
            {
                var fitele = new Altaxo.Calc.Regression.Nonlinear.FitElement(
                    xyPlotItem.Data.DataTable,
                    xyPlotItem.Data.GroupNumber,
                    xyPlotItem.Data.DataRowSelection,
                    xColumn,
                    yColumn);

                localdoc.FitEnsemble.Add(fitele);
            }
            else // there was a fit before, thus localdoc.FitEnsemble.Count>0
            {
                bool hasColumnsChanged = false;

                hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].DataTable, xyPlotItem.Data.DataTable));
                hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].GroupNumber, xyPlotItem.Data.GroupNumber));
                hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].IndependentVariables(0), xColumn));
                hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].DependentVariables(0), yColumn));

                localdoc.FitEnsemble[0].SetIndependentVariable(0, xColumn);
                localdoc.FitEnsemble[0].SetDependentVariable(0, yColumn);

                if (hasColumnsChanged) // if some of the columns has changed, take the data row selection of the plot item
                {
                    localdoc.FitEnsemble[0].DataRowSelection = xyPlotItem.Data.DataRowSelection;
                }
            }

            return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>(string.Empty, localdoc, null, activeLayer));
        }
Exemplo n.º 6
0
        private static Tuple <string, NonlinearFitDocument, string, XYPlotLayer> SelectFitDocument(Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl)
        {
            XYPlotLayer activeLayer = null;

            // is a nonlinear fit function plot item selected ?
            var funcPlotItem = ctrl.SelectedRealObjects.OfType <XYNonlinearFitFunctionPlotItem>().FirstOrDefault();

            if (null != funcPlotItem)
            {
                activeLayer = Altaxo.Main.AbsoluteDocumentPath.GetRootNodeImplementing <XYPlotLayer>(funcPlotItem);
                return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>(string.Empty, funcPlotItem.FitDocumentCopy, funcPlotItem.FitDocumentIdentifier, activeLayer)); // if a fit function plot item was selected, then use the fit document of this item
            }

            // is a normal plot item selected ?
            // ------------------------------------------------------------------------------------
            var columnPlotItem = ctrl.SelectedRealObjects.OfType <XYColumnPlotItem>().FirstOrDefault();

            if (null != columnPlotItem)
            {
                return(SelectFitDocument(ctrl, columnPlotItem));
            }

            // is the active layer an XY-plot layer ? Or do we have any XY-plot-layer ?
            // ------------------------------------------------------------------------------------
            activeLayer = (ctrl.ActiveLayer as XYPlotLayer);
            if (null != activeLayer)
            {
                var result = SelectFitDocument(ctrl, activeLayer);
                if (result.Item2 != null)
                {
                    return(result);
                }
            } // null != activeLayer

            activeLayer = TreeNodeExtensions.TakeFromHereToFirstLeaves(ctrl.Doc.RootLayer).OfType <XYPlotLayer>().FirstOrDefault();
            if (null != activeLayer)
            {
                var result = SelectFitDocument(ctrl, activeLayer);
                if (result.Item2 != null)
                {
                    return(result);
                }
                else
                {
                    var localdoc = (ctrl.Doc.GetGraphProperty(FitDocumentPropertyName) as Calc.Regression.Nonlinear.NonlinearFitDocument) ??
                                   (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)_lastFitDocument?.Clone() ??
                                   new Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument();

                    return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>(null, localdoc, null, activeLayer));
                }
            } // null != activeLayer

            // no idea what to fit - there is not even an XY plot layer
            return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>("The graph has no XYPlotLayer to host any fit function", null, null, null));
        }