Esempio n. 1
0
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
Esempio n. 2
0
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