Ejemplo n.º 1
0
    def reference_plane(self, time):
        """Compute the orbit at specified times in the two-body barycentric
        frame aligned with the reference plane coordinate system (XYZ).

        Parameters
        ----------
        time : array_like, `astropy.time.Time`
            Array of times as barycentric MJD values, or an Astropy
            `~astropy.time.Time` object containing the times to evaluate at.
        """

        xyz = self.orbital_plane(time)
        vxyz = xyz.differentials['s']
        xyz = xyz.without_differentials()

        # Construct rotation matrix to take the orbit from the orbital plane
        # system (xyz) to the reference plane system (XYZ):
        R1 = rotation_matrix(-self.omega, axis='z')
        R2 = rotation_matrix(self.i, axis='x')
        R3 = rotation_matrix(self.Omega, axis='z')
        Rot = matrix_product(R3, R2, R1)

        # Rotate to the reference plane system
        XYZ = coord.CartesianRepresentation(matrix_product(Rot, xyz.xyz))
        VXYZ = coord.CartesianDifferential(matrix_product(Rot, vxyz.d_xyz))
        XYZ = XYZ.with_differentials(VXYZ)

        kw = dict()
        if self.barycenter is not None:
            kw['origin'] = self.barycenter.origin
        return ReferencePlaneFrame(XYZ, **kw)
Ejemplo n.º 2
0
def get_galactocentric2019():
    """
    References
    ----------
    Galactic center sky position:
    - `Reid & Brunthaler (2004) <https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R/abstract>`_

    Galactic center distance:
    - `GRAVITY collaboration (2018) <https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G/abstract>`_

    Solar velocity:
    - `Drimmel & Poggio (2018) <https://ui.adsabs.harvard.edu/abs/2018RNAAS...2d.210D/abstract>`_
    - `Reid & Brunthaler (2004) <https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R/abstract>`_
    - `GRAVITY collaboration (2018) <https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G/abstract>`_

    Solar height above midplane:
    - `Bennett & Bovy (2019) <https://ui.adsabs.harvard.edu/abs/2019MNRAS.482.1417B/abstract>`_

    Returns
    -------
    galcen_frame : `~astropy.coordinates.Galactocentric`
        The modern (2019) Galactocentric reference frame.

    """
    rsun = 8.122 * u.kpc
    vsun = coord.CartesianDifferential([12.9, 245.6, 7.78] * u.km / u.s)
    zsun = 20.8 * u.pc

    return coord.Galactocentric(galcen_distance=rsun,
                                galcen_v_sun=vsun,
                                z_sun=zsun)
Ejemplo n.º 3
0
def correct_pm0(ra, dec, pmra, pmdec, dist, vlsr=vlsr0, vz=0):
    """Corrects the proper motion for the speed of the Sun
    Arguments:
        ra - RA in deg
        dec -- Declination in deg
        pmra -- pm in RA in mas/yr
        pmdec -- pm in declination in mas/yr
        dist -- distance in kpc
    Returns:
        (pmra,pmdec) the tuple with the proper motions corrected for the Sun's motion
    """
    C = acoo.ICRS(ra=ra * auni.deg,
                  dec=dec * auni.deg,
                  radial_velocity=0 * auni.km / auni.s,
                  distance=dist * auni.kpc,
                  pm_ra_cosdec=pmra * auni.mas / auni.year,
                  pm_dec=pmdec * auni.mas / auni.year)
    kw = dict(galcen_v_sun=acoo.CartesianDifferential(
        np.array([11.1, vlsr + 12.24, vz + 7.25]) * auni.km / auni.s))
    frame = acoo.Galactocentric(**kw)
    Cg = C.transform_to(frame)
    Cg1 = acoo.Galactocentric(x=Cg.x,
                              y=Cg.y,
                              z=Cg.z,
                              v_x=Cg.v_x * 0,
                              v_y=Cg.v_y * 0,
                              v_z=Cg.v_z * 0,
                              **kw)
    C1 = Cg1.transform_to(acoo.ICRS())
    return ((C.pm_ra_cosdec - C1.pm_ra_cosdec).to_value(auni.mas / auni.year),
            (C.pm_dec - C1.pm_dec).to_value(auni.mas / auni.year))
Ejemplo n.º 4
0
    def evaluate(
        x: u.kpc,
        y: u.kpc,
        z: u.kpc,
        v_x: u.km / u.s,
        v_y: u.km / u.s,
        v_z: u.km / u.s,
    ):
        # TODO using actual mechanics of transformation
        d_xyz = coord.CartesianDifferential(d_x=v_x, d_y=v_y, d_z=v_z)
        xyz = coord.CartesianRepresentation(x=x, y=y, z=z, differentials=d_xyz)

        sph = xyz.represent_as(
            coord.SphericalRepresentation,
            differential_class=coord.SphericalDifferential,
        )
        d_sph = sph.differentials["s"]

        return (
            sph.lon,
            sph.lat,
            sph.distance,
            d_sph.d_lon,
            d_sph.d_lat,
            d_sph.d_distance,
        )
