def itrs_to_enu_6D(X, ref_location=None):
    """
    Convert the given coordinates from ITRS to ENU

    :param X: float array [b0,...,bB,6]
        The coordinates are ordered [time, ra, dec, itrs.x, itrs.y, itrs.z]
    :param ref_location: float array [3]
        Point about which to rotate frame.
    :return: float array [b0,...,bB, 7]
        The transforms coordinates.
    """
    time = np.unique(X[..., 0])
    if time.size > 1:
        raise ValueError("Times should be the same.")

    shape = X.shape[:-1]
    X = X.reshape((-1, 6))
    if ref_location is None:
        ref_location = X[0, 3:]
    obstime = at.Time(time / 86400., format='mjd')
    location = ac.ITRS(x=ref_location[0] * dist_type,
                       y=ref_location[1] * dist_type,
                       z=ref_location[2] * dist_type)
    enu = ENU(location=location, obstime=obstime)
    antennas = ac.ITRS(x=X[:, 3] * dist_type,
                       y=X[:, 4] * dist_type,
                       z=X[:, 5] * dist_type,
                       obstime=obstime)
    antennas = antennas.transform_to(enu).cartesian.xyz.to(dist_type).value.T
    directions = ac.ICRS(ra=X[:, 1] * angle_type, dec=X[:, 2] * angle_type)
    directions = directions.transform_to(enu).cartesian.xyz.value.T
    return np.concatenate([X[:, 0:1], directions, antennas],
                          axis=1).reshape(shape + (7, ))
Example #2
0
def test_plot_data():
    dp = DataPack(
        '/home/albert/data/gains_screen/data/L342938_DDS5_full_merged.h5',
        readonly=True)
    with dp:
        select = dict(pol=slice(0, 1, 1), ant=[0, 50], time=slice(0, 100, 1))
        dp.current_solset = 'sol000'
        dp.select(**select)
        tec_mean, axes = dp.tec
        tec_mean = tec_mean[0, ...]
        const_mean, axes = dp.const
        const_mean = const_mean[0, ...]
        tec_std, axes = dp.weights_tec
        tec_std = tec_std[0, ...]
        patch_names, directions = dp.get_directions(axes['dir'])
        antenna_labels, antennas = dp.get_antennas(axes['ant'])
        timestamps, times = dp.get_times(axes['time'])
    antennas = ac.ITRS(*antennas.cartesian.xyz, obstime=times[0])
    ref_ant = antennas[0]

    for i, time in enumerate(times):
        frame = ENU(obstime=time, location=ref_ant.earth_location)
        antennas = antennas.transform_to(frame)
        directions = directions.transform_to(frame)
        x = antennas.cartesian.xyz.to(au.km).value.T
        k = directions.cartesian.xyz.value.T

        dtec = tec_mean[:, 1, i]
        ax = plot_vornoi_map(k[:, 0:2], dtec)
        ax.set_title(time)
        plt.show()
Example #3
0
    def EarthLocation(self, jd):
        """
		Returns positions as an EarthLocation object, which can be feed
		directly into :func:`astropy.time.Time.light_travel_time`.

		Parameters:
			jd (ndarray): Time in Julian Days where position of TESS should be calculated.

		Returns:
			:class:`astropy.coordinates.EarthLocation`: EarthLocation object that can be passed
				directly into :py:class:`astropy.time.Time`.

		.. codeauthor:: Rasmus Handberg <*****@*****.**>
		"""

        # Get positions as 2D array:
        positions = self.position(jd, relative_to='EARTH')

        # Transform into appropiate Geocentric frame:
        obstimes = Time(jd, format='jd', scale='tdb')
        cartrep = coord.CartesianRepresentation(positions,
                                                xyz_axis=1,
                                                unit=u.km)
        gcrs = coord.GCRS(cartrep, obstime=obstimes)
        itrs = gcrs.transform_to(coord.ITRS(obstime=obstimes))

        # Create EarthLocation object
        return coord.EarthLocation.from_geocentric(*itrs.cartesian.xyz,
                                                   unit=u.km)
Example #4
0
def test_frames(tmpdir):
    frames = [
        cf.CelestialFrame(reference_frame=coord.ICRS()),
        cf.CelestialFrame(reference_frame=coord.FK5(
            equinox=time.Time('2010-01-01'))),
        cf.CelestialFrame(reference_frame=coord.FK4(
            equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))),
        cf.CelestialFrame(reference_frame=coord.FK4NoETerms(
            equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))),
        cf.CelestialFrame(reference_frame=coord.Galactic()),
        cf.CelestialFrame(
            reference_frame=coord.Galactocentric(galcen_distance=5.0 * u.m,
                                                 galcen_ra=45 * u.deg,
                                                 galcen_dec=1 * u.rad,
                                                 z_sun=3 * u.pc,
                                                 roll=3 * u.deg)),
        cf.CelestialFrame(
            reference_frame=coord.GCRS(obstime=time.Time('2010-01-01'),
                                       obsgeoloc=[1, 3, 2000] * u.pc,
                                       obsgeovel=[2, 1, 8] * (u.m / u.s))),
        cf.CelestialFrame(reference_frame=coord.CIRS(
            obstime=time.Time('2010-01-01'))),
        cf.CelestialFrame(reference_frame=coord.ITRS(
            obstime=time.Time('2022-01-03'))),
        cf.CelestialFrame(reference_frame=coord.PrecessedGeocentric(
            obstime=time.Time('2010-01-01'),
            obsgeoloc=[1, 3, 2000] * u.pc,
            obsgeovel=[2, 1, 8] * (u.m / u.s)))
    ]

    tree = {'frames': frames}

    helpers.assert_roundtrip_tree(tree, tmpdir)
