Ejemplo n.º 1
0
    def _regen_kernel(self, XYZ):
        """
        Compute kernel.

        Parameters
        ----------
        XYZ : :py:class:`~numpy.ndarray`
            (N_antenna, 3) Cartesian instrument geometry.

            `XYZ` must be given in BFSF.
        """
        N_samples = fftpack.next_fast_len(self._NFS)
        lon_smpl = fourier.ffs_sample(self._T, self._NFS, self._Tc, N_samples)
        px_x, px_y, px_z = sph.pol2cart(1, self._grid_colat,
                                        lon_smpl.reshape(1, -1))
        pix_smpl = np.stack([px_x, px_y, px_z], axis=0)

        N_antenna = len(XYZ)
        N_height = len(self._grid_colat)

        # `self._NFS` assumes imaging is performed with `XYZ` centered at the origin.
        XYZ_c = XYZ - XYZ.mean(axis=0)
        window = func.Tukey(self._T, self._Tc, self._alpha_window)
        k_smpl = np.zeros((N_antenna, N_height, N_samples), dtype=self._cp)
        ne.evaluate('exp(A * B) * C',
                    dict(A=1j * 2 * np.pi / self._wl,
                         B=np.tensordot(XYZ_c, pix_smpl, axes=1),
                         C=window(lon_smpl)),
                    out=k_smpl,
                    casting='same_kind')  # Due to limitations of NumExpr2

        self._FSk = fourier.ffs(k_smpl, self._T, self._Tc, self._NFS, axis=2)
        self._XYZk = XYZ
Ejemplo n.º 2
0
    def _from_fits(cls, primary_hdu, image_hdu):
        """
        Load image from Header Descriptor Units.

        Parameters
        ----------
        primary_hdu : :py:class:`~astropy.io.fits.PrimaryHDU`
        image_hdu : :py:class:`~astropy.io.fits.ImageHDU`

        Returns
        -------
        I : :py:class:`~pypeline.phased_array.util.io.image.SphericalImage`
        """
        # PrimaryHDU: grid specification.
        colat, lon = primary_hdu.data
        x, y, z = sph.pol2cart(1, np.radians(colat), np.radians(lon))
        grid = np.stack([x, y, z], axis=0)

        # ImageHDU: extract data cube.
        image = image_hdu.data
        # Make sure (image, grid) have the same dtype to work with SphericalImageContainer_floatxx().
        image = image.astype(grid.dtype)

        if grid.dtype == np.dtype(np.float32):
            I_container = im_cpp.SphericalImageContainer_float32(image, grid)
        else:  # float64 mode
            I_container = im_cpp.SphericalImageContainer_float64(image, grid)
        I = cls(I_container)
        return I
Ejemplo n.º 3
0
    def _get_geometry(self, station_only):
        """
        Load instrument geometry.

        Parameters
        ----------
        station_only : bool
            If :py:obj:`True`, model stations as single-element antennas.

        Returns
        -------
        :py:class:`~pypeline.phased_array.instrument.InstrumentGeometry`
            ITRS instrument geometry.
        """
        rel_path = pathlib.Path('data', 'phased_array', 'instrument',
                                'MWA.csv')
        abs_path = pkg.resource_filename('pypeline', str(rel_path))

        itrs_geom = (pd.read_csv(abs_path).set_index('STATION_ID'))

        station_id = itrs_geom.index.get_level_values('STATION_ID')
        if station_only:
            itrs_geom.index = (pd.MultiIndex.from_product(
                [station_id, [0]], names=['STATION_ID', 'ANTENNA_ID']))
        else:
            # Generate flat 4x4 antenna grid pointing towards the Noth pole.
            x_lim = y_lim = 1.65
            lY, lX = np.meshgrid(np.linspace(-y_lim, y_lim, 4),
                                 np.linspace(-x_lim, x_lim, 4),
                                 indexing='ij')
            l = np.stack((lX, lY, np.zeros((4, 4))), axis=0)

            # For each station: rotate 4x4 array to lie on the sphere's surface.
            xyz_station = itrs_geom.loc[:, ['X', 'Y', 'Z']].values
            df_stations = []
            for st_id, st_cog in zip(station_id, xyz_station):
                _, st_colat, st_lon = sph.cart2pol(*st_cog)
                st_cog_unit = np.array(sph.pol2cart(1, st_colat, st_lon))

                R_1 = pylinalg.rot([0, 0, 1], st_lon)
                R_2 = pylinalg.rot(axis=np.cross([0, 0, 1], st_cog_unit),
                                   angle=st_colat)
                R = R_2 @ R_1

                st_layout = np.reshape(
                    st_cog.reshape(3, 1, 1) + np.tensordot(R, l, axes=1),
                    (3, -1))
                idx = (pd.MultiIndex.from_product(
                    [[st_id], range(16)], names=['STATION_ID', 'ANTENNA_ID']))
                df_stations += [
                    pd.DataFrame(data=st_layout.T,
                                 index=idx,
                                 columns=['X', 'Y', 'Z'])
                ]
            itrs_geom = pd.concat(df_stations)

        XYZ = _as_InstrumentGeometry(itrs_geom)
        return XYZ
