Example #1
0
    def d_phase_d_param(self, toas, delay, param):
        """ Return the derivative of phase with respect to the parameter.
        """
        # TODO need to do correct chain rule stuff wrt delay derivs, etc
        # Is it safe to assume that any param affecting delay only affects
        # phase indirectly (and vice-versa)??
        par = getattr(self, param)
        result = np.longdouble(np.zeros(len(toas))) * u.cycle/par.units
        param_phase_derivs = []
        phase_derivs = self.phase_deriv_funcs
        delay_derivs = self.delay_deriv_funcs
        if param in list(phase_derivs.keys()):
            for df in phase_derivs[param]:
                result += df(toas, param, delay).to(result.unit,
                            equivalencies=u.dimensionless_angles())
        else:
            # Apply chain rule for the parameters in the delay.
            # total_phase = Phase1(delay(param)) + Phase2(delay(param))
            # d_total_phase_d_param = d_Phase1/d_delay*d_delay/d_param +
            #                         d_Phase2/d_delay*d_delay/d_param
            #                       = (d_Phase1/d_delay + d_Phase2/d_delay) *
            #                         d_delay_d_param

            d_delay_d_p = self.d_delay_d_param(toas, param)
            dpdd_result = np.longdouble(np.zeros(len(toas))) * u.cycle/u.second
            for dpddf in self.d_phase_d_delay_funcs:
                dpdd_result += dpddf(toas, delay)
            result = dpdd_result * d_delay_d_p
        return result.to(result.unit, equivalencies=u.dimensionless_angles())
def test_lsr_sanity():

    # random numbers, but zero velocity in ICRS frame
    icrs = ICRS(ra=15.1241*u.deg, dec=17.5143*u.deg, distance=150.12*u.pc,
                pm_ra_cosdec=0*u.mas/u.yr, pm_dec=0*u.mas/u.yr,
                radial_velocity=0*u.km/u.s)
    lsr = icrs.transform_to(LSR)

    lsr_diff = lsr.data.differentials['s']
    cart_lsr_vel = lsr_diff.represent_as(CartesianRepresentation, base=lsr.data)
    lsr_vel = ICRS(cart_lsr_vel)
    gal_lsr = lsr_vel.transform_to(Galactic).cartesian.xyz
    assert allclose(gal_lsr.to(u.km/u.s, u.dimensionless_angles()),
                    lsr.v_bary.d_xyz)

    # moving with LSR velocity
    lsr = LSR(ra=15.1241*u.deg, dec=17.5143*u.deg, distance=150.12*u.pc,
              pm_ra_cosdec=0*u.mas/u.yr, pm_dec=0*u.mas/u.yr,
              radial_velocity=0*u.km/u.s)
    icrs = lsr.transform_to(ICRS)

    icrs_diff = icrs.data.differentials['s']
    cart_vel = icrs_diff.represent_as(CartesianRepresentation, base=icrs.data)
    vel = ICRS(cart_vel)
    gal_icrs = vel.transform_to(Galactic).cartesian.xyz
    assert allclose(gal_icrs.to(u.km/u.s, u.dimensionless_angles()),
                    -lsr.v_bary.d_xyz)
Example #3
0
def get_relevant_wcs_properties(wcs, center, distance):

    """
    This function ...
    :param wcs:
    :param center:
    :param distance:
    :return:
    """

    # PIXEL SIZE
    pixels_x = wcs.xsize
    pixels_y = wcs.ysize

    # CENTER PIXEL
    pixel_center = center.to_pixel(wcs)
    # center = Position(0.5*pixels_x - pixel_center.x - 0.5, 0.5*pixels_y - pixel_center.y - 0.5) # when not convolved ...
    center = Position(0.5 * pixels_x - pixel_center.x - 1, 0.5 * pixels_y - pixel_center.y - 1)  # when convolved ...
    center_x = center.x * Unit("pix")
    center_y = center.y * Unit("pix")
    center_x = (center_x * wcs.pixelscale.x.to("deg/pix") * distance).to("pc", equivalencies=dimensionless_angles())
    center_y = (center_y * wcs.pixelscale.y.to("deg/pix") * distance).to("pc", equivalencies=dimensionless_angles())

    # FIELD OF VIEW
    field_x_angular = wcs.pixelscale.x.to("deg/pix") * pixels_x * Unit("pix")
    field_y_angular = wcs.pixelscale.y.to("deg/pix") * pixels_y * Unit("pix")
    field_x_physical = (field_x_angular * distance).to("pc", equivalencies=dimensionless_angles())
    field_y_physical = (field_y_angular * distance).to("pc", equivalencies=dimensionless_angles())

    return pixels_x, pixels_y, center_x, center_y, field_x_physical, field_y_physical
Example #4
0
def test_equivalency_context_manager():
    base_registry = u.get_current_unit_registry()

    def just_to_from_units(equivalencies):
        return [(equiv[0], equiv[1]) for equiv in equivalencies]

    tf_dimensionless_angles = just_to_from_units(u.dimensionless_angles())
    tf_spectral = just_to_from_units(u.spectral())
    assert base_registry.equivalencies == []
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        new_registry = u.get_current_unit_registry()
        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.set_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.add_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_dimensionless_angles) | set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

    assert base_registry is u.get_current_unit_registry()
def examinalyze(smat):
    mst = minimum_spanning_tree(smat)
    connections = np.where(mst.toarray())
    lines = [(coords[ii], coords[jj]) for ii,jj in zip(*connections)]
    plotlines = [((a.ra.deg, b.ra.deg), (a.dec.deg, b.dec.deg)) for a,b in lines]
    xx,yy = np.array(list(zip(*plotlines)))

    lines2 = [(coords[ll], coords[rr]) for ll,rr in edges]
    plotlines2 = [((a.ra.deg, b.ra.deg), (a.dec.deg, b.dec.deg)) for a,b in lines2]
    xx2,yy2 = np.array(list(zip(*plotlines2)))

    import pylab as pl
    pl.clf()
    pl.plot(coords.ra.deg, coords.dec.deg, '*')
    pl.plot(xx.T, yy.T, color='b', alpha=0.5, linewidth=2)
    pl.plot(xx2.T, yy2.T, color='r', alpha=0.5, linewidth=2)

    inds = np.where(np.tril(smat, -1))
    mps = smat[inds].mean()
    mbl = mst[mst.nonzero()].mean()
    print("Mean branch length: {0} arcsec {1}".format(mbl*3600,
                                                         (mbl*u.deg*distance).to(u.pc,
                                                                                 u.dimensionless_angles())))
    print("Mean point separation: {0} arcsec {1}".format(mps*3600,
                                                            (mbl*u.deg*distance).to(u.pc,
                                                                                    u.dimensionless_angles())))
    print("Q parameter: {0}".format(mbl/mps))
Example #6
0
def test_hel_gal():
    n = 100

    l = np.random.uniform(0.,360.,size=n)*u.degree
    b = np.random.uniform(-90.,90.,size=n)*u.degree
    d = np.random.uniform(0.,100.,size=n)*u.kpc
    mul = np.random.normal(0., 300., size=n)*u.km/u.s/d
    mub = np.random.normal(0., 300., size=n)*u.km/u.s/d
    vr = np.random.normal(0., 300., size=n)*u.km/u.s

    mul = mul.to(u.mas/u.yr,equivalencies=u.dimensionless_angles())
    mub = mub.to(u.mas/u.yr,equivalencies=u.dimensionless_angles())

    xyz,vxyz = sc.hel_to_gal_xyz((l,b,d), pm=(mul,mub), vr=vr,
                                 vlsr=[0.,0.,0.]*u.km/u.s)
    x,y,z = xyz.decompose(usys).value
    vx,vy,vz = vxyz.decompose(usys).value

    X = hel_to_gal(np.vstack((l.decompose(usys).value,
                              b.decompose(usys).value,
                              d.decompose(usys).value,
                              mul.decompose(usys).value,
                              mub.decompose(usys).value,
                              vr.decompose(usys).value)).T)
    x1,y1,z1,vx1,vy1,vz1 = X.T

    assert np.allclose(x1, x)
    assert np.allclose(y1, y)
    assert np.allclose(z1, z)
    assert np.allclose(vx1, vx)
    assert np.allclose(vy1, vy)
    assert np.allclose(vz1, vz)
Example #7
0
def test_hel_gal():
    """
    Note: slight offsets between Astropy / gary transformation and
    this transformation are expected because this assumes (l,b)=(0,0)
    is the Galactic center. Astropy uses a more modern measurement of
    the position of the GC.
    """
    np.random.seed(42)

    RSUN = 8.*u.kpc
    VCIRC = 240.*u.km/u.s
    VLSR = [0,0,0.] * u.km/u.s
    gc_frame = coord.Galactocentric(z_sun=0.*u.pc,
                                    galcen_distance=RSUN)

    l = np.random.uniform(0.,360.,size=n)*u.degree
    b = np.random.uniform(-90.,90.,size=n)*u.degree
    d = np.random.uniform(0.,100.,size=n)*u.kpc
    mul_cosb = np.random.normal(0., 300., size=n)*u.km/u.s/d * np.cos(b)
    mub = np.random.normal(0., 300., size=n)*u.km/u.s/d
    vr = np.random.normal(0., 300., size=n)*u.km/u.s

    mul_cosb = mul_cosb.to(u.mas/u.yr, equivalencies=u.dimensionless_angles())
    mub = mub.to(u.mas/u.yr, equivalencies=u.dimensionless_angles())

    c = coord.Galactic(l=l, b=b, distance=d)
    vxyz = gc.vhel_to_gal(c, (mul_cosb,mub), vr,
                          vcirc=VCIRC, vlsr=VLSR,
                          galactocentric_frame=gc_frame)
    xyz = c.transform_to(gc_frame).cartesian.xyz

    x,y,z = xyz.decompose(galactic).value
    vx,vy,vz = vxyz.decompose(galactic).value

    X = hel_to_gal(np.vstack((l.decompose(galactic).value,
                              b.decompose(galactic).value,
                              d.decompose(galactic).value,
                              mul_cosb.decompose(galactic).value,
                              mub.decompose(galactic).value,
                              vr.decompose(galactic).value)).T,
                   Vcirc=VCIRC.decompose(galactic).value,
                   Rsun=RSUN.decompose(galactic).value)
    x1,y1,z1,vx1,vy1,vz1 = X.T

    assert np.allclose(x1, x, rtol=1E-2)
    assert np.allclose(y1, y, rtol=1E-2)
    assert np.allclose(z1, z, rtol=1E-2)
    assert np.allclose(vx1, vx, rtol=1E-2)
    assert np.allclose(vy1, vy, rtol=1E-2)
    assert np.allclose(vz1, vz, rtol=1E-2)
Example #8
0
File: stretch.py Project: SKIRT/PTS
    def from_sky(cls, stretch, distance):

        """
        This function ...
        :param stretch:
        :param distance:
        :return:
        """

        # Convert
        length1 = (stretch.x * distance).to("kpc", equivalencies=dimensionless_angles())
        length2 = (stretch.y * distance).to("kpc", equivalencies=dimensionless_angles())

        # Create
        return cls(length1, length2)
Example #9
0
File: stretch.py Project: SKIRT/PTS
    def from_physical(cls, stretch, distance):

        """
        Thisn function ...
        :param stretch:
        :param distance:
        :return:
        """

        # Convert
        x_angular = (stretch.x / distance).to("deg", equivalencies=dimensionless_angles())
        y_angular = (stretch.y / distance).to("deg", equivalencies=dimensionless_angles())

        # Create and return
        return cls(x_angular, y_angular)
Example #10
0
    def __call__(self, duration, samplerate):
        """Produce simulated voltages for given duration and samplerate

        Parameters
        ----------
        duration : Quantity
            Should be time units
        samplerate : Quantity
            Rate at which samples should be generated

        The samples are complex, so the real and imaginary parts can be
        used as separate time streams, or can be thought of as complex
        voltages.  The total number of samples is duration * samplerate.
        """
        times = (np.arange(0., (duration * samplerate).to(1).value,
                           dtype=np.float32) / samplerate).to(duration.unit)
        nbins = times.shape[0]
        spectral_power = (np.arange(0., (duration * samplerate).to(1).value,
                                    dtype=np.float32) /
                          (duration * self.nu0)).to(1) ** self.spectral_index
        spectral_power *= self.fnu0.astype(np.float32)
        spectral_phase = np.random.uniform(size=nbins) * u.cycle
        with u.add_enabled_equivalencies(u.dimensionless_angles()):
            spectrum = np.sqrt(spectral_power) * np.exp(1j * spectral_phase)
        spectrum[0] = 0.
        return times, ifft(spectrum, overwrite_x=True)
