Exemplo n.º 1
0
def get_spectral_limits(cube,
                        freq_range=None,
                        vel_range=None,
                        chan_range=None,
                        chan_halfwidth=None,
                        vlsr=None,
                        linefreq=None):
    # Turn everything into frequency or velocity
    spec_unit = cube.spectral_axis.unit
    rangefmt = '{0.value[0]:.4f} {0.value[1]:.4f} {0.unit}'
    if freq_range is not None:
        LOG.info('Using frequency range = %s',
                 rangefmt.format(freq_range.to(u.GHz)))
        if spec_unit.is_equivalent(freq_range.unit):
            return freq_range[0], freq_range[1]
        else:
            # Convert to spectral units
            restfreq = get_restfreq(cube)
            freq_to_vel = u.doppler_radio(restfreq)
            lim = freq_range.to(spec_unit, equivalencies=freq_to_vel)
            return np.min(lim), np.max(lim)
    elif vel_range is not None:
        LOG.info('Using velocity range = %s',
                 rangefmt.fmt(vel_range.to(u.km / u.s)))
        if spec_unit.is_equivalent(vel_range.unit):
            return vel_range[0], vel_range[1]
        else:
            # Convert to spectral units
            restfreq = get_restfreq(cube)
            freq_to_vel = u.doppler_radio(restfreq)
            lim = vel_range.to(spec_unit, equivalencies=freq_to_vel)
            return np.min(lim), np.max(lim)
    elif chan_range is not None:
        LOG.info('Channel range = %i %i', *chan_range)
        return sorted(chan_range)
    elif chan_halfwidth is not None and linefreq and vlsr:
        # Get spectral axis
        spaxis = cube.spectral_axis
        restfreq = get_restfreq(cube)

        # Convert to velocity from line
        vel_to_freq = u.doppler_radio(restfreq)
        spaxis = spaxis.to(linefreq.unit, equivalencies=vel_to_freq)
        freq_to_vel = u.doppler_radio(linefreq)
        spaxis = spaxis.to(vlsr.unit, equivalencies=freq_to_vel)
        spaxis = spaxis - vlsr

        # Closest value to vlsr
        ind = np.nanargmin(np.abs(spaxis.value))
        chmin = ind - chan_halfwidth
        chmax = ind + chan_halfwidth
        if chmin < 0:
            chmin = 0
        if chmax >= len(spaxis):
            chmax = len(spaxis) - 1
        LOG.info('Using channel range = %i %i', chmin, chmax)
        return chmin, chmax
    else:
        LOG.info('No spectral limit')
        return None, None
Exemplo n.º 2
0
def test_byhand_vrad():
    # VRAD
    CRVAL3F = 1.37847121643E+09
    CDELT3F = 9.764775E+04
    RESTFRQR= 1.420405752E+09
    CRVAL3R = 8.85075090419E+06
    CDELT3R = -2.0609645E+04
    CUNIT3R = 'm/s'
    CUNIT3F = 'Hz'

    crvalf = CRVAL3F * u.Unit(CUNIT3F)
    crvalv = CRVAL3R * u.Unit(CUNIT3R)
    restfreq = RESTFRQR * u.Unit(CUNIT3F)
    cdeltf = CDELT3F * u.Unit(CUNIT3F)
    cdeltv = CDELT3R * u.Unit(CUNIT3R)

    # (Pdb) crval_in,crval_lin1,crval_lin2,crval_out
    # (<Quantity 1378471216.43 Hz>, <Quantity 1378471216.43 Hz>, <Quantity 8850750.904040769 m / s>, <Quantity 8850750.904040769 m / s>)
    # (Pdb) cdelt_in, cdelt_lin1, cdelt_lin2, cdelt_out
    # (<Quantity 97647.75 Hz>, <Quantity 97647.75 Hz>, <Quantity -20609.645482954576 m / s>, <Quantity -20609.645482954576 m / s>)
    crvalv_computed = crvalf.to(CUNIT3R, u.doppler_radio(restfreq))
    cdeltv_computed = -(cdeltf / restfreq)*constants.c
    
    assert_allclose(crvalv_computed, crvalv, rtol=1.e-3)
    assert_allclose(cdeltv_computed, cdeltv, rtol=1.e-3)

    crvalf_computed = crvalv_computed.to(CUNIT3F, u.doppler_radio(restfreq))
    cdeltf_computed = -(cdeltv_computed/constants.c) * restfreq

    assert_allclose(crvalf_computed, crvalf, rtol=1.e-3)
    assert_allclose(cdeltf_computed, cdeltf, rtol=1.e-3)
def test_byhand_vrad():
    # VRAD
    CRVAL3F = 1.37847121643E+09
    CDELT3F = 9.764775E+04
    RESTFRQR= 1.420405752E+09
    CRVAL3R = 8.85075090419E+06
    CDELT3R = -2.0609645E+04
    CUNIT3R = 'm/s'
    CUNIT3F = 'Hz'

    crvalf = CRVAL3F * u.Unit(CUNIT3F)
    crvalv = CRVAL3R * u.Unit(CUNIT3R)
    restfreq = RESTFRQR * u.Unit(CUNIT3F)
    cdeltf = CDELT3F * u.Unit(CUNIT3F)
    cdeltv = CDELT3R * u.Unit(CUNIT3R)

    # (Pdb) crval_in,crval_lin1,crval_lin2,crval_out
    # (<Quantity 1378471216.43 Hz>, <Quantity 1378471216.43 Hz>, <Quantity 8850750.904040769 m / s>, <Quantity 8850750.904040769 m / s>)
    # (Pdb) cdelt_in, cdelt_lin1, cdelt_lin2, cdelt_out
    # (<Quantity 97647.75 Hz>, <Quantity 97647.75 Hz>, <Quantity -20609.645482954576 m / s>, <Quantity -20609.645482954576 m / s>)
    crvalv_computed = crvalf.to(CUNIT3R, u.doppler_radio(restfreq))
    cdeltv_computed = -(cdeltf / restfreq)*constants.c

    assert_allclose(crvalv_computed, crvalv, rtol=1.e-3)
    assert_allclose(cdeltv_computed, cdeltv, rtol=1.e-3)

    crvalf_computed = crvalv_computed.to(CUNIT3F, u.doppler_radio(restfreq))
    cdeltf_computed = -(cdeltv_computed/constants.c) * restfreq

    assert_allclose(crvalf_computed, crvalf, rtol=1.e-3)
    assert_allclose(cdeltf_computed, cdeltf, rtol=1.e-3)
Exemplo n.º 4
0
    def closest_spectral_channel(self, value, rest_frequency=None):
        """
        Find the index of the closest spectral channel to the specified
        spectral coordinate.

        Parameters
        ----------
        value : :class:`~astropy.units.Quantity`
            The value of the spectral coordinate to search for.
        rest_frequency : :class:`~astropy.units.Quantity`
            The rest frequency for any Doppler conversions
        """

        # TODO: we have to not compute this every time
        spectral_axis = self.spectral_axis

        try:
            value = value.to(spectral_axis.unit, equivalencies=u.spectral())
        except u.UnitsError:
            if value.unit.is_equivalent(spectral_axis.unit, equivalencies=u.doppler_radio(None)):
                if rest_frequency is None:
                    raise u.UnitsError("{0} cannot be converted to {1} without a "
                                       "rest frequency".format(value.unit, spectral_axis.unit))
                else:
                    try:
                        value = value.to(spectral_axis.unit,
                                         equivalencies=u.doppler_radio(rest_frequency))
                    except u.UnitsError:
                        raise u.UnitsError("{0} cannot be converted to {1}".format(value.unit, spectral_axis.unit))
            else:
                raise u.UnitsError("'value' should be in frequency equivalent or velocity units (got {0})".format(value.unit))

        # TODO: optimize the next line - just brute force for now
        return np.argmin(np.abs(spectral_axis - value))
