/// <summary>
        /// Visualization of data from <see cref="WriteTrendToTable"/> in gnuplot
        /// </summary>
        public Plot2Ddata PlotIterationTrend(bool ErrorOrResidual, bool SepVars, bool SepPoly, bool SepLev)
        {
            var Ret = new Plot2Ddata();

            Ret.Title = ErrorOrResidual ? "\"Error trend\"" : "\"Residual trend\"";
            Ret.LogY  = true;

            string[] Titels;
            MultidimensionalArray ConvTrendData;

            WriteTrendToTable(ErrorOrResidual, SepVars, SepPoly, SepLev, out Titels, out ConvTrendData);
            double[] IterNo = ConvTrendData.GetLength(0).ForLoop(i => ((double)i));

            for (int iCol = 0; iCol < Titels.Length; iCol++)
            {
                var g = new Plot2Ddata.XYvalues(Titels[iCol], IterNo, ConvTrendData.GetColumn(iCol));
                g.Format = new PlotFormat(lineColor: ((LineColors)(iCol + 1)), Style: Styles.Lines);
            }

            return(Ret);
        }
        /// <summary>
        /// Visualization of data from <see cref="WriteTrendToTable"/> in gnuplot
        /// </summary>
        public Plot2Ddata Waterfall(bool ErrorOrResidual, int NoOfIter = int.MaxValue)
        {
            var Ret = new Plot2Ddata();

            Ret.Title = (ErrorOrResidual ? "\"Error Waterfall\"" : "\"Residual Waterfall\"");


            //string[] Titels;
            //MultidimensionalArray ConvTrendData;
            //WriteTrendToTable(ErrorOrResidual, SepVars, SepPoly, SepLev, out var Titels, out ConvTrendData);
            var AllData = ErrorOrResidual ? this.ErrNormTrend : this.ResNormTrend;

            int DegMax  = AllData.Keys.Max(tt => tt.deg);
            int MglMax  = AllData.Keys.Max(tt => tt.MGlevel);
            int MaxIter = AllData.First().Value.Count - 1;

            var WaterfallData = new List <double[]>();
            var Row           = new List <double>();
            var xCoords       = new List <double>();

            for (int iIter = 0; iIter <= Math.Min(NoOfIter, MaxIter); iIter++)
            {
                Row.Clear();
                for (int iLv = MglMax; iLv >= 0; iLv--)
                {
                    for (int p = 0; p <= DegMax; p++)
                    {
                        double Acc = 0;

                        foreach (var kv in AllData)
                        {
                            if (kv.Key.deg == p && kv.Key.MGlevel == iLv)
                            {
                                Acc += kv.Value[iIter].Pow2();
                            }
                        }

                        Acc = Acc.Sqrt();
                        Row.Add(Acc);

                        if (iIter == 0)
                        {
                            double xCoord = -iLv + MglMax + 1.0 + (p) * 0.1;
                            xCoords.Add(xCoord);
                        }
                    }
                }

                WaterfallData.Add(Row.ToArray());
            }

            Ret.LogY       = true;
            Ret.ShowLegend = false;

            for (int iIter = 1; iIter <= Math.Min(NoOfIter, MaxIter); iIter++)
            {
                var PlotRow = WaterfallData[iIter];
                var XAxis   = PlotRow.Length.ForLoop(i => i + 1.0);

                var g = new Plot2Ddata.XYvalues("iter" + iIter, XAxis, PlotRow);

                Ret.AddDataGroup(g);
            }
            return(Ret);
        }