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)
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)
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)
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))
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)
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))
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]))
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))
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]))