def plot_hk(hk, hk_lims, fulldirname, config, plt_temp=True): r""" This function plots the hk of the DRE-DEMUX prototype. Parameters ---------- hk: Dictionnary hk values. hk_lims: Dictionnary hk limits. fulldirname: string The name of the dump file (with the path) config: dictionnary Contains path and constants definitions plt_temp: Boolean If True a dedicated plot is made with the temperature of the DAC Returns ------- Nothing """ plotdirname = os.path.join(os.path.normcase(fulldirname), os.path.normcase(config['dir_plots'])) general_tools.checkdir(plotdirname) pltfilename1 = os.path.join(plotdirname, 'PLOT_HK.png') pltfilename2 = os.path.join(plotdirname, 'PLOT_HK_LIMS.png') pltfilename3 = os.path.join(plotdirname, 'PLOT_HK_TEMP.png') # detection of valid hks n_valid_hk = count_valid_hk(hk) n_cols = 4 n_lines = n_valid_hk // n_cols if n_valid_hk % n_cols != 0: n_lines = n_lines + 1 deltatime = np.array([0]) for i in range(len(hk['Date']) - 1): deltatime = np.append(deltatime, (datetxt_to_date(hk['Date'][i + 1]) - datetxt_to_date(hk['Date'][0])).total_seconds()) fig = plt.figure(figsize=(12, 18)) ihk = 1 for key in hk.keys(): if key != 'Date' and ihk <= n_valid_hk: ax = fig.add_subplot(n_lines, n_cols, ihk) ax.plot(deltatime, hk[key], linewidth=3) ax.grid(color='k', linestyle=':', linewidth=0.5) ax.set_title(key[1:-1]) ax.set_xlabel('time (s)') if hk_lims[key]['lowalert']: ax.plot([deltatime[0], deltatime[-1]], [hk_lims[key]['lowalertv'], hk_lims[key]['lowalertv']], '--', color='red') if hk_lims[key]['lowwarn']: ax.plot([deltatime[0], deltatime[-1]], [hk_lims[key]['lowwarnv'], hk_lims[key]['lowwarnv']], '--', color='orange') if hk_lims[key]['highwarn']: ax.plot([deltatime[0], deltatime[-1]], [hk_lims[key]['highwarnv'], hk_lims[key]['highwarnv']], '--', color='orange') if hk_lims[key]['highalert']: ax.plot( [deltatime[0], deltatime[-1]], [hk_lims[key]['highalertv'], hk_lims[key]['highalertv']], '--', color='red') mini = min(hk[key].min(), hk_lims[key]['lowalertv']) maxi = max(hk[key].max(), hk_lims[key]['highalertv']) margin = 0.2 * (maxi - mini) ax.set_ylim(mini - margin, maxi + margin) ax.grid(color='k', linestyle=':', linewidth=0.5) ihk = ihk + 1 fig.tight_layout() plt.savefig(pltfilename2, bbox_inches='tight') fig = plt.figure(figsize=(12, 18)) ihk = 1 for key in hk.keys(): #print(key) if key != 'Date' and ihk <= n_valid_hk: ax = fig.add_subplot(n_lines, n_cols, ihk) ax.plot(deltatime, hk[key], linewidth=3) ax.grid(color='k', linestyle=':', linewidth=0.5) ax.set_title(key[1:-1]) ax.set_xlabel('time (s)') mini = hk[key].min() maxi = hk[key].max() margin = 0.2 * (maxi - mini) if margin == 0: margin = 0.05 ax.set_ylim(mini - margin, maxi + margin) ax.grid(color='k', linestyle=':', linewidth=0.5) ihk = ihk + 1 fig.tight_layout() plt.savefig(pltfilename1, bbox_inches='tight') if plt_temp: fig = plt.figure(figsize=(9, 5)) key = "\"Temperature DAC CH1 (C)\"" ax = fig.add_subplot(1, 1, 1) ax.plot(deltatime, hk[key], linewidth=3) ax.grid(color='k', linestyle=':', linewidth=0.5) ax.set_ylabel(key[1:-1]) ax.set_xlabel('time (s)') mini = hk[key].min() maxi = hk[key].max() margin = 0.2 * (maxi - mini) if margin == 0: margin = 0.05 ax.set_ylim(mini - margin, maxi + margin) ax.grid(color='k', linestyle=':', linewidth=0.5) for item in (ax.yaxis.label, ax.xaxis.label): item.set_weight('bold') item.set_fontsize(15) fig.tight_layout() plt.savefig(pltfilename3, bbox_inches='tight') return ()
def process_gbw(fulldirname, config, chan, margin_pc=5): r""" This function reads data from several DRE IQ data files to compute the Gain BadWidth product (GBW). Parameters ---------- fulldirname: string The name of the directory containing the data files config: dictionnary Contains path and constants definitions chan: number Specifies the channel to be processed (0 or 1) margin_pc: number Acceptable margin, as a percentage, on the value of the GBWP (default is 5) Returns ------- gbwp_ok: boolean True if gain bandwidth product is in the correct range. """ fs = config["fs"] datadirname = os.path.join(fulldirname, config['dir_data']) plotdirname = os.path.join(fulldirname, config['dir_plots']) general_tools.checkdir(plotdirname) pltfilename = os.path.join(plotdirname, "PLOT_GBW.png") f, a, gain_dre = get_gbw_freq_and_amp(datadirname, "IQ-TST", chan) if len(f) > 0: a_db = 20 * np.log10(a / a.max()) # Fit of the transfer function and measurement of the GBP fit_params = fit_tools.low_pass_fit(f, a) f_high_res = np.linspace(1, 1e6, num=1e5) fit = fit_tools.low_pass(f_high_res, fit_params[0], fit_params[1]) fit_db = 20 * np.log10(fit / fit.max()) gbw = 1. / fit_params[1] gbwp_ok = (gbw >= config['GBWP'] * (1 - margin_pc / 100)) and (gbw <= config['GBWP'] * (1 + margin_pc / 100)) min_amp_db, max_amp_db = -80, 10 gbw_min, gbw_max = 13e3, 17e3 fs_sur2 = fs / (2 * 2**7) gbw_color = color_ok(gbw, gbw_min, gbw_max) # Plot fig = plt.figure(figsize=(8, 6)) ax = fig.add_subplot(1, 1, 1) ax.semilogx(f, a_db, 's', label='Transfer function before decimation filter') ax.semilogx(f_high_res, fit_db, color='k', label='Fit (LPF 1st order)') # Processing filtered data f2, a2, _ = get_gbw_freq_and_amp(datadirname, "IQ-ALL", chan) if len(f2) > 0: a2_db = 20 * np.log10(a2 / a2.max()) ax.semilogx(f2, a2_db, '.', label='Transfer function after decimation filter') ax.semilogx([gbw, gbw], [min_amp_db, max_amp_db], '--', color='b', label='BBFB Gain Bandwidth Product') # Adding some references and text on the plot comment1 = 'Channel {0:1d}'.format(chan) comment2 = 'GainDRE = ' + gain_dre comment3 = 'GBW = {0:6.0f} Hz'.format(gbw) ax.semilogx([fs_sur2, fs_sur2], [min_amp_db, max_amp_db], '--', color='k', linewidth=0.5, label='Fs / 2') ax.text(20, min_amp_db + 35, comment1, color='b') ax.text(20, min_amp_db + 30, comment2, color='b') ax.text(20, min_amp_db + 25, comment3, color=gbw_color) ax.legend() ax.axis([10, 1e6, min_amp_db, max_amp_db]) ax.set_xlabel(r'Frequency (Hz)') ax.set_ylabel(r'Amplitude (dB)') ax.set_title(r'Bandwidth measurement') major_ticks = np.arange(min_amp_db, max_amp_db, 10) minor_ticks = np.arange(min_amp_db, max_amp_db, 2) ax.set_yticks(major_ticks) ax.set_yticks(minor_ticks, minor=True) ax.grid(which='minor', alpha=0.2) ax.grid(which='major', alpha=0.5) fig.tight_layout() plt.savefig(pltfilename, bbox_inches='tight') else: f = a_db = 0 gbwp_ok = False return (gbwp_ok)
def ep(fulldirname, config, verbose=False): """Perform the operations to measure the energy resolution (with and without tes noise). Arguments: fulldirname: string The name of the directory containing the data files config: dictionnary Contains path and constants definitions verbose: boolean If True some informations are printed (Default=False) Returns: eres_ok: boolean True if DRE energy resolution contribution is below the requirement """ datadirname = os.path.join(fulldirname, config['dir_data']) plotdirname = os.path.join(fulldirname, config['dir_plots']) general_tools.checkdir(plotdirname) pixeldirname = os.path.normcase("./Pixel_data_LPA75um_AR0.5/") file_xifusim_template = os.path.join(pixeldirname, "pulse_withBBFB.npy") file_xifusim_tes_noise = os.path.join(pixeldirname, "noise_spectra_bbfb_noFBDAC.fits") EP_filter_exist = False eres_mean = np.inf # searching data files f_type_deb = 15 list_file_pulses = [f for f in os.listdir(datadirname) \ if os.path.isfile(os.path.join(datadirname, f)) \ and f[f_type_deb:]=="_mk_EP_filter_events_record.fits"] f_type_deb = 15 list_file_noise = [f for f in os.listdir(datadirname) \ if os.path.isfile(os.path.join(datadirname, f)) \ and f[f_type_deb:]=="_mk_EP_filter_noise_record.fits"] f_type_deb = 15 list_file_measures = [f for f in os.listdir(datadirname) \ if os.path.isfile(os.path.join(datadirname, f)) \ and f[f_type_deb:]=="_meas_E_resol_events_record.fits"] # Computing EP filter if len(list_file_pulses) == 1 and len(list_file_noise) == 1: file_pulses = os.path.join(datadirname, list_file_pulses[0]) file_noise = os.path.join(datadirname, list_file_noise[0]) optimal_filter, optimal_filter_tot = do_EP_filter( file_noise, file_pulses, file_xifusim_template, file_xifusim_tes_noise, plotdirname, verbose) EP_filter_exist = True else: print("No file available for EP processing") # Measuring energies if EP_filter_exist: summary_file_name = os.path.join(plotdirname, "er_results.csv") summary_file = open(summary_file_name, "w") summary_file.write("Cession;" + "To be done;" + "\n") summary_file.write(";Energy resolution (with TES noise);Error;Unit;\n") index = 0 eres_list = [] for file_measures_name in list_file_measures: file_measures_fullname = os.path.join(datadirname, file_measures_name) eres, eres_error = measure_er(file_measures_fullname, optimal_filter, optimal_filter_tot, pixeldirname, plotdirname, index, verbose) eres_list.append(eres) summary_file.write(";{0:6.4f};{1:6.4f};eV;\n".format( eres, eres_error)) index += 1 eres_mean = np.array(eres_list).mean() summary_file.write("Mean value;{0:6.4f};;eV;\n".format(eres_mean)) if index > 1: summary_file.write("Standard dev.;{0:6.4f};;eV;\n".format( np.array(eres_list).std())) summary_file.close() return (eres_mean < config['eres_req_cbe_dre_7kev'])
def check_baseline(fulldirname, config): npix = 41 datadirname = os.path.join(fulldirname, config['dir_data']) plotdirname = os.path.join(fulldirname, config['dir_plots']) general_tools.checkdir(plotdirname) pltfilename = os.path.join(plotdirname, "PLOT_BASELINE") i_test_deb, i_test_fin = 21, 40 test = "IQ-ALL_Science-Data" fichlist = [f for f in os.listdir(datadirname) \ if os.path.isfile(os.path.join(datadirname, f)) \ and f[-4:]=='.dat' and f[i_test_deb:i_test_fin]==test] # ----------------------------------------------------------------------- # Processing baseline if len(fichlist) > 0: chan0_i, chan0_q, _, _, _ = get_data.read_iq( os.path.join(datadirname, fichlist[0])) l = len(chan0_i[:, 0]) mod = np.zeros((l, npix)) for pix in range(npix): mod[:, pix] = np.sqrt(chan0_i[:, pix].astype('float')**2 + chan0_q[:, pix].astype('float')**2) chan0_i, chan0_q = 0, 0 # Checking which pixel is on pix_on = general_tools.non_empty_lines(mod) t = np.arange(l) / (config['fs'] / 2**config['power_to_fs2']) n_boxes = npix n_lines = 6 n_cols = 7 fig = plt.figure(figsize=(18, 12)) for box in range(n_boxes): if pix_on[box]: marge = 0.5 ymax = mod[:, box].max() + (mod[:, box].max() - mod[:, box].min()) * marge ymin = mod[:, box].min() - (mod[:, box].max() - mod[:, box].min()) * marge ax = fig.add_subplot(n_lines, n_cols, box + 1) ax.plot(t, mod[:, box]) ax.set_ylim([ymin, ymax]) ax.set_title(r'Pixel {0:2d}'.format(box)) plt.gca().get_yaxis().get_major_formatter().set_useOffset( False) ratio = 100 / 2**15 ax2 = plt.gca().twinx() ax2.set_ylim([ymin * ratio, ymax * ratio]) plt.gca().get_yaxis().get_major_formatter().set_useOffset( False) if box // n_cols == n_lines - 1: ax.set_xlabel(r'Time (s)') else: plt.xticks(visible=False) if box % n_cols == 0: ax.set_ylabel(r'Module (A.U.)') if box % n_cols == n_cols - 1: ax2.set_ylabel(r'Module (% of FSR)') for item in ([ ax.title, ax.xaxis.label, ax.yaxis.label, ax2.yaxis.label ]): item.set_fontsize(10) item.set_weight('bold') for item in (ax.get_xticklabels() + ax.get_yticklabels() + ax2.get_yticklabels()): item.set_fontsize(8) for item in (ax.get_yticklabels() + ax2.get_yticklabels()): item.set_rotation(45) fig.tight_layout() plt.savefig(pltfilename + '_40pix.png', bbox_inches='tight')
def plot_scanfb(scanfbdata, fulldirname, config, limit_error): r""" This function plots scan feedback data. Parameters ---------- scanfbdata: Dictionnary scan feedback data (frequencies, module, phase minus best fit) values. fulldirname: string The name of the dump file (with the path) config: dictionnary Contains path and constants definitions limit_error: number Acceptance level for the phase-fit values (default=1.5 degrees) Returns ------- Nothing """ fmin_khz = 1e3 fmax_khz = 5e3 plotdirname = os.path.join(os.path.normcase(fulldirname), os.path.normcase(config['dir_plots'])) general_tools.checkdir(plotdirname) pltfilename = os.path.join(plotdirname, 'PLOT_SCANFEEDBACK.png') fig = plt.figure(figsize=(12, 8)) ax1 = fig.add_subplot(2, 1, 1) ax1.plot(scanfbdata['Freq(kHz)'], scanfbdata['Mod(dB)'], linewidth=3) axes = plt.gca() ymin, ymax = axes.get_ylim() ax1.plot([fmin_khz, fmin_khz], [ymin, ymax], '--r', linewidth=1) ax1.plot([fmax_khz, fmax_khz], [ymin, ymax], '--r', linewidth=1) ax1.set_title('Scan-Feedback plot') ax1.grid(color='k', linestyle=':', linewidth=0.5) #ax1.set_xlabel('Frequency (kHz)') ax1.set_xticklabels([]) ax1.set_ylabel('Module (dB)') ax2 = fig.add_subplot(2, 1, 2) ax2.plot(scanfbdata['Freq(kHz)'], scanfbdata['Phi-fit(deg)'], linewidth=3) axes = plt.gca() ymin, ymax = axes.get_ylim() ax2.plot([fmin_khz, fmin_khz], [-1 * limit_error, limit_error], '--r', linewidth=1) ax2.plot([fmax_khz, fmax_khz], [-1 * limit_error, limit_error], '--r', linewidth=1) ax2.plot([fmin_khz, fmax_khz], [limit_error, limit_error], '--r', linewidth=1) ax2.plot([fmin_khz, fmax_khz], [-1 * limit_error, -1 * limit_error], '--r', linewidth=1) xmin, xmax = scanfbdata['Freq(kHz)'].min(), scanfbdata['Freq(kHz)'].max() ax2.plot([xmin, xmax], [0, 0], '-k', linewidth=2) ax2.grid(color='k', linestyle=':', linewidth=0.5) ax2.set_xlabel('Frequency (kHz)') ax2.set_ylabel('Phase - fit (deg)') fig.tight_layout() plt.savefig(pltfilename, bbox_inches='tight')