Example #5
0
def satellite_position():
    """not used"""
    # Hardcoded for one satellite
    satellite_name = "ODIN"
    satellite_line1 = '1 26702U 01007A   19291.79098765 -.00000023  00000-0  25505-5 0  9996'
    satellite_line2 = '2 26702  97.5699 307.6930 0011485  26.4207 333.7604 15.07886437 19647'

    current_time = datetime.datetime.now()

    satellite = twoline2rv(satellite_line1, satellite_line2, wgs72)
    position, velocity = satellite.propagate(
        current_time.year,
        current_time.month,
        current_time.day,
        current_time.hour,
        current_time.minute,
        current_time.second)

    now = Time.now()
    # position of satellite in GCRS or J20000 ECI:
    cartrep = coord.CartesianRepresentation(x=position[0],
                                            y=position[1],
                                            z=position[2], unit=u.m)
    gcrs = coord.GCRS(cartrep, obstime=now)
    itrs = gcrs.transform_to(coord.ITRS(obstime=now))
    loc = coord.EarthLocation(*itrs.cartesian.xyz)

    return jsonify({
        'eci': {'x': position[0], 'y': position[1], 'z': position[2]},
        'geodetic': {'latitude': loc.lat.deg, 'longitude': loc.lon.deg, 'height': loc.height.to(u.m).value}
    })
    def transform(X, ref_location=ref_location):
        """
        Convert the given coordinates from ITRS to ENU

        :param X: float array [Nd, Na,6]
            The coordinates are ordered [time, ra, dec, itrs.x, itrs.y, itrs.z]
        :return: float array [Nd, Na, 7(10(13))]
            The transforms coordinates.
        """
        time = np.unique(X[..., 0])
        if time.size > 1:
            raise ValueError("Times should be the same.")
        shape = X.shape[:-1]
        X = X.reshape((-1, 6))
        if ref_location is None:
            ref_location = X[0, 3:6]
        obstime = at.Time(time / 86400., format='mjd')
        location = ac.ITRS(x=ref_location[0] * dist_type,
                           y=ref_location[1] * dist_type,
                           z=ref_location[2] * dist_type)
        ref_ant = ac.ITRS(x=ref_antenna[0] * dist_type,
                          y=ref_antenna[1] * dist_type,
                          z=ref_antenna[2] * dist_type,
                          obstime=obstime)
        ref_dir = ac.ICRS(ra=ref_direction[0] * angle_type,
                          dec=ref_direction[1] * angle_type)
        enu = ENU(location=location, obstime=obstime)
        ref_ant = ref_ant.transform_to(enu).cartesian.xyz.to(dist_type).value.T
        ref_dir = ref_dir.transform_to(enu).cartesian.xyz.value.T
        antennas = ac.ITRS(x=X[:, 3] * dist_type,
                           y=X[:, 4] * dist_type,
                           z=X[:, 5] * dist_type,
                           obstime=obstime)
        antennas = antennas.transform_to(enu).cartesian.xyz.to(
            dist_type).value.T
        directions = ac.ICRS(ra=X[:, 1] * angle_type, dec=X[:, 2] * angle_type)
        directions = directions.transform_to(enu).cartesian.xyz.value.T
        result = np.concatenate([X[:, 0:1], directions, antennas], axis=1)  #
        if ref_antenna is not None:
            result = np.concatenate(
                [result, np.tile(ref_ant, (result.shape[0], 1))], axis=-1)
        if ref_direction is not None:
            result = np.concatenate(
                [result, np.tile(ref_dir, (result.shape[0], 1))], axis=-1)
        result = result.reshape(shape + result.shape[-1:])
        return result
def itrs2gcrs(years, months, dates, hours, minutes, seconds, pos, vel,
              utc_time, gcrs_filename):
    """ This function is to transform the coordinates and velocities from itrs into gcrs
    """
    date_list = []
    for index, element in enumerate(
            zip(years, months, dates, hours, minutes, seconds)):
        date_list.append(str(int(element[0])) + '-' + str(int(element[1])) + '-' + str(int(element[2])) + ' ' + \
            str(int(element[3])) + ':' + str(int(element[4])) + ':' + str(element[5]))

    a_date = atime(date_list)
    pos = pos * u.km
    vel = vel * u.km
    itrs1 = coor.ITRS(x=pos[:, 0],
                      y=pos[:, 1],
                      z=pos[:, 2],
                      representation_type='cartesian',
                      obstime=a_date)
    gcrs1 = itrs1.transform_to(coor.GCRS(obstime=a_date))
    itrs2 = coor.ITRS(x=vel[:, 0],
                      y=vel[:, 1],
                      z=vel[:, 2],
                      representation_type='cartesian',
                      obstime=a_date)
    gcrs2 = itrs2.transform_to(coor.GCRS(obstime=a_date))

    gcrs_xyz1 = np.asarray(gcrs1.cartesian.xyz)
    gcrs_xyz2 = np.asarray(gcrs2.cartesian.xyz)

    dd_igrf = dd.from_pandas(pd.DataFrame({
        'utc_time': utc_time,
        'gcrs_x': gcrs_xyz1[0],
        'gcrs_y': gcrs_xyz1[1],
        'gcrs_z': gcrs_xyz1[2],
        'gcrs_rvx': gcrs_xyz2[0],
        'gcrs_rvy': gcrs_xyz2[1],
        'gcrs_rvz': gcrs_xyz2[2]
    }),
                             npartitions=1)
    write_gcrs_file_header(gcrs_filename, dd_igrf)
    dd_igrf.to_csv(gcrs_filename,
                   single_file=True,
                   sep='\t',
                   index=False,
                   mode='a+')
def get_coord_in_ecef(xyz):
    from astropy import coordinates as coord
    from astropy import units as u
    from astropy.time import Time
    now = Time(TIME)
    # position of satellite in GCRS or J20000 ECI:
    cartrep = coord.CartesianRepresentation(*xyz, unit=u.m)
    gcrs = coord.GCRS(cartrep, obstime=now)
    itrs = gcrs.transform_to(coord.ITRS(obstime=now))
    loc = coord.EarthLocation(*itrs.cartesian.xyz)
    return [loc.lat, loc.lon, loc.height]
def GCRS2ITRS(r, v, jd, fr):
    now = Time(jd + fr, format="jd")
    itrs = coord.GCRS(r[0] * u.m,
                      r[1] * u.m,
                      r[2] * u.m,
                      v[0] * u.m / u.s,
                      v[1] * u.m / u.s,
                      v[2] * u.m / u.s,
                      obstime=now,
                      representation_type='cartesian')
    gcrs = itrs.transform_to(coord.ITRS(obstime=now))
    r, v = gcrs.cartesian.xyz.value, gcrs.velocity.d_xyz.value
    return r, v * 1000
