Beispiel #1
0
def isotropic_w0(N=100):
    # positions
    d = np.random.lognormal(mean=np.log(25), sigma=0.5, size=N)
    phi = np.random.uniform(0, 2 * np.pi, size=N)
    theta = np.arccos(np.random.uniform(size=N) - 0.5)

    vr = np.random.normal(150., 40., size=N) * u.km / u.s
    vt = np.random.normal(100., 40., size=N)
    vt = np.vstack((vt, np.zeros_like(vt))).T

    # rotate to be random position angle
    pa = np.random.uniform(0, 2 * np.pi, size=N)
    M = np.array([[np.cos(pa), -np.sin(pa)], [np.sin(pa), np.cos(pa)]]).T
    vt = np.array([vv.dot(MM) for (vv, MM) in zip(vt, M)]) * u.km / u.s
    vphi, vtheta = vt.T

    rep = coord.PhysicsSphericalRepresentation(r=d * u.dimensionless_unscaled,
                                               phi=phi * u.radian,
                                               theta=theta * u.radian)
    x = rep.represent_as(coord.CartesianRepresentation).xyz.T.value

    vr = vr.decompose(galactic).value * u.one
    vphi = vphi.decompose(galactic).value * u.one
    vtheta = vtheta.decompose(galactic).value * u.one

    vsph = coord.PhysicsSphericalDifferential(d_phi=vphi / (d * np.sin(theta)),
                                              d_theta=vtheta / d,
                                              d_r=vr)

    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        v = vsph.represent_as(coord.CartesianDifferential,
                              base=rep).d_xyz.value.T

    return np.hstack((x, v)).T
Beispiel #2
0
    def read_pop_fromhdf5(self, filename):
        """
		Read from an hdf5 file the cloud population. the :class:`Cloud_Population` is thus  initialized by :func:`initialize_cloud_population_from_output`
		"""
        f = h5.File(filename, 'r')
        g = f["Cloud_Population"]
        self.r = g["R"][...]
        self.phi = g["Phi"][...]
        self.L = g["Sizes"][...]
        self.W = g["Emissivity"][...]
        coord_array = np.zeros(self.n)
        if self.models[self.model] == 1:
            self.theta = g["Theta"][...]
            coord_array = coord.PhysicsSphericalRepresentation(
                self.phi * u.rad, self.theta * u.rad, self.r * u.kpc)
        elif self.models[self.model] >= 2:
            self.zeta = g["Z"][...]
            coord_array = coord.CylindricalRepresentation(
                self.r * u.kpc, self.phi * u.rad, self.zeta * u.kpc)
        self.d_sun = g["D_sun"][...]
        self.long = g["Gal_longitude"][...]
        self.lat = g["Gal_Latitude"][...]
        self.healpix_vecs = g["Healpix_Vec"][...]

        self.cartesian_galactocentric = self.cartesianize_coordinates(
            coord_array)
        from utilities.utilities_functions import bash_colors

        cols = bash_colors()
        f.close()
        print(cols.bold("////// \t read from " + filename + "\t ////////"))
        pass
Beispiel #3
0
def isotropic_w0(N=100):
    # positions
    d = np.random.lognormal(mean=np.log(25), sigma=0.5, size=N)
    phi = np.random.uniform(0, 2*np.pi, size=N)
    theta = np.arccos(np.random.uniform(size=N) - 0.5)

    vr = np.random.normal(150., 40., size=N)*u.km/u.s
    vt = np.random.normal(100., 40., size=N)
    vt = np.vstack((vt,np.zeros_like(vt))).T

    # rotate to be random position angle
    pa = np.random.uniform(0, 2*np.pi, size=N)
    M = np.array([[np.cos(pa), -np.sin(pa)],[np.sin(pa), np.cos(pa)]]).T
    vt = np.array([vv.dot(MM) for (vv,MM) in zip(vt,M)])*u.km/u.s
    vphi,vtheta = vt.T

    rep = coord.PhysicsSphericalRepresentation(r=d*u.dimensionless_unscaled,
                                               phi=phi*u.radian,
                                               theta=theta*u.radian)
    x = rep.represent_as(coord.CartesianRepresentation).xyz.T.value

    vr = vr.decompose(galactic).value
    vphi = vphi.decompose(galactic).value
    vtheta = vtheta.decompose(galactic).value
    v = physicsspherical_to_cartesian(rep, [vr,vphi,vtheta]*u.dimensionless_unscaled).T.value

    return np.hstack((x,v)).T
