def figures_fn(pathss_x=None,
               read_paths_data=False,
               paths_file_name=None,
               beta=4.,
               N_path=10,
               N_iter=int(1e5),
               delta=0.5,
               potential_string='harmonic_potential',
               append_every=1,
               N_plot=201,
               x_max=3,
               N_beta_ticks=11,
               msq_file=None,
               plot_file_name=None,
               show_QHO_theory=True,
               show_matrix_squaring=True,
               show_path=True,
               show_compare_hist=True,
               show_complete_path_hist=True,
               save_plot=True,
               show_plot=True,
               *args,
               **kwargs):
    """
    Uso: 
        Genera figuras del algoritmo path integral naive sampling.

    Recibe:
        pathss_x: list                  ->  contiene paths generados por path_naive_sampling.
        read_paths_data: bool           ->  decide si lee datos. True ignora pathss_x.
        paths_file_name: str            ->  nombre del archivo en que estan guardados datos
                                            de paths. Solo necesario si read_paths_data = True.
                                            Si read_paths_data = True y paths_file_name = None
                                            se intenta abrir archivo con nombre igual al
                                            generado automáticamente por path_naive_sampling y
                                            los parámetros especificados en figures_fn. 
        **kwargs                        ->  argumentos de función path_naive_sampling.
        N_plot: int                     ->  número de puntos para graficar función teórica.
        x_max: int                      ->  límite de eje x en gráfica es (-|x_max|,|x_max|)
        N_beta_ticks: int               ->  Número de valores de beta mostrados al graficar un
                                            camino aleatorio. Recomendable  valor < 12.
        msq_file: str                   ->  archivo en que están guardados datos de algoritmo
                                            matrix squaring para comparar con path integral.
                                            Necesario solo si show_matrix_squaring=True.
        plot_file_name: str             ->  nombre de la figura que se genera. Necesario solo si
                                            show_plot=True.
        show_QHO_theory: bool           ->  decide si muestra valor teórico del oscilador
                                            armónico.
        show_matrix_squaring: bool      ->  decide si muestra resultado de algoritmo Matrix
                                            Squaring. Si True es necesario especificar msq_file.
        show_path: bool                 ->  decide si muestra un camino aleatorio generado.
        show_compare_hist: bool         ->  decide si muestra comparación de histograma x[0]
                                            con histograma x[k], con k aleatorio entre [1,N-1].
        show_complete_path_hist: bool   ->  decide si muestra comparación de histograma x[0]
                                            con histograma de todo el camino {x[k]}.
        save_plot: bool                 ->  decide si guarda figura.
        show_plot: bool                 ->  decide si muestra figura en pantalla. 
    """

    script_dir = os.path.dirname(os.path.abspath(__file__))

    # Decide si lee datos e ignora input pathss_x
    if read_paths_data:
        if not paths_file_name:
            paths_file_name = (
                'pi_x-pi-%s-beta_%.3f-N_path_%d-N_iter_%d-delta_%.3f-append_every_%d.csv'
                %
                (potential_string, beta, N_path, N_iter, delta, append_every))
        paths_file_name = script_dir + '/' + paths_file_name
        pathss_x = pd.read_csv(paths_file_name, index_col=0, comment='#')
        pathss_x = pathss_x.to_numpy()

    pathss_x = np.array(pathss_x)
    N_path = len(pathss_x[-1])
    x_max = np.abs(x_max)

    # Crea figura
    fig, ax1 = plt.subplots()

    # Grafica histograma, teórico y si se pide un camino aleatorio
    ax1.set_xlabel(u'$x$')
    ax1.set_ylabel(u'$\pi^{(Q)} (x;\\beta)$')

    # Muestra teórico del oscilador armónico cuántico.
    if show_QHO_theory:
        x_plot = np.linspace(-x_max, x_max, N_plot)
        lns1 = ax1.plot(x_plot,
                        QHO_canonical_ensemble(x_plot, beta),
                        label=u'Oscilador Armónico\n(Teórico)')

    # Muestra valores generados por algoritmo matrix squaring.
    # Hay que especificar nombre del archivo en que están guardados estos datos.
    if show_matrix_squaring:

        msq_file = script_dir + '/' + msq_file
        matrix_squaring_data = pd.read_csv(msq_file, index_col=0, comment='#')

        lns2 = ax1.plot(matrix_squaring_data['position_x'],
                        matrix_squaring_data['prob_density'],
                        label=u'Algoritmo Matrix\nSquaring')

    # Muestra histograma generado con los las frecuencias de los valores de x[0] de cada path.
    lns3 = ax1.hist(pathss_x[:, 0],
                    bins=int(np.sqrt(N_iter / append_every)),
                    normed=True,
                    label=u'Integral de camino\nnaive sampling $x[0]$',
                    alpha=.40)

    # Muestra histograma generado con los las frecuencias de los valores de x[k] de cada path
    # con k aleatorio entre 1 y N_path-1
    if show_compare_hist:
        lns5 = ax1.hist(pathss_x[:, np.random.choice(np.arange(1, N_path))],
                        bins=int(np.sqrt(N_iter / append_every)),
                        normed=True,
                        label=u'Comparación hist. $x[k]$',
                        alpha=.40)

    # Muestra histograma generado con las frecuencias de todas las posiciones {x[k]} de todos
    # los caminos aleatorios
    if show_complete_path_hist:
        pathss_x2 = pathss_x.copy()
        pathss_x2 = pathss_x2.flatten()
        lns6 = ax1.hist(
            pathss_x2,
            bins=int(np.sqrt(N_iter * N_path / append_every)),
            normed=True,
            label=u'Comparación tomando\npath completo $\{x[k]\}_k$',
            alpha=.40)

    # Parámetros del aspecto de la figura
    ax1.tick_params(axis='y')
    ax1.set_ylim(bottom=0)
    ax1.set_xlim(-x_max, x_max)

    if save_plot:

        if not plot_file_name:
            plot_file_name = (
                'pi_x-pi-plot-%s-beta_%.3f-' % (potential_string, beta) +
                'N_path_%d-N_iter_%d-delta_%.3f-' % (N_path, N_iter, delta) +
                'append_every_%d-x_max_%.3f-' % (append_every, x_max) +
                'theory_%d-ms_%d-' % (show_QHO_theory, show_matrix_squaring) +
                'path_%d-compare_%d-' % (show_path, show_compare_hist) +
                'complete_path-%d.eps' % (show_complete_path_hist))

        plot_file_name = script_dir + '/' + plot_file_name

    if show_path:
        ax2 = ax1.twinx(
        )  # instantiate a second axes that shares the same x-axis

        beta_plot = np.linspace(0, beta, N_path + 1)
        path_plot = list(pathss_x[-1])
        path_plot.append(pathss_x[-1][0])
        lns4 = ax2.plot(path_plot, beta_plot, 'o-', c='k', label=u'Path')
        ax2.tick_params(axis='y')
        beta_ticks = np.linspace(0, beta, N_beta_ticks)
        ax2.set_yticks(beta_ticks)
        ax2.set_yticklabels(u'$%.2f$' % b for b in beta_ticks)
        ax2.set_ylabel(u'$\\tau$', rotation=270)
        ax2.set_ylim(bottom=0)
        ax2.set_xlim(-x_max, x_max)

        # Parafernalia para agregar labels correctamente cuando se usan dos ejes con
        # escalas diferentes
        if not show_QHO_theory: lns1 = [0]
        if not show_matrix_squaring: lns2 = [0]
        if not show_compare_hist: lns5 = [0]
        if not show_complete_path_hist: lns6 = [0]
        try:
            lns3_test = [lns3[2][0]]
        except:
            lns3_test = [0]
        try:
            lns6_test = [lns6[2][0]]
        except:
            lns6_test = [0]
        try:
            lns5_test = [lns5[2][0]]
        except:
            lns5_test = [0]
        leg_test = lns1 + lns2 + lns4 + lns3_test + lns6_test + lns5_test
        labs = []
        leg = []
        for i, l in enumerate(leg_test):
            try:
                labs.append(l.get_label())
                leg.append(leg_test[i])
            except:
                pass
        ax1.legend(leg,
                   labs,
                   loc='best',
                   title=u'$\\beta=%.2f$' % beta,
                   fontsize=12)

        fig.tight_layout()

        if save_plot:
            plt.savefig(plot_file_name)
        if show_plot:
            plt.show()
        plt.close()

    else:
        plt.legend(loc='best', title=u'$\\beta=%.2f$' % beta, fontsize=12)
        if save_plot:
            plt.savefig(plot_file_name)
        if show_plot:
            plt.show()
        plt.close()

    return
