Beispiel #1
0
    def parallactic_angles(self, context):
        """ Provides Montblanc with an array of parallactic angles. """

        # Time and antenna extents
        (lt, ut), (la, ua) = context.dim_extents('ntime', 'na')
        if not self.do_pa_rotation:
            return np.zeros(context.shape, dtype=context.dtype)

        def __mjd2dt(utc_timestamp):
            """
            Converts array of UTC timestamps to list of datetime objects for human readable printing
            """
            return [
                dt.datetime.utcfromtimestamp(
                    pq.quantity(t, "s").to_unix_time()) for t in utc_timestamp
            ]

        utc_times = np.unique(self._times[self.sort_ind])[lt:ut]
        dt_start = __mjd2dt([np.min(utc_times)
                             ])[0].strftime('%Y/%m/%d %H:%M:%S')
        dt_end = __mjd2dt([np.max(utc_times)])[0].strftime('%Y/%m/%d %H:%M:%S')
        log(2).print(
            "Computing parallactic angles for times between %s and %s UTC" %
            (dt_start, dt_end))
        return mbu.parallactic_angles(
            np.unique(self._times[self.sort_ind])[lt:ut], self._antpos[la:ua],
            self._phadir).reshape(context.shape).astype(context.dtype)
Beispiel #2
0
    def parallactic_angles(self, context):
        # Time extents
        (lt, ut) = context.dim_extents('ntime')
        mgr = self._manager

        return mbu.parallactic_angles(mgr._phase_dir, mgr._antenna_positions,
                                      mgr._tstep_times[lt:ut]).astype(
                                          context.dtype)
Beispiel #3
0
    def parallactic_angles(self, context):
        """ Provides Montblanc with an array of parallactic angles. """

        # Time and antenna extents
        (lt, ut), (la, ua) = context.dim_extents('ntime', 'na')

        return mbu.parallactic_angles(
            np.unique(self._times[self.sort_ind])[lt:ut], self._antpos[la:ua],
            self._phadir).reshape(context.shape).astype(context.dtype)
Beispiel #4
0
    def parallactic_angles(self, context):
        """ parallactic angle data source """
        # Time and antenna extents
        (lt, ut), (la, ua) = context.dim_extents('ntime', 'na')

        return (mbu.parallactic_angles(self._times[lt:ut],
                self._antenna_positions[la:ua], self._phase_dir)
                                            .reshape(context.shape)
                                            .astype(context.dtype))
Beispiel #5
0
 def parallactic_angles(self, context):
     self.update_nchunks(context)
     # Time extents
     (lt, ut) = context.dim_extents('ntime')
     mgr = self._manager
     pointing_errs = np.nanmean(self.pointing_errors(context), axis=2)
     return mbu.parallactic_angles(mgr._unique_time[lt:ut],
         mgr._antenna_positions,
         mgr._phase_dir,
         offsets=pointing_errs).astype(context.dtype)
