Exemple #1
0
    def jtok_equiv(self, freq):
        '''
        Return conversion function between Jy/beam to K at the specified
        frequency.

        The function can be used with the usual astropy.units conversion:
        >>> beam = Beam.from_fits_header("header.fits") # doctest: +SKIP
        >>> (1.0*u.Jy).to(u.K, beam.jtok_equiv(1.4*u.GHz)) # doctest: +SKIP

        Parameters
        ----------
        freq : astropy.units.quantity.Quantity
            Frequency to calculate conversion.

        Returns
        -------
        u.brightness_temperature
        '''

        if not isinstance(freq, u.quantity.Quantity):
            raise TypeError("freq must be a Quantity object. "
                            "Try 'freq*u.Hz' or another equivalent unit.")

        try:
            return u.brightness_temperature(beam_area=self.sr, frequency=freq)
        except TypeError:
            # old astropy used ordered arguments
            return u.brightness_temperature(self.sr, freq)
def test_brightness_temperature():
    omega_B = np.pi * (50 * u.arcsec) ** 2
    nu = u.GHz * 5
    tb = 7.052587837212582 * u.K
    np.testing.assert_almost_equal(
        tb.value, (1 * u.Jy).to_value(
            u.K, equivalencies=u.brightness_temperature(nu, beam_area=omega_B)))
    np.testing.assert_almost_equal(
        1.0, tb.to_value(
            u.Jy, equivalencies=u.brightness_temperature(nu, beam_area=omega_B)))
Exemple #3
0
def test_brightness_temperature():
    omega_B = np.pi * (50 * u.arcsec) ** 2
    nu = u.GHz * 5
    tb = 7.052590289134352 * u.K
    np.testing.assert_almost_equal(
        tb.value, (1 * u.Jy).to_value(
            u.K, equivalencies=u.brightness_temperature(nu, beam_area=omega_B)))
    np.testing.assert_almost_equal(
        1.0, tb.to_value(
            u.Jy, equivalencies=u.brightness_temperature(nu, beam_area=omega_B)))
Exemple #4
0
def Snu(Te=default_te, nu=95*u.GHz, R=0.1*u.pc, Qlyc=1e45*u.s**-1, beam=4000*u.au,
        angular_beam=0.5*u.arcsec):
    tb = Tb(Te=Te, nu=nu, EM=EM(R=R, Qlyc=Qlyc))
    if beam < R:
        return tb.to(u.mJy,
                     u.brightness_temperature(radio_beam.Beam(angular_beam),
                                              nu))
    else:
        return (tb * (R/beam)**2).to(u.mJy,
                                     u.brightness_temperature(radio_beam.Beam(angular_beam),
                                                              nu))
    def to_unit(self, final_unit, barea=None, freq=None):

        input_units = self.physical_units

        if freq is None:
            freq = self.obs_frequency

        if barea is None:
            beam_area = self.beam_area
        else:
            beam_area = barea

        if self.nmaps == 1:
            try:
                x = 1.0 * input_units[0]
                t = x.to(final_unit,
                         equivalencies=u.brightness_temperature(
                             beam_area, freq))
                self.data[:] = t * self.data[:]
                self.header['TUNIT{0}'.format(1)] = final_unit.to_string()
            except UnitConversionError:
                try:
                    x = 1.0 * input_units[0]**(1 / 2)
                    t = x.to(final_unit,
                             equivalencies=u.brightness_temperature(
                                 beam_area, freq))
                    self.data[:] = t * t * self.data[:]
                    self.header['TUNIT{0}'.format(
                        1)] = final_unit.to_string() + '^2'
                except UnitConversionError:
                    pass
        else:
            for jmap in range(self.nmaps):
                try:
                    x = 1.0 * input_units[jmap]
                    t = x.to(final_unit,
                             equivalencies=u.brightness_temperature(
                                 beam_area[jmap], freq))
                    self.data[jmap, :] = t * self.data[jmap, :]
                    self.header['TUNIT{0}'.format(jmap +
                                                  1)] = final_unit.to_string()
                except UnitConversionError:
                    try:
                        x = 1.0 * input_units[jmap]**(1 / 2)
                        t = x.to(final_unit,
                                 equivalencies=u.brightness_temperature(
                                     beam_area[jmap], freq))
                        self.data[jmap, :] = t * t * self.data[jmap, :]
                        self.header['TUNIT{0}'.format(
                            jmap + 1)] = '(' + final_unit.to_string() + ')^2'
                    except UnitConversionError:
                        pass
Exemple #6
0
def JybeamtoKkms(fluxdict):
    intensitylist={}
    t_bright={}
    dictkeys=fluxdict.keys()
    for key in dictkeys:
        temptransdict=fluxdict[key]
        temptransdictkeys=list(temptransdict.keys())
        print(temptransdictkeys)
        for i in range(len(temptransdictkeys)):
            if 'restfreq' in temptransdictkeys[i]:
                continue
            else:
                temp=(temptransdict[temptransdictkeys[i]]['flux']/linewidth_vel).to('Jy')
                #print(temp)
                equiv=u.brightness_temperature(temptransdict[temptransdictkeys[i]]['freq'])
                #print(equiv)
                jy_sr=temp/temptransdict[temptransdictkeys[i]]['beam']
                #print(jy_sr)
                conversion=jy_sr.to(u.K,equivalencies=equiv)
                t_bright.update({temptransdictkeys[i]:conversion})
                #print(conversion)
                velflux_T=conversion*linewidth_vel
                d_velfluxT=(temptransdict[temptransdictkeys[i]]['stddev']/conversion)*velflux_T
                intensityerror.append(d_velfluxT)
                #print(velflux_T)
                #print('\n')
                intensitylist.update({temptransdictkeys[i]:velflux_T})
    return intensitylist,t_bright
def test_swapped_args_brightness_temperature():
    """
    #5173 changes the order of arguments but accepts the old (deprecated) args
    """
    omega_B = np.pi * (50 * u.arcsec) ** 2
    nu = u.GHz * 5
    tb = 7.052587837212582 * u.K

    with pytest.warns(AstropyDeprecationWarning) as w:
        result = (1*u.Jy).to(
            u.K, equivalencies=u.brightness_temperature(omega_B, nu))
        roundtrip = result.to(
            u.Jy, equivalencies=u.brightness_temperature(omega_B, nu))
    assert len(w) == 2
    np.testing.assert_almost_equal(tb.value, result.value)
    np.testing.assert_almost_equal(roundtrip.value, 1)
Exemple #8
0
def convert_jyperbeam_k(v, bmaj=0., bmin=0., fits_img=None):
    """
    calculate the conversion factor from Jy/beam to K
    ref: http://docs.astropy.org/en/stable/api/astropy.units.brightness_temperature.html#astropy.units.brightness_temperature
    this code give the same results as miriad imstat
    :param v: MHz, the freqency of observation
    :param bmaj: deg, the beam major angle
    :param bmin: deg, the beam minor angle
    :param fits_img: optional, the fits image to provide the bmaj and bmin
    :return: the conversion factor from Jy/beam to K
    """

    if fits_img != None:
        fits_open = fits.open(fits_img)
        head = fits_open[0].header
        bmaj = head['BMAJ']
        bmin = head['BMIN']

    bmaj = bmaj * u.deg
    bmin = bmin * u.deg
    fwhm_to_sigma = 1. / (8. * np.log(2.))**0.5
    beam_area = 2. * np.pi * (bmaj * bmin * fwhm_to_sigma**2.)
    freq = v * u.MHz
    equiv = u.brightness_temperature(beam_area, freq)
    return u.Jy.to(u.K, equivalencies=equiv)