Example #10
0
    def __init__(self,
                 dt: int = 1000,
                 orbvec: np.array = np.array([6621000.1, 0.0, 94.3, 180, 0,
                                              0]),
                 plot=False,
                 coordinate='spherical'):

        re = 6.3781e3

        #Setting Classical Orbital Parameters
        self.__a = orbvec[0] * u.meter
        self.__ecc = orbvec[1] * u.one
        self.__inc = orbvec[2] * u.deg
        self.__raan = orbvec[3] * u.deg
        self.__argp = orbvec[4] * u.deg
        self.__nu = 0 * u.deg

        #Generate Satellite Orbit
        self.__ss = Orbit.from_classical(Earth, self.__a, self.__ecc,
                                         self.__inc, self.__raan, self.__argp,
                                         self.__nu)

        # Transform GCRS to ITRS
        self.__ss_gcrs = self.__ss.sample(dt)
        self.__ss_itrs = self.__ss_gcrs.transform_to(
            coord.ITRS(obstime=self.__ss_gcrs.obstime))

        # Convert to lat and lon
        self.__latlon_itrs = self.__ss_itrs.represent_as(
            coord.SphericalRepresentation)

        self.__vals = np.zeros([dt, 4])

        self.timedata()

        if coordinate == 'spherical':
            self.sphericalpos(dt, re)
            self.__df = pd.DataFrame(
                self.__vals,
                columns=['Time [s]', 'Lat [deg]', 'Lon [deg]', 'Height [km]'])

        if coordinate == 'cartesian':
            self.cartesianpos(dt)
            self.__df = pd.DataFrame(
                self.__vals, columns=['Time [s]', 'X [m]', 'Y [m]', 'Z [m]'])

        if plot == True:
            self.GroundPlot()
Example #11
0
def ecef_to_eci(ecef_positions, ecef_velocities, posix_times):
    """Converts one or multiple Cartesian vectors in the ECEF to a GCRS frame at the given time.
    When converting multiple objects, each object should have a ECEF position, ECEF velocity and a
    reference time in the same index of the appropriate input list

    Args:
        ecef_positions (list of tuples): A list of the Cartesian coordinate tuples of the objects in
        the ECCF frame (m)
        ecef_velocities (list of tuples): A list of the velocity tuples of the objects in the EECF
        frame (m/s)
        time_posix (int): A list of times to be used as reference frame time for objects

    Returns:
    A list of tuples, each tuple has the following format:
        (Position Vector3D(x,y,z), Velocity Vector3D(x,y,z))
        Position Vector:
            x = GCRS X-coordinate (m)
            y = GCRS Y-coordinate (m)
            z = GCRS Z-coordinate (m)
        Velocity Vector
            x = GCRS X-velocity (m/s)
            y = GCRS Y-velocity (m/s)
            z = GCRS Z-velocity (m/s)

    Note:
        Unlike the rest of the software that uses J2000 FK5, the ECI frame used here is
        GCRS; This can potentially introduce around 200m error for locations on surface of Earth.
    """
    posix_times = Time(posix_times, format='unix')
    cart_diff = coordinates.CartesianDifferential(ecef_velocities, unit='m/s', copy=False)
    cart_rep = coordinates.CartesianRepresentation(ecef_positions, unit='m',
                                                   differentials=cart_diff, copy=False)

    ecef = coordinates.ITRS(cart_rep, obstime=posix_times)
    gcrs = ecef.transform_to(coordinates.GCRS(obstime=posix_times))

    # pylint: disable=no-member
    positions = array(transpose(gcrs.cartesian.xyz.value), ndmin=2)
    velocities = array(transpose(gcrs.cartesian.differentials.values()[0].d_xyz
                                 .to(units.m / units.s).value), ndmin=2)
    # pylint: enable=no-member

    ret_pairs = [(Vector3D(*pos), Vector3D(*vel)) for pos, vel in zip(positions, velocities)]

    return ret_pairs
Example #12
0
def test_tomographic_kernel():
    dp = make_example_datapack(500, 24, 1, clobber=True)
    with dp:
        select = dict(pol=slice(0, 1, 1), ant=slice(0, None, 1))
        dp.current_solset = 'sol000'
        dp.select(**select)
        tec_mean, axes = dp.tec
        tec_mean = tec_mean[0, ...]
        patch_names, directions = dp.get_directions(axes['dir'])
        antenna_labels, antennas = dp.get_antennas(axes['ant'])
        timestamps, times = dp.get_times(axes['time'])
    antennas = ac.ITRS(*antennas.cartesian.xyz, obstime=times[0])
    ref_ant = antennas[0]
    frame = ENU(obstime=times[0], location=ref_ant.earth_location)
    antennas = antennas.transform_to(frame)
    ref_ant = antennas[0]
    directions = directions.transform_to(frame)
    x = antennas.cartesian.xyz.to(au.km).value.T
    k = directions.cartesian.xyz.value.T
    X = make_coord_array(x[50:51, :], k)
    x0 = ref_ant.cartesian.xyz.to(au.km).value
    print(k.shape)

    kernel = TomographicKernel(x0, x0, RBF(), S_marg=25)
    K = jit(lambda X: kernel(
        X, X, bottom=200., width=50., fed_kernel_params=dict(l=7., sigma=1.)))(
            jnp.asarray(X))
    # K /= jnp.outer(jnp.sqrt(jnp.diag(K)), jnp.sqrt(jnp.diag(K)))
    plt.imshow(K)
    plt.colorbar()
    plt.show()
    L = jnp.linalg.cholesky(K + 1e-6 * jnp.eye(K.shape[0]))
    print(L)
    dtec = L @ random.normal(random.PRNGKey(24532), shape=(K.shape[0], ))
    print(jnp.std(dtec))
    ax = plot_vornoi_map(k[:, 0:2], dtec)
    ax.set_xlabel(r"$k_{\rm east}$")
    ax.set_ylabel(r"$k_{\rm north}$")
    ax.set_xlim(-0.1, 0.1)
    ax.set_ylim(-0.1, 0.1)
    plt.show()
Example #13
0
def satlla_from_TLE(line1, line2):
    start = timer()
    satellite = twoline2rv(line1, line2, wgs72)
    stop = timer()
    print("3 i  . Duration : %f s" % (stop - start))

    start = timer()
    # try to propagate for a period of time
    propTimeSecs = np.pi*2/satellite.no*60
    timeDivisor = 10
    STARTTIME = satellite.epoch
    stop = timer()
    print("3 ii . Duration : %f s" % (stop - start))