Beispiel #6
0
    def load(self, solver, slvr_cfg):
        """
        Load the Measurement Set
        """
        tm = self.tables['main']
        ta = self.tables['ant']
        tf = self.tables['freq']
        tfi = self.tables['field']

        ntime, na, nbl, nbands, nchan = solver.dim_global_size(
            'ntime', 'na', 'nbl', 'nbands', 'nchan')

        # Transfer frequencies
        freqs = (tf.getcol(CHAN_FREQ).reshape(solver.frequency.shape).astype(
            solver.frequency.dtype))
        solver.transfer_frequency(np.ascontiguousarray(freqs))

        # Transfer reference frequencies
        ref_freqs = tf.getcol(REF_FREQUENCY).astype(solver.ref_frequency.dtype)
        num_chans = tf.getcol(NUM_CHAN)

        ref_freqs_per_band = np.concatenate(
            [np.repeat(rf, size) for rf, size in zip(ref_freqs, num_chans)],
            axis=0)
        solver.transfer_ref_frequency(ref_freqs_per_band)

        # If the main table has visibilities for multiple bands, then
        # there will be multiple (duplicate) UVW, ANTENNA1 and ANTENNA2 values
        # Ensure uniqueness to get a single value here
        uvw_table = pt.taql("SELECT TIME, UVW, ANTENNA1, ANTENNA2 "
                            "FROM $tm ORDERBY UNIQUE TIME, ANTENNA1, ANTENNA2")

        # Check that we're getting the correct shape...
        uvw_shape = (ntime * nbl, 3)

        # Read in UVW
        # Reshape the array and correct the axes
        ms_uvw = uvw_table.getcol(UVW)
        assert ms_uvw.shape == uvw_shape, \
            'MS UVW shape %s != expected %s' % (ms_uvw.shape, uvw_shape)

        # Create per antenna UVW coordinates.
        # u_01 = u_1 - u_0
        # u_02 = u_2 - u_0
        # ...
        # u_0N = u_N - U_0
        # where N = na - 1.

        # We choose u_0 = 0 and thus have
        # u_1 = u_01
        # u_2 = u_02
        # ...
        # u_N = u_0N

        # Then, other baseline values can be derived as
        # u_21 = u_1 - u_2
        uvw = np.empty(shape=solver.uvw.shape, dtype=solver.uvw.dtype)
        uvw[:,1:na,:] = ms_uvw.reshape(ntime, nbl, 3)[:,:na-1,:] \
            .astype(solver.ft)
        uvw[:, 0, :] = solver.ft(0)
        solver.transfer_uvw(np.ascontiguousarray(uvw))

        # Get the baseline antenna pairs and correct the axes
        ant1 = uvw_table.getcol(ANTENNA1).reshape(ntime, nbl)
        ant2 = uvw_table.getcol(ANTENNA2).reshape(ntime, nbl)

        solver.transfer_antenna1(np.ascontiguousarray(ant1))
        solver.transfer_antenna2(np.ascontiguousarray(ant2))

        # Compute parallactic angles
        time_table = pt.taql('SELECT TIME FROM $tm ORDERBY UNIQUE TIME')
        times = time_table.getcol(TIME)
        antenna_positions = ta.getcol(POSITION)
        phase_dir = tfi.getcol(PHASE_DIR)[0][0]

        # Handle negative right ascension
        if phase_dir[0] < 0:
            phase_dir[0] += 2 * np.pi

        parallactic_angles = mbu.parallactic_angles(phase_dir,
                                                    antenna_positions, times)
        solver.transfer_parallactic_angles(
            parallactic_angles.astype(solver.parallactic_angles.dtype))

        time_table.close()
        uvw_table.close()

        # Load in visibility data, if it exists.
        if tm.colnames().count(DATA) > 0:
            montblanc.log.info('{lp} Loading visibilities '
                               'into the {ovis} array'.format(
                                   lp=self.LOG_PREFIX, ovis='observed_vis'))
            # Obtain visibilities stored in the DATA column
            # This comes in as (ntime*nbl,nchan,4)
            vis_data = (tm.getcol(DATA).reshape(
                solver.observed_vis.shape).astype(solver.ct))
            solver.transfer_observed_vis(np.ascontiguousarray(vis_data))
        else:
            montblanc.log.info(
                '{lp} No visibilities found.'.format(lp=self.LOG_PREFIX))
            # Should be zeroed out by array defaults

        # Load in flag data if available
        if tm.colnames().count(FLAG) > 0:
            montblanc.log.info(
                '{lp} Loading flag data.'.format(lp=self.LOG_PREFIX))

            flag = tm.getcol(FLAG)
            flag_row = tm.getcol(FLAG_ROW)

            # Incorporate the flag_row data into the larger flag matrix
            flag = np.logical_or(flag, flag_row[:, np.newaxis, np.newaxis])

            # Reshape
            flag = flag.reshape(solver.flag.shape).astype(solver.flag.dtype)

            # Transfer, asking for contiguity
            solver.transfer_flag(np.ascontiguousarray(flag))
        else:
            montblanc.log.info(
                '{lp} No flag data found.'.format(lp=self.LOG_PREFIX))
            # Should be zeroed out by array defaults

        # Should we initialise our weights from the MS data?
        init_weights = slvr_cfg.get(Options.INIT_WEIGHTS)

        chans_per_band = nchan // nbands

        # Load in weighting data, if it exists
        if init_weights is not Options.INIT_WEIGHTS_NONE:
            if init_weights == Options.INIT_WEIGHTS_WEIGHT:
                # Obtain weighting information from WEIGHT_SPECTRUM
                # preferably, otherwise WEIGHT.
                if tm.colnames().count(WEIGHT_SPECTRUM) > 0:
                    # Try obtain the weightings from WEIGHT_SPECTRUM first.
                    montblanc.log.info(
                        '{lp} Initialising {wv} from {n}.'.format(
                            lp=self.LOG_PREFIX,
                            wv='weight_vector',
                            n=WEIGHT_SPECTRUM))

                    weight_vector = tm.getcol(WEIGHT_SPECTRUM)
                elif tm.colnames().count(WEIGHT) > 0:
                    # Otherwise we should try obtain the weightings from WEIGHT.
                    # This doesn't have per-channel weighting, so we introduce
                    # this with a broadcast
                    montblanc.log.info(
                        '{lp} Initialising {wv} from {n}.'.format(
                            lp=self.LOG_PREFIX, wv='weight_vector', n=WEIGHT))

                    weight = tm.getcol(WEIGHT)[:, np.newaxis, :]
                    weight_vector = weight * np.ones(shape=(chans_per_band, 1))
                else:
                    # We couldn't find anything, set to one
                    montblanc.log.info(
                        '{lp} No {ws} or {w} columns. '
                        'Initialising {wv} from with ones.'.format(
                            lp=self.LOG_PREFIX,
                            ws=WEIGHT_SPECTRUM,
                            w=WEIGHT,
                            wv='weight_vector'))

                    weight_vector = np.ones(shape=solver.weight_vector.shape,
                                            dtype=solver.weight_vector.dtype)
            elif init_weights == Options.INIT_WEIGHTS_SIGMA:
                # Obtain weighting information from SIGMA_SPECTRUM
                # preferably, otherwise SIGMA.
                if tm.colnames().count(SIGMA_SPECTRUM) > 0:
                    # Try obtain the weightings from WEIGHT_SPECTRUM first.
                    montblanc.log.info(
                        '{lp} Initialising {wv} from {n}.'.format(
                            lp=self.LOG_PREFIX,
                            wv='weight_vector',
                            n=SIGMA_SPECTRUM))

                    weight_vector = tm.getcol(SIGMA_SPECTRUM)
                elif tm.colnames().count(SIGMA) > 0:
                    # Otherwise we should try obtain the weightings from WEIGHT.
                    # This doesn't have per-channel weighting, so we introduce
                    # this with a broadcast
                    montblanc.log.info(
                        '{lp} Initialising {wv} from {n}.'.format(
                            lp=self.LOG_PREFIX, wv='weight_vector', n=SIGMA))

                    sigma = tm.getcol(SIGMA)[:, np.newaxis, :]
                    weight_vector = (sigma *
                                     np.ones(shape=(chans_per_band, 1)))
                else:
                    # We couldn't find anything, set to one
                    montblanc.log.info(
                        '{lp} No {ss} or {s} columns. '
                        'Initialising {wv} from with ones.'.format(
                            lp=self.LOG_PREFIX,
                            ss=SIGMA_SPECTRUM,
                            s=SIGMA,
                            wv='weight_vector'))

                    weight_vector = np.ones(shape=solver.weight_vector.shape,
                                            dtype=solver.weight_vector.dtype)
            else:
                raise Exception, 'init_weights used incorrectly!'

            assert weight_vector.shape == (ntime * nbl * nbands,
                                           chans_per_band, 4)

            weight_vector = weight_vector.reshape(ntime,nbl,nchan,4) \
                .astype(solver.ft)

            solver.transfer_weight_vector(np.ascontiguousarray(weight_vector))
