def test_rebin(): # 1D a = np.array([1, 1, 1, 1]) aR = utils.rebin(a, 2) assert np.allclose(aR, np.array([1, 1])) # 2D b = np.array([[1,1,1,1], [2,2,2,2]]) bR = utils.rebin(b, 1, 2) assert np.allclose(bR, [[1,1], [2,2]]) bR = utils.rebin(b, None, 2) assert np.allclose(bR, [[1,1], [2,2]]) bR = utils.rebin(b, 2, 1) assert np.allclose(bR, [1.5, 1.5, 1.5, 1.5]) bR = utils.rebin(b, 2, None) assert np.allclose(bR, [1.5, 1.5, 1.5, 1.5]) c = np.zeros([10, 10, 10]) cR = utils.rebin(c, n_z=2) assert cR.shape == (10, 10, 5) cR = utils.rebin(c, n_y=2) assert cR.shape == (10, 5, 10) cR = utils.rebin(c, n_x=2) assert cR.shape == (5, 10, 10) c = np.zeros([10, 10, 10, 10]) with pytest.raises(RuntimeError): utils.rebin(c, 2, 2)
def plot_waterfall(fil, f_start=None, f_stop=None, if_id=0, logged=True, cb=False, freq_label=False, MJD_time=False, **kwargs): """ Plot waterfall of data Args: f_start (float): start frequency, in MHz f_stop (float): stop frequency, in MHz logged (bool): Plot in linear (False) or dB units (True), cb (bool): for plotting the colorbar kwargs: keyword args to be passed to matplotlib imshow() """ matplotlib.rc('font', **font) plot_f, plot_data = fil.grab_data(f_start, f_stop, if_id) # Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = plot_data.shape[1] / MAX_IMSHOW_POINTS[1] plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) if MJD_time: extent = (plot_f[0], plot_f[-1], fil.timestamps[-1], fil.timestamps[0]) else: extent = (plot_f[0], plot_f[-1], (fil.timestamps[-1] - fil.timestamps[0]) * 24. * 60. * 60, 0.0) this_plot = plt.imshow(plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, cmap='viridis_r', **kwargs) if cb: plt.colorbar() if freq_label: plt.xlabel("Frequency [Hz]", fontdict=font) if MJD_time: plt.ylabel("Time [MJD]", fontdict=font) else: plt.ylabel("Time [s]", fontdict=font) return this_plot
def __write_to_hdf5_light(wf, filename_out, f_scrunch=None, *args, **kwargs): """ Write data to HDF5 file in one go. Args: filename_out (str): Name of output file f_scrunch (int or None): Average (scrunch) N channels together """ block_size = 0 with h5py.File(filename_out, 'w') as h5: h5.attrs['CLASS'] = 'FILTERBANK' h5.attrs['VERSION'] = '1.0' bs_compression = hdf5plugin.Bitshuffle(nelems=0, lz4=True)['compression'] bs_compression_opts = hdf5plugin.Bitshuffle(nelems=0, lz4=True)['compression_opts'] if f_scrunch is None: data_out = wf.data else: wf.logger.info('Frequency scrunching by %i' % f_scrunch) data_out = utils.rebin(wf.data, n_z=f_scrunch) wf.header['foff'] *= f_scrunch dset = h5.create_dataset('data', data=data_out, compression=bs_compression, compression_opts=bs_compression_opts) dset_mask = h5.create_dataset('mask', shape=data_out.shape, compression=bs_compression, compression_opts=bs_compression_opts, dtype='uint8') dset.dims[2].label = b"frequency" dset.dims[1].label = b"feed_id" dset.dims[0].label = b"time" dset_mask.dims[2].label = b"frequency" dset_mask.dims[1].label = b"feed_id" dset_mask.dims[0].label = b"time" # Copy over header information as attributes for key, value in wf.header.items(): dset.attrs[key] = value
def test_rebin(): # 1D a = np.array([1, 1, 1, 1]) aR = utils.rebin(a, 2) assert np.allclose(aR, np.array([1, 1])) # 2D b = np.array([[1,1,1,1], [2,2,2,2]]) bR = utils.rebin(b, 1, 2) assert np.allclose(bR, [[1,1], [2,2]]) bR = utils.rebin(b, None, 2) assert np.allclose(bR, [[1,1], [2,2]]) bR = utils.rebin(b, 2, 1) assert np.allclose(bR, [1.5, 1.5, 1.5, 1.5]) bR = utils.rebin(b, 2, None) assert np.allclose(bR, [1.5, 1.5, 1.5, 1.5]) c = np.zeros([10, 10, 10]) with pytest.raises(RuntimeError): utils.rebin(c, 2, 2)
def plot_waterfall(fil, source_name, f_start=None, f_stop=None, **kwargs): r""" Plot waterfall of data in a .fil or .h5 file. Parameters ---------- fil : str Filterbank file containing the dynamic spectrum data. source_name : str Name of the target. f_start : float Start frequency, in MHz. f_stop : float Stop frequency, in MHz. kwargs : dict Keyword args to be passed to matplotlib imshow(). Notes ----- Plot a single-panel waterfall plot (frequency vs. time vs. intensity) for one of the on or off observations in the cadence of interest, at the frequency of the expected event. Calls :func:`~overlay_drift` """ # prepare font matplotlib.rc('font', **font) # Load in the data from fil plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) # Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 # rebinning data to plot correctly with fewer points if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) # Rolled back PR #82 # determine extent of the plotting panel for imshow extent = (plot_f[0], plot_f[-1], (fil.timestamps[-1] - fil.timestamps[0]) * 24. * 60. * 60, 0.0) # plot and scale intensity (log vs. linear) kwargs['cmap'] = kwargs.get('cmap', 'viridis') plot_data = 10.0 * np.log10(plot_data) # get normalization parameters vmin = plot_data.min() vmax = plot_data.max() normalized_plot_data = (plot_data - vmin) / (vmax - vmin) # display the waterfall plot this_plot = plt.imshow(normalized_plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, **kwargs) # add plot labels plt.xlabel("Frequency [Hz]", fontdict=font) plt.ylabel("Time [s]", fontdict=font) # add source name ax = plt.gca() plt.text(0.03, 0.8, source_name, transform=ax.transAxes, bbox=dict(facecolor='white')) # if plot_snr != False: # plt.text(0.03, 0.6, plot_snr, transform=ax.transAxes, bbox=dict(facecolor='white')) # return plot return this_plot
def make_waterfall_plots(fil_file_list, on_source_name, f_start, f_stop, drift_rate, f_mid, filter_level, source_name_list, offset=0, **kwargs): r''' Makes waterfall plots of an event for an entire on-off cadence. Parameters ---------- fil_file_list : str List of filterbank files in the cadence. on_source_name : str Name of the on_source target. f_start : float Start frequency, in MHz. f_stop : float Stop frequency, in MHz. drift_rate : float Drift rate in Hz/s. f_mid : float <iddle frequency of the event, in MHz. filter_level : int Filter level (1, 2, or 3) that produced the event. source_name_list : list List of source names in the cadence, in order. bandwidth : int Width of the plot, incorporating drift info. kwargs : dict Keyword args to be passed to matplotlib imshow(). Notes ----- Makes a series of waterfall plots, to be read from top to bottom, displaying a full cadence at the frequency of a recorded event from find_event. Calls :func:`~plot_waterfall` ''' global logger_plot_event # prepare for plotting matplotlib.rc('font', **font) # set up the sub-plots n_plots = len(fil_file_list) fig = plt.subplots(n_plots, sharex=True, sharey=True, figsize=(10, 2 * n_plots)) # get directory path for storing PNG files dirpath = dirname(fil_file_list[0]) + '/' # read in data for the first panel fil1 = bl.Waterfall(fil_file_list[0], f_start=f_start, f_stop=f_stop) t0 = fil1.header['tstart'] dummy, plot_data1 = fil1.grab_data() # rebin data to plot correctly with fewer points dec_fac_x, dec_fac_y = 1, 1 if plot_data1.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data1.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data1.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data1.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data1 = rebin(plot_data1, dec_fac_x, dec_fac_y) # define more plot parameters # never used: delta_f = 0.000250 mid_f = np.abs(f_start + f_stop) / 2. subplots = [] # Fill in each subplot for the full plot for i, filename in enumerate(fil_file_list): logger_plot_event.debug( 'make_waterfall_plots: file {} in list: {}'.format(i, filename)) # identify panel subplot = plt.subplot(n_plots, 1, i + 1) subplots.append(subplot) # read in data fil = bl.Waterfall(filename, f_start=f_start, f_stop=f_stop) # make plot with plot_waterfall source_name = source_name_list[i] this_plot = plot_waterfall(fil, source_name, f_start=f_start, f_stop=f_stop, **kwargs) # calculate parameters for estimated drift line t_elapsed = Time(fil.header['tstart'], format='mjd').unix - Time( t0, format='mjd').unix t_duration = (fil.n_ints_in_file - 1) * fil.header['tsamp'] f_event = f_mid + drift_rate / 1e6 * t_elapsed # plot estimated drift line overlay_drift(f_event, f_start, f_stop, drift_rate, t_duration, offset) # Title the full plot if i == 0: plot_title = "%s \n $\dot{\\nu}$ = %2.3f Hz/s , MJD:%5.5f" % ( on_source_name, drift_rate, t0) plt.title(plot_title) # Format full plot if i < len(fil_file_list) - 1: plt.xticks(np.linspace(f_start, f_stop, num=4), ['', '', '', '']) # More overall plot formatting, axis labelling factor = 1e6 units = 'Hz' ax = plt.gca() ax.get_xaxis().get_major_formatter().set_useOffset(False) xloc = np.linspace(f_start, f_stop, 5) xticks = [round(loc_freq) for loc_freq in (xloc - mid_f) * factor] if np.max(xticks) > 1000: xticks = [xt / 1000 for xt in xticks] units = 'kHz' plt.xticks(xloc, xticks) plt.xlabel("Relative Frequency [%s] from %f MHz" % (units, mid_f), fontdict=font) # Add colorbar cax = fig[0].add_axes([0.94, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot, cax=cax, label='Normalized Power (Arbitrary Units)') # Adjust plots plt.subplots_adjust(hspace=0, wspace=0) # save the figures path_png = dirpath + filter_level + '_' + on_source_name + '_dr_' + "{:0.2f}".format( drift_rate) + '_freq_' "{:0.6f}".format(f_start) + ".png" plt.savefig(path_png, bbox_inches='tight') logger_plot_event.debug( 'make_waterfall_plots: Saved file {}'.format(path_png)) # show figure before closing if this is an interactive context mplbe = matplotlib.get_backend() logger_plot_event.debug('make_waterfall_plots: backend = {}'.format(mplbe)) if mplbe in matplotlib.rcsetup.interactive_bk: plt.show() # close all figure windows plt.close('all') return subplots
def make_waterfall_plots(filenames_list, f_start, f_stop, plot_range=True, target='', ion=False, epoch=None, local_host='', plot_name='', save_pdf_plot=False, saving_fig=False, **kwargs): ''' Makes waterfall plots per group of ON-OFF pairs (up to 6 plots.) plot_range: selecting vmin vmax from first On observation, or not. ''' matplotlib.rc('font', **font) if ion: plt.ion() min_val = 0 max_val = 5. factor = 1e6 units = 'Hz' n_plots = len(filenames_list) fig = plt.subplots(n_plots, sharex=True, sharey=True, figsize=(10, 2 * n_plots)) #finding plotting values range fil = Waterfall(filenames_list[0], f_start=f_start, f_stop=f_stop) plot_f, plot_data = fil.grab_data(f_start, f_stop, 0) dec_fac_x, dec_fac_y = 1, 1 if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = plot_data.shape[1] / MAX_IMSHOW_POINTS[1] plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) A1_avg = np.median(plot_data) A1_max = plot_data.max() A1_std = np.std(plot_data) if not epoch: epoch = fil.header[u'tstart'] if not target: target = fil.header[u'source_name'] labeling = ['A', 'B', 'A', 'C', 'A', 'D'] # delta_f = ('%f0.6'%np.abs(f_start-f_stop)) delta_f = f_start - f_stop mid_f = np.abs(f_start + f_stop) / 2. for i, filename in enumerate(filenames_list): print(filename) plt.subplot(n_plots, 1, i + 1) fil = Waterfall(filename, f_start=f_start, f_stop=f_stop) if plot_range: this_plot = plot_waterfall(fil, f_start=f_start, f_stop=f_stop, vmin=A1_avg - A1_std * min_val, vmax=A1_avg + max_val * A1_std, **kwargs) else: this_plot = plot_waterfall(fil, f_start=f_start, f_stop=f_stop, **kwargs) if i == 0: plt.title(target.replace('HIP', 'HIP ')) if i < len(filenames_list) - 1: plt.xticks(np.arange(f_start, f_stop, delta_f / 4.), ['', '', '', '']) #Some plot formatting. ax = plt.gca() ax.get_xaxis().get_major_formatter().set_useOffset(False) print('delta_f', delta_f) plt.xticks(np.arange(f_start, f_stop, delta_f / 4.), [ round(loc_freq) for loc_freq in np.arange( (f_start - mid_f), (f_stop - mid_f), delta_f / 4.) * factor ]) plt.xlabel("Relative Frequency [%s] from %f MHz" % (units, mid_f), fontdict=font) #to plot color bar. for now. cax = fig[0].add_axes([0.9, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot, cax=cax, label='Power [Arbitrary Units]') # Fine-tune figure; make subplots close to each other and hide x ticks for # all but bottom plot. plt.subplots_adjust(hspace=0, wspace=0) if saving_fig: if not plot_name: plot_name = 'Candidate_waterfall_plots.%s.t%.0f.%s.f%.0f.png' % ( target, epoch, local_host, mid_f * 1e6) print('Saving png figure.') plt.savefig(plot_name, bbox_inches='tight') if save_pdf_plot: print('Saving pdf figure.') plt.savefig(plot_name.replace('.png', '') + '.pdf', format='pdf', dpi=300, bbox_inches='tight')
def make_waterfall_plots(fil_file_list, on_source_name, f_start, f_stop, drift_rate, f_mid, filter_level, source_name_list, bandwidth, offset=0, **kwargs): ''' Makes waterfall plots of an event for an entire on-off cadence Args: fil_file_list (str): list of filterbank files in the cadence on_source_name (str): name of the on_source target f_start (float): start frequency, in MHz f_stop (float): stop frequency, in MHz drift_rate (float) = drift rate in Hz/s f_mid = middle frequency of the event, in MHz filter_level = filter level (1,2,or 3) that produced the event source_name_list = list of source names in the cadence, in order bandwidth = width of the plot, incorporating drift info kwargs: keyword args to be passed to matplotlib imshow() ''' #prepare for plotting matplotlib.rc('font', **font) #set up the sub-plots n_plots = len(fil_file_list) fig = plt.subplots(n_plots, sharex=True, sharey=True, figsize=(10, 2 * n_plots)) #read in data for the first panel fil1 = bl.Waterfall(fil_file_list[0], f_start=f_start, f_stop=f_stop) t0 = fil1.header['tstart'] plot_f1, plot_data1 = fil1.grab_data() #rebin data to plot correctly with fewer points dec_fac_x, dec_fac_y = 1, 1 if plot_data1.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data1.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data1.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data1.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data1 = rebin(plot_data1, dec_fac_x, dec_fac_y) #define more plot parameters delta_f = 0.000250 mid_f = np.abs(f_start + f_stop) / 2. subplots = [] #Fill in each subplot for the full plot for i, filename in enumerate(fil_file_list): #identify panel subplot = plt.subplot(n_plots, 1, i + 1) subplots.append(subplot) #read in data fil = bl.Waterfall(filename, f_start=f_start, f_stop=f_stop) try: #make plot with plot_waterfall source_name = source_name_list[i] this_plot = plot_waterfall(fil, source_name, f_start=f_start, f_stop=f_stop, drift_rate=drift_rate, **kwargs) #calculate parameters for estimated drift line t_elapsed = Time(fil.header['tstart'], format='mjd').unix - Time( t0, format='mjd').unix t_duration = (fil.n_ints_in_file - 1) * fil.header['tsamp'] f_event = f_mid + drift_rate / 1e6 * t_elapsed #plot estimated drift line overlay_drift(f_event, f_start, f_stop, drift_rate, t_duration, offset) except: raise #Title the full plot if i == 0: plot_title = "%s \n $\dot{\\nu}$ = %2.3f Hz/s" % (on_source_name, drift_rate) plt.title(plot_title) #Format full plot if i < len(fil_file_list) - 1: plt.xticks(np.arange(f_start, f_stop, delta_f / 4.), ['', '', '', '']) #More overall plot formatting, axis labelling factor = 1e6 units = 'Hz' ax = plt.gca() ax.get_xaxis().get_major_formatter().set_useOffset(False) xloc = np.linspace(f_start, f_stop, 5) xticks = [round(loc_freq) for loc_freq in (xloc - mid_f) * factor] if np.max(xticks) > 1000: xticks = [xt / 1000 for xt in xticks] units = 'kHz' plt.xticks(xloc, xticks) plt.xlabel("Relative Frequency [%s] from %f MHz" % (units, mid_f), fontdict=font) #Add colorbar cax = fig[0].add_axes([0.94, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot, cax=cax, label='Normalized Power') #Adjust plots plt.subplots_adjust(hspace=0, wspace=0) #save the figures plt.savefig(filter_level + '_' + on_source_name + '_dr_' + "{:0.2f}".format(drift_rate) + '_freq_' "{:0.6f}".format(f_start) + ".png", bbox_inches='tight') return subplots
def plot_waterfall(fil, source_name, f_start=None, f_stop=None, drift_rate=None, logged=True, **kwargs): """ Plot waterfall of data in a .fil or .h5 file Args: fil (str): filterbank file containing the dynamic spectrum data source_name (str): name of the target f_start (float): start frequency, in MHz f_stop (float): stop frequency, in MHz drift_rate (float) = drift rate in Hz/s logged (bool): Plot in linear (False) or dB units (True), kwargs: keyword args to be passed to matplotlib imshow() """ #prepare font matplotlib.rc('font', **font) #Load in the data from fil plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) #Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 #rebinning data to plot correctly with fewer points if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) #determine extent of the plotting panel for imshow extent = (plot_f[0], plot_f[-1], (fil.timestamps[-1] - fil.timestamps[0]) * 24. * 60. * 60, 0.0) #plot and scale intensity (log vs. linear) kwargs['cmap'] = kwargs.get('cmap', 'viridis') kwargs['logged'] = True if kwargs['logged'] == True: plot_data = 10 * np.log10(plot_data) kwargs.pop('logged') #get normalization parameters vmin = plot_data.min() vmax = plot_data.max() normalized_plot_data = (plot_data - vmin) / (vmax - vmin) #display the waterfall plot this_plot = plt.imshow(normalized_plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, **kwargs) #add plot labels plt.xlabel("Frequency [Hz]", fontdict=font) plt.ylabel("Time [s]", fontdict=font) #add source name ax = plt.gca() plt.text(0.03, 0.8, source_name, transform=ax.transAxes, bbox=dict(facecolor='white')) #return plot return this_plot
def make_waterfall_plots(filenames_list, target, drates, fvals, f_start,f_stop, node_string, filter_level, ion=False, epoch=None,bw=250.0, local_host='',plot_name='',save_pdf_plot=False,saving_fig=False,offset=0, dedoppler=False,**kwargs): """Makes waterfall plots per group of ON-OFF pairs (up to 6 plots.) Args: filenames_list: target: drates: fvals: f_start: f_stop: node_string: filter_level: ion: (Default value = False) epoch: (Default value = None) bw: (Default value = 250.0) local_host: (Default value = '') plot_name: (Default value = '') save_pdf_plot: (Default value = False) saving_fig: (Default value = False) offset: (Default value = 0) dedoppler: (Default value = False) **kwargs: Returns: """ #prepares for plotting print('Preparing to plot: ', target) matplotlib.rc('font', **font) if ion: plt.ion() #defines a minimum and maximum of... something min_val = 0 max_val = 5. factor = 1e6 units = 'Hz' #finding plotting values range for the first panel (A1) fil = bl.Waterfall(filenames_list[0], f_start=f_start, f_stop=f_stop) t0 = fil.header['tstart'] plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) dec_fac_x, dec_fac_y = 1, 1 #rebinning data to plot correctly with fewer points if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] // MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = plot_data.shape[1] / MAX_IMSHOW_POINTS[1] print ('dec_fac_y', dec_fac_y) #insert rebin definition code from utils.py in blimpy and edit it because this is the problem d=plot_data n_x=dec_fac_x n_y=dec_fac_y d = rebin(d, n_x, n_y) plot_data=d #print('d', d) #plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) #investigate intensity values for A1 (first panel) plot_data = 10*np.log10(plot_data) A1_avg = np.median(plot_data) A1_max = plot_data.max() A1_std = np.std(plot_data) #defining more plot parameters delta_f = 0.000250 epoch = fil.header['tstart'] mid_f = np.abs(f_start+f_stop)/2. drate_max = np.max(np.abs(drates)) subplots = [] #working out intensity scale if kwargs.get('clim', None) is None: vmin=A1_avg-A1_std*min_val-2 vmax=A1_avg+max_val*A1_std else: vmin, vmax = kwargs['clim'] #Filling in each subplot for the full plot for i,filename in enumerate(filenames_list): subplot = plt.subplot(n_plots,1,i+1) subplots.append(subplot) #read in data fil = bl.Waterfall(filename, f_start=f_start, f_stop=f_stop) try: #make plot with plot_waterfall source_name = source_name_list[i] this_plot = plot_waterfall(fil, source_name, f_start=f_start, f_stop=f_stop, drift_rate=drift_rate, **kwargs) #calculate parameters for estimated drift line t_elapsed = Time(fil.header['tstart'], format='mjd').unix - Time(t0, format='mjd').unix t_duration = (fil.n_ints_in_file - 1) * fil.header['tsamp'] f_event = f_mid + drift_rate / 1e6 * t_elapsed #plot estimated drift line overlay_drift(f_event, f_start, f_stop, drift_rate, t_duration, offset) except: raise #Title the full plot if i == 0: plot_title = "%s \n $\dot{\\nu}$ = %2.3f Hz/s" % (on_source_name, drift_rate) plt.title(plot_title) #Format full plot if i < len(fil_file_list)-1: plt.xticks(np.arange(f_start, f_stop, delta_f/4.), ['','','','']) #More overall plot formatting, axis labelling factor = 1e6 units = 'Hz' ax = plt.gca() ax.get_xaxis().get_major_formatter().set_useOffset(False) xloc = np.linspace(f_start, f_stop, 5) xticks = [round(loc_freq) for loc_freq in (xloc - mid_f)*factor] if np.max(xticks) > 1000: xticks = [xt/1000 for xt in xticks] units = 'kHz' plt.xticks(xloc, xticks) plt.xlabel("Relative Frequency [%s] from %f MHz"%(units,mid_f),fontdict=font) #Add colorbar cax = fig[0].add_axes([0.94, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot,cax=cax,label='Normalized Power') #Adjust plots plt.subplots_adjust(hspace=0,wspace=0) #save the figures plt.savefig(filter_level + '_' + on_source_name + '_dr_' + "{:0.2f}".format(drift_rate) + '_freq_' "{:0.6f}".format(f_start) + ".png", bbox_inches='tight') return subplots
def plot_waterfall(fil, source_name, f_start=None, f_stop=None, drift_rate=None, logged=True, plot_snr=False, **kwargs): """ Plot waterfall of data in a .fil or .h5 file Args: fil (str): filterbank file containing the dynamic spectrum data source_name (str): name of the target f_start (float): start frequency, in MHz f_stop (float): stop frequency, in MHz drift_rate (float) = drift rate in Hz/s logged (bool): Plot in linear (False) or dB units (True), kwargs: keyword args to be passed to matplotlib imshow() """ #prepare font matplotlib.rc('font', **font) #Load in the data from fil plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) #Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 #rebinning data to plot correctly with fewer points if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) #determine extent of the plotting panel for imshow if plot_f[-1] < plot_f[0]: plot_f = plot_f[::-1] extent = (plot_f[0], plot_f[-1], (fil.timestamps[-1] - fil.timestamps[0]) * 24. * 60. * 60, 0.0) #plot and scale intensity (log vs. linear) kwargs['cmap'] = kwargs.get('cmap', 'viridis') kwargs['logged'] = True if kwargs['logged'] == True: plot_data = 10 * np.log10(plot_data) kwargs.pop('logged') # data = np.copy(plot_data) # tsamp = fil.header['tsamp'] # chan_bw = fil.header['foff'] # drift_rate = -0.15 # n_roll = (drift_rate * 1e-6 * tsamp) / chan_bw # for ii in range(data.shape[0]): # plot_data[ii] = np.roll(data[ii], int(n_roll*ii), axis = 0) #get normalization parameters vmin = plot_data.min() vmax = plot_data.max() normalized_plot_data = (plot_data - vmin) / (vmax - vmin) #display the waterfall plot this_plot = plt.imshow(normalized_plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, **kwargs) #add plot labels plt.xlabel("Frequency [Hz]", fontdict=font) plt.ylabel("Time [s]", fontdict=font) plt.locator_params(axis='x', nbins=3) #add source name ax = plt.gca() # if extent[2] > 300: # ax.figure.set_size_inches(5,2) if source_name == 'ProxCen': if drift_rate > 0: plt.text(0.03, 0.9, source_name, transform=ax.transAxes, bbox=dict(facecolor='white', edgecolor='none', alpha=0.75)) else: plt.text(0.97, 0.9, source_name, transform=ax.transAxes, ha='right', bbox=dict(facecolor='white', edgecolor='none', alpha=0.75)) plt.yticks(np.arange(0, extent[2], (extent[2]) // 5)[:-1]) else: if drift_rate > 0: plt.text(0.03, 0.35, source_name, transform=ax.transAxes, bbox=dict(facecolor='white', edgecolor='none', alpha=0.75)) else: plt.text(0.97, 0.35, source_name, transform=ax.transAxes, ha='right', bbox=dict(facecolor='white', edgecolor='none', alpha=0.75)) plt.yticks(np.arange(0, extent[2], (extent[2]) // 2)[:-1]) # if plot_snr != False: # plt.text(0.03, 0.6, plot_snr, transform=ax.transAxes, bbox=dict(facecolor='white')) #return plot return this_plot
def __write_to_hdf5_heavy(wf, filename_out, f_scrunch=None, *args, **kwargs): """ Write data to HDF5 file. Args: filename_out (str): Name of output file f_scrunch (int or None): Average (scrunch) N channels together """ block_size = 0 # Note that a chunk is not a blob!! # chunk_dim = wf._get_chunk_dimensions() <-- seems intended for raw to fil # And, chunk dimensions should not exceed the Waterfall selection shape dimensions. chunk_list = list(wf._get_chunk_dimensions()) for ix in range(0, len(chunk_list)): if chunk_list[ix] > wf.selection_shape[ix]: chunk_list[ix] = wf.selection_shape[ix] chunk_dim = tuple(chunk_list) blob_dim = wf._get_blob_dimensions(chunk_dim) n_blobs = wf.container.calc_n_blobs(blob_dim) with h5py.File(filename_out, 'w') as h5: h5.attrs['CLASS'] = 'FILTERBANK' h5.attrs['VERSION'] = '1.0' bs_compression = hdf5plugin.Bitshuffle(nelems=0, lz4=True)['compression'] bs_compression_opts = hdf5plugin.Bitshuffle(nelems=0, lz4=True)['compression_opts'] dout_shape = list(wf.selection_shape) # Make sure not a tuple dout_chunk_dim = list(chunk_dim) if f_scrunch is not None: dout_shape[-1] //= f_scrunch dout_chunk_dim[-1] //= f_scrunch wf.header['foff'] *= f_scrunch dset = h5.create_dataset('data', shape=tuple(dout_shape), chunks=tuple(dout_chunk_dim), compression=bs_compression, compression_opts=bs_compression_opts, dtype=wf.data.dtype) dset_mask = h5.create_dataset('mask', shape=tuple(dout_shape), chunks=tuple(dout_chunk_dim), compression=bs_compression, compression_opts=bs_compression_opts, dtype='uint8') dset.dims[2].label = b"frequency" dset.dims[1].label = b"feed_id" dset.dims[0].label = b"time" dset_mask.dims[2].label = b"frequency" dset_mask.dims[1].label = b"feed_id" dset_mask.dims[0].label = b"time" # Copy over header information as attributes for key, value in wf.header.items(): dset.attrs[key] = value if blob_dim[wf.freq_axis] < wf.selection_shape[wf.freq_axis]: wf.logger.info('Using %i n_blobs to write the data.'% n_blobs) for ii in range(0, n_blobs): wf.logger.info('Reading %i of %i' % (ii + 1, n_blobs)) bob = wf.container.read_blob(blob_dim, n_blob=ii) #----- #Using channels instead of frequency. c_start = wf.container.chan_start_idx + ii * blob_dim[wf.freq_axis] t_start = wf.container.t_start + (c_start / wf.selection_shape[wf.freq_axis]) * blob_dim[wf.time_axis] t_stop = t_start + blob_dim[wf.time_axis] # Reverse array if frequency axis is flipped # if self.header['foff'] < 0: # c_stop = self.selection_shape[self.freq_axis] - (c_start)%self.selection_shape[self.freq_axis] # c_start = c_stop - blob_dim[self.freq_axis] # else: c_start = (c_start) % wf.selection_shape[wf.freq_axis] c_stop = c_start + blob_dim[wf.freq_axis] #----- if f_scrunch is not None: c_start //= f_scrunch c_stop //= f_scrunch bob = utils.rebin(bob, n_z=f_scrunch) wf.logger.debug(t_start,t_stop,c_start,c_stop) dset[t_start:t_stop,0,c_start:c_stop] = bob[:] else: wf.logger.info('Using %i n_blobs to write the data.'% n_blobs) for ii in range(0, n_blobs): wf.logger.info('Reading %i of %i' % (ii + 1, n_blobs)) bob = wf.container.read_blob(blob_dim, n_blob=ii) t_start = wf.container.t_start + ii * blob_dim[wf.time_axis] #This prevents issues when the last blob is smaller than the others in time if (ii+1)*blob_dim[wf.time_axis] > wf.n_ints_in_file: t_stop = wf.n_ints_in_file else: t_stop = (ii+1)*blob_dim[wf.time_axis] if f_scrunch is not None: bob = utils.rebin(bob, n_z=f_scrunch) dset[t_start:t_stop] = bob[:]
def plot_hit_candidate(dat_file_list, fil_file_list, source_name_list, all_hits_frame, candidate=None, check_zero_drift=False, outdir=None, alpha=1, color='black', window=None): """ Parameters ---------- dat_file_list : list A Python list that contains a series of strings corresponding to the filenames of .dat files, each on a new line, that corresponds to the .dat files created when running turboSETI candidate search on the .h5 or .fil files below fil_file_list : list A Python list that contains a series of strings corresponding to the filenames of .dat files, each on a new line, that corresponds to the cadence used to create the .csv file used for event_csv_string. source_name_list : list A Python list that contains a series of strings corresponding to the source names of the cadence in chronological (descending through the plot pannels) cadence. all_hits_frame : dict A pandas dataframe contining information about all the hits detected. The necessary data includes the start and stop frequencies, the drift rate, and the source name. This dataframe is generated in plot_all_hit_and_candidates above. candidate : dict, optional A single row from a pandas dataframe containing information about one of the candidate signals detected. Contains information about the candidate signal to be plotted. The necessary data includes the start and stop frequencies, the drift rate, and the source name. The dataframe the candiate comes from is generated in plot_all_hit_and_candidates above as `candidate_event_dataframe`. The default is None. check_zero_drift : bool, optional A True/False flag that tells the program whether to include hits that have a drift rate of 0 Hz/s. Earth- based RFI tends to have no drift rate, while signals from the sky are expected to have non-zero drift rates. The default is False. outdir : str, optional Path to the directory where the plots will be saved to. The default is None, which will result in the plots being saved to the directory the .dat file are located. alpha : float, optional The opacity of the overlayed hit plot. This should be between 0 and 1, with 0 being invisible, and 1 being the default opacity. This is passed into matplotlib.pyplot function. color : str, optional Allows for the specification of the color of the overlayed hits. The default is 'black'. window : tuple, optional Sets the start and stop frequencies of the plot, in MHz. The input takes the form of a tuple: (start, stop). And assumes that the start is less than the stop. The resulting plot will range exactly between the start/stop frequencies. The default is None, which will result in a plot of the entire range of hits detected. """ #set plot boundaries based on the contents of the file freq_range = np.max(all_hits_frame["Freq"]) - np.min( all_hits_frame["Freq"]) filter_level = "f0" # total range all hits fall between f_min = np.min(all_hits_frame["Freq"]) f_max = np.max(all_hits_frame["Freq"]) fil1 = bl.Waterfall(fil_file_list[0], load_data=False) t0 = fil1.header["tstart"] t_elapsed = Time(fil1.header['tstart'], format='mjd').unix - Time( t0, format='mjd').unix bandwidth = 2.4 * abs(freq_range) / 1e6 * t_elapsed bandwidth = np.max((bandwidth, 500. / 1e6)) # Get start and stop frequencies based on midpoint and bandwidth f_start, f_stop = np.sort( (f_min - (bandwidth / 2), f_max + (bandwidth / 2))) mid_f = 0.5 * (f_start + f_stop) #if given a window to plot in, set boundaries accordingly if window is not None: f_start = min(window) f_stop = max(window) mid_f = 0.5 * (f_start + f_stop) # plugging some code from make_waterfall_plots global logger_plot_event # prepare for plotting matplotlib.rc('font', **font) # set up the sub-plots n_plots = len(fil_file_list) fig = plt.subplots(n_plots, sharex=True, sharey=True, figsize=(10, 2 * n_plots)) # get directory path for storing PNG files dirpath = dirname(fil_file_list[0]) + '/' # read in data for the first panel max_load = bl.calcload.calc_max_load(fil_file_list[0]) print('plot_dat plot_hit_candidate: max_load={} is required for {}'.format( max_load, fil_file_list[0])) fil1 = bl.Waterfall(fil_file_list[0], f_start=f_start, f_stop=f_stop, max_load=max_load) t0 = fil1.header['tstart'] dummy, plot_data1 = fil1.grab_data() # rebin data to plot correctly with fewer points dec_fac_x, dec_fac_y = 1, 1 if plot_data1.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data1.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data1.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data1.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data1 = rebin(plot_data1, dec_fac_x, dec_fac_y) subplots = [] del fil1, dummy, plot_data1 gc.collect() on_source_name = source_name_list[0] f_candidate = mid_f if candidate is not None: on_source_name = candidate["Source"] f_candidate = candidate["Freq"] for i, filename in enumerate(fil_file_list): subplot = plt.subplot(n_plots, 1, i + 1) subplots.append(subplot) #read in the data max_load = bl.calcload.calc_max_load(filename) print( 'plot_event make_waterfall_plots: max_load={} is required for {}'. format(max_load, filename)) wf = bl.Waterfall(filename, f_start=f_start, f_stop=f_stop, max_load=max_load) this_plot = plot_event.plot_waterfall(wf, source_name_list[i], f_start, f_stop) make_plot(dat_file_list[i], fil_file_list[i], f_start, f_stop, t0, candidate, check_zero_drift=check_zero_drift, alpha=alpha, color=color) #more code from make_waterfall_plots # Title the full plot if i == 0: plot_title = "%s \n MJD:%5.5f" % (on_source_name, t0) plt.title(plot_title) # Format full plot if i < len(fil_file_list) - 1: plt.xticks(np.linspace(f_start, f_stop, num=4), ['', '', '', '']) del wf gc.collect() # More overall plot formatting, axis labelling factor = 1e6 units = 'Hz' #ax = plt.gca() #ax.get_xaxis().get_major_formatter().set_useOffset(False) xloc = np.linspace(f_start, f_stop, 5) xticks = [round(loc_freq) for loc_freq in (xloc - mid_f) * factor] if np.max(xticks) > 1000: xticks = [xt / 1000 for xt in xticks] units = 'kHz' plt.xticks(xloc, xticks) plt.xlabel("Relative Frequency [%s] from %f MHz" % (units, mid_f), fontdict=font) # Add colorbar cax = fig[0].add_axes([0.94, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot, cax=cax, label='Normalized Power (Arbitrary Units)') # Adjust plots plt.subplots_adjust(hspace=0, wspace=0) # save the figures if outdir is not None: dirpath = outdir # make note if the plot contains a candidate cand = "" if candidate is not None: cand = "_candidate" path_png = dirpath + filter_level + '_' + on_source_name + cand + '_freq_' "{:0.6f}".format( f_candidate) + ".png" plt.savefig(path_png, bbox_inches='tight', transparent=False) logger_plot_event.debug( 'make_waterfall_plots: Saved file {}'.format(path_png)) # close all figure windows plt.close('all')
def plot_waterfall(fil, source_name, f_start=None, f_stop=None, f_scrunch=1, **kwargs): """ Plot waterfall of data in a .fil or .h5 file Args: fil (str): filterbank file containing the dynamic spectrum data source_name (str): name of the target f_start (float): start frequency, in MHz f_stop (float): stop frequency, in MHz f_scrunch (int): Average across frequency channels kwargs: keyword args to be passed to matplotlib imshow() """ file1 = os.getcwd() + '/' + fil #prepare font #matplotlib.rc('font', **font) fil = bl.Waterfall(file1, f_start=f_start, f_stop=f_stop) #Load in the data from fil plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) #Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 if dec_fac_y == 1 and f_scrunch > 1: dec_fac_y = f_scrunch #rebinning data to plot correctly with fewer points if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) #fix case where frequencies are reversed by fil.grab_data() # Shane Smith PR #82 if plot_f[-1] < plot_f[0]: plot_f = plot_f[::-1] plot_data = plot_data[:, ::-1] #determine extent of the plotting panel for imshow extent = (plot_f[0], plot_f[-1], (fil.timestamps[-1] - fil.timestamps[0]) * 24. * 60. * 60, 0.0) #plot and scale intensity (log vs. linear) kwargs['cmap'] = kwargs.get('cmap', 'viridis') kwargs['logged'] = True if kwargs['logged'] == True: plot_data = 10 * np.log10(plot_data) kwargs.pop('logged') #get normalization parameters vmin = plot_data.min() vmax = plot_data.max() normalized_plot_data = (plot_data - vmin) / (vmax - vmin) #display the waterfall plot this_plot = plt.imshow(normalized_plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, **kwargs) #add plot labels plt.xlabel("Frequency [Hz]", fontdict=font) plt.ylabel("Time [s]", fontdict=font) #add source name ax = plt.gca() #plt.text(0.03, 0.8, source_name, transform=ax.transAxes, bbox=dict(facecolor='white')) #if plot_snr != False: # plt.text(0.03, 0.6, plot_snr, transform=ax.transAxes, bbox=dict(facecolor='white')) #return plot return this_plot
def plot_waterfall(fil, f_start=None, f_stop=None, drate=None, if_id=0, logged=True, cb=False,freq_label=False,MJD_time=False, **kwargs): """Plot waterfall of data Args: f_start(float, optional): start frequency, in MHz (Default value = None) f_stop(float, optional): stop frequency, in MHz (Default value = None) logged(bool, optional): Plot in linear (False) or dB units (True), (Default value = True) cb(bool, optional): for plotting the colorbar (Default value = False) kwargs: keyword args to be passed to matplotlib imshow() fil: drate: (Default value = None) if_id: (Default value = 0) freq_label: (Default value = False) MJD_time: (Default value = False) **kwargs: Returns: """ #prepare font matplotlib.rc('font', **font) #Get the data plot_f, plot_data = fil.grab_data(f_start=f_start, f_stop=f_stop) # Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = plot_data.shape[1] / MAX_IMSHOW_POINTS[1] #insert rebin definition code from utils.py in blimpy and edit it because this is the problem d=plot_data n_x=dec_fac_x n_y=dec_fac_y d = rebin(d, n_x, n_y) plot_data=d #print('d', d) #plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) if MJD_time: extent=(plot_f[0], plot_f[-1], fil.timestamps[-1], fil.timestamps[0]) else: extent=(plot_f[0], plot_f[-1], (fil.timestamps[-1]-fil.timestamps[0])*24.*60.*60, 0.0) #plots and scales intensity kwargs['cmap'] = kwargs.get('cmap', 'viridis') kwargs['logged'] = True if kwargs['logged'] == True: plot_data = 10*np.log10(plot_data) kwargs.pop('logged') #shows the waterfall plot this_plot = plt.imshow(plot_data, aspect='auto', rasterized=True, interpolation='nearest', extent=extent, **kwargs ) #add colorbar if cb: plt.colorbar() #add plot labels if freq_label: plt.xlabel("Frequency [Hz]",fontdict=font) if MJD_time: plt.ylabel("Time [MJD]",fontdict=font) else: plt.ylabel("Time [s]",fontdict=font) return this_plot
def make_waterfall_plots(file_list, plot_dir, f_start=None, f_stop=None, **kwargs): r""" Make waterfall plots of a file set, view from top to bottom. Parameters ---------- file_list : str List of filterbank files to plot in a stacked mode. f_start : float Start frequency, in MHz. f_stop : float Stop frequency, in MHz. source_name_list : list List of source names in the set, in order. kwargs : dict Keyword args to be passed to matplotlib imshow(). """ # prepare for plotting matplotlib.rc("font", **font) # set up the sub-plots n_plots = len(file_list) fig = plt.subplots(n_plots, sharex=True, sharey=True, figsize=(10, 2 * n_plots)) # get directory path for storing PNG files if plot_dir is None: dirpath = dirname(abspath(file_list[0])) + "/" else: if not isdir(plot_dir): os.mkdir(plot_dir) dirpath = plot_dir # read in data for the first panel max_load = bl.calcload.calc_max_load(file_list[0]) #print("plot_event make_waterfall_plots: max_load={} is required for {}".format(max_load, file_list[0])) wf1 = bl.Waterfall(file_list[0], max_load=max_load) t0 = wf1.header["tstart"] source_name = wf1.header["source_name"] # Fix frequency boundaries if required. freqs = wf1.container.populate_freqs() if f_start is None: f_start = freqs[0] if f_stop is None: f_stop = freqs[-1] the_lowest, the_highest = sort2(f_start, f_stop) # rebin data to plot correctly with fewer points plot_f1, plot_data1 = wf1.grab_data(f_start=the_lowest, f_stop=the_highest) dec_fac_x, dec_fac_y = 1, 1 if plot_data1.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data1.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data1.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data1.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data1 = rebin(plot_data1, dec_fac_x, dec_fac_y) # Compute the midpoint. the_midpoint = np.abs(the_lowest + the_highest) / 2. # Protect RAM utilisation. del wf1, freqs, plot_f1, plot_data1 gc.collect() # Fill in each subplot for the full plot subplots = [] for ii, filename in enumerate(file_list): logger.debug("make_waterfall_plots: file {} in list: {}".format( ii, filename)) # identify panel subplot = plt.subplot(n_plots, 1, ii + 1) subplots.append(subplot) # read in data max_load = bl.calcload.calc_max_load(filename) wf = bl.Waterfall(filename, max_load=max_load) # Validate frequency range. freqs = wf.container.populate_freqs() ii_lowest, ii_highest = sort2(freqs[0], freqs[-1]) logger.info("Processing: {}, freq lowest={}, highest={}".format( filename, ii_lowest, ii_highest)) if the_lowest < ii_lowest or the_highest > ii_highest: logger.warning( "Frequency range not compatible! Ignoring this file.") # Protect RAM utilisation. del wf, freqs gc.collect() continue # Skip this file. # make plot with plot_waterfall source_name = wf.header["source_name"] this_plot = plot_waterfall(wf, f_start=the_lowest, f_stop=the_highest, **kwargs) # Title the full plot if processing the first file. if ii == 0: plot_title = "%s \n MJD:%5.5f (first file)" % (source_name, t0) plt.title(plot_title) # Format full plot. if ii < len(file_list) - 1: plt.xticks(np.linspace(the_lowest, the_highest, num=4), ["", "", "", ""]) # Protect RAM utilisation. del wf, freqs gc.collect() # More overall plot formatting, axis labelling. factor = 1e6 units = "Hz" xloc = np.linspace(the_lowest, the_highest, 5) xticks = [round(loc_freq) for loc_freq in (xloc - the_midpoint) * factor] if np.max(xticks) > 1000: xticks = [xt / 1000 for xt in xticks] units = "kHz" plt.xticks(xloc, xticks) plt.xlabel("Relative Frequency [%s] from %f MHz" % (units, the_midpoint), fontdict=font) # Add colorbar. cax = fig[0].add_axes([0.94, 0.11, 0.03, 0.77]) fig[0].colorbar(this_plot, cax=cax, label="Normalized Power (Arbitrary Units)") # Adjust plots plt.subplots_adjust(hspace=0, wspace=0) # Save the figures. path_png = dirpath + source_name + "_fstart_{:0.6f}".format(f_start) \ + "_fstop_{:0.6f}".format(f_stop) + ".png" plt.savefig(path_png, bbox_inches="tight") logger.info("Saved plot: {}".format(path_png)) # show figure before closing if this is an interactive context mplbe = matplotlib.get_backend() logger.debug("make_waterfall_plots: backend = {}".format(mplbe)) if mplbe != "agg": plt.show() # close all figure windows plt.close("all")
def plot_waterfall(wf, f_start=None, f_stop=None, **kwargs): r""" Plot waterfall of data in a .fil or .h5 file. Parameters ---------- wf : blimpy.Waterfall object Waterfall object of an H5 or Filterbank file containing the dynamic spectrum data. f_start : float Start frequency, in MHz. f_stop : float Stop frequency, in MHz. kwargs : dict Keyword args to be passed to matplotlib imshow(). Notes ----- Plot a single-panel waterfall plot (frequency vs. time vs. intensity) for one of the files in the set of interest, at the frequency of the expected event. """ # Extract source name. source_name = wf.header["source_name"] # prepare font matplotlib.rc("font", **font) # Load in the data from fil plot_f, plot_data = wf.grab_data(f_start=f_start, f_stop=f_stop) # Make sure waterfall plot is under 4k*4k dec_fac_x, dec_fac_y = 1, 1 # rebinning data to plot correctly with fewer points try: if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) except Exception as ex: print( "\n*** Oops, grab_data returned plot_data.shape={}, plot_f.shape={}" .format(plot_data.shape, plot_f.shape)) print("Waterfall info for {}:".format(wf.filename)) wf.info() raise ValueError( "*** Something is wrong with the grab_data output!") from ex # Rolled back PR #82 # determine extent of the plotting panel for imshow extent = (plot_f[0], plot_f[-1], (wf.timestamps[-1] - wf.timestamps[0]) * 24. * 60. * 60, 0.0) # plot and scale intensity (log vs. linear) kwargs["cmap"] = kwargs.get("cmap", "viridis") plot_data = 10.0 * np.log10(plot_data) # get normalization parameters vmin = plot_data.min() vmax = plot_data.max() normalized_plot_data = (plot_data - vmin) / (vmax - vmin) # display the waterfall plot this_plot = plt.imshow(normalized_plot_data, aspect="auto", rasterized=True, interpolation="nearest", extent=extent, **kwargs) # add plot labels plt.xlabel("Frequency [Hz]", fontdict=font) plt.ylabel("Time [s]", fontdict=font) # add source name ax = plt.gca() plt.text(0.03, 0.8, source_name, transform=ax.transAxes, bbox=dict(facecolor="white")) return this_plot
for i in range(len(low_freqs)): f_start=low_freqs[i] f_stop=high_freqs[i] plt.figure(i) fil = Waterfall(filename, f_start=f_start, f_stop=f_stop) dummy, plot_data = fil.grab_data() # rebin data to plot correctly with fewer points dec_fac_x, dec_fac_y = 1, 1 if plot_data.shape[0] > MAX_IMSHOW_POINTS[0]: dec_fac_x = plot_data.shape[0] / MAX_IMSHOW_POINTS[0] if plot_data.shape[1] > MAX_IMSHOW_POINTS[1]: dec_fac_y = int(np.ceil(plot_data.shape[1] / MAX_IMSHOW_POINTS[1])) plot_data = rebin(plot_data, dec_fac_x, dec_fac_y) f_mid = round(np.abs(f_start+f_stop)/2., 4) mid_f = round(np.abs(f_start+f_stop)/2., 4) drift_rate=drift_rates[i] # read in data fig=plt.figure(1) t0 = fil.header['tstart'] # make plot with plot_waterfall source_name = 'TESS_TOI_1449.02'