#    STOPTIME = STARTTIME + datetime.timedelta(seconds = propTimeSecs)
    
    start = timer()
    r = np.zeros((int(propTimeSecs/timeDivisor), 3))
    v = np.zeros((int(propTimeSecs/timeDivisor), 3))
    lat = np.zeros((int(propTimeSecs/timeDivisor), 1))
    lon = np.zeros((int(propTimeSecs/timeDivisor), 1))
    stop = timer()
    print("3 iii. Duration : %f s" % (stop - start))

    #print(STARTTIME)
    #print(STOPTIME)
    
    start = timer()
    print("%s / %s = %s" % (propTimeSecs, timeDivisor, propTimeSecs/timeDivisor))
    for i in range(int(propTimeSecs/timeDivisor)): # propagate orbit and convert to LLA
        CURRTIME = STARTTIME + datetime.timedelta(seconds=i*timeDivisor)
        r[i,], v[i,] = satellite.propagate(CURRTIME.year, CURRTIME.month, CURRTIME.day, CURRTIME.hour, CURRTIME.minute, CURRTIME.second)
        cartRep = coord.CartesianRepresentation(x=r[i,0], y=r[i,1], z=r[i,2], unit=u.km)
        gcrs = coord.GCRS(cartRep, obstime=CURRTIME) # cast xyz coordinate in ECI frame
        itrs = gcrs.transform_to(coord.ITRS(obstime=CURRTIME))
        lat[i], lon[i] = itrs.spherical.lat.value , itrs.spherical.lon.value
    stop = timer()
    print("3 iv . Duration : %f s" % (stop - start))

    return r, v, lat, lon
Example #14
0
def create_test_frames():
    """Creates an array of frames to be used for testing."""

    # Suppress warnings from astropy that are caused by having 'dubious' dates
    # that are too far in the future. It's not a concern for the purposes of
    # unit tests. See issue #5809 on the astropy GitHub for discussion.
    from astropy._erfa import ErfaWarning
    warnings.simplefilter("ignore", ErfaWarning)

    frames = [
        cf.CelestialFrame(reference_frame=coord.ICRS()),
        cf.CelestialFrame(reference_frame=coord.FK5(
            equinox=time.Time('2010-01-01'))),
        cf.CelestialFrame(reference_frame=coord.FK4(
            equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))),
        cf.CelestialFrame(reference_frame=coord.FK4NoETerms(
            equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))),
        cf.CelestialFrame(reference_frame=coord.Galactic()),
        cf.CelestialFrame(reference_frame=coord.Galactocentric(
            # A default galcen_coord is used since none is provided here
            galcen_distance=5.0 * u.m,
            z_sun=3 * u.pc,
            roll=3 * u.deg)),
        cf.CelestialFrame(
            reference_frame=coord.GCRS(obstime=time.Time('2010-01-01'),
                                       obsgeoloc=[1, 3, 2000] * u.pc,
                                       obsgeovel=[2, 1, 8] * (u.m / u.s))),
        cf.CelestialFrame(reference_frame=coord.CIRS(
            obstime=time.Time('2010-01-01'))),
        cf.CelestialFrame(reference_frame=coord.ITRS(
            obstime=time.Time('2022-01-03'))),
        cf.CelestialFrame(reference_frame=coord.PrecessedGeocentric(
            obstime=time.Time('2010-01-01'),
            obsgeoloc=[1, 3, 2000] * u.pc,
            obsgeovel=[2, 1, 8] * (u.m / u.s))),
        cf.StokesFrame(),
        cf.TemporalFrame(time.Time("2011-01-01"))
    ]

    return frames
Example #15
0
 def load(self, filename):
     super(Solution, self).load(filename)
     f = h5py.File(filename, 'r')
     try:
         obstime = at.Time(f['TCI'].attrs['obstime'],
                           format='gps',
                           scale='tai')
         fixtime = at.Time(f['TCI'].attrs['fixtime'],
                           format='gps',
                           scale='tai')
         location = ac.ITRS().realize_frame(
             CartesianRepresentation(*(f['TCI'].attrs['location'] * au.km)))
         phase = ac.SkyCoord(*(f['TCI'].attrs['phase'] * au.deg),
                             frame='icrs')
         pointing_frame = Pointing(location=location,
                                   obstime=obstime,
                                   phase=phase,
                                   fixtime=fixtime)
     except:
         pointing_frame = None
     f.close()
     self.__init__(pointing_frame=pointing_frame)
Example #16
0
def el2rv(inc, raan, ecc, argp, mean_anomaly, mean_motion, epoch):
    """
    Converts mean orbital elements to state vector
    """

    time_tle = epoch.jd - 2433281.5
    sat = Satrec()
    sat.sgp4init(
        WGS84,
        "i",
        0,
        time_tle,
        0.0,
        0.0,
        0.0,
        ecc,
        argp,
        inc,
        mean_anomaly,
        mean_motion,
        raan,
    )

    errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2)
    if errorCode != 0:
        raise RuntimeError(SGP4_ERRORS[errorCode])

    pTEME = coord.CartesianRepresentation(rTEME * u.km)
    vTEME = coord.CartesianDifferential(vTEME * u.km / u.s)
    svTEME = TEME(pTEME.with_differentials(vTEME), obstime=epoch)

    svITRS = svTEME.transform_to(coord.ITRS(obstime=epoch))

    orb = Orbit.from_coords(Earth, svITRS)

    return orb.r, orb.v