Beispiel #7
0
    def load(self, solver, slvr_cfg):
        """
        Load the Measurement Set
        """
        tm = self.tables["main"]
        ta = self.tables["ant"]
        tf = self.tables["freq"]
        tfi = self.tables["field"]

        ntime, na, nbl, nchan, nbands, npol = solver.dim_global_size("ntime", "na", "nbl", "nchan", "nbands", "npol")

        self.log("Processing main table {n}.".format(n=os.path.split(self.msfile)[1]))

        msrows = tm.nrows()
        column_names = tm.colnames()

        # Determine row increments in terms of a time increment
        # This is required for calculating per antenna UVW coordinates below
        time_inc = 1
        nblbands = nbl * nbands

        while time_inc * nblbands < 5000:
            time_inc *= 2

        row_inc = time_inc * nblbands

        self.log(
            "Processing rows in increments of {ri} = "
            "{ti} timesteps x {nbl} baselines x {nb} bands.".format(ri=row_inc, ti=time_inc, nbl=nbl, nb=nbands)
        )

        # Optionally loaded data
        data_present = False
        flag_present = False

        # Set up our weight vector loading strategy
        weight_strategy = self.weight_vector_strategy(solver, slvr_cfg.get(Options.INIT_WEIGHTS), column_names)

        # Check for presence of visibilities
        if column_names.count(DATA) > 0:
            data_present = True
            self.log_load(DATA, "observed_vis")

        # Check for the presence of flags
        if column_names.count(FLAG) > 0:
            flag_present = True
            self.log_load(FLAG, "flag")

        weight_strategy.log_strategy()

        self.log_load(UVW, "uvw")
        self.log_load(ANTENNA1, "antenna1")
        self.log_load(ANTENNA2, "antenna2")

        # Iterate over the main MS rows
        for start in xrange(0, msrows, row_inc):
            nrows = min(row_inc, msrows - start)
            end = start + nrows

            self.log("Loading rows {s} -- {e}.".format(s=start, e=end))

            if data_present:
                # Dump visibility data straight into the observed visibility array
                observed_vis_view = solver.observed_vis.reshape(ntime * nbl * nbands, -1, npol)
                tm.getcolnp(DATA, observed_vis_view[start:end, :, :], startrow=start, nrow=nrows)

            if flag_present:
                # getcolnp doesn't handle solver.flag's dtype of np.uint8
                # Read into buffer and copy solver array

                # Get per polarisation flagging data
                flag_buffer = tm.getcol(FLAG, startrow=start, nrow=nrows)

                # Incorporate per visibility flagging into the buffer
                flag_row = tm.getcol(FLAG_ROW, startrow=start, nrow=nrows)
                flag_buffer = np.logical_or(flag_buffer, flag_row[:, np.newaxis, np.newaxis])

                # Take a view of the solver array and copy the buffer in
                flag_view = solver.flag.reshape(ntime * nbl * nbands, -1, npol)
                flag_view[start:end, :, :] = flag_buffer.astype(solver.flag.dtype)

            # Execute weight vector loading strategy
            weight_strategy.load(start, nrows)

        # If the main table has visibilities for multiple bands, then
        # there will be multiple (duplicate) UVW, ANTENNA1 and ANTENNA2 values
        # Ensure uniqueness to get a single value here
        uvw_table = pt.taql("SELECT TIME, UVW, ANTENNA1, ANTENNA2 " "FROM $tm ORDERBY UNIQUE TIME, ANTENNA1, ANTENNA2")
        msrows = uvw_table.nrows()
        time_inc = 1

        while time_inc * nbl < 5000:
            time_inc *= 2

        row_inc = time_inc * nbl

        for start in xrange(0, msrows, row_inc):
            nrows = min(row_inc, msrows - start)
            end = start + nrows
            t_start = start // nbl
            t_end = end // nbl

            ant_view = solver.antenna1.reshape(ntime * nbl)
            uvw_table.getcolnp(ANTENNA1, ant_view[start:end], startrow=start, nrow=nrows)

            ant_view = solver.antenna2.reshape(ntime * nbl)
            uvw_table.getcolnp(ANTENNA2, ant_view[start:end], startrow=start, nrow=nrows)

            # Read UVW coordinates into a buffer
            uvw_buffer = uvw_table.getcol(UVW, startrow=start, nrow=nrows).reshape(t_end - t_start, nbl, 3)

            # Create per antenna UVW coordinates.
            # u_01 = u_1 - u_0
            # u_02 = u_2 - u_0
            # ...
            # u_0N = u_N - U_0
            # where N = na - 1.

            # We choose u_0 = 0 and thus have
            # u_1 = u_01
            # u_2 = u_02
            # ...
            # u_N = u_0N

            # Then, other baseline values can be derived as
            # u_21 = u_1 - u_2
            solver.uvw[t_start:t_end, 1:na, :] = uvw_buffer[:, : na - 1, :]
            solver.uvw[:, 0, :] = 0

        self.log("Computing parallactic angles")
        # Compute parallactic angles
        time_table = pt.taql("SELECT TIME FROM $tm ORDERBY UNIQUE TIME")
        times = time_table.getcol(TIME)
        antenna_positions = ta.getcol(POSITION)
        phase_dir = tfi.getcol(PHASE_DIR)[0][0]

        # Handle negative right ascension
        if phase_dir[0] < 0:
            phase_dir[0] += 2 * np.pi

        solver.parallactic_angles[:] = mbu.parallactic_angles(phase_dir, antenna_positions, times)

        time_table.close()
        uvw_table.close()

        self.log("Processing frequency table {n}.".format(n=os.path.split(self.freqfile)[1]))

        # Offset of first channel in the band
        band_ch0 = 0

        # Iterate over each band
        for b, (rf, bs) in enumerate(zip(tf.getcol(REF_FREQUENCY), tf.getcol(NUM_CHAN))):
            # Transfer this band's frequencies into the solver's frequency array
            from_str = "".join([CHAN_FREQ, "[{b}][0:{bs}]".format(b=b, bs=bs)])
            to_str = "frequency[{s}:{e}]".format(s=band_ch0, e=band_ch0 + bs)
            self.log_load(from_str, to_str)
            tf.getcellslicenp(CHAN_FREQ, solver.frequency[band_ch0 : band_ch0 + bs], rownr=b, blc=(-1), trc=(-1))

            # Repeat this band's reference frequency in the solver's
            # reference frequency array
            from_str = "".join([REF_FREQUENCY, "[{b}] == {rf}".format(b=b, rf=rf)])
            to_str = "ref_frequency[{s}:{e}]".format(s=band_ch0, e=band_ch0 + bs)
            self.log_load(from_str, to_str)
            solver.ref_frequency[band_ch0 : band_ch0 + bs] = np.repeat(rf, bs)

            # Next band
            band_ch0 += bs

        self.log("Processing antenna table {n}.".format(n=os.path.split(self.freqfile)[1]))