def scale_values(cat=None, type=None, cubhd=None):
    if type == 'imean':  # Convert Jy*ch to K km/s
        if 'RESTFREQ' in cubhd.keys():
            freq = cubhd['RESTFREQ'] * u.Hz
        elif 'RESTFRQ' in cubhd.keys():
            freq = cubhd['RESTFRQ'] * u.Hz
        deltav = cubhd['cdelt3'] / 1000. * u.km / u.s
        as2 = 1 * u.arcsec**2
        kflux = deltav * as2 * cat['flux'].to(
            u.K, equivalencies=u.brightness_temperature(as2, freq))
        cat[type] = kflux / cat['area_exact']
        cat[type].unit = 'K km / s'
        label = 'mean intensity'
    elif type == 'v_rms':  # Convert m/s to km/s
        cat[type] = cat['v_rms'].to(u.km / u.s)
        cat[type].unit = 'km / s'
        label = 'velocity dispersion'
    elif type == 'v_cen':  # convert ch number to km/s
        cat[type] = 1.e-3 * (cubhd['crval3'] + cubhd['cdelt3'] *
                             (cat['v_cen'] - cubhd['crpix3']))
        cat[type].unit = 'km / s'
        label = 'mean velocity'
    elif type == 'tmax':
        label = 'peak temperature'
    else:
        label = type
    return label
Exemple #10
0
def conversion(v, bmaj, bmin):
    '''
    v(GHz),bmaj(deg),bmin(deg),retrun(Jy/beam -> K)
    '''
    if bmaj == bmin:
        beam_sigma = bmaj * u.deg
        beam_area = 2 * np.pi * (beam_sigma)**2
        freq = v * u.GHz
        equiv = u.brightness_temperature(beam_area, freq)
    else:
        bmaj = bmaj * u.deg
        bmin = bmin * u.deg
        fwhm_to_sigma = 1. / (8 * np.log(2))**0.5
        beam_area = 2. * np.pi * (bmaj * bmin * fwhm_to_sigma**2)
        freq = v * u.GHz
        equiv = u.brightness_temperature(beam_area, freq)
    return u.Jy.to(u.K, equivalencies=equiv)
def get_cont(header):
    contfn = paths.dpath('W51_te_continuum_best.fits')
    beam = radio_beam.Beam.from_fits_header(contfn)
    cont_Jy = reproject.reproject_interp(input_data=contfn,
                                         output_projection=header)[0]*u.Jy
    cont_K = cont_Jy.to(u.K, u.brightness_temperature(beam,
                                                      continuum_frequency))
    return cont_K
def convert_to_K(radmc_fits_img, distance=5400*u.pc):
    fh = fits.open(radmc_fits_img)
    mywcs = wcs.WCS(fh[0].header)
    pix_area = np.abs(mywcs.celestial.pixel_scale_matrix.diagonal().prod()) * u.deg**2
    conv = u.Jy.to(u.K, equivalencies=u.brightness_temperature(pix_area, mywcs.wcs.crval[2]*u.Hz))
    fh[0].data *= conv
    fh[0].header['BUNIT'] = 'K'
    return fh
 def factor_K2JyPixel(self):
     """
     Conversion factor from [K] to [Jy/pixel]
     """
     pixarea = (self.pixelsize * au.arcsec)**2
     freq = self.freq * au.MHz
     equiv = au.brightness_temperature(pixarea, freq)
     factor = au.K.to(au.Jy, equivalencies=equiv)
     return factor
Exemple #14
0
 def factor_K2JyPixel(self):
     """
     Conversion factor from [K] to [Jy/pixel]
     """
     pixarea = (self.pixelsize * au.arcsec) ** 2
     freq = self.freq * au.MHz
     equiv = au.brightness_temperature(pixarea, freq)
     factor = au.K.to(au.Jy, equivalencies=equiv)
     return factor
Exemple #15
0
def convert_jy_to_k(hdul):
    header = hdul[0].header
    beam = radio_beam.Beam.from_fits_header(header)
    name = hdul[0].fileinfo()['file'].name
    freq = re.search('\d+\.\d+GHz', name).group().rstrip('GHz')
    freq = float(freq) * u.GHz
    conv = (1 * u.Jy).to(u.K, u.brightness_temperature(beam, freq))
    hdul[0].data = hdul[0].data * conv.value
    return conv
def convert_jy_kelvin(bmajor,bminor,frequ):

    beam_major = bmajor*u.arcsec
    beam_minor = bminor*u.arcsec
    freq       = frequ*u.Hz
    fwhm_to_sigma = 1./(8*np.log(2))**0.5
    beam_area = 2.*np.pi*(beam_major*beam_minor*fwhm_to_sigma**2) 
    equiv = u.brightness_temperature(beam_area, freq)
    T = (u.Jy.to(u.K, equivalencies=equiv))
    return T
Exemple #17
0
    def source_line_brightness_temperature(self):
        """
        The surface brightness of the source assuming it is observed with a
        beam matched to its size and it has ff=1

        (this is consistent with the online RADEX calculator)
        """
        #return (self.line_flux * beamsize)
        # because each line has a different frequency, have to loop it
        return ((self.source_line_surfbrightness * u.sr).to(
            u.K, u.brightness_temperature(1 * u.sr, self.frequency)))
Exemple #18
0
def test_jtok():

    major = 0.1 * u.rad
    beam = Beam(major, major, 30 * u.deg)

    freq = 1.42 * u.GHz

    conv_factor = u.brightness_temperature(beam.sr, freq)

    assert_quantity_allclose((1 * u.Jy).to(u.K, equivalencies=conv_factor),
                             beam.jtok(freq))
def test_jtok():

    major = 0.1 * u.rad
    beam = Beam(major, major, 30 * u.deg)

    freq = 1.42 * u.GHz

    conv_factor = u.brightness_temperature(beam.sr, freq)

    assert_quantity_allclose((1 * u.Jy).to(u.K, equivalencies=conv_factor),
                             beam.jtok(freq))
Exemple #20
0
def test_swapped_args_brightness_temperature():
    """
    #5173 changes the order of arguments but accepts the old (deprecated) args
    """
    omega_B = np.pi * (50 * u.arcsec) ** 2
    nu = u.GHz * 5
    tb = 7.052590289134352 * u.K
    # https://docs.pytest.org/en/latest/warnings.html#ensuring-function-triggers
    with warnings.catch_warnings():
        warnings.simplefilter('always')
        with pytest.warns(DeprecationWarning) as warning_list:
            result = (1*u.Jy).to(u.K,
                                 equivalencies=u.brightness_temperature(omega_B,
                                                                        nu))
            roundtrip = result.to(u.Jy,
                                  equivalencies=u.brightness_temperature(omega_B,
                                                                         nu))
    assert len(warning_list) == 2
    np.testing.assert_almost_equal(tb.value, result.value)
    np.testing.assert_almost_equal(roundtrip.value, 1)