Ejemplo n.º 5
0
def get_gc_frame():
    v_sun = coord.CartesianDifferential([11.1, 250, 7.25] * u.km / u.s)
    #gc_frame = coord.Galactocentric(galcen_distance=8.3*u.kpc,
    #                                z_sun=0*u.pc,
    #                                galcen_v_sun=v_sun)
    gc_frame = coord.Galactocentric()
    return gc_frame
    def setup_class(cls):
        """Setup fixtures for testing."""
        cls.num = 40
        cls.affine = np.linspace(0, 10, num=cls.num) * u.Myr

        cls.rep = coord.CartesianRepresentation(
            x=np.linspace(0, 1, num=cls.num) * u.kpc,
            y=np.linspace(1, 2, num=cls.num) * u.kpc,
            z=np.linspace(2, 3, num=cls.num) * u.kpc,
            differentials=coord.CartesianDifferential(
                d_x=np.linspace(3, 4, num=cls.num) * u.km / u.s,
                d_y=np.linspace(4, 5, num=cls.num) * u.km / u.s,
                d_z=np.linspace(5, 6, num=cls.num) * u.km / u.s,
            ),
        )

        if cls.klass is icoord.InterpolatedRepresentationOrDifferential:

            class SubClass(cls.klass):
                pass  # so not abstract & can instantiate

            cls.inst = SubClass(cls.rep, affine=cls.affine)

        else:
            cls.inst = cls.klass(cls.rep, affine=cls.affine)
def test_infer_derivative_type():
    """Test ``_infer_derivative_type``."""
    # ----------------------------
    # Test when rep is a differential

    rep = coord.CartesianDifferential(d_x=1, d_y=2, d_z=3)
    dif = icoord._infer_derivative_type(rep, u.s)

    assert dif.__name__ == "GenericCartesian2ndDifferential"
    assert dif is gcoord.GenericCartesian2ndDifferential

    # ----------------------------
    # Test when non-time dif unit

    rep = coord.CartesianRepresentation(x=1, y=2, z=3)
    dif = icoord._infer_derivative_type(rep, u.deg)

    assert dif.__name__ == "GenericCartesianDifferential"
    assert dif is gcoord.GenericCartesianDifferential

    # ----------------------------
    # Test when Rep & time

    rep = coord.CartesianRepresentation(x=1, y=2, z=3)
    dif = icoord._infer_derivative_type(rep, u.s)

    assert dif is coord.CartesianDifferential
    def setup_class(cls):
        """Setup fixtures for testing."""
        cls.num = 40
        cls.affine = np.linspace(0, 10, num=cls.num) * u.Myr
        cls.frame = coord.Galactocentric

        cls.rep = coord.CartesianRepresentation(
            x=np.linspace(0, 1, num=cls.num) * u.kpc,
            y=np.linspace(1, 2, num=cls.num) * u.kpc,
            z=np.linspace(2, 3, num=cls.num) * u.kpc,
            differentials=coord.CartesianDifferential(
                d_x=np.linspace(3, 4, num=cls.num) * u.km / u.s,
                d_y=np.linspace(4, 5, num=cls.num) * u.km / u.s,
                d_z=np.linspace(5, 6, num=cls.num) * u.km / u.s,
            ),
        )

        cls.irep = icoord.InterpolatedRepresentation(
            cls.rep,
            affine=cls.affine,
        )

        cls.coord = cls.frame(cls.irep)
        cls.icoord = icoord.InterpolatedCoordinateFrame(cls.coord)

        cls.inst = cls.klass(cls.icoord)
Ejemplo n.º 9
0
def correct_vel(ra, dec, vel, vlsr=vlsr0):
    """Corrects the proper motion for the speed of the Sun
    Arguments:
        ra - RA in deg
        dec -- Declination in deg
        pmra -- pm in RA in mas/yr
        pmdec -- pm in declination in mas/yr
        dist -- distance in kpc
    Returns:
        (pmra,pmdec) the tuple with the proper motions corrected for the Sun's motion
    """

    C = acoo.ICRS(ra=ra * auni.deg,
                  dec=dec * auni.deg,
                  radial_velocity=vel * auni.km / auni.s,
                  distance=np.ones_like(vel) * auni.kpc,
                  pm_ra_cosdec=np.zeros_like(vel) * auni.mas / auni.year,
                  pm_dec=np.zeros_like(vel) * auni.mas / auni.year)
    #frame = acoo.Galactocentric (galcen_vsun = np.array([ 11.1, vlsr+12.24, 7.25])*auni.km/auni.s)
    kw = dict(galcen_v_sun=acoo.CartesianDifferential(
        np.array([11.1, vlsr + 12.24, 7.25]) * auni.km / auni.s))
    frame = acoo.Galactocentric(**kw)
    Cg = C.transform_to(frame)
    Cg1 = acoo.Galactocentric(x=Cg.x,
                              y=Cg.y,
                              z=Cg.z,
                              v_x=Cg.v_x * 0,
                              v_y=Cg.v_y * 0,
                              v_z=Cg.v_z * 0,
                              **kw)
    C1 = Cg1.transform_to(acoo.ICRS)
    return np.asarray(((C.radial_velocity - C1.radial_velocity) /
                       (auni.km / auni.s)).decompose())