Beispiel #8
0
    def load(self, solver, slvr_cfg):
        """
        Load the Measurement Set
        """
        tm = self.tables['main']
        ta = self.tables['ant']
        tf = self.tables['freq']
        tfi = self.tables['field']

        ntime, na, nbl, nbands, nchan = solver.dim_global_size(
            'ntime', 'na', 'nbl', 'nbands', 'nchan')

        # Transfer frequencies
        freqs = (tf.getcol(CHAN_FREQ)
            .reshape(solver.frequency.shape)
            .astype(solver.frequency.dtype))
        solver.transfer_frequency(np.ascontiguousarray(freqs))

        # Transfer reference frequencies
        ref_freqs = tf.getcol(REF_FREQUENCY).astype(solver.ref_frequency.dtype)
        num_chans = tf.getcol(NUM_CHAN)

        ref_freqs_per_band = np.concatenate(
            [np.repeat(rf, size) for rf, size
            in zip(ref_freqs, num_chans)], axis=0)
        solver.transfer_ref_frequency(ref_freqs_per_band)

        # If the main table has visibilities for multiple bands, then
        # there will be multiple (duplicate) UVW, ANTENNA1 and ANTENNA2 values
        # Ensure uniqueness to get a single value here
        uvw_table = pt.taql("SELECT TIME, UVW, ANTENNA1, ANTENNA2 "
            "FROM $tm ORDERBY UNIQUE TIME, ANTENNA1, ANTENNA2")

        # Check that we're getting the correct shape...
        uvw_shape = (ntime*nbl, 3)

        # Read in UVW
        # Reshape the array and correct the axes
        ms_uvw = uvw_table.getcol(UVW)
        assert ms_uvw.shape == uvw_shape, \
            'MS UVW shape %s != expected %s' % (ms_uvw.shape, uvw_shape)

        # Create per antenna UVW coordinates.
        # u_01 = u_1 - u_0
        # u_02 = u_2 - u_0
        # ...
        # u_0N = u_N - U_0
        # where N = na - 1.

        # We choose u_0 = 0 and thus have
        # u_1 = u_01
        # u_2 = u_02
        # ...
        # u_N = u_0N

        # Then, other baseline values can be derived as
        # u_21 = u_1 - u_2
        uvw = np.empty(shape=solver.uvw.shape, dtype=solver.uvw.dtype)
        uvw[:,1:na,:] = ms_uvw.reshape(ntime, nbl, 3)[:,:na-1,:] \
            .astype(solver.ft)
        uvw[:,0,:] = solver.ft(0)
        solver.transfer_uvw(np.ascontiguousarray(uvw))

        # Get the baseline antenna pairs and correct the axes
        ant1 = uvw_table.getcol(ANTENNA1).reshape(ntime,nbl)
        ant2 = uvw_table.getcol(ANTENNA2).reshape(ntime,nbl)

        solver.transfer_antenna1(np.ascontiguousarray(ant1))
        solver.transfer_antenna2(np.ascontiguousarray(ant2))

        # Compute parallactic angles
        time_table = pt.taql('SELECT TIME FROM $tm ORDERBY UNIQUE TIME')
        times = time_table.getcol(TIME)
        antenna_positions = ta.getcol(POSITION)
        phase_dir = tfi.getcol(PHASE_DIR)[0][0]

        # Handle negative right ascension
        if phase_dir[0] < 0:
            phase_dir[0] += 2*np.pi

        parallactic_angles = mbu.parallactic_angles(phase_dir,
            antenna_positions, times)
        solver.transfer_parallactic_angles(parallactic_angles.astype(solver.parallactic_angles.dtype))

        time_table.close()
        uvw_table.close()

        # Load in visibility data, if it exists.
        if tm.colnames().count(DATA) > 0:
            montblanc.log.info('{lp} Loading visibilities '
                'into the {ovis} array'.format(
                    lp=self.LOG_PREFIX, ovis='observed_vis'))
            # Obtain visibilities stored in the DATA column
            # This comes in as (ntime*nbl,nchan,4)
            vis_data = (tm.getcol(DATA).reshape(solver.observed_vis.shape)
                .astype(solver.ct))
            solver.transfer_observed_vis(np.ascontiguousarray(vis_data))
        else:
            montblanc.log.info('{lp} No visibilities found.'
                .format(lp=self.LOG_PREFIX))
            # Should be zeroed out by array defaults

        # Load in flag data if available
        if tm.colnames().count(FLAG) > 0:
            montblanc.log.info('{lp} Loading flag data.'.format(
                    lp=self.LOG_PREFIX))

            flag = tm.getcol(FLAG)
            flag_row = tm.getcol(FLAG_ROW)

            # Incorporate the flag_row data into the larger flag matrix
            flag = np.logical_or(flag, flag_row[:,np.newaxis,np.newaxis])

            # Reshape
            flag = flag.reshape(solver.flag.shape).astype(solver.flag.dtype)

            # Transfer, asking for contiguity
            solver.transfer_flag(np.ascontiguousarray(flag))
        else:
            montblanc.log.info('{lp} No flag data found.'
                .format(lp=self.LOG_PREFIX))
            # Should be zeroed out by array defaults

        # Should we initialise our weights from the MS data?
        init_weights = slvr_cfg.get(Options.INIT_WEIGHTS)
 
        chans_per_band = nchan // nbands

        # Load in weighting data, if it exists
        if init_weights is not Options.INIT_WEIGHTS_NONE:
            if init_weights == Options.INIT_WEIGHTS_WEIGHT:
            # Obtain weighting information from WEIGHT_SPECTRUM
            # preferably, otherwise WEIGHT.
                if tm.colnames().count(WEIGHT_SPECTRUM) > 0:
                    # Try obtain the weightings from WEIGHT_SPECTRUM first.
                    montblanc.log.info('{lp} Initialising {wv} from {n}.'
                        .format(lp=self.LOG_PREFIX, wv='weight_vector',
                            n=WEIGHT_SPECTRUM))

                    weight_vector = tm.getcol(WEIGHT_SPECTRUM)
                elif tm.colnames().count(WEIGHT) > 0:
                    # Otherwise we should try obtain the weightings from WEIGHT.
                    # This doesn't have per-channel weighting, so we introduce
                    # this with a broadcast
                    montblanc.log.info('{lp} Initialising {wv} from {n}.'
                        .format(lp=self.LOG_PREFIX, wv='weight_vector',
                            n=WEIGHT))

                    weight = tm.getcol(WEIGHT)[:,np.newaxis,:]
                    weight_vector = weight*np.ones(shape=(chans_per_band,1))
                else:
                    # We couldn't find anything, set to one
                    montblanc.log.info('{lp} No {ws} or {w} columns. '
                        'Initialising {wv} from with ones.'
                        .format(lp=self.LOG_PREFIX, ws=WEIGHT_SPECTRUM,
                            w=WEIGHT, wv='weight_vector'))

                    weight_vector = np.ones(
                        shape=solver.weight_vector.shape,
                        dtype=solver.weight_vector.dtype)
            elif init_weights == Options.INIT_WEIGHTS_SIGMA:
                # Obtain weighting information from SIGMA_SPECTRUM
                # preferably, otherwise SIGMA.
                if tm.colnames().count(SIGMA_SPECTRUM) > 0:
                    # Try obtain the weightings from WEIGHT_SPECTRUM first.
                    montblanc.log.info('{lp} Initialising {wv} from {n}.'
                        .format(lp=self.LOG_PREFIX, wv='weight_vector',
                            n=SIGMA_SPECTRUM))

                    weight_vector = tm.getcol(SIGMA_SPECTRUM)
                elif tm.colnames().count(SIGMA) > 0:
                    # Otherwise we should try obtain the weightings from WEIGHT.
                    # This doesn't have per-channel weighting, so we introduce
                    # this with a broadcast
                    montblanc.log.info('{lp} Initialising {wv} from {n}.'
                        .format(lp=self.LOG_PREFIX, wv='weight_vector',
                            n=SIGMA))

                    sigma = tm.getcol(SIGMA)[:,np.newaxis,:]
                    weight_vector = (sigma*np.ones(shape=(chans_per_band,1)))
                else:
                    # We couldn't find anything, set to one
                    montblanc.log.info('{lp} No {ss} or {s} columns. '
                        'Initialising {wv} from with ones.'
                        .format(lp=self.LOG_PREFIX, ss=SIGMA_SPECTRUM,
                            s=SIGMA, wv='weight_vector'))

                    weight_vector = np.ones(shape=solver.weight_vector.shape,
                        dtype=solver.weight_vector.dtype)
            else:
                raise Exception, 'init_weights used incorrectly!'

            assert weight_vector.shape == (ntime*nbl*nbands, chans_per_band, 4)

            weight_vector = weight_vector.reshape(ntime,nbl,nchan,4) \
                .astype(solver.ft)

            solver.transfer_weight_vector(np.ascontiguousarray(weight_vector))
