Exemplo n.º 1
0
def add_nmax_data(Nmax_list):
    """
    Add data to be plotted on the level scheme for each Nmax in Nmax_list

    Nmax_list:
        list of floats
    """
    for i, Nmax in enumerate(Nmax_list):
        print("working on Nmax =", Nmax)
        # get ncsmc, .out output files
        ps = phase_shift_list[i]
        es = eigenphase_shift_list[i]
        dot_out = ncsmc_dot_out_list[i]

        # make unflipped plots, flipped=True prevents flipping
        resonance_plotter.plot(
            ps, flipped=True, Nmax=Nmax, suffix='_unflipped')
        resonance_plotter.plot(
            es, flipped=True, Nmax=Nmax, suffix='_unflipped')

        # flip phase files
        ps = flipper.flip(ps, verbose=False)
        es = flipper.flip(es, verbose=False)

        # make flipped plots
        resonance_plotter.plot(ps, flipped=True, Nmax=Nmax)
        resonance_plotter.plot(es, flipped=True, Nmax=Nmax)

        # get bound state info
        bound_energies, bound_titles = output_simplifier.simplify(dot_out)

        # select interesting channels, i.e. those with resonances
        # eigen_channels_string, eigen_channels_titles, phase_channels_string
        # just shortened so the line wasn't weirdly long
        e_ch_str, e_ch_titles, p_ch_str = select_interesting_channels(Nmax)
        # stick those channels in the overall plot
        add_resonances(Nmax, es, e_ch_str, e_ch_titles,
                       ps, p_ch_str,
                       bound_energies, bound_titles)
def test_flip():
    # assert <statement>, 'Info message in case of failure of statement'
    assert flipper.flip('John') == 'nhoJ'
Exemplo n.º 3
0
def plot(filename,
         flipped=False,
         e_bounds=(-inf, inf),
         res_types="all",
         channels="",
         Nmax=None,
         dpi=dpi,
         suffix=""):
    """
    Makes a whole bunch of plots.

    - one for each of the user-specified channels
    - one with all channels on the same plot

    filename:
        string, an eigenphase_shift / phase_shift file path

    flipped:
        boolean, has this file been put throught flipper.py?

    e_bounds:
        tuple, (left, right) bounds of the energy axis

    res_types:
        string or list. what types of resonances should be plotted?

    channels:
        big string, one channel per line, of channels to be plotted

    Nmax:
        float, for giving the plot a title

    dpi:
        resolution of the image
    """
    if res_types == "all":
        res_types = ["strong", "possible", "none"]

    filename = utils.abs_path(filename)
    phase_word = "eigenphase" if "eigen" in filename else "phase"

    # ensure file is flipped
    if flipped:
        new_filename = filename
    else:
        new_filename = flipper.flip(filename)

    # if channels are provided, there will be at least one number in the string
    # if no channels are provided, get them all
    if not any([utils.is_float(char) for char in channels]):
        file_suffix = "auto"
        # get csv filename with resonance info
        res_output_file = get_resonance_info(filename,
                                             Nmax=Nmax,
                                             already_flipped=True)
        # take all channels, i.e. all text in the file
        with open(res_output_file, "r+") as channel_file:
            channels = channel_file.read()
    else:
        file_suffix = "custom"

    # make channel titles
    lines = channels.split("\n")
    input_titles = []
    for line in lines:
        if line == "":
            continue
        Jx2, parity, Tx2, col_num, res_type = line.split(",")
        # only take the types of resonances we want to plot
        if res_type in res_types:
            title = "_".join([Jx2, parity, Tx2, "column", col_num])
            input_titles.append(title)

    # all_channels: dict, key = title, value = list of phases for that channel
    # energies: a list of energy values, possibly longer than some channels
    all_channels, energies = flipper.separate_into_channels(new_filename)

    # if energy bounds are -inf, inf, let's set them to the min / max e values
    if e_bounds == (-inf, inf):
        l_bound, r_bound = min(energies), max(energies)
    else:
        l_bound, r_bound = e_bounds

    output_dir = utils.output_dir.format(Nmax)
    if not exists(output_dir):
        os.mkdir(output_dir)
    png_dir = join(output_dir, "PNGs_" + phase_word)
    csv_dir = join(output_dir, "CSVs_" + phase_word)
    grace_dir = join(output_dir, "grace_files_" + phase_word)
    for d in [png_dir, csv_dir, grace_dir]:
        if not exists(d):
            os.mkdir(d)

    print("Working on resonance plotting")
    main_xmgrace_string = ""  # xmgrace string for the full file
    channel_string = ""  # xmgrace string for each individual channel
    series_counter = 0  # xmgrace series titles
    csv_paths = []  # list of csv files of channels we plot

    # now look in each channel, plot the ones we care about
    to_plot = []
    for title, phases in all_channels.items():
        # see if the title matches one we were given. If so, plot
        nice_title = utils.make_nice_title(title)
        if nice_title in input_titles:
            print("adding", nice_title, "to plot\r", end="")
            # energies may be longer than phases,
            # so we truncate energy where needed
            len_diff = len(energies) - len(phases)
            if len_diff != 0:
                trunc_energies = energies[len_diff:]
            else:
                trunc_energies = energies
            # then only plot within the given bounds
            plot_energies, plot_phases = [], []
            for e, p in zip(trunc_energies, phases):
                if l_bound <= e and e <= r_bound:
                    plot_energies.append(e)
                    plot_phases.append(p)

            # make a matplotlib channel plot
            channel_fig, channel_ax = plt.subplots()
            plot_title = utils.make_plot_title(nice_title)
            channel_ax.set_title(plot_title)
            channel_ax.set_ylabel("Phase (degrees)")
            # nothing interesting should happen outside this range, right?
            # I'd let matplotlib autogenerate the graph limits,
            # but then you get graphs with a range of -1 to 1, which have
            # an interesting shape but are not large enough to be useful
            channel_ax.set_ylim(-50, 200)
            channel_ax.set_xlim(l_bound, r_bound)
            channel_ax.set_xlabel("Energy (MeV)")
            channel_ax.plot(plot_energies, plot_phases)
            channel_path = join(
                png_dir,
                phase_word + "_" + nice_title + "_Nmax_" + str(Nmax) + ".png")
            channel_fig.savefig(channel_path, dpi=dpi)
            plt.close(channel_fig)
            to_plot.append((plot_energies, plot_phases, plot_title))

            # make xmgrace file for channel
            c_title = utils.xmgrace_title(title, series_counter) + "\n"
            channel_string = c_title
            series_counter += 1
            for e, p in zip(plot_energies, plot_phases):
                channel_string += str(e) + " " + str(p) + "\n"
            channel_string += "&\n"
            # append it to the full file string
            main_xmgrace_string += channel_string
            # and also save it as its own file with series number = 0
            lines = channel_string.splitlines()
            lines[0] = utils.xmgrace_title(lines[0], 0)
            channel_string = "\n".join(lines)
            grace_name = join(
                grace_dir,
                phase_word + "_" + nice_title + "_Nmax_" + str(Nmax) + ".agr")
            with open(grace_name, "w+") as channel_file:
                channel_file.write(channel_string)

            # make csv file for channel too
            csv_path = join(
                csv_dir,
                phase_word + "_" + nice_title + "_Nmax_" + str(Nmax) + ".csv")
            with open(csv_path, "w+") as csv_file:
                for e, p in zip(plot_energies, plot_phases):
                    csv_file.write(",".join([str(e), str(p)]) + "\n")
            csv_paths.append(csv_path)

    # make main matplotlib plot
    print("Making a big spaghetti plot...\r", end="")
    plt.cla()
    plt.clf()
    plt.title(phase_word.title() + " Shift vs. Energy for $N_{max}$ = " +
              str(Nmax))
    plt.ylabel("Phase (degrees)")
    plt.ylim(-5, 150)
    plt.xlim(l_bound, r_bound)
    plt.xlabel("Energy (MeV)")
    for energy, phase, title in to_plot:
        plt.plot(energy, phase, label=title)
    main_mpl_path = join(
        png_dir, phase_word + "_Nmax_" + str(Nmax) + "_" + file_suffix +
        suffix + ".png")
    plt.legend(loc='lower right', shadow=False, fontsize='medium')
    plt.savefig(main_mpl_path, dpi=dpi)
    plt.savefig(main_mpl_path.replace(".png", ".svg"))
    plt.close()

    # make main xmgrace file
    main_grace_path = join(
        grace_dir, phase_word + "_plot_Nmax_" + str(Nmax) + "_" + file_suffix +
        suffix + ".agr")
    with open(main_grace_path, "w+") as grace_file:
        grace_file.write(main_xmgrace_string)

    print("Done plotting! Saved main plot(s) to:")
    print(main_mpl_path)
    print(main_mpl_path.replace(".png", ".svg"))
    print(main_grace_path)

    # return paths to csv files of channels we plotted
    return csv_paths