Example #17
0
    def run(self, output_h5parm, ncpu, avg_direction_spacing,
            field_of_view_diameter, duration, time_resolution, start_time,
            array_name, phase_tracking):

        Nd = get_num_directions(
            avg_direction_spacing,
            field_of_view_diameter,
        )
        Nf = 2  # 8000
        Nt = int(duration / time_resolution) + 1
        min_freq = 700.
        max_freq = 2000.
        dp = create_empty_datapack(
            Nd,
            Nf,
            Nt,
            pols=None,
            field_of_view_diameter=field_of_view_diameter,
            start_time=start_time,
            time_resolution=time_resolution,
            min_freq=min_freq,
            max_freq=max_freq,
            array_file=ARRAYS[array_name],
            phase_tracking=(phase_tracking.ra.deg, phase_tracking.dec.deg),
            save_name=output_h5parm,
            clobber=True)

        with dp:
            dp.current_solset = 'sol000'
            dp.select(pol=slice(0, 1, 1))
            axes = dp.axes_tec
            patch_names, directions = dp.get_directions(axes['dir'])
            antenna_labels, antennas = dp.get_antennas(axes['ant'])
            timestamps, times = dp.get_times(axes['time'])
            ref_ant = antennas[0]
            ref_time = times[0]

        Na = len(antennas)
        Nd = len(directions)
        Nt = len(times)

        logger.info(f"Number of directions: {Nd}")
        logger.info(f"Number of antennas: {Na}")
        logger.info(f"Number of times: {Nt}")
        logger.info(f"Reference Ant: {ref_ant}")
        logger.info(f"Reference Time: {ref_time.isot}")

        # Plot Antenna Layout in East North Up frame
        ref_frame = ENU(obstime=ref_time, location=ref_ant.earth_location)

        _antennas = ac.ITRS(*antennas.cartesian.xyz,
                            obstime=ref_time).transform_to(ref_frame)
        # plt.scatter(_antennas.east, _antennas.north, marker='+')
        # plt.xlabel(f"East (m)")
        # plt.ylabel(f"North (m)")
        # plt.show()

        x0 = ac.ITRS(
            *antennas[0].cartesian.xyz,
            obstime=ref_time).transform_to(ref_frame).cartesian.xyz.to(
                au.km).value
        earth_centre_x = ac.ITRS(
            x=0 * au.m, y=0 * au.m, z=0. * au.m,
            obstime=ref_time).transform_to(ref_frame).cartesian.xyz.to(
                au.km).value
        self._kernel = TomographicKernel(x0,
                                         earth_centre_x,
                                         M32(),
                                         S_marg=20,
                                         compute_tec=False)

        k = directions.transform_to(ref_frame).cartesian.xyz.value.T

        t = times.mjd * 86400.
        t -= t[0]

        X1 = GeodesicTuple(x=[], k=[], t=[], ref_x=[])

        logger.info("Computing coordinates in frame ...")

        for i, time in tqdm(enumerate(times)):
            x = ac.ITRS(*antennas.cartesian.xyz,
                        obstime=time).transform_to(ref_frame).cartesian.xyz.to(
                            au.km).value.T
            ref_ant_x = ac.ITRS(
                *ref_ant.cartesian.xyz,
                obstime=time).transform_to(ref_frame).cartesian.xyz.to(
                    au.km).value

            X = make_coord_array(x,
                                 k,
                                 t[i:i + 1, None],
                                 ref_ant_x[None, :],
                                 flat=True)

            X1.x.append(X[:, 0:3])
            X1.k.append(X[:, 3:6])
            X1.t.append(X[:, 6:7])
            X1.ref_x.append(X[:, 7:8])

        X1 = X1._replace(
            x=jnp.concatenate(X1.x, axis=0),
            k=jnp.concatenate(X1.k, axis=0),
            t=jnp.concatenate(X1.t, axis=0),
            ref_x=jnp.concatenate(X1.ref_x, axis=0),
        )

        logger.info(f"Total number of coordinates: {X1.x.shape[0]}")

        def compute_covariance_row(X1: GeodesicTuple, X2: GeodesicTuple):
            K = self._kernel(X1,
                             X2,
                             self._bottom,
                             self._width,
                             self._fed_sigma,
                             self._fed_kernel_params,
                             wind_velocity=self._wind_vector)  # 1, N
            return K[0, :]

        covariance_row = lambda X: compute_covariance_row(
            tree_map(lambda x: x.reshape((1, -1)), X), X1)

        mean = jit(lambda X1: self._kernel.mean_function(X1,
                                                         self._bottom,
                                                         self._width,
                                                         self._fed_mu,
                                                         wind_velocity=self.
                                                         _wind_vector))(X1)

        cov = chunked_pmap(covariance_row,
                           X1,
                           batch_size=X1.x.shape[0],
                           chunksize=ncpu)

        plt.imshow(cov)
        plt.show()

        Z = random.normal(random.PRNGKey(42), (cov.shape[0], 1),
                          dtype=cov.dtype)

        t0 = default_timer()
        jitter = 1e-6
        logger.info(f"Computing Cholesky with jitter: {jitter}")
        L = jnp.linalg.cholesky(cov + jitter * jnp.eye(cov.shape[0]))
        if np.any(np.isnan(L)):
            logger.info("Numerically instable. Using SVD.")
            L = msqrt(cov)

        logger.info(f"Cholesky took {default_timer() - t0} seconds.")

        dtec = (L @ Z + mean[:, None])[:, 0].reshape((Na, Nd, Nt)).transpose(
            (1, 0, 2))

        logger.info(f"Saving result to {output_h5parm}")
        with dp:
            dp.current_solset = 'sol000'
            dp.select(pol=slice(0, 1, 1))
            dp.tec = np.asarray(dtec[None])
