def _sky_frequencies(spectra, df): # The spectra array dimensions are now: # sigref, windows, polarizations, channels nsig, nwin, npol, nchan = spectra.shape # ---------------------- calculate frequencies lo1, offset, iffile_info = filedata.info_from_files(df.project_id, df.scan_number) # NB 'BANK_A' is a column name that could hold ANY bank value # and not necessarily 'A' # The port number is (I think) a unique identifier for polarization # but it shouldn't matter because frequencies should be the same # for both polarizations. So, I just grab the first. port=1. sampler_table = _sampler_table(df) port, bank = 1, sampler_table['BANK_A'][0] _, sff_sb, sff_multi, sff_offset = iffile_info[(port, bank)] # The CRVAL1 and CDELT1 value differ with subband, so collect # all of them for later reference to determine frequencies. crval1 = [] cdelt1 = [] for sb in df.subband: mask = sampler_table['SUBBAND'] == sb crval1.append(sampler_table[mask]['CRVAL1'][0]) cdelt1.append(sampler_table[mask]['CDELT1'][0]) display_sky_frequencies = [] for count in range(nwin * npol): ifval = np.array(range(1, df.number_channels+1)) # Below I use df.number_channels/2 instead of df.crpix1 because crpix1 # is currently holding the incorrect value of 0. # That is a bug in the protobuf Data key sent in the stream from # the manager. ifval = crval1[count] + cdelt1[count] * (ifval - df.number_channels/2) skyfreq = sff_sb * ifval + sff_multi * lo1 + sff_offset # only return NCHANS numbers of frequencies for each subband reduced_skyfreqs = (skyfreq[::df.number_channels/cfg.NCHANS]/1e9).tolist() display_sky_frequencies.extend(reduced_skyfreqs + offset[0]/1e9) # 0 represents the frequency signal if nsig > 1: # If we have a 2nd switching state, create another frequency vector with the shift. # offset[1] is the offset for the reference frequency. display_sky_frequencies.extend([_ + offset[1]/1e9 for _ in display_sky_frequencies]) return display_sky_frequencies
def _handle_data(sock, key): """Do something with the response from a VEGAS bank. Args: sock(socket): A bank socket object. key(str): Either state or data key. Returns: If it's data, a list containing project, scan number, integration number and a spectrum. If it's state info, we get the state string. If there is an error, None. """ rl = sock.recv_multipart() el = len(rl) if el == 1: # Got an error if rl[0] == "E_NOKEY": logging.info("No key/value pair found: {}".format(key)) return None elif el > 1: # first element is the key # the following elements are the values if not rl[0].endswith("Data"): # This should only happen when we get state info. df = PBDataField() df.ParseFromString(rl[1]) return df else: # We should only be here if we got a data response. df = pbVegasData() df.ParseFromString(rl[1]) ff = array.array('f') # 'f' is typecode for C float ff.fromstring(df.data_blob) n_sig_states = len(set(df.sig_ref_state)) n_cal_states = len(set(df.cal_state)) n_subbands = len(set(df.subband)) logging.debug("Project ID is: {}".format(df.project_id)) logging.debug("Scan number is: {}".format(df.scan_number)) logging.debug("Polarization is: {}".format(df.polarization)) logging.debug("Number of sub-bands is: {}".format(n_subbands)) logging.debug("Number of sig switching states is: {}".format(n_sig_states)) logging.debug("Number of cal states is: {}".format(n_cal_states)) logging.debug("Number of polarizations: {}".format(df.number_stokes)) problem = False if n_subbands < 1: problem = True if n_sig_states < 1: problem = True if n_cal_states < 1: problem = True if problem: return None n_chans, n_samplers, n_states = df.data_dims full_res_spectra = np.array(ff) logging.debug('full_res_spectra {}'.format(full_res_spectra[:10])) # change the dimensions of the spectra to be # STATES (sigref, cal), SAMPLERS (windows, polarizations), CHANNELS full_res_spectra = full_res_spectra.reshape(df.data_dims[::-1]) # estimate the number of polarizations used to grab the first # of each subband n_pols = (n_samplers/n_subbands) logging.debug('polarization estimate: {}'.format(n_pols)) # Reshape the spectra into these dimensions: # sigref, cals, windows, polarizations, channels full_res_spectra = full_res_spectra.reshape((n_sig_states, n_cal_states, n_subbands, n_pols, n_chans)) # If we have more than two polarizations, only keep the first two. full_res_spectra = full_res_spectra[:,:,:,:2,:] if n_pols > 2: n_pols = 2 # average the calon/caloff pairs # this reduces the state dimension by 1/2 # i.e. 2,14,1024 becomes 1,14,1024 or 14,1024 # TODO this assumes only cal and sig switching # if other switching is added in the future, it could # be an issue. n_states should == 2. myspectra = np.mean(full_res_spectra, axis=1) if n_sig_states == 2: logging.debug('SIG SWITCHING') # The spectra array dimensions are now: # sigref, windows, polarizations, channels files_available = True try: sky_freqs = _sky_frequencies(myspectra, df) except: logging.debug('Frequency information unavailable. Substituting with dummy freq. data.') files_available = False sky_freqs = _make_dummy_frequencies(n_sig_states, n_subbands, n_pols) # Reduce the number of channels in all spectra to make them easier to display. # This is also where we remove the center spike. sampled_spectra = _trim_spectra(myspectra) # Join the frequencies to the spectra. spectrum = np.array(zip(sky_freqs, sampled_spectra)) # The 2 in the following line accounts for the data and frequency axes. spectrum = spectrum.reshape((n_sig_states, n_subbands, n_pols, cfg.NCHANS, 2)).tolist() # sort each spectrum by frequency for sigidx in range(n_sig_states): for winidx in range(n_subbands): for polidx in range(n_pols): spectrum[sigidx][winidx][polidx] = sorted(spectrum[sigidx][winidx][polidx]) project = str(df.project_id) scan = int(df.scan_number) integration = int(df.integration) # collect the polarization names to display, e.g. "L" or "R" sampler_table = _sampler_table(df) polname = [] if files_available: _, _, iffile_info = filedata.info_from_files(project, scan) for pnum in range(1, n_pols+1): port, bank = pnum, sampler_table['BANK_A'][0] pname, _, _, _ = iffile_info[(pnum, bank)] polname.append(pname*2) # double the string, e.g. 'R' -> 'RR' else: for pnum in range(1, n_pols+1): polname.append(str(pnum)) response = (project, scan, integration, polname, np.array(spectrum)) return response else: return None