def convert_to_K(radmc_fits_img, distance=5400 * u.pc):
    fh = fits.open(radmc_fits_img)
    mywcs = wcs.WCS(fh[0].header)
    pix_area = np.abs(
        mywcs.celestial.pixel_scale_matrix.diagonal().prod()) * u.deg**2
    conv = u.Jy.to(u.K,
                   equivalencies=u.brightness_temperature(
                       pix_area, mywcs.wcs.crval[2] * u.Hz))
    fh[0].data *= conv
    fh[0].header['BUNIT'] = 'K'
    return fh
Exemple #22
0
def test_swapped_args_brightness_temperature():
    """
    #5173 changes the order of arguments but accepts the old (deprecated) args
    """
    omega_B = np.pi * (50 * u.arcsec)**2
    nu = u.GHz * 5
    tb = 7.052590289134352 * u.K
    # https://docs.pytest.org/en/latest/warnings.html#ensuring-function-triggers
    with warnings.catch_warnings():
        warnings.simplefilter('always')
        with pytest.warns(DeprecationWarning) as warning_list:
            result = (1 * u.Jy).to(u.K,
                                   equivalencies=u.brightness_temperature(
                                       omega_B, nu))
            roundtrip = result.to(u.Jy,
                                  equivalencies=u.brightness_temperature(
                                      omega_B, nu))
    assert len(warning_list) == 2
    np.testing.assert_almost_equal(tb.value, result.value)
    np.testing.assert_almost_equal(roundtrip.value, 1)
Exemple #23
0
    def source_line_brightness_temperature(self):
        """
        The surface brightness of the source assuming it is observed with a
        beam matched to its size and it has ff=1

        (this is consistent with the online RADEX calculator)
        """
        #return (self.line_flux * beamsize)
        # because each line has a different frequency, have to loop it
        return ((self.source_line_surfbrightness*u.sr).
                 to(u.K, u.brightness_temperature(1*u.sr,
                                                  self.frequency)))
Exemple #24
0
def T2I(temperature, v, bmaj, bmin):
    '''
    calculate intensity
    temperature(K) v(GHz) bmaj(arcsec) bmin(arcsec)
    return 1 (Jy/beam)
    '''
    fwhm_to_sigma = 1. / (8 * np.log(2))**0.5
    beam_area = 2. * np.pi * (bmaj * un.arcsec * bmin * un.arcsec *
                              fwhm_to_sigma**2)
    freq = v * u.GHz
    equiv = u.brightness_temperature(freq)

    return temperature / (u.Jy / beam_area).to(u.K, equivalencies=equiv)
Exemple #25
0
 def line_brightness_temperature(self,beamsize):
     """
     Return the line surface brightness in kelvins for a given beam area
     (Assumes the frequencies are rest frequencies)
     """
     #return (self.line_flux * beamsize)
     # because each line has a different frequency, have to loop it
     try:
         return u.Quantity([x.to(u.K, u.brightness_temperature(beamsize, f)).value
                            for x,f in zip(self.line_flux_density,self.frequency)
                            ],
                           unit=u.K)
     except AttributeError as ex:
         raise NotImplementedError("line brightness temperature is not implemented "
                                   "without reference to astropy units yet")
Exemple #26
0
 def line_brightness_temperature(self,beamsize):
     """
     Return the line surface brightness in kelvins for a given beam area
     (Assumes the frequencies are rest frequencies)
     """
     #return (self.line_flux * beamsize)
     # because each line has a different frequency, have to loop it
     try:
         return u.Quantity([x.to(u.K, u.brightness_temperature(beamsize, f)).value
                            for x,f in zip(self.line_flux_density,self.frequency)
                            ],
                           unit=u.K)
     except AttributeError as ex:
         raise NotImplementedError("line brightness temperature is not implemented "
                                   "without reference to astropy units yet")
Exemple #27
0
def JybeamtoK(beams,data):
    intensitylist=[]
    t_bright=[]
    for i in range(len(data)):
        temp=(data[i]).to('Jy/beam')
        #print(temp)
        equiv=u.brightness_temperature(data.spectral_axis[i])
        #print(equiv)
        jy_sr=temp/beams[i]
        #print(jy_sr)
        conversion=jy_sr.to(u.K,equivalencies=equiv)
        t_bright.append(conversion.value)
        #print(conversion)
        #velflux_T=conversion*lwvel
        #print(velflux_T)
        #print('\n')
        #intensitylist.append(velflux_T)
    return t_bright
Exemple #28
0
def Jy_to_Kelvin(flux, freqs):
    '''
    Convert flux spectrum in Jy/beam to temperature units. Frequency inputs in MHz.

    Parameters
    ----------
    flux : 1D Array (float)
        Spectrum over frequency band in Jy
    freqs : 1D Array (float)
        Frequencies (in MHz)
    '''
    beam_FWHM = 755.0 / (np.mean(freqs * 0.001)) * u.arcsec
    beam_area = 2 * np.pi * (beam_FWHM * fwhm_to_sig)**2
    freq_MHz = np.mean(freqs) * u.MHz
    equiv = u.brightness_temperature(beam_area, freq_MHz)
    T = (flux * u.Jy).to(u.K, equivalencies=equiv)

    return T, freqs
Exemple #29
0
def get_nhi(sigma, sens, linewidth, beam_maj, beam_min):
    """
    Get N_HI sens at sigma level
    Inputs:
    - sigma: Number, significance level for result
    - sens: Quantity, sensitivity matched to linewidth
    - linewidth: Quantity, linewidth from N_HI calc
    - beam_fwhm: Quantity, beam fwhm
    """
    omega_beam = get_beam_area(beam_maj, beam_min)
    #hitools, hi freq
    #should maybe define globally?
    freq = 1420.405752 * u.MHz
    #convert to brightness temp
    tb = sens.to(u.K, u.brightness_temperature(freq, beam_area=omega_beam))
    #convert to N_HI
    nhi = 1.823e18 * tb * linewidth / (u.K * u.km / u.s) / (u.cm * u.cm)
    nhi_sig = sigma * nhi
    return nhi_sig