def train_neural_network(datapack: DataPack, batch_size, learning_rate,
                         num_batches):

    with datapack:
        select = dict(pol=slice(0, 1, 1), ant=None, time=slice(0, 1, 1))
        datapack.current_solset = 'sol000'
        datapack.select(**select)
        axes = datapack.axes_tec
        patch_names, directions = datapack.get_directions(axes['dir'])
        antenna_labels, antennas = datapack.get_antennas(axes['ant'])
        timestamps, times = datapack.get_times(axes['time'])

    antennas = ac.ITRS(*antennas.cartesian.xyz, obstime=times[0])
    ref_ant = antennas[0]
    frame = ENU(obstime=times[0], location=ref_ant.earth_location)
    antennas = antennas.transform_to(frame)
    ref_ant = antennas[0]
    directions = directions.transform_to(frame)
    x = antennas.cartesian.xyz.to(au.km).value.T
    k = directions.cartesian.xyz.value.T
    t = times.mjd
    t -= t[len(t) // 2]
    t *= 86400.
    n_screen = 250
    kstar = random.uniform(random.PRNGKey(29428942), (n_screen, 3),
                           minval=jnp.min(k, axis=0),
                           maxval=jnp.max(k, axis=0))
    kstar /= jnp.linalg.norm(kstar, axis=-1, keepdims=True)
    X = jnp.asarray(
        make_coord_array(x, jnp.concatenate([k, kstar], axis=0), t[:, None]))
    x0 = jnp.asarray(antennas.cartesian.xyz.to(au.km).value.T[0, :])
    ref_ant = x0

    kernel = TomographicKernel(x0, ref_ant, RBF(), S_marg=100)
    neural_kernel = NeuralTomographicKernel(x0, ref_ant)

    def loss(params, key):
        keys = random.split(key, 5)
        indices = random.permutation(keys[0],
                                     jnp.arange(X.shape[0]))[:batch_size]
        X_batch = X[indices, :]

        wind_velocity = random.uniform(keys[1],
                                       shape=(3, ),
                                       minval=jnp.asarray([-200., -200., 0.]),
                                       maxval=jnp.asarray([200., 200., 0.
                                                           ])) / 1000.
        bottom = random.uniform(keys[2], minval=50., maxval=500.)
        width = random.uniform(keys[3], minval=40., maxval=300.)
        l = random.uniform(keys[4], minval=1., maxval=30.)
        sigma = 1.
        K = kernel(X_batch,
                   X_batch,
                   bottom,
                   width,
                   l,
                   sigma,
                   wind_velocity=wind_velocity)
        neural_kernel.set_params(params)
        neural_K = neural_kernel(X_batch,
                                 X_batch,
                                 bottom,
                                 width,
                                 l,
                                 sigma,
                                 wind_velocity=wind_velocity)

        return jnp.mean((K - neural_K)**2) / width**2

    init_params = neural_kernel.init_params(random.PRNGKey(42))

    def train_one_batch(params, key):
        l, g = value_and_grad(lambda params: loss(params, key))(params)
        params = tree_multimap(lambda p, g: p - learning_rate * g, params, g)
        return params, l

    final_params, losses = jit(lambda key: scan(
        train_one_batch, init_params, random.split(key, num_batches)))(
            random.PRNGKey(42))

    plt.plot(losses)
    plt.yscale('log')
    plt.show()
def test_enu():
    lofar_array = np.random.normal(size=[10, 3])
    antennas = lofar_array[1]
    obstime = at.Time("2018-01-01T00:00:00.000", format='isot')
    location = ac.ITRS(x=antennas[0, 0] * dist_type,
                       y=antennas[0, 1] * dist_type,
                       z=antennas[0, 2] * dist_type)
    enu = ENU(obstime=obstime, location=location.earth_location)
    altaz = ac.AltAz(obstime=obstime, location=location.earth_location)
    lofar_antennas = ac.ITRS(x=antennas[:, 0] * dist_type,
                             y=antennas[:, 1] * dist_type,
                             z=antennas[:, 2] * dist_type,
                             obstime=obstime)
    assert np.all(
        np.linalg.norm(lofar_antennas.transform_to(enu).cartesian.xyz.to(
            dist_type).value,
                       axis=0) < 100.)
    assert np.all(
        np.isclose(
            lofar_antennas.transform_to(enu).cartesian.xyz.to(dist_type).value,
            lofar_antennas.transform_to(enu).transform_to(altaz).transform_to(
                enu).cartesian.xyz.to(dist_type).value))
    assert np.all(
        np.isclose(
            lofar_antennas.transform_to(altaz).cartesian.xyz.to(
                dist_type).value,
            lofar_antennas.transform_to(altaz).transform_to(enu).transform_to(
                altaz).cartesian.xyz.to(dist_type).value))
    north_enu = ac.SkyCoord(east=0., north=1., up=0., frame=enu)
    north_altaz = ac.SkyCoord(az=0 * au.deg,
                              alt=0 * au.deg,
                              distance=1.,
                              frame=altaz)
    assert np.all(
        np.isclose(
            north_enu.transform_to(altaz).cartesian.xyz.value,
            north_altaz.cartesian.xyz.value))
    assert np.all(
        np.isclose(north_enu.cartesian.xyz.value,
                   north_altaz.transform_to(enu).cartesian.xyz.value))
    east_enu = ac.SkyCoord(east=1., north=0., up=0., frame=enu)
    east_altaz = ac.SkyCoord(az=90 * au.deg,
                             alt=0 * au.deg,
                             distance=1.,
                             frame=altaz)
    assert np.all(
        np.isclose(
            east_enu.transform_to(altaz).cartesian.xyz.value,
            east_altaz.cartesian.xyz.value))
    assert np.all(
        np.isclose(east_enu.cartesian.xyz.value,
                   east_altaz.transform_to(enu).cartesian.xyz.value))
    up_enu = ac.SkyCoord(east=0., north=0., up=1., frame=enu)
    up_altaz = ac.SkyCoord(az=0 * au.deg,
                           alt=90 * au.deg,
                           distance=1.,
                           frame=altaz)
    assert np.all(
        np.isclose(
            up_enu.transform_to(altaz).cartesian.xyz.value,
            up_altaz.cartesian.xyz.value))
    assert np.all(
        np.isclose(up_enu.cartesian.xyz.value,
                   up_altaz.transform_to(enu).cartesian.xyz.value))
    ###
    # dimensionful
    north_enu = ac.SkyCoord(east=0. * dist_type,
                            north=1. * dist_type,
                            up=0. * dist_type,
                            frame=enu)
    north_altaz = ac.SkyCoord(az=0 * au.deg,
                              alt=0 * au.deg,
                              distance=1. * dist_type,
                              frame=altaz)
    assert np.all(
        np.isclose(
            north_enu.transform_to(altaz).cartesian.xyz.to(dist_type).value,
            north_altaz.cartesian.xyz.to(dist_type).value))
    assert np.all(
        np.isclose(
            north_enu.cartesian.xyz.to(dist_type).value,
            north_altaz.transform_to(enu).cartesian.xyz.to(dist_type).value))
    east_enu = ac.SkyCoord(east=1. * dist_type,
                           north=0. * dist_type,
                           up=0. * dist_type,
                           frame=enu)
    east_altaz = ac.SkyCoord(az=90 * au.deg,
                             alt=0 * au.deg,
                             distance=1. * dist_type,
                             frame=altaz)
    assert np.all(
        np.isclose(
            east_enu.transform_to(altaz).cartesian.xyz.to(dist_type).value,
            east_altaz.cartesian.xyz.to(dist_type).value))
    assert np.all(
        np.isclose(
            east_enu.cartesian.xyz.to(dist_type).value,
            east_altaz.transform_to(enu).cartesian.xyz.to(dist_type).value))
    up_enu = ac.SkyCoord(east=0. * dist_type,
                         north=0. * dist_type,
                         up=1. * dist_type,
                         frame=enu)
    up_altaz = ac.SkyCoord(az=0 * au.deg,
                           alt=90 * au.deg,
                           distance=1. * dist_type,
                           frame=altaz)
    assert np.all(
        np.isclose(
            up_enu.transform_to(altaz).cartesian.xyz.to(dist_type).value,
            up_altaz.cartesian.xyz.to(dist_type).value))
    assert np.all(
        np.isclose(
            up_enu.cartesian.xyz.to(dist_type).value,
            up_altaz.transform_to(enu).cartesian.xyz.to(dist_type).value))
Example #20
0
data = np.load('iono_char_save.npz')['arr_0'].item(0)
iono_ls = np.array(list(data.keys()))
length_scales = []
var_scales = []
for k in data:
    length_scales.append(data[k]['l_space'])
    var_scales.append(data[k]['var'])
length_scales = np.stack(length_scales, 0)
var_scales = np.stack(var_scales, 0)

from ionotomo import RadioArray, ENU

radio_array = RadioArray(array_file=RadioArray.lofar_array)
antennas = radio_array.get_antenna_locs()
array_center = ac.ITRS(np.mean(antennas.data))
enu = ENU(location=array_center)
ants_enu = antennas.transform_to(enu)
ref_dist = np.sqrt(
    (antennas.x.to(au.km).value - antennas.x.to(au.km).value[0])**2 +
    (antennas.y.to(au.km).value - antennas.y.to(au.km).value[0])**2 +
    (antennas.z.to(au.km).value - antennas.z.to(au.km).value[0])**2)

east_color = (ants_enu.east.to(au.km).value - np.min(
    ants_enu.east.to(au.km).value)) / (np.max(ants_enu.east.to(au.km).value) -
                                       np.min(ants_enu.east.to(au.km).value))
north_color = (ants_enu.north.to(au.km).value - np.min(
    ants_enu.north.to(au.km).value)) / (np.max(ants_enu.north.to(
        au.km).value) - np.min(ants_enu.north.to(au.km).value))

print(length_scales.shape, var_scales.shape)
Example #21
0
def air_density(years, months, date_i):
    dd_aird_i = dd.read_csv(
        urlpath='..//output//taiji-01-0222-air-drag-gcrs-2019-09.txt',
        header=None,
        engine='c',
        skiprows=35,
        storage_options=dict(auto_mkdir=False),
        sep='\s+',
        names=[
            'gps_time', 'xacc', 'yacc', 'zacc', 'xacc_s', 'yacc_s', 'zacc_s'
        ],
        dtype=np.float64,
        encoding='gb2312')
    utc_time = dd_aird_i.gps_time.compute().to_numpy()

    dates = np.floor((utc_time - utc_time[0]) / 86400.).astype(np.int) + date_i
    hours = np.floor((utc_time - utc_time[0] - (dates - date_i) * 86400.) /
                     3600.).astype(np.int)
    minutes = np.floor((utc_time - utc_time[0] - hours * 3600.0 -
                        (dates - date_i) * 86400.) / 60.).astype(np.int)
    seconds = np.mod((utc_time - utc_time[0] - hours * 3600.0 -
                      (dates - date_i) * 86400. - minutes * 60.0),
                     60.).astype(np.int)

    date_list = []
    years = np.ones(dates.__len__()) * years
    months = np.ones(dates.__len__()) * months
    for index, element in enumerate(
            zip(years, months, dates, hours, minutes, seconds)):
        date_list.append(
            str(int(element[0])) + '-' + str(int(element[1])) + '-' +
            str(int(element[2])) + ' ' + str(int(element[3])) + ':' +
            str(int(element[4])) + ':' + str(element[5]))
    a_date = atime(date_list)
    xacc = dd_aird_i.xacc.compute().to_numpy()
    yacc = dd_aird_i.yacc.compute().to_numpy()
    zacc = dd_aird_i.zacc.compute().to_numpy()
    gcrs = coor.GCRS(x=xacc,
                     y=yacc,
                     z=zacc,
                     representation_type='cartesian',
                     obstime=a_date)
    itrs = gcrs.transform_to(coor.ITRS(obstime=a_date))

    itrs = np.asarray(itrs.cartesian.xyz)

    plt.style.use(['science', 'no-latex', 'high-vis'])
    fig, ax = plt.subplots(figsize=(15, 8))
    plt.plot(utc_time, itrs[0], linewidth=2, label='xacc_gcrs')
    plt.plot(utc_time, itrs[1], linewidth=2, label='yacc_gcrs')
    plt.plot(utc_time, itrs[2], linewidth=2, label='zacc_gcrs')
    plt.tick_params(labelsize=25, width=2.9)
    ax.yaxis.get_offset_text().set_fontsize(24)
    ax.xaxis.get_offset_text().set_fontsize(24)
    plt.xlabel('GPS time [s]', fontsize=20)
    plt.ylabel('$Air \quad drag \quad accelaration [km/s^2]$', fontsize=20)
    # plt.legend(fontsize=20, loc='best')
    plt.legend(fontsize=20,
               loc='lower left',
               bbox_to_anchor=(0, 1, 1, .1),
               ncol=3,
               mode='expand')
    plt.grid(True, which='both', ls='dashed', color='0.5', linewidth=0.6)
    plt.gca().spines['left'].set_linewidth(2)
    plt.gca().spines['top'].set_linewidth(2)
    plt.gca().spines['right'].set_linewidth(2)
    plt.gca().spines['bottom'].set_linewidth(2)
    plt.savefig('..//images//air_drag_itrs.png', dpi=500)
    plt.show()
Example #22
0
def latlon_from_cartrep(cartRep, CURRTIME):
    gcrs = coord.GCRS(cartRep, obstime=CURRTIME) # cast xyz coordinate in ECI frame
    itrs = gcrs.transform_to(coord.ITRS(obstime=CURRTIME))
    return itrs.spherical.lat.value, itrs.spherical.lon.value
Example #23
0
        0.0,
        0.0,
        ecc,
        argp,
        inc,
        m_ano,
        m_mot,
        raan,
    )
    errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2)
    if errorCode != 0:
        raise RuntimeError(SGP4_ERRORS[errorCode])

    # Convert state vector from TEME (True Equator Mean Equinox) to ITRS
    pTEME = coord.CartesianRepresentation(rTEME * u.km)
    vTEME = coord.CartesianDifferential(vTEME * u.km / u.s)
    svTEME = TEME(pTEME.with_differentials(vTEME), obstime=iss.epoch)
    svITRS = svTEME.transform_to(coord.ITRS(obstime=iss.epoch))
    sv = Orbit.from_coords(Earth, svITRS)

    # Display results
    print("State vector [rv2el]")
    print(f"     r = {sv.r}")
    print(f"     v = {sv.v}")
    print()

    print("State vector differences [poliastro - rv2el]")
    print(f"    dr = {iss.r - sv.r}")
    print(f"    dv = {iss.v - sv.v}")
    print()