Exemplo n.º 5
0
def freqs_to_vel(center_freq, fs, sc):
    """Convert frequency to radial Doppler velocity.

    Accounts for movement of the earth relative to the sun and the sun relative to galactic center.

    Args:
        center_freq: frequency at zero velocity
        fs: Quantity object representing frequencies
        sc: SkyCoord object representing one or many coordinates (must have obstime and location set)
    """

    # Convert from earth reference frame to solar reference frame using
    # https://docs.astropy.org/en/stable/coordinates/velocities.html#radial-velocity-corrections
    # Then convert from solar reference frame to Galactic Standard of Rest using
    # https://docs.astropy.org/en/stable/generated/examples/coordinates/rv-to-gsr.html
    pos_gal = sc.galactic
    v_to_bary = pos_gal.radial_velocity_correction(kind='barycentric')
    # Calculate the sun's velocity projected in the observing direction.
    v_sun = Galactocentric().galcen_v_sun.to_cartesian()
    cart_data = pos_gal.data.to_cartesian()
    unit_vector = cart_data / cart_data.norm()
    v_proj = v_sun.dot(unit_vector)

    doppler_shift = u.doppler_radio(center_freq)

    v_local = fs.to(u.km/u.s, doppler_shift)
    v_bary = v_local + v_to_bary + v_local * v_to_bary / c
    # v_bary is now barycentric; now we need to remove the solar system motion as well
    return (v_bary + v_proj)
Exemplo n.º 6
0
def convert_chan_freq_vel(chan_res):
    """
    Takes an input channel resolution, either in freq or velocity
    Will return matching resolution in other dimensions
    Presumes radio definition; can consider as a param for future
    Inputs:
    chan_res (Quantity): Input resolution, with units
    Outputs:
    new_res (Quantity): Output resolution, with units, opp of input
    """
    #define conversion
    restfreq = 1420.405752 * u.MHz
    freq_to_vel = u.doppler_radio(restfreq)
    #check if in frequency; if so, get vel
    if 'Hz' in chan_res.unit.to_string():
        offsetfreq = restfreq - chan_res
        vel = restfreq.to(u.km / u.s, equivalencies=freq_to_vel)
        offsetvel = offsetfreq.to(u.km / u.s, equivalencies=freq_to_vel)
        new_res = offsetvel - vel

    else:
        print("Not frequency unit, presuming velocity")
        offsetfreq = chan_res.to(u.kHz, equivalencies=freq_to_vel)
        new_res = restfreq - offsetfreq

    return new_res
Exemplo n.º 7
0
 def velocity_axis(self):
     """Obtain spectral axis en velocity units."""
     if self.spectral_axis.unit.is_equivalent(u.km / u.s):
         return self.spectral_axis
     else:
         equiv = u.doppler_radio(self.restfreq)
         return self.spectral_axis.to(u.km / u.s, equivalencies=equiv)
def test_convert_to_unit(run_with_assert=False):
    for from_unit, to_unit, _, __ in u.doppler_optical(1 * u.Hz):
        sp = SpectroscopicAxis(np.linspace(-100, 100, 100),
                               unit=from_unit,
                               refX=23.2 * u.Hz,
                               velocity_convention='optical')
        sp.convert_to_unit(to_unit)
        if (run_with_assert):
            assert sp.unit == to_unit
    for from_unit, to_unit, _, __ in u.doppler_radio(1 * u.eV):
        sp = SpectroscopicAxis(np.linspace(-100, 100, 100),
                               unit=from_unit,
                               refX=23.2 * u.Hz,
                               velocity_convention='optical')
        sp.convert_to_unit(to_unit)
        if (run_with_assert):
            assert sp.unit == to_unit
    for from_unit, to_unit, _, __ in u.doppler_relativistic(1 * u.Angstrom):
        sp = SpectroscopicAxis(np.linspace(-100, 100, 100),
                               unit=from_unit,
                               refX=23.2 * u.Hz,
                               velocity_convention='relativistic')
        sp.convert_to_unit(to_unit)
        if (run_with_assert):
            assert sp.unit == to_unit
