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'
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
#!/usr/bin/env python from flipper import flip if __name__ == '__main__': flip(10)
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