Example #11
0
    def create_deprojection_model(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Calculating the deprojection parameters ...")

        filename = None
        hz = None

        # Get the galaxy distance, the inclination and position angle
        distance = self.parameters.distance
        inclination = self.parameters.inclination
        pa = self.parameters.disk.PA

        # Get the center pixel
        pixel_center = self.parameters.center.to_pixel(self.reference_wcs)
        xc = pixel_center.x
        yc = pixel_center.y

        # Get the pixelscale in physical units
        pixelscale_angular = self.reference_wcs.average_pixelscale * Unit("pix") # in deg
        pixelscale = (pixelscale_angular * distance).to("pc", equivalencies=dimensionless_angles())

        # Get the number of x and y pixels
        x_size = self.reference_wcs.xsize
        y_size = self.reference_wcs.ysize

        # Create the deprojection model
        self.deprojection = DeprojectionModel(filename, pixelscale, pa, inclination, x_size, y_size, xc, yc, hz)
Example #12
0
    def _physical_size(self):
        if not hasattr(self, "_distance"):
            raise AttributeError("No distance has not been given.")

        return (self._ang_size *
                self.distance).to(self.distance.unit,
                                  equivalencies=u.dimensionless_angles())
Example #13
0
    def d_omega_d_par(self,par):
        """derivative for omega respect to user input Parameter.
           if par is not 'OM','OMDOT','PB'
           dOmega/dPar =  k*dAe/dPar
           k = OMDOT/n
           Parameters
           ----------
           par : string
                 parameter name
           Return
           ----------
           Derivitve of omega respect to par
        """
        if par not in self.binary_params:
            errorMesg = par + "is not in binary parameter list."
            raise ValueError(errorMesg)
        par_obj = getattr(self, par)

        PB = self.pb()
        OMDOT = self.OMDOT
        OM = self.OM
        nu = self.nu()
        k = OMDOT.to(u.rad/u.second)/(2*np.pi*u.rad/PB)
        if par in ['OM','OMDOT']:
            dername = 'd_omega_d_' + par
            return getattr(self,dername)()
        elif par in self.orbits_cls.orbit_params:
            d_nu_d_par = self.d_nu_d_par(par)
            d_pb_d_par = self.d_pb_d_par(par)
            return d_nu_d_par * k + d_pb_d_par * nu * \
                   OMDOT.to(u.rad/u.second)/(2*np.pi*u.rad)
        else:
            # For parameters only in nu
            return (k * self.d_nu_d_par(par)).to(OM.unit/par_obj.unit,
                                     equivalencies = u.dimensionless_angles())
Example #14
0
 def d_delta_a1_proper_motion_d_KIN(self):
     a1 = self.a1_k(False, False)
     kin = self.kin()
     d_kin = self.delta_kin_proper_motion()
     d_delta_a1_proper_motion_d_KIN = - a1 * d_kin / np.sin(kin) ** 2
     return d_delta_a1_proper_motion_d_KIN.to(a1.unit/kin.unit,
             equivalencies=u.dimensionless_angles())
Example #15
0
    def d_delayI_d_par(self,par):
        """Derivative on delay inverse.
        """
        e = self.ecc()
        sE = np.sin(self.E())
        cE = np.cos(self.E())
        dE_dpar = self.prtl_der('E',par)
        decc_dpar = self.prtl_der('ecc',par)

        Dre = self.Dre()
        Drep = self.Drep()
        Drepp = self.Drepp()
        nHat = self.nhat()
        delayI = self.delayInverse()

        dDre_dpar = self.d_Dre_d_par(par)
        dDrep_dpar = self.d_Drep_d_par(par)
        dDrepp_dpar = self.d_Drepp_d_par(par)
        dnhat_dpar = self.d_nhat_d_par(par)
        oneMeccTcosE = (1-e*cE) # 1-e*cos(E)
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            x =  -1.0/2.0*e*sE/oneMeccTcosE # -1/2*e*sin(E)/(1-e*cos(E))

            dx_dpar = -sE/(2*oneMeccTcosE**2)*decc_dpar+e*(e-cE)/(2*oneMeccTcosE**2)*dE_dpar

            diDelay_dDre = 1+(Drep*nHat)**2+Dre*Drepp*nHat**2+Drep*nHat*(2*Dre*nHat*x-1)
            diDelay_dDrep = Dre*nHat*(2*Drep*nHat+Dre*nHat*x-1)
            diDelay_dDrepp = (Dre*nHat)**2/2
            diDelay_dnhat = Dre*(-Drep+2*Drep**2*nHat+nHat*Dre*Drepp+2*x*nHat*Dre*Drep)
            diDelay_dx = (Dre*nHat)**2*Drep

            return dDre_dpar*diDelay_dDre + dDrep_dpar*diDelay_dDrep + \
                   dDrepp_dpar*diDelay_dDrepp + dx_dpar*diDelay_dx+ \
                   dnhat_dpar*diDelay_dnhat
Example #16
0
    def d_delayS_d_par(self,par):
        """dsDelay/dPar = dsDelay/dTM2*dTM2/dPar+
                          dsDelay/decc*decc/dPar+
                          dsDelay/dE*dE/dPar+
                          dsDelay/domega*domega/dPar+
                          dsDelay/dSINI*dSINI/dPar
        """
        e = self.ecc()
        cE = np.cos(self.E())
        sE = np.sin(self.E())
        sOmega = np.sin(self.omega())
        cOmega = np.cos(self.omega())
        TM2 = self.M2.value*Tsun

        logNum = 1-e*cE-self.SINI*(sOmega*(cE-e)+
                 (1-e**2)**0.5*cOmega*sE)
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            dTM2_dpar = self.prtl_der('TM2',par)
            dsDelay_dTM2 = -2*np.log(logNum)
            decc_dpar = self.prtl_der('ecc',par)
            dsDelay_decc = -2*TM2/logNum*(-cE-self.SINI*(-e*cOmega*sE/np.sqrt(1-e**2)-sOmega))
            dE_dpar = self.prtl_der('E',par)
            dsDelay_dE =  -2*TM2/logNum*(e*sE-self.SINI*(np.sqrt(1-e**2)*cE*cOmega-sE*sOmega))
            domega_dpar = self.prtl_der('omega',par)
            dsDelay_domega = 2*TM2/logNum*self.SINI*((cE-e)*cOmega-np.sqrt(1-e**2)*sE*sOmega)
            dSINI_dpar = self.prtl_der('SINI',par)
            dsDelay_dSINI = -2*TM2/logNum*(-(1-e**2)**0.5*cOmega*sE-(cE-e)*sOmega)
            return dTM2_dpar*dsDelay_dTM2 + decc_dpar*dsDelay_decc + \
                   dE_dpar*dsDelay_dE +domega_dpar*dsDelay_domega +  \
                   dSINI_dpar*dsDelay_dSINI
Example #17
0
    def d_beta_d_par(self,par):
        """beta = A1/c*(1-eTheta**2)**0.5*cos(omega)
           eTheta = ecc+Dth  ??
           dBeta/dA1 = 1.0/c*(1-eTheta**2)**0.5*cos(omega)
           dBeta/dECC = A1/c*((-(e+dr)/sqrt(1-(e+dr)**2)*cos(omega)*de/dECC-
                        (1-eTheta**2)**0.5*sin(omega)*domega/dECC
           dBeta/dEDOT = A1/c*((-(e+dr)/sqrt(1-(e+dr)**2)*cos(omega)*de/dEDOT-
                        (1-eTheta**2)**0.5*sin(omega)*domega/dEDOT
           dBeta/dDth = A1/c*(-(e+dr)/sqrt(1-(e+dr)**2)*cos(omega)
           Other parameters
           dBeta/dPar = -A1/c*(1-eTheta**2)**0.5*sin(omega)*dOmega/dPar
        """
        if par not in self.binary_params:
            errorMesg = par + "is not in binary parameter list."
            raise ValueError(errorMesg)
        par_obj = getattr(self, par)
        beta = self.beta()
        eTheta = self.eTheta()
        a1 = self.a1()
        omega = self.omega()
        sinOmg = np.sin(omega)
        cosOmg = np.cos(omega)
        d_a1_d_par = self.d_a1_d_par(par)
        d_omega_d_par = self.d_omega_d_par(par)
        d_eTheta_d_par = self.d_eTheta_d_par(par)

        d_beta_d_a1 = 1.0/c.c*(1-eTheta**2)**0.5*cosOmg
        d_beta_d_omega = -a1/c.c*(1-eTheta**2)**0.5*sinOmg
        d_beta_d_eTheta = a1/c.c*(-eTheta)/np.sqrt(1-eTheta**2)*cosOmg
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            return (d_beta_d_a1 * d_a1_d_par + d_beta_d_omega * d_omega_d_par + \
                    d_beta_d_eTheta * d_eTheta_d_par).to(beta.unit/par_obj.unit)
Example #18
0
    def d_Dre_d_par(self,par):
        """Dre = alpha*(cos(E)-er)+(beta+gamma)*sin(E)
           dDre = alpha*(-der-dE*sin(E)) + (cos[E]-er)*dalpha +
                  (dBeta+dGamma)*sin(E) + (beta+gamma)*cos(E)*dE

           dDre/dpar = alpha*(-der/dpar-dE/dpar*sin(E)) +
                       (cos[E]-er)*dalpha/dpar +
                       (dBeta/dpar+dGamma/dpar)*sin(E) +
                       (beta+gamma)*cos(E)*dE/dpar

            er = e + Dr
        """
        Dre = self.Dre()
        par_obj = getattr(self, par)
        sinE = np.sin(self.E())
        cosE = np.cos(self.E())
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            # First term
            term1 = self.alpha()*(-self.prtl_der('er',par)-self.prtl_der('E',par)*sinE)
            # Second term
            term2 = (cosE-self.er())*self.prtl_der('alpha',par)
            # Third term
            term3 = (self.prtl_der('beta',par)+self.prtl_der('GAMMA',par))*sinE
            # Fourth term
            term4 = (self.beta()+self.GAMMA)*cosE*self.prtl_der('E',par)

            return (term1 + term2 + term3 +term4).to(Dre.unit/par_obj.unit)
Example #19
0
    def d_alpha_d_par(self,par):
        """T. Damour and N. Deruelle(1986)equation [46]
           alpha = a1/c*sin(omega)
           dAlpha/dpar = d_a1_d_par /c * sin(omega) + a1/c*cos(omega)*dOmega/dPar
        """

        if par not in self.binary_params:
            errorMesg = par + "is not in binary parameter list."
            raise ValueError(errorMesg)
        par_obj = getattr(self, par)
        alpha = self.alpha()
        sinOmg = np.sin(self.omega())
        cosOmg = np.cos(self.omega())
        a1 = self.a1()
        d_a1_d_par = self.d_a1_d_par(par)
        d_omega_d_par = self.d_omega_d_par(par)
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            dAlpha_dpar = d_a1_d_par / c.c * sinOmg + a1 / c.c * cosOmg * d_omega_d_par
        #
        # if par in ['A1','A1DOT']:
        #     dername = 'd_alpha_d_'+par
        #     return getattr(self,dername)()
        #
        # else:
        #     dername = 'd_omega_d_'+par # For parameters only in Ae
        #     if hasattr(self,dername):
        #         cosOmg=np.cos(self.omega())
        #         return self.a1()/c.c*cosOmg*getattr(self,dername)()
        #     else:
        #         return np.longdouble(np.zeros(len(self.tt0)))
        return dAlpha_dpar.to(alpha.unit/par_obj.unit)
Example #20
0
def approximate_primary_beam_sizes(frequency_support_str):
    freq_ranges = parse_frequency_support(frequency_support_str)
    beam_sizes = [(1.22*fr.mean().to(u.m,
                                     u.spectral())/(12*u.m)).to(u.arcsec,
                                                                u.dimensionless_angles())
                  for fr in freq_ranges]
    return u.Quantity(beam_sizes)
Example #21
0
def test_dimensionless_angles():
    # test that the angles_dimensionless option allows one to change
    # by any order in radian in the unit (#1161)
    rad1 = u.dimensionless_angles()
    assert u.radian.to(1, equivalencies=rad1) == 1.
    assert u.deg.to(1, equivalencies=rad1) == u.deg.to(u.rad)
    assert u.steradian.to(1, equivalencies=rad1) == 1.
    assert u.dimensionless_unscaled.to(u.steradian, equivalencies=rad1) == 1.
    # now quantities
    assert (1.*u.radian).to_value(1, equivalencies=rad1) == 1.
    assert (1.*u.deg).to_value(1, equivalencies=rad1) == u.deg.to(u.rad)
    assert (1.*u.steradian).to_value(1, equivalencies=rad1) == 1.
    # more complicated example
    I = 1.e45 * u.g * u.cm**2
    Omega = u.cycle / (1.*u.s)
    Erot = 0.5 * I * Omega**2
    # check that equivalency makes this work
    Erot_in_erg1 = Erot.to(u.erg, equivalencies=rad1)
    # and check that value is correct
    assert_allclose(Erot_in_erg1.value, (Erot/u.radian**2).to_value(u.erg))

    # test build-in equivalency in subclass
    class MyRad1(u.Quantity):
        _equivalencies = rad1

    phase = MyRad1(1., u.cycle)
    assert phase.to_value(1) == u.cycle.to(u.radian)
Example #22
0
 def d_delta_omega_proper_motion_d_KIN(self):
     kin = self.kin()
     sin_kin = np.sin(kin)
     cos_kin = np.cos(kin)
     d_omega_dot = -cos_kin/sin_kin **2 * (self.PMRA_DDK * self.cos_KOM +
                                           self.PMDEC_DDK * self.sin_KOM)
     return (d_omega_dot * self.tt0).to(self.OM.unit/self.KIN.unit,
                                        equivalencies=u.dimensionless_angles())
Example #23
0
 def _angle_to_length(self, arc, **kwargs):
     """
     Approximate a surface length from the observed arc length.
     Uses the small angle approximation.
     """
     r = self.map_boundary_data.dsun - self.map_boundary_data.rsun_meters
     length = (r * arc.to(u.radian))
     return length.to(u.m, equivalencies=u.dimensionless_angles())
def convolve_to_beam(fitsfilename, beam=radio_beam.Beam(0.04*u.arcsec), distance=5400*u.pc):
    hdr = fits.getheader(fitsfilename)
    pix_area = (hdr['CDELT1']*u.cm)**2
    pix_area_arcsec = (pix_area/distance**2).to(u.arcsec**2, u.dimensionless_angles())
    kernel = beam.as_kernel(pix_area_arcsec**0.5)

    data = fits.getdata(fitsfilename)
    smoothed = convolve_fft(data, kernel)
    return fits.PrimaryHDU(data=smoothed, header=hdr)
Example #25
0
    def test_vgal_to_hel_single(self):

        # test a single entry
        row = self.data[0]
        c = coord.SkyCoord(ra=row['ra']*u.deg, dec=row['dec']*u.deg, distance=row['dist']*u.pc)
        pm = [row['pml'],row['pmb']]*u.mas/u.yr
        rv = row['rv']*u.km/u.s

        true_pmrv = (pm[0], pm[1], rv)
        vxyz = [row['U'],row['V'],row['W']]*u.km/u.s
        pmrv = vgal_to_hel(c.galactic, vxyz=vxyz,
                           vcirc=0.*u.km/u.s,
                           vlsr=[0.,0,0]*u.km/u.s)

        for i in range(3):
            np.testing.assert_allclose(pmrv[i].to(true_pmrv[i].unit).value,
                                       true_pmrv[i].value,
                                       atol=1.)

        # some sanity checks - first, some convenience definitions
        g = coord.Galactic(l=0*u.deg, b=0*u.deg).transform_to(coord.ICRS)
        frargs = dict(galcen_ra=g.ra,
                      galcen_dec=g.dec,
                      z_sun=0*u.kpc,
                      galcen_distance=8*u.kpc)
        galcen_frame = coord.Galactocentric(**frargs)

        # --------------------------------------------------------------------
        # l = 0
        # without LSR and circular velocity
        # c = coord.Galactocentric([6,0,0]*u.kpc,**frargs)
        c = coord.SkyCoord(l=0*u.deg, b=0*u.deg, distance=2*u.kpc, frame=coord.Galactic)
        vxyz = [20.,0,0]*u.km/u.s
        pmv = vgal_to_hel(c.galactic, vxyz,
                          vcirc=0*u.km/u.s,
                          vlsr=[0.,0,0]*u.km/u.s,
                          galactocentric_frame=galcen_frame)
        np.testing.assert_allclose(pmv[0].to(u.mas/u.yr).value, 0., atol=1E-12)
        np.testing.assert_allclose(pmv[1].to(u.mas/u.yr).value, 0., atol=1E-12)
        np.testing.assert_allclose(pmv[2].to(u.km/u.s).value, 20., atol=1E-12)

        # with LSR and circular velocity
        c = coord.SkyCoord(l=0*u.deg, b=0*u.deg, distance=2*u.kpc, frame=coord.Galactic)
        vxyz = [20.,0,0]*u.km/u.s
        pmv = vgal_to_hel(c.galactic, vxyz,
                          vcirc=-200*u.km/u.s,
                          vlsr=[0.,0,10]*u.km/u.s,
                          galactocentric_frame=galcen_frame)

        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            np.testing.assert_allclose(pmv[0].to(u.mas/u.yr).value,
                                       ((200.*u.km/u.s)/(2*u.kpc)).to(u.mas/u.yr).value,
                                       atol=1E-12)
            np.testing.assert_allclose(pmv[1].to(u.mas/u.yr).value,
                                       ((-10.*u.km/u.s)/(2*u.kpc)).to(u.mas/u.yr).value,
                                       atol=1E-4)
        np.testing.assert_allclose(pmv[2].to(u.km/u.s).value, 20., atol=1E-12)
Example #26
0
 def d_delta_omega_parallax_d_KIN(self):
     kin = self.kin()
     sin_kin = np.sin(kin)
     cos_kin = np.cos(kin)
     PX_kpc= self.PX.to(u.kpc, equivalencies=u.parallax())
     kom_projection = self.delta_I0() * self.cos_KOM + \
                      self.delta_J0() * self.sin_KOM
     d_delta_omega_d_KIN = cos_kin / sin_kin ** 2 / PX_kpc * kom_projection
     return d_delta_omega_d_KIN.to(self.OM.unit / kin.unit,
                                   equivalencies=u.dimensionless_angles())
Example #27
0
def approximate_primary_beam_sizes(frequency_support_str):
    """
    Given a frequency support string, return the approximate 12m array beam
    size using 1.22 lambda / D
    """
    freq_ranges = parse_frequency_support(frequency_support_str)
    beam_sizes = [(1.22 * fr.mean().to(u.m, u.spectral()) /
                   (12 * u.m)).to(u.arcsec, u.dimensionless_angles())
                  for fr in freq_ranges]
    return u.Quantity(beam_sizes)
Example #28
0
 def delta_omega_parallax(self):
     """
     Reference: (Kopeikin 1995 Eq 19)
     """
     kin = self.kin()
     sin_kin = np.sin(kin)
     PX_kpc= self.PX.to(u.kpc, equivalencies=u.parallax())
     delta_omega = -1.0 / sin_kin / PX_kpc * (self.delta_I0() * self.cos_KOM + \
                                               self.delta_J0() * self.sin_KOM)
     return delta_omega.to(self.OM.unit, equivalencies=u.dimensionless_angles())
Example #29
0
def create_one_dust_grid_for_galaxy_from_deprojection(grid_type, deprojection, distance, sky_ellipse, min_level,
                                                      max_mass_fraction, max_ndivisions_per_pixel=2, nscaleheights=10.):

    """
    This function ...
    :param grid_type: 
    :param deprojection:
    :param distance:
    :param sky_ellipse:
    :param min_level:
    :param max_mass_fraction:
    :param max_ndivisions_per_pixel:
    :param nscaleheights:
    :return: 
    """

    if sky_ellipse is not None:
        # Calculate the major radius of the truncation ellipse in physical coordinates (pc)
        semimajor_angular = sky_ellipse.semimajor  # semimajor axis length of the sky ellipse
        radius_physical = (semimajor_angular * distance).to("pc", equivalencies=dimensionless_angles())
    else:
        x_radius_physical = deprojection.x_range.radius
        y_radius_physical = deprojection.y_range.radius
        radius_physical = max(x_radius_physical, y_radius_physical)

    # Get properties
    average_pixelscale = deprojection.pixelscale
    scaleheight = deprojection.scale_height

    # Get the pixelscale in physical units
    if types.is_angle(average_pixelscale):
        pixelscale_angular = average_pixelscale.to("deg")
        # pixelscale_angular = self.reference_wcs.average_pixelscale.to("deg")  # in deg
        pixelscale = (pixelscale_angular * distance).to("pc", equivalencies=dimensionless_angles())
    elif types.is_length_quantity(average_pixelscale): pixelscale = average_pixelscale.to("pc") # normally it should be this case (deprojections should have their pixelscale defined in physical units)
    else: raise ValueError("Pixelscale should be an angle or a length quantity")

    # Determine the minimum physical scale
    min_scale = pixelscale / float(max_ndivisions_per_pixel)

    # Create the dust grid
    return create_one_dust_grid_for_galaxy(grid_type, radius_physical, scaleheight, min_scale, min_level, max_mass_fraction, nscaleheights=nscaleheights)
Example #30
0
def integ_to_lum(fn):

    hdr = fits.getheader(fn)
    img = fits.getdata(fn) * u.Unit(hdr["BUNIT"])
    w = wcs.WCS(hdr)
    pixscale = np.abs(w.wcs.get_cdelt()[0]) * u.deg
    pixarea_cm = ((pixscale * distance) ** 2).to(u.cm ** 2, u.dimensionless_angles())

    lum = pixarea_cm * img

    return lum.to(u.L_sun) * 4 * np.pi
Example #31
0
 def d_kin_proper_motion_d_KOM(self):
     d_DKIN_d_KOM = (-self.PMRA_DDK * self.cos_KOM -
                     self.PMDEC_DDK * self.sin_KOM) * self.tt0
     return d_DKIN_d_KOM.to(self.KIN.unit / self.KOM.unit,
                            equivalencies=u.dimensionless_angles())
Example #32
0
def circle(n_points=61):
    with u.add_enabled_equivalencies(u.dimensionless_angles()):
        circle = np.exp(np.linspace(0., 1., n_points) * u.cycle * 1j)
    return circle.real, circle.imag
Example #33
0
"""Kopeikin corrected DD model."""
from __future__ import absolute_import, division, print_function

import astropy.constants as c
import astropy.units as u
import numpy as np
from astropy import log

from pint import GMsun, Tsun, ls

from .DD_model import DDmodel

u.set_enabled_equivalencies(u.dimensionless_angles())


class DDKmodel(DDmodel):
    """DDK model, a Kopeikin method corrected DD model.
    The main difference is that DDK model considers the annual parallax of earth and
    the proper motion of the pulsar.
    effects on the pulsar binary parameters.
    Speical parameters are:

        KIN
            the inclination angle
        KOM
            the longitude of the ascending node, Kopeikin (1995) Eq 9. OMEGA

    """
    def __init__(self, t=None, input_params=None):
        super(DDKmodel, self).__init__()
        self.binary_name = "DDK"
Example #34
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)
Example #35
0
def approximate_ruwe(t,
                     P,
                     m1,
                     m2,
                     distance,
                     f1=None,
                     f2=None,
                     t0=None,
                     i=0 * u.deg,
                     **kwargs):
    """
    Approximate the on-sky astrometric excess noise for a binary system with the
    given system parameters at a certain distance.

    This approximating function ignores the following effects:

    (1) The distortions that arise due to sky projections.
    (2) Inclination effects.
    (3) Omega effects.

    In part it also assumes:

    (1) The times were observed pseudo-randomly.
    (2) The orbit is fully sampled.

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

    :param P:
        The period of the binary system.

    :param m1:
        The mass of the primary star.

    :param m2:
        The mass of the secondary system.

    :param distance:
        The distance from the observer to the center of mass of the binary
        system.

    :param f1: [optional]
        The flux of the primary star. If `None` is given then this is assumed to
        be $m_1^{3.5}$.

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

    :returns:
        A two-part tuple containing the root-mean-squared deviations in on-sky
        position (in units of milliarcseconds), and a dictionary containing meta
        information about the binary system.
    """

    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')

    m_total = m1 + m2
    w = np.array([f1, f2]) / (f1 + f2)
    a = twobody.P_m_to_a(P, m_total).to(u.AU).value

    a1 = m2 * a / m_total
    a2 = m1 * a / m_total

    w1, w2 = (w[0], w[1])

    # TODO: replace this with integral!
    dt = (t - t0).to(u.day)
    phi = (2 * np.pi * dt / P).value
    N = phi.size

    dx = a1 * w1 * np.cos(phi) + a2 * w2 * np.cos(phi + np.pi)
    dy = a1 * w1 * np.sin(phi) + a2 * w2 * np.sin(phi + np.pi)

    planar_rms_in_au = np.sqrt(
        np.sum((dx - np.mean(dx))**2 + (dy - np.mean(dy))**2) / N).value

    # Need some corrections for when the period is longer than the observing timespan, and the
    # inclination angle is non-zero.

    # For this it really depends on what t0/Omega is: if you see half the orbit in one phase or
    # another...
    # TODO: this requires a thinko.
    """
    Approximate given some inclination angle.
    At zero inclination, assume circle on sky such that:
    
        rms = sqrt(ds^2 + ds^2) = sqrt(2ds^2)

    and 
        
        ds = np.sqrt(0.5 * rms^2)

    Now when inclined (even at 90) we still get ds + contribution:

        rms_new = sqrt(ds^2 + (cos(i) * ds)^2)
    """

    ds = np.sqrt(0.5 * planar_rms_in_au**2)
    rms_in_au = np.sqrt(ds**2 + (np.cos(i) * ds)**2)
    rms_in_mas = (rms_in_au * u.au / distance).to(
        u.mas, equivalencies=u.dimensionless_angles())

    intrinsic_ra_error = kwargs.get("intrinsic_ra_error", __intrinsic_ra_error)
    intrinsic_dec_error = kwargs.get("intrinsic_dec_error",
                                     __intrinsic_dec_error)

    chi2 = N * rms_in_mas.to(
        u.mas).value**2 / (intrinsic_ra_error**2 + intrinsic_dec_error**2)

    # sqrt(2) from approximating rms in one dimension instead of 2
    approx_ruwe = np.sqrt(2) * np.sqrt(chi2 / (N - 2))

    meta = dict(weights=w,
                a=a,
                a1=a1,
                a2=a2,
                w1=w1,
                w2=w2,
                phi=phi,
                dx=dx,
                dy=dy,
                rms_in_au=rms_in_au)

    return (approx_ruwe, meta)