Ejemplo n.º 10
0
def pmlb_solar_correction(l, b, dist, pml, pmb, vsun=(11.1, 12.2, 7.25), vlsr=235, vrad=0):

	vsun=np.array(vsun)
	vsun[1]=vsun[1]+vlsr


	c = coord.SkyCoord(l=l*u.deg, b=b*u.deg, distance=dist*u.kpc, pm_l_cosb=pml*u.mas/u.yr, pm_b=pmb*u.mas/u.yr, radial_velocity=0*u.km/u.s, frame='galactic')
	vsun = coord.CartesianDifferential(vsun*u.km/u.s)
	gc_frame = coord.Galactocentric(galcen_v_sun=vsun, z_sun=0*u.kpc)
	ccorr=gala.reflex_correct(c,gc_frame)

	return ccorr.pm_l_cosb.value, ccorr.pm_b.value
    def setup_class(cls):
        """Setup fixtures for testing."""
        cls.num = 40
        cls.affine = np.linspace(0, 10, num=cls.num) * u.Myr

        cls.rep = coord.CartesianDifferential(
            d_x=np.linspace(3, 4, num=cls.num) * u.km / u.s,
            d_y=np.linspace(4, 5, num=cls.num) * u.km / u.s,
            d_z=np.linspace(5, 6, num=cls.num) * u.km / u.s,
        )

        cls.inst = cls.klass(rep=cls.rep, affine=cls.affine)
Ejemplo n.º 12
0
def get_solar_and_R_gal():
    # Set up Solar position and motion.
    sun_xyz = [-8.122, 0, 0] * u.kpc
    sun_vxyz = [12.9, 245.6, 7.78] * u.km/u.s
    sun_vxyzCD = coord.CartesianDifferential(12.9, 245.6, 7.78, u.km/u.s)

    galcen_frame = coord.Galactocentric(galcen_distance=np.abs(sun_xyz[0]),
                                        galcen_v_sun=sun_vxyzCD,
                                        z_sun=sun_xyz[2].value*1e3*u.pc)

    # Rotation matrix from Galactocentric to ICRS
    R_gal, _ = get_matrix_vectors(galcen_frame, inverse=True)
    return sun_xyz, sun_vxyz, R_gal, galcen_frame
Ejemplo n.º 13
0
def pmradec_solar_correction(ra, dec, dist, pmra, pmdec,vsun=(11.1, 12.2, 7.25),vlsr=235, vrad=0):

	vsun=np.array(vsun)
	vsun[1]=vsun[1]+vlsr


	c = coord.SkyCoord(ra=ra*u.deg, dec=dec*u.deg, distance=dist*u.kpc, pm_ra_cosdec=pmra*u.mas/u.yr, pm_dec=pmdec*u.mas/u.yr, radial_velocity=0*u.km/u.s)

	vsun = coord.CartesianDifferential(vsun*u.km/u.s)
	gc_frame = coord.Galactocentric(galcen_v_sun=vsun, z_sun=0*u.kpc)
	ccorr=gala.reflex_correct(c,gc_frame)

	return ccorr.pm_ra_cosdec.value, ccorr.pm_dec.value
Ejemplo n.º 14
0
def gc(ra, dec, p, pmra, pmdec, rv):

    # Coordinate transformation (ICRS to Galactic)
    coordinates = coord.ICRS(ra=np.multiply(ra, u.degree), dec=np.multiply(dec, u.degree), distance=(list(p.values) * u.mas).to(u.pc, u.parallax()), pm_ra_cosdec=np.multiply(pmra, u.mas/u.yr), pm_dec=np.multiply(pmdec, u.mas/u.yr), radial_velocity=np.multiply(rv, u.km/u.s))


    # Returns (x, y, z) spatial coordinates wrt galactic center, thus distance is the square difference
    # Returns (v_x, v_y, v_z) velocity coordinates wrt galactic center, thus velocity is the square difference

    # Velocity of the Sun
    v_sun = coord.CartesianDifferential([12.4, 236, 7.7]*u.km/u.s)
    
    # Galactocentric coordinates
    return coordinates.transform_to(coord.Galactocentric(galcen_distance=8 * u.kpc, galcen_v_sun=v_sun, z_sun=17 * u.pc))
Ejemplo n.º 15
0
    def __call__(self,
                 n: int = 1,
                 representation_type: TH.OptRepresentationLikeType = None,
                 random: RandomLike = None,
                 **kwargs) -> TH.SkyCoordType:
        """Sample.

        Parameters
        ----------
        n : int
            number of samples
        frame : frame-like or None
            output frame of samples
        **kwargs:
            ignored.

        Returns
        -------
        SkyCoord

        """
        # Get preferred frame and representation
        frame = self.frame
        representation_type = self._infer_representation(representation_type)

        # TODO accepts a potential parameter. what does this do?
        # TODO confirm random seed.
        with self._random_context(random):
            pos, masses = self._potential.sample(n=n)

        # process the position and mass
        if np.shape(pos)[1] == 6:
            pos, vel = pos[:, :3], pos[:, 3:]  # TODO: vel
            differentials = dict(s=coord.CartesianDifferential(*vel.T * u.km /
                                                               u.s), )
        else:
            differentials = None
        rep = coord.CartesianRepresentation(*pos.T * u.kpc,
                                            differentials=differentials)

        if representation_type is None:
            representation_type = rep.__class__
        samples = SkyCoord(
            frame.realize_frame(rep, representation_type=representation_type),
            copy=False,
        )
        samples.cache["mass"] = masses * u.solMass
        samples.cache["potential"] = self.potential

        return samples
