def uvw(self, context): """ Provides Montblanc with an array of uvw coordinates. """ # Figure out our extents in the time dimension and our global antenna and baseline sizes. (t_low, t_high) = context.dim_extents('ntime') # Figure out chunks in time (may be repetitious, but needed an easy fix). _, counts = np.unique(self._times[:self._nrows], return_counts=True) chunks = np.asarray(counts) # Compute per antenna uvw coordinates. Data must be ordered by time. # Per antenna uvw coordinates fail on data where time!=time_centroid. ant_uvw = mbu.antenna_uvw(self._uvwco[:self._nrows], self._antea[:self._nrows], self._anteb[:self._nrows], chunks, self._nants, check_missing=False, check_decomposition=False, max_err=100) return ant_uvw[t_low:t_high, ...].astype(context.dtype)
def test_uvw_disjoint(self): # Three initially disjoint baselines here, but the last baseline [2, 9] # connects the first and the last # Set 1: 0, 1, 2, 3 # Set 2: 4, 5, 6, 7, 8 # Set 3: 8, 10, 11, 12 # Connection between Set 1 and Set 3 is the last baseline [2, 9] ant1 = np.array([1, 2, 3, 4, 5, 5, 7, 9, 10, 11, 2]) ant2 = np.array([2, 2, 0, 5, 5, 6, 8, 10, 11, 12, 9]) na = np.unique(np.concatenate([ant1, ant2])).size ntime = 1 # Create random per-antenna UVW coordinates. # zeroing the first antenna ant_uvw = np.random.random(size=(ntime, na, 3)).astype(np.float64) ant_uvw[0, 0, :] = 0 time_chunks = np.array([ant1.size], dtype=ant1.dtype) # Compute per-baseline UVW coordinates. bl_uvw = (ant_uvw[:, ant1, :] - ant_uvw[:, ant2, :]).reshape(-1, 3) # Now recover the per-antenna and per-baseline UVW coordinates. rant_uvw = antenna_uvw(bl_uvw, ant1, ant2, time_chunks, nr_of_antenna=na, check_decomposition=True)
def test_uvw_antenna_missing_bl_impl(self): na = 17 removed_ants_per_time = ([0, 1, 7], [2, 10, 15, 9], [3, 6, 9, 12]) # For both auto correlations and without them for auto_cor in (0, 1): def _create_ant_arrays(): for remove_ants in removed_ants_per_time: # Compute default antenna pairs ant1, ant2 = np.triu_indices(na, auto_cor) # Shuffle the antenna indices idx = np.arange(ant1.size) np.random.shuffle(idx) ant1 = ant1[idx] ant2 = ant2[idx] # Remove any baselines containing flagged antenna reduce_tuple = tuple(a != ra for a in (ant1, ant2) for ra in remove_ants) keep = np.logical_and.reduce(reduce_tuple) ant1 = ant1[keep] ant2 = ant2[keep] valid_ants = list(set(range(na)).difference(remove_ants)) yield valid_ants, remove_ants, ant1, ant2 tup = zip(*list(_create_ant_arrays())) valid_ants, remove_ants, ant1, ant2 = tup bl_uvw = [] # Create per-baseline UVW coordinates for each time chunk it = enumerate(zip(valid_ants, remove_ants, ant1, ant2)) for t, (va, ra, a1, a2) in it: # Create random per-antenna UVW coordinates. # zeroing the first valid antenna ant_uvw = np.random.random(size=(na, 3)).astype(np.float64) ant_uvw[va[0], :] = 0 # Create per-baseline UVW coordinates for this time chunk bl_uvw.append(ant_uvw[a1, :] - ant_uvw[a2, :]) # Produced concatenated antenna and baseline uvw arrays time_chunks = np.array([a.size for a in ant1], dtype=ant1[0].dtype) cant1 = np.concatenate(ant1) cant2 = np.concatenate(ant2) cbl_uvw = np.concatenate(bl_uvw) # Now recover the per-antenna and per-baseline UVW coordinates # for the ntime chunks rant_uvw = antenna_uvw(cbl_uvw, cant1, cant2, time_chunks, nr_of_antenna=na, check_decomposition=True)
def uvw(self, context): self.update_nchunks(context) lrow, urow = MS.row_extents(context) (lt, ut), (lb, ub) = context.dim_extents('ntime', 'nbl') na = context.dim_global_size('na') a1 = self._manager._padded_a1[lrow:urow] a2 = self._manager._padded_a2[lrow:urow] chunks = np.repeat(ub-lb, ut-lt).astype(a1.dtype) return mbu.antenna_uvw(self._manager._padded_uvw[lrow:urow], a1, a2, chunks, nr_of_antenna=na, check_decomposition=False, check_missing=True)
def test_uvw_antenna(self): na = 17 ntime = 1 # For both auto correlations and without them for auto_cor in (0, 1): # Compute default antenna pairs ant1, ant2 = np.triu_indices(na, auto_cor) # Create random per-antenna UVW coordinates. # zeroing the first antenna ant_uvw = np.random.random(size=(ntime, na, 3)).astype(np.float64) ant_uvw[0, 0, :] = 0 time_chunks = np.array([ant1.size], dtype=ant1.dtype) # Compute per-baseline UVW coordinates. bl_uvw = (ant_uvw[:, ant1, :] - ant_uvw[:, ant2, :]).reshape(-1, 3) # Now recover the per-antenna and per-baseline UVW coordinates. rant_uvw = antenna_uvw(bl_uvw, ant1, ant2, time_chunks, nr_of_antenna=na, check_decomposition=True)
def uvw(self, context): """ Per-antenna UVW coordinate data source """ # Hacky access of private member cube = context._cube # Create antenna1 source context a1_actual = cube.array("antenna1", reify=True) a1_ctx = SourceContext("antenna1", cube, context.cfg, context.iter_args, cube.array("antenna1"), a1_actual.shape, a1_actual.dtype) # Create antenna2 source context a2_actual = cube.array("antenna2", reify=True) a2_ctx = SourceContext("antenna2", cube, context.cfg, context.iter_args, cube.array("antenna2"), a2_actual.shape, a2_actual.dtype) # Get antenna1 and antenna2 data ant1 = self.antenna1(a1_ctx).ravel() ant2 = self.antenna2(a2_ctx).ravel() # Obtain per baseline UVW data lrow, urow = MS.uvw_row_extents(context) uvw = self._manager.ordered_uvw_table.getcol(MS.UVW, startrow=lrow, nrow=urow-lrow) # Perform the per-antenna UVW decomposition ntime, nbl = context.dim_extent_size('ntime', 'nbl') na = context.dim_global_size('na') chunks = np.repeat(nbl, ntime).astype(ant1.dtype) auvw = mbu.antenna_uvw(uvw, ant1, ant2, chunks, nr_of_antenna=na) return auvw.reshape(context.shape).astype(context.dtype)