Example #36
0
    def get_parameters_from_table(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info(
            "Getting the structural galaxy parameters from the S4G catalog ..."
        )

        # Inform the user
        log.info("Parsing S4G table 8 to get the decomposition parameters ...")

        #The table columns are:
        # (1) the running number (1-2352),
        # (2) the galaxy name,
        # (3) the type of final decomposition model,
        # (4) the number N of components in the final model , and
        # (5) the quality flag Q.

        # 6- 8 for unresolved central component ('psf'; phys, frel,  mag),
        # 9-15 for inner sersic-component ('sersic1'; phys,  frel,  mag,    re,    ar,      pa,    n),
        # 16-22 for inner disk-component ('expo1'; phys,  frel,  mag,    hr,    ar,      pa,   mu0),
        # 23-28 for inner ferrers-component ('ferrers1'; phys,  frel,  mu0,   rout,   ar,     pa),
        # 29-34 for inner edge-on disk component ('edgedisk1';  phys, frel, mu0,  rs,    hs,      pa ).
        # 35-41 for outer sersic-component ('sersic2'; phys,  frel,  mag,    re,    ar,      pa,    n),
        # 42-49 for outer disk-component ('expo2'; phys,  frel,  mag,    hr,    ar,      pa,   mu0),
        # 50-55 for outer ferrers-component ('ferrers2'; phys,  frel,  mu0,   rout,   ar,     pa),
        # 56-61 for outer edge-on disk component ('edgedisk2';  phys, frel, mu0,  rs,    hs,      pa ).

        sersic_1_index = 8
        disk_1_index = 15

        edgedisk_1_index = 28

        #For each function:

        #the first entry stands for the physical intepretation of the component:
        #'N' for a central source (or unresolved bulge), 'B' for a bulge (or elliptical), 'D' for a disk, 'BAR' for a bar, and 'Z' for an edge-on disk.

        # 'rel    =  the relative contribution of the component to the total model flux,
        #  mag    =  the component's total 3.6 micron AB magnitude,
        #  mu0    =  the central  surface brightness (mag/arcsec^2;  de-projected central surface brightness for expdisk and edgedisk, and
        #                                                          sky-plane central surface brightness for ferrer)
        #  ar     =  axial ratio
        #  pa     =  position angle (degrees ccw from North)
        #  n      =  sersic index
        #  hr     =  exponential scale lenght (arcsec)
        #  rs     =  radial scale lenght (arcsec)
        #  hs     =  vertical scale height (arcsec)
        #  rout   =  bar outer truncation radius (arcsec)

        # SERSIC: phys,  frel,  mag,    re,    ar,      pa,    n
        # DISK: phys,  frel,  mag,    hr,    ar,      pa,   mu0

        # EDGEDISK: phys frel mu0    rs    hs      pa

        with open(local_table_path, 'r') as s4g_table:

            for line in s4g_table:

                splitted = line.split()

                if len(splitted) < 2: continue

                name = splitted[1]

                #print(list(name))

                # Only look at the line corresponding to the galaxy
                if name != self.ngc_name_nospaces: continue

                #if self.ngc_name_nospaces not in name: continue

                #self.parameters.model_type = splitted[2]
                #self.parameters.number_of_components = splitted[3]
                #self.parameters.quality = splitted[4]

                ## BULGE

                #self.parameters.bulge.interpretation = splitted[sersic_1_index].split("|")[1]
                bulge_f = float(splitted[sersic_1_index + 1])
                mag = float(splitted[sersic_1_index + 2])
                bulge_fluxdensity = unitconversion.ab_to_jansky(mag) * u("Jy")

                # Effective radius in pc
                re_arcsec = float(splitted[sersic_1_index + 3]) * u("arcsec")
                bulge_re = (self.properties.distance * re_arcsec).to(
                    "pc", equivalencies=dimensionless_angles())

                bulge_q = float(splitted[sersic_1_index + 4])
                bulge_pa = Angle(
                    float(splitted[sersic_1_index + 5]) - 90., "deg")
                bulge_n = float(splitted[sersic_1_index + 6])

                # Create the bulge component
                bulge = SersicModel2D(rel_contribution=bulge_f,
                                      fluxdensity=bulge_fluxdensity,
                                      effective_radius=bulge_re,
                                      axial_ratio=bulge_q,
                                      position_angle=bulge_pa,
                                      index=bulge_n)

                # Add the bulge to the components dictionary
                self.components["bulge"] = bulge

                ## DISK

                if splitted[disk_1_index + 1] != "-":

                    #self.parameters.disk.interpretation = splitted[disk_1_index].split("|")[1]
                    disk_f = float(splitted[disk_1_index + 1])
                    mag = float(splitted[disk_1_index + 2])
                    disk_fluxdensity = unitconversion.ab_to_jansky(mag) * u(
                        "Jy")

                    # Scale length in pc
                    hr_arcsec = float(splitted[disk_1_index + 3]) * u("arcsec")
                    disk_hr = (self.properties.distance * hr_arcsec).to(
                        "pc", equivalencies=dimensionless_angles())

                    disk_q = float(splitted[disk_1_index + 4])  # axial ratio
                    disk_pa = Angle(
                        float(splitted[disk_1_index + 5]) - 90., "deg")
                    disk_mu0 = float(
                        splitted[disk_1_index + 6]) * u("mag/arcsec2")

                    # Create the disk component
                    disk = ExponentialDiskModel2D(rel_contribution=disk_f,
                                                  fluxdensity=disk_fluxdensity,
                                                  scalelength=disk_hr,
                                                  axial_ratio=disk_q,
                                                  position_angle=disk_pa,
                                                  mu0=disk_mu0)

                else:

                    # phys frel mu0    rs    hs      pa

                    disk_f = float(splitted[edgedisk_1_index + 1])
                    mag = None
                    fluxdensity = None

                    # frel mu0    rs    hs      pa

                    #print(disk_f)

                    disk_mu0 = float(
                        splitted[edgedisk_1_index + 2]) * u("mag/arcsec2")

                    #  rs    hs      pa

                    #  rs     =  radial scale lenght (arcsec)
                    #  hs     =  vertical scale height (arcsec)

                    rs = float(splitted[edgedisk_1_index + 3])
                    hs = float(splitted[edgedisk_1_index + 4])

                    #print(rs)
                    #print(hs)

                    disk_pa = Angle(
                        float(splitted[edgedisk_1_index + 5]) - 90., "deg")

                    #print(disk_pa)

                    disk_q = hs / rs

                    # Create the disk component
                    disk = ExponentialDiskModel2D(rel_contribution=disk_f,
                                                  scalelength=rs,
                                                  axial_ratio=disk_q,
                                                  position_angle=disk_pa,
                                                  mu0=disk_mu0)

                # Add the disk to the components dictionary
                self.components["disk"] = disk

        # Set the disk position angle
        self.disk_pa = self.components["disk"].position_angle
from astropy import units as u
from astropy import constants
from masscalc import distance, centerfreq as freq

im = fits.getdata(paths.dpath('W51_te_continuum_best.fits'))
hd = fits.getheader(paths.dpath('W51_te_continuum_best.fits'))
beam = radio_beam.Beam.from_fits_header(hd)

e2e_peak_flux = im[1350:1400, 850:867].max() * u.Jy
e2e_peak_tb = e2e_peak_flux.to(u.K, beam.jtok_equiv(freq))
print("e2e peak brightness: {0}".format(e2e_peak_tb))

e2e_luminosity = (constants.sigma_sb * (e2e_peak_tb)**4 *
                  (4 * np.pi * (beam.major * distance) *
                   (beam.minor * distance) / (8 * np.log(2)))).to(
                       u.L_sun, u.dimensionless_angles())
print("e2e luminosity: {0}".format(e2e_luminosity))

e2e_dustmass = dust_emissivity.dust.massofsnu(freq,
                                              e2e_peak_flux,
                                              distance=distance,
                                              temperature=e2e_peak_tb)
print("e2e dust mass: {0}".format(e2e_dustmass))

e2e_peak_column = dust_emissivity.dust.colofsnu(freq,
                                                e2e_peak_flux,
                                                beamomega=beam,
                                                temperature=100 * u.K).to(
                                                    u.cm**-2,
                                                    u.dimensionless_angles())
print("e2e peak column (T=100K): {0}".format(e2e_peak_column))
Example #38
0
 def d_DDdelay_d_par(self, par):
     """Full DD model delay derivtive"""
     with u.set_enabled_equivalencies(u.dimensionless_angles()):
         return (self.d_delayI_d_par(par) + self.d_delayS_d_par(par) +
                 self.d_delayA_d_par(par))
Example #39
0
def test_gyroradius():
    r"""Test the gyroradius function in parameters.py."""

    assert gyroradius(B, T_i=T_e).unit.is_equivalent(u.m)

    assert gyroradius(B, Vperp=25 * u.m / u.s).unit.is_equivalent(u.m)

    Vperp = 1e6 * u.m / u.s
    Bmag = 1 * u.T
    omega_ce = gyrofrequency(Bmag)
    analytical_result = (Vperp / omega_ce).to(
        u.m, equivalencies=u.dimensionless_angles()
    )
    assert gyroradius(Bmag, Vperp=Vperp) == analytical_result

    with pytest.raises(TypeError):
        gyroradius(u.T)

    with pytest.raises(u.UnitTypeError):
        gyroradius(5 * u.A, Vperp=8 * u.m / u.s)

    with pytest.raises(u.UnitTypeError):
        gyroradius(5 * u.T, Vperp=8 * u.m)

    with pytest.raises(ValueError):
        gyroradius(np.array([5, 6]) * u.T, Vperp=np.array([5, 6, 7]) * u.m / u.s)

    assert np.isnan(gyroradius(np.nan * u.T, Vperp=1 * u.m / u.s))

    with pytest.raises(ValueError):
        gyroradius(3.14159 * u.T, T_i=-1 * u.K)

    with pytest.warns(u.UnitsWarning):
        assert gyroradius(1.0, Vperp=1.0) == gyroradius(
            1.0 * u.T, Vperp=1.0 * u.m / u.s
        )

    with pytest.warns(u.UnitsWarning):
        assert gyroradius(1.1, T_i=1.2) == gyroradius(1.1 * u.T, T_i=1.2 * u.K)

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, Vperp=1 * u.m / u.s, T_i=1.2 * u.K)

    with pytest.raises(u.UnitTypeError):
        gyroradius(1.1 * u.T, Vperp=1.1 * u.m, T_i=1.2 * u.K)

    assert gyroradius(B, particle="p", T_i=T_i).unit.is_equivalent(u.m)

    assert gyroradius(B, particle="p", Vperp=25 * u.m / u.s).unit.is_equivalent(u.m)

    # Case when Z=1 is assumed
    assert np.isclose(
        gyroradius(B, particle="p", T_i=T_i),
        gyroradius(B, particle="H+", T_i=T_i),
        atol=1e-6 * u.m,
    )

    gyroPos = gyroradius(B, particle="p", Vperp=V)
    gyroNeg = gyroradius(B, particle="p", Vperp=-V)
    assert gyroPos == gyroNeg

    Vperp = 1e6 * u.m / u.s
    Bmag = 1 * u.T
    omega_ci = gyrofrequency(Bmag, particle="p")
    analytical_result = (Vperp / omega_ci).to(
        u.m, equivalencies=u.dimensionless_angles()
    )
    assert gyroradius(Bmag, particle="p", Vperp=Vperp) == analytical_result

    T2 = 1.2 * u.MK
    B2 = 123 * u.G
    particle2 = "alpha"
    Vperp2 = thermal_speed(T2, particle=particle2)
    gyro_by_vperp = gyroradius(B2, particle="alpha", Vperp=Vperp2)
    assert gyro_by_vperp == gyroradius(B2, particle="alpha", T_i=T2)

    explicit_positron_gyro = gyroradius(1 * u.T, particle="positron", T_i=1 * u.MK)
    assert explicit_positron_gyro == gyroradius(1 * u.T, T_i=1 * u.MK)

    with pytest.raises(TypeError):
        gyroradius(u.T, particle="p", Vperp=8 * u.m / u.s)

    with pytest.raises(ValueError):
        gyroradius(B, particle="p", T_i=-1 * u.K)

    with pytest.warns(u.UnitsWarning):
        gyro_without_units = gyroradius(1.0, particle="p", Vperp=1.0)
        gyro_with_units = gyroradius(1.0 * u.T, particle="p", Vperp=1.0 * u.m / u.s)
        assert gyro_without_units == gyro_with_units

    with pytest.warns(u.UnitsWarning):
        gyro_t_without_units = gyroradius(1.1, particle="p", T_i=1.2)
        gyro_t_with_units = gyroradius(1.1 * u.T, particle="p", T_i=1.2 * u.K)
        assert gyro_t_with_units == gyro_t_without_units

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, particle="p", Vperp=1 * u.m / u.s, T_i=1.2 * u.K)

    with pytest.raises(u.UnitTypeError):
        gyroradius(1.1 * u.T, particle="p", Vperp=1.1 * u.m, T_i=1.2 * u.K)

    with pytest.raises(u.UnitTypeError):
        gyroradius(1.1 * u.T, particle="p", Vperp=1.2 * u.m, T_i=1.1 * u.K)