Ejemplo n.º 16
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
Ejemplo n.º 17
0
def _add_galactic_cartesian_data(input_data, reverse=False, gal_coor=True):
    """

    :param input_data:
    :param reverse:
    :param gal_coor:
    :return:
    """
    output_data = deepcopy(input_data)
    # input ra/dec coordinates of object(s)
    ra_dec = coord.ICRS(ra=input_data['ra'] * un.deg,
                        dec=input_data['dec'] * un.deg,
                        distance=1e3 / input_data['parallax'] * un.pc,
                        pm_ra_cosdec=input_data['pmra'] * un.mas / un.yr,
                        pm_dec=input_data['pmdec'] * un.mas / un.yr,
                        radial_velocity=input_data['rv'] * un.km / un.s)
    # convert to galactic cartesian values
    if not gal_coor:
        cartesian_coord = ra_dec.transform_to(coord.Galactic).cartesian
    else:
        # again same velocities and distances as used by JBH in his paper
        v_sun = coord.CartesianDifferential([11., 238. + 10., 7.25] * un.km /
                                            un.s)
        gc_frame = coord.Galactocentric(galcen_distance=8.2 * un.kpc,
                                        galcen_v_sun=v_sun,
                                        z_sun=25 * un.pc)
        cartesian_coord = ra_dec.transform_to(gc_frame).cartesian
    # store computed positional values back to the
    output_data['x'] = cartesian_coord.x.value
    output_data['y'] = cartesian_coord.y.value
    output_data['z'] = cartesian_coord.z.value
    # get differential (velocities) cartesian values
    cartesian_vel = cartesian_coord.differentials
    cartesian_vel = cartesian_vel[list(cartesian_vel.keys())[0]]
    # convert them to pc/yr for easier computation
    if reverse:
        vel_multi = -1.
    else:
        vel_multi = 1.
    output_data['d_x'] = vel_multi * cartesian_vel.d_x.to(un.pc / un.yr).value
    output_data['d_y'] = vel_multi * cartesian_vel.d_y.to(un.pc / un.yr).value
    output_data['d_z'] = vel_multi * cartesian_vel.d_z.to(un.pc / un.yr).value

    return output_data
Ejemplo n.º 18
0
def getXYZUVW(ra,
              dec,
              distance,
              pm_ra_cosdec,
              pm_dec,
              radial_velocity,
              v_sun=pmsun,
              galcen_distance=Rs):
    #degree,degree,kpc,mas/yr,mas/yr,km/s,km/s,kpc
    c1=coord.ICRS(ra=ra*u.degree,dec=dec*u.degree,distance=distance*u.kpc,\
        pm_ra_cosdec=pm_ra_cosdec*u.mas/u.yr,pm_dec=pm_dec*u.mas/u.yr,\
        radial_velocity=radial_velocity*u.km/u.s)

    gc_frame=coord.Galactocentric(galcen_distance=galcen_distance*u.kpc,\
        galcen_v_sun=coord.CartesianDifferential(v_sun*u.km/u.s))
    gc2 = c1.transform_to(gc_frame)
    #kpc,kpc,kpc,km/s,km/s,km/s
    return [
        gc2.x.value, gc2.y.value, gc2.z.value, gc2.v_x.value, gc2.v_y.value,
        gc2.v_z.value
    ]
Ejemplo n.º 19
0
def test_reflex():
    c = coord.SkyCoord(ra=162 * u.deg,
                       dec=-17 * u.deg,
                       distance=172 * u.pc,
                       pm_ra_cosdec=-11 * u.mas / u.yr,
                       pm_dec=4 * u.mas / u.yr,
                       radial_velocity=110 * u.km / u.s)

    # First, test execution but don't validate
    reflex_correct(c)
    with coord.galactocentric_frame_defaults.set('v4.0'):
        reflex_correct(c, coord.Galactocentric(z_sun=0 * u.pc))

    # Reflext correct the observed, Reid & Brunthaler (2004) Sgr A* measurements
    # and make sure the corrected velocity is close to zero
    # https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R/abstract
    # also using
    # https://ui.adsabs.harvard.edu/abs/2018RNAAS...2d.210D/abstract
    # https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G/abstract
    vsun = coord.CartesianDifferential([12.9, 245.6, 7.78] * u.km / u.s)
    with coord.galactocentric_frame_defaults.set('v4.0'):
        galcen_fr = coord.Galactocentric(galcen_distance=8.122 * u.kpc,
                                         galcen_v_sun=vsun,
                                         z_sun=20.8 * u.pc)

    sgr_Astar_obs = coord.SkyCoord(ra=galcen_fr.galcen_coord.ra,
                                   dec=galcen_fr.galcen_coord.dec,
                                   distance=galcen_fr.galcen_distance,
                                   pm_ra_cosdec=-3.151 * u.mas / u.yr,
                                   pm_dec=-5.547 * u.mas / u.yr,
                                   radial_velocity=-12.9 * u.km / u.s)

    new_c = reflex_correct(sgr_Astar_obs, galcen_fr)
    assert u.allclose(new_c.pm_ra_cosdec,
                      0 * u.mas / u.yr,
                      atol=1e-2 * u.mas / u.yr)
    assert u.allclose(new_c.pm_dec, 0 * u.mas / u.yr, atol=1e-2 * u.mas / u.yr)
    assert u.allclose(new_c.radial_velocity,
                      0 * u.km / u.s,
                      atol=1e-1 * u.km / u.s)