Beispiel #4
0
def rv_to_3d_isotropic(r, v):
    """Given radii and velocity magnitudes, generate a set of 6D initial
    conditions by assuming isotropy.

    Parameters
    ----------
    r : quantity_like [length]
        Radii.
    v : quantity_like [speed]
        Velocity magnidues.
    """

    phi = np.random.uniform(0, 2*np.pi, size=r.size) * u.radian
    theta = np.arccos(2*np.random.uniform(size=r.size) - 1) * u.radian
    sph = coord.PhysicsSphericalRepresentation(phi=phi, theta=theta, r=r)
    xyz = sph.represent_as(coord.CartesianRepresentation).xyz

    phi = np.random.uniform(0, 2*np.pi, size=r.size) * u.radian
    theta = np.arccos(2*np.random.uniform(size=r.size) - 1) * u.radian
    v_sph = coord.PhysicsSphericalRepresentation(phi=phi, theta=theta,
                                                 r=np.ones_like(v.value)*u.one)
    v_xyz = v * v_sph.represent_as(coord.CartesianRepresentation).xyz

    return gd.PhaseSpacePosition(pos=xyz, vel=v_xyz)
    def test_represent_as(self) -> None:
        """Test method ``represent_as``.

        Astropy tests the underlying method. Only need to test that
        it is interpolated.

        """
        # super().test_represent_as()

        rep = self.inst.represent_as(
            coord.PhysicsSphericalDifferential,
            base=coord.PhysicsSphericalRepresentation(
                0 * u.rad,
                0 * u.rad,
                0 * u.km,
            ),
        )

        assert isinstance(rep, coord.PhysicsSphericalDifferential)
        assert isinstance(rep, icoord.InterpolatedDifferential)
        assert isinstance(rep, self.klass)
Beispiel #6
0
    def __call__(self):

        self.clouds = []
        np.random.seed(11 + self.random_seed)

        a = np.random.uniform(low=0., high=1., size=self.n)
        self.phi = 2. * np.pi * a

        if self.model == 'Spherical':
            self.r = norm.rvs(loc=self.R_params[0],
                              scale=self.R_params[1],
                              size=self.n)

            v = np.random.uniform(low=0., high=1., size=self.n)
            self.theta = np.arccos(2. * v - 1.)

            coord_array = coord.PhysicsSphericalRepresentation(
                self.phi * u.rad, self.theta * u.rad, self.r * u.kpc)
            self.cartesian_galactocentric = self.cartesianize_coordinates(
                coord_array)
            self.heliocentric_coordinates()

            for i, x, p, t, d, latit, longit in zip(np.arange(self.n), self.r,
                                                    self.phi, self.theta,
                                                    self.d_sun, self.lat,
                                                    self.long):
                if x <= 0.:
                    self.r[i] = np.random.uniform(low=0., high=1., size=1)
                    x = self.r[i]
                c = Cloud(i, x, p, t, size=None, em=None)
                c.assign_sun_coord(d, latit, longit)
                self.clouds.append(c)

        else:
            self.r = self.phi * 0.
            rbar = self.R_params[2]

            if self.model == 'Axisymmetric':
                np.random.seed(self.random_seed + 29)
                self.r = norm.rvs(loc=self.R_params[0],
                                  scale=self.R_params[1],
                                  size=self.n)
                negs = np.ma.masked_less(self.r, 0.)
                #central molecular zone
                self.r[negs.mask] = 0.
            elif self.model == 'LogSpiral':
                #the bar is assumed axisymmetric and with an inclination angle phi0~25 deg as
                #it has been measured by  F*x et al. 1999

                phi_0 = np.deg2rad(25.)
                self.phi += phi_0
                subsize = np.int(self.n / 10)
                self.r[0:subsize] = norm.rvs(loc=self.R_params[0],
                                             scale=self.R_params[1],
                                             size=subsize)
                #np.random.uniform(low=0.,high=8.,size=self.n/4)
                rscale = rbar / 1.5
                self.r[subsize:self.n],self.phi[subsize:self.n]=log_spiral_radial_distribution2(\
                            rbar,phi_0,self.n-subsize,self.R_params[0],self.R_params[1])
                #self.r[subsize:self.n]=log_spiral_radial_distribution(self.phi[subsize:self.n],rbar,phi_0)
                #simulate the bar
                arr = np.ma.masked_less(self.r, rbar)
                self.r[arr.mask] = abs(
                    np.random.normal(loc=0.,
                                     scale=rscale,
                                     size=len(self.r[arr.mask])))
                negs = np.ma.masked_less(self.r, 0.)
                #central molecular zone
                self.r[negs.mask] = 0.

            #the thickness of the Galactic plane is function of the Galactic Radius roughly as ~ 100 pc *cosh((x/R0) ), with R0~10kpc
            # for reference see fig.6 of Heyer and Dame, 2015
            sigma_z0 = self.z_distr[0]
            R_z0 = self.z_distr[1]

            sigma_z = lambda R: sigma_z0 * np.cosh((R / R_z0))
            self.zeta = self.phi * 0.
            np.random.seed(self.random_seed + 19)
            for i, x, p in zip(np.arange(self.n), self.r, self.phi):
                self.zeta[i] = np.random.normal(loc=0., scale=sigma_z(x))
                self.clouds.append(
                    Cloud(i, x, p, self.zeta[i], size=None, em=None))
            coord_array = coord.CylindricalRepresentation(
                self.r * u.kpc, self.phi * u.rad, self.zeta * u.kpc)
            self.cartesian_galactocentric = self.cartesianize_coordinates(
                coord_array)
            self.heliocentric_coordinates()

            for c, d, latit, longit in zip(self.clouds, self.d_sun, self.lat,
                                           self.long):
                c.assign_sun_coord(d, latit, longit)
        self.L = np.array(self.sizes)
        self.healpix_vecs = self.compute_healpix_vec()
        self.W = self.get_pop_emissivities_sizes()[0]