Exemplo n.º 9
0
    def f_kernel(self):
        """
        Returns a function defining the beam amplitude as a function of
        position.

        The model implemented is based on an interpolation of an image of the
        WSRT beam, re-scaled according to declination and frequency.

        Returns
        -------
        Callable accepting 2 arguments (both float or array) and returning a
        float or array of corresponding size.
        """

        if self.dec <= 0. * U.deg:
            raise ValueError('WSRT beam requires positive declination.')
        freq = self.vel.to(U.GHz, equivalencies=U.doppler_radio(f_HI))
        bheader, bdata = self._load_beamfile()
        centroid = self._centroid()
        bpx_ra = np.abs(bheader['CDELT1'] * U.deg).to(U.arcsec)
        bpx_dec = np.abs(bheader['CDELT2'] * U.deg).to(U.arcsec)
        dRAs = np.arange(-(bdata.shape[0] // 2), bdata.shape[0] // 2 + 1) \
            * bpx_ra * (centroid[2] / freq).to(U.dimensionless_unscaled)
        dDecs = np.arange(-(bdata.shape[1] // 2), bdata.shape[1] // 2 + 1) \
            * bpx_dec * np.sin(self.dec) / np.sin(centroid[1]) \
            * (centroid[2] / freq)\
            .to(U.dimensionless_unscaled)
        interpolator = RectBivariateSpline(
            dRAs, dDecs, bdata[..., 0], kx=1, ky=1, s=0)
        # RectBivariateSpline is a wrapper around Fortran code and causes a
        # transpose
        return lambda x, y: interpolator(y, x, grid=False).T
Exemplo n.º 10
0
    def kernel_size_px(self):
        """
        Returns a 2-tuple specifying the half-size of the beam image to be
        initialized, in pixels.

        The interpolation may become unstable if the image is severely
        undersampled, pixel sizes of more than 8 arcsec are not recommended.

        Returns
        -------
        out : 2-tuple, each element an integer.
        """

        if self.px_size > 12. * U.arcsec:
            warnings.warn(
                "Using WSRT beam with datacube pixel size >> 8 arcsec,"
                " beam interpolation may fail.")
        freq = self.vel.to(U.GHz, equivalencies=U.doppler_radio(f_HI))
        bheader, bdata = self._load_beamfile()
        centroid = self._centroid()
        aspect_x, aspect_y = np.floor(bdata.shape[0] // 2 *
                                      np.sin(self.dec)), bdata.shape[1] // 2
        aspect_x = aspect_x * np.abs((bheader['CDELT1'] * U.deg)).to(U.arcsec)\
            * (centroid[2] / freq).to(U.dimensionless_unscaled)
        aspect_y = aspect_y * (bheader['CDELT2'] * U.deg).to(U.arcsec) \
            * (centroid[2] / freq).to(U.dimensionless_unscaled)
        return tuple([
            (a.to(U.pix, U.pixel_scale(self.px_size / U.pix))).value + 1
            for a in (aspect_x, aspect_y)
        ])
Exemplo n.º 11
0
    def __init__(self,
                 species: str,
                 qns: str,
                 restfreq: u.Quantity,
                 obsfreq: Optional[u.Quantity] = None,
                 vlsr: Optional[u.Quantity] = None,
                 eup: Optional[u.Quantity] = None,
                 logaij: Optional[u.Quantity] = None) -> None:
        """Initiate a transition object.

        Args:
          species: chemical formula.
          qns: quantum numbers.
          restfreq: transition rest frequency.
          obsfreq: optional; observed frequency.
          vlsr: optional; used to determine `obsfreq` if not given.
          eup: optional; upper level energy.
          logaij: optional; log of the Aij coeficient.
        """
        self.species = species
        self.qns = qns
        self.restfreq = restfreq.to(u.GHz)
        self.obsfreq = obsfreq
        if self.obsfreq is None and vlsr is not None:
            equiv = u.doppler_radio(self.restfreq)
            self.obsfreq = to_rest_freq(self.restfreq, -vlsr, equiv)
        try:
            self.obsfreq = self.obsfreq.to(u.GHz)
        except AttributeError:
            pass
        self.eup = eup
        self.logaij = logaij
Exemplo n.º 12
0
def redshift_frequency(f, vlsr):
    """Assumes (for now) rest frequency (f) in GHz and velocity of the source (vlsr) in km/s."""
    f_rest = f * u.GHz  # rest frequency
    vlsr = vlsr * u.km / u.s  # velocity of the source
    radio_equiv = u.doppler_radio(f_rest)
    f_shifted = vlsr.to(u.GHz, equivalencies=radio_equiv)
    return f_shifted.value
Exemplo n.º 13
0
def make_synthspec_cold(
        velo=np.linspace(-25, 25, 251),
        tkin=25,
        column=13,
        width=0.5,
        vcen=0.0,
        lines=('oneone', 'twotwo', 'fourfour'),
):

    velo = u.Quantity(velo, u.km / u.s)

    spectra_list = []
    for line in lines:
        cfrq = ammonia_constants.freq_dict[line] * u.Hz
        frq = velo.to(u.GHz, u.doppler_radio(cfrq))
        xarr = units.SpectroscopicAxis(frq, refX=cfrq)
        data = ammonia.cold_ammonia(xarr,
                                    tkin=tkin,
                                    width=width,
                                    ntot=column,
                                    xoff_v=vcen)
        sp = Spectrum(xarr=xarr, data=data)
        spectra_list.append(sp)

    return Spectra(spectra_list)
Exemplo n.º 14
0
    def col_d_tot(self):
    ###--return total column density of the line species (cm^-2)--###
        lwd  = np.abs(self.lw)
        #channel width in Hz
        ftov = u.doppler_radio(self.ln[self.ll][2]*u.Hz)
        lw   = self.ln[self.ll][2]- \
               (lwd*(u.km/u.s)).to(u.Hz,equivalencies=ftov).value
        
        #upper column density
        to = h.value/k_B.value*self.ln[self.ll][2]
        ex = to/self.Tx
        
        n_u = 8*np.pi*self.ln[self.ll][2]**2/(c.value*100.)**2* \
              self.f(ex)/self.ln[self.ll][0]* \
              np.sum(self.tau())*lw
        #alternatively, one may use d(nu)/nu_0 = dv/c in linewidth:
        #n_u = 8*np.pi*self.ln[self.ll][2]/(c.value*100.)*\
        #      self.f(ex)/self.ln[self.ll][0]* \
        #      np.sum(self.tau())*lwd

        #partition function, approximated by integral
        eu = k_B.value*self.Tx/h.value/self.ln[self.ll][1]
        zz = eu/(self.ln[self.ll][3]*2+1)* \
             np.exp(self.ln[self.ll][3]*(self.ln[self.ll][3]+1)/eu)
        
        return n_u*zz
Exemplo n.º 15
0
def get_molecule(args: argparse.Namespace) -> Molecule:
    """Generate a `Molecule` from argparse.

    Requires the argparse to have `cube` and `log` attributes. The `vlsr`
    attribute is also needed but does not need to be initialized.
    """
    # Frequency ranges
    spectral_axis = args.cube.spectral_axis
    obs_freq_range = spectral_axis[[0,-1]]
    args.log.info((f'Observed freq. range: {obs_freq_range[0].value} '
                   f'{obs_freq_range[1].value} {obs_freq_range[1].unit}'))
    if args.vlsr is not None:
        equiv = u.doppler_radio(get_restfreq(args.cube))
        rest_freq_range = to_rest_freq(obs_freq_range, args.vlsr, equiv)
        args.log.info((f'Rest freq. range: {rest_freq_range[0].value} '
                       f'{rest_freq_range[1].value} {rest_freq_range[1].unit}'))
    else:
        args.log.warn('Could not determine rest frequency, using observed')
        rest_freq_range = obs_freq_range

    # Create molecule
    if args.onlyj:
        filter_out = ['F', 'K']
    else:
        filter_out = None
    mol = Molecule.from_query(f' {args.molecule[0]} ', rest_freq_range,
                              vlsr=args.vlsr, filter_out=filter_out,
                              line_lists=args.line_lists, qns=args.qns)
    mol.reduce_qns()
    args.log.info(f'Number of transitions: {len(mol.transitions)}')

    return mol
Exemplo n.º 16
0
def sio_model(xarr, vcen, width, tex, column, background=None, tbg=2.73):

    if hasattr(tex, 'unit'):
        tex = tex.value
    if hasattr(tbg, 'unit'):
        tbg = tbg.value
    if hasattr(column, 'unit'):
        column = column.value
    if column < 25:
        column = 10**column
    if hasattr(vcen, 'unit'):
        vcen = vcen.value
    if hasattr(width, 'unit'):
        width = width.value

    if background is not None:
        tbg = background

    # assume equal-width channels
    kwargs = dict(rest=ref_freq)
    equiv = u.doppler_radio(**kwargs)
    channelwidth = np.abs(xarr[1].to(u.Hz, equiv) -
                          xarr[0].to(u.Hz, equiv)).value
    velo = xarr.to(u.km / u.s, equiv).value
    mol_model = np.zeros_like(xarr).value

    freqs_ = freqs.to(u.Hz).value

    Q = m.calculate_partitionfunction(result.data['States'],
                                      temperature=tex)[sio.Id]

    jnu_bg = lte_molecule.Jnu_cgs(xarr.to(u.Hz).value, tbg)
    bg_model = np.ones_like(xarr).value * jnu_bg

    for voff, A, g, nu, eu in zip(vdiff, aij, deg, freqs_, EU):
        tau_per_dnu = lte_molecule.line_tau_cgs(tex, column, Q, g, nu, eu,
                                                10**A)
        s = np.exp(-(velo - vcen - voff)**2 /
                   (2 * width**2)) * tau_per_dnu / channelwidth
        jnu_mol = lte_molecule.Jnu_cgs(nu, tex)

        # the "emission" model is generally zero everywhere, so we can just
        # add to it as we move along
        mol_model = mol_model + jnu_mol * (1 - np.exp(-s))

        # background is assumed to start as a uniform value, then each
        # absorption line multiplies to reduce it.  s is zero for most velocities,
        # so this is mostly bg_model *= 1
        bg_model *= np.exp(-s)

    if background:
        # subtract jnu_bg because we *must* rezero for the case of
        # having multiple components, otherwise the backgrounds add,
        # which is nonsense
        model = bg_model + mol_model - jnu_bg
    else:
        model = mol_model

    return model
Exemplo n.º 17
0
    def closest_spectral_channel(self, value, rest_frequency=None):
        """
        Find the index of the closest spectral channel to the specified
        spectral coordinate.

        Parameters
        ----------
        value : :class:`~astropy.units.Quantity`
            The value of the spectral coordinate to search for.
        rest_frequency : :class:`~astropy.units.Quantity`
            The rest frequency for any Doppler conversions
        """

        # TODO: we have to not compute this every time
        spectral_axis = self.spectral_axis

        try:
            value = value.to(spectral_axis.unit, equivalencies=u.spectral())
        except u.UnitsError:
            if value.unit.is_equivalent(spectral_axis.unit,
                                        equivalencies=u.doppler_radio(None)):
                if rest_frequency is None:
                    raise u.UnitsError(
                        "{0} cannot be converted to {1} without a "
                        "rest frequency".format(value.unit,
                                                spectral_axis.unit))
                else:
                    try:
                        value = value.to(
                            spectral_axis.unit,
                            equivalencies=u.doppler_radio(rest_frequency))
                    except u.UnitsError:
                        raise u.UnitsError(
                            "{0} cannot be converted to {1}".format(
                                value.unit, spectral_axis.unit))
            else:
                raise u.UnitsError(
                    "'value' should be in frequency equivalent or velocity units (got {0})"
                    .format(value.unit))

        # TODO: optimize the next line - just brute force for now
        return np.argmin(np.abs(spectral_axis - value))
def get_spectral_equivalencies(restfreqs: list,
                               keys: Optional[list] = None) -> dict:
    """Get spectral equivalencies from rest frequencies.

    Args:
      restfreqs: rest frequencies.
      keys: optional; keys for the output dictionary.
    Returns:
      A dictionary with the astropy equivalency functions.
    """
    # Define keys
    if keys is None:
        keys = range(len(restfreqs))

    # Process restfreqs
    if len(restfreqs) == 1:
        equiv = {key: u.doppler_radio(restfreqs[0]) for key in keys}
    else:
        if len(keys) != len(restfreqs):
            raise ValueError('Size of keys and restfreqs do not match')
        aux = zip(keys, restfreqs)
        equiv = {key: u.doppler_radio(restfreq) for key, restfreq in aux}

    return equiv
Exemplo n.º 19
0
def _preproc(args: argparse.Namespace) -> None:
    """Prepare args inputs for analysis."""
    # Equivalencies
    if args.restfreq:
        if args.table is not None and 'spw' in args.table[0].dtype.names:
            spws = np.unique(args.table[0]['spw'])
            args.equivalencies = get_spectral_equivalencies(args.restfreq,
                                                            keys=spws)
        else:
            args.equivalencies['all'] = u.doppler_radio(args.restfreq[0])

    # Define filename
    if args.filename is not None:
        args.filename = args.filename[0]
    else:
        args.filename = pathlib.Path('./results.ecsv').resolve()
Exemplo n.º 20
0
Arquivo: axes.py Projeto: maray/craspy
def spectral_velocities(data, wcs=None, fqs=None, fqis=None, restfrq=None):
    """
        Get the spectral velocities from frequencies fqs given a rest
        frequency (by default search for it in the WCS). If fqs is None,
        then frequencies indices (fqis) need to be given.

        Parameters
        ----------
        data : (M,N) or (M,N,Z) numpy.ndarray or astropy.nddata.NDData or astropy.nddata.NDDataRef
            Astronomical data cube.
        wcs : astropy.wcs.wcs.WCS
            World Coordinate System to use.
        fqs : astropy.units.quantity.Quantity
            Array of frequencies with units.
        fqis : list of integers
            Array of frequencies indices
        restfrq : astropy.units.quantity.Quantity
            Rest frequency

        Returns
        -------
        result: astropy.units.quantity.Quantity
            Array of Spectral velocities.


    """
    if wcs is None:
        log.error("A world coordinate system (WCS) is needed")
        return None
    if data.ndim != 3:
        log.error("Not spectral axis found.")
        return None
    if restfrq is None:
        restfrq = wcs.wcs.restfrq * u.Hz
    if fqs is None:
        dim = wcs.wcs.spec
        if fqis is None:
            # Semi Hardconded...
            fqis = np.arange(data.shape[data.ndim - dim - 1])
        idx = np.zeros((fqis.size, data.ndim))
        idx[:, dim] = fqis
        vals = wcs.all_pix2world(idx, 0)
        fqs = vals[:, dim] * u.Hz
    eq = u.doppler_radio(restfrq)
    return fqs.to(u.km / u.s, equivalencies=eq)
Exemplo n.º 21
0
def convert_vel_freq(quantity, restfreq=1420.405752 * u.MHz):
    """
    Take an input quantity that is either vel or freq and return the other
    Default for HI line
    Use radio convention (could set as param)
    """
    freq_to_vel = u.doppler_radio(restfreq)
    if 'Hz' in quantity.unit.to_string():
        new_quantity = quantity.to(u.km / u.s, equivalencies=freq_to_vel)
    else:
        #presume in vel, use try/except in case
        try:
            new_quantity = quantity.to(u.MHz, equivalencies=freq_to_vel)
        except:
            print("Units of input not recognized")
            new_quantity = np.nan

    return new_quantity
Exemplo n.º 22
0
def make_synthspec_cold(velo=np.linspace(-25, 25, 251), tkin=25,
                        column=13, width=0.5, vcen=0.0,
                        lines=('oneone', 'twotwo', 'fourfour'),
                        ):

    velo = u.Quantity(velo, u.km/u.s)

    spectra_list = []
    for line in lines:
        cfrq = ammonia_constants.freq_dict[line]*u.Hz
        frq = velo.to(u.GHz, u.doppler_radio(cfrq))
        xarr = units.SpectroscopicAxis(frq, refX=cfrq)
        data = ammonia.cold_ammonia(xarr, tkin=tkin, width=width, ntot=column,
                                    xoff_v=vcen)
        sp = Spectrum(xarr=xarr, data=data)
        spectra_list.append(sp)

    return Spectra(spectra_list)
Exemplo n.º 23
0
def ch3cn_model(xarr, vcen, width, tex, column, background=None, tbg=2.73):

    if hasattr(tex,'unit'):
        tex = tex.value
    if hasattr(tbg,'unit'):
        tbg = tbg.value
    if hasattr(column, 'unit'):
        column = column.value
    if column < 25:
        column = 10**column
    if hasattr(vcen, 'unit'):
        vcen = vcen.value
    if hasattr(width, 'unit'):
        width = width.value

    # assume equal-width channels
    kwargs = dict(rest=ref_freq)
    equiv = u.doppler_radio(**kwargs)
    channelwidth = np.abs(xarr[1].to(u.Hz, equiv) - xarr[0].to(u.Hz, equiv)).value
    velo = xarr.to(u.km/u.s, equiv).value
    model = np.zeros_like(xarr).value

    freqs_ = freqs.to(u.Hz).value

    Q = m.calculate_partitionfunction(result.data['States'],
                                      temperature=tex)[ch3cn.Id]

    for voff, A, g, nu, eu in zip(vdiff, aij, deg, freqs_, EU):
        tau_per_dnu = lte_molecule.line_tau_cgs(tex,
                                                column,
                                                Q,
                                                g,
                                                nu,
                                                eu,
                                                10**A)
        s = np.exp(-(velo-vcen-voff)**2/(2*width**2))*tau_per_dnu/channelwidth
        jnu = (lte_molecule.Jnu_cgs(nu, tex)-lte_molecule.Jnu_cgs(nu, tbg))

        model = model + jnu*(1-np.exp(-s))

    if background is not None:
        return background-model
    return model
Exemplo n.º 24
0
    def __init__(self, mode='relativistic'):
        # HI restframe
        self.nu0 = 1420.4058
        self.nu0_u = self.nu0 * u.MHz

        # full mode for Minkowski space time
        if mode.lower() == 'relativistic':
            self.v_frame = u.doppler_relativistic(self.nu0_u)
        # radio definition
        elif mode.lower() == 'radio':
            self.v_frame = u.doppler_radio(self.nu0_u)
            # velo = c * (1. - nu/nu0)

        # optical definition
        elif mode.lower() == 'optical':
            self.v_frame = u.doppler_optical(self.nu0_u)

        self.mode = mode

        return None
Exemplo n.º 25
0
def spectral_velocities(data,wcs=None,fqs=None,fqis=None,restfrq=None):
    """
        Get the spectral velocities from frequencies fqs given a rest
        frequency (by default search for it in the WCS). If fqs is None,
        then frequencies indices (fqis) need to be given.

        Parameters
        ----------
        data : (M,N) or (M,N,Z) numpy.ndarray or astropy.nddata.NDData or astropy.nddata.NDDataRef
            Astronomical data cube.
        wcs : astropy.wcs.wcs.WCS
            World Coordinate System to use.
        fqs : astropy.units.quantity.Quantity
            Array of frequencies with units.
        fqis : list of integers
            Array of frequencies indices
        restfrq : astropy.units.quantity.Quantity
            Rest frequency

        Returns
        -------
        result: astropy.units.quantity.Quantity
            Array of Spectral velocities.


    """
    if wcs is None:
        log.error("A world coordinate system (WCS) is needed")
        return None
    if restfrq is None:
        restfrq=wcs.wcs.restfrq*u.Hz
    if fqs is None:
        if fqis is None:
           return None
        dim=wcs.wcs.spec
        idx=np.zeros((fqis.size,data.ndim))
        idx[:,dim]=fqis
        vals=wcs.all_pix2world(idx,0)
        fqs=vals[:,dim]*u.Hz
    eq=u.doppler_radio(restfrq)
    return fqs.to(u.km/u.s, equivalencies=eq)
Exemplo n.º 26
0
 def get_spectrum(self, region_pix):
     # import image
     print("\t>>> Importing fits image...")
     hdul = fits.open(self.name)
     data_image = hdul[0].data[0]
     # get info from header
     beam_maj = hdul[0].header["BMAJ"]
     beam_min = hdul[0].header["BMIN"]
     beam_units = hdul[0].header["BUNIT"]
     delta_ra = hdul[0].header["CDELT1"]
     delta_dec = hdul[0].header["CDELT2"]
     delta_freq = hdul[0].header["CDELT3"]
     initial_freq = hdul[0].header["CRVAL3"]
     freq_units = hdul[0].header["CUNIT3"]
     channels = hdul[0].header["NAXIS3"]
     rest_freq = hdul[0].header["RESTFRQ"]
     hdul.close()
     # calculate beam
     beam_area = (np.pi / (4 * np.log(2)) * beam_maj * beam_min * 3600**2
                  )  # arcsec^2
     pix_area = abs(delta_ra * delta_dec) * 3600**2  # arcsec^2
     beam_pix = beam_area / pix_area  # pixels
     # calculate sum inside mask
     print("\t>>> Taking spectrum...")
     spectrum = []
     for channel in data_image:
         intensity = np.nansum(channel * self.mask)
         spectrum.append(intensity)
     # generate freq column
     freq = (np.arange(initial_freq, initial_freq + channels * delta_freq,
                       delta_freq)[:channels] * 10**-9 * u.GHz)
     # generate velocity column
     radio_equiv = u.doppler_radio(rest_freq * 10**-9 * u.GHz)
     velocity = freq.to(u.km / u.s, equivalencies=radio_equiv)
     # generate channel column
     chan = np.arange(channels)
     # generate pixels column
     pix = np.full(channels, region_pix)
     return chan, pix, freq.value, velocity.value, spectrum, beam_area, beam_pix
def test_convert_to_unit(run_with_assert=False):
    for from_unit, to_unit, _, __ in u.doppler_optical(1 * u.Hz):
        sp = SpectroscopicAxis(
            np.linspace(-100, 100, 100), unit=from_unit, refX=23.2 * u.Hz, velocity_convention="optical"
        )
        sp.convert_to_unit(to_unit)
        if run_with_assert:
            assert sp.unit == to_unit
    for from_unit, to_unit, _, __ in u.doppler_radio(1 * u.eV):
        sp = SpectroscopicAxis(
            np.linspace(-100, 100, 100), unit=from_unit, refX=23.2 * u.Hz, velocity_convention="optical"
        )
        sp.convert_to_unit(to_unit)
        if run_with_assert:
            assert sp.unit == to_unit
    for from_unit, to_unit, _, __ in u.doppler_relativistic(1 * u.Angstrom):
        sp = SpectroscopicAxis(
            np.linspace(-100, 100, 100), unit=from_unit, refX=23.2 * u.Hz, velocity_convention="relativistic"
        )
        sp.convert_to_unit(to_unit)
        if run_with_assert:
            assert sp.unit == to_unit
Exemplo n.º 28
0
  def _init_vel(self):
    """
    Converts the spectral coordinate to (radio) velocities.
     
    Currently assumes that the spectral coordinate is in units of Hz.

    FIXME: read unit from fits file 

    FIXME: stolen from here ... https://github.com/astropy/astropy/issues/4529
    mabe not the best way to go
    
    FIXME: maybe could be generalized
         
    """
    wcsvel=wcs.WCS(self.header)
    xv = numpy.repeat(0, self.header['NAXIS3'])
    yv = numpy.repeat(0, self.header['NAXIS3'])
    zv = numpy.arange(self.header['NAXIS3']) 
     
    wx, wy, wz = wcsvel.wcs_pix2world(xv, yv, zv, 0)
    freq_to_vel = u.doppler_radio(self.header['RESTFRQ']*u.Hz)
    vel=(wz * u.Hz).to(u.km / u.s, equivalencies=freq_to_vel)
     
    return vel  
Exemplo n.º 29
0
    def frequencies(self):
        if self._frequencies is None:
            specax = self.wcs.wcs.spec

            channels = np.arange(self.data.shape[::-1][specax])

            spec = self.spec_wcs.wcs_pix2world(channels, 0)[0]

            specc = spec * self.axis_units[specax]

            # Convert radio or optical velocities to frequencies
            if 'VRAD' in self.wcs.wcs.ctype[specax]:
                eq = u.doppler_radio(self.rest_frequency)
            elif 'VOPT' in self.wcs.wcs.ctype[specax]:
                eq = u.doppler_optical(self.rest_frequency)
            elif 'FREQ' in self.wcs.wcs.ctype[specax]:
                eq = []
            else:
                raise AttributeError(
                    'Unsupported spectral type {:s} in header.'.format(self.wcs.wcs.ctype[specax]))

            self._frequencies = specc.to(u.Hz, eq)

        return self._frequencies
Exemplo n.º 30
0
def test_equivalencies():
    """
    Testing spectral equivalencies
    """
    # range in "RADIO" with "100 * u.GHz" as rest frequancy
    range = u.Quantity([-318 * u.km / u.s, -320 * u.km / u.s])

    # range in freq
    r1 = range.to("GHz", equivalencies=u.doppler_radio(100 * u.GHz))

    # round conversion for "doppler_z"
    r2 = r1.to("km/s", equivalencies=doppler_z(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_z(100*u.GHz))
    assert_quantity_allclose(r1, r3)

    # round conversion for "doppler_beta"
    r2 = r1.to("km/s", equivalencies=doppler_beta(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_beta(100 * u.GHz))
    assert_quantity_allclose(r1, r3)

    # round conversion for "doppler_gamma"
    r2 = r1.to("km/s", equivalencies=doppler_gamma(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_gamma(100 * u.GHz))
    assert_quantity_allclose(r1, r3)
Exemplo n.º 31
0
def test_equivalencies():
    """
    Testing spectral equivalencies
    """
    # range in "RADIO" with "100 * u.GHz" as rest frequancy
    range = u.Quantity([-318 * u.km / u.s, -320 * u.km / u.s])

    # range in freq
    r1 = range.to("GHz", equivalencies=u.doppler_radio(100 * u.GHz))

    # round conversion for "doppler_z"
    r2 = r1.to("km/s", equivalencies=doppler_z(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_z(100 * u.GHz))
    assert_quantity_allclose(r1, r3)

    # round conversion for "doppler_beta"
    r2 = r1.to("km/s", equivalencies=doppler_beta(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_beta(100 * u.GHz))
    assert_quantity_allclose(r1, r3)

    # round conversion for "doppler_gamma"
    r2 = r1.to("km/s", equivalencies=doppler_gamma(100 * u.GHz))
    r3 = r2.to("GHz", equivalencies=doppler_gamma(100 * u.GHz))
    assert_quantity_allclose(r1, r3)
Exemplo n.º 32
0
 def convert_to_ms(q):
     return q.to(U.m / U.s, equivalencies=U.doppler_radio(HIfreq))
Exemplo n.º 33
0
def find_linefree_freq(ms_name, vel_map, spw_dict,
                       vel_width=40 * u.km / u.s,
                       field_name='M33',
                       pb_size=0 * u.deg,
                       debug_printing=False):
    '''
    Use a velocity map (e.g., from HI) to define line-free channels
    in an MS.

    Parameters
    ----------
    ms_name : str
        Name of MS file to open.
    vel_map : spectral_cube.Projection
        Line velocity map to use extents from.
    spw_dict : dict
        Dictionary of SPWs numbers (as keys) and the
        rest frequency. Continuum SPWs can be set to
        the brightest line (e.g., CO) to exclude those
        channels.
    '''

    try:
        # CASA 6
        import casatools
        # iatool = casatools.image()
        tb = casatools.table()
    except ImportError:
        try:
            from taskinit import tbtool
            # iatool = iatool()
            tb = tbtool()
        except ImportError:
            raise ImportError("Could not import CASA (casac).")

    # Get channel frequencies.
    tb.open(os.path.join(ms_name, 'SPECTRAL_WINDOW'))
    chanfreqs = tb.getvarcol('CHAN_FREQ')
    tb.close()

    # Get science field positions to define enclosing box of mosaic.
    tb.open(os.path.join(ms_name, 'FIELD'))
    field_names = tb.getcol('NAME')
    phase_dirns = tb.getcol('PHASE_DIR').squeeze()
    tb.close()

    # Screen out non-science fields
    selected_fields = np.array([True if field_name in name else False
                                for name in field_names])
    ras, decs = (phase_dirns * u.rad).to(u.deg)

    ras = ras[selected_fields]
    decs = decs[selected_fields]

    pointings = SkyCoord(ras, decs, frame='icrs')

    # Make bounding box.

    min_ra = pointings.ra.min() - 0.5 * pb_size.to(u.deg)
    max_ra = pointings.ra.max() + 0.5 * pb_size.to(u.deg)
    min_dec = pointings.dec.min() - 0.5 * pb_size.to(u.deg)
    max_dec = pointings.dec.max() + 0.5 * pb_size.to(u.deg)

    vel_map_box = vel_map.subimage(ylo=min_dec, yhi=max_dec,
                                   xlo=max_ra, xhi=min_ra).to(u.km / u.s)

    if vel_map_box.ndim != 2:
        raise ValueError("Spatial slicing failed. Don't think this should happen?")

    linefree_range = dict.fromkeys(spw_dict.keys())

    for line_name in spw_dict:

        spw_props = spw_dict[line_name]

        spw_num = spw_props['spw_num']
        restfreq = spw_props['restfreq'].to(u.Hz)

        # Check if a velocity padding is defined
        if 'vel_pad' in spw_props:
            vel_pad = spw_props['vel_pad']
        else:
            vel_pad = vel_width

        if debug_printing:
            print('Velocity padding used for {0} is {1}'.format(spw_num,
                                                                vel_pad))

        # Get the channel frequencies
        key_name = "r{0}".format(int(spw_num) + 1)

        chanfreqs_spw = chanfreqs[key_name].squeeze() * u.Hz

        # Convert velocity extrema to freq.

        vel_min = np.nanmin(vel_map_box.quantity) - vel_pad.to(u.km / u.s) / 2.
        vel_max = np.nanmax(vel_map_box.quantity) + vel_pad.to(u.km / u.s) / 2.

        freq_min = vel_min.to(u.Hz, u.doppler_radio(restfreq))
        freq_max = vel_max.to(u.Hz, u.doppler_radio(restfreq))

        if debug_printing:
            print("Min velocity of spw {}".format(chanfreqs_spw.to(u.km / u.s, u.doppler_radio(restfreq)).min()))
            print("Max velocity of spw {}".format(chanfreqs_spw.to(u.km / u.s, u.doppler_radio(restfreq)).max()))
            print("Min velocity of line-free {}".format(vel_min))
            print("Max velocity of line-free {}".format(vel_max))

        # Switch if needed
        if freq_max < freq_min:
            freq_max, freq_min = freq_min, freq_max

        line_chans = np.logical_and(chanfreqs_spw > freq_min,
                                    chanfreqs_spw < freq_max)

        if debug_printing:
            print("Valid line channels found: {0}".format(line_chans))

        if not line_chans.any():
            raise ValueError("Invalid range found for {}".format(line_name))

        chan_min = np.where(line_chans)[0].min()
        chan_max = np.where(line_chans)[0].max()

        # Make the line-free channel ranges
        linefree_range[line_name] = []

        if debug_printing:
            print("Chan min/max for {0} are {1}/{2}".format(spw_num, chan_min,
                                                            chan_max))

        if chan_min > 0:
            lows = [0, chan_min]
            linefree_range[line_name].append(lows)

        if chan_max < chanfreqs_spw.size - 1:
            highs = [chan_max, chanfreqs_spw.size]
            linefree_range[line_name].append(highs)

    return linefree_range
Exemplo n.º 34
0
    "J3-2_38": 0.016574,
    "J3-2_39": 0.009776,
    "J3-2_40": 0.000995,
    "J3-2_41": 0.000491,
    "J3-2_42": 0.000067,
    "J3-2_43": 0.000039,
    "J3-2_44": 0.000010,
}

# freq_dict = {
#     'J2-1': (voff_lines_dict['J2-1']*u.km/u.s).to(u.GHz, equivalencies=u.doppler_radio(freq_dict_cen['J2-1']*u.Hz)).value,
#     'J3-2': (voff_lines_dict['J3-2']*u.km/u.s).to(u.GHz, equivalencies=u.doppler_radio(freq_dict_cen['J3-2']*u.Hz)).value,
# }

# Get frequency dictionary in Hz based on the offset velocity and rest frequency
conv_J21 = u.doppler_radio(freq_dict_cen["J2-1"] * u.Hz)
conv_J32 = u.doppler_radio(freq_dict_cen["J3-2"] * u.Hz)
freq_dict = {
    name: ((voff_lines_dict[name] * u.km / u.s).to(u.Hz, equivalencies=conv_J21).value)
    for name in voff_lines_dict.keys()
    if "J2-1" in name
}
freq_dict.update(
    {
        name: ((voff_lines_dict[name] * u.km / u.s).to(u.Hz, equivalencies=conv_J32).value)
        for name in voff_lines_dict.keys()
        if "J3-2" in name
    }
)

# I don't know yet how to use this parameter... in CLASS it does not exist
Exemplo n.º 35
0
from __future__ import print_function
import pyspeckit
from astropy import units as u
sp = pyspeckit.Spectrum('G203.04+1.76_h2co.fits',wcstype='D')
sp.xarr.center_frequency._unit = u.Hz
sp.xarr = sp.xarr.as_unit('km/s', equivalencies=u.doppler_radio(sp.xarr.center_frequency))
sp.specfit(fittype='formaldehyde',multifit=True,usemoments=True,guesses=[-0.6,4,0.2],equivalencies=u.doppler_optical(sp.xarr.center_frequency))
sp.plotter(figure=2)
sp.crop(-5*u.km/u.s,15*u.km/u.s)
sp.specfit(fittype='formaldehyde',multifit=True,usemoments=True,guesses=[-0.6,4,0.2])
sp.specfit(fittype='formaldehyde',multifit=True,usemoments=True,guesses=[-0.6,4,0.2])
sp.specfit.plot_fit(show_components=True)
sp.plotter.savefig("h2co_11_h2cofit.png")
print("Line integral (Formaldehyde,11): ",sp.specfit.integral())
print("Direct Line integral (Formaldehyde,11): ",sp.specfit.integral(direct=True,return_error=True))

sp2 = pyspeckit.Spectrum('G203.04+1.76_h2co.fits',wcstype='V')
sp2.xarr.convert_to_unit('km/s')
sp2.crop(-5*u.km/u.s,15*u.km/u.s)
sp2.plotter(figure=3)
sp2.specfit.peakbgfit(negamp=True, vheight=False)
sp2.specfit.peakbgfit(negamp=True, vheight=False)
sp2.plotter.savefig("h2co_11_gaussfit.png")
print("Line integral (Gaussian,11): ",sp2.specfit.integral())
print("Direct Line integral (Gaussian,11): ",sp2.specfit.integral(direct=True,return_error=True))


sp22g = pyspeckit.Spectrum('G203.04+1.76_h2co_Tastar.fits',wcstype='V')
sp22g.specfit.peakbgfit(negamp=True)
sp22g.xarr = sp22g.xarr.as_unit('km/s')
sp22g.plotter(figure=5)
Exemplo n.º 36
0
    'p-1_01-1_11_03': 0.417,
    'p-1_01-1_11_04': 0.083,
    'p-1_01-1_11_05': 0.139,
    'p-1_01-1_11_06': 0.111,
    ####### para-NH2D J=1_01-0_00
    'p-1_01-0_00_01': 0.111,
    'p-1_01-0_00_02': 0.556,
    'p-1_01-0_00_03': 0.333,
}

# freq_dict = {
#     'J2-1': (voff_lines_dict['J2-1']*u.km/u.s).to(u.GHz, equivalencies=u.doppler_radio(freq_dict_cen['J2-1']*u.Hz)).value,
#     'J3-2': (voff_lines_dict['J3-2']*u.km/u.s).to(u.GHz, equivalencies=u.doppler_radio(freq_dict_cen['J3-2']*u.Hz)).value,
# }
# Get offset velocity dictionary in km/s based on the lines frequencies and rest frequency
conv_o1_1=u.doppler_radio(freq_dict_cen['o-1_01-1_11']*u.Hz)
conv_p1_1=u.doppler_radio(freq_dict_cen['p-1_01-1_11']*u.Hz)
conv_o1_0=u.doppler_radio(freq_dict_cen['o-1_01-0_00']*u.Hz)
conv_p1_0=u.doppler_radio(freq_dict_cen['p-1_01-0_00']*u.Hz)

voff_lines_dict = {
    name: ((freq_dict[name]*u.Hz).to(u.km/u.s, equivalencies=conv_o1_1).value) for name in freq_dict.keys() if "o-1_01-1_11" in name
    }
voff_lines_dict.update({
	name: ((freq_dict[name]*u.Hz).to(u.km/u.s, equivalencies=conv_p1_1).value) for name in freq_dict.keys() if "p-1_01-1_11" in name
    })
voff_lines_dict.update({
	name: ((freq_dict[name]*u.Hz).to(u.km/u.s, equivalencies=conv_p1_1).value) for name in freq_dict.keys() if "o-1_01-0_00" in name
    })
voff_lines_dict.update({
	name: ((freq_dict[name]*u.Hz).to(u.km/u.s, equivalencies=conv_p1_1).value) for name in freq_dict.keys() if "p-1_01-0_00" in name
import matplotlib
import numpy as np
from astropy import units as u
from distutils.version import StrictVersion

if not 'savedir' in globals():
    savedir = ''

# load a FITS-compliant spectrum
spec = pyspeckit.Spectrum('10074-190_HCOp.fits')
# The units are originally frequency (check this by printing spec.xarr.units).
# I want to know the velocity.  Convert!
# Note that this only works because the reference frequency is set in the header
# this is no longer necessary!  #spec.xarr.frequency_to_velocity()
# Default conversion is to m/s, but we traditionally work in km/s
spec.xarr = spec.xarr.as_unit('km/s', equivalencies=u.doppler_radio(spec.xarr.center_frequency))
# plot it up!
spec.plotter()
# Subtract a baseline (the data is only 'mostly' reduced)
spec.baseline(interactive=True)

# specify x points in data units.  We need to transform them to axis units
# because the axis are not consistently generated by mpl
xpoints = [-270,0,50,218,218]
ypoints = [0]*5
buttons = [1,1,1,1,2]
transform = spec.plotter.axis.transData.transform_point
# this absolutely ridiculous line is to deal with scope changes from py2->py3
# http://stackoverflow.com/questions/13905741/accessing-class-variables-from-a-list-comprehension-in-the-class-definition#comment19179733_13913933
def xy_(transform, xpoints, ypoints):
    return [transform((xp,yp)) for xp,yp in zip(xpoints,ypoints)]
Exemplo n.º 38
0
        point = SkyCoord(hdu[0].header['OBSRA'] * u.deg,
                         hdu[0].header['OBSDEC'] * u.deg)
        point_string = point.to_string(style='hmsdms')

        # hdu[0].header['CRVAL5'] = hdu[0].header['OBSRA']
        # hdu[0].header['CRVAL6'] = hdu[0].header['OBSDEC']

        # The ref freq is also confusing. It's the frequency in the rest frame
        # So it needs to be altered to be in the observed frame.
        # GILDAS appears to have this conversion built-in everywhere
        restfreq = hdu[0].header['RESTFREQ'] * u.Hz
        rest_cent_freq = hdu[0].header['CRVAL4'] * u.Hz
        source_vel = hdu[0].header['VELO-LSR'] * u.m / u.s

        # Calculate the frequency shift
        del_f = rest_cent_freq - source_vel.to(u.Hz, u.doppler_radio(restfreq))

        # Adjust CRVAL4 to the observed frame frequency
        hdu[0].header['CRVAL4'] -= del_f.value

        # Need to assign the SD visibilities to an ant pair
        # CASA doesn't barf when doing this, but I can't be sure it worked in
        # any useful way. So don't use this for any science products, just as
        # a check against the GILDAS imaging
        if 'merged' in pref:
            raise ValueError("This does not work. Don't import merged files "
                             "into CASA!")
            baselines = hdu[0].data['BASELINE']
            baselines[np.where(baselines == 0)] = baselines[0]
            hdu[0].data['BASELINE'] = baselines
Exemplo n.º 39
0
 def convert_to_Hz(q):
     return q.to(U.Hz, equivalencies=U.doppler_radio(HIfreq))
from astropy import units as u
rest = 4829.66*u.MHz
chwid = (7.8125*u.kHz)
chan0 = 4824.861*u.MHz
vlsr = 42.27*u.km/u.s
firstchan = (((35*u.km/u.s-vlsr).to(u.MHz, u.doppler_radio(rest)) - chan0) / chwid).decompose()
lastchan = (((80*u.km/u.s-vlsr).to(u.MHz, u.doppler_radio(rest)) - chan0) / chwid).decompose()
print firstchan, lastchan
print "Frequency at channel 550: ",(550*chwid + chan0).to(u.GHz)
print "Frequency at channel 0: ",(0*chwid + chan0).to(u.GHz)
print "Frequency at channel 1024: ",(1024*chwid + chan0).to(u.GHz)
print "Frequency at channel 512: ",(512*chwid + chan0).to(u.GHz)," and according to CASA: ",4.82886*u.GHz
print "total bw: ",1024*chwid
Exemplo n.º 41
0
                  extent=[minfrq, maxfrq, nfields * nconfigs, 0],
                  interpolation='nearest',
                  cmap='gnuplot')
        ax.set_aspect((maxfrq - minfrq) * 2 / (nfields * nconfigs))

        xmin, xmax = ax.get_xlim()
        ax.hlines(np.arange(nfields) * 3, xmin, xmax, color='w', linestyle='-')

        for linename, linefrq in lines_to_overplot.items():
            linefrq = u.Quantity(linefrq).to(u.GHz)
            linefrqval = linefrq.value
            if (minfrq < linefrqval) & (maxfrq > linefrqval):
                for fieldnum, field in fields_and_numbers:
                    vlsr = u.Quantity(field_vlsr[field])
                    shifted_frq = vlsr.to(u.GHz,
                                          u.doppler_radio(linefrq)).value
                    if (minfrq < shifted_frq) & (maxfrq > shifted_frq):
                        ax.vlines(shifted_frq,
                                  fieldnum * nconfigs,
                                  (fieldnum + 1) * nconfigs,
                                  color='b')

    pl.figure(fig.number)
    pl.tight_layout()
    pl.subplots_adjust(wspace=0.05, hspace=0)

    fig.text(0.5, xlabel_offset[band], 'Frequency (GHz)', ha='center')

    fig.savefig(
        f"{basepath}/paper_figures/continuum_selection_regions_band{band}.png",
        bbox_inches='tight')
Exemplo n.º 42
0
from __future__ import print_function
import pyspeckit
import numpy as np
from astropy import units as u

from pyspeckit.spectrum.models import ammonia

xarr = np.linspace(-40, 40, 300) * u.km/u.s
oneonemod = ammonia.ammonia(xarr.to(u.GHz, u.doppler_radio(ammonia.freq_dict['oneone']*u.Hz)),)
twotwomod = ammonia.ammonia(xarr.to(u.GHz, u.doppler_radio(ammonia.freq_dict['twotwo']*u.Hz)),)

sp11 = pyspeckit.Spectrum(xarr=xarr, data=oneonemod, unit=u.K,
                          xarrkwargs={'refX': ammonia.freq_dict['oneone']*u.Hz},
                          header={})
sp22 = pyspeckit.Spectrum(xarr=xarr, data=twotwomod, unit=u.K,
                          xarrkwargs={'refX': ammonia.freq_dict['twotwo']*u.Hz},
                          header={})


input_dict={'oneone':sp11, 'twotwo':sp22,}
spf, specout = pyspeckit.wrappers.fitnh3.fitnh3tkin(input_dict, dobaseline=False)
print(specout.specfit.modelpars)
print(specout.specfit.parinfo)

spf2, specout2 = pyspeckit.wrappers.fitnh3.fitnh3tkin(input_dict,
                                                      dobaseline=True,
                                                      baselinekwargs={'exclude':[-30,30]*u.km/u.s})
print(specout.specfit.modelpars)
print(specout.specfit.parinfo)
Exemplo n.º 43
0
def calculate_syn(linedata=None,
                  ntot=None,
                  tex=None,
                  source_size=None,
                  beam_size=None,
                  species=None,
                  fwhm=None,
                  usetau=True,
                  returnjy=True,
                  spectra=None,
                  fluxcol=None,
                  ilims=[None,None],
                  vsys=None,
                  modelname="model_flux_1",
                  dnu=0.001 * u.GHz,
                  verbose=True,
                  qrot_method='cdms',
                  use_ilims=True
                  ):

    # Step 0, sort table according to frequency
    linedata.sort('freq_rest')

    # Step 1, calculate integrated synthetic line fluxes
    # from Ntot and Tex for the given lines in input "model"
    # This function will calculate Jy if returnjy=True
    # and then use the input beam and source size to also
    # account for beam dilution. This is total integrated fluxes.
    linemodel = utils.calc_line_fluxes(linedata=linedata,
                                      ntot=ntot,
                                      tex=tex,
                                      source=source_size,
                                      beam=beam_size,
                                      species=species,
                                      fwhm=fwhm,
                                      usetau=True,
                                      ilims=ilims,
                                      returnjy=True,
                                      verbose=verbose,
                                      qrot_method=qrot_method,
                                      )
        
    # Step 2, integrate the observed spectrum around frequency for
    # each line. This step is not crucial, but for fitting Ntot or Tex
    # it is useful. However, be careful to compare the same intensity.
    # i.e. integrated vs. fitted Gaussian etc.
    linemodel = utils.integrate_all_lines(spectra=spectra,
                                             model=linemodel,
                                             linedata=linedata,
                                             fluxcol=fluxcol,
                                             ilims=ilims,
                                             vsys=vsys,
                                             verbose=verbose,
                                             )
    # Step 3, check the model for line blends

    linemodel = utils.check_for_blend(model=linemodel,
                                      dnu=dnu,
                                      verbose=verbose)

    if linemodel.meta['blends_present']:
        if verbose:
            print('Blends present, process blends.')
        # Step 4, calculate a summed integrated synthetic line flux
        linemodel = utils.process_model_blends(model=linemodel)
    # Step 5, calculate the synthetic spectrum and put it in
    # a new column named as the input parameter "modelname".
    # note that linemodel_syn is different from the linemodel
    # data structure.

    spectra_syn, linemodel_syn = utils.calc_synthetic_spectrum(model=linemodel,
                                                                  spectra=spectra,
                                                                  fluxcol=fluxcol,
                                                                  modelname=modelname,
                                                                  fwhm=fwhm,
                                                                  verbose=verbose,
                                                                  )

    linemodel.meta['ilims'] = ilims

    # add a column with velocity for each line
    # makes plotting some what easier
    try:
        linemodel_syn['vel_rest'] = [i.quantity.to(u.km/u.s, 
            equivalencies=u.doppler_radio(j)) for (i,j) in zip(
                linemodel_syn['freq_rest'],
                linemodel['freq_rest'].quantity)]
    except(AttributeError): # if theres only one entry
        if verbose:
            print('WARN:Only one line, ugly hack ahead. Check units.')
        linemodel_syn['vel_rest'] = [(i*u.GHz).to(u.km/u.s, 
            equivalencies=u.doppler_radio(j*u.GHz)) for (i,j) in zip(
                linemodel_syn['freq_rest'],
                linemodel['freq_rest'])]
    return spectra_syn, linemodel_syn, linemodel
Exemplo n.º 44
0
    def radio_velocities(self):
        if self._radio_velocities is None:
            rad_eq = u.doppler_radio(self.rest_frequency)
            self._radio_velocities = self.frequencies.to(u.km / u.s, rad_eq)

        return self._radio_velocities