Ejemplo n.º 4
0
def spherical_grid(direction, FoV, size):
    """
    Spherical pixel grid.

    Parameters
    ----------
    direction : :py:class:`~numpy.ndarray`
        (3,) vector around which the grid is centered.
    FoV : float
        Span of the grid centered at `direction` [rad].
    size : array-like(int)
        (N_height, N_width)

        The grid will consist of `N_height` concentric circles around `direction`, each containing `N_width` pixels.

    Returns
    -------
    :py:class:`~numpy.ndarray`
        (3, N_height, N_width) pixel grid.
    """
    direction = np.array(direction, dtype=float)
    direction /= linalg.norm(direction)

    if not (0 < FoV <= 2 * np.pi):
        raise ValueError('Parameter[FoV] must lie in (0, 360] degrees.')

    size = np.array(size, copy=False)
    if np.any(size <= 0):
        raise ValueError('Parameter[size] must contain positive entries.')

    N_height, N_width = size
    colat, lon = np.meshgrid(np.linspace(0, FoV / 2, N_height),
                             np.linspace(0, 2 * np.pi, N_width),
                             indexing='ij')
    XYZ = np.stack(sph.pol2cart(1, colat, lon), axis=0)

    # Center grid at 'direction'
    _, dir_colat, _ = sph.cart2pol(*direction)
    R_axis = np.cross([0, 0, 1], direction)
    if np.allclose(R_axis, 0):
        # R_axis is in span(E_z), so we must manually set R
        R = np.eye(3)
        if direction[2] < 0:
            R[2, 2] = -1
    else:
        R = pylinalg.rot(axis=R_axis, angle=dir_colat)

    XYZ = np.tensordot(R, XYZ, axes=1)
    return XYZ
Ejemplo n.º 5
0
    def as_image(self):
        """
        Transform integrated statistics to viewable image.

        The image is stored in a :py:class:`~pypeline.phased_arraay.util.io.image.SphericalImageContainer_floatxx` that
        can then be fed to :py:class:`~pypeline.phased_arraay.util.io.image.SphericalImage` for visualization.

        Returns
        -------
        std_c : :py:class:`~pypeline.phased_array.util.io.image.SphericalImageContainer_floatxx`
            (N_level, N_height, N_width) standardized energy-levels.

        lsq_c : :py:class:`~pypeline.phased_array.util.io.image.SphericalImageContainer_floatxx`
            (N_level, N_height, N_width) least-squares energy-levels.
        """
        if self._fp == np.float32:
            container_type = image.SphericalImageContainer_float32
        else:
            container_type = image.SphericalImageContainer_float64

        bfsf_x, bfsf_y, bfsf_z = sph.pol2cart(1,
                                              self._synthesizer._grid_colat,
                                              self._synthesizer._grid_lon)
        bfsf_grid = np.stack([bfsf_x, bfsf_y, bfsf_z], axis=0)
        icrs_grid = np.tensordot(self._synthesizer._R.T,
                                 bfsf_grid,
                                 axes=1).astype(self._fp)

        stat_std = self._statistics[0]
        field_std = self._synthesizer.synthesize(stat_std).astype(self._fp)
        std = container_type(field_std, icrs_grid)

        stat_lsq = self._statistics[1]
        field_lsq = self._synthesizer.synthesize(stat_lsq).astype(self._fp)
        lsq = container_type(field_lsq, icrs_grid)

        return std, lsq
Ejemplo n.º 6
0
T_integration = 8
sky_model = sky.from_tgss_catalog(field_center, field_of_view, N_src=20)
vis = visibility.VisibilityGeneratorBlock(sky_model,
                                          T_integration,
                                          fs=196e3,
                                          SNR=np.inf)
time = obs_start + (T_integration * u.s) * np.arange(3595)

# Imaging
N_level = 4
N_bits = 32
pix_q, pix_l, pix_colat, pix_lon = grid.ea_harmonic_grid(
    direction=field_center.cartesian.xyz.value,
    FoV=field_of_view,
    N=dev.nyquist_rate(wl))
pix_grid = np.stack(sph.pol2cart(1, pix_colat, pix_lon), axis=0)

### Intensity Field ===========================================================
# Parameter Estimation
I_est = param_est.IntensityFieldParameterEstimator(N_level, sigma=0.95)
for t in ProgressBar(time[::200]):
    XYZ = dev(t)
    W = mb(XYZ, wl)
    S = vis(XYZ, W, wl)
    G = gram(XYZ, W, wl)

    I_est.collect(S, G)
N_eig, c_centroid = I_est.infer_parameters()

# Imaging
I_dp = data_proc.IntensityFieldDataProcessorBlock(N_eig, c_centroid)