def get_mean_powers(r, c): ''' Get autocorrelation powers from redis and scale them appropriately. ''' # find indices of correlation matrices representing autos corr_conf = c['Configuration']['correlator']['hardcoded'] bl_order = sim.get_bl_order(corr_conf['n_ants']) n_bls = len(bl_order) auto_indices = np.zeros(corr_conf['n_ants']) for bn, bl in enumerate(bl_order): if bl[0] == bl[1]: auto_indices[bl[0]] = bn # get current data and store as numpy array data, ts = r.hmget('RECEIVER:xeng_raw0', ['val', 'timestamp']) n_chans = c['FEngine']['n_chans'] ts = float(ts) data_c = np.fromstring(data, dtype=np.int32).reshape( [corr_conf['n_bands'] * n_chans, n_bls, 1, 2]) # carve out the autos autos = np.zeros([corr_conf['n_ants'], corr_conf['n_bands'] * n_chans], dtype=np.float32) for an, auto_index in enumerate(auto_indices): autos[an] = data_c[:, auto_index, 0, 1] / c['XEngine'][ 'acc_len'] / corr_conf[ 'window_len'] #This is scaled relative to a correlator input between +/-7 return autos
def parse_config_file(self): """ Parse the instance's config file, saving some parameters as attributes for easy access. This method is automatically called on object instantiation. """ #some common params self.n_ants = self.config['Configuration']['correlator']['hardcoded']['n_ants'] self.n_bands = self.config['Configuration']['correlator']['hardcoded']['n_bands'] self.n_inputs= self.config['Configuration']['correlator']['hardcoded']['inputs_per_board'] self.n_chans = self.config['Configuration']['correlator']['hardcoded']['n_chans'] self.n_pols = self.config['Configuration']['correlator']['hardcoded']['n_pols'] self.output_format = self.config['Configuration']['correlator']['hardcoded']['output_format'] self.data_path = self.config['Configuration']['correlator']['runtime']['data_path'] self.adc_clk = float(self.config['FEngine']['adc_clk'] * 1e6) self.lo_freq = self.config['FEngine']['mix_freq'] self.f_n_chans = self.config['FEngine']['n_chans'] self.x_acc_len = self.config['XEngine']['acc_len'] self.n_bls = (self.n_ants * (self.n_ants + 1))/2 self.bl_order = sim.get_bl_order(self.n_ants) self.roaches = set([node['host'] for node in self.config['FEngine']['nodes']+self.config['XEngine']['nodes']]) #shortcuts to sections self.c_testing = self.config['Configuration']['correlator']['runtime']['testing'] self.c_correlator = self.config['Configuration']['correlator']['runtime'] self.c_correlator_hard = self.config['Configuration']['correlator']['hardcoded'] self.c_global = self.config['Configuration'] self.c_antennas = self.config['Antennas'] self.c_array = self.config['Array'] # other useful vars self.window_len = self.c_correlator_hard['window_len'] self.sync_clocks= self.c_correlator_hard['sync_period']*16 #measured in ADC clocks self.sync_period = self.sync_clocks / self.adc_clk self.acc_samples = self.x_acc_len * self.c_correlator_hard['window_len'] * self.f_n_chans * 2 self.acc_time = self.acc_samples / self.adc_clk # some debugging / info self._logger.info("ROACHes are %r"%self.roaches) # ant array shortcuts self.array_lon = self.c_array['lon'] self.array_lat = self.c_array['lat'] self.ant_locs = [[0., 0., 0.] for a in self.c_antennas] for ant in self.c_antennas: self.ant_locs[ant['ant']] = ant['loc'] #this way the ants don't have to be in order in the config file self.array = antenna_functions.AntArray((self.array_lat, self.array_lon), self.ant_locs)
def get_expected_output(n_ants=16): ''' Generate the correlation matrix based on the test vectors specified in firmware. ''' bl_order = sim.get_bl_order(n_ants) # Get a list of antenna pairs n_bls = len(bl_order) oput = np.zeros([4096, n_bls, 4], dtype=np.complex128) # n_chans * n_baselines * n_stokes iput = np.zeros( [n_ants, 2, 4096], dtype=np.complex128) # n_antennas * n_polarizations * n_chans # First generate the inputs # y pol first. counter = np.arange(4096) im = counter & 0xf re = (counter >> 4) & 0xf # convert to 2's complement binary re[re > 7] -= 16 im[im > 7] -= 16 # vectors are the same for all antennas for ant in range(n_ants): iput[ant, 1, :] = re + 1j * im # xpol im = (counter >> 8) & 0xf # convert to 2's complement binary im[im > 7] -= 16 # xpol -- odd numbered antennas (i.e., second input of each ROACH) have 1 in real part for ant in range(n_ants): if ant % 2 == 0: iput[ant, 0, :] = 0 + 1j * im elif ant % 2 == 1: iput[ant, 0, :] = 1 + 1j * im # compute correlation matrix for bn, bl in enumerate(bl_order): oput[:, bn, 0] = iput[bl[0], 0] * np.conj(iput[bl[1], 0]) #XX oput[:, bn, 1] = iput[bl[0], 1] * np.conj(iput[bl[1], 1]) #YY oput[:, bn, 2] = iput[bl[0], 0] * np.conj(iput[bl[1], 1]) #XY oput[:, bn, 3] = iput[bl[0], 1] * np.conj(iput[bl[1], 0]) #YX return oput
def get_expected_output(n_ants=16): ''' Generate the correlation matrix based on the test vectors specified in firmware. ''' bl_order = sim.get_bl_order(n_ants) # Get a list of antenna pairs n_bls = len(bl_order) oput = np.zeros([4096, n_bls, 4], dtype=np.complex128) # n_chans * n_baselines * n_stokes iput = np.zeros([n_ants, 2, 4096], dtype=np.complex128) # n_antennas * n_polarizations * n_chans # First generate the inputs # y pol first. counter = np.arange(4096) im = counter&0xf re = (counter>>4)&0xf # convert to 2's complement binary re[re>7] -= 16 im[im>7] -= 16 # vectors are the same for all antennas for ant in range(n_ants): iput[ant, 1, :] = re + 1j*im # xpol im = (counter>>8) & 0xf # convert to 2's complement binary im[im>7] -= 16 # xpol -- odd numbered antennas (i.e., second input of each ROACH) have 1 in real part for ant in range(n_ants): if ant % 2 == 0: iput[ant, 0, :] = 0 + 1j*im elif ant % 2 == 1: iput[ant, 0, :] = 1 + 1j*im # compute correlation matrix for bn,bl in enumerate(bl_order): oput[:, bn, 0] = iput[bl[0],0] * np.conj(iput[bl[1],0]) #XX oput[:, bn, 1] = iput[bl[0],1] * np.conj(iput[bl[1],1]) #YY oput[:, bn, 2] = iput[bl[0],0] * np.conj(iput[bl[1],1]) #XY oput[:, bn, 3] = iput[bl[0],1] * np.conj(iput[bl[1],0]) #YX return oput
def get_mean_powers(r, c): ''' Get autocorrelation powers from redis and scale them appropriately. ''' # find indices of correlation matrices representing autos corr_conf = c['Configuration']['correlator']['hardcoded'] bl_order = sim.get_bl_order(corr_conf['n_ants']) n_bls = len(bl_order) auto_indices = np.zeros(corr_conf['n_ants']) for bn, bl in enumerate(bl_order): if bl[0] == bl[1]: auto_indices[bl[0]] = bn # get current data and store as numpy array data, ts = r.hmget('RECEIVER:xeng_raw0', ['val', 'timestamp']) n_chans = c['FEngine']['n_chans'] ts = float(ts) data_c = np.fromstring(data, dtype=np.int32).reshape([corr_conf['n_bands'] * n_chans, n_bls, 1, 2]) # carve out the autos autos = np.zeros([corr_conf['n_ants'], corr_conf['n_bands'] * n_chans], dtype=np.float32) for an, auto_index in enumerate(auto_indices): autos[an] = data_c[:, auto_index, 0, 1] / c['XEngine']['acc_len'] / corr_conf['window_len'] #This is scaled relative to a correlator input between +/-7 return autos
def parse_config_file(self): """ Parse the instance's config file, saving some parameters as attributes for easy access. This method is automatically called on object instantiation. """ #some common params self.n_ants = self.config['Configuration']['correlator']['hardcoded'][ 'n_ants'] self.n_bands = self.config['Configuration']['correlator']['hardcoded'][ 'n_bands'] self.n_inputs = self.config['Configuration']['correlator'][ 'hardcoded']['inputs_per_board'] self.n_chans = self.config['Configuration']['correlator']['hardcoded'][ 'n_chans'] self.n_pols = self.config['Configuration']['correlator']['hardcoded'][ 'n_pols'] self.output_format = self.config['Configuration']['correlator'][ 'hardcoded']['output_format'] self.data_path = self.config['Configuration']['correlator']['runtime'][ 'data_path'] self.adc_clk = float(self.config['FEngine']['adc_clk'] * 1e6) self.lo_freq = self.config['FEngine']['mix_freq'] self.f_n_chans = self.config['FEngine']['n_chans'] self.x_acc_len = self.config['XEngine']['acc_len'] self.n_bls = (self.n_ants * (self.n_ants + 1)) / 2 self.bl_order = sim.get_bl_order(self.n_ants) self.roaches = set([ node['host'] for node in self.config['FEngine']['nodes'] + self.config['XEngine']['nodes'] ]) #shortcuts to sections self.c_testing = self.config['Configuration']['correlator']['runtime'][ 'testing'] self.c_correlator = self.config['Configuration']['correlator'][ 'runtime'] self.c_correlator_hard = self.config['Configuration']['correlator'][ 'hardcoded'] self.c_global = self.config['Configuration'] self.c_antennas = self.config['Antennas'] self.c_array = self.config['Array'] # other useful vars self.window_len = self.c_correlator_hard['window_len'] self.sync_clocks = self.c_correlator_hard[ 'sync_period'] * 16 #measured in ADC clocks self.sync_period = self.sync_clocks / self.adc_clk self.acc_samples = self.x_acc_len * self.c_correlator_hard[ 'window_len'] * self.f_n_chans * 2 self.acc_time = self.acc_samples / self.adc_clk # some debugging / info self._logger.info("ROACHes are %r" % self.roaches) # ant array shortcuts self.array_lon = self.c_array['lon'] self.array_lat = self.c_array['lat'] self.ant_locs = [[0., 0., 0.] for a in self.c_antennas] for ant in self.c_antennas: self.ant_locs[ant['ant']] = ant[ 'loc'] #this way the ants don't have to be in order in the config file self.array = antenna_functions.AntArray( (self.array_lat, self.array_lon), self.ant_locs)
"-p", "--npackets", dest="npackets", type="int", default=100000, help="Maximum number of packets to read (per pcap files). Default:100000") (opts, args) = parser.parse_args() if opts.reorder: #rel_order[x] = y -> the channel labelled x really y # i.e. real_channel = rel_order[channel_label] rel_order = get_rel_order() else: rel_order = range(4096) bl_order = sim.get_bl_order(16) limit = opts.npackets hdr_len = 42 + 88 # we only capture 1000 bytes per packet -- # header is 42+88 bytes => 870 bytes data # => 108 complex values # => 27 dual-pol baselines (+ some leftover) n_bls = 27 #n_bls = 16*17/2 * 4 n_windows = 100 packet_cnts = np.zeros(n_windows) time_slots = np.ones(n_windows) * -1 spectra = np.ones([n_windows, 4096, n_bls * 4], dtype=complex) * 2**31
from optparse import OptionParser parser = OptionParser(usage='%prog [options] pcap_file1 pcap_file2 ...') parser.add_option("-r", "--reorder", dest="reorder", action="store_true", default=False, help="Use this flag to reorder frequency channels based on a known firmware issue. This issue was fixed in firmware version eovsa_corr_2016_Feb_20_1600.bof. This option should be unnecessary for pcap files generated with this, or later, firmware.") parser.add_option("-p", "--npackets", dest="npackets", type="int", default=100000, help="Maximum number of packets to read (per pcap files). Default:100000") (opts, args) = parser.parse_args() if opts.reorder: #rel_order[x] = y -> the channel labelled x really y # i.e. real_channel = rel_order[channel_label] rel_order = get_rel_order() else: rel_order = range(4096) bl_order = sim.get_bl_order(16) limit = opts.npackets hdr_len = 42+88 # we only capture 1000 bytes per packet -- # header is 42+88 bytes => 870 bytes data # => 108 complex values # => 27 dual-pol baselines (+ some leftover) n_bls = 27 #n_bls = 16*17/2 * 4 n_windows = 100 packet_cnts = np.zeros(n_windows) time_slots = np.ones(n_windows) * -1 spectra = np.ones([n_windows, 4096, n_bls*4], dtype=complex)*2**31