Example #24
0
def test_compare_with_forward_model():
    dp = make_example_datapack(5, 24, 1, clobber=True)
    with dp:
        select = dict(pol=slice(0, 1, 1), ant=slice(0, None, 1))
        dp.current_solset = 'sol000'
        dp.select(**select)
        tec_mean, axes = dp.tec
        tec_mean = tec_mean[0, ...]
        patch_names, directions = dp.get_directions(axes['dir'])
        antenna_labels, antennas = dp.get_antennas(axes['ant'])
        timestamps, times = dp.get_times(axes['time'])

    antennas = ac.ITRS(*antennas.cartesian.xyz, obstime=times[0])
    ref_ant = antennas[0]
    earth_centre = ac.ITRS(x=0 * au.m,
                           y=0 * au.m,
                           z=0. * au.m,
                           obstime=times[0])
    frame = ENU(obstime=times[0], location=ref_ant.earth_location)
    antennas = antennas.transform_to(frame)
    earth_centre = earth_centre.transform_to(frame)
    ref_ant = antennas[0]
    directions = directions.transform_to(frame)
    x = antennas.cartesian.xyz.to(au.km).value.T[20:21, :]
    k = directions.cartesian.xyz.value.T
    X = make_coord_array(x, k)
    x0 = ref_ant.cartesian.xyz.to(au.km).value
    earth_centre = earth_centre.cartesian.xyz.to(au.km).value
    bottom = 200.
    width = 50.
    l = 10.
    sigma = 1.
    fed_kernel_params = dict(l=l, sigma=sigma)
    S_marg = 1000
    fed_kernel = M12()

    def get_points_on_rays(X):
        x = X[0:3]
        k = X[3:6]
        smin = (bottom - (x[2] - x0[2])) / k[2]
        smax = (bottom + width - (x[2] - x0[2])) / k[2]
        ds = (smax - smin)
        _x = x + k * smin
        _k = k * ds
        t = jnp.linspace(0., 1., S_marg + 1)
        return _x + _k * t[:, None], ds / S_marg

    points, ds = vmap(get_points_on_rays)(X)
    points = points.reshape((-1, 3))
    plt.scatter(points[:, 1], points[:, 2], marker='.')
    plt.show()

    K = fed_kernel(points, points, l, sigma)
    plt.imshow(K)
    plt.show()
    L = jnp.linalg.cholesky(K + 1e-6 * jnp.eye(K.shape[0]))
    Z = L @ random.normal(random.PRNGKey(1245214), (L.shape[0], 3000))
    Z = Z.reshape((directions.shape[0], -1, Z.shape[1]))
    Y = jnp.sum(Z * ds[:, None, None], axis=1)
    K = jnp.mean(Y[:, None, :] * Y[None, :, :], axis=2)
    # print("Directly Computed TEC Covariance",K)
    plt.imshow(K)
    plt.colorbar()
    plt.title("Directly Computed TEC Covariance")
    plt.show()

    # kernel = TomographicKernel(x0, x0,fed_kernel, S_marg=200, compute_tec=False)
    # K = kernel(X, X, bottom, width, fed_kernel_params)
    # plt.imshow(K)
    # plt.colorbar()
    # plt.title("Analytic Weighted TEC Covariance")
    # plt.show()
    #
    # print("Analytic Weighted TEC Covariance",K)
    # print(x0, earth_centre, fed_kernel)
    kernel = TomographicKernel(x0,
                               earth_centre,
                               fed_kernel,
                               S_marg=200,
                               compute_tec=True)
    # print(X)
    X1 = GeodesicTuple(x=X[:, 0:3],
                       k=X[:, 3:6],
                       t=jnp.zeros_like(X[:, :1]),
                       ref_x=x0)
    print(X1)
    K = kernel(X1, X1, bottom, width, fed_kernel_params)
    plt.imshow(K)
    plt.colorbar()
    plt.title("Analytic TEC Covariance")
    plt.show()
    print("Analytic TEC Covariance", K)