Example #40
0
        elif 'HERACOMING' in galaxy_ratios['SURVEY_PAIR']:
            idx = galaxy_ratios['SURVEY_PAIR'] == 'HERACOMING'
            r21_gal = 10**galaxy_ratios[idx]['LOGRAT'][0]
        elif 'HERANROATLAS' in galaxy_ratios['SURVEY_PAIR']:
            idx = galaxy_ratios['SURVEY_PAIR'] == 'HERANROATLAS'
            r21_gal = 10**galaxy_ratios[idx]['LOGRAT'][0]
        else:
            print('No galaxy-specific R21 value found for ' + galaxy['NAME'] +
                  ". Using fiducial value.")
            r21_gal = r21

        # convert Re to to kpc
        # The input map is in Mstar/yr/kpc^2, so I think I want the output unit to be Mstar/yr/kpc^2.
        re_kpc = ((galaxy['RE_ARCSEC'] * u.arcsec) *
                  (galaxy['DIST_MPC'] * u.Mpc)).to(
                      u.kpc, equivalencies=u.dimensionless_angles())

        # now do more complex spatial scaling
        sfrR21scale(cube,
                    sigmaSFR,
                    galaxy=galaxy['NAME'],
                    re=re_kpc.value,
                    sfr=10**galaxy['LOGSFR'],
                    r21=r21_gal,
                    r21_ref=r21_ref)

        sfrR21scale(mom0,
                    sigmaSFR,
                    galaxy=galaxy['NAME'],
                    re=re_kpc.value,
                    sfr=10**galaxy['LOGSFR'],
Example #41
0
def test_gyroradius():
    r"""Test the gyroradius function in parameters.py."""

    assert gyroradius(B, T_e).unit == u.m

    assert gyroradius(B, 25 * u.m / u.s).unit == u.m

    assert gyroradius(T_e, B) == gyroradius(B, T_e)

    assert gyroradius(V, B) == gyroradius(B, V)

    assert gyroradius(B, V) == gyroradius(B, -V)

    Vperp = 1e6 * u.m / u.s
    Bmag = 1 * u.T
    omega_ce = gyrofrequency(Bmag)
    assert gyroradius(Bmag, Vperp) == \
        (Vperp / omega_ce).to(u.m, equivalencies=u.dimensionless_angles())

    with pytest.raises(TypeError):
        gyroradius(u.T, 8 * u.m / u.s)

    with pytest.raises(u.UnitConversionError):
        gyroradius(5 * u.A, 8 * u.m / u.s)

    with pytest.raises(u.UnitConversionError):
        gyroradius(5 * u.T, 8 * u.m)

    with pytest.raises(ValueError):
        gyroradius(np.array([5, 6]) * u.T, np.array([5, 6, 7]) * u.m / u.s)

    with pytest.raises(ValueError):
        gyroradius(np.nan * u.T, 1 * u.m / u.s)

    with pytest.raises(ValueError):
        gyroradius(3.14159 * u.T, -1 * u.K)

    with pytest.raises(UserWarning):
        assert gyroradius(1.0, Vperp=1.0) == \
            gyroradius(1.0 * u.T, Vperp=1.0 * u.m / u.s)

    with pytest.raises(UserWarning):
        assert gyroradius(1.1, T_i=1.2) == \
            gyroradius(1.1 * u.T, T_i=1.2 * u.K)

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, T_i=1.2 * u.K, Vperp=1 * u.m / u.s)

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, 1.2 * u.K, 1.1 * u.m)

    assert gyroradius(B, T_i, particle="p").unit == u.m

    assert gyroradius(B, 25 * u.m / u.s, particle="p").unit == u.m

    # Case when Z=1 is assumed
    assert gyroradius(B, T_i, particle='p') == \
        gyroradius(B, T_i, particle='H-1')

    assert gyroradius(T_i, B, particle="p") == gyroradius(B, T_i, particle="p")

    assert gyroradius(V, B, particle="p") == gyroradius(B, V, particle="p")

    assert gyroradius(B, V, particle="p") == gyroradius(B, -V, particle="p")

    Vperp = 1e6 * u.m / u.s
    Bmag = 1 * u.T
    omega_ci = gyrofrequency(Bmag, particle='p')
    assert gyroradius(Bmag, Vperp, particle="p") == \
        (Vperp / omega_ci).to(u.m, equivalencies=u.dimensionless_angles())

    T2 = 1.2 * u.MK
    B2 = 123 * u.G
    particle2 = 'alpha'
    Vperp2 = thermal_speed(T2, particle=particle2)
    assert gyroradius(B2, Vperp=Vperp2, particle='alpha') == \
        gyroradius(B2, T_i=T2, particle='alpha')

    assert gyroradius(1 * u.T, 1 * u.MK, particle='positron') == \
        gyroradius(1 * u.T, 1 * u.MK)

    with pytest.raises(TypeError):
        gyroradius(u.T, 8 * u.m / u.s, particle="p")

    with pytest.raises(ValueError):
        gyroradius(B, T_i, particle='asfdas')

    with pytest.raises(ValueError):
        gyroradius(B, -1 * u.K, particle='p')

    with pytest.raises(UserWarning):
        assert gyroradius(1.0, Vperp=1.0, particle="p") == \
            gyroradius(1.0 * u.T, Vperp=1.0 * u.m / u.s, particle="p")

    with pytest.raises(UserWarning):
        assert gyroradius(1.1, T_i=1.2, particle="p") == \
            gyroradius(1.1 * u.T, T_i=1.2 * u.K, particle="p")

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, T_i=1.2 * u.K, Vperp=1 * u.m / u.s, particle="p")

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, 1.2 * u.K, 1.1 * u.m, particle="p")

    with pytest.raises(ValueError):
        gyroradius(1.1 * u.T, 1.2 * u.m, 1.1 * u.K, particle="p")