Beispiel #7
0
def isochrone_to_xv(actions, angles, potential):
    """
    Transform the input actions and angles to ordinary phase space (position
    and velocity) in cartesian coordinates. See Section 3.5.2 in
    Binney & Tremaine (2008), and be aware of the errata entry for
    Eq. 3.225.

    .. note::

        This function is included as a method of the :class:`~gala.potential.IsochronePotential`
        and it is recommended to call :meth:`~gala.potential.IsochronePotential.action_angle()`
        instead.

    Parameters
    ----------
    actions : array_like
        Action variables. Must have shape ``(3,N)`` or ``(3,)``.
    angles : array_like
        Angle variables. Must have shape ``(3,N)`` or ``(3,)``.
        Should be in radians.
    potential : :class:`gala.potential.IsochronePotential`
        An instance of the potential to use for computing the transformation
        to angle-action coordinates.

    Returns
    -------
    x : :class:`numpy.ndarray`
        An array of cartesian positions computed from the input
        angles and actions.
    v : :class:`numpy.ndarray`
        An array of cartesian velocities computed from the input
        angles and actions.
    """

    raise NotImplementedError(
        "Implementation not supported until working with "
        "angle-action variables has a better API.")

    actions = atleast_2d(actions, insert_axis=1).copy()
    angles = atleast_2d(angles, insert_axis=1).copy()

    usys = potential.units
    GM = (G * potential.parameters['m']).decompose(usys).value
    b = potential.parameters['b'].decompose(usys).value

    # actions
    Jr = actions[0]
    Lz = actions[1]
    L = actions[2] + np.abs(Lz)

    # angles
    theta_r, theta_phi, theta_theta = angles

    # get longitude of ascending node
    theta_1 = theta_phi - np.sign(Lz) * theta_theta
    Omega = theta_1

    # Ly = -np.cos(Omega) * np.sqrt(L**2 - Lz**2)
    # Lx = np.sqrt(L**2 - Ly**2 - Lz**2)
    cosi = Lz / L
    sini = np.sqrt(1 - cosi**2)

    # Hamiltonian (energy)
    H = -2. * GM**2 / (2. * Jr + L + np.sqrt(4. * b * GM + L**2))**2

    if np.any(H > 0.):
        raise ValueError("Unbound particle. (E = {})".format(H))

    # Eq. 3.240
    c = -GM / (2. * H) - b
    e = np.sqrt(1 - L * L * (1 + b / c) / GM / c)

    # solve for eta
    theta_3 = theta_r
    eta_func = lambda x: x - e * c / (b + c) * np.sin(x) - theta_3
    eta_func_prime = lambda x: 1 - e * c / (b + c) * np.cos(x)

    # use newton's method to find roots
    niter = 100
    eta = np.ones_like(theta_3) * np.pi / 2.
    for i in range(niter):
        eta -= eta_func(eta) / eta_func_prime(eta)

    # TODO: when to do this???
    eta -= 2 * np.pi

    r = c * np.sqrt((1 - e * np.cos(eta)) * (1 - e * np.cos(eta) + 2 * b / c))
    vr = np.sqrt(GM / (b + c)) * (c * e * np.sin(eta)) / r

    theta_2 = theta_theta
    Omega_23 = 0.5 * (1 + L / np.sqrt(L**2 + 4 * GM * b))

    a = np.sqrt((1 + e) / (1 - e))
    ap = np.sqrt((1 + e + 2 * b / c) / (1 - e + 2 * b / c))

    def F(x, y):
        z = np.zeros_like(x)

        ix = y > np.pi / 2.
        z[ix] = np.pi / 2. - np.arctan(
            np.tan(np.pi / 2. - 0.5 * y[ix]) / x[ix])

        ix = y < -np.pi / 2.
        z[ix] = -np.pi / 2. + np.arctan(
            np.tan(np.pi / 2. + 0.5 * y[ix]) / x[ix])

        ix = (y <= np.pi / 2) & (y >= -np.pi / 2)
        z[ix] = np.arctan(x[ix] * np.tan(0.5 * y[ix]))
        return z

    theta_2[Lz < 0] -= 2 * np.pi
    theta_3 -= 2 * np.pi
    A = Omega_23 * theta_3 - F(
        a, eta) - F(ap, eta) / np.sqrt(1 + 4 * GM * b / L / L)
    psi = theta_2 - A

    # theta
    theta = np.arccos(np.sin(psi) * sini)
    vtheta = L * sini * np.cos(psi) / np.cos(theta)
    vtheta = -L * sini * np.cos(psi) / np.sin(theta) / r
    vphi = Lz / (r * np.sin(theta))

    # phi
    sinu = np.sin(psi) * cosi / np.sin(theta)

    uu = np.arcsin(sinu)
    uu[sinu > 1.] = np.pi / 2.
    uu[sinu < -1.] = -np.pi / 2.
    uu[vtheta > 0.] = np.pi - uu[vtheta > 0.]

    sinu = cosi / sini * np.cos(theta) / np.sin(theta)
    phi = (uu + Omega) % (2 * np.pi)

    # We now need to convert from spherical polar coord to cart. coord.
    pos = coord.PhysicsSphericalRepresentation(r=r * u.dimensionless_unscaled,
                                               phi=phi * u.rad,
                                               theta=theta * u.rad)
    x = pos.represent_as(coord.CartesianRepresentation).xyz.value
    v = physicsspherical_to_cartesian(pos, [vr, vphi, vtheta] *
                                      u.dimensionless_unscaled).value
    return x, v