Example #25
0
    def visualise_grid(self):
        for d in range(0, 5):
            with DataPack(self._input_datapack, readonly=True) as dp:
                dp.current_solset = 'sol000'
                dp.select(pol=slice(0, 1, 1), dir=d, time=0)
                tec_grid, axes = dp.tec
                tec_grid = tec_grid[0]
                patch_names, directions_grid = dp.get_directions(axes['dir'])
                antenna_labels, antennas_grid = dp.get_antennas(axes['ant'])
                ref_ant = antennas_grid[0]
                timestamps, times_grid = dp.get_times(axes['time'])
                frame = ENU(location=ref_ant.earth_location,
                            obstime=times_grid[0])
                antennas_grid = ac.ITRS(
                    *antennas_grid.cartesian.xyz,
                    obstime=times_grid[0]).transform_to(frame)

            ant_pos = antennas_grid.cartesian.xyz.to(au.km).value.T
            plt.scatter(ant_pos[:, 0],
                        ant_pos[:, 1],
                        c=tec_grid[0, :, 0],
                        cmap=plt.cm.PuOr)
            plt.xlabel('East [km]')
            plt.ylabel("North [km]")
            plt.title(f"Direction {repr(directions_grid)}")
            plt.show()

        ant_scatter_args = (ant_pos[:, 0], ant_pos[:, 1], tec_grid[0, :, 0])

        for a in [0, 50, 150, 200, 250]:
            with DataPack(self._input_datapack, readonly=True) as dp:
                dp.current_solset = 'sol000'
                dp.select(pol=slice(0, 1, 1), ant=a, time=0)
                tec_grid, axes = dp.tec
                tec_grid = tec_grid[0]
                patch_names, directions_grid = dp.get_directions(axes['dir'])
                antenna_labels, antennas_grid = dp.get_antennas(axes['ant'])
                timestamps, times_grid = dp.get_times(axes['time'])
                frame = ENU(location=ref_ant.earth_location,
                            obstime=times_grid[0])
                antennas_grid = ac.ITRS(
                    *antennas_grid.cartesian.xyz,
                    obstime=times_grid[0]).transform_to(frame)

            _ant_pos = antennas_grid.cartesian.xyz.to(au.km).value.T[0]

            fig, axs = plt.subplots(2, 1, figsize=(4, 8))
            axs[0].scatter(*ant_scatter_args[0:2],
                           c=ant_scatter_args[2],
                           cmap=plt.cm.PuOr,
                           alpha=0.5)
            axs[0].scatter(*_ant_pos[0:2], marker='x', c='red')
            axs[0].set_xlabel('East [km]')
            axs[0].set_ylabel('North [km]')
            pos = 180 / np.pi * np.stack(
                [wrap(directions_grid.ra.rad),
                 wrap(directions_grid.dec.rad)],
                axis=-1)
            plot_vornoi_map(pos, tec_grid[:, 0, 0], fov_circle=True, ax=axs[1])
            axs[1].set_xlabel('RA(2000) [ded]')
            axs[1].set_ylabel('DEC(2000) [ded]')
            plt.show()