Exemplo n.º 4
0
#!/usr/bin/env python 
from flipper import flip

if __name__ == '__main__':
    flip(10)
Exemplo n.º 5
0
def get_resonance_info(filename, Nmax=None, already_flipped=False):
    """
    Parses a ncsmc (eigen)phase shift file and writes info about each
    channel to a .csv file, with information about whether or not there is a
    resonance there. Returns name of said .csv file

    filename:
        path to phase shift file

    Nmax:
        integer, max number of excitations allowed

    already_flipped:
        boolean, whether or not the file has already been
        "flipped" by flipper.py
     """
    filename = utils.abs_path(filename)
    phase_word = "Eigenphase" if "eigen" in filename else "Phase"

    if Nmax is None:
        Nmax = int(input("What is Nmax? Enter an integer: "))

    # first flip the file if needed
    if already_flipped:
        new_filename = filename
    else:
        new_filename = flipper.flip(filename)

    print("Finding resonances...\r", end="")

    # channels: dict, key = title, value = list with channel numbers
    channels, _ = flipper.separate_into_channels(new_filename)

    # now look in each channel for a resonance
    resonance_info = {}
    for title, phases in channels.items():
        nice_title = utils.make_nice_title(title)

        resonance = False
        max_difference = abs(max(phases) - min(phases))

        if max_difference > 90:
            resonance = True
            res_type = "strong"
        elif max_difference > 60:
            res_type = "possible"
        else:
            res_type = "none"

        resonance_info[nice_title] = res_type

        if resonance:
            # anything we should do here?
            pass

    # write resonance info to a file, (res = resonance)
    output_dir = utils.output_dir.format(Nmax)
    if not exists(output_dir):
        os.mkdir(output_dir)
    res_file_title = "resonances_" + phase_word.lower() + "_Nmax_" + str(
        Nmax) + ".csv"
    res_file_name = join(output_dir, res_file_title)
    with open(res_file_name, "w+") as res_file:
        res_file.write("2J,parity,2T,column_number,resonance_type\n")
        for title, res_type in resonance_info.items():
            Jx2, parity, Tx2, _, column_number = title.split("_")
            write_list = [Jx2, parity, Tx2, column_number, res_type]
            res_file.write(",".join(write_list) + "\n")
    print("Analyzed all channels, saved CSV with info to", res_file_name)
    return res_file_name