Exemple #30
0
def k2jysr(temp, freq):
    """
    Convert K to Jy/sr.

    Parameters
    ----------
    temp: array-like
        Brightness temperature in Kelvin
    freq: float
        Frequency of the map in MHz

    Return
    ------
    out: array-like or float
        Intensity (brightness) in Jy/sr

    """
    ba = 1 * u.sr
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (temp * u.K).to(u.Jy, equivalencies=equiv).value
Exemple #31
0
def k2jysr(temp, freq):
    """
    Convert K to Jy/sr.

    Parameters
    ----------
    temp: array-like
        Brightness temperature in Kelvin
    freq: float
        Frequency of the map in MHz

    Return
    ------
    out: array-like or float
        Intensity (brightness) in Jy/sr

    """
    ba = 1 * u.sr
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (temp * u.K).to(u.Jy, equivalencies=equiv).value
Exemple #32
0
def jysr2k(intensity, freq):
    """
    Convert Jy/sr to K.

    Parameters
    ----------
    intensity: array-like
        Intensity (brightness) in Jy/sr
    freq: float
        Frequency of the map in MHz

    Return
    ------
    out: array-like or float
        Brightness temperature in Kelvin


    """
    ba = 1 * u.sr
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (intensity * u.Jy).to(u.K, equivalencies=equiv).value
Exemple #33
0
def jysr2k(intensity, freq):
    """
    Convert Jy/sr to K.

    Parameters
    ----------
    intensity: array-like
        Intensity (brightness) in Jy/sr
    freq: float
        Frequency of the map in MHz

    Return
    ------
    out: array-like or float
        Brightness temperature in Kelvin


    """
    ba = 1 * u.sr
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (intensity * u.Jy).to(u.K, equivalencies=equiv).value
Exemple #34
0
def convert_to_casa(hdu):
    """
    Convert a FITS HDU to casa-compatible units, i.e., Jy/beam
    """
    hdu = file_in(hdu)[0].copy()

    beam = radio_beam.Beam.from_fits_header(hdu.header)

    if hdu.header['BUNIT'] == 'K':
        imwcs = wcs.WCS(hdu.header)
        cfreq = imwcs.sub([wcs.WCSSUB_SPECTRAL]).wcs_world2pix([0], 0)[0][0]
        hdu.data = u.Quantity(hdu.data, unit=u.K).to(
            u.Jy, u.brightness_temperature(beam, cfreq * u.Hz)).value
    elif u.Unit(hdu.header['BUNIT']).is_equivalent(u.MJy / u.sr):
        hdu.data = u.Quantity(hdu.data, u.Unit(hdu.header['BUNIT'])).to(
            u.Jy / beam).value
    elif hdu.header['BUNIT'] != 'Jy/beam':
        raise ValueError("Header BUNIT not recognized")

    hdu.header['BUNIT'] = 'Jy/beam'

    return hdu
Exemple #35
0
def k2jybeam(temp, freq, beam_width):
    """
    Convert K to Jy/beam.

    Parameters
    ----------
    temp: array-like
        Brightness temperature in Kelvin
    freq: float
        Frequency of the map in MHz
    beam_width: float
        The Gaussian FWHM width in degree

    Return
    ------
    out: array-like or float
        Intensity (brightness) in Jy/beam

    """
    ba = beam_area(beam_width) * u.Unit('deg2')
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (temp * u.K).to(u.Jy, equivalencies=equiv).value
Exemple #36
0
def jybeam2k(intensity, freq, beam_width):
    """
    Convert Jy/beam to K.

    Parameters
    ----------
    intensity: array-like
        Intensity (brightness) in Jy/beam
    freq: float
        Frequency of the map in MHz
    beam_width: float
        The Gaussian FWHM width in degree

    Return
    ------
    out: array-like or float
        Brightness temperature in Kelvin

    """
    ba = beam_area(beam_width) * u.Unit('deg2')
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (intensity * u.Jy).to(u.K, equivalencies=equiv).value
Exemple #37
0
def jybeam2k(intensity, freq, beam_width):
    """
    Convert Jy/beam to K.

    Parameters
    ----------
    intensity: array-like
        Intensity (brightness) in Jy/beam
    freq: float
        Frequency of the map in MHz
    beam_width: float
        The Gaussian FWHM width in degree

    Return
    ------
    out: array-like or float
        Brightness temperature in Kelvin

    """
    ba = beam_area(beam_width) * u.Unit('deg2')
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (intensity * u.Jy).to(u.K, equivalencies=equiv).value
Exemple #38
0
def k2jybeam(temp, freq, beam_width):
    """
    Convert K to Jy/beam.

    Parameters
    ----------
    temp: array-like
        Brightness temperature in Kelvin
    freq: float
        Frequency of the map in MHz
    beam_width: float
        The Gaussian FWHM width in degree

    Return
    ------
    out: array-like or float
        Intensity (brightness) in Jy/beam

    """
    ba = beam_area(beam_width) * u.Unit('deg2')
    equiv = u.brightness_temperature(ba, freq * u.MHz)
    return (temp * u.K).to(u.Jy, equivalencies=equiv).value
def dendrogram_downaddmom_cube(*args, **kwargs):

    datacube_dt, datacube_dt_header = downsample_addnoise_and_momentmask(*args)
    datacube_dt_wcs = wcs.wcs.WCS(datacube_dt_header)

    beam_size = 1/8 * u.deg
    frequency = 115 * u.GHz

    d = astrodendro.Dendrogram.compute(datacube_dt, wcs=datacube_dt_wcs, **kwargs)

    v_scale = datacube_dt_header['cdelt3']
    v_unit = u.km / u.s
    l_scale = datacube_dt_header['cdelt1']
    b_scale = datacube_dt_header['cdelt2']

    metadata = {}
    metadata['data_unit'] = u.K
    metadata['spatial_scale'] = b_scale * u.deg
    metadata['velocity_scale'] = v_scale * v_unit
    metadata['wavelength'] = frequency 
    metadata['beam_major'] = beam_size
    metadata['beam_minor'] = beam_size    
    metadata['vaxis'] = 0 # keep it this way if you think the (post-downsample/transposed) input data is (l, b, v)
    metadata['wcs'] = datacube_dt_wcs

    catalog = astrodendro.ppv_catalog(d, metadata, verbose=True)

    flux = u.Quantity(catalog['flux'])
    area_exact = catalog['area_exact'].unit*catalog['area_exact'].data

    # average brightness temperature integrated over area_exact
    flux_kelvin = flux.to('K', equivalencies=u.brightness_temperature(area_exact, frequency))
    # flux integrated over area and velocity
    flux_kelvin_kms_deg2 = flux_kelvin * metadata['velocity_scale'] * area_exact

    catalog.add_column(astropy.table.Column(data=flux_kelvin_kms_deg2, name='flux_kelvin_kms_deg2'))

    return d, catalog, datacube_dt_header, metadata
Exemple #40
0
def jy_to_ksr(freqs):
    """
    Calculate multiplicative factors to convert [Jy] to [K sr].

    Parameters
    ----------
    freqs : :class:`astropy.Quantity` or array_like of float (Deprecated)
        Frequencies, assumed to be in Hz if not a Quantity.

    Returns
    -------
    Quantity
        Conversion factor(s) to go from [Jy] to [K sr]. Shape equal to shape of freqs.
    """
    freqs = np.atleast_1d(freqs)
    if not isinstance(freqs, Quantity):
        freqs = freqs * units.Hz

    equiv = units.brightness_temperature(freqs, beam_area=1 * units.sr)
    conv_factor = (1 * units.Jy).to(units.K,
                                    equivalencies=equiv) * units.sr / units.Jy

    return conv_factor
