def get_noise_power(TBB_datafile, RFI_filter, ant_i, block_range, max_fraction_doubleZeros=0.0005): ret = None for block in range(block_range[0], block_range[1]): data = TBB_datafile.get_data(block * RFI_filter.blocksize, RFI_filter.blocksize, antenna_index=ant_i) DBZ_fraction = num_double_zeros(data) / RFI_filter.blocksize if DBZ_fraction > max_fraction_doubleZeros: continue data = RFI_filter.filter(np.array(data, dtype=np.double)) edge_width = int(RFI_filter.blocksize * RFI_filter.half_window_percent) HE = np.abs(data[edge_width:-edge_width]) noise_power = HE * HE ave_noise_power = np.average(noise_power) ret = ave_noise_power break return ret
def get_trace_fromIndex(self, starting_index, ant_name, width, do_remove_RFI=True, do_remove_saturation=True, positive_saturation=2046, negative_saturation=-2047, removal_length=50, saturation_half_hann_length=50): """similar to previous, but now retrieve trace based on location in file. For repeatability. Has same returns. predicted arrival time is just the time in middle of trace""" station_name = SId_to_Sname[int(ant_name[:3])] station_data = self.data_file_dict[station_name] data_filter = self.data_filter_dict[station_name] file_antenna_index = station_data.get_antenna_names().index(ant_name) total_time_offset = station_data.get_total_delays()[file_antenna_index] local_data_index = int(data_filter.blocksize * 0.5) input_data = station_data.get_data(starting_index - local_data_index, data_filter.blocksize, antenna_index=file_antenna_index) input_data = np.array(input_data, dtype=np.double) if do_remove_saturation: remove_saturation(input_data, positive_saturation, negative_saturation, removal_length, saturation_half_hann_length) if self.return_dbl_zeros: dbl_zeros = num_double_zeros( input_data[local_data_index:local_data_index + width]) if do_remove_RFI: data = data_filter.filter( input_data)[local_data_index:local_data_index + width] else: data = input_data[local_data_index:local_data_index + width] predicted_arrival_time = starting_index * 5.0E-9 - total_time_offset + 0.5 * width * 5.0E-9 if self.return_dbl_zeros: return starting_index, total_time_offset, predicted_arrival_time, data, dbl_zeros else: return starting_index, total_time_offset, predicted_arrival_time, data
def FindRFI(TBB_in_file, block_size, initial_block, num_blocks, max_blocks=None, verbose=False, figure_location=None, lower_frequency=10E6, upper_frequency=90E6, num_dbl_z=100): """ use phase-variance to find RFI in data. TBB_in_file should be a MultiFile_Dal1, encompassing the data for one station. block_size should be around 65536 (2^16). num_blocks should be at least 20. Sometimes a block needs to be skipped, so max_blocks shows the maximum number of blocks used (after initial block) used to find num_blocks number of good blocks. initial block should be such that there is no lightning in the max_blocks number of blocks. If max_blocks is None (default), it is set to num_blocks figure_location should be a folder to save relavent figures, default is None (do not save figures). num_dbl_z is number of double zeros allowed in a block, if there are too many, then there could be data loss. returns a dictionary with the following key-value pairs: "ave_spectrum_magnitude":a numpy array that contains the average of the magnitude of the frequency spectrum "ave_spectrum_phase": a numpy array containing the average of the phase of the frequency spectrum "phase_variance":a numpy array containing the phase variance of each frequency channel "dirty_channels": an array of indeces indicating the channels that are contaminated with RFI """ if max_blocks is None: max_blocks = num_blocks window_function = half_hann_window(block_size, 0.1) num_antennas = len(TBB_in_file.get_antenna_names()) if figure_location is not None: max_over_blocks = np.zeros((num_antennas, max_blocks), dtype=np.double) #### step one: find which blocks are good, and find average power #### oneAnt_data = np.empty(block_size, dtype=np.double) if verbose: print('finding good blocks') blocks_good = np.zeros((num_antennas, max_blocks), dtype=bool) num_good_blocks = np.zeros(num_antennas, dtype=int) average_power = np.zeros(num_antennas, dtype=np.double) for block_i in range(max_blocks): block = block_i + initial_block for ant_i in range(num_antennas): oneAnt_data[:] = TBB_in_file.get_data(block_size * block, block_size, antenna_index=ant_i) if num_double_zeros( oneAnt_data ) < num_dbl_z: ## this antenna on this block is good blocks_good[ant_i, block_i] = True num_good_blocks[ant_i] += 1 oneAnt_data *= window_function FFT_data = np.fft.fft(oneAnt_data) np.abs(FFT_data, out=FFT_data) magnitude = FFT_data magnitude *= magnitude average_power[ant_i] += np.real(np.sum(magnitude)) # else: # print(block_i, ant_i, num_double_zeros( oneAnt_data )) # plt.plot(oneAnt_data) # plt.show() if figure_location is not None: max_over_blocks[ant_i, block_i] = np.max(oneAnt_data[ant_i]) average_power[num_good_blocks != 0] /= num_good_blocks[ num_good_blocks != 0] #### now we try to find the best referance antenna, Require that antenan allows for maximum number of good antennas, and has **best** average recieved power allowed_num_antennas = np.empty( num_antennas, dtype=np.int ) ## if ant_i is choosen to be your referance antnena, then allowed_num_antennas[ ant_i ] is the number of antennas with num_blocks good blocks for ant_i in range(num_antennas): ### fill allowed_num_antennas blocks_can_use = np.where(blocks_good[ant_i])[0] num_good_blocks_per_antenna = np.sum(blocks_good[:, blocks_can_use], axis=1) allowed_num_antennas[ant_i] = np.sum( num_good_blocks_per_antenna >= num_blocks) max_allowed_antennas = np.max(allowed_num_antennas) if max_allowed_antennas < 2: print("ERROR: station", TBB_in_file.get_station_name(), "cannot find RFI") return ## pick ref antenna that allows max number of atnennas, and has most median amount of power can_be_ref_antenna = (allowed_num_antennas == max_allowed_antennas) sorted_by_power = np.argsort(average_power) mps = median_sorted_by_power(sorted_by_power) for ant_i in mps: if can_be_ref_antenna[ant_i]: ref_antenna = ant_i break if verbose: print('Taking channel %d as reference antenna' % ref_antenna) ## define some helping variables ## good_blocks = np.where(blocks_good[ref_antenna])[0] num_good_blocks = np.sum(blocks_good[:, good_blocks], axis=1) antenna_is_good = num_good_blocks >= num_blocks blocks_good[np.logical_not(antenna_is_good), :] = False #### process data #### num_processed_blocks = np.zeros(num_antennas, dtype=int) frequencies = np.fft.fftfreq(block_size, 1.0 / TBB_in_file.get_sample_frequency()) lower_frequency_index = np.searchsorted( frequencies[:int(len(frequencies) / 2)], lower_frequency) upper_frequency_index = np.searchsorted( frequencies[:int(len(frequencies) / 2)], upper_frequency) phase_mean = np.zeros( (num_antennas, upper_frequency_index - lower_frequency_index), dtype=complex) spectrum_mean = np.zeros( (num_antennas, upper_frequency_index - lower_frequency_index), dtype=np.double) data = np.empty((num_antennas, len(frequencies)), dtype=np.complex) temp_mag_spectrum = np.empty((num_antennas, len(frequencies)), dtype=np.double) temp_phase_spectrum = np.empty((num_antennas, len(frequencies)), dtype=np.complex) for block_i in good_blocks: block = block_i + initial_block if verbose: print('Doing block %d' % block) for ant_i in range(num_antennas): if (num_processed_blocks[ant_i] == num_blocks and not ant_i == ref_antenna) or not blocks_good[ant_i, block_i]: continue oneAnt_data[:] = TBB_in_file.get_data(block_size * block, block_size, antenna_index=ant_i) ##window the data # Note: No hanning window if we want to measure power accurately from spectrum # in the same units as power from timeseries. Applying a window gives (at least) a scale factor # difference! # But no window makes the cleaning less effective... :( oneAnt_data *= window_function data[ant_i] = np.fft.fft(oneAnt_data) data /= block_size np.abs(data, out=temp_mag_spectrum) temp_phase_spectrum[:] = data temp_phase_spectrum /= (temp_mag_spectrum + 1.0E-15) temp_phase_spectrum[:, :] /= temp_phase_spectrum[ref_antenna, :] temp_mag_spectrum *= temp_mag_spectrum ## square for ant_i in range(num_antennas): if (num_processed_blocks[ant_i] == num_blocks and not ant_i == ref_antenna) or not blocks_good[ant_i, block_i]: continue phase_mean[ant_i, :] += temp_phase_spectrum[ant_i][ lower_frequency_index:upper_frequency_index] spectrum_mean[ant_i, :] += temp_mag_spectrum[ant_i][ lower_frequency_index:upper_frequency_index] num_processed_blocks[ant_i] += 1 if np.min(num_processed_blocks[antenna_is_good]) == num_blocks: break if verbose: print(num_blocks, "analyzed blocks", np.sum(antenna_is_good), "analyzed antennas out of", len(antenna_is_good)) ## get only good antennas antenna_is_good[ ref_antenna] = False ## we don't want to analyze the phase stability of the referance antenna ### get mean and phase stability ### spectrum_mean /= num_blocks phase_stability = np.abs(phase_mean) phase_stability *= -1.0 / num_blocks phase_stability += 1.0 #### get median of stability by channel, across each antenna ### median_phase_spread_byChannel = np.median(phase_stability[antenna_is_good], axis=0) #### get median across all chanells median_spread = np.median(median_phase_spread_byChannel) #### create a noise cuttoff### sorted_phase_spreads = np.sort(median_phase_spread_byChannel) N = len(median_phase_spread_byChannel) noise = sorted_phase_spreads[int(N * 0.95)] - sorted_phase_spreads[int( N / 2)] #### get channels contaminated by RFI, where phase stability is smaller than noise ### dirty_channels = np.where( median_phase_spread_byChannel < (median_spread - 3 * noise))[0] ### extend dirty channels by some size, in order to account for shoulders #### extend_dirty_channels = np.zeros(N, dtype=bool) half_flagwidth = int(block_size / 8192) for i in dirty_channels: flag_min = i - half_flagwidth flag_max = i + half_flagwidth if flag_min < 0: flag_min = 0 if flag_max >= N: flag_max = N - 1 extend_dirty_channels[flag_min:flag_max] = True dirty_channels = np.where(extend_dirty_channels)[0] antenna_is_good[ref_antenna] = True ## cause'.... ya know.... it is #### plot and return data #### frequencies = frequencies[lower_frequency_index:upper_frequency_index] if figure_location is not None: frequencies_MHZ = frequencies * 1.0E-6 plt.figure() plt.plot(frequencies_MHZ, median_phase_spread_byChannel) plt.axhline(median_spread - 3 * noise, color='r') plt.title( "Phase spread vs frequency. Red horizontal line shows cuttoff.") plt.ylabel("Spread value") plt.xlabel("Frequency [MHz]") # plt.legend() if figure_location == "show": plt.show() else: plt.savefig(figure_location + '/phase_spreads.png') plt.close() plt.figure() plt.plot(frequencies_MHZ, spectrum_mean[ref_antenna]) plt.plot(frequencies_MHZ[dirty_channels], spectrum_mean[ref_antenna][dirty_channels], 'ro') plt.xlabel("Frequency [MHz]") plt.ylabel("magnitude") plt.yscale('log', nonposy='clip') # plt.legend() if figure_location == "show": plt.show() else: plt.savefig(figure_location + '/magnitude.png') plt.close() plt.figure() for maxes, ant_name in zip(max_over_blocks, TBB_in_file.get_antenna_names()): plt.plot(maxes, label=ant_name) plt.ylabel("maximum") plt.xlabel("block index") plt.legend() if figure_location == "show": plt.show() else: plt.savefig(figure_location + '/max_over_blocks.png') plt.close() output_dict = {} output_dict["ave_spectrum_magnitude"] = spectrum_mean output_dict["ave_spectrum_phase"] = np.angle(phase_mean, deg=False) output_dict["phase_variance"] = phase_stability output_dict["dirty_channels"] = dirty_channels + lower_frequency_index output_dict["blocksize"] = block_size cleaned_spectrum = np.array(spectrum_mean) cleaned_spectrum[:, dirty_channels] = 0.0 output_dict["cleaned_spectrum_magnitude"] = cleaned_spectrum output_dict["cleaned_power"] = 2 * np.sum(cleaned_spectrum, axis=1) print('cleaned power:', output_dict["cleaned_power"]) print('old power', 2 * np.sum(spectrum_mean, axis=1)) print('num dirty channels:', len(dirty_channels)) output_dict["antenna_names"] = TBB_in_file.get_antenna_names() output_dict["timestamp"] = TBB_in_file.get_timestamp() output_dict["antennas_good"] = antenna_is_good output_dict["frequency"] = frequencies return output_dict
def process_block(self, start_index, block_index, h5_groupobject, log_func=do_nothing): #### open and filter the data #### prefered_ant_i = None prefered_ant_dataLoss = np.inf for ant_i, (station_i, station_ant_i) in enumerate(self.antennas_to_use): data_file = self.input_files[station_i] RFI_filter = self.RFI_filters[station_i] offset = self.antenna_data_offsets[ant_i] self.data_block[ant_i, :] = data_file.get_data(start_index+offset, self.block_size, antenna_index=station_ant_i) ## get the data. accounting for the offsets calculated earlier remove_saturation(self.data_block[ant_i, :], self.positive_saturation, self.negative_saturation, post_removal_length=self.saturation_removal_length, half_hann_length=self.saturation_hann_window_length) if ant_i in self.station_to_antenna_indeces_dict[ self.prefered_station ]: ## this must be done before filtering num_D_zeros = num_double_zeros( self.data_block[ant_i, :] ) if num_D_zeros < prefered_ant_dataLoss: ## this antenna could be teh antenna, in the prefered station, with least data loss prefered_ant_dataLoss = num_D_zeros prefered_ant_i = ant_i self.data_block[ant_i, :] = RFI_filter.filter( self.data_block[ant_i, :] ) ### make output object ### h5_groupobject = h5_groupobject.create_group(str(block_index)) h5_groupobject.attrs['block_index'] = block_index h5_groupobject.attrs['start_index'] = start_index h5_groupobject.attrs['prefered_ant_i'] = prefered_ant_i #### find sources #### np.abs( self.data_block[ prefered_ant_i ], out=self.hilbert_envelope_tmp ) for event_i in range(self.max_events_perBlock): ## find peak ## peak_loc = np.argmax(self.hilbert_envelope_tmp[self.startBlock_exclusion : -self.endBlock_exclusion ]) + self.startBlock_exclusion trace_start_loc = peak_loc - int( self.pulse_length/2 ) # pobably account for fact that trace is now longer than pulse_length on prefered antenna if self.hilbert_envelope_tmp[peak_loc] < self.min_pref_ant_amplitude: log_func("peaks are too small. Done searching") break ## select data for stage one ## s1_ant_i = 0 for ant_i, (station_i, station_ant_i) in enumerate(self.antennas_to_use): if self.use_core_stations_S1 or self.is_not_core[ant_i]: half_window_length = self.half_antenna_data_length[ant_i] self.stage_1_imager.set_data( self.data_block[ant_i][trace_start_loc : trace_start_loc+2*half_window_length], s1_ant_i ) s1_ant_i += 1 ## fft and xcorrelation ## self.stage_1_imager.prepare_image( prefered_ant_i, self.min_pulse_amplitude ) log_func("source:", event_i) stage_1_result, num_itter, num_stage1_itters = stochastic_minimizer(self.stage_1_imager.intensity, self.bounding_box, converg_num=self.stage_1_converg_num, converg_rad=self.stage_1_converg_radius, max_itters=self.stage_1_max_itters) log_func(" stoch. itters:", num_itter, num_stage1_itters) ## select data for stage 2 ## previous_solution = stage_1_result converged = False for stage2loop_i in range(self.stage_2_max_itters): problem = False s2_ant_i = -1 for ant_i in range( self.num_antennas ): if self.use_core_stations_S2 or self.is_not_core[ant_i]: s2_ant_i += 1 ## do this here cause of break below modeled_dt = -( np.linalg.norm( self.antenna_locations[ prefered_ant_i ]-previous_solution.x ) - np.linalg.norm( self.antenna_locations[ant_i]-previous_solution.x ) )/v_air modeled_dt -= self.antenna_delays[ prefered_ant_i ] - self.antenna_delays[ant_i] modeled_dt /= 5.0E-9 modeled_dt += peak_loc modeled_dt = int(modeled_dt) if modeled_dt+int(self.pulse_length/2) >= len(self.data_block[ant_i]): problem = True break self.stage_2_imager.set_data( self.data_block[ant_i, modeled_dt-int(self.pulse_length/2):modeled_dt+int(self.pulse_length/2)]*self.stage_2_window, s2_ant_i, -modeled_dt*5.0E-9 ) if problem: log_func("unknown problem. LOC at", previous_solution.x) self.hilbert_envelope_tmp[peak_loc-int(self.pulse_length/2):peak_loc+int(self.pulse_length/2)] = 0.0 continue ## fft and and xcorrelation ## self.stage_2_imager.prepare_image( self.min_pulse_amplitude ) # BB = np.array( [ [previous_solution.x[0]-50, previous_solution.x[0]+50], [previous_solution.x[1]-50, previous_solution.x[1]+50], [previous_solution.x[2]-50, previous_solution.x[2]+50] ] ) stage_2_result, s2_itternum, num_stage2_itters = stochastic_minimizer(self.stage_2_imager.intensity_ABSbefore , BB, converg_num=5, test_spot=previous_solution.x, converg_rad=self.stage_2_convergence_length, max_itters=self.stage_2_max_stoch_itters, options={'maxiter':1000}) D = np.linalg.norm( stage_2_result.x - previous_solution.x ) log_func(" s2 itter: {:2d} {:4.2f} {:d}".format(stage2loop_i, -stage_2_result.fun, int(D)) ) if D < self.stage_2_convergence_length: converged = True break elif D > self.stage_2_break_length: converged = False break previous_solution = stage_2_result new_stage_1_result = minimize(self.stage_1_imager.intensity, stage_2_result.x, method="Nelder-Mead", options={'maxiter':1000}) log_func(" old S1: {:4.2f} new SH1: {:4.2f}".format(-stage_1_result.fun, -new_stage_1_result.fun) ) if stage_1_result.fun < new_stage_1_result.fun: S1_S2_distance = np.linalg.norm(stage_1_result.x-stage_2_result.x) else: S1_S2_distance = np.linalg.norm(new_stage_1_result.x-stage_2_result.x) log_func(" loc: {:d} {:d} {:d}".format(int(stage_2_result.x[0]), int(stage_2_result.x[1]), int(stage_2_result.x[2])) ) log_func(" S1-S2 distance: {:d} converged: {} ".format( int(S1_S2_distance), converged) ) log_func(" intensity: {:4.2f} amplitude: {:d} ".format( -stage_2_result.fun, int(self.hilbert_envelope_tmp[peak_loc])) ) log_func() log_func() ## save to file ## source_dataset = h5_groupobject.create_dataset(str(event_i), (self.num_antennas,self.pulse_length), dtype=np.complex) source_dataset.attrs["loc"] = stage_2_result.x source_dataset.attrs["unique_index"] = block_index*self.max_events_perBlock + event_i source_time_s2 = (peak_loc+start_index+self.antenna_data_offsets[prefered_ant_i])*5.0E-9 - np.linalg.norm( stage_2_result.x - self.antenna_locations[ prefered_ant_i ] )/v_air source_time_s2 -= self.prefered_station_timing_offset + self.prefered_station_antenna_timing_offsets[ self.antennas_to_use[prefered_ant_i][1] ] source_dataset.attrs["T"] = source_time_s2 source_dataset.attrs["peak_index"] = peak_loc source_dataset.attrs["intensity"] = -stage_2_result.fun source_dataset.attrs["stage_1_success"] = (num_stage1_itters==self.stage_1_converg_num) source_dataset.attrs["stage_1_num_itters"] = num_stage1_itters source_dataset.attrs["amplitude"] = self.hilbert_envelope_tmp[peak_loc] source_dataset.attrs["S1_S2_distance"] = S1_S2_distance source_dataset.attrs["converged"] = converged source_time_s1 = (peak_loc+start_index+self.antenna_data_offsets[prefered_ant_i])*5.0E-9 - np.linalg.norm( stage_1_result.x - self.antenna_locations[ prefered_ant_i ] )/v_air source_time_s1 -= self.prefered_station_timing_offset + self.prefered_station_antenna_timing_offsets[ self.antennas_to_use[prefered_ant_i][1] ] source_dataset.attrs["XYZT_s1"] = np.append(stage_1_result.x, [source_time_s1]) #### erase the peaks !! #### # self.hilbert_envelope_tmp[peak_loc-int(self.pulse_length/2):peak_loc+int(self.pulse_length/2)] *= self.erasure_window self.hilbert_envelope_tmp[peak_loc-int(self.pulse_length/2):peak_loc+int(self.pulse_length/2)] = 0.0 if converged and self.erase_pulses: for ant_i in range( self.num_antennas ): modeled_dt = -( np.linalg.norm( self.antenna_locations[ prefered_ant_i ]-stage_2_result.x ) - np.linalg.norm( self.antenna_locations[ant_i]-stage_2_result.x ) )/v_air modeled_dt -= self.antenna_delays[ prefered_ant_i ] - self.antenna_delays[ant_i] modeled_dt /= 5.0E-9 modeled_dt += peak_loc modeled_dt = int(modeled_dt) source_dataset[ant_i] = self.data_block[ant_i, modeled_dt-int(self.pulse_length/2):modeled_dt+int(self.pulse_length/2)] self.data_block[ant_i, modeled_dt-int(self.pulse_length/2):modeled_dt+int(self.pulse_length/2)] *= self.erasure_window
def get_noise_std(timeID, initial_block, max_num_blocks, max_double_zeros=100, stations=None, polarization_flips="polarization_flips.txt", bad_antennas="bad_antennas.txt"): processed_data_folder = processed_data_dir(timeID) if isinstance(polarization_flips, str): polarization_flips = read_antenna_pol_flips(processed_data_folder + '/' + polarization_flips) if isinstance(processed_data_folder, str): bad_antennas = read_bad_antennas(processed_data_folder + '/' + bad_antennas) half_window_percent = 0.1 half_window_percent *= 1.1 ## just to be sure we are away from edge raw_fpaths = filePaths_by_stationName(timeID) if stations is None: stations = raw_fpaths.keys() out_dict = {} for sname in stations: print(sname) TBB_data = MultiFile_Dal1(raw_fpaths[sname], polarization_flips=polarization_flips, bad_antennas=bad_antennas) RFI_filter = window_and_filter(timeID=timeID, sname=sname) block_size = RFI_filter.blocksize edge_size = int(half_window_percent * block_size) antenna_names = TBB_data.get_antenna_names() measured_std = np.zeros(len(antenna_names)) measured_std[:] = -1 for block_i in range(initial_block, initial_block + max_num_blocks): for ant_i in range(len(antenna_names)): if measured_std[ant_i] > 0: continue ## we got a measurment, so skip it data = np.array(TBB_data.get_data(block_i * block_size, block_size, antenna_index=ant_i), dtype=np.double) if num_double_zeros(data) > max_double_zeros: continue ## bad block, skip filtered_data = np.real(RFI_filter.filter(data)) filtered_data = filtered_data[edge_size: -edge_size] ##avoid the edge measured_std[ant_i] = np.std(filtered_data) if np.all(measured_std > 0): ## we can break early break for ant_name, std in zip(antenna_names, measured_std): out_dict[ant_name] = std filter = measured_std > 0 print(" ave std:", np.average(measured_std[filter])) print(" total ant:", len(filter), "good ant:", np.sum(filter)) print() return out_dict
def __init__(self, TBB_data, polarization, initial_block, number_of_blocks, pulses_per_block=10, pulse_length=50, min_amplitude=50, upsample_factor=0, min_num_antennas=4, max_num_planewaves=np.inf, timeID=None, blocksize=2**16, positive_saturation=2046, negative_saturation=-2047, saturation_post_removal_length=50, saturation_half_hann_length=50, verbose=True): self.parabolic_fitter = parabolic_fitter() self.polarization = polarization self.TBB_data = TBB_data left_pulse_length = int(pulse_length / 2) right_pulse_length = pulse_length - left_pulse_length ant_names = TBB_data.get_antenna_names() num_antenna_pairs = int(len(ant_names) / 2) self.num_found_planewaves = 0 if num_antenna_pairs < min_num_antennas: return RFI_filter = window_and_filter( timeID=timeID, sname=TBB_data.get_station_name(), blocksize=(blocksize if timeID is None else None)) block_size = RFI_filter.blocksize self.num_found_planewaves = 0 data = np.empty((num_antenna_pairs, block_size), dtype=np.double) self.planewave_data = [] self.planewave_second_derivatives = [] for block in range(initial_block, initial_block + number_of_blocks): if self.num_found_planewaves >= max_num_planewaves: break #### open and filter data # print('open block', block) for pair_i in range(num_antenna_pairs): ant_i = pair_i * 2 + polarization data[pair_i, :] = TBB_data.get_data(block * block_size, block_size, antenna_index=ant_i) remove_saturation(data[pair_i, :], positive_saturation, negative_saturation, saturation_post_removal_length, saturation_half_hann_length) np.abs(RFI_filter.filter(data[pair_i, :]), out=data[pair_i, :]) #### loop over finding planewaves i = 0 while i < pulses_per_block: if self.num_found_planewaves >= max_num_planewaves: break pulse_location = 0 pulse_amplitude = 0 ## find highest peak for pair_i, HE in enumerate(data): loc = np.argmax(HE) amp = HE[loc] if amp > pulse_amplitude: pulse_amplitude = amp pulse_location = loc ## check if is strong enough if pulse_amplitude < min_amplitude: break ## get newPW_data = np.full(num_antenna_pairs, np.nan, dtype=np.double) newPW_derivatives = np.full(num_antenna_pairs, np.nan, dtype=np.double) for pair_i, HE in enumerate(data): # ant_i = pair_i*2 + polarization signal = np.array( HE[pulse_location - left_pulse_length:pulse_location + right_pulse_length]) if num_double_zeros(signal, threshold=0.1) == 0: sample_time = 5.0E-9 if upsample_factor > 1: sample_time /= upsample_factor signal = resample(signal, len(signal) * upsample_factor) newPW_data[pair_i] = self.parabolic_fitter.fit( signal) * sample_time newPW_derivatives[ pair_i] = self.parabolic_fitter.second_derivative( ) * sample_time HE[pulse_location - left_pulse_length:pulse_location + right_pulse_length] = 0.0 if np.sum(np.isfinite(newPW_data)) >= min_num_antennas: self.planewave_data.append(newPW_data) self.planewave_second_derivatives.append(newPW_derivatives) self.num_found_planewaves += 1 i += 1
processed_data_dir = processed_data_dir(timeID) output_fpath = processed_data_dir + output_folder if not isdir(output_fpath): mkdir(output_fpath) log.set(output_fpath + '/log.txt', True) log.take_stdout() for station, fpaths in raw_fpaths.items(): print(station) TBB_data = MultiFile_Dal1(fpaths) for i, ant_name in enumerate(TBB_data.get_antenna_names()): num_data_points = 0 num_zeros = 0 for block in range(initial_block, final_block): data = TBB_data.get_data(block * block_size, block_size, antenna_index=i) num_zeros += num_double_zeros(data) num_data_points += block_size print(i, ant_name, 100.0 * float(num_zeros) / num_data_points) print()
def planewave_fits(timeID, station, polarization, initial_block, number_of_blocks, pulses_per_block=10, pulse_length=50, min_amplitude=50, upsample_factor=0, min_num_antennas=4, polarization_flips="polarization_flips.txt", bad_antennas="bad_antennas.txt", additional_antenna_delays = "ant_delays.txt", max_num_planewaves=np.inf, positive_saturation = 2046, negative_saturation = -2047, saturation_post_removal_length = 50, saturation_half_hann_length = 50, verbose=True): left_pulse_length = int(pulse_length/2) right_pulse_length = pulse_length-left_pulse_length processed_data_folder = processed_data_dir(timeID) polarization_flips = read_antenna_pol_flips( processed_data_folder + '/' + polarization_flips ) bad_antennas = read_bad_antennas( processed_data_folder + '/' + bad_antennas ) additional_antenna_delays = read_antenna_delays( processed_data_folder + '/' + additional_antenna_delays ) raw_fpaths = filePaths_by_stationName(timeID) TBB_data = MultiFile_Dal1( raw_fpaths[station], polarization_flips=polarization_flips, bad_antennas=bad_antennas, additional_ant_delays=additional_antenna_delays ) ant_names = TBB_data.get_antenna_names() antenna_locations = TBB_data.get_LOFAR_centered_positions() antenna_delays = TBB_data.get_timing_callibration_delays() num_antenna_pairs = int( len( ant_names )/2 ) if num_antenna_pairs < min_num_antennas: return np.array([]), np.array([]), np.array([]) RFI_filter = window_and_filter(timeID=timeID, sname=station) block_size = RFI_filter.blocksize out_RMS = np.empty( number_of_blocks*pulses_per_block, dtype=np.double ) out_zenith = np.empty( number_of_blocks*pulses_per_block, dtype=np.double ) out_azimuth = np.empty( number_of_blocks*pulses_per_block, dtype=np.double ) N = 0 data = np.empty( (num_antenna_pairs,block_size), dtype=np.double ) for block in range(initial_block, initial_block+number_of_blocks): if N >= max_num_planewaves: break #### open and filter data for pair_i in range(num_antenna_pairs): ant_i = pair_i*2 + polarization data[pair_i,:] = TBB_data.get_data(block*block_size, block_size, antenna_index=ant_i) remove_saturation(data[pair_i,:], positive_saturation, negative_saturation, saturation_post_removal_length, saturation_half_hann_length) np.abs( RFI_filter.filter( data[pair_i,:] ), out=data[pair_i,:]) #### loop over finding planewaves i = 0 while i < pulses_per_block: if N >= max_num_planewaves: break pulse_location = 0 pulse_amplitude = 0 ## find highest peak for pair_i, HE in enumerate(data): loc = np.argmax( HE ) amp = HE[ loc ] if amp > pulse_amplitude: pulse_amplitude = amp pulse_location = loc ## check if is strong enough if pulse_amplitude < min_amplitude: break ## get fitter = locatefier() for pair_i, HE in enumerate(data): ant_i = pair_i*2 + polarization signal = np.array( HE[ pulse_location-left_pulse_length : pulse_location+right_pulse_length] ) if num_double_zeros(signal, threshold=0.1) == 0: sample_time = 5.0E-9 if upsample_factor > 1: sample_time /= upsample_factor signal = resample(signal, len(signal)*upsample_factor ) peak_finder = parabolic_fit( signal ) peak_time = peak_finder.peak_index*sample_time - antenna_delays[ant_i] fitter.add_antenna(peak_time, antenna_locations[ant_i]) HE[ pulse_location-left_pulse_length : pulse_location+right_pulse_length] = 0.0 if fitter.num_measurments() < min_num_antennas: continue fitter.prep_for_fitting() X = brute(fitter.RMS, ranges=[[0,np.pi/2],[0,np.pi*2]], Ns=20) if X[0] >= np.pi/2: X[0] = (np.pi/2)*0.99 if X[1] >= np.pi*2: X[1] = (np.pi*2)*0.99 if X[0] < 0: X[0] = 0.00000001 if X[1] < 0: X[1] = 0.00000001 ret = least_squares( fitter.time_fits, X, bounds=[[0,0],[np.pi/2,2*np.pi]], ftol=3e-16, xtol=3e-16, gtol=3e-16, x_scale='jac' ) out_RMS[N] = fitter.RMS(ret.x, 3) out_zenith[N] = ret.x[0] out_azimuth[N] = ret.x[1] N += 1 i += 1 return out_RMS[:N], out_zenith[:N], out_azimuth[:N]
def get_trace_fromLoc(self, XYZT, ant_name, width, do_remove_RFI=True, do_remove_saturation=True, positive_saturation=2046, negative_saturation=-2047, removal_length=50, half_hann_length=50): """given the location of the source in XYZT, name of the antenna, and width (in num data samples) of the desired pulse, return starting_index of the returned trace, total time calibration delay of that antenna (from TBB.get_total_delays), predicted arrival time of pulse at that antenna, and the time trace centered on the arrival time.""" station_name = SId_to_Sname[int(ant_name[:3])] station_data = self.data_file_dict[station_name] data_filter = self.data_filter_dict[station_name] file_antenna_index = station_data.get_antenna_names().index(ant_name) # ant_loc = station_data.get_LOFAR_centered_positions()[ file_antenna_index ] # ant_time_offset = station_data.get_timing_callibration_delays()[file_antenna_index] - station_data.get_nominal_sample_number()*5.0E-9 # total_time_offset = ant_time_offset + self.station_timing_calibration[station_name] # predicted_arrival_time = np.linalg.norm( XYZT[:3]-ant_loc )/v_air + XYZT[3] total_time_offset = station_data.get_total_delays()[file_antenna_index] antenna_locations = station_data.get_LOFAR_centered_positions() predicted_arrival_time = station_data.get_geometric_delays( XYZT[:3], antenna_locations=antenna_locations[ file_antenna_index:file_antenna_index + 1]) + XYZT[3] data_arrival_index = int(predicted_arrival_time / 5.0E-9 + total_time_offset / 5.0E-9) local_data_index = int(data_filter.blocksize * 0.5) data_start_sample = data_arrival_index - local_data_index input_data = station_data.get_data(data_start_sample, data_filter.blocksize, antenna_index=file_antenna_index) input_data = np.array(input_data, dtype=np.double) if do_remove_saturation: remove_saturation(input_data, positive_saturation, negative_saturation, removal_length, half_hann_length) width_before = int(width * 0.5) width_after = width - width_before if self.return_dbl_zeros: dbl_zeros = num_double_zeros( input_data[local_data_index - width_before:local_data_index + width_after]) if do_remove_RFI: data = data_filter.filter( input_data)[local_data_index - width_before:local_data_index + width_after] else: data = input_data[local_data_index - width_before:local_data_index + width_after] if self.return_dbl_zeros: return data_start_sample + local_data_index - width_before, total_time_offset, predicted_arrival_time, data, dbl_zeros else: return data_start_sample + local_data_index - width_before, total_time_offset, predicted_arrival_time, data
def FindEnergy_BothPolarizations(self, source_bounds, min_amp=None, ret_amps=False, plot=False): edge = self.edge_width + 20 # a little extra for pulse width usable_blockwidth = self.blocksize - 2 * edge bounds_corners = corners_of_bounds(source_bounds) largest_edge = 0 for C1 in bounds_corners: for C2 in bounds_corners: L = np.linalg.norm(C2 - C1) # print(L, C1, C2) if L > largest_edge: largest_edge = L new_XYZT_bounds = np.array(source_bounds) new_XYZT_bounds[3, 0] -= largest_edge / v_air new_XYZT_bounds[3, 1] += largest_edge / v_air sources, indeces_by_source = self.sources_in_bounds(new_XYZT_bounds) sources = list(sources) indeces_by_antenna = [[] for i in range(self.num_antennas)] for source_ilist in indeces_by_source: for anti, i in enumerate(source_ilist): indeces_by_antenna[anti].append(i) # source_XYZTs_in_bounds = np.array( [source.XYZT for source in sources ] ) locX = (source_bounds[0, 0] + source_bounds[0, 1]) / 2 locY = (source_bounds[1, 0] + source_bounds[1, 1]) / 2 locZ = (source_bounds[2, 0] + source_bounds[2, 1]) / 2 XYZT_start = np.array([locX, locY, locZ, source_bounds[3, 0]]) samples_left = int( (source_bounds[3, 1] - source_bounds[3, 0]) / 5.0e-9) current_sample = np.array([ self.TraceLocator.source_recieved_index(XYZT_start, ant_name) for ant_name in self.antenna_names ]) # event_samples = [ np.sort([self.TraceLocator.source_recieved_index(XYZT, ant_name ) for XYZT in source_XYZTs_in_bounds]) for ant_name in self.antenna_names ] event_samples = [np.sort(I) for I in indeces_by_antenna] current_event_index = [0] * self.num_antennas print('num total source:', len(sources)) total_energy = 0.0 imaged_energy = 0.0 amps = [] while samples_left > 0: width = usable_blockwidth if samples_left < width: width = samples_left samples_left -= width ### FIRST FOR EVENS even_ant_found = False for ant_pair_i in range(self.num_pairs): ant_i = ant_pair_i * 2 noise_power = self.antenna_noise_power[ant_i] if noise_power is None: continue start_sample = current_sample[ant_i] data = self.TBB_datafile.get_data(start_sample - edge, self.RFI_filter.blocksize, antenna_index=ant_i) DBZ_fraction = num_double_zeros( data) / self.RFI_filter.blocksize if DBZ_fraction > self.max_fraction_doubleZeros: continue even_ant_found = True data = self.RFI_filter.filter(np.array(data, dtype=np.double)) HE = np.abs(data) if plot: T = np.arange( self.RFI_filter.blocksize) + (start_sample - edge) plt.plot(T, HE) power = HE * HE N = noise_power * width * 5.0E-9 if min_amp is None: power_to_integrate = power else: power_to_integrate = np.array(power) power_to_integrate[HE < min_amp] = 0.0 # print('ARG:', np.sum(HE<min_amp)) N *= 0.0000000001 # recieved energy A = simps(power_to_integrate[edge:edge + width], dx=5.0E-9) energy = A - N if energy < 0: energy = 0.001 * N total_energy += energy # imaged energy N = 0 # used_samples = [] event_sample_numbers = event_samples[ant_i] last_sample_number = 0 for source_i in range(current_event_index[ant_i], len(event_sample_numbers)): source_sample_number = event_sample_numbers[source_i] if source_sample_number < start_sample: last_sample_number = source_i elif start_sample <= source_sample_number < start_sample + width: # used_samples.append( source_sample_number ) last_sample_number = source_i local_sample_number = source_sample_number - ( start_sample - edge) A = HE[local_sample_number - 3:local_sample_number + 3] E = np.max(A) if E >= min_amp: imaged_energy += E * E N += 1 if ret_amps: amps.append(E) else: break current_event_index[ant_i] = last_sample_number # print('E:', ant_i, 'samples:', start_sample, start_sample+width) # print(' NS:', N) # print(' used sources locs', used_samples) # if N > 0: # print(' final source loc:', event_sample_numbers[last_sample_number] ) # print( event_sample_numbers ) break if not even_ant_found: print("ERROR! too much data loss on even antenna!") quit() ### Odd antennas odd_ant_found = False for ant_pair_i in range(self.num_pairs): ant_i = ant_pair_i * 2 + 1 noise_power = self.antenna_noise_power[ant_i] if noise_power is None: continue start_sample = current_sample[ant_i] data = self.TBB_datafile.get_data(start_sample - edge, self.RFI_filter.blocksize, antenna_index=ant_i) DBZ_fraction = num_double_zeros( data) / self.RFI_filter.blocksize if DBZ_fraction > self.max_fraction_doubleZeros: continue odd_ant_found = True data = self.RFI_filter.filter(np.array(data, dtype=np.double)) HE = np.abs(data) if plot: T = np.arange( self.RFI_filter.blocksize) + (start_sample - edge) plt.plot(T, HE) # print("odd num GE:", np.sum()) power = HE * HE N = noise_power * width * 5.0E-9 if min_amp is None: power_to_integrate = power else: power_to_integrate = np.array(power) power_to_integrate[HE < min_amp] = 0.0 # print('ARG:', np.sum(HE<min_amp)) N *= 0.0000000001 # recieved energy A = simps(power_to_integrate[edge:edge + width], dx=5.0E-9) energy = A - N if energy < 0: energy = 0.001 * N total_energy += energy # imaged energy N = 0 event_sample_numbers = event_samples[ant_i] last_sample_number = 0 for source_i in range(current_event_index[ant_i], len(event_sample_numbers)): source_sample_number = event_sample_numbers[source_i] if source_sample_number < start_sample: last_sample_number = source_i elif start_sample <= source_sample_number < start_sample + width: last_sample_number = source_i local_sample_number = source_sample_number - ( start_sample - edge) A = HE[local_sample_number - 3:local_sample_number + 3] E = np.max(A) if E >= min_amp: imaged_energy += E * E N += 1 # if ret_amps : # amps.append(E) else: break current_event_index[ant_i] = last_sample_number break if not odd_ant_found: print("ERROR! too much data loss on even antenna!") quit() ## update current_sample += width if plot: print(total_energy, imaged_energy * self.pulse_width) plt.show() if ret_amps: return total_energy, imaged_energy * self.pulse_width, amps else: return total_energy, imaged_energy * self.pulse_width