Ejemplo n.º 20
0
    def orbital_plane(self, time):
        """Compute the orbit at specified times in the two-body barycentric
        frame aligned with the orbital plane (xyz).

        Parameters
        ----------
        time : array_like, `astropy.time.Time`
            Array of times as barycentric MJD values, or an Astropy
            `~astropy.time.Time` object containing the times to evaluate at.
        """

        # mean anomaly
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            M = 2*pi * (time.tcb - self.t0.tcb) / self.P - self.M0
            M = M.to(u.radian)

        # eccentric anomaly
        E = eccentric_anomaly_from_mean_anomaly(M, self.e)

        # true anomaly
        f = true_anomaly_from_eccentric_anomaly(E, self.e)

        # distance from center of mass to orbiting body
        r = self.a * (1. - self.e * np.cos(E))

        # compute the orbit in the cartesian, orbital plane system (xyz):
        x = r * np.cos(f)
        y = r * np.sin(f)
        z = np.zeros_like(x)

        fac = 2*pi * self.a / self.P / np.sqrt(1 - self.e**2)
        vx = -fac * np.sin(f)
        vy = fac * (np.cos(f) + self.e)
        vz = np.zeros_like(vx)

        xyz = coord.CartesianRepresentation(x=x, y=y, z=z)
        vxyz = coord.CartesianDifferential(d_x=vx, d_y=vy, d_z=vz)

        return xyz.with_differentials(vxyz)
Ejemplo n.º 21
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
Ejemplo n.º 22
0
    icrs = coord.ICRS(ra=star["ra"] * u.deg,
                      dec=star["dec"] * u.deg,
                      distance=1.0 / star["parallax"] * u.kpc,
                      pm_ra_cosdec=star["pmra"] * u.mas / u.yr,
                      pm_dec=star["pmdec"] * u.mas / u.yr,
                      radial_velocity=star['radial_velocity'] * u.km / u.s)
    """
  icrs_err = coord.ICRS(ra=0*u.deg, dec=0*u.deg, distance=6*u.kpc,
                      pm_ra_cosdec=0.009*u.mas/u.yr,
                      pm_dec=0.009*u.mas/u.yr,
                      radial_velocity=0.1*u.km/u.s)

  """

    v_sun = coord.CartesianDifferential([0, 0, 0] * u.km / u.s)
    gc_frame = coord.Galactocentric(galcen_distance=8.3 * u.kpc,
                                    z_sun=0 * u.pc,
                                    galcen_v_sun=v_sun)

    gc = icrs.transform_to(gc_frame)

    w0 = gd.PhaseSpacePosition(gc.data)

    if (star["Ba_only_candidate"] == 'true'
            and star["Ba_Sr_candidate"] == 'false'):

        Ba_velx.append(w0.v_x.to(u.km / u.s).value)
        Ba_vely.append(w0.v_y.to(u.km / u.s).value)
        Ba_velz.append(w0.v_z.to(u.km / u.s).value)
        Ba_y.append(np.sqrt(Ba_velx[-1]**2 + Ba_velz[-1]**2))
print(gc1.v_x, gc1.v_y, gc1.v_z)

##############################################################################
# The default parameters for the `~astropy.coordinates.Galactocentric` frame
# are detailed in the linked documentation, but we can modify the most commonly
# changes values using the keywords ``galcen_distance``, ``galcen_v_sun``, and
# ``z_sun`` which set the sun-Galactic center distance, the 3D velocity vector
# of the sun, and the height of the sun above the Galactic midplane,
# respectively. The velocity of the sun must be specified as a
# `~astropy.coordinates.CartesianDifferential` instance, as in the example
# below. Note that, as with the positions, the Galactocentric frame is a
# right-handed system - the x-axis is positive towards the Galactic center, so
# ``v_x`` is opposite of the Galactocentric radial velocity:

v_sun = coord.CartesianDifferential([11.1, 244, 7.25] * u.km / u.s)
gc_frame = coord.Galactocentric(galcen_distance=8 * u.kpc,
                                galcen_v_sun=v_sun,
                                z_sun=0 * u.pc)

##############################################################################
# We can then transform to this frame instead, with our custom parameters:

gc2 = c1.transform_to(gc_frame)
print(gc2.v_x, gc2.v_y, gc2.v_z)

##############################################################################
# It's sometimes useful to specify the solar motion using the `proper motion
# of Sgr A* <https://arxiv.org/abs/astro-ph/0408107>`_ instead of Cartesian
# velocity components. With an assumed distance, we can convert proper motion
# components to Cartesian velocity components using `astropy.units`:
Ejemplo n.º 24
0
                      pm_dec=pm_dec,
                      radial_velocity=rv)