Exemple #41
0
    def to_temperature(self,
                       bmaj: Optional[u.Quantity] = None,
                       bmin: Optional[u.Quantity] = None) -> u.Quantity:
        """Obtain the intensity axis in temperature units.

        Args:
          bmaj: optional; beam major axis.
          bmin: optional; beam minor axis.

        Returns:
          The intensity axis in temperature units.
        """
        # Beam
        if bmaj is not None and bmin is not None:
            beam = Beam(bmaj, bmin)
        elif self.beam is not None:
            beam = self.beam
        else:
            raise ValueError('Cannot convert to temperature units')

        # Convert
        equiv = u.brightness_temperature(self.spectral_axis, beam_area=beam)
        return self.intensity.to(u.K, equivalencies=equiv)
Exemple #42
0
    def jtok_equiv(self, freq):
        '''
        Return conversion function between Jy/beam to K at the specified
        frequency.

        The function can be used with the usual astropy.units conversion:
        >>> (1.0*u.Jy).to(u.K, self.jtok_equiv(1.4*u.GHz))

        Parameters
        ----------
        freq : astropy.units.quantity.Quantity
            Frequency to calculate conversion.

        Returns
        -------
        u.brightness_temperature
        '''

        if not isinstance(freq, u.quantity.Quantity):
            raise TypeError("freq must be a Quantity object. "
                            "Try 'freq*u.Hz' or another equivalent unit.")

        return u.brightness_temperature(self.sr, freq)
def load_spectrum(j=6, object='w51e2-tot',
                  npix=1,
                  headerfile='../W51-25GHzcont.map.image.fits',
                  fntemplate='spec-{object}-{j}{j2}-pb.txt',):
    # convert 6 -> 'six' for use below
    linename = ammonia_constants.num_to_name[j] * 2

    # the beam size is important for determining the brighntess conversion
    bm = radio_beam.Beam.from_fits_header(headerfile)

    # read in the file (dumped to text)
    xx,yy=np.loadtxt(fntemplate.format(object=object, j=j, j2=j if j < 10 else ""),
                     comments="#").T
    # we want MEAN flux, not SUM
    yy = yy / npix

    # x units are in km/s, reference is in Hz
    xarr = SpectroscopicAxis(xx*u.km/u.s,
                             refX=ammonia.freq_dict[linename]*u.Hz,
                             velocity_convention='radio')
    sp = pyspeckit.Spectrum(xarr=xarr, data=yy)
    sp.unit = 'Jy'
    # compute the typical noise over the -10 to 10 km/s region
    mean_error = sp.stats((-10,10))['std']
    sp.error[:] = mean_error
    sp.specname = '{0} {1}'.format(object, linename)

    # Copy the spectrum so we can convert it to Kelvins
    spK = sp.copy()
    jytok = ((1*u.Jy).to(u.K, u.brightness_temperature(bm, sp.xarr.refX)).value)
    sp.header['JYTOK'] = jytok
    spK.unit = 'K'
    spK.data = sp.data * jytok
    spK.error = sp.error * jytok
    mean_error_k = mean_error * jytok

    return sp, spK, mean_error, mean_error_k
Exemple #44
0
def density_distribution(densarr, distr, moleculecolumn, tauthresh=0.8,
                         opr=None, line_ids=[], mincol=None, Radex=Radex,
                         **kwargs):
    """
    Compute the LVG model for a single zone with an assumed density
    *distribution* but other properties fixed.

    Parameters
    ----------
    dendarr : array
        Array of densities corresponding to the distribution function
    distr : array
        The density distribution corresponding to the density array
    moleculecolumn : quantity
        The total column density of the molecule in question.  It will be
        redistributed across the appropriate densities.  Units: cm^-2
        [this is wrong - each density will assume a too-low optical depth]
    """
    try:
        np.testing.assert_almost_equal(distr.sum(), 1)
    except AssertionError:
        raise ValueError("The distribution must be normalized.")

    if not line_ids:
        raise ValueError("Specify at least one line ID")

    meandens = (densarr*distr).mean()
    if opr is None:
        collider_densities = {'H2': meandens}
    else:
        fortho = opr/(1+opr)
        collider_densities = {'oH2':meandens*fortho,'pH2':meandens*(1-fortho)}


    # Test whether the multi-slab model is reasonable by checking:
    # if the column was all at the mean density, would any lines be
    # optically thick?
    R = Radex(collider_densities=collider_densities, column=moleculecolumn, **kwargs)
    R.run_radex()
    if np.any(R.tau > tauthresh):
        warnings.warn(("At least one line optical depth is >{tauthresh}.  "
                       "Smoothing may be invalid.").format(tauthresh=tauthresh))

    # set the optical depth from the *mean* density assuming the *total* column
    tau = R.tau
    print("Mean density: {0}  Optical Depth: {1}".format(meandens, tau[line_ids]))

    _thc = (2 * constants.h * constants.c).cgs / u.sr
    _fk = (constants.h * constants.c / constants.k_B).cgs
    _thc_value = _thc.value
    _fk_value = _fk.value
    _u_brightness = (u.erg * u.s**-1 * u.cm**-2 * u.Hz**-1 * u.sr**-1)

    xnu = R.frequency.to(u.cm**-1, u.spectral()).value

    linestrengths = []
    texs = []
    for dens,prob in zip(densarr,distr):
        if opr is None:
            collider_densities = {'H2':dens}
        else:
            collider_densities = {'oH2':dens*fortho,'pH2':dens*(1-fortho)}
        R.density = collider_densities
        try:
            R.column = moleculecolumn * prob
            if mincol is not None and R.column < mincol:
                R.column = mincol
            R.run_radex()
        except ValueError as ex:
            if ex.args[0] == "Extremely low or extremely high column.":
                if R.column > u.Quantity(1e20, u.cm**-2):
                    raise ex
                else:
                    texs.append(np.zeros_like(line_ids)+2.73)
                    linestrengths.append(np.zeros_like(line_ids))
                    continue
            else:
                raise ex
        
        if hasattr(R, 'radex'):
            R.radex.radi.taul[:len(tau)] = tau
        elif hasattr(R, '_data_dict'):
            R._data_dict['tau'] = tau

        fk = _fk_value
        thc = _thc_value

        with QuantityOff():
            ftau = np.exp(-tau)
            xt = xnu**3
            earg = fk*xnu/R.tex
            bnutex = thc*xt/(np.exp(earg)-1.0)
            toti_nounit = R.background_brightness*ftau+bnutex*(1.0-ftau)

        toti = u.Quantity(toti_nounit, _u_brightness)
        totK = ((toti*u.sr).to(u.K, u.brightness_temperature(1*u.sr,
                                                             R.frequency)))

        linestrengths.append(totK[line_ids])
        texs.append(R.tex[line_ids])

    linestrengths = np.array(linestrengths)
    texs = np.array(texs)

    return R, linestrengths, linestrengths.sum(axis=0), texs, tau[line_ids]
import mpl_plot_templates
import numpy as np
from agpy import fit_a_line
import astropy.units as u
import common_constants
from common_constants import h2co11freq, h2co22freq, etamb_77, rrl, aobeamarea, gbbeamarea
from paths import datapath, fpath
import matplotlib

matplotlib.rc_file("pubfiguresrc")
pl.mpl.rcParams["axes.color_cycle"] = [
    "#" + x for x in "348ABD, 7A68A6, A60628, 467821, CF4457, 188487, E24A33".split(", ")
]

