def center_check(data_list): x_axis_mm = np.linspace(-23, 23, 2**9) r_axis_mm = np.linspace(0, 23, 2**9 + 1)[1::2] th_axis_rad = np.linspace(0, np.pi * 2, 2**9 + 1)[1::2] xy_center_slice = slice(x_axis_mm.searchsorted(-1), x_axis_mm.searchsorted(1, side='right')) x = [] y = [] r = [] th = [] for data in data_list: x.extend(data.electrons.pos_x.value) y.extend(data.electrons.pos_y.value) if np.any(data.electrons.pos_t.value > np.pi * 2): data.electrons.recalculate_polar_coordinates() r.extend(data.electrons.pos_r.value) th.extend(data.electrons.pos_t.value) image_xy = epicea.center_histogram_2d(x, y, x_axis_mm) x_slice = image_xy[xy_center_slice, :].sum(axis=0) y_slice = image_xy[:, xy_center_slice].sum(axis=1) image_rt = epicea.center_histogram_2d(r, th, r_axis_mm, th_axis_rad) plt_func.figure_wrapper('Electron data {} eV pass'.format( data_list[0].electron_center_energy())) plt.subplot(231) plt_func.imshow_wrapper(image_xy, x_axis_mm) plt.subplot(234) plt_func.imshow_wrapper(image_rt, r_axis_mm, th_axis_rad, kw_args={'aspect': 'auto'}) plt.subplot(132) plt.plot(x_axis_mm, x_slice, label='normal') plt.plot(x_axis_mm[::-1], x_slice, label='flipped') plt_func.title_wrapper('x slice') plt_func.legend_wrapper() plt.xlim(xmin=7) plt.subplot(133) plt.plot(x_axis_mm, y_slice, label='normal') plt.plot(x_axis_mm[::-1], y_slice, label='flipped') plt_func.title_wrapper('y slice') plt_func.legend_wrapper() plt.xlim(xmin=7)
plt.plot(centers, th_axis_rad, label='full center') plt.plot(low_radius_centers, th_axis_rad, label='first center') plt.title('center position') plt_func.legend_wrapper() plt.subplot(122) plt.plot(radial_factors, th_axis_rad) plt.title('r factors') r = data.electrons.pos_r.value th = data.electrons.pos_t.value for i in range(len(th_axis_rad)): selection = (th_limits[i] < th) & (th < th_limits[i + 1]) r[selection] *= radial_factors[i] r_th_img_corrected = epicea.center_histogram_2d(r, th, r_axis_mm, th_axis_rad) r_proj_corrected = r_th_img_corrected.sum(axis=0) proj_corrected_params_initial = \ epicea.electron_calibration_helper.start_params( r_axis_mm, r_proj_corrected, n_lines=2) proj_corrected_result = lmfit.minimize(line_model, proj_corrected_params_initial, args=(r_axis_mm, r_proj_corrected), kws={'line_type': line}) ax = r_th_fig.add_subplot(222) plt.sca(ax) plt_func.imshow_wrapper(r_th_img_corrected, r_axis_mm, th_axis_rad,
def plot_two_ion_corelations(data, verbose=False): if verbose: print('In plot_two_ion_corelations.') # Get some ions filters data.get_filter('two_ions_events_ions') double_ions_e_start = data.get_filter('two_ion_e_start_events_ions') data.get_filter('two_ion_rand_start_events_ions') NN_O_events_ions = data.get_filter('NN_O_events_ions', verbose=verbose) NO_N_events_ions = data.get_filter('NO_N_events_ions', verbose=verbose) # Plot distribution of nomber of ions num_ions = data.events.num_i.value num_ions_axis = np.arange(5) hist_ions_all = epicea.center_histogram(num_ions, num_ions_axis) hist_ions_e_start = epicea.center_histogram( num_ions[data.get_filter('e_start_events')], num_ions_axis) hist_ions_rand_start = epicea.center_histogram( num_ions[data.get_filter('rand_start_events')], num_ions_axis) plt_func.figure_wrapper('Two-ion correlations {}'.format(data.name())) plt.subplot(221) plt.plot(num_ions_axis, hist_ions_all, 'o-', label='All events') plt.plot(num_ions_axis, hist_ions_rand_start, 'o-', label='random start') plt.plot(num_ions_axis, hist_ions_e_start, 'o-', label='e start') plt_func.legend_wrapper() plt_func.title_wrapper('Ion number distributions.') plt_func.xlabel_wrapper('Number of ions per event') plt_func.ylabel_wrapper('Number of events') plt_func.tick_fontsize() # Look at some two ions, e start event correlations # Angle information # plt_func.figure_wrapper('two ion angles {}'.format(data.name())) plt.subplot(222) if verbose: print('Get angles.') th_e_start = data.ions.pos_t[double_ions_e_start] th_NN_O = data.ions.pos_t[NN_O_events_ions] th_NO_N = data.ions.pos_t[NO_N_events_ions] th_axis_rad = np.linspace(0, np.pi, 513)[1::2] th_hist_e_start, th_diff_e_start = calc_angle_diffs_hist( th_e_start, th_axis_rad) th_hist_NN_O, _ = calc_angle_diffs_hist(th_NN_O, th_axis_rad) th_hist_NO_N, _ = calc_angle_diffs_hist(th_NO_N, th_axis_rad) plt_func.bar_wrapper(th_axis_rad, th_hist_e_start, label='e start ion pairs') sl = slice(th_axis_rad.searchsorted(ANGLE_CUT), None) plt_func.bar_wrapper(th_axis_rad[sl], th_hist_e_start[sl], 'r', label='selection') plt_func.bar_wrapper(th_axis_rad, th_hist_NN_O, 'y', label='NN+ O+ ion pairs') plt_func.bar_wrapper(th_axis_rad, th_hist_NO_N, 'm', label='NO+ N+ ion pairs') # plt.hist(angle_diff[np.isfinite(angle_diff)], # bins=np.linspace(-0.1, np.pi, 256)) plt_func.xlabel_wrapper('Angle difference between tow ions (rad)') plt_func.ylabel_wrapper('Number of ion pairs') plt_func.title_wrapper('Two ion angles.') plt_func.legend_wrapper() plt_func.tick_fontsize() if verbose: print('{} events with two ions and electron start identified.'.format( data.get_filter('two_ion_e_start_events').sum())) print('{} valid angle diffs found.'.format(th_hist_e_start.sum())) # Radial information # plt_func.figure_wrapper('radii {}'.format(data.name())) plt.subplot(223) if verbose: print('Get radii.') r_frac_axis = np.linspace(1., 3.5, 257)[1::2] r_e_start = data.ions.pos_r[double_ions_e_start] r_NN_O = data.ions.pos_r[NN_O_events_ions] r_NO_N = data.ions.pos_r[NO_N_events_ions] r_frac_e_start_hist = calc_radius_fraction_hist(r_e_start, r_frac_axis) r_frac_selection_hist = calc_radius_fraction_hist( r_e_start.reshape(-1, 2)[th_diff_e_start > ANGLE_CUT, :], r_frac_axis) r_frac_NN_O_hist = calc_radius_fraction_hist(r_NN_O, r_frac_axis) r_frac_NO_N_hist = calc_radius_fraction_hist(r_NO_N, r_frac_axis) plt_func.bar_wrapper(r_frac_axis, r_frac_e_start_hist, label='e start') plt_func.bar_wrapper(r_frac_axis, r_frac_selection_hist, 'r', label='selection') plt_func.bar_wrapper(r_frac_axis, r_frac_NN_O_hist, 'y', label='NN+ O+ ions') plt_func.bar_wrapper(r_frac_axis, r_frac_NO_N_hist, 'm', label='NO+ N+ ions') # plt.hist(r_frac, bins=np.linspace(0.9, 3., 256)) plt_func.xlabel_wrapper('Radial quotient for two ions r1/r2') plt_func.ylabel_wrapper('Number of ion pairs') plt_func.title_wrapper('Radius quotient') plt_func.legend_wrapper() plt_func.tick_fontsize() plt_func.savefig_wrapper() ########################### # TOF-TOF correlation plot plt_func.figure_wrapper('tof-tof hist {}'.format(data.name())) t_axis_us = np.linspace(3.3, 5.3, 512) t_axis = t_axis_us * 1e6 # names = ['e start', 'all', 'random start'] # for i, ions_filter in enumerate([double_ions_e_start, # double_ions, # double_ions_rand_start]): # plt.subplot(2, 2, i+1) names = ['electrons'] for i, ions_filter in enumerate([double_ions_e_start]): i_tof = data.ions.tof_falling_edge[ions_filter] i_tof = i_tof.reshape(-1, 2) i_tof.sort(axis=1) i_tof = i_tof[np.isfinite(i_tof).sum(1) == 2, :] tof_tof_hist = epicea.center_histogram_2d(i_tof[:, 0], i_tof[:, 1], t_axis) tof_tof_sym_hist = tof_tof_hist + tof_tof_hist.T # plt_func.imshow_wrapper(tof_tof_sym_hist, t_axis_us) plt_func.imshow_wrapper(np.log(tof_tof_sym_hist + 1), t_axis_us) # plt.plot(t_axis_us, # glob.NN_O_TIME_SUM_RANGE_US[data.name()][0] - t_axis_us, # 'y', label='NN+ O+ selection') # plt.plot(t_axis_us, # glob.NN_O_TIME_SUM_RANGE_US[data.name()][1] - t_axis_us, # 'y') # plt.plot(t_axis_us, # glob.NN_O_TIME_DIFF_RANGE_US[data.name()][0] + t_axis_us, # 'y') # plt.plot(t_axis_us, # glob.NN_O_TIME_DIFF_RANGE_US[data.name()][1] + t_axis_us, # 'y') for sum_range, diff_range, label, c in zip([ glob.NO_N_TIME_SUM_RANGE_US[data.name()], glob.NN_O_TIME_SUM_RANGE_US[data.name()] ], [ glob.NO_N_TIME_DIFF_RANGE_US[data.name()], glob.NN_O_TIME_DIFF_RANGE_US[data.name()] ], ['NO+ N+ selection', 'NN+ O+ selection'], ['m', 'y']): s = sum_range[[0, 1, 1, 0, 0]] d = diff_range[[1, 1, 0, 0, 1]] x = (s - d) / 2 y = (s + d) / 2 plt.plot(x, y, c, label=label) plt_func.title_wrapper(names[i]) plt.axis([ t_axis_us.min(), t_axis_us.max(), t_axis_us.min(), t_axis_us.max() ]) plt_func.ylabel_wrapper('Time of flight (us)') plt_func.xlabel_wrapper('Time of flight (us)') plt_func.legend_wrapper(loc='center right') plt_func.colorbar_wrapper('log(counts + 1)') plt_func.tick_fontsize() # if i == 0: # tof_tof_hist_e_start = tof_tof_sym_hist.copy() # if i == 2: # tof_tof_hist_random = tof_tof_sym_hist.copy() # # sl = slice(t_axis.searchsorted(5.5e6)) # factor = (tof_tof_hist_e_start[sl, :].sum() / # tof_tof_hist_random[sl, :].sum()) # pure = tof_tof_hist_e_start - tof_tof_hist_random * factor # # plt.subplot(224) # plt_func.imshow_wrapper(pure, t_axis_us) # plt_func.tick_fontsize() plt_func.savefig_wrapper()
def make_calibration(setting, plot=True, verbose=False): """Make the electron calibration for a given center energy setting.""" # The Kr binding energies are needed for Kr based calibrations calibration_file_name = 'h5_data/calib_{}.h5'.format(setting) # Get the list of data sets calib_data_list = load_data_for_calibration(setting, verbose=verbose) if 'Kr' in calib_data_list[0].name(): gas = 'Kr' n_lines = 2 elif 'N2' in calib_data_list[0].name(): gas = 'N2' n_lines = 1 else: print('Unknown gas.', 'Dataset names must specify the used gas (N2 or Kr).') # Create an empty calibration object calibration = epicea.ElectronEnergyCalibration() # # Make an x axis # x_axis_mm = np.linspace(-23, 23, 2**8) # # Define polar coordinate axis vectors # r_axis_mm = np.linspace(0, 25, 2**7+1)[1::2] # th_axis_rad = np.linspace(0, 2*np.pi, 2**9+1)[1::2] if plot: # Create a plot of all the spectra in the data list if verbose: print('Plot all the raw spectra.') # Create the figure plt_func.figure_wrapper('Calibration spectra {} eV'.format(setting)) # One subplot for each data set... n_subplots = calib_data_list.len() # ... nicely set in collumns and rows n_rows = np.floor(np.sqrt(n_subplots)) n_cols = np.ceil(float(n_subplots) / n_rows) # Iterate over the datasets for i, c_data in enumerate(calib_data_list): plt.subplot(n_rows, n_cols, i + 1) # Make the subplot # Show the electron figure plt_func.imshow_wrapper( c_data.get_e_xy_image(x_axis_mm)[0], x_axis_mm) # Adjust the figure for good looks plt_func.tick_fontsize() plt_func.title_wrapper(c_data.name()) plt_func.xlabel_wrapper('Position (mm)') plt_func.ylabel_wrapper('Position (mm)') # plt.tight_layout() # Keep track of the latest time stamp of the lines latest_lines = 0 rth_fig = {} straight_img = {} straight_img_time_stamp = {} radial_factors = {} # Iterate over the datasets and make images for each set. # Also find the lines in each of the spectra for i, c_data in enumerate(calib_data_list): d_name = c_data.name() ####################################### # Raw theta vs. r spectrum e_rth_image, e_rth_image_time_stamp, rth_fig[d_name] = \ get_r_theta_image(c_data, r_axis_mm, th_axis_rad, gas, plot=True, verbose=verbose, fig=None) ####################################### # radial factors radial_factors[d_name], radial_factors_time_stamp, _ = \ get_radial_factors(c_data, r_axis_mm, th_axis_rad, e_rth_image_time_stamp, gas, e_rth_image=e_rth_image, verbose=verbose) ####################################### # Straight image straight_img[d_name], straight_img_time_stamp[d_name], _= \ get_straight_image(c_data, r_axis_mm, th_axis_rad, radial_factors_time_stamp, gas, radial_factors=radial_factors[d_name], verbose=verbose, plot=plot, fig=rth_fig[d_name]) # Make sure the straight image is avaliable for all the calibration data # sets before making the background. # This is achieved by exiting the loop and starting a neew one. for i, c_data in enumerate(calib_data_list): d_name = c_data.name() ####################################### # N_2 background if gas == 'N2': if not background.check_bg_valid( setting, len(r_axis_mm), verbose=verbose): if verbose: print('Make new N2 background.', flush=True) background.make_new_bg(setting=setting, plot=plot, verbose=verbose) elif verbose: print('Use old N2 background.') n2_bg = (background.load_background(setting, len(r_axis_mm)) * c_data.data_scaling) kws = {'bg': n2_bg} else: n2_bg = None kws = {} ######## # do some plotting of the straight image projection and a fit to it if plot: plot_projections(rth_fig[d_name], c_data, straight_img[d_name], r_axis_mm, th_axis_rad, gas, n_lines, setting, verbose=verbose, **kws) ####################################### # Find lines r, w, a, red_chi2, lines_time_stamp = get_lines( c_data, r_axis_mm, th_axis_rad, n_lines, setting, max(straight_img_time_stamp.values()), gas, verbose=verbose, plot=plot, fig=rth_fig[d_name], straight_img=straight_img[d_name], radial_factors=radial_factors[d_name], n2_bg=n2_bg, calibration=calibration) # Keep the latest time stamp latest_lines = max(lines_time_stamp, latest_lines) print('Create calibration', flush=True) # calibration.create_conversion(poly_order=2) calibration.create_or_load_conversion(calibration_file_name, compare_time_stmp=max( latest_lines, 1444746720), poly_order=2, verbose=verbose) print('Check the calibration', flush=True) plt_func.figure_wrapper('Calib data check') theta_list, data_list = calibration.get_data_copy() r_min = data_list[:, :, 0].min() r_max = data_list[:, :, 0].max() r_axis_for_calib_check_mm = np.linspace(r_min + (r_min - r_max) * 0.0, r_max + (r_max - r_min) * 0.0, 256) for idx in range(0, len(theta_list), int(np.ceil(float(len(theta_list)) / 20))): plt.subplot(121) plt.plot(data_list[:, idx, 0], data_list[:, idx, 1], '.:') # plt.plot(r_axis_for_calib_check_mm, # epicea.poly_line(calibration._energy_params_list[idx], # r_axis_for_calib_check_mm), 'r') plt.plot( r_axis_for_calib_check_mm, epicea.electron_calibration_helper.r_to_e_conversion( calibration._energy_params_list[idx], r_axis_for_calib_check_mm), 'r') plt.subplot(122) shift = 0.1 * idx plt.plot(data_list[:, idx, 0], 1. / data_list[:, idx, 3] + shift, '.:') # plt.plot(r_axis_for_calib_check_mm, # epicea.poly_line(calibration._weights_params_list[idx], # r_axis_for_calib_check_mm) + shift, 'r') plt.plot(data_list[..., 0].mean(1), 1. / data_list[..., 3].mean(1), 'k', lw=2) a, b = ((338, 368) if setting == 357 else (359, 368) if setting == 366 else (366, 376) if setting == 373 else (480, 508)) E_axis_eV = np.linspace(a, b, 2**9 + 1)[1::2] E_all = [] err_all = [] theta_all = [] weight_all = [] for c_data in calib_data_list: print('Get the calibrated energies, {} eV.'.format( c_data.photon_energy()), flush=True) c_data.calculate_electron_energy(calibration, verbose=verbose) # E, err, weigths = calibration.get_energies(c_data.electrons.pos_r, # c_data.electrons.pos_t) E_all.extend(c_data.electrons.energy.value) err_all.extend(c_data.electrons.energy_uncertainty.value) theta_all.extend(c_data.electrons.pos_t.value) weight_all.extend(c_data.electrons.spectral_weight.value) plt_func.figure_wrapper('Energy domain all calibration data') ax = plt.subplot(211) E_image = epicea.center_histogram_2d(E_all, theta_all, E_axis_eV, th_axis_rad, weights=weight_all) plt_func.imshow_wrapper(E_image, E_axis_eV, th_axis_rad, kw_args={'aspect': 'auto'}) plt.subplot(212, sharex=ax) plt.plot(E_axis_eV, E_image.sum(0)) plt.grid(True) calibration.save_to_file(calibration_file_name)
def get_straight_image(data, r_axis_mm, th_axis_rad, compare_time_stamp, gas, *, verbose=False, plot=False, fig=None, radial_factors=None): d_name = data.name() if radial_factors is None: radial_factors, r_f_time_stamp, fig = get_radial_factors( data, r_axis_mm, th_axis_rad, 0, gas, verbose=verbose, plot=plot) compare_time_stamp = max(compare_time_stamp, r_f_time_stamp) compare_time_stamp = max(compare_time_stamp, 144178446) th_limits = epicea.limits_from_centers(th_axis_rad) # Get the corrected image with some defined properties straight_img_name = 'e_rth_image_straight' filter_sum_string = 'no_filter' match_data_dict = {'r_axis_mm': r_axis_mm, 'th_axis_rad': th_axis_rad} # With the radial factors done, now look for the corrected image match_data_dict['radial_factors'] = radial_factors straight_img, straight_img_time_stamp = \ data.load_derived_data( straight_img_name, filter_sum_string, compare_time_stamp=compare_time_stamp, verbose=verbose, match_data_dict=match_data_dict) # If there is no data it needs to be made if straight_img.size > 0: if verbose: print('Use old straight image.', flush=True) else: if verbose: print('Make new straight image.', flush=True) # Get and adjust the coordinates th = data.electrons.pos_t.value r = data.electrons.pos_r.value for i_th in range(len(th_axis_rad)): try: I = (th_limits[i_th] <= th) & (th < th_limits[i_th + 1]) except RuntimeWarning as W: print(W.args) print(W.with_traceback) print('I.sum() =', I.sum(), 'i_th =', i_th, th_limits[i_th]) r[I] *= radial_factors[i_th] straight_img = epicea.center_histogram_2d(r, th, r_axis_mm, th_axis_rad) # Save the straight image straight_img_time_stamp = data.store_derived_data( straight_img, straight_img_name, filter_sum_string, match_data_dict=match_data_dict, verbose=verbose) if (fig is not None) & (plot == True): if verbose: print('Plot the straight image of', d_name, flush=True) plt.sca(fig.axes[1]) img_axis = plt_func.imshow_wrapper(straight_img, r_axis_mm, th_axis_rad, kw_args={'aspect': 'auto'}) plt_func.tick_fontsize() plt_func.title_wrapper('straight ' + d_name) plt_func.xlabel_wrapper('Position (mm)') plt_func.ylabel_wrapper('Angle (rad)') plt_func.colorbar_wrapper(mappable=img_axis) return straight_img, straight_img_time_stamp, fig
com_corr_max_line = com_corr_img[max_line_number] # com_corr_max_line = com_corr_img.mean(axis=0) com_shift = com_corr_img - com_corr_max_line com_corrected = com_corr_max_line + com_shift plt.plot(com_corr_img, th_axis_rad, '.') r_factors = com_corrected.mean() / com_corrected r = data.electrons.pos_r.value th = data.electrons.pos_t.value for i_th in range(len(th_axis_rad)): mask_th = (th_limits[i_th] < th) & (th <= th_limits[i_th + 1]) r[mask_th] *= r_factors[i_th] straigt_img = epicea.center_histogram_2d(r, th, r_axis_mm, th_axis_rad) plt_func.imshow_wrapper(straigt_img, r_axis_mm, th_axis_rad, ax=ax_img_straight, kw_args={'aspect': 'auto'}) straight_proj = straigt_img.sum(axis=0) plt.figure('projections') plt.clf() plt.plot(r_axis_mm, r_proj / r_proj.sum()) plt.plot(r_axis_mm, straight_proj / straight_proj.sum()) random_slice = r_th_img[np.random.randint(len(th_axis_rad)), :] plt.plot(r_axis_mm, random_slice / random_slice.sum())