def compute_orbit(icrs, dt=-0.1 * u.Myr, n_steps=50000):
    """Integrate the orbit."""
    c_icrs = icrs.transform_to(gc_frame).cartesian
    object_phase_space = gd.PhaseSpacePosition(
        pos=c_icrs.xyz, vel=c_icrs.differentials['s'].d_xyz)
    return gp.Hamiltonian(pot).integrate_orbit(object_phase_space,
                                               dt=dt,
                                               n_steps=n_steps)


pot = gp.MilkyWayPotential()
v_sun = coord.CartesianDifferential([11, 248, 7.25] * u.km / u.s)
gc_frame = coord.Galactocentric(galcen_distance=8.2 * u.kpc,
                                z_sun=25. * u.pc,
                                galcen_v_sun=v_sun)

icrs = coord.ICRS(ra=262.806 * u.deg,
                  dec=-39.822 * u.deg,
                  distance=11.5 * u.kpc,
                  pm_ra_cosdec=-2.85 * u.mas / u.yr,
                  pm_dec=2.55 * u.mas / u.yr,
                  radial_velocity=227 * u.km / u.s)
icrs_err = coord.ICRS(ra=0 * u.deg,
                      dec=0 * u.deg,
                      distance=1. * u.kpc,
                      pm_ra_cosdec=0.1 * u.mas / u.yr,
                      pm_dec=0.1 * u.mas / u.yr,
Ejemplo n.º 25
0
nloop = args.n
dt = args.dt * u.Myr
noerr = args.no_errors
node = args.node
totnodes = args.tot

if (nproc > 1):
    print('multithreading activated, using ', nproc, ' processors')

# defines reference frame
rsun = 8 * u.kpc
zsun = 0.025 * u.kpc
vsun = [11.1, 232.24, 7.25] * u.km / u.s
gc_frame = coord.Galactocentric(
    galcen_distance=rsun,
    galcen_v_sun=coord.CartesianDifferential(*vsun),
    z_sun=zsun)

# load in data, load MW potential
with warnings.catch_warnings(record=True):
    warnings.simplefilter("ignore")
    gaiadata = GaiaData(filein)
    hdul = fits.open(filein)
    sttable = Table(hdul[1].data)
    if (totnodes > 1):
        thiskeys = np.array_split(range(len(sttable['source_id'])),
                                  totnodes)[node]
        gaiadata = gaiadata[thiskeys]
        sttable = sttable[thiskeys]
    mw = gp.MilkyWayPotential()
Ejemplo n.º 26
0
    axes[1, 0].set_xlabel('Pmra');
    axes[1, 1].hist(sample[:, 4], bins='fd')
    axes[1, 1].set_xlabel('Pmdec');
    axes[1, 2].hist(sample[:, 5], bins='fd')
    axes[1, 2].set_xlabel('RV');
    pp.savefig(bbox_inches='tight')
    pp.close()

assert np.all(sample[:, 2] > 0)

# Calculate dynamics
print('Get dynamics')
R0 = 8.34 * u.kpc  # Reid et al 2014
V0 = 240 * u.km/u.s  # Reid et al 2014
z_sun = 27 * u.pc  # Chen et al 2001
v_sun = coord.CartesianDifferential([11.1, -(240+12.24), 7.25] * u.km/u.s)  # Schonrich et al 2010
# NB: Here I just use the inverse parallax as dist
cs = coord.SkyCoord(ra=sample[:, 0] * u.deg,
        dec=sample[:, 1] * u.deg,
        distance=coord.Distance(parallax=sample[:, 2] * u.mas),
        pm_ra_cosdec=sample[:, 3] * u.mas / u.yr,
        pm_dec=sample[:, 4] * u.mas / u.yr,
        radial_velocity=sample[:, 5] * u.km / u.s,
        galcen_distance=R0,
        galcen_v_sun=v_sun,  
        z_sun=z_sun)

# Define Galactocentric frame
gc = coord.Galactocentric(galcen_distance=R0,
        galcen_v_sun=v_sun,  # 240 is from Reid etal 2014
        z_sun=z_sun)  # Default, Chen et al 2001
Ejemplo n.º 27
0
import matplotlib.patches as mp
from astropy.time import Time

#import plotting_dicts as pod

###########
#Galactic parameters from Gaia collaboration (D. Katz et al. 2018) "Mapping the Milky Way Disc Kinematics"
sun_height = 27. * u.pc
sun_dist = 8.34 * u.kpc
circular_v_at_sun = 240. * u.km / u.s
v_sun_pec = [11.1, 12.24, 7.25] * u.km / u.s
v_sun_bobylev = [
    7.90, 11.73, 7.39
] * u.km / u.s  #Bobylev 2017 value, used by Torres et al. 2019

v_sun_tot = coord.CartesianDifferential(
    [v_sun_pec[0], v_sun_pec[1] + circular_v_at_sun, v_sun_pec[2]])
v_sun_bobylev_diff = coord.CartesianDifferential(v_sun_bobylev)

gc_frame = coord.Galactocentric(galcen_distance=sun_dist,
                                galcen_v_sun=v_sun_tot,
                                z_sun=sun_height)

galcart = coord.Galactic(representation_type=coord.CartesianRepresentation,
                         differential_type=coord.CartesianDifferential)

#altGalacticLSR=coord.GalacticLSR(v_bary=v_sun_bobylev_diff)

altGalacticLSR = coord.GalacticLSR(v_bary=v_sun_bobylev_diff,
                                   differential_type='cartesian')

#galLSR_base=coord.GalacticLSR
Ejemplo n.º 28
0
def astrometric_excess_noise(t,
                             P,
                             m1,
                             m2,
                             f1=None,
                             f2=None,
                             e=0,
                             t0=None,
                             omega=0 * u.deg,
                             i=0 * u.deg,
                             Omega=0 * u.deg,
                             origin=None,
                             **kwargs):
    """
    Calculate the astrometric excess noise for a binary system with given
    properties that was observed at certain times from the given origin position.
    
    # TODO: There are a number of assumptions that we look over here

    :param t:
        The times that the system was observed.

    :param P:
        The period of the binary system.

    :param m1:
        The mass of the primary body.

    :param m2:
        The mass of the secondary body.

    :param f1: [optional]
        The flux of the primary body. If `None` is given then $M_1^{3.5}$ will
        be assumed.

    :param f2: [optional]
        The flux of the secondary body. If `None` is given then $M_2^{3.5}$ will
        be assumed.

    :param e: [optional]
        The eccentricity of the system (default: 0).

    # TODO: more docs pls
    """

    # TODO: Re-factor this behemoth by applying the weights after calculating positions?
    if f1 is None:
        f1 = m1.to(u.solMass).value**3.5
    if f2 is None:
        f2 = m2.to(u.solMass).value**3.5

    if t0 is None:
        t0 = Time('J2015.5')

    N = t.size

    # Compute orbital positions.
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        M1 = (2 * np.pi * (t.tcb - t0.tcb) / P).to(u.radian)
        # Set secondary to have opposite phase.
        M2 = (2 * np.pi * (t.tcb - t0.tcb) / P - np.pi).to(u.radian)

    # eccentric anomaly
    E1 = twobody.eccentric_anomaly_from_mean_anomaly(M1, e)
    E2 = twobody.eccentric_anomaly_from_mean_anomaly(M2, e)

    # mean anomaly
    F1 = twobody.true_anomaly_from_eccentric_anomaly(E1, e)
    F2 = twobody.true_anomaly_from_eccentric_anomaly(E2, e)

    # Calc a1/a2.
    m_total = m1 + m2
    a = twobody.P_m_to_a(P, m_total)
    a1 = m2 * a / m_total
    a2 = m1 * a / m_total

    r1 = (a1 * (1. - e * np.cos(E1))).to(u.au).value
    r2 = (a2 * (1. - e * np.cos(E2))).to(u.au).value

    # Calculate xy positions in orbital plane.
    x = np.vstack([
        r1 * np.cos(F1),
        r2 * np.cos(F2),
    ]).value
    y = np.vstack([r1 * np.sin(F1), r2 * np.sin(F2)]).value

    # Calculate photocenter in orbital plane.
    w = np.atleast_2d([f1, f2]) / (f1 + f2)
    x, y = np.vstack([w @ x, w @ y])
    z = np.zeros_like(x)

    # Calculate photocenter velocities in orbital plane.
    fac = (2 * np.pi * a / P / np.sqrt(1 - e**2)).to(u.au / u.s).value
    vx = np.vstack([-fac * np.sin(F1), -fac * np.sin(F2)]).value
    vy = np.vstack([fac * (np.cos(F1) + e), fac * (np.cos(F2) + e)]).value
    vx, vy = np.vstack([w @ vx, w @ vy])
    vz = np.zeros_like(vx)

    # TODO: handle units better w/ dot product
    x, y, z = (x * u.au, y * u.au, z * u.au)
    vx, vy, vz = (vx * u.au / u.s, vy * u.au / u.s, vz * u.au / u.s)

    xyz = coord.CartesianRepresentation(x=x, y=y, z=z)
    vxyz = coord.CartesianDifferential(d_x=vx, d_y=vy, d_z=vz)
    xyz = xyz.with_differentials(vxyz)

    vxyz = xyz.differentials["s"]
    xyz = xyz.without_differentials()

    # Construct rotation matrix from orbital plane system to reference plane system.
    R1 = rotation_matrix(-omega, axis='z')
    R2 = rotation_matrix(i, axis='x')
    R3 = rotation_matrix(Omega, axis='z')
    Rot = matrix_product(R3, R2, R1)

    # Rotate photocenters to the reference plane system.
    XYZ = coord.CartesianRepresentation(matrix_product(Rot, xyz.xyz))
    VXYZ = coord.CartesianDifferential(matrix_product(Rot, vxyz.d_xyz))
    XYZ = XYZ.with_differentials(VXYZ)

    barycenter = twobody.Barycenter(origin=origin, t0=t0)
    kw = dict(origin=barycenter.origin)
    rp = twobody.ReferencePlaneFrame(XYZ, **kw)

    # Calculate the ICRS positions.
    icrs_cart = rp.transform_to(coord.ICRS).cartesian
    icrs_pos = icrs_cart.without_differentials()
    icrs_vel = icrs_cart.differentials["s"]

    bary_cart = barycenter.origin.cartesian
    bary_vel = bary_cart.differentials["s"]

    dt = t - barycenter.t0
    dx = (bary_vel * dt).to_cartesian()

    pos = icrs_pos + dx
    vel = icrs_vel + bary_vel

    icrs = coord.ICRS(pos.with_differentials(vel))

    positions = np.array([icrs.ra.deg, icrs.dec.deg])

    mean_position = np.mean(positions, axis=1)
    assert mean_position.size == 2
    '''
    __intrinsic_ra_error = 0.029 # mas
    __intrinsic_dec_error = 0.026 # mas

    __intrinsic_ra_error /= 10
    __intrinsic_dec_error /= 10

    chi2 = N * rms_in_mas.to(u.mas).value**2 / np.sqrt(__intrinsic_ra_error**2 + __intrinsic_dec_error**2)

    approx_ruwe = np.sqrt(chi2/(N - 2))
    '''

    # Calculate on sky RMS.

    astrometric_rms = np.sqrt(np.sum((positions.T - mean_position)**2) / N)
    astrometric_rms *= u.deg

    diff = ((positions.T - mean_position) * u.deg).to(u.mas)
    #chi2 = diff**2 / (__intrinsic_ra_error**2 + __intrinsic_dec_error**2)
    ruwe = np.sqrt(
        np.sum((diff.T[0] / __intrinsic_ra_error)**2 +
               (diff.T[1] / __intrinsic_dec_error)**2) / (N - 2)).value

    meta = dict()
    return (ruwe, meta)
# Galactocentric position of the Sun:
X_GC_sun_kpc = 8.122  #[kpc] # (Gravity collaboration 2018)
Z_GC_sun_kpc = 0.025  #[kpc] (e.g. Juric et al. 2008)

# Galactocentric velocity of the Sun:
vX_GC_sun_kms = -11.1  # [km/s]   (e.g. Schoenrich et al. 2009)
vY_GC_sun_kms = 245.8  # [km/s]  (combined with Sgr A* proper motions from Reid & Brunnthaler 2004)
vZ_GC_sun_kms = 7.8  # [km/s]

# -------------------------------------------------------------------------------
# transformation
# -------------------------------------------------------------------------------

gc = coord.Galactocentric(
    galcen_distance=X_GC_sun_kpc * u.kpc,
    galcen_v_sun=coord.CartesianDifferential(
        [-vX_GC_sun_kms, vY_GC_sun_kms, vZ_GC_sun_kms] * u.km / u.s),
    z_sun=Z_GC_sun_kpc * u.kpc)

galcen = cs.transform_to(gc)
xs, ys, zs = galcen.x.to(u.kpc), galcen.y.to(u.kpc), galcen.z.to(u.kpc)
vxs, vys, vzs = galcen.v_x, galcen.v_y, galcen.v_z

XS = np.vstack([xs, ys, zs, vxs, vys, vzs]).T.value
Xlimits = [[-30, 10], [-10, 30], [-20, 20], [-200, 200], [-200, 200],
           [-200, 200]]
Xlabels = ['$x$', '$y$', '$z$', r'$v_x$', r'$v_y$', r'$v_z$']

d2d = np.sqrt(XS[:, 0]**2 + XS[:, 1]**2)
units = XS[:, 0:2] / d2d[:, None]
perps = np.zeros_like(units)
perps[:, 0] = units[:, 1]
Ejemplo n.º 30
0
#                         radial_velocity=-58.7*u.km/u.s)

# These are from fitting the sky track of the stream
pal5_c = coord.SkyCoord(phi1=0*u.deg,
                        phi2=1.53066768e-02*u.deg,
                        distance=22.4957324*u.kpc,
                        pm_phi1_cosphi2=3.07244231*u.mas/u.yr,
                        pm_phi2=0.637385934*u.mas/u.yr,
                        radial_velocity=-56.2232384*u.km/u.s,
                        frame=gc.Pal5PriceWhelan18).transform_to(coord.ICRS)
pal5_M = 14404 * u.Msun

# Setting Sun's params - should update distance
v_lsr = [11.1, 12.24, 7.25]*u.km/u.s
v_circ = 220 * u.km/u.s
v_sun = coord.CartesianDifferential(v_lsr + [0, 1, 0] * v_circ)
galcen_frame = coord.Galactocentric(galcen_distance=8.1*u.kpc,
                                    galcen_v_sun=v_sun)


trail_a = [230, 242]
trail_d = [0.75, 6.6]
trail_epts = coord.SkyCoord(ra=trail_a*u.deg, dec=trail_d*u.deg)

lead_a = [228, 225]
lead_d = [-1.2, -4.3]
lead_epts = coord.SkyCoord(ra=lead_a*u.deg, dec=lead_d*u.deg)

pal5_lead_frame = gc.GreatCircleICRSFrame.from_endpoints(lead_epts[0], lead_epts[1],
                                                         ra0=pal5_c.ra)
pal5_trail_frame = gc.GreatCircleICRSFrame.from_endpoints(trail_epts[0], trail_epts[1],