# Have to convert to Jy to compare fairly
ktojy111 = (1 * u.K).to(u.Jy, u.brightness_temperature(aobeamarea, h2co11freq))
ktojy77 = (1 * u.K).to(u.Jy, u.brightness_temperature(gbbeamarea, h2co22freq))

aofn = os.path.join(datapath, "W51_Halpha_6cm_cube_supersampled.fits")
h112i = (
    fits.getdata(os.path.join(datapath, "H110a_integral.fits")) * ktojy111
)  # ,aofn.replace("cube","integrated"))) * ktojy111
h112a = fits.getdata(os.path.join(datapath, "H110a_amplitude.fits")) * ktojy111
h112a.value[h112a == 0] = np.nan
h112c = fits.getdata(os.path.join(datapath, "W51_Halpha_6cm_cube_supersampled_continuum.fits")) * ktojy111
h112c.value[h112c == 0] = np.nan
h112h = fits.getheader(os.path.join(datapath, "W51_Halpha_6cm_cube_supersampled_continuum.fits"))

h77iname = os.path.join(datapath, "H77a_integral.fits")  #'W51_h77a_pyproc_integrated_supersampled.fits')
h77aname = os.path.join(datapath, "H77a_amplitude.fits")  #'W51_h77a_pyproc_integrated_supersampled.fits')
h77i = fits.getdata(h77iname) * ktojy77 / etamb_77
def compute_catalog(d, header):
    """
    Computes a catalog on a dendrogram.

    Parameters
    ----------
    d : astrodendro.dendrogram.Dendrogram
        Dendrogram on which to compute a catalog
    header : astropy.io.fits.header.Header
        Header corresponding exactly to `d.data`. 
        Used for unit and scaling information to calculate flux and 
        world coordinates.

    Returns
    -------
    catalog : astropy.table.table.Table
        Catalog describing the structures in dendrogram `d`
        using units provided in `header`.
    metadata : dict
        Explicitly lists unit properties used in `catalog`
        
    """

    # rough average of North and South telescopes: 
    # see Dame et al. 2001, p. 794. 
    # "The Northern telescope... has a beamwidth of 8'.4 +/- 0'.2.... 
    # The Southern telescope has nearly the same beamwidth to within 
    # the uncertainties: 8'.8 +/- 0'.2"
    beam_size = 8.5 * u.arcmin 
    frequency = 115.27 * u.GHz # http://www.cv.nrao.edu/php/splat/

    # Remember: by this point, the data ought to be in (v, b, l), with FITS header order opposite that
    if 'vel' not in header['ctype3'].lower():
        raise ValueError("CTYPE3 must be velocity - check that the data were permuted correctly")

    v_scale = header['cdelt3']
    v_unit = u.km / u.s
    l_scale = header['cdelt1']
    b_scale = header['cdelt2']

    metadata = {}
    metadata['data_unit'] = u.K
    metadata['spatial_scale'] = b_scale * u.deg
    metadata['velocity_scale'] = v_scale * v_unit
    metadata['wavelength'] = frequency # formerly: (c.c / frequency).to('mm') but now compute_flux can handle frequency in spectral equivalency
    metadata['beam_major'] = beam_size
    metadata['beam_minor'] = beam_size    
    metadata['vaxis'] = 0 # keep it this way if you think the (post-downsample/transposed) input data is (l, b, v)
    metadata['wcs'] = d.wcs

    catalog = astrodendro.ppv_catalog(d, metadata, verbose=True)

    if catalog['flux'].unit.is_equivalent('Jy'):
        # Workaround because flux is computed wrong (see https://github.com/dendrograms/astrodendro/issues/107)

        flux = u.Quantity(catalog['flux'])
        area_exact = u.Quantity(catalog['area_exact']) #.unit*catalog['area_exact'].data

        # average brightness temperature integrated over area_exact
        flux_kelvin = flux.to('K', equivalencies=u.brightness_temperature(area_exact, frequency))
        # flux integrated over area and velocity
        flux_kelvin_kms_sr = flux_kelvin * metadata['velocity_scale'] * area_exact.to(u.steradian)

        catalog['flux_true'] = flux_kelvin_kms_sr

        background_flux_array = np.zeros_like(catalog['flux_true'])
        # do a clipping -- 
        # this uses the approximation that any given structure's background is well-represented by its lowest-valued pixel, which can get messy sometimes.
        for i, row in enumerate(catalog):
            background_kelvins = d[i].vmin * u.K
            background_flux = background_kelvins * d[i].get_npix() * metadata['velocity_scale'] * metadata['spatial_scale']**2

            background_flux_array[i] = background_flux.to(u.K * u.km/u.s * u.steradian).value

        catalog['flux_clipped'] = catalog['flux_true'] - background_flux_array

    return catalog, metadata
                 'Dec': u.deg,
                }

        results = photometry(data, mywcs, regs, beam)

        for name in results:
            rslt_dict = {line+"_"+key: value
                         for key,value in results[name].items()}
            if name in all_results:
                all_results[name].update(rslt_dict)
            else:
                all_results[name] = rslt_dict

            restfrq = header['RESTFRQ'] * u.Hz
            tbmax = (results[name]['peak']*u.Jy).to(u.K,
                                                    u.brightness_temperature(results[name]['beam_area'],
                                                                             restfrq))
            all_results[name][line+'_peak_brightness'] = tbmax

            all_results[name][line+"_freq"] = restfrq

    # invert the table to make it parseable by astropy...
    # (this shouldn't be necessary....)
    results_inv = {'name':{}}
    columns = {'name':[]}
    colnames = {'name'} # set
    for k,v in all_results.items():
        results_inv['name'][k] = k
        columns['name'].append(k)
        for kk,vv in v.items():
            colnames.add(kk)
            if kk in results_inv:
Exemple #48
0
def test_surfacebrightness():
    sb = 50*u.MJy/u.sr
    k = sb.to(u.K, u.brightness_temperature(50*u.GHz))
    np.testing.assert_almost_equal(k.value, 0.650965, 5)
    assert k.unit.is_equivalent(u.K)
#ax3.set_ylabel("Number of sources")
#pl.legend(loc='best')
#fig2.savefig(paths.fpath('coreplots/mass_histograms.png'))
#peak_plot[0].set_visible(False)
#H,L,P = ax3.hist(cores_merge['peak_cont_mass'], bins=bins, color='b',
#                 facecolor='none', histtype='step', label='M($20$K)',
#                 linewidth=2, alpha=0.5)
#ax3.set_xlim(0,7)
#fig2.savefig(paths.fpath('coreplots/mass_histograms_low.png'))
#
#
#
#
# beam area is for the continuum data
beam_area = u.Quantity(np.array(dendro_merge['beam_area']), u.sr)
jy_to_k = (1*u.Jy).to(u.K, u.brightness_temperature(beam_area,
                                                    220*u.GHz)).mean()

m20kconv = float(dendro_merge.meta['keywords']['mass_conversion_factor']['value'].split()[1])
def m20ktickfunc(x):
    return ["{0:0.0f}".format(y*m20kconv) for y in x]

