def lineplot(self,
                 column_name_draw,
                 column_name_true_values=None,
                 envelope_flag=True,
                 separators_plot=None,
                 palette='PuOr',
                 hue=None,
                 style=None,
                 markers=None,
                 sizes=None,
                 dict_plot_for_main_line={},
                 path_save_plot=None,
                 list_aplots=None,
                 *args,
                 **kwargs):
        list_aplots = [APlot()]
        xx = self.get_values_evolution_column(self.estimator.df)
        list_unique_length = self.get_data2evolution(self.estimator.df,
                                                     column_name_draw)
        rescaled_xx = xx / xx[0] * list_unique_length[0] * 3
        # rescaled_xx2 = rescaled_xx * rescaled_xx

        print(list_unique_length)
        list_aplots[0].uni_plot(0,
                                xx,
                                rescaled_xx,
                                dict_plot_param={
                                    'label': 'o(x)',
                                    'linewidth': 0.9,
                                    'markersize': 0,
                                    'color': 'black'
                                })
        # list_aplots[0].uni_plot(0, xx, rescaled_xx2, dict_plot_param={'label': 'o(x^2)', 'linewidth'  : 0.9,
        #                                                                             'markersize' : 0, 'color' : 'black'})

        current_plots, keys = super().lineplot(
            column_name_draw, column_name_true_values, envelope_flag,
            separators_plot, palette, hue, style, markers, sizes,
            dict_plot_for_main_line, path_save_plot, list_aplots, *args,
            **kwargs)
        return current_plots, keys
    def hist(self,
             column_name_draw,
             separators_plot=None,
             separators_filter=None,
             palette='PuOr',
             hue=None,
             bins=20,
             binrange=None,
             stat='count',
             multiple="stack",
             kde=False,
             path_save_plot=None):
        """
        Semantics:
            histogram plot.
            Issue with seaborn:
                When writing overloading, always draw before using super().
                Otherwise, the legend is not actualised.
                If it is, then seaborn's style in the legend will be erased.

        Args:
            column_name_draw:
            separators_plot:
            separators_filter:
            palette:
            hue:
            bins:
            binrange (pair): borns of the ax.
            stat: Aggregate statistic to compute in each bin.
                'count' shows the number of observations.
                'frequency' shows the number of observations divided by the bin width.
                'density' normalizes counts so that the area of the histogram is 1.
                'probability' normalizes counts so that the sum of the bar heights is 1.
            multiple: Approach to resolving multiple elements when semantic mapping creates subsets.
                {“layer”, “dodge”, “stack”, “fill”}
            kde (bool): If True, compute a kernel density estimate to smooth the distribution and show on the plot as (one or more) line(s). Only relevant with univariate data.
            path_save_plot:

        Returns:

        """
        # super call for gathering all separators together and having the group by done.
        separators, global_dict, keys = super().draw(
            separators_plot=separators_plot)
        keys = filter(separators, keys, separators_filter)
        plots = []
        for key in keys:
            if key is None:  # case where we cannot use groupby.
                data = global_dict
                separators = ["data used"]
                key = ["whole dataset"]  # for the title
            else:
                data = global_dict.get_group(key)

            plot = APlot()
            plots.append(plot)

            # get the good palette (sliced avoiding white.
            palette = self.color_scheme(palette)

            sns.histplot(x=column_name_draw,
                         bins=bins,
                         hue=hue,
                         multiple=multiple,
                         binrange=binrange,
                         legend='full',
                         kde=kde,
                         palette=palette,
                         data=data,
                         ax=plot._axs[0],
                         stat=stat)
            fig_dict = self.get_dict_fig(separators, key)
            plot.set_dict_ax(0, fig_dict)

            if path_save_plot is not None:
                name_file = ''.join(
                    [function_str.tuple_to_str(key, ''), 'evol_estimation'])
                plot.save_plot(name_save_file=name_file)
        return plots
    def draw(self,
             separators=None,
             separator_colour=None,
             kernel_plot_param=None,
             one_kernel_plot_param=None,
             all_kernels_drawn=False):
        """
        plot the evolution of the estimators over the attribute given by get_plot_data.
        It is almost the same version as the upper class, the difference lies in that I m drawing the kernel on the graph additionally.
        I draw the kernels iff I give kernel_plot_param.

        kernel_plot_param for drawing over a list of kernels, one_kernel_plot for drawing the kernels in the middle.

        Args:
            separators:
            separator_colour: the column of the dataframe to consider for color discrimination
            kernel_plot_param: list_of_kernels, Times = kernel_plot_param. Used in order to plot all the decided kernels.
            one_kernel_plot_param:  Plots only the middle kernel. For a centred drawing, pic an even number of times.
            all_kernels_drawn: conditions used when one wants to draw all the kernels on the plot.
        Returns:

        """
        # we use the coloured keys for identifying which colors goes to whom in the one kernel plot case. We assume in the list_of_kernels all name are unique.

        NB_OF_KERNELS_DRAWN = 14

        _, coloured_keys = super().draw(separators, separator_colour)
        if kernel_plot_param is not None:
            list_of_kernels, Times = kernel_plot_param

            # here is all the plots I draw. I start at 1 bc I always plot the parameters as a first drawing.
            list_of_plots = APlot.print_register()[1:]
            # on each plot
            for counter, plots in enumerate(list_of_plots):
                # for each eval point
                for number, (kernel,
                             a_time) in enumerate(zip(list_of_kernels, Times)):
                    condition = all_kernels_drawn or not (
                        len(Times) // NB_OF_KERNELS_DRAWN) or (
                            not number % (len(Times) // NB_OF_KERNELS_DRAWN))
                    if condition:
                        # first : whether I want all kernels to be drawn
                        # the second condition is checking whether len(TIMES) > NB_OF_KERNELS_DRAWN. Otherwise, there is a modulo by 0, which returns an error.
                        # third condition is true for all 14 selected kernels.
                        tt = [np.linspace(0, self.T_max, 3000)]
                        yy = kernel.eval(tt, a_time, self.T_max)
                        plots.uni_plot_ax_bis(nb_ax=0,
                                              xx=tt[0],
                                              yy=yy[0],
                                              dict_plot_param={
                                                  "color": "m",
                                                  "markersize": 0,
                                                  "linewidth": 0.4,
                                                  "linestyle": "--"
                                              },
                                              tight=False)
                        lim_ = plots.axs[0].get_ylim()
                        plots.plot_vertical_line(a_time,
                                                 np.linspace(
                                                     0, lim_[-1] * 0.9, 5),
                                                 nb_ax=0,
                                                 dict_plot_param={
                                                     "color": "k",
                                                     "markersize": 0,
                                                     "linewidth": 0.2,
                                                     "linestyle": "--"
                                                 })
                name_file = 'double_estimation_result_{}'.format(counter)
                plots.save_plot(name_save_file=name_file)

        elif one_kernel_plot_param is not None:
            list_of_kernels, Time = one_kernel_plot_param

            # here is all the plots I draw. I start at 1 bc I always plot the parameters as a first drawing.
            list_of_plots = APlot.print_register()[1:]
            # on each plot
            for counter, plots in enumerate(list_of_plots):
                # for each eval point

                colors = plt.cm.Dark2.colors  # Dark2 is qualitative cm and pretty dark cool colors.

                # we use the coloured keys for identifying which colors goes to whom in the one kernel plot case. We assume in the list_of_kernels all name are unique.
                for number, (kernel_name,
                             color) in enumerate(zip(coloured_keys, colors)):
                    # basically, we retrieve the name and find the matching kernel.
                    kernel_counter = 0
                    kernel = None
                    while kernel is None and kernel_counter < len(
                            list_of_kernels):
                        if list_of_kernels[kernel_counter].name == kernel_name:
                            kernel = list_of_kernels[kernel_counter]
                        else:
                            kernel_counter += 1
                    if kernel_counter > len(
                            list_of_kernels
                    ):  # if he hasn't found the kernel, there is an error.
                        raise Exception(
                            "The kernels given and plotted are not matching.")
                    tt = [
                        np.linspace(self.T_max * 0.05, self.T_max * 0.95, 3000)
                    ]
                    yy = kernel.eval(tt, Time, self.T_max)
                    plots.uni_plot_ax_bis(nb_ax=0,
                                          xx=tt[0],
                                          yy=yy[0],
                                          dict_plot_param={
                                              "color": color,
                                              "markersize": 0,
                                              "linewidth": 0.7,
                                              "linestyle": "--"
                                          },
                                          tight=False)
                # lim_ = plots.axs[0].get_ylim()
                # plots.plot_vertical_line(Time, np.linspace(0, lim_[-1] * 0.9, 5), nb_ax=0,
                #                         dict_plot_param={"color": "k", "markersize": 0, "linewidth": 1,
                #                         "linestyle": "--"})
                name_file = 'double_estimation_result_{}'.format(counter)
                plots.save_plot(name_save_file=name_file)

        return