Example #42
0
def gyroradius(B: u.T,
               particle='e-',
               *,
               Vperp: u.m / u.s = np.nan * u.m / u.s,
               T_i: u.K = np.nan * u.K):
    r"""Return the particle gyroradius.

    Parameters
    ----------
    B : ~astropy.units.Quantity
        The magnetic field magnitude in units convertible to tesla.

    particle : str, optional
        Representation of the particle species (e.g., `'p'` for protons, `'D+'`
        for deuterium, or `'He-4 +1'` for singly ionized helium-4),
        which defaults to electrons.  If no charge state information is
        provided, then the particles are assumed to be singly charged.

    Vperp : ~astropy.units.Quantity, optional
        The component of particle velocity that is perpendicular to the
        magnetic field in units convertible to meters per second.
        Must be input as a keyword argument.

    T_i : ~astropy.units.Quantity, optional
        The particle temperature in units convertible to kelvin.
        Must be input as a keyword argument.

    Returns
    -------
    r_Li : ~astropy.units.Quantity
        The particle gyroradius in units of meters.  This
        ~astropy.units.Quantity will be based on either the
        perpendicular component of particle velocity as inputted, or
        the most probable speed for an particle within a Maxwellian
        distribution for the particle temperature.

    Raises
    ------
    TypeError
        The arguments are of an incorrect type

    ~astropy.units.UnitConversionError
        The arguments do not have appropriate units

    ValueError
        If any argument contains invalid values

    Warns
    -----
    ~astropy.units.UnitsWarning
        If units are not provided, SI units are assumed

    Notes
    -----
    One but not both of `Vperp` and `T_i` must be inputted.

    If any of `B`, `Vperp`, or `T_i` is a number rather than a
    `~astropy.units.Quantity`, then SI units will be assumed and a
    warning will be raised.

    The particle gyroradius is also known as the particle Larmor
    radius and is given by

    .. math::
        r_{Li} = \frac{V_{\perp}}{omega_{ci}}

    where :math:`V_{\perp}` is the component of particle velocity that is
    perpendicular to the magnetic field and :math:`\omega_{ci}` is the
    particle gyrofrequency.  If a temperature is provided, then
    :math:`V_\perp` will be the most probable thermal velocity of an
    particle at that temperature.

    Examples
    --------
    >>> from astropy import units as u
    >>> gyroradius(0.2*u.T,particle='p+',T_i=1e5*u.K)
    <Quantity 0.00212087 m>
    >>> gyroradius(0.2*u.T,particle='p+',T_i=1e5*u.K)
    <Quantity 0.00212087 m>
    >>> gyroradius(5*u.uG,particle='alpha',T_i=1*u.eV)
    <Quantity 288002.38837768 m>
    >>> gyroradius(400*u.G,particle='Fe+++',Vperp=1e7*u.m/u.s)
    <Quantity 48.23129811 m>
    >>> gyroradius(B=0.01*u.T,T_i=1e6*u.K)
    <Quantity 0.00313033 m>
    >>> gyroradius(B=0.01*u.T,Vperp=1e6*u.m/u.s)
    <Quantity 0.00056856 m>
    >>> gyroradius(0.2*u.T,T_i=1e5*u.K)
    <Quantity 4.94949252e-05 m>
    >>> gyroradius(5*u.uG,T_i=1*u.eV)
    <Quantity 6744.2598183 m>
    >>> gyroradius(400*u.G,Vperp=1e7*u.m/u.s)
    <Quantity 0.00142141 m>

    """

    isfinite_Ti = np.isfinite(T_i)
    isfinite_Vperp = np.isfinite(Vperp)

    # check 1: ensure either Vperp or T_i invalid, keeping in mind that
    # the underlying values of the astropy quantity may be numpy arrays
    if np.any(np.logical_not(np.logical_xor(isfinite_Vperp, isfinite_Ti))):
        raise ValueError(
            "Must give Vperp or T_i, but not both, as arguments to gyroradius")

    # check 2: get Vperp as the thermal speed if is not already a valid input
    if np.isscalar(Vperp.value) and np.isscalar(
            T_i.value):  # both T_i and Vperp are scalars
        # we know exactly one of them is nan from check 1
        if isfinite_Ti:
            # T_i is valid, so use it to determine Vperp
            Vperp = thermal_speed(T_i, particle=particle)
        # else: Vperp is alread valid, do nothing
    elif np.isscalar(Vperp.value):  # only T_i is an array
        # this means either Vperp must be nan, or T_i must be array of all nan,
        # or else we couldn't have gotten through check 1
        if isfinite_Vperp:
            # Vperp is valid, T_i is a vector that is all nan
            # uh...
            Vperp = np.repeat(Vperp, len(T_i))
        else:
            # normal case where Vperp is scalar nan and T_i is valid array
            Vperp = thermal_speed(T_i, particle=particle)
    elif np.isscalar(T_i.value):  # only Vperp is an array
        # this means either T_i must be nan, or V_perp must be array of all nan,
        # or else we couldn't have gotten through check 1
        if isfinite_Ti:
            # T_i is valid, V_perp is an array of all nan
            # uh...
            Vperp = thermal_speed(np.repeat(T_i, len(Vperp)),
                                  particle=particle)
        # else: normal case where T_i is scalar nan and Vperp is already a valid array
        # so, do nothing
    else:  # both T_i and Vperp are arrays
        # we know all the elementwise combinations have one nan and one finite, due to check 1
        # use the valid Vperps, and replace the others with those calculated from T_i
        Vperp = Vperp.copy()  # avoid changing Vperp's value outside function
        Vperp[isfinite_Ti] = thermal_speed(T_i[isfinite_Ti], particle=particle)

    omega_ci = gyrofrequency(B, particle)

    r_Li = np.abs(Vperp) / omega_ci

    return r_Li.to(u.m, equivalencies=u.dimensionless_angles())