Beispiel #9
0
    def load(self, solver, slvr_cfg):
        """
        Load the Measurement Set
        """
        tm = self.tables['main']
        ta = self.tables['ant']
        tf = self.tables['freq']
        tfi = self.tables['field']

        ntime, na, nbl, nchan, nbands, npol = solver.dim_global_size(
            'ntime', 'na', 'nbl', 'nchan', 'nbands', 'npol')

        self.log("Processing main table {n}.".format(
            n=os.path.split(self.msfile)[1]))

        msrows = tm.nrows()
        column_names = tm.colnames()

        # Determine row increments in terms of a time increment
        # This is required for calculating per antenna UVW coordinates below
        time_inc = 1
        nblbands = nbl * nbands

        while time_inc * nblbands < 5000:
            time_inc *= 2

        row_inc = time_inc * nblbands

        self.log('Processing rows in increments of {ri} = '
                 '{ti} timesteps x {nbl} baselines x {nb} bands.'.format(
                     ri=row_inc, ti=time_inc, nbl=nbl, nb=nbands))

        # Optionally loaded data
        data_present = False
        flag_present = False

        # Set up our weight vector loading strategy
        weight_strategy = self.weight_vector_strategy(
            solver, slvr_cfg.get(Options.INIT_WEIGHTS), column_names)

        # Check for presence of visibilities
        if column_names.count(DATA) > 0:
            data_present = True
            self.log_load(DATA, 'observed_vis')

        # Check for the presence of flags
        if column_names.count(FLAG) > 0:
            flag_present = True
            self.log_load(FLAG, 'flag')

        weight_strategy.log_strategy()

        self.log_load(UVW, 'uvw')
        self.log_load(ANTENNA1, 'antenna1')
        self.log_load(ANTENNA2, 'antenna2')

        # Iterate over the main MS rows
        for start in xrange(0, msrows, row_inc):
            nrows = min(row_inc, msrows - start)
            end = start + nrows

            self.log('Loading rows {s} -- {e}.'.format(s=start, e=end))

            if data_present:
                # Dump visibility data straight into the observed visibility array
                observed_vis_view = solver.observed_vis.reshape(
                    ntime * nbl * nbands, -1, npol)
                tm.getcolnp(DATA,
                            observed_vis_view[start:end, :, :],
                            startrow=start,
                            nrow=nrows)

            if flag_present:
                # getcolnp doesn't handle solver.flag's dtype of np.uint8
                # Read into buffer and copy solver array

                # Get per polarisation flagging data
                flag_buffer = tm.getcol(FLAG, startrow=start, nrow=nrows)

                # Incorporate per visibility flagging into the buffer
                flag_row = tm.getcol(FLAG_ROW, startrow=start, nrow=nrows)
                flag_buffer = np.logical_or(
                    flag_buffer, flag_row[:, np.newaxis, np.newaxis])

                # Take a view of the solver array and copy the buffer in
                flag_view = solver.flag.reshape(ntime * nbl * nbands, -1, npol)
                flag_view[start:end, :, :] = flag_buffer.astype(
                    solver.flag.dtype)

            # Execute weight vector loading strategy
            weight_strategy.load(start, nrows)

        # If the main table has visibilities for multiple bands, then
        # there will be multiple (duplicate) UVW, ANTENNA1 and ANTENNA2 values
        # Ensure uniqueness to get a single value here
        uvw_table = pt.taql("SELECT TIME, UVW, ANTENNA1, ANTENNA2 "
                            "FROM $tm ORDERBY UNIQUE TIME, ANTENNA1, ANTENNA2")
        msrows = uvw_table.nrows()
        time_inc = 1

        while time_inc * nbl < 5000:
            time_inc *= 2

        row_inc = time_inc * nbl

        for start in xrange(0, msrows, row_inc):
            nrows = min(row_inc, msrows - start)
            end = start + nrows
            t_start = start // nbl
            t_end = end // nbl

            ant_view = solver.antenna1.reshape(ntime * nbl)
            uvw_table.getcolnp(ANTENNA1,
                               ant_view[start:end],
                               startrow=start,
                               nrow=nrows)

            ant_view = solver.antenna2.reshape(ntime * nbl)
            uvw_table.getcolnp(ANTENNA2,
                               ant_view[start:end],
                               startrow=start,
                               nrow=nrows)

            # Read UVW coordinates into a buffer
            uvw_buffer = (uvw_table.getcol(UVW, startrow=start,
                                           nrow=nrows).reshape(
                                               t_end - t_start, nbl, 3))

            # Create per antenna UVW coordinates.
            # u_01 = u_1 - u_0
            # u_02 = u_2 - u_0
            # ...
            # u_0N = u_N - U_0
            # where N = na - 1.

            # We choose u_0 = 0 and thus have
            # u_1 = u_01
            # u_2 = u_02
            # ...
            # u_N = u_0N

            # Then, other baseline values can be derived as
            # u_21 = u_1 - u_2
            solver.uvw[t_start:t_end, 1:na, :] = uvw_buffer[:, :na - 1, :]
            solver.uvw[:, 0, :] = 0

        self.log('Computing parallactic angles')
        # Compute parallactic angles
        time_table = pt.taql('SELECT TIME FROM $tm ORDERBY UNIQUE TIME')
        times = time_table.getcol(TIME)
        antenna_positions = ta.getcol(POSITION)
        phase_dir = tfi.getcol(PHASE_DIR)[0][0]

        # Handle negative right ascension
        if phase_dir[0] < 0:
            phase_dir[0] += 2 * np.pi

        solver.parallactic_angles[:] = mbu.parallactic_angles(
            phase_dir, antenna_positions, times)

        time_table.close()
        uvw_table.close()

        self.log("Processing frequency table {n}.".format(
            n=os.path.split(self.freqfile)[1]))

        # Offset of first channel in the band
        band_ch0 = 0

        # Iterate over each band
        for b, (rf, bs) in enumerate(
                zip(tf.getcol(REF_FREQUENCY), tf.getcol(NUM_CHAN))):
            # Transfer this band's frequencies into the solver's frequency array
            from_str = ''.join([CHAN_FREQ, '[{b}][0:{bs}]'.format(b=b, bs=bs)])
            to_str = 'frequency[{s}:{e}]'.format(s=band_ch0, e=band_ch0 + bs)
            self.log_load(from_str, to_str)
            tf.getcellslicenp(CHAN_FREQ,
                              solver.frequency[band_ch0:band_ch0 + bs],
                              rownr=b,
                              blc=(-1),
                              trc=(-1))

            # Repeat this band's reference frequency in the solver's
            # reference frequency array
            from_str = ''.join(
                [REF_FREQUENCY, '[{b}] == {rf}'.format(b=b, rf=rf)])
            to_str = 'ref_frequency[{s}:{e}]'.format(s=band_ch0,
                                                     e=band_ch0 + bs)
            self.log_load(from_str, to_str)
            solver.ref_frequency[band_ch0:band_ch0 + bs] = np.repeat(rf, bs)

            # Next band
            band_ch0 += bs

        self.log("Processing antenna table {n}.".format(
            n=os.path.split(self.freqfile)[1]))