Beispiel #8
0
    def test__fix_branch_cuts(self):
        """Test method ``_fix_branch_cuts``.

        .. todo::

            graphical proof via mpl_test that the point hasn't moved.

        """
        # -------------------------------
        # no angular units

        rep = coord.CartesianRepresentation(
            x=[1, 2] * u.kpc,
            y=[3, 4] * u.kpc,
            z=[5, 6] * u.kpc,
        )
        array = rep._values.view(dtype=np.float64).reshape(rep.shape[0], -1).T
        got = self.inst._fix_branch_cuts(array, rep.__class__, rep._units)

        assert got is array

        # -------------------------------
        # UnitSphericalRepresentation

        # 1) all good
        rep = coord.UnitSphericalRepresentation(
            lon=[1, 2] * u.deg,
            lat=[3, 4] * u.deg,
        )
        array = rep._values.view(dtype=np.float64).reshape(rep.shape[0], -1).T
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(got, array)

        # 2) needs correction
        array = np.array([[-360, 0, 360], [-91, 0, 91]])
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(got, np.array([[-180, 0, 540], [-89, 0, 89]]))

        # -------------------------------
        # SphericalRepresentation

        # 1) all good
        rep = coord.SphericalRepresentation(
            lon=[1, 2] * u.deg,
            lat=[3, 4] * u.deg,
            distance=[5, 6] * u.kpc,
        )
        array = rep._values.view(dtype=np.float64).reshape(rep.shape[0], -1).T
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(got, array)

        # 2) needs correction
        array = np.array([[-360, 0, 360], [-91, 0, 91], [5, 6, 7]])
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(
            got,
            np.array([[-180, 0, 540], [-89, 0, 89], [5, 6, 7]]),
        )

        # 3) needs correction
        array = np.array([[-360, 0, 360], [-91, 0, 91], [-5, 6, -7]])
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(
            got,
            np.array([[0, 0, 720], [89, 0, -89], [5, 6, 7]]),
        )

        # -------------------------------
        # CylindricalRepresentation

        # 1) all good
        rep = coord.CylindricalRepresentation(
            rho=[5, 6] * u.kpc,
            phi=[1, 2] * u.deg,
            z=[3, 4] * u.parsec,
        )
        array = rep._values.view(dtype=np.float64).reshape(rep.shape[0], -1).T
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(got, array)

        # 2) needs correction
        array = np.array([[-5, 6, -7], [-180, 0, 180], [-4, 4, 4]])
        got = self.inst._fix_branch_cuts(
            array.copy(),
            rep.__class__,
            rep._units,
        )
        assert np.allclose(got, np.array([[5, 6, 7], [0, 0, 360], [-4, 4, 4]]))

        # -------------------------------
        # NotImplementedError

        with pytest.raises(NotImplementedError):

            rep = coord.PhysicsSphericalRepresentation(
                phi=[1, 2] * u.deg,
                theta=[3, 4] * u.deg,
                r=[5, 6] * u.kpc,
            )
            array = (rep._values.view(dtype=np.float64).reshape(
                rep.shape[0], -1).T)
            self.inst._fix_branch_cuts(
                array.copy(),
                coord.PhysicsSphericalRepresentation,
                rep._units,
            )