fig4 = pl.figure(4)
fig4.clf()
ax5 = fig4.gca()
#for species in np.unique(dendro_merge['PeakLineSpecies']):
#    if species != 'NONE':
#        mask = species == dendro_merge['PeakLineSpecies']
#        ax5.plot(dendro_merge['cont_flux0p4arcsec'][mask]-dendro_merge['cont_flux0p2arcsec'][mask],
#                 dendro_merge['peak_cont_flux'][mask], 's', label=species)
ax5.plot(dendro_merge['cont_flux0p4arcsec']-dendro_merge['cont_flux0p2arcsec'],
         dendro_merge['peak_cont_flux'], 'ks', alpha=0.75, label='')
import FITS_tools
import os
import aplpy
import numpy as np
from astropy import units as u
import pylab as pl


#lawfile = os.path.join(datapath,'GCCBand_Brick_zoom_crop.fits')
lawfile = os.path.join(datapath,'GCCBand_lb.2.fits')
lawdata = fits.getdata(lawfile).squeeze()
law_hdr = FITS_tools.strip_headers.flatten_header(fits.getheader(lawfile))

fwhm = np.sqrt(8*np.log(2))
beam = (2*np.pi*u.deg**2*(4.241274E-02)**2/fwhm**2)
kperjy = (1*u.Jy).to(u.K, equivalencies=u.brightness_temperature(beam,4.829*u.GHz))
lawdata = lawdata * kperjy.value

ccontfile = os.path.join(datapath,'LimaBean_H2CO11_cube_continuum.fits')
ccontdata = fits.getdata(ccontfile).squeeze()
#ccontdata -= np.nanmin(ccontdata) # HACK
ccont_hdr = fits.getheader(ccontfile)

brick_mask = fits.getdata(datapath+'brick_mask11.fits').astype('bool')

okimg = np.isfinite(ccontdata).astype('float')

resampled_law = FITS_tools.hcongrid.hcongrid(lawdata, law_hdr, ccont_hdr)

xok = (np.isfinite(ccontdata) * (ccontdata != 0)).max(axis=0)
yok = (np.isfinite(ccontdata) * (ccontdata != 0)).max(axis=1)
 def K2JyPixel(self):
     pixarea = (self._pixelsize * au.arcsec) ** 2
     equiv = au.brightness_temperature(pixarea, self._freq*au.MHz)
     return au.K.to(au.Jy, equivalencies=equiv)
             Column(data=([cubes[name].wcs.wcs.restfrq for name in cube_names]*u.Hz).to(u.GHz),
                    name='Frequency'),
             Column(data=[dv[name].to(u.km/u.s).value for name in cube_names]*u.km/u.s,
                    name='Channel Width'),
             Column(data=[errors[name].to(u.mJy).value for name in
                          cube_names]*u.mJy/u.beam, name='RMS'),
             Column(data=[beams[name].major.to(u.arcsec).value for name in
                          cube_names]*u.arcsec, name='BMAJ'),
             Column(data=[beams[name].minor.to(u.arcsec).value for name in
                          cube_names]*u.arcsec, name='BMIN'),
             Column(data=[beams[name].pa.to(u.deg).value for name in
                          cube_names]*u.deg, name='BPA'),

            ]
           )
tbl.add_column(Column(data=[(1*u.Jy).to(u.K, u.brightness_temperature(bm.sr,
                                                                      freq*u.GHz,)).value
                            for bm,freq in zip(beams.values(),
                                               tbl['Frequency'])
                           ],
                      name='Jy-Kelvin'))
tbl.add_column(Column(data=((tbl['RMS']*u.beam).to(u.Jy).value*tbl['Jy-Kelvin'])*u.K,
                      name='RMS$_K$'), index=4)

tbl.sort(['Frequency'])
latexdict['header_start'] = '\label{tab:cubes}'
latexdict['caption'] = 'Spectral Cubes'
latexdict['tablefoot'] = ('\par\nJy-Kelvin gives the conversion factor from Jy '
                          'to Kelvin given the synthesized beam size and '
                          'observation frequency.')
latexdict['col_align'] = 'l'*len(tbl.columns)
#latexdict['tabletype'] = 'longtable'
            centroid_par='shift',
            )
    myclass.__name__ = "ch3cn_absorption"
    
    return myclass

pyspeckit.spectrum.fitters.default_Registry.add_fitter('ch3cn_absorption',ch3cn_absorption_fitter(),5)