Example #43
0
def fold(fh,
         comm,
         samplerate,
         fedge,
         fedge_at_top,
         nchan,
         nt,
         ntint,
         ngate,
         ntbin,
         ntw,
         dm,
         fref,
         phasepol,
         dedisperse='incoherent',
         do_waterfall=True,
         do_foldspec=True,
         verbose=True,
         progress_interval=100,
         rfi_filter_raw=None,
         rfi_filter_power=None,
         return_fits=False):
    """
    FFT data, fold by phase/time and make a waterfall series

    Folding is done from the position the file is currently in

    Parameters
    ----------
    fh : file handle
        handle to file holding voltage timeseries
    comm: MPI communicator or None
        will use size, rank attributes
    samplerate : Quantity
        rate at which samples were originally taken and thus double the
        band width (frequency units)
    fedge : float
        edge of the frequency band (frequency units)
    fedge_at_top: bool
        whether edge is at top (True) or bottom (False)
    nchan : int
        number of frequency channels for FFT
    nt, ntint : int
        total number nt of sets, each containing ntint samples in each file
        hence, total # of samples is nt*ntint, with each sample containing
        a single polarisation
    ngate, ntbin : int
        number of phase and time bins to use for folded spectrum
        ntbin should be an integer fraction of nt
    ntw : int
        number of time samples to combine for waterfall (does not have to be
        integer fraction of nt)
    dm : float
        dispersion measure of pulsar, used to correct for ism delay
        (column number density)
    fref: float
        reference frequency for dispersion measure
    phasepol : callable
        function that returns the pulsar phase for time in seconds relative to
        start of the file that is read.
    dedisperse : None or string (default: incoherent).
        None, 'incoherent', 'coherent', 'by-channel'.
        Note: None really does nothing
    do_waterfall, do_foldspec : bool
        whether to construct waterfall, folded spectrum (default: True)
    verbose : bool or int
        whether to give some progress information (default: True)
    progress_interval : int
        Ping every progress_interval sets
    return_fits : bool (default: False)
        return a subint fits table for rank == 0 (None otherwise)

    """
    assert dedisperse in (None, 'incoherent', 'by-channel', 'coherent')
    assert nchan % fh.nchan == 0
    if dedisperse == 'by-channel':
        oversample = nchan // fh.nchan
        assert ntint % oversample == 0
    else:
        oversample = 1

    if dedisperse == 'coherent' and fh.nchan > 1:
        raise ValueError("For coherent dedispersion, data must be "
                         "unchannelized before folding.")

    if comm is None:
        mpi_rank = 0
        mpi_size = 1
    else:
        mpi_rank = comm.rank
        mpi_size = comm.size

    npol = getattr(fh, 'npol', 1)
    assert npol == 1 or npol == 2
    if verbose > 1 and mpi_rank == 0:
        print("Number of polarisations={}".format(npol))

    # initialize folded spectrum and waterfall
    # TODO: use estimated number of points to set dtype
    if do_foldspec:
        foldspec = np.zeros((ntbin, nchan, ngate, npol**2), dtype=np.float32)
        icount = np.zeros((ntbin, nchan, ngate), dtype=np.int32)
    else:
        foldspec = None
        icount = None

    if do_waterfall:
        nwsize = nt * ntint // ntw
        waterfall = np.zeros((nwsize, nchan, npol**2), dtype=np.float64)
    else:
        waterfall = None

    if verbose and mpi_rank == 0:
        print('Reading from {}'.format(fh))

    nskip = fh.tell() / fh.blocksize
    if nskip > 0:
        if verbose and mpi_rank == 0:
            print('Starting {0} blocks = {1} bytes out from start.'.format(
                nskip, nskip * fh.blocksize))

    dt1 = (1. / samplerate).to(u.s)
    # need 2*nchan real-valued samples for each FFT
    if fh.telescope == 'lofar':
        dtsample = fh.dtsample
    else:
        dtsample = nchan // oversample * 2 * dt1
    tstart = dtsample * ntint * nskip

    # pre-calculate time delay due to dispersion in coarse channels
    # for channelized data, frequencies are known

    if fh.nchan == 1:
        if getattr(fh, 'data_is_complex', False):
            # for complex data, really each complex sample consists of
            # 2 real ones, so multiply dt1 by 2.
            if fedge_at_top:
                freq = fedge - fftfreq(nchan, 2. * dt1.value) * u.Hz
            else:
                freq = fedge + fftfreq(nchan, 2. * dt1.value) * u.Hz
        else:
            if fedge_at_top:
                freq = fedge - rfftfreq(nchan * 2, dt1.value)[::2] * u.Hz
            else:
                freq = fedge + rfftfreq(nchan * 2, dt1.value)[::2] * u.Hz
        freq_in = freq
    else:
        # input frequencies may not be the ones going out
        freq_in = fh.frequencies
        if oversample == 1:
            freq = freq_in
        else:
            if fedge_at_top:
                freq = (freq_in[:, np.newaxis] -
                        u.Hz * fftfreq(oversample, dtsample.value))
            else:
                freq = (freq_in[:, np.newaxis] +
                        u.Hz * fftfreq(oversample, dtsample.value))
    ifreq = freq.ravel().argsort()

    # pre-calculate time offsets in (input) channelized streams
    dt = dispersion_delay_constant * dm * (1. / freq_in**2 - 1. / fref**2)

    if dedisperse in ['coherent', 'by-channel']:
        # pre-calculate required turns due to dispersion
        if fedge_at_top:
            fcoh = (freq_in[np.newaxis, :] -
                    u.Hz * fftfreq(ntint, dtsample.value)[:, np.newaxis])
        else:
            fcoh = (freq_in[np.newaxis, :] +
                    u.Hz * fftfreq(ntint, dtsample.value)[:, np.newaxis])

        # set frequency relative to which dispersion is coherently corrected
        if dedisperse == 'coherent':
            _fref = fref
        else:
            _fref = freq_in[np.newaxis, :]
        # (check via eq. 5.21 and following in
        # Lorimer & Kramer, Handbook of Pulsar Astronomy
        dang = (dispersion_delay_constant * dm * fcoh *
                (1. / _fref - 1. / fcoh)**2) * u.cycle

        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            dd_coh = np.exp(dang * 1j).conj().astype(np.complex64)

        # add dimension for polarisation
        dd_coh = dd_coh[..., np.newaxis]

    # Calculate the part of the whole file this node should handle.
    size_per_node = (nt - 1) // mpi_size + 1
    start_block = mpi_rank * size_per_node
    end_block = min((mpi_rank + 1) * size_per_node, nt)
    for j in range(start_block, end_block):
        if verbose and j % progress_interval == 0:
            print('#{:4d}/{:4d} is doing {:6d}/{:6d} [={:6d}/{:6d}]; '
                  'time={:18.12f}'.format(
                      mpi_rank, mpi_size, j + 1, nt, j - start_block + 1,
                      end_block - start_block,
                      (tstart +
                       dtsample * j * ntint).value))  # time since start

        # Just in case numbers were set wrong -- break if file ends;
        # better keep at least the work done.
        try:
            raw = fh.seek_record_read(int((nskip + j) * fh.blocksize),
                                      fh.blocksize)
        except (EOFError, IOError) as exc:
            print("Hit {0!r}; writing data collected.".format(exc))
            break
        if verbose >= 2:
            print("#{:4d}/{:4d} read {} items".format(mpi_rank, mpi_size,
                                                      raw.size),
                  end="")

        if npol == 2:  # multiple polarisations
            raw = raw.view(raw.dtype.fields.values()[0][0])

        if fh.nchan == 1:  # raw.shape=(ntint*npol)
            raw = raw.reshape(-1, npol)
        else:  # raw.shape=(ntint, nchan*npol)
            raw = raw.reshape(-1, fh.nchan, npol)

        if rfi_filter_raw is not None:
            raw, ok = rfi_filter_raw(raw)
            if verbose >= 2:
                print("... raw RFI (zap {0}/{1})".format(
                    np.count_nonzero(~ok), ok.size),
                      end="")

        if np.can_cast(raw.dtype, np.float32):
            vals = raw.astype(np.float32)
        else:
            assert raw.dtype.kind == 'c'
            vals = raw

        if fh.nchan == 1:
            # have real-valued time stream of complex baseband
            # if we need some coherentdedispersion, do FT of whole thing,
            # otherwise to output channels
            if raw.dtype.kind == 'c':
                ftchan = nchan if dedisperse == 'incoherent' else len(vals)
                vals = fft(vals.reshape(-1, ftchan, npol),
                           axis=1,
                           overwrite_x=True,
                           **_fftargs)
            else:  # real data
                ftchan = nchan if dedisperse == 'incoherent' else len(
                    vals) // 2
                vals = rfft(vals.reshape(-1, ftchan * 2, npol),
                            axis=1,
                            overwrite_x=True,
                            **_fftargs)
                # rfft: Re[0], Re[1], Im[1], ..., Re[n/2-1], Im[n/2-1], Re[n/2]
                # re-order to normal fft format (like Numerical Recipes):
                # Re[0], Re[n], Re[1], Im[1], .... (channel 0 is junk anyway)
                vals = np.hstack(
                    (vals[:, 0], vals[:, -1], vals[:,
                                                   1:-1])).view(np.complex64)
            # for incoherent, vals.shape=(ntint, nchan, npol) -> OK
            # for others, have           (1, ntint*nchan, npol)
            # reshape(nchan, ntint) gives rough as slowly varying -> .T
            if dedisperse != 'incoherent':
                fine = vals.reshape(nchan, -1, npol).transpose(1, 0, 2)
                # now have fine.shape=(ntint, nchan, npol)

        else:  # data already channelized
            if dedisperse == 'by-channel':
                fine = fft(vals, axis=0, overwrite_x=True, **_fftargs)
                # have fine.shape=(ntint, fh.nchan, npol)

        if dedisperse in ['coherent', 'by-channel']:
            fine *= dd_coh
            # rechannelize to output channels
            if oversample > 1 and dedisperse == 'by-channel':
                # fine.shape=(ntint*oversample, chan_in, npol)
                #           =(coarse,fine,fh.chan, npol)
                #  -> reshape(oversample, ntint, fh.nchan, npol)
                # want (ntint=fine, fh.nchan, oversample, npol) -> .transpose
                fine = (fine.reshape(oversample, -1, fh.nchan, npol).transpose(
                    1, 2, 0, 3).reshape(-1, nchan, npol))
            # now, for both,     fine.shape=(ntint, nchan, npol)
            vals = ifft(fine, axis=0, overwrite_x=True, **_fftargs)
            # vals[time, chan, pol]
            if verbose >= 2:
                print("... dedispersed", end="")

        if npol == 1:
            power = vals.real**2 + vals.imag**2
        else:
            p0 = vals[..., 0]
            p1 = vals[..., 1]
            power = np.empty(vals.shape[:-1] + (4, ), np.float32)
            power[..., 0] = p0.real**2 + p0.imag**2
            power[..., 1] = p0.real * p1.real + p0.imag * p1.imag
            power[..., 2] = p0.imag * p1.real - p0.real * p1.imag
            power[..., 3] = p1.real**2 + p1.imag**2

        if verbose >= 2:
            print("... power", end="")

        if rfi_filter_power is not None:
            power = rfi_filter_power(power)
            print("... power RFI", end="")

        # current sample positions in stream
        isr = j * (ntint // oversample) + np.arange(ntint // oversample)

        if do_waterfall:
            # loop over corresponding positions in waterfall
            for iw in xrange(isr[0] // ntw, isr[-1] // ntw + 1):
                if iw < nwsize:  # add sum of corresponding samples
                    waterfall[iw, :] += np.sum(power[isr // ntw == iw],
                                               axis=0)[ifreq]
            if verbose >= 2:
                print("... waterfall", end="")

        if do_foldspec:
            ibin = (j * ntbin) // nt  # bin in the time series: 0..ntbin-1

            # times since start
            tsample = (tstart + isr * dtsample * oversample)[:, np.newaxis]
            # correct for delay if needed
            if dedisperse in ['incoherent', 'by-channel']:
                # tsample.shape=(ntint/oversample, nchan_in)
                tsample = tsample - dt

            phase = (phasepol(tsample.to(u.s).value.ravel()).reshape(
                tsample.shape))
            # corresponding PSR phases
            iphase = np.remainder(phase * ngate, ngate).astype(np.int)

            for k, kfreq in enumerate(ifreq):  # sort in frequency while at it
                iph = iphase[:, (0 if iphase.shape[1] == 1 else kfreq //
                                 oversample)]
                # sum and count samples by phase bin
                for ipow in xrange(npol**2):
                    foldspec[ibin, k, :,
                             ipow] += np.bincount(iph, power[:, kfreq, ipow],
                                                  ngate)
                icount[ibin,
                       k, :] += np.bincount(iph, power[:, kfreq, 0] != 0.,
                                            ngate)

            if verbose >= 2:
                print("... folded", end="")

        if verbose >= 2:
            print("... done")

    #Commented out as workaround, this was causing "Referenced before assignment" errors with JB data
    #if verbose >= 2 or verbose and mpi_rank == 0:
    #    print('#{:4d}/{:4d} read {:6d} out of {:6d}'
    #          .format(mpi_rank, mpi_size, j+1, nt))

    if npol == 1:
        if do_foldspec:
            foldspec = foldspec.reshape(foldspec.shape[:-1])
        if do_waterfall:
            waterfall = waterfall.reshape(waterfall.shape[:-1])

    return foldspec, icount, waterfall
Example #44
0
 def ELL1_om(self):
     # arctan(om)
     om = np.arctan2(self.eps1(), self.eps2())
     return om.to(u.deg, equivalencies=u.dimensionless_angles())
Example #45
0
 def d_kin_proper_motion_d_T0(self):
     d_DKIN_d_T0 = -1 * (-self.PMRA_DDK * self.sin_KOM +
                         self.PMDEC_DDK * self.cos_KOM)
     return d_DKIN_d_T0.to(self.KIN.unit / self.T0.unit,
                           equivalencies=u.dimensionless_angles())
    def test_vgal_to_hel_single(self):

        for row in self.data:  # test one entry at a time
            c = coord.SkyCoord(ra=row['ra'] * u.deg,
                               dec=row['dec'] * u.deg,
                               distance=row['dist'] * u.pc)
            gal = c.galactic
            vxyz = [row['U'], row['V'], row['W']] * u.km / u.s

            vhel = vgal_to_hel(gal,
                               vxyz,
                               vcirc=0. * u.km / u.s,
                               vlsr=[0., 0, 0] * u.km / u.s,
                               galactocentric_frame=self.galcen_frame)

            # tolerance set by the catalog rounded numbers
            assert quantity_allclose(vhel[0],
                                     row['pml'] * u.mas / u.yr,
                                     rtol=1E-2)
            assert quantity_allclose(vhel[1],
                                     row['pmb'] * u.mas / u.yr,
                                     rtol=1E-2)
            assert quantity_allclose(vhel[2],
                                     row['rv'] * u.km / u.s,
                                     rtol=1E-2)

        # --------------------------------------------------------------------
        # l = 0
        # without LSR and circular velocity
        c = coord.SkyCoord(l=0 * u.deg,
                           b=0 * u.deg,
                           distance=2 * u.kpc,
                           frame=coord.Galactic)
        vxyz = [20., 0, 0] * u.km / u.s
        vhel = vgal_to_hel(c.galactic,
                           vxyz,
                           vcirc=0 * u.km / u.s,
                           vlsr=[0., 0, 0] * u.km / u.s,
                           galactocentric_frame=self.galcen_frame)

        assert np.allclose(vhel[0].value, 0., atol=1E-12)
        assert np.allclose(vhel[1].value, 0., atol=1E-12)
        assert np.allclose(vhel[2].to(u.km / u.s).value, 20., atol=1E-12)

        vxyz = [20., 0, 50] * u.km / u.s
        vhel = vgal_to_hel(c.galactic,
                           vxyz,
                           vcirc=0 * u.km / u.s,
                           vlsr=[0., 0, 0] * u.km / u.s,
                           galactocentric_frame=self.galcen_frame)

        assert np.allclose(vhel[0].value, 0.,
                           atol=2E-5)  # TODO: astropy precision issues
        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            assert quantity_allclose(vhel[1],
                                     50 * u.km / u.s / (2 * u.kpc),
                                     atol=1E-10 * u.mas / u.yr)
        assert quantity_allclose(vhel[2].to(u.km / u.s),
                                 vxyz[0],
                                 atol=1E-10 * u.km / u.s)

        # with LSR and circular velocity
        vxyz = [20., 0, 50] * u.km / u.s
        vhel = vgal_to_hel(c.galactic,
                           vxyz,
                           vcirc=-200 * u.km / u.s,
                           vlsr=[0., 0, 10] * u.km / u.s,
                           galactocentric_frame=self.galcen_frame)

        with u.set_enabled_equivalencies(u.dimensionless_angles()):
            assert quantity_allclose(vhel[0],
                                     (200. * u.km / u.s) / (2 * u.kpc),
                                     atol=1E-10 * u.mas / u.yr)
            assert quantity_allclose(vhel[1], (40. * u.km / u.s) / (2 * u.kpc),
                                     atol=1E-6 * u.mas / u.yr)

        assert quantity_allclose(vhel[2],
                                 20. * u.km / u.s,
                                 atol=1E-10 * u.km / u.s)
Example #47
0
def virial_mass_estimator(cluster):
    """
    Calculates virial masses of galaxy clusters with the virial mass formula

    Parameters
    ----------
    cluster: Cluster object

    Returns
    -------
    mass: float
        Mass of cluster in M_sun

    cluster_vel_disp: float
        Estimated velocity dispersion of cluster in (km/s)**2

    cluster_radius: float
        Estimated radius of cluster in Mpc
    """
    member_galaxies = cluster.galaxies

    # velocity dispersion
    cluster_size = len(member_galaxies)
    z_arr = member_galaxies[:, 2]

    average_redshift = np.mean(z_arr)
    cluster_vel = redshift_to_velocity(z_arr, average_redshift)
    cluster_vel_err = velocity_error(cluster, z_arr, average_redshift,
                                     cluster_vel)
    cluster_vel_disp = velocity_dispersion(cluster_vel, cluster_size)

    bootfunc = lambda x: (velocity_dispersion(x, len(x)))
    bootstrap_disp = np.std(bootstrapping(cluster_vel.value, bootfunc))
    harmonic_disp = (1 / cluster_size) * (sum(1 / (cluster_vel_err**2)))**(-1)
    combined_disp_err = (np.sqrt(harmonic_disp.value**2 +
                                 (bootstrap_disp)**2)) * (u.km**2 / u.s**2)

    # galaxy separations
    c = SkyCoord(ra=member_galaxies[:, 0] * u.degree,
                 dec=member_galaxies[:, 1] * u.degree)  # array of coordinates

    pairs_idx = np.asarray(
        list((i, j) for ((i, _), (j, _)) in itertools.combinations(
            enumerate(c), 2)))  # index of galaxies in combinations

    photoz_pairs = np.take(
        z_arr, pairs_idx)  # photoz values of galaxies from the indices

    d_A = cosmo.angular_diameter_distance(
        z=average_redshift)  # angular diameter distance

    pairs = c[pairs_idx]

    projected_sep = pairs[:, 0].separation(
        pairs[:, 1])  # projected separation (in deg)
    actual_sep = (projected_sep * d_A).to(
        u.Mpc, u.dimensionless_angles())  # convert projected separation to Mpc

    actual_sep = ((actual_sep * ((cosmo.H0 / 100).value)) / u.littleh).to(
        u.Mpc / u.littleh)  # include littleh scaling
    total_separation = sum(1 / actual_sep)

    cluster_radius = projected_radius(cluster_size, total_separation)
    mass = cluster_mass(cluster_vel_disp, cluster_radius)
    mass_err = mass_error(mass, cluster_vel_disp, combined_disp_err)

    return (
        mass,
        mass_err,
        cluster_vel_disp,
        combined_disp_err,
        cluster_radius,
    )  # M_sun/littleh, km^2/s^2, Mpc/littleh
Example #48
0
 def ELL1_T0(self):
     return self.TASC + self.pb() / (2 * np.pi) * (np.arctan(
         self.eps1() / self.eps2())).to(
             u.Unit(""), equivalencies=u.dimensionless_angles())
Example #49
0
    def create_dust_grids(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Creating the grids ...")

        # Calculate the major radius of the truncation ellipse in physical coordinates (pc)
        semimajor_angular = self.truncation_ellipse.semimajor  # semimajor axis length of the sky ellipse
        radius_physical = (semimajor_angular * self.galaxy_distance).to(
            "pc", equivalencies=dimensionless_angles())

        # Get the pixelscale in physical units
        pixelscale_angular = self.definition.basic_maps_minimum_average_pixelscale.to(
            "deg")
        #pixelscale_angular = self.reference_wcs.average_pixelscale.to("deg")  # in deg
        pixelscale = (pixelscale_angular * self.galaxy_distance).to(
            "pc", equivalencies=dimensionless_angles())

        # BINTREE: (smallest_cell_pixels, min_level, max_mass_fraction)
        # Low-resolution: 10., 6, 1e-5
        # High-resolution: 0.5, 9, 0.5e-6

        # OCTTREE:
        # Low-resolution: 10., 2, 1e-5
        # High-resolution: 0.5, 3, 0.5e-6

        # Because we (currently) can't position the grid exactly as the 2D pixels (rotation etc.),
        # take half of the pixel size to avoid too much interpolation
        min_scale = self.config.dg.scale_range.min * pixelscale
        max_scale = self.config.dg.scale_range.max * pixelscale
        scale_range = QuantityRange(min_scale, max_scale, invert=True)

        # The range of the max mass fraction
        mass_fraction_range = RealRange(self.config.dg.mass_fraction_range.min,
                                        self.config.dg.mass_fraction_range.max,
                                        invert=True)  # must be inverted

        # Set fixed grid properties
        self.dg_generator.grid_type = self.config.dg.grid_type  # set grid type
        self.dg_generator.x_radius = radius_physical
        self.dg_generator.y_radius = radius_physical
        self.dg_generator.z_radius = self.definition.dust_scaleheight * self.config.dg.scale_heights

        # Set options
        self.dg_generator.show = False
        self.dg_generator.write = False

        # Set the range of the minimum tree level
        if self.config.dg.grid_type == "bintree":
            level_range = self.config.dg.bintree_level_range  # 6 to 9
        elif self.config.dg.grid_type == "octtree":
            level_range = self.config.dg.octtree_level_range  # 2 to 3
        else:
            level_range = None

        # Generate the dust grids
        self.dg_generator.run(scale_range=scale_range,
                              level_range=level_range,
                              mass_fraction_range=mass_fraction_range,
                              ngrids=self.config.nrepresentations)
                   vmax=vmax,
                   norm=ImageNormalize(stretch=stretch))

    (x1, y1), (x2, y2) = mywcs.wcs_world2pix(coord_limits, 0)
    ax.set_xlim(x1, x2)
    ax.set_ylim(y1, y2)
    ra = ax.coords['ra']
    ra.set_major_formatter('hh:mm:ss.s')
    ra.set_ticks(spacing=spacing * u.deg)
    dec = ax.coords['dec']
    ra.set_axislabel("RA (J2000)")
    dec.set_axislabel("Dec (J2000)")
    cb = fig.colorbar(im)
    cb.set_label("mJy/beam")

    sblength_deg = (sblength / distance).to(u.degree, u.dimensionless_angles())
    sblength_pix = sblength_deg.value / pixscale
    if name in scalebarpos and scalebarpos[name] == 'right':
        ax.plot([
            x2 - np.abs(x2 - x1) * 0.05,
            x2 - np.abs(x2 - x1) * 0.05 - sblength_pix
        ], [y1 + np.abs(y2 - y1) * 0.05] * 2,
                linewidth=3,
                color='black')
        ax.text(np.mean([
            x2 - np.abs(x2 - x1) * 0.05,
            x2 - np.abs(x2 - x1) * 0.05 - sblength_pix
        ]),
                y1 + np.abs(y2 - y1) * 0.10,
                horizontalalignment='center',
                s=str(sblength))
Example #51
0
Theta0 = 220 * u.km / u.s

# We will assume a flat rotation curve: not the best but probably OK
b = m.coords_as_GAL().b
l = m.coords_as_GAL().l
beta = (d / R0) * np.cos(b) - np.cos(l)
# Nice & Taylor (1995), Eqn. 5
# https://ui.adsabs.harvard.edu/abs/1995ApJ...441..429N/abstract
a_dot_n = (
    -np.cos(b) * (Theta0 ** 2 / R0) * (np.cos(l) + beta / (np.sin(l) ** 2 + beta ** 2))
)
# Galactic acceleration contribution to PBDOT
PBDOT_gal = (fit.model.PB.quantity * a_dot_n / c.c).decompose()
# Shklovskii contribution
PBDOT_shk = (fit.model.PB.quantity * pint.utils.pmtot(m) ** 2 * d / c.c).to(
    u.s / u.s, equivalencies=u.dimensionless_angles()
)
# the uncertainty from the Galactic acceleration isn't included
# but it's much smaller than the Shklovskii term so we'll ignore it
PBDOT_err = (fit.model.PB.quantity * pint.utils.pmtot(m) ** 2 * d_err / c.c).to(
    u.s / u.s, equivalencies=u.dimensionless_angles()
)
print(f"PBDOT_gal = {PBDOT_gal:.2e}, PBDOT_shk = {PBDOT_shk:.2e} +/- {PBDOT_err:.2e}")

# %%
# make a dense grid of Mp,Mc values to compute all of the PK parameters
mp = np.linspace(1, 2, 500) * u.Msun
mc = np.linspace(1, 2, 400) * u.Msun
Mp, Mc = np.meshgrid(mp, mc)
omdot_pred = pint.derived_quantities.omdot(
    Mp, Mc, fit.model.PB.quantity, fit.model.ECC.quantity
Example #52
0
__all__ = [
    'EarthLocation', 'BaseGeodeticRepresentation',
    'WGS84GeodeticRepresentation', 'WGS72GeodeticRepresentation',
    'GRS80GeodeticRepresentation'
]

GeodeticLocation = collections.namedtuple('GeodeticLocation',
                                          ['lon', 'lat', 'height'])

ELLIPSOIDS = {}
"""Available ellipsoids (defined in erfam.h, with numbers exposed in erfa)."""
# Note: they get filled by the creation of the geodetic classes.

OMEGA_EARTH = ((1.002_737_811_911_354_48 * u.cycle / u.day).to(
    1 / u.s, u.dimensionless_angles()))
"""
Rotational velocity of Earth, following SOFA's pvtob.

In UT1 seconds, this would be 2 pi / (24 * 3600), but we need the value
in SI seconds, so multiply by the ratio of stellar to solar day.
See Explanatory Supplement to the Astronomical Almanac, ed. P. Kenneth
Seidelmann (1992), University Science Books. The constant is the
conventional, exact one (IERS conventions 2003); see
http://hpiers.obspm.fr/eop-pc/index.php?index=constants.
"""


def _check_ellipsoid(ellipsoid=None, default='WGS84'):
    if ellipsoid is None:
        ellipsoid = default
##############################################################################
# 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`:

galcen_distance = 8*u.kpc
pm_gal_sgrA = [-6.379, -0.202] * u.mas/u.yr # from Reid & Brunthaler 2004
vy, vz = -(galcen_distance * pm_gal_sgrA).to(u.km/u.s, u.dimensionless_angles())

##############################################################################
# We still have to assume a line-of-sight velocity for the Galactic center,
# which we will again take to be 11 km/s:
vx = 11.1 * u.km/u.s

gc_frame2 = coord.Galactocentric(galcen_distance=galcen_distance,
                                 galcen_v_sun=coord.CartesianDifferential(vx, vy, vz),
                                 z_sun=0*u.pc)
gc3 = c1.transform_to(gc_frame2)
print(gc3.v_x, gc3.v_y, gc3.v_z)

##############################################################################
# The transformations also work in the opposite direction. This can be useful
# for transforming simulated or theoretical data to observable quantities. As
                       interpolation='nearest',
                       origin='lower',
                       norm=asinh_norm.AsinhNorm())
        tr_fk5 = ax.get_transform("fk5")
        #(x1,y1),(x2,y2) = (1200,434),(2142,1743)
        # wrong (x1,y1),(x2,y2) = tr_fk5.transform_point([bottomleft.ra.deg, bottomleft.dec.deg]),tr_fk5.transform_point([topright.ra.deg, topright.dec.deg])
        (x1, y1), (x2, y2) = (toplevel_wcs.wcs_world2pix(
            [[bottomleft.ra.deg, bottomleft.dec.deg]], 0)[0],
                              toplevel_wcs.wcs_world2pix(
                                  [[topright.ra.deg, topright.dec.deg]], 0)[0])

        make_scalebar(
            ax,
            scalebarpos,
            length=(0.5 * u.pc / distance).to(u.arcsec,
                                              u.dimensionless_angles()),
            color='k',
            label='0.5 pc',
            text_offset=1.0 * u.arcsec,
        )

        if regionname in ('full', 'fullN'):

            markersize = 1
            coredots = plotcores(ax,
                                 alpha=1,
                                 transform=ax.get_transform('fk5'),
                                 markerfacecolor='none',
                                 markersize=markersize,
                                 zorder=50)
Example #55
0
    def _physical_size(self):
        if not hasattr(self, "_distance"):
            raise AttributeError("No distance has not been given.")

        return (self._ang_size * self.distance).to(
            self.distance.unit, equivalencies=u.dimensionless_angles())
    proj_coldens_padded = np.pad(proj_coldens, padder, mode='constant',
                                 constant_values=np.NaN)

    proj_coldens_padded[np.isnan(proj_coldens_padded)] = 0.

    im = ax.imshow(proj_coldens_padded,
                   cmap=cmap,
                   origin='lower',
                   interpolation='nearest',
                   norm=ImageNormalize(vmin=0.0,
                                       vmax=vmax_scale,
                                       stretch=AsinhStretch()),)
    ax.set_xticks([])
    ax.set_yticks([])

    length = (1000. * u.pc / fitinfo_dict[gal]['distance']).to(u.deg, u.dimensionless_angles())
    length_pix = length.value / np.abs(hdu_coldens[0].header['CDELT2'])

    x_vals = [0.1 * proj_coldens_padded.shape[0]] * 2
    y_val1 = 0.1 * proj_coldens_padded.shape[0]
    y_val2 = 0.1 * proj_coldens_padded.shape[0] + length_pix

    ax.plot(x_vals, [y_val1, y_val2], 'k',
            linewidth=2)
    ax.text(x_vals[0], 0.07 * proj_coldens_padded.shape[0],
            "1 kpc", color='k', va='top', ha='center')

    # Galaxy name
    if gal == 'M33' or gal == 'M31':
        y_val_gal = 0.9 * proj_coldens_padded.shape[0]
    else:
Example #57
0
    def prtl_der(self, y, x):
        """Find the partial derivatives in binary model pdy/pdx

        Parameters
        ----------
        y : str
           Name of variable to be differentiated
        x : str
           Name of variable the derivative respect to

        Returns
        -------
        np.array
           The derivatives pdy/pdx
        """
        if y not in self.binary_params + self.inter_vars:
            errorMesg = y + " is not in binary parameter and variables list."
            raise ValueError(errorMesg)

        if x not in self.inter_vars + self.binary_params:
            errorMesg = x + " is not in binary parameters and variables list."
            raise ValueError(errorMesg)
        # derivative to itself
        if x == y:
            return np.longdouble(np.ones(len(self.tt0))) * u.Unit("")
        # Get the unit right

        yAttr = getattr(self, y)
        xAttr = getattr(self, x)
        U = [None, None]
        for i, attr in enumerate([yAttr, xAttr]):
            if hasattr(attr,
                       "units"):  # If attr is a PINT Parameter class type
                U[i] = attr.units
            elif hasattr(attr, "unit"):  # If attr is a Quantity type
                U[i] = attr.unit
            elif hasattr(attr, "__call__"):  # If attr is a method
                U[i] = attr().unit
            else:
                raise TypeError(type(attr) + "can not get unit")
            # U[i] = 1*U[i]

            # commonU = list(set(U[i].unit.bases).intersection([u.rad,u.deg]))
            # if commonU != []:
            #     strU = U[i].unit.to_string()
            #     for cu in commonU:
            #         scu = cu.to_string()
            #         strU = strU.replace(scu,'1')
            #     U[i] = U[i].to(strU, equivalencies=u.dimensionless_angles()).unit

        yU = U[0]
        xU = U[1]
        # Call derivtive functions
        derU = yU / xU

        if hasattr(self, "d_" + y + "_d_" + x):
            dername = "d_" + y + "_d_" + x
            result = getattr(self, dername)()

        elif hasattr(self, "d_" + y + "_d_par"):
            dername = "d_" + y + "_d_par"
            result = getattr(self, dername)(x)

        else:
            result = np.longdouble(np.zeros(len(self.tt0)))

        if hasattr(result, "unit"):
            return result.to(derU, equivalencies=u.dimensionless_angles())
        else:
            return result * derU
Example #58
0
    def simulate_bulge2d(self):
        """
        :return:
        """

        # Inform the user
        log.info("Creating ski file to simulate the bulge image ...")

        # Load the bulge ski file template
        bulge_template_path = fs.join(template_path, "bulge.ski")
        ski = SkiFile(bulge_template_path)

        # Set the number of photon packages
        ski.setpackages(self.config.bulge_packages)

        # Change the ski file parameters
        # component_id, index, radius, y_flattening=1, z_flattening=1
        ski.set_stellar_component_sersic_geometry(
            0,
            self.components["bulge"].index,
            self.components["bulge"].effective_radius,
            y_flattening=self.components["bulge"].axial_ratio)

        # Remove all existing instruments
        ski.remove_all_instruments()

        # Create the instrument
        distance = self.galaxy_properties.distance
        inclination = Angle(0.0, "deg")
        #inclination = 0.0 # doesn't matter, also works! (thanks to intelligent parse_quantity)
        azimuth = Angle(90., "deg")
        #position_angle = self.parameters.bulge.PA + Angle(90., "deg") # + 90° because we can only do y_flattening and not x_flattening
        position_angle = self.components["bulge"].position_angle
        pixels_x = self.wcs.xsize
        pixels_y = self.wcs.ysize
        pixel_center = self.galaxy_properties.center.to_pixel(self.wcs)
        center = Position(0.5 * pixels_x - pixel_center.x - 0.5,
                          0.5 * pixels_y - pixel_center.y - 0.5)
        center_x = center.x
        center_y = center.y
        center_x = (center_x * self.wcs.pixelscale.x.to("deg") * distance).to(
            "pc", equivalencies=dimensionless_angles())
        center_y = (center_y * self.wcs.pixelscale.y.to("deg") * distance).to(
            "pc", equivalencies=dimensionless_angles())
        field_x_angular = self.wcs.pixelscale.x.to("deg") * pixels_x
        field_y_angular = self.wcs.pixelscale.y.to("deg") * pixels_y
        field_x_physical = (field_x_angular * distance).to(
            "pc", equivalencies=dimensionless_angles())
        field_y_physical = (field_y_angular * distance).to(
            "pc", equivalencies=dimensionless_angles())
        fake = SimpleInstrument(distance=distance,
                                inclination=inclination,
                                azimuth=azimuth,
                                position_angle=position_angle,
                                field_x=field_x_physical,
                                field_y=field_y_physical,
                                pixels_x=pixels_x,
                                pixels_y=pixels_y,
                                center_x=center_x,
                                center_y=center_y)

        # Add the instrument
        ski.add_instrument(instrument_name, fake)

        # Determine the path to the ski file
        ski_path = fs.join(self.images_bulge2d_path, "bulge.ski")

        # Save the ski file to the new path
        ski.saveto(ski_path)

        # Determine the path to the simulation output directory
        out_path = fs.create_directory_in(self.images_bulge2d_path, "out")

        # Inform the user
        log.info("Running the bulge 2D simulation ...")

        # Simulate the bulge image
        fluxdensity = self.components["bulge"].fluxdensity
        self.bulge2d_image = self.launcher.run(ski_path,
                                               out_path,
                                               self.wcs,
                                               fluxdensity,
                                               self.psf,
                                               progress_bar=True)

        # Check WCS
        if self.bulge2d_image.wcs != self.wcs:
            raise RuntimeError(
                "Something went wrong setting the coordinate system")
Example #59
0
    def get_p4(self):
        """
        This function ...
        :return:
        """

        #http://vizier.cfa.harvard.edu/viz-bin/VizieR?-source=J/ApJS/219/4

        # J/ApJS/219/4: S4G pipeline 4: multi-component decompositions (Salo+, 2015)

        #  - J/ApJS/219/4/galaxies: Parameters of the galaxies; center, outer orientation, sky background; and 1-component Sersic fits (tables 1 and 6) (2352 rows)
        #  - J/ApJS/219/4/table7: *Parameters of final multicomponent decompositions (Note) (4629 rows)

        # Inform the user
        log.info("Querying the S4G pipeline 4 catalog ...")

        # Get the "galaxies" table
        result = self.vizier.query_object(self.config.galaxy_name,
                                          catalog=["J/ApJS/219/4/galaxies"])
        table = result[0]

        # PA: [0.2/180] Outer isophote position angle
        # e_PA: [0/63] Standard deviation in PA
        # Ell:  [0.008/1] Outer isophote ellipticity
        # e_Ell: [0/0.3] Standard deviation in Ell

        pa = Angle(table["PA"][0] - 90., "deg")
        pa_error = Angle(table["e_PA"][0], "deg")

        ellipticity = table["Ell"][0]
        ellipticity_error = table["e_Ell"][0]

        # Get the "table7" table
        result = self.vizier.get_catalogs("J/ApJS/219/4/table7")
        table = result[0]

        # Name: Galaxy name
        # Mod: Type of final decomposition model
        # Nc: [1/4] Number of components in the model (1-4)
        # Q: [3/5] Quality flag, 5=most reliable
        # C: Physical interpretation of the component
        # Fn: The GALFIT function used for the component (sersic, edgedisk, expdisk, ferrer2 or psf)
        # f1: [0.006/1] "sersic" fraction of the total model flux
        # mag1:  [7/19.4] "sersic" total 3.6um AB magnitude
        # q1: [0.1/1] "sersic" axis ratio
        # PA1: [0.08/180] "sersic" position angle [deg]
        # Re: [0.004/430] "sersic" effective radius (Re) [arcsec]
        # n: [0.01/20] "sersic" parameter n
        # f2: [0.02/1] "edgedisk" fraction of the total model flux
        # mu02: [11.8/24.6] "edgedisk" central surface face-on brightness (µ0) [mag/arcsec2]
        # PA2: [-90/90] "edgedisk" PA [deg]
        # hr2: [1/153] "edgedisk" exponential scale length (hr) [arcsec]
        # hz2: [0.003/39] "edgedisk" z-scale hz [arcsec]
        # f3: [0.02/1] "expdisk" fraction of the total model flux
        # mag3: [6.5/18.1] "expdisk" total 3.6um AB magnitude [mag]
        # q3: [0.1/1] "expdisk" axis ratio
        # PA3: [-90/90] "expdisk" position angle [deg]
        # hr3: [0.7/332] "expdisk" exponential scale length (hr) [arcsec]
        # mu03: [16.4/25.3] "expdisk" central surface face-on brightness (µ0) [mag/arcsec2]
        # f4: [0.003/0.6] "ferrer2" fraction of the total model flux
        # mu04: [16/24.8] "ferrer2" central surface sky brightness (µ0) [mag/arcsec2]
        # q4: [0.01/1] "ferrer2" axis ratio
        # PA4: [-90/90] "ferrer2" position angle [deg]
        # Rbar: [3.7/232.5] "ferrer2" outer truncation radius of the bar (Rbar) [arcsec]
        # f5: [0.001/0.4] "psf" fraction of the total model flux
        # mag5: [11.5/21.1] "psf" total 3.6um AB magnitude [mag]

        indices = tables.find_indices(table, self.ngc_name_nospaces, "Name")

        labels = {
            "sersic": 1,
            "edgedisk": 2,
            "expdisk": 3,
            "ferrer2": 4,
            "psf": 5
        }

        #units = {"f": None, "mag": "mag", "q": None, "PA": "deg", }

        # Loop over the indices
        for index in indices:

            model_type = table["Mod"][index]
            number_of_components = table["Nc"][index]
            quality = table["Q"][index]
            interpretation = table["C"][index]
            functionname = table["Fn"][index]

            component_parameters = Map()

            if self.parameters.model_type is not None:
                assert model_type == self.parameters.model_type
            if self.parameters.number_of_components is not None:
                assert number_of_components == self.parameters.number_of_components
            if self.parameters.quality is not None:
                assert quality == self.parameters.quality
            self.parameters.model_type = model_type
            self.parameters.number_of_components = number_of_components
            self.parameters.quality = quality

            for key in table.colnames:

                if not key.endswith(str(labels[functionname])): continue

                parameter = key[:-1]

                value = table[key][index]

                if parameter == "PA":
                    value = Angle(value + 90., "deg")
                    if quadrant(value) == 2: value = value - Angle(180., "deg")
                    elif quadrant(value) == 3:
                        value = value + Angle(180., "deg")

                    if value.to("deg").value > 180.:
                        value = value - Angle(360., "deg")
                    elif value.to("deg").value < -180.:
                        value = value + Angle(360., "deg")
                elif parameter == "mag":
                    parameter = "fluxdensity"
                    value = unitconversion.ab_to_jansky(value) * u("Jy")
                elif parameter == "mu0":
                    value = value * u("mag/arcsec2")
                elif parameter == "hr":
                    value = value * u("arcsec")
                    value = (self.parameters.distance * value).to(
                        "pc", equivalencies=dimensionless_angles())
                elif parameter == "hz":
                    value = value * u("arcsec")
                    value = (self.parameters.distance * value).to(
                        "pc", equivalencies=dimensionless_angles())

                component_parameters[parameter] = value

            if functionname == "sersic":

                re = table["Re"][index] * u("arcsec")
                component_parameters["Re"] = (
                    self.parameters.distance * re).to(
                        "pc", equivalencies=dimensionless_angles())
                component_parameters["n"] = table["n"][index]

            elif functionname == "ferrer2":

                rbar = table["Rbar"][index] * u("arcsec")
                component_parameters["Rbar"] = (
                    self.parameters.distance * rbar).to(
                        "pc", equivalencies=dimensionless_angles())

            if interpretation == "B":  # bulge

                self.parameters.bulge = component_parameters

            elif interpretation == "D":  # disk

                self.parameters.disk = component_parameters

            else:
                raise RuntimeError("Unrecognized component: " + interpretation)
                              output=rgb_cube_png,
                              vmax_g=0.017,
                              vmax_b=6.5,
                              vmax_r=7.0,
                              vmin_g=0.0001,
                              stretch_g='arcsinh',
                              embed_avm_tags=True)

pl.rcParams['font.size'] = 18
fig1 = pl.figure(1)
fig1.clf()
F = aplpy.FITSFigure(rgb_cube_png, figure=fig1)
F.show_rgb(rgb_cube_png)
F.recenter(290.93315, 14.509584, radius=0.0005)
F.add_scalebar((0.025 * u.pc / (5400 * u.pc)).to(u.deg,
                                                 u.dimensionless_angles()))
F.scalebar.set_label('5000 au / 0.025 pc')
F.scalebar.set_color('w')
F.save(paths.fpath("W51e2_cycle3green_outflows_aplpy.png"))
F.save(paths.fpath("W51e2_cycle3green_outflows_aplpy.pdf"))

e8_rgb_cube_png = rgb_cube_fits[:-5] + "_asinhgreen.png"
rgb_im = aplpy.make_rgb_image(data=rgb_cube_fits,
                              output=e8_rgb_cube_png,
                              vmax_g=0.017,
                              vmin_g=-0.0001,
                              vmax_b=1.5,
                              vmin_b=-0.05,
                              vmax_r=4.0,
                              vmin_r=-0.05,
                              stretch_g='arcsinh',