def figures_fn(pathss_x,
               beta=4,
               N_plot=201,
               x_max=3,
               N_iter=int(1e5),
               append_every=1,
               N_beta_ticks=11,
               msq_file='file.csv',
               file_name='path-plot-prueba',
               show_theory=True,
               show_matrix_squaring=True,
               show_path=True,
               show_compare_hist=True,
               show_complete_path_hist=True,
               save_plot=True,
               show_plot=True):

    pathss_x = np.array(pathss_x)
    script_dir = os.path.dirname(os.path.abspath(__file__))
    x_plot = np.linspace(-x_max, x_max, N_plot)
    N_path = len(pathss_x[-1])

    # Crea figura
    fig, ax1 = plt.subplots()

    # Grafica histograma, teórico y si se pide un camino aleatorio
    ax1.set_xlabel(u'$x$')
    ax1.set_ylabel(u'$\pi^{(Q)} (x;\\beta)$')
    if show_theory:
        lns1 = ax1.plot(x_plot,
                        QHO_canonical_ensemble(x_plot, beta),
                        label=u'Teórico')
    if show_matrix_squaring:
        msq_file = script_dir + '/' + msq_file
        matrix_squaring_data = pd.read_csv(msq_file, index_col=0, comment='#')
        lns2 = ax1.plot(matrix_squaring_data['position_x'],
                        matrix_squaring_data['prob_density'],
                        label=u'Algoritmo Matrix\nSquaring')
    lns3 = ax1.hist(pathss_x[:, 0],
                    bins=int(np.sqrt(N_iter / append_every)),
                    normed=True,
                    label=u'Integral de camino\nnaive sampling',
                    alpha=.40)
    if show_compare_hist:
        lns5 = ax1.hist(pathss_x[:, np.random.choice(np.arange(1, N_path))],
                        bins=int(np.sqrt(N_iter / append_every)),
                        normed=True,
                        label=u'Comparación hist. $x[k]$',
                        alpha=.40)
    if show_complete_path_hist:
        pathss_x2 = pathss_x.copy()
        pathss_x2 = pathss_x2.flatten()
        lns6 = ax1.hist(
            pathss_x2,
            bins=int(np.sqrt(N_iter * N_path / append_every)),
            normed=True,
            label=u'Comparación tomando\npath completo $\{x[k]\}_k$',
            alpha=.40)
    ax1.tick_params(axis='y')
    ax1.set_ylim(bottom=0)
    ax1.set_xlim(-x_max, x_max)
    if not show_path:
        plt.legend(loc='best', fontsize=12)
        if save_plot:
            plt.savefig(script_dir + '/' + file_name)
        if show_plot:
            plt.show()
        plt.close()

    if show_path:
        ax2 = ax1.twinx(
        )  # instantiate a second axes that shares the same x-axis

        ax2.set_ylabel(u'$\\tau$')  # we already handled the x-label with ax1
        beta_plot = np.linspace(0, beta, N_path + 1)
        path_plot = list(pathss_x[-1])
        path_plot.append(pathss_x[-1][0])
        lns4 = ax2.plot(path_plot, beta_plot, 'o-', c='k', label=u'Path')
        ax2.tick_params(axis='y')
        beta_ticks = np.linspace(0, beta, N_beta_ticks)
        ax2.set_yticks(beta_ticks)
        ax2.set_yticklabels(u'$%.2f$' % b for b in beta_ticks)
        ax2.set_ylim(bottom=0)
        ax2.set_xlim(-x_max, x_max)
        # Parafernalia para agrgar labels correctamente cuando se usan dos ejes con
        # escalas diferentes
        if not show_theory:
            lns1 = [0]
        if not show_matrix_squaring:
            lns2 = [0]
        if not show_compare_hist:
            lns5 = [0]
        if not show_complete_path_hist:
            lns6 = [0]
        try:
            lns3_test = [lns3[2][0]]
        except:
            lns3_test = [0]
        try:
            lns6_test = [lns6[2][0]]
        except:
            lns6_test = [0]
        try:
            lns5_test = [lns5[2][0]]
        except:
            lns5_test = [0]
        leg_test = lns1 + lns2 + lns4 + lns3_test + lns6_test + lns5_test
        labs = []
        leg = []
        for i, l in enumerate(leg_test):
            try:
                labs.append(l.get_label())
                leg.append(leg_test[i])
            except:
                pass
        ax1.legend(leg,
                   labs,
                   loc='best',
                   title=u'$\\beta=%.2f$' % beta,
                   fontsize=12)

        fig.tight_layout()  # otherwise the right y-label is slightly clipped
        if save_plot:
            plt.savefig(script_dir + '/' + file_name)
        if show_plot:
            plt.show()
        plt.close()
    return 0