if __name__ == "__main__" and False:
    import paths
    cube = SpectralCube.read(paths.dpath('longbaseline/W51e2e_CH3CN_cutout.fits'))
    sp_ = cube[:,43,43]
    hdr = sp_.header
    hdr['BUNIT'] = 'K'
    sphdu = fits.PrimaryHDU(data=sp_.to(u.K, u.brightness_temperature(cube.beam,
                                                                      cube.wcs.wcs.restfrq*u.Hz)).value,
                            header=hdr)
    sp = pyspeckit.Spectrum.from_hdu(sphdu)
    sp.data -= np.percentile(sp.data, 25)
    sp.plotter()
    sp.specfit(fittype='ch3cn', guesses=[62, 2, 500, 1e16])

    # do it again, excluding k=0 and k=1
    sp2 = sp[:400]
    sp2.plotter()
    sp2.specfit(fittype='ch3cn', guesses=[62, 2, 500, 1e16])

    F = False
    T = True

    sp.specfit(fittype='ch3cn_spw', guesses=[62, 2,]+[100]*14 + [0],
"""
A 1 mJy source will have T_B = 811.6665408856167 K at 4.9 GHz
The upper size limit for a 10^4 K source is 0.030297250253506165 arcsec,or 0.7946490089788438 mpc = 163.9081238701842 AU
"""

import numpy as np
from astropy.io import fits
from astropy import units as u
import radio_beam
import paths
from common_constants import distance

header = fits.getheader(paths.dpath("W51C_ACarray_continuum_4096_both_uniform_contsplit.clean.image.fits"))
beam = radio_beam.Beam.from_fits_header(header)

mJytoK = (1*u.mJy).to(u.K, u.brightness_temperature(beam, 4.9*u.GHz))

print("A 1 mJy source will have T_B = {0} at 4.9 GHz".format(mJytoK))
sizelim = (((mJytoK/(1e4*u.K) * (beam.sr))/(2.*np.pi))**0.5).to(u.arcsec)
print("The upper size limit for a 10^4 K source is {0},"
      "or {1} = {2}".format(sizelim, (sizelim*distance).to(u.mpc,
                                                           u.dimensionless_angles()),
                            (sizelim*distance).to(u.au,
                                                  u.dimensionless_angles())
                           ))
    w = wcs.WCS(header).sub([wcs.WCSSUB_CELESTIAL])
    mask = noisereg.get_mask(header=w.to_header(), shape=im[0].data.squeeze().shape)
    noise_est[ep] = im[0].data.squeeze()[mask].std() * 1000
    peak[ep] = im[0].data.max()*1000
    

obstbl = Table([Column(data=[ep.split()[-1] for ep in beams], name='Epoch'),
                Column(data=[float(ep.split()[0]) for ep in beams]*u.GHz, name='Frequency'),
                Column(data=[bm.major.to(u.arcsec).value for bm in beams.values()]*u.arcsec, name='BMAJ'),
                Column(data=[bm.minor.to(u.arcsec).value for bm in beams.values()]*u.arcsec, name='BMIN'),
                Column(data=[bm.pa.to(u.deg).value for bm in beams.values()]*u.deg, name='BPA'),
                Column(data=[noise_est[ep] for ep in beams]*u.mJy/u.beam, name='Noise Estimate'),
                Column(data=[peak[ep]/noise_est[ep] for ep in beams], name='Dynamic Range'),
               ])
obstbl.add_column(Column(data=[(1*u.Jy).to(u.K,
                                           u.brightness_temperature(bm.sr, freq*u.GHz,)
                                          ).value
                               for bm,freq in zip(beams.values(),
                                                  obstbl['Frequency'])
                              ],
                         name='Jy-Kelvin'
                        )
                 )

obstbl.sort(['Frequency', 'Epoch'])
latexdict['header_start'] = '\label{tab:observations}'
latexdict['caption'] = 'Observations'
latexdict['tablefoot'] = ('\par\nJy-Kelvin gives the conversion factor from Jy '
                          'to Kelvin given the synthesized beam size and '
                          'observation frequency.')
#latexdict['col_align'] = 'lllrr'
        results_inv['name'][k] = k
        columns['name'].append(k)
        for kk,vv in v.items():
            if kk in results_inv:
                results_inv[kk][k] = vv
                columns[kk].append(vv)
            else:
                results_inv[kk] = {k:vv}
                columns[kk] = [vv]

    for c in columns:
        if c in units:
            columns[c] = u.Quantity(columns[c], units[c])

    tbl = Table([Column(data=columns[k],
                        name=k)
                 for k in ['name', 'RA', 'Dec', 'peak', 'sum', 'npix', 'beam_area',
                           'bgmad', 
                           'peak_90GHz', 'sum_90GHz', 'bgmad_90GHz',
                           'peak_100GHz', 'sum_100GHz', 'bgmad_100GHz',
                           'peak_mass_20K', 'peak_col_20K']])

    peak_brightness = (tbl['peak']*u.beam).to(u.K,
                                              u.brightness_temperature(tbl['beam_area'],
                                                                       masscalc.centerfreq))
    tbl.add_column(Column(data=peak_brightness, name='peak_K', unit=u.K))

    tbl.sort('peak_mass_20K')
    tbl.write(paths.tpath("continuum_photometry.ipac"), format='ascii.ipac',
              overwrite=True)
from astropy.io import fits
from astropy import units as u
import numpy as np
from paths import dpath

#f = fits.open('H2CO_11_speccube.fits')
f = fits.open(dpath('H2CO_11_speccube_contsub17_big_uniform.image.fits'))

beam = (np.pi*f[0].header['BMAJ']*f[0].header['BMAJ']*u.deg**2)
cont_offset = (2.7315*u.K).to(u.Jy,u.brightness_temperature(beam, 4.82966*u.GHz))

# try to fix NANs.... this definitely makes everything technically wrong, but more aesthetically useful
extra_cont_offset = 0.10

# 0.05 arbitrarily selected to get a decent match...
#cont = (f[0].data[0,100:300,:,:].sum(axis=0) + f[0].data[0,600:900,:,:].sum(axis=0)) / 500. + 0.05
cont = fits.getdata(dpath('H2CO_11_speccube_cont_16_18_big_uniform.image.fits')).squeeze() + cont_offset.value + extra_cont_offset

cspec = f[0].data[:70,:,:]
cspec[cspec > 0] = 0
spec = cspec + cont
# try to "subtract out" the negative continuum...
spec[:,cont<0] -= cont[cont<0]
cont[cont<0] = cont_offset.value + extra_cont_offset

# avoid huge NAN splotches
#spec[spec<0] = cont_offset.value

tau = -np.log((spec/cont))
tau[0,:,:] = cont # just so we have it... that first channel sucked anyway
dd = ds9.ds9()

cubes = {name: SpectralCube.read(dpath(fn)) for name,fn in cube_names.items()}

vcubes = {name: cube.with_spectral_unit(u.km/u.s, velocity_convention='radio')
          for name,cube in cubes.items()}

beams = {name: radio_beam.Beam.from_fits_header(cube.header)
         for name,cube in vcubes.items()}

for cube in vcubes.values():
    cube._unit = u.Jy

vkcubes = {name: cube.with_flux_unit(u.K,
                                     u.brightness_temperature(beams[name],
                                                              cube.wcs.wcs.restfrq*u.Hz))
          for name,cube in vcubes.items()}

for name,vc in vkcubes.items():
    vc._header['OBJECT'] = name
    vc.to_ds9(dd.id, newframe=True)

dd.set('tile yes')
dd.set('frame frameno 1')
dd.set('frame delete')
dd.set('scale limits -300 300')
dd.set('wcs fk5')
dd.set('lock frame wcs')
dd.set('lock slice wcs')
dd.set('lock scale yes')
dd.set('lock color yes')
#ln selfcal_allspw_selfcal_4ampphase_mfs_tclean_deeper_5mJy.image.pbcor.fits W51_te_continuum_best.fits
#ln selfcal_allspw_selfcal_4ampphase_mfs_tclean_deeper_5mJy.residual.fits W51_te_continuum_best_residual.fits
contfile = fits.open(paths.dpath('W51_te_continuum_best.fits'))
data = u.Quantity(contfile[0].data, unit=contfile[0].header['BUNIT'])
mywcs = wcs.WCS(contfile[0].header)
beam = radio_beam.Beam.from_fits_header(contfile[0].header)
pixel_scale = np.abs(mywcs.pixel_scale_matrix.diagonal().prod())**0.5 * u.deg
pixel_scale_as = pixel_scale.to(u.arcsec).value
ppbeam = (beam.sr/(pixel_scale**2)).decompose().value / u.beam

#pl.hist(data[np.isfinite(data)], bins=np.linspace(1e-4,0.1,100))

# over what threshold are we including flux when measuring total masses?
threshold = 10*u.mJy/u.beam
# threshold above which 20 K is very thick
thick_threshold = (20*u.K).to(u.mJy, u.brightness_temperature(beam, masscalc.centerfreq)) / u.beam
threshold_column = (threshold * u.beam/u.Jy * masscalc.col_conversion_factor(beam)).to(u.cm**-2)
threshold_column = masscalc.dust.colofsnu(nu=masscalc.centerfreq,
                                          snu=threshold*u.beam,
                                          beamomega=beam.sr).to(u.cm**-2,
                                                                u.dimensionless_angles())
threshold_density = (masscalc.mass_conversion_factor(20) * (threshold*u.beam).to(u.mJy).value /
                     (4/3.*np.pi) /
                     (beam.sr.value*masscalc.distance**2)**(1.5) /
                     (2.8*constants.m_p)).to(1/u.cm**3)
definitely_signal = data > threshold
definitely_thick_if_20K = data > thick_threshold
total_signal = data[definitely_signal].sum() / ppbeam
print("Total pixels > 10mJy/beam: {0} = {1}; r_eff = {2}"
      .format(definitely_signal.sum(), definitely_signal.sum()/ppbeam,
              ((definitely_signal.sum()*(pixel_scale*masscalc.distance)**2)**0.5).to(u.pc,