/// <summary>
 /// Makes a function to plot a histogram with a given number of bins.
 /// </summary>
 /// <returns>The hist function which takes the individual data values as well
 /// as the number of desired bins and returns the figure variable name.</returns>
 /// <param name="plotLabels">The labeling of the plot</param>
 /// <param name="normalize">If true, histogram will be normalized to sum 1</param>
 /// <param name="gridStyle">Grid style.</param>
 /// <param name="despine">If set to <c>true</c> despine.</param>
 public Func <double[], int, string> MakeHistFunction(PlotDecorators plotLabels, bool normalize = false
                                                      , bool cumulative = false, AxesStyle gridStyle = AxesStyle.whitegrid, bool despine = true)
 {
     return((x, nbins) =>
     {
         if (IsDisposed)
         {
             throw new ObjectDisposedException("PyPlotInterface");
         }
         if (x == null)
         {
             throw new ArgumentNullException("x", "Data series has to exist");
         }
         if (nbins < 1)
         {
             throw new ArgumentOutOfRangeException("nbins", "nbins has to be >=1");
         }
         //plot
         SetAxesStyle(gridStyle);                   //sets the plotting style
         string figName = Subplots();               //creates figure and axis
         CallHist(x, nbins, normalize, cumulative); //draw histogram
         Decorate(plotLabels);                      //adds title and axis label decorations
         if (despine)
         {
             Despine();     //uses seaborn to remove the top and right spine
         }
         TerminateIndent(); //leaves the indented block structure
         Flush();           //forces transfer to python process
         return figName;
     });
 }
        /// <summary>
        /// Makes an x,y line plot function.
        /// </summary>
        /// <returns>The plot function which takes an x and optionally
        /// y series and returns the figure varible name.</returns>
        /// <param name="plotLabels">The labeling of the plot</param>
        /// <param name="AxesStyle">Seaborn axes plot style</param>
        /// <param name="despine">If set to <c>true</c> despine the plot using seaborn.</param>
        public Func <double[], double[], string> MakePlotFunction(PlotDecorators plotLabels
                                                                  , AxesStyle gridStyle = AxesStyle.whitegrid, bool despine = true)
        {
            return((x, y) =>
            {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException("PyPlotInterface");
                }
                if (x == null)
                {
                    throw new ArgumentNullException("x", "X series has to exist");
                }
                if (y != null && y.Length != x.Length)
                {
                    throw new ArgumentException("If y series is present it needs to have same length as x series");
                }


                //plot
                SetAxesStyle(gridStyle);     //sets the plotting style
                string figName = Subplots(); //creates figure and axis
                PlotColor?col = Cycle(plotLabels.ColorCycle, 0);
                CallPlot(x, y, col);         //plots the data on the axis object
                Decorate(plotLabels);        //adds title and axis label decorations
                if (despine)
                {
                    Despine();          //uses seaborn to remove the top and right spine
                }
                TerminateIndent();      //leaves the indented block structure
                Flush();                //forces transfer to python process
                return figName;
            });
        }
 /// <summary>
 /// Decorates a plot by adding title and labels, limits, etc.
 /// </summary>
 /// <param name="PlotLabels">The plot labels</param>
 private void Decorate(PlotDecorators plotLabels)
 {
     if (plotLabels.XLabel != null && plotLabels.XLabel != "")
     {
         WriteLine("ax.set_xlabel('{0}')", plotLabels.XLabel);
     }
     if (plotLabels.YLabel != null && plotLabels.YLabel != "")
     {
         WriteLine("ax.set_ylabel('{0}')", plotLabels.YLabel);
     }
     if (plotLabels.Title != null && plotLabels.Title != "")
     {
         WriteLine("ax.set_title('{0}')", plotLabels.Title);
     }
     if (plotLabels.XLims != null)
     {
         WriteLine("ax.set_xlim({0},{1})", plotLabels.XLims.Item1, plotLabels.XLims.Item2);
     }
     if (plotLabels.YLims != null)
     {
         WriteLine("ax.set_ylim({0},{1})", plotLabels.YLims.Item1, plotLabels.YLims.Item2);
     }
 }
        /// <summary>
        /// Makes a plot function for multiple x/y series.
        /// </summary>
        /// <returns>The plot function which takes multiple x and optionall y series
        /// and returns the figure variable name</returns>
        /// <param name="plotLabels">The labeling of the plot</param>
        /// <param name="AxesStyle">Seaborn axes plot style</param>
        /// <param name="despine">If set to <c>true</c> despine the plot using seaborn.</param>
        public Func <List <double[]>, List <double[]>, string> MakeSeriesPlotFunction(PlotDecorators plotLabels
                                                                                      , AxesStyle gridStyle = AxesStyle.whitegrid, bool despine = true)
        {
            return((list_x, list_y) =>
            {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException("PyPlotInterface");
                }
                if (list_x == null)
                {
                    throw new ArgumentNullException("x", "X series have to exist");
                }
                if (list_y != null && list_x.Count != 1 && list_y.Count != list_x.Count)
                {
                    throw new ArgumentException("If y series are present there either needs to be exactly" +
                                                "one x-series or one x-series object per y series!");
                }

                //make sure that all corresponding series have the same length
                if (list_y != null)
                {
                    if (list_x.Count == 1)
                    {
                        foreach (double[] y in list_y)
                        {
                            if (y.Length != list_x[0].Length)
                            {
                                throw new ArgumentException("At least one y-series did not have same length as x-series");
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < list_x.Count; i++)
                        {
                            if (list_x[i].Length != list_y[i].Length)
                            {
                                throw new ArgumentException("At least one y-series did not have same length as corresponding x-series");
                            }
                        }
                    }
                }


                //plot
                SetAxesStyle(gridStyle);                //sets the plotting style
                string figName = Subplots();            //creates figure and axis
                if (list_y == null)
                {
                    for (int i = 0; i < list_x.Count; i++)
                    {
                        PlotColor?col = Cycle(plotLabels.ColorCycle, i);
                        CallPlot(list_x[i], null, col);
                    }
                }
                else
                {
                    if (list_x.Count == 1)
                    {
                        for (int i = 0; i < list_y.Count; i++)
                        {
                            PlotColor?col = Cycle(plotLabels.ColorCycle, i);
                            CallPlot(list_x[0], list_y[i], col);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < list_x.Count; i++)
                        {
                            PlotColor?col = Cycle(plotLabels.ColorCycle, i);
                            CallPlot(list_x[i], list_y[i], col);
                        }
                    }
                }
                Decorate(plotLabels);//adds title and axis label decorations
                if (despine)
                {
                    Despine();          //uses seaborn to remove the top and right spine
                }
                TerminateIndent();      //leaves the indented block structure
                Flush();                //forces transfer to python process
                return figName;
            });
        }