def figures_fn(pathss_x=None,
               read_paths_data=False,
               paths_file_name=None,
               beta=4,
               N_plot=201,
               x_max=3,
               N_iter=int(1e5),
               append_every=1,
               N_beta_ticks=11,
               msq_file='file.csv',
               plot_file_name='path-plot-prueba',
               show_theory=True,
               show_matrix_squaring=True,
               show_path=True,
               show_compare_hist=True,
               show_complete_path_hist=True,
               save_plot=True,
               show_plot=True):
    """
    Uso: 
        Genera figuras del algoritmo path integral naive sampling.

    Recibe:
        read_paths_data: bool           ->  decide si lee datos. True ignora pathss_x.
        paths_file_name: str            ->  nombre del archivo en que estan guardados datos
                                            de paths. Solo necesario si read_paths_data = True
        N_beta_ticks: int               ->  Número de valores de beta mostrados al graficar un
                                            camino aleatorio. Recomendable  valor < 12.
        msq_file: str                   ->  archivo en que están guardados datos de algoritmo
                                            matrix squaring para comparar con path integral.
                                            Necesario solo si show_matrix_squaring=True.
        plot_file_name: str             ->  nombre del gráfico que se genera. Necesario solo si
                                            show_plot=True.
        show_theory: bool               ->  decide si muestra valor teórico del oscilador
                                            armónico.
        show_matrix_squaring: bool      ->  decide si muestra resultado de algoritmo Matrix
                                            Squaring. Si True es necesario especificar msq_file.
        show_path: bool                 ->  decide si muestra un camino aleatorio generado.
        show_compare_hist: bool         ->  decide si muestra comparación de histograma x[0]
                                            con histograma x[k], con k aleatorio entre [1,N-1].
        show_complete_path_hist: bool   ->  decide si muestra comparación de histograma x[0]
                                            con histograma de todo el camino {x[k]}.
        save_plot: bool                 ->  decide si guarda gráfico.
        show_plot: bool                 ->  decide si muestra gráfico en pantalla. 
    """

    script_dir = os.path.dirname(os.path.abspath(__file__))

    if read_paths_data:
        paths_file_name = script_dir + '/' + paths_file_name
        pathss_x = pd.read_csv(paths_file_name, index_col=0, comment='#')
        pathss_x = pathss_x.to_numpy()

    pathss_x = np.array(pathss_x)
    x_plot = np.linspace(-x_max, x_max, N_plot)
    N_path = len(pathss_x[-1])

    # Crea figura
    fig, ax1 = plt.subplots()

    # Grafica histograma, teórico y si se pide un camino aleatorio
    ax1.set_xlabel(u'$x$')
    ax1.set_ylabel(u'$\pi^{(Q)} (x;\\beta)$')

    # Muestra teórico del oscilador armónico cuántico.
    if show_theory:
        lns1 = ax1.plot(x_plot,
                        QHO_canonical_ensemble(x_plot, beta),
                        label=u'Oscilador Armónico\nTeórico')

    # Muestra valores generados por algoritmo matrix squaring.
    # Hay que especificar nombre del archivo en que están guardados estos datos.
    if show_matrix_squaring:

        msq_file = script_dir + '/' + msq_file
        matrix_squaring_data = pd.read_csv(msq_file, index_col=0, comment='#')

        lns2 = ax1.plot(matrix_squaring_data['position_x'],
                        matrix_squaring_data['prob_density'],
                        label=u'Algoritmo Matrix\nSquaring')

    # Muestra histograma generado con los las frecuencias de los valores de x[0] de cada path.
    lns3 = ax1.hist(pathss_x[:, 0],
                    bins=int(np.sqrt(N_iter / append_every)),
                    normed=True,
                    label=u'Integral de camino\nnaive sampling',
                    alpha=.40)

    # Muestra histograma generado con los las frecuencias de los valores de x[k] de cada path
    # con k aleatorio entre 1 y N_path-1
    if show_compare_hist:
        lns5 = ax1.hist(pathss_x[:, np.random.choice(np.arange(1, N_path))],
                        bins=int(np.sqrt(N_iter / append_every)),
                        normed=True,
                        label=u'Comparación hist. $x[k]$',
                        alpha=.40)

    # Muestra histograma generado con las frecuencias de todas las posiciones {x[k]} de todos
    # los caminos aleatorios
    if show_complete_path_hist:
        pathss_x2 = pathss_x.copy()
        pathss_x2 = pathss_x2.flatten()
        lns6 = ax1.hist(
            pathss_x2,
            bins=int(np.sqrt(N_iter * N_path / append_every)),
            normed=True,
            label=u'Comparación tomando\npath completo $\{x[k]\}_k$',
            alpha=.40)

    # Parámetros del aspecto de la figura
    ax1.tick_params(axis='y')
    ax1.set_ylim(bottom=0)
    ax1.set_xlim(-x_max, x_max)

    if save_plot:
        if plot_file_name is None:
            ############################ Dar nombre al plot
            plot_file_name = '.eps'
        plot_file_name = script_dir + '/' + plot_file_name

    if not show_path:
        plt.legend(loc='best', fontsize=12)
        if save_plot:
            plt.savefig(plot_file_name)
        if show_plot:
            plt.show()
        plt.close()

    if show_path:
        ax2 = ax1.twinx(
        )  # instantiate a second axes that shares the same x-axis

        ax2.set_ylabel(u'$\\tau$')  # we already handled the x-label with ax1
        beta_plot = np.linspace(0, beta, N_path + 1)
        path_plot = list(pathss_x[-1])
        path_plot.append(pathss_x[-1][0])
        lns4 = ax2.plot(path_plot, beta_plot, 'o-', c='k', label=u'Path')
        ax2.tick_params(axis='y')
        beta_ticks = np.linspace(0, beta, N_beta_ticks)
        ax2.set_yticks(beta_ticks)
        ax2.set_yticklabels(u'$%.2f$' % b for b in beta_ticks)
        ax2.set_ylim(bottom=0)
        ax2.set_xlim(-x_max, x_max)
        # Parafernalia para agrgar labels correctamente cuando se usan dos ejes con
        # escalas diferentes
        if not show_theory:
            lns1 = [0]
        if not show_matrix_squaring:
            lns2 = [0]
        if not show_compare_hist:
            lns5 = [0]
        if not show_complete_path_hist:
            lns6 = [0]
        try:
            lns3_test = [lns3[2][0]]
        except:
            lns3_test = [0]
        try:
            lns6_test = [lns6[2][0]]
        except:
            lns6_test = [0]
        try:
            lns5_test = [lns5[2][0]]
        except:
            lns5_test = [0]
        leg_test = lns1 + lns2 + lns4 + lns3_test + lns6_test + lns5_test
        labs = []
        leg = []
        for i, l in enumerate(leg_test):
            try:
                labs.append(l.get_label())
                leg.append(leg_test[i])
            except:
                pass
        ax1.legend(leg,
                   labs,
                   loc='best',
                   title=u'$\\beta=%.2f$' % beta,
                   fontsize=12)

        fig.tight_layout()  # otherwise the right y-label is slightly clipped
        if save_plot:
            plt.savefig(plot_file_name)
        if show_plot:
            plt.show()
        plt.close()

    return