u.sr)
peak_line_freq = u.Quantity([dendro_merge['peak{0}freq'.format(pid)][ii]
                             if pid >= 0 else 1.0
                             for ii,pid in enumerate(peak_line_id)],
                            u.GHz)
peak_line_cont = u.Quantity([dendro_merge['continuum20pct{0}'.format(pid)][ii]
                             if pid >= 0 else 0.0
                             for ii,pid in enumerate(peak_line_id)],
                            u.Jy)
tbequiv = u.brightness_temperature(peak_line_beam_area, peak_line_freq)
peak_line_brightness = (peak_line_flux*u.Jy).to(u.K, tbequiv)
dendro_merge.add_column(Column(peak_line_brightness, name='PeakLineBrightness'))
continuum20pct_K = (peak_line_cont.to(u.K, tbequiv))
dendro_merge.add_column(Column(continuum20pct_K, name='PeakLineContinuumBG'))

tcm = Column([(masscalc.mass_conversion_factor(20).to(u.M_sun).value if
               np.isnan(row['PeakLineBrightness']) else
               masscalc.mass_conversion_factor(TK=row['PeakLineBrightness']).to(u.M_sun).value)
              * row['peak_cont_flux'] for row in dendro_merge],
             name='T_corrected_mass', unit=u.M_sun)
temperature_corrected_mass = tcm
dendro_merge.add_column(temperature_corrected_mass)

columns = ['SourceID',
           'peak_cont_mass',
           'T_corrected_mass',
           'PeakLineBrightness',
           'PeakLineFlux',
           'PeakLineSpecies',
           'peak_cont_col',
           'mean_velo',
        'mean_cont_flux', 'peak_cont_mass', 'peak_cont_col', 'beam_area']
radii = (0.2,0.4,0.6,0.8,1.0,1.5)*u.arcsec
columns = {k:[] for k in (keys)}

log.info("Doing photometry")
for ii, row in enumerate(ProgressBar(ppcat)):
    structure = dend[row['_idx']]
    assert structure.idx == row['_idx'] == ii
    dend_inds = structure.indices()
    columns['noise'].append(noise[dend_inds].mean())
    columns['is_leaf'].append(structure.is_leaf)
    peakflux = data[dend_inds].max()
    columns['peak_cont_flux'].append(peakflux)
    columns['min_cont_flux'].append(data[dend_inds].min())
    columns['mean_cont_flux'].append(data[dend_inds].mean())
    columns['peak_cont_mass'].append((masscalc.mass_conversion_factor()*peakflux).to(u.M_sun).value)
    columns['peak_cont_col'].append((masscalc.col_conversion_factor(beamomega=beam.sr.value)*peakflux).to(u.cm**-2).value)
    columns['beam_area'].append(beam.sr.value)
for k in columns:
    if k not in ppcat.keys():
        ppcat.add_column(Column(name=k, data=columns[k]))

cat_mask = (ppcat['is_leaf'] &
            (ppcat['peak_cont_flux']>8*ppcat['noise']) &
            (ppcat['mean_cont_flux']>5*ppcat['noise']) &
            (ppcat['min_cont_flux']>1*ppcat['noise']))
pruned_ppcat = ppcat[cat_mask]
mask = dend.index_map.copy()
log.info("Pruning mask image")
for ii in ProgressBar(list(range(len(ppcat)))):
    if ii not in pruned_ppcat['_idx']:
    print(rpath)
    reg = pyregion.open(paths.rpath(rpath))

    mask = reg.get_mask(fh[0])
    cutout = fh[0].data*mask

    limits = [0.005, 0.015]

    total_flux_perbeam = cutout[(cutout > limits[0]) & (cutout < limits[1])].sum()
    total_flux = total_flux_perbeam / ppbeam.value
    print("Total flux: {0}".format(total_flux))

    rad = reg[0].coord_list[-1]*u.deg
    rad_pc = (rad*masscalc.distance).to(u.pc, u.dimensionless_angles())

    print("Total mass(20K): {0}".format(total_flux*masscalc.mass_conversion_factor(TK=20)))
    print("Total mass(50K): {0}".format(total_flux*masscalc.mass_conversion_factor(TK=50)))
    print("Assumed radius: {0}".format(rad_pc))
    print("Total density(50K): {0}".format((total_flux*masscalc.mass_conversion_factor(TK=50)/(4/3*np.pi*rad_pc**3) / (2.8*u.Da)).to(u.cm**-3)))

Qlyc = 1e49 * 1/u.s
alpha_b = 3e-13*u.cm**3*u.s**-1
n_h = 5e5*u.cm**-3
rstrom = (3 * Qlyc /(4*np.pi*alpha_b*n_h**2))**(1/3.)
print("Stromgren radius: {0}".format(rstrom))

# sound speed at 8500K
cii = 7.1*u.km/u.s

def r_of_t(Rs, t, cii=cii, ):
    return Rs * (1+7/4. * cii/Rs * t)**(4/7.)
예제 #4
0
        'mean_cont_flux', 'peak_cont_mass', 'peak_cont_col', 'beam_area']
radii = (0.2,0.4,0.6,0.8,1.0,1.5)*u.arcsec
columns = {k:[] for k in (keys)}

log.info("Doing photometry")
for ii, row in enumerate(ProgressBar(ppcat)):
    structure = dend[row['_idx']]
    assert structure.idx == row['_idx'] == ii
    dend_inds = structure.indices()
    columns['noise'].append(noise[dend_inds].mean())
    columns['is_leaf'].append(structure.is_leaf)
    peakflux = data[dend_inds].max()
    columns['peak_cont_flux'].append(peakflux)
    columns['min_cont_flux'].append(data[dend_inds].min())
    columns['mean_cont_flux'].append(data[dend_inds].mean())
    columns['peak_cont_mass'].append((masscalc.mass_conversion_factor()*peakflux).to(u.M_sun).value)
    columns['peak_cont_col'].append((masscalc.col_conversion_factor(beamomega=beam.sr.value)*peakflux).to(u.cm**-2).value)
    columns['beam_area'].append(beam.sr.value)
for k in columns:
    if k not in ppcat.keys():
        ppcat.add_column(Column(name=k, data=columns[k]))

cat_mask = (ppcat['is_leaf'] &
            (ppcat['peak_cont_flux']>6.5*ppcat['noise']) &
            (ppcat['mean_cont_flux']>3*ppcat['noise']) &
            (ppcat['min_cont_flux']>1*ppcat['noise']))
log.info("Keeping {0} of {1} core candidates ({2}%)".format(cat_mask.sum(), len(cat_mask), cat_mask.sum()/len(cat_mask)*100))
pruned_ppcat = ppcat[cat_mask]
mask = dend.index_map.copy()
log.info("Pruning mask image")
for ii in ProgressBar(list(range(len(ppcat)))):
def make_rprof(regions, ploteach=False):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    size = u.Quantity([1.25, 1.25], u.arcsec)

    if ploteach:
        nplots = len(names)
        for ii in range(nplots):
            pl.figure(ii).clf()
            pl.figure(nplots + ii).clf()
            pl.figure(nplots * 2 + ii).clf()

        linestyles = {
            name: itertools.cycle(['-'] + ['--'] + [':'] + ['-.'])
            for name in names
        }

        for fn in ffiles:
            fh = fits.open(paths.dpath("12m/continuum/" + fn))
            mywcs = wcs.WCS(fh[0].header)

            if 'BMAJ' not in fh[0].header:
                #print("File {0} does not have BMAJ".format(fn))
                continue
            try:
                beam = radio_beam.Beam.from_fits_header(fh[0].header)
            except KeyError:
                #print("File {0} doesn't have beam info in the header".format(fn))
                continue

            pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
            ppbeam = (beam.sr /
                      (pixscale**2 * u.deg**2)).decompose().value / u.beam
            print("fn  {0} ppbeam={1:0.2f}".format(fn, ppbeam))

            for ii, (name, position) in enumerate(zip(names,
                                                      center_positions)):
                cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

                nr, bins, rprof = image_tools.radialprofile.azimuthalAverage(
                    cutout.data, binsize=1.0, return_nr=True)

                linestyle = next(linestyles[name])

                pl.figure(ii)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        rprof / ppbeam,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Azimuthally Averaged Flux (Jy)")
                pl.xlabel("Radius (arcsec)")

                cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

                pl.figure(nplots + ii)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        cumul_rprof,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Cumulative Flux (Jy)")
                pl.xlabel("Radius (arcsec)")
                if ii == 0:
                    ax = pl.gca()
                    ax2 = ax.twiny()
                    ax3 = ax.twinx()

                    def tick_function(old_x):
                        newx = (old_x * u.arcsec * masscalc.distance).to(
                            u.pc, u.dimensionless_angles()).value
                        return ["%.1f" % z for z in newx]

                    new_tick_locations = [0.005, 0.01, 0.015, 0.02, 0.025
                                          ] * u.pc
                    new_tick_locs_as = (new_tick_locations /
                                        masscalc.distance).to(
                                            u.arcsec, u.dimensionless_angles())
                    ax2.set_xlim(ax.get_xlim())
                    ax2.set_xticks(new_tick_locs_as.value)
                    ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
                    ax2.set_xlabel(r"Radius (pc)")
                    ax3.set_ylim(ax.get_ylim())
                    yticks_mass = np.arange(0, 6000, 1000)
                    yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                    ).value
                    ax3.set_yticks(yticks_Jy)
                    ax3.set_yticklabels(yticks_mass)
                    ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")

                pl.figure(nplots * 2 + ii)
                pl.title(name)
                pl.plot(((bins * pixscale * u.deg) * masscalc.distance).to(
                    u.pc, u.dimensionless_angles()),
                        cumul_rprof * masscalc.mass_conversion_factor(),
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")
                pl.xlabel("Radius (pc)")

        for ii in range(nplots):
            for xtra in (0, nplots * 2):
                ax = pl.figure(ii + xtra).gca()
                box = ax.get_position()
                ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

                # Put a legend to the right of the current axis
                ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    else:
        nplots = 0

    pl.matplotlib.rc_file('pubfiguresrc')
    pl.figure(nplots * 3 + 1).clf()
    pl.figure(nplots * 3 + 2).clf()
    pl.figure(nplots * 3 + 3).clf()
    fn = "selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits"
    fh = fits.open(paths.dpath("12m/continuum/" + fn))
    mywcs = wcs.WCS(fh[0].header)
    beam = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
    ppbeam = (beam.sr / (pixscale**2 * u.deg**2)).decompose().value / u.beam
    for ii, (name, position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        nr, bins, rprof = image_tools.radialprofile.azimuthalAverage(
            cutout.data, binsize=1.0, return_nr=True)

        pl.figure(nplots * 3 + 1)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., rprof / ppbeam, label=name)
        pl.ylabel("Azimuthally Averaged Flux (Jy)")
        pl.xlabel("Radius (arcsec)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

        pl.figure(nplots * 3 + 2)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., cumul_rprof, label=name)
        pl.ylabel("Cumulative Flux (Jy)")
        pl.xlabel("Radius (arcsec)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            ax3 = ax.twinx()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius (au)")
            ax3.set_ylim(ax.get_ylim())
            yticks_mass = np.arange(0, 6000, 1000)
            yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                TK=40).value
            ax3.set_yticks(yticks_Jy)
            ax3.set_yticklabels(yticks_mass)
            ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        pl.figure(nplots * 3 + 3)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(((bins * pixscale * u.deg) * masscalc.distance).to(
            u.pc, u.dimensionless_angles()),
                cumul_rprof * masscalc.mass_conversion_factor(TK=40),
                label=name)
        pl.ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
예제 #6
0
def jeans_maps(regions, size=u.Quantity([2.25, 2.25], u.arcsec), smooth=0):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    fn = "W51_te_continuum_best.fits"
    fh = fits.open(paths.dpath(fn))
    mywcs = wcs.WCS(fh[0].header)
    bm = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
    pixscale_cm = (pixscale * masscalc.distance).to(u.cm,
                                                    u.dimensionless_angles())
    ppbeam = (bm.sr / (pixscale**2)).decompose().value / u.beam

    mass_maps = {}

    for ii, (name, position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        source = 'e2' if name == 'e2e' else name

        temperature_map_fn = paths.dpath(
            '12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        #ch3ohN_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        #ch3ohT_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source)))
        #bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        #bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
        #ch3ohN = ch3ohN_hdul[0].data
        #ch3ohT = ch3ohT_hdul[0].data
        #dust_brightness,wts = reproject.reproject_interp(fits.open(paths.dpath('W51_te_continuum_best.fits')),
        #                                                 ch3ohN_hdul[0].header)

        temwcs = wcs.WCS(temperature_map_fh[0].header)
        temcutout = Cutout2D(temperature_map_fh[0].data,
                             position,
                             size,
                             wcs=temwcs)
        #maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)
        tem_pixscale = (temwcs.pixel_scale_matrix.diagonal()**
                        2).sum()**0.5 * u.deg
        ppbeam_tem = ppbeam * (pixscale / tem_pixscale)**2
        print("ppbeam, ppbeam_tem: ", ppbeam, ppbeam_tem)

        # geometric average FWHM
        bm_cm_fwhm = ((bm.major * bm.minor)**0.5 * masscalc.distance).to(
            u.cm, u.dimensionless_angles())
        bm_cm = bm_cm_fwhm / (8 * np.log(2))**0.5

        if smooth != 0:
            stddev_pix = ((smooth**2 / (8 * np.log(2)) - bm_cm**2)**0.5 /
                          pixscale_cm).decompose()
            print('stddev_pix: {0}'.format(stddev_pix.decompose()))
            kernel = Gaussian2DKernel(stddev_pix)

            kernel.normalize('peak')
            #smdata = convolve(cutout.data / ppbeam, kernel)
            mass_map = (cutout.data *
                        masscalc.mass_conversion_factor(TK=temcutout.data)).to(
                            u.M_sun)
            # mass_map is the sum over a gaussian 'aperture', but it has to account for the
            # beam to avoid double-counting
            # (this is better than using smooth temperature, since that leads to a huge overestimate)
            new_ppbeam = (2 * np.pi * smooth**2 / (8 * np.log(2)) /
                          pixscale_cm**2).decompose() / u.beam
            print('new_ppbeam: {0}, ppbeam: {1}, old_ppbeam: {2}'.format(
                new_ppbeam, ppbeam_tem,
                2 * np.pi * (bm_cm / pixscale_cm).decompose()**2))
            mass_map = convolve(mass_map, kernel) * u.M_sun * (
                ppbeam / new_ppbeam).decompose()

            # temperature should be the average temperature
            kernel.normalize('integral')
            temmap = convolve(temcutout.data, kernel)
            #mass_map = (smdata * masscalc.mass_conversion_factor(TK=temcutout.data)).to(u.M_sun)

            bm_cm = smooth / (8 * np.log(2))**0.5
        else:
            mass_map = (cutout.data *
                        masscalc.mass_conversion_factor(TK=temcutout.data)).to(
                            u.M_sun)
            temmap = temcutout.data

        # volume of a gaussian: sqrt(2 pi)^N r^N
        volume = (2 * np.pi)**(1.5) * bm_cm**3
        density_map = (mass_map / volume / (2.8 * u.Da)).to(u.cm**-3)
        print("Scale: {0}".format(bm_cm.to(u.au)))

        c_s_map = ((constants.k_B * temmap * u.K / (2.4 * u.Da))**0.5).to(
            u.km / u.s)
        MJ_map_ = (np.pi / 6. * c_s_map**3 /
                   (constants.G**1.5 * (2.8 * u.Da * density_map)**0.5)).to(
                       u.M_sun)

        LJ_map = (c_s_map / (constants.G**0.5 *
                             (2.8 * u.Da * density_map)**0.5)).to(u.au)
        MJ_map = (4 / 3. * np.pi * (LJ_map / 2.)**3 *
                  (2.8 * u.Da * density_map)).to(u.M_sun)
        np.testing.assert_almost_equal(MJ_map.value, MJ_map_.value)

        fig = pl.figure(ii)
        fig.clf()
        ax1 = pl.subplot(2, 3, 1)
        im1 = ax1.imshow(mass_map.value, cmap='gray', vmin=0, vmax=10)
        ax1.set_title("Measured mass")
        fig.colorbar(im1)

        ax2 = pl.subplot(2, 3, 2)
        im2 = ax2.imshow(MJ_map.value, cmap='gray', vmin=0, vmax=10)
        ax2.set_title("Jeans mass")
        fig.colorbar(im2)
        ax3 = pl.subplot(2, 3, 3)
        ax3.set_title("Black: unstable")
        # 1 -> white
        # 0 -> black
        # mass > M_J = unstable
        # M_J > mass = stable = 1 = white
        ax3.imshow(MJ_map > mass_map, cmap='gray', vmin=0, vmax=1)

        ax4 = pl.subplot(2, 3, 4)
        ax4.set_title("log Density")
        im4 = ax4.imshow(np.log10(density_map.value),
                         cmap='gray',
                         vmin=7,
                         vmax=9.5)
        fig.colorbar(im4)

        ax5 = pl.subplot(2, 3, 5)
        ax5.set_title("Temperature")
        im5 = ax5.imshow(temmap, cmap='gray', vmin=0, vmax=700)
        fig.colorbar(im5)

        ax6 = pl.subplot(2, 3, 6)
        im6 = ax6.imshow(LJ_map.value, cmap='gray', vmin=0, vmax=1e4)
        ax6.contourf(LJ_map.value,
                     levels=[
                         0, 2 * (bm_cm_fwhm.to(u.au)).value *
                         gaussian_fwhm_to_sphere_r
                     ],
                     colors=['r', 'r'])
        ax6.set_title("Jeans Length (AU)")
        fig.colorbar(im6)

        for jj in range(1, 7):
            pl.subplot(2, 3, jj).xaxis.set_major_formatter(pl.NullFormatter())
            pl.subplot(2, 3, jj).yaxis.set_major_formatter(pl.NullFormatter())

        if smooth == 0:
            fig.savefig(paths.fpath("jeans_maps_{0}.png".format(name)))
        else:
            fig.savefig(
                paths.fpath("jeans_maps_{0}_smooth{1}.png".format(
                    name, smooth)))

        mass_maps[name] = (mass_map, MJ_map)

    return mass_maps
def jeans_maps(regions, size=u.Quantity([2.25,2.25], u.arcsec), smooth=0):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list
                                             for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    fn = "W51_te_continuum_best.fits"
    fh = fits.open(paths.dpath(fn))
    mywcs = wcs.WCS(fh[0].header)
    bm = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
    pixscale_cm = (pixscale * masscalc.distance).to(u.cm, u.dimensionless_angles())
    ppbeam = (bm.sr/(pixscale**2)).decompose().value / u.beam

    mass_maps = {}

    for ii,(name,position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        source = 'e2' if name == 'e2e' else name

        temperature_map_fn = paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        #ch3ohN_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        #ch3ohT_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source)))
        #bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        #bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
        #ch3ohN = ch3ohN_hdul[0].data
        #ch3ohT = ch3ohT_hdul[0].data
        #dust_brightness,wts = reproject.reproject_interp(fits.open(paths.dpath('W51_te_continuum_best.fits')),
        #                                                 ch3ohN_hdul[0].header)

        temwcs = wcs.WCS(temperature_map_fh[0].header)
        temcutout = Cutout2D(temperature_map_fh[0].data, position, size, wcs=temwcs)
        #maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)
        tem_pixscale = (temwcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
        ppbeam_tem = ppbeam * (pixscale/tem_pixscale)**2
        print("ppbeam, ppbeam_tem: ",ppbeam,ppbeam_tem)

        # geometric average FWHM
        bm_cm_fwhm = ((bm.major * bm.minor)**0.5 * masscalc.distance).to(u.cm, u.dimensionless_angles())
        bm_cm = bm_cm_fwhm / (8*np.log(2))**0.5

        if smooth != 0:
            stddev_pix = ((smooth**2/(8*np.log(2)) - bm_cm**2)**0.5 / pixscale_cm).decompose()
            print('stddev_pix: {0}'.format(stddev_pix.decompose()))
            kernel = Gaussian2DKernel(stddev_pix)

            kernel.normalize('peak')
            #smdata = convolve(cutout.data / ppbeam, kernel)
            mass_map = (cutout.data * masscalc.mass_conversion_factor(TK=temcutout.data)).to(u.M_sun)
            # mass_map is the sum over a gaussian 'aperture', but it has to account for the
            # beam to avoid double-counting
            # (this is better than using smooth temperature, since that leads to a huge overestimate)
            new_ppbeam = (2*np.pi*smooth**2/(8*np.log(2)) / pixscale_cm**2).decompose() / u.beam
            print('new_ppbeam: {0}, ppbeam: {1}, old_ppbeam: {2}'.format(new_ppbeam, ppbeam_tem, 2*np.pi*(bm_cm/pixscale_cm).decompose()**2))
            mass_map = convolve(mass_map, kernel)*u.M_sun * (ppbeam/new_ppbeam).decompose()

            # temperature should be the average temperature
            kernel.normalize('integral')
            temmap = convolve(temcutout.data, kernel)
            #mass_map = (smdata * masscalc.mass_conversion_factor(TK=temcutout.data)).to(u.M_sun)

            bm_cm = smooth/(8*np.log(2))**0.5
        else:
            mass_map = (cutout.data * masscalc.mass_conversion_factor(TK=temcutout.data)).to(u.M_sun)
            temmap = temcutout.data

        # volume of a gaussian: sqrt(2 pi)^N r^N
        volume = (2*np.pi)**(1.5) * bm_cm**3
        density_map = (mass_map / volume / (2.8*u.Da)).to(u.cm**-3)
        print("Scale: {0}".format(bm_cm.to(u.au)))

        c_s_map = ((constants.k_B * temmap*u.K / (2.4*u.Da))**0.5).to(u.km/u.s)
        MJ_map_ = (np.pi/6. * c_s_map**3 / (constants.G**1.5 *
                                           (2.8*u.Da*density_map)**0.5)).to(u.M_sun)

        LJ_map = (c_s_map / (constants.G**0.5 *
                             (2.8*u.Da*density_map)**0.5)).to(u.au)
        MJ_map = (4/3. * np.pi * (LJ_map/2.)**3 * (2.8*u.Da*density_map)).to(u.M_sun)
        np.testing.assert_almost_equal(MJ_map.value, MJ_map_.value)

        fig = pl.figure(ii)
        fig.clf()
        ax1=pl.subplot(2,3,1)
        im1 = ax1.imshow(mass_map.value, cmap='gray', vmin=0, vmax=10)
        ax1.set_title("Measured mass")
        fig.colorbar(im1)

        ax2=pl.subplot(2,3,2)
        im2 = ax2.imshow(MJ_map.value, cmap='gray', vmin=0, vmax=10)
        ax2.set_title("Jeans mass")
        fig.colorbar(im2)
        ax3=pl.subplot(2,3,3)
        ax3.set_title("Black: unstable")
        # 1 -> white
        # 0 -> black
        # mass > M_J = unstable
        # M_J > mass = stable = 1 = white
        ax3.imshow(MJ_map > mass_map, cmap='gray', vmin=0, vmax=1)

        ax4=pl.subplot(2,3,4)
        ax4.set_title("log Density")
        im4 = ax4.imshow(np.log10(density_map.value), cmap='gray', vmin=7, vmax=9.5)
        fig.colorbar(im4)

        ax5=pl.subplot(2,3,5)
        ax5.set_title("Temperature")
        im5 = ax5.imshow(temmap, cmap='gray', vmin=0, vmax=700)
        fig.colorbar(im5)

        ax6=pl.subplot(2,3,6)
        im6 = ax6.imshow(LJ_map.value, cmap='gray', vmin=0, vmax=1e4)
        ax6.contourf(LJ_map.value, levels=[0, 2*(bm_cm_fwhm.to(u.au)).value * gaussian_fwhm_to_sphere_r], colors=['r', 'r'])
        ax6.set_title("Jeans Length (AU)")
        fig.colorbar(im6)

        for jj in range(1,7):
            pl.subplot(2,3,jj).xaxis.set_major_formatter(pl.NullFormatter())
            pl.subplot(2,3,jj).yaxis.set_major_formatter(pl.NullFormatter())


        if smooth == 0:
            fig.savefig(paths.fpath("jeans_maps_{0}.png".format(name)))
        else:
            fig.savefig(paths.fpath("jeans_maps_{0}_smooth{1}.png".format(name, smooth)))

                
        mass_maps[name] = (mass_map, MJ_map)

    return mass_maps
예제 #8
0
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_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
total_signal = data[definitely_signal].sum() / ppbeam
print("Total flux: {0}".format(total_signal))
print("Total mass(20K): {0}".format(
    total_signal * masscalc.mass_conversion_factor() * u.M_sun / u.Jy))
print("Threshold column (20K): {0:e}".format(threshold_column))
print("Threshold density (20K): {0:e}".format(threshold_density))
flux_of_filament = 132 * u.Jy / u.beam / ppbeam
print("Total *filament* mass(20K): {0}".format(
    flux_of_filament * masscalc.mass_conversion_factor() * u.M_sun / u.Jy))
print("Total *filament* mass(100K): {0}".format(
    flux_of_filament * masscalc.mass_conversion_factor(TK=100) * u.M_sun /

cores_merge.add_column(Column(brightest_noncld_lines, 'BrightestFittedLine'))
cores_merge.add_column(Column(brightest_noncld_qns, 'BrightestFittedQNs'))
cores_merge.add_column(Column(brightest_noncld_fluxes, 'BrightestFittedPeakPixFlux', unit=u.Jy))
cores_merge.add_column(Column(brightest_fitted_brightness, 'BrightestFittedPeakPixBrightness', unit=u.K))

# need to add back in continuum because we're concerned with the *absolute*
# brightness
# moved to other merge jtok_eq = u.brightness_temperature(cores_merge['beam_area'], 225*u.GHz)
# moved to other merge cont_brightness = (u.beam * cores_merge['sum']/cores_merge['npix']).to(u.K, jtok_eq)
cont_brightness = cores_merge['MeanContinuumBrightness']
contincluded_line_brightness = cores_merge['BrightestFittedPeakPixBrightness'] + cont_brightness
cores_merge.add_column(Column(contincluded_line_brightness, 'BrightestFittedPeakPixBrightnessWithcont', unit=u.K))

temperature_corrected_aperturemass = Column([(masscalc.mass_conversion_factor(20).value
                                          if np.isnan(row['BrightestFittedPeakPixBrightnessWithcont'])
                                          or (row['BrightestFittedPeakPixBrightnessWithcont'] < 20)
                                          else masscalc.mass_conversion_factor(row['BrightestFittedPeakPixBrightnessWithcont']).value)
                                         * row['sum']/ppbeam for row in cores_merge],
                                        name='T_corrected_aperturemass',
                                        unit=u.M_sun)
cores_merge.add_column(temperature_corrected_aperturemass)

apertures = ('0p2', '0p4', '0p6', '0p8', '1p0', '1p5')
for ap in apertures:
    tcm = Column([(masscalc.mass_conversion_factor(20).value
                   if np.isnan(row['BrightestFittedPeakPixBrightnessWithcont'])
                   or row['BrightestFittedPeakPixBrightnessWithcont'] < 20
                   else
                   masscalc.mass_conversion_factor(row['BrightestFittedPeakPixBrightnessWithcont']).value)
    Column(peak_line_flux, name='PeakLineFlux',
           unit=cores_merge['peak0'].unit))
cores_merge.add_column(Column(brightest_line_name, name='PeakLineSpecies'))

peak_line_brightness = (peak_line_flux * u.Jy).to(
    u.K, u.brightness_temperature(cores_merge['beam_area'], 220 * u.GHz))
cores_merge.add_column(Column(peak_line_brightness, name='PeakLineBrightness'))

jtok_eq = u.brightness_temperature(cores_merge['beam_area'], 225 * u.GHz)
cont_brightness = Column(
    (u.beam * cores_merge['sum'] / cores_merge['npix']).to(u.K, jtok_eq),
    name='MeanContinuumBrightness')
cores_merge.add_column(cont_brightness)

aperturemass20k = cores_merge[
    'sum'] / ppbeam * masscalc.mass_conversion_factor(20)
cores_merge.add_column(
    Column(aperturemass20k.value, name='ApertureMass20K', unit=u.M_sun))

temperature_corrected_mass = Column(
    [(masscalc.mass_conversion_factor(20).value if np.isnan(
        row['PeakLineBrightness']) else masscalc.mass_conversion_factor(
            row['PeakLineBrightness'])).value * row['peak']
     for row in cores_merge],
    name='T_corrected_peakmass',
    unit=u.M_sun)
cores_merge.add_column(temperature_corrected_mass)

cores_merge = cores_merge['SourceID', 'peak_mass', 'ApertureMass20K',
                          'T_corrected_peakmass', 'PeakLineBrightness',
                          'PeakLineFlux', 'PeakLineSpecies', 'peak_col',
예제 #11
0
radii = (0.2, 0.4, 0.6, 0.8, 1.0, 1.5) * u.arcsec
columns = {k: [] for k in (keys)}

log.info("Doing photometry")
for ii, row in enumerate(ProgressBar(ppcat)):
    structure = dend[row['_idx']]
    assert structure.idx == row['_idx'] == ii
    dend_inds = structure.indices()
    columns['noise'].append(noise[dend_inds].mean())
    columns['is_leaf'].append(structure.is_leaf)
    peakflux = data[dend_inds].max()
    columns['peak_cont_flux'].append(peakflux)
    columns['min_cont_flux'].append(data[dend_inds].min())
    columns['mean_cont_flux'].append(data[dend_inds].mean())
    columns['peak_cont_mass'].append(
        (masscalc.mass_conversion_factor() * peakflux).to(u.M_sun).value)
    columns['peak_cont_col'].append(
        (masscalc.col_conversion_factor(beamomega=beam.sr.value) *
         peakflux).to(u.cm**-2).value)
    columns['beam_area'].append(beam.sr.value)
for k in columns:
    if k not in ppcat.keys():
        ppcat.add_column(Column(name=k, data=columns[k]))

cat_mask = (ppcat['is_leaf'] & (ppcat['peak_cont_flux'] > 8 * ppcat['noise']) &
            (ppcat['mean_cont_flux'] > 5 * ppcat['noise']) &
            (ppcat['min_cont_flux'] > 1 * ppcat['noise']))
pruned_ppcat = ppcat[cat_mask]
mask = dend.index_map.copy()
log.info("Pruning mask image")
for ii in ProgressBar(list(range(len(ppcat)))):
예제 #12
0
ax1.vlines(3, 0, 25, linestyle='-', color='k', label='3')
ax1.vlines(5, 0, 25, linestyle='--', color='r', label='5')
ax1.vlines(7, 0, 25, linestyle=':', color='b', label='7')
ax1.set_xscale('log')
#ax1.set_xlim(l[:-1][h>0].min()/1.1, l[1:][h>0].max()*1.1)
ax1.set_ylim(0, 25)
ax1.set_xlabel("S/N")
ax1.set_ylabel("$N(cores)$")

fig1.savefig(paths.fpath('core_SN_histogram.pdf'), bbox_inches='tight')

fig1 = pl.figure(1)
fig1.clf()
ax1 = fig1.gca()

shift = np.log10(masscalc.mass_conversion_factor().value)
h, l, p = ax1.hist(core_phot_tbl['peak'] *
                   masscalc.mass_conversion_factor(TK=40, beta=1.75),
                   log=False,
                   bins=np.logspace(-4 + shift, -1 + shift, 50))
ax1.set_xscale('log')
ax1.set_xlim(l[:-1][h > 0].min() / 1.1, l[1:][h > 0].max() * 1.1)
#ax1.set_ylim(0.6, 15)
ax1.set_xlabel("$M(T=40$ K, $\\beta=1.75$) [$M_\odot$]")
ax1.set_ylabel("$N(cores)$")

fig1.savefig(paths.fpath('core_mass_histogram_40K.pdf'), bbox_inches='tight')

fig2 = pl.figure(2)
fig2.clf()
ax2 = fig2.gca()
def make_rprof(regions, ploteach=False):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list
                                             for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    size = u.Quantity([1.25,1.25], u.arcsec)

    if ploteach:
        nplots = len(names)
        for ii in range(nplots):
            pl.figure(ii).clf()
            pl.figure(nplots+ii).clf()
            pl.figure(nplots*2+ii).clf()

        linestyles = {name: itertools.cycle(['-'] + ['--'] + [':'] + ['-.'])
                      for name in names}

        for fn in ffiles:
            fh = fits.open(paths.dpath("12m/continuum/"+fn))
            mywcs = wcs.WCS(fh[0].header)

            if 'BMAJ' not in fh[0].header:
                #print("File {0} does not have BMAJ".format(fn))
                continue
            try:
                beam = radio_beam.Beam.from_fits_header(fh[0].header)
            except KeyError:
                #print("File {0} doesn't have beam info in the header".format(fn))
                continue

            pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
            ppbeam = (beam.sr/(pixscale**2*u.deg**2)).decompose().value / u.beam
            #print("fn  {0} ppbeam={1:0.2f}".format(fn, ppbeam))
            
            for ii,(name,position) in enumerate(zip(names, center_positions)):
                cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

                nr, bins, rprof = azimuthalAverage(cutout.data, binsize=1.0,
                                                   return_nr=True)

                linestyle = next(linestyles[name])

                pl.figure(ii)
                pl.title(name)
                pl.plot(bins*pixscale*3600., rprof/ppbeam,
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Azimuthally Averaged Flux (Jy)")
                pl.xlabel("Radius [arcsec]")

                cumul_rprof = np.nan_to_num(rprof*nr/ppbeam).cumsum()

                pl.figure(nplots+ii)
                pl.title(name)
                pl.plot(bins*pixscale*3600., cumul_rprof,
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Cumulative Flux (Jy)")
                pl.xlabel("Radius [arcsec]")
                if ii == 0:
                    ax = pl.gca()
                    ax2 = ax.twiny()
                    ax3 = ax.twinx()
                    def tick_function(old_x):
                        newx = (old_x*u.arcsec*masscalc.distance).to(u.pc, u.dimensionless_angles()).value
                        return ["%.1f" % z for z in newx]
                    new_tick_locations = [0.005,0.01,0.015,0.02,0.025]*u.pc
                    new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
                    ax2.set_xlim(ax.get_xlim())
                    ax2.set_xticks(new_tick_locs_as.value)
                    ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
                    ax2.set_xlabel(r"Radius (pc)")
                    ax3.set_ylim(ax.get_ylim())
                    yticks_mass = np.arange(0,6000,1000)
                    yticks_Jy = yticks_mass/masscalc.mass_conversion_factor().value
                    ax3.set_yticks(yticks_Jy)
                    ax3.set_yticklabels(yticks_mass)
                    ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")

                pl.figure(nplots*2+ii)
                pl.title(name)
                pl.plot(((bins*pixscale*u.deg)*masscalc.distance).to(u.pc,
                                                                     u.dimensionless_angles()),
                        cumul_rprof * masscalc.mass_conversion_factor(),
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")
                pl.xlabel("Radius (pc)")

        for ii in range(nplots):
            for xtra in (0,nplots*2):
                ax = pl.figure(ii+xtra).gca()
                box = ax.get_position()
                ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

                # Put a legend to the right of the current axis
                ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    else:
        nplots = 0

    pl.matplotlib.rc_file('pubfiguresrc')
    for jj in range(nplots*3+1, nplots*3+15+1):
        pl.figure(jj).clf()
    # $ find ~/work/w51/alma/FITS/ -samefile ~/work/w51/alma/FITS/W51_te_continuum_best.fits
    # /Users/adam/work/w51/alma/FITS//12m/continuum/selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits
    # /Users/adam/work/w51/alma/FITS//W51_te_continuum_best.fits
    fn = "selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits"
    fh = fits.open(paths.dpath("12m/continuum/"+fn))
    mywcs = wcs.WCS(fh[0].header)
    beam = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
    ppbeam = (beam.sr/(pixscale**2*u.deg**2)).decompose().value / u.beam
    for ii,(name,position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        nr, bins, rprof = azimuthalAverage(cutout.data, binsize=1.0,
                                           return_nr=True)

        pl.figure(nplots*3+1)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., rprof/ppbeam,
                label=name)
        pl.ylabel("Azimuthally Averaged Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        cumul_rprof = np.nan_to_num(rprof*nr/ppbeam).cumsum()

        pl.figure(nplots*3+2)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., cumul_rprof,
                label=name)
        pl.ylabel("Cumulative Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            ax3.set_ylim(ax.get_ylim())
            yticks_mass = np.arange(0,6000,1000)
            yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            ax3.set_yticks(yticks_Jy)
            ax3.set_yticklabels(yticks_mass)
            ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")



        radii = ((bins*pixscale*u.deg)*masscalc.distance).to(u.pc,
                                                             u.dimensionless_angles())
        mass_40k_profile = (cumul_rprof * masscalc.mass_conversion_factor(TK=40) / u.beam).to(u.M_sun)

        pl.figure(nplots*3+3)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(radii, mass_40k_profile, label=name)
        pl.ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))


        density_40k_profile = (mass_40k_profile / (4/3.*np.pi*radii**3) / (2.8*u.Da)).to(u.cm**-3)
        #print(density_40k_profile)
        #print(radii)

        pl.figure(nplots*3+4)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.semilogy(radii, density_40k_profile, label=name)
        pl.ylabel("Cumulative Density [n(H$_2$), $T=40$ K]")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        angular_radii = bins*pixscale*3600.
        azimuthal_average_flux = rprof/ppbeam
        azimuthal_average_mass_40K = azimuthal_average_flux * masscalc.mass_conversion_factor(TK=40) / u.beam
        bindiff_as = np.diff(bins).mean() * pixscale * 3600.
        bindiff_cm = bindiff_as * masscalc.distance / 206265.
        bins_cm = (angular_radii * masscalc.distance / 206265.).to(u.cm)
        sqdiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**2] +
                                   (bins_cm.to(u.cm)[1:]**2 -
                                    bins_cm.to(u.cm)[:-1]**2).value.tolist(),
                                   u.cm**2)
        cudiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**3] +
                                   (bins_cm.to(u.cm)[1:]**3 -
                                    bins_cm.to(u.cm)[:-1]**3).value.tolist(),
                                   u.cm**3)
        sqdiffbins_pix = [bins[0]**2] + (bins[1:]**2 - bins[:-1]**2).tolist()
        azimuthal_average_density_40K = (azimuthal_average_mass_40K * sqdiffbins_pix /
                                        (2.8*u.Da) /
                                        (4/3.*np.pi*(cudiffbins_cm))).to(u.cm**-3)

        pl.figure(nplots*3+5)
        pl.semilogy(angular_radii, azimuthal_average_density_40K, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat T=40K [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")



        c_s_40k = ((constants.k_B * 40*u.K / (2.4*u.Da))**0.5).to(u.km/u.s)
        azimuthal_average_MJ_40k = (np.pi/6. * c_s_40k**3 /
                                    (constants.G**1.5 *
                                     (2.8*u.Da*azimuthal_average_density_40K)**0.5)).to(u.M_sun)

        pl.figure(nplots*3+6)
        pl.semilogy(angular_radii, azimuthal_average_MJ_40k, label=name)
        pl.ylabel("Azimuthally Averaged $M_J$\nat $T=40$K")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        source = 'e2' if name == 'e2e' else name
        temperature_map_fn = paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        ch3ohN_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        ch3ohT_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source)))
        bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
        ch3ohN = ch3ohN_hdul[0].data
        ch3ohT = ch3ohT_hdul[0].data
        dust_brightness,wts = reproject.reproject_interp(fits.open(paths.dpath('W51_te_continuum_best.fits')),
                                                         ch3ohN_hdul[0].header)
        bm = radio_beam.Beam.from_fits_header(paths.dpath("W51_te_continuum_best.fits"))

        yy,xx = np.indices(ch3ohN.shape)
        if source == 'north':
            center = [84.,38.]
        else:
            center = [ch3ohN.shape[0]/2., ch3ohN.shape[1]/2.]
        yyc = (yy-center[0])
        xxc = (xx-center[1])
        rr = (yyc**2 + xxc**2)**0.5
        rr_as = (rr*bigpixscale).to(u.arcsec)
        theta = np.arctan2(yyc,xxc)*u.rad

        dust_column = dust_emissivity.dust.colofsnu(225*u.GHz, dust_brightness*u.Jy,
                                                    beamomega=bm,
                                                    temperature=ch3ohT*u.K)
        ch3oh_abundance = ch3ohN / dust_column.value
        mask = (ch3oh_abundance > 1e-10) & (ch3oh_abundance < 1e-5)
        if source == 'e2':
            mask = mask & (((theta > 15*u.deg) & (theta < 345*u.deg)) | (theta < -15*u.deg))
        mask = mask & np.isfinite(ch3oh_abundance)
        # exclude high-abundance, low-column regions: likely to be div-by-zero zones
        mask = mask & (~((ch3ohN < 1e18) & (ch3oh_abundance > 5e-6)))
        mask = mask & (~((dust_brightness<1e-2) & (ch3ohT > 500) & (ch3oh_abundance > 1e-6)))

        #mask = mask & (~((ch3ohT > 250) &
        #                 (ch3ohN < 1e18) &
        #                 (rr_as>1.5*u.arcsec))
        #               )# these are low-column,

        temwcs = wcs.WCS(temperature_map_fh[0].header)

        temcutout = Cutout2D(temperature_map_fh[0].data, position, size, wcs=temwcs)
        maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)

        tem_nr, tem_bins, tem_rprof = azimuthalAverage(temcutout.data,
                                                       weights=(maskcutout.data>0).astype('float'),
                                                       binsize=1.0,
                                                       return_nr=True,
                                                       interpnan=True,
                                                      )
        azimuthal_average_temperature = tem_rprof

        mass_map = (cutout.data * masscalc.mass_conversion_factor(TK=temcutout.data) ).to(u.M_sun)
        yy,xx = np.indices(cutout.data.shape)
        rr_map = ((xx-cutout.data.shape[1]/2.)**2 + (yy-cutout.data.shape[0]/2.)**2)
        mass_profile = (cumul_rprof *
                        masscalc.mass_conversion_factor(TK=tem_rprof) /
                        u.beam).to(u.M_sun)
        density_profile = (mass_profile / (4/3.*np.pi*radii**3) /
                           (2.8*u.Da)).to(u.cm**-3)

        azimuthal_average_mass = (azimuthal_average_flux *
                                  masscalc.mass_conversion_factor(TK=tem_rprof)
                                  / u.beam)

        # how accurate is this?  We are measuring mass in cylindrical annuli,
        # but we are assuming the underlying source structure is spherical
        # See Cores.ipynb (in notes/, not in this repo) for a detailed
        # analysis...
        azimuthal_average_density = (azimuthal_average_mass * sqdiffbins_pix /
                                     (2.8*u.Da) /
                                     (4/3.*np.pi*(cudiffbins_cm))).to(u.cm**-3)


        # this is not a good approximation for the spherial density profile...
        # see cores.ipynb.
        # Really should be this number +1 (so see the +1 below)
        # Also, negatived...
        density_alpha_ = 1-((np.log(density_profile[1:].value) -
                             np.log(density_profile[:-1].value)) /
                            (np.log(angular_radii[1:]) -
                             np.log(angular_radii[:-1]))
                           )
        # from cores.ipynb, this actually gets (close to) the right answer
        density_alpha = -((np.log(azimuthal_average_density[1:].value) -
                           np.log(azimuthal_average_density[:-1].value)) /
                          (np.log(angular_radii[1:]) -
                           np.log(angular_radii[:-1]))
                         )

        c_s = ((constants.k_B * tem_rprof*u.K / (2.4*u.Da))**0.5).to(u.km/u.s)
        azimuthal_average_MJ = (np.pi/6. * c_s**3 /
                                (constants.G**1.5 *
                                 (2.8*u.Da*azimuthal_average_density)**0.5)
                               ).to(u.M_sun)

        cumulative_mass_weighted_temperature = ((azimuthal_average_mass *
                                                 azimuthal_average_temperature).cumsum()
                                                / mass_profile)
        cumulative_c_s = ((constants.k_B *
                           cumulative_mass_weighted_temperature*u.K /
                           (2.4*u.Da))**0.5).to(u.km/u.s)
        cumulative_profile_MJ = (np.pi/6. * cumulative_c_s**3 /
                                (constants.G**1.5 *
                                 (2.8*u.Da*density_profile)**0.5)
                               ).to(u.M_sun)



        pl.figure(nplots*3+7)
        line, = pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        # WRONG pl.plot(angular_radii, azimuthal_average_mass, linestyle='--',
        # WRONG         alpha=0.75, color=line.get_color())
        #pl.plot(rr_map*pixscale*3600., mass_map, 'k.', alpha=0.25)
        pl.axis([0,1.2,0.0,5.0])
        pl.ylabel("Azimuthally Averaged $M_J$\nat $T(\\mathrm{CH}_3\\mathrm{OH})$ [$M_\\odot$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")


        pl.figure(nplots*3+8)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., mass_profile,
                label=name)
        pl.ylabel("Cumulative Mass at T(CH$_3$OH)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='upper left')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots*3+9)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., tem_rprof,
                label=name)
        pl.legend(loc='best')
        pl.ylabel("CH$_3$OH temperature")
        pl.xlabel("Radius [as]")


        # Jeans length (radius = length/2)
        azimuthal_average_RJ = (c_s**1 /
                                (constants.G**0.5 *
                                 (2.8*u.Da*azimuthal_average_density)**0.5)
                               ).to(u.au) / 2.

        pl.figure(nplots*3+10)
        pl.plot(angular_radii, azimuthal_average_RJ, label=name)
        pl.plot([0,(7000*u.au/masscalc.distance).to(u.arcsec,
                                                    u.dimensionless_angles()).value],
                [0,7000], 'k--', alpha=0.5)
        pl.ylabel("Azimuthally Averaged $R_J$\nat $T(\\mathrm{CH}_3\\mathrm{OH})$ [au]")
        pl.xlabel("Radius [arcsec]")
        pl.ylim(0,8000)
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")


        pl.figure(nplots*3+11)
        line, = pl.plot((angular_radii[1:]+angular_radii[:-1])/2., density_alpha)
        pl.plot((angular_radii[1:]+angular_radii[:-1])/2., density_alpha_, '--',
                color=line.get_color(), alpha=0.5)
        pl.xlabel("Radius [as]")
        pl.ylabel("Density Profile Exponent $\\kappa_\\rho$")


        pl.figure(nplots*3+12)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat T=T(CH$_3$OH) [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e6, 2e9)
            ax.set_xlim(0,1.2)
            ax2 = ax.twiny()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,7000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

            ax3 = ax.twinx()
            def tick_function(old_x):
                newx = ((constants.G * 2.8*u.Da * (old_x*u.cm**-3))**-0.5).to(u.kyr).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = [1.3,1.5,2,3,5]*u.kyr
            new_tick_locs_dens = ((new_tick_locations**2 * constants.G *
                                   2.8*u.Da)**-1).to(u.cm**-3)
            ax3.set_ylim(ax.get_ylim())
            ax3.set_yticks(new_tick_locs_dens.value)
            ax3.set_yticklabels(tick_function(new_tick_locs_dens.value))
            ax3.set_ylabel(r"$t_{ff}$ [kyr]")

            # start from 0.05 arcsec
            xlim = u.Quantity([0.05, ax.get_xlim()[1]], u.arcsec)
            xax_as = np.linspace(xlim[0], xlim[1], 100)
            xax_m = (xax_as *
                     masscalc.distance).to(u.m, u.dimensionless_angles())
            yax_s = ((ax.get_ylim() * u.cm**-3 * 2.8 * u.Da * constants.G)**-0.5).to(u.s)

            # plot 1 km/s line
            line_1 = (((xax_m / (7.5*u.km/u.s))**2 * constants.G *
                       2.8*u.Da)**-1).to(u.cm**-3)
            line_2 = (((xax_m / (5*u.km/u.s))**2 * constants.G *
                       2.8*u.Da)**-1).to(u.cm**-3)
            line_3 = (((xax_m / (10*u.km/u.s))**2 * constants.G *
                       2.8*u.Da)**-1).to(u.cm**-3)

            line, = pl.plot(xax_as.value, line_1.value, 'k:',
                            label='7.5 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.45, "7.5 km s$^{-1}$")
            line, = pl.plot(xax_as.value, line_2.value, 'k:',
                            label='5 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.6, "5 km s$^{-1}$")
            line, = pl.plot(xax_as.value, line_3.value, 'k-.',
                            label='10 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.7, "10 km s$^{-1}$")

            #ax.set_xlim(0,1.2)


            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        pl.figure(nplots*3+13)
        pl.plot(angular_radii, cumulative_profile_MJ, label=name)
        pl.ylabel("$M_J(r<R)$ at T=T(CH$_3$OH) [$M_\odot$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(0, 2)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        pl.figure(nplots*3+14)
        line, = pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        pl.plot(angular_radii, azimuthal_average_mass,
                linestyle='--', color=line.get_color())
        pl.ylabel("Mass at T=T(CH$_3$OH) [$M_\odot$]")
        pl.xlabel("Radius [arcsec]")

        handles, labels = ax.get_legend_handles_labels()
        if '$\\bar{M}$' not in labels:
            handles.append(pl.matplotlib.lines.Line2D([],[],
                                                      color='k', linestyle='--'))
            labels.append('$\\bar{M}$')
        if '$M_J$' not in labels:
            handles.append(pl.matplotlib.lines.Line2D([],[],
                                                      color='k', linestyle='-'))
            labels.append('$M_J$')


        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(0, 5)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
            ax2.set_position([box.x0, box.y0, box.width * 0.8, box.height])

            # Put a legend to the right of the current axis
            ax.legend(handles, labels, loc='center left', bbox_to_anchor=(1, 0.5))


        pl.figure(nplots*3+15)
        pl.subplot(2,2,1)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat T=T(CH$_3$OH) [cm$^{-3}$]")
        pl.subplot(2,2,3)
        pl.semilogy(angular_radii, density_profile, label=name)
        pl.ylabel("Cumulative Average Density\nat T=T(CH$_3$OH) [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        pl.subplot(2,2,2)
        pl.plot(azimuthal_average_density, density_profile, label=name)
        pl.plot(sorted(azimuthal_average_density.value),
                sorted(azimuthal_average_density.value), 'k--')
        pl.xlabel("Azimuthally Averaged Density\nat T=T(CH$_3$OH) [cm$^{-3}$]",
                  fontsize=12)
        pl.ylabel("Cumulative Average Density\nat T=T(CH$_3$OH) [cm$^{-3}$]",
                  fontsize=12)
        pl.subplot(2,2,4)
        pl.ylabel("Azimuthal / Cumulative", fontsize=12)
        pl.plot(angular_radii, azimuthal_average_density / density_profile,
                label=name)
        #pl.plot(angular_radii, [1.0] * len(angular_radii), 'k--')
        pl.xlabel("Radius [arcsec]")

    return locals()
예제 #14
0
           unit=u.K))

# need to add back in continuum because we're concerned with the *absolute*
# brightness
# moved to other merge jtok_eq = u.brightness_temperature(cores_merge['beam_area'], 225*u.GHz)
# moved to other merge cont_brightness = (u.beam * cores_merge['sum']/cores_merge['npix']).to(u.K, jtok_eq)
cont_brightness = cores_merge['MeanContinuumBrightness']
contincluded_line_brightness = cores_merge[
    'BrightestFittedPeakPixBrightness'] + cont_brightness
cores_merge.add_column(
    Column(contincluded_line_brightness,
           'BrightestFittedPeakPixBrightnessWithcont',
           unit=u.K))

temperature_corrected_aperturemass = Column(
    [(masscalc.mass_conversion_factor(20).value
      if np.isnan(row['BrightestFittedPeakPixBrightnessWithcont']) or
      (row['BrightestFittedPeakPixBrightnessWithcont'] < 20) else
      masscalc.mass_conversion_factor(
          row['BrightestFittedPeakPixBrightnessWithcont']).value) *
     row['sum'] / ppbeam for row in cores_merge],
    name='T_corrected_aperturemass',
    unit=u.M_sun)
cores_merge.add_column(temperature_corrected_aperturemass)

apertures = ('0p2', '0p4', '0p6', '0p8', '1p0', '1p5')
for ap in apertures:
    tcm = Column(
        [
            (masscalc.mass_conversion_factor(20).value
             if np.isnan(row['BrightestFittedPeakPixBrightnessWithcont'])
h,l,p = ax1.hist(peak_brightness, log=False, bins=np.logspace(-0.6, 3.0,30))
ax1.set_xscale('log')
ax1.set_xlim(l[:-1][h>0].min()/1.1, l[1:][h>0].max()*1.1)
#ax1.set_ylim(0.6, 15)
ax1.set_xlabel("$T_{B,3 mm}$ [K]")
ax1.set_ylabel("$N(cores)$")

fig1.savefig(paths.fpath('core_peak_brightness_histogram.png'))


fig1 = pl.figure(1)
fig1.clf()
ax1 = fig1.gca()

shift = np.log10(masscalc.mass_conversion_factor().value)
h,l,p = ax1.hist(core_phot_tbl['peak']*masscalc.mass_conversion_factor(40, beta=1.75),
                 log=False, bins=np.logspace(-4+shift,-1+shift,50))
ax1.set_xscale('log')
ax1.set_xlim(l[:-1][h>0].min()/1.1, l[1:][h>0].max()*1.1)
#ax1.set_ylim(0.6, 15)
ax1.set_xlabel("$M(T=40$ K, $\\beta=1.75$) [$M_\odot$]")
ax1.set_ylabel("$N(cores)$")

fig1.savefig(paths.fpath('core_mass_histogram_40K.png'))


fig2 = pl.figure(2)
fig2.clf()
ax2 = fig2.gca()
    mask = reg.get_mask(fh[0])
    cutout = fh[0].data * mask

    limits = [0.005, 0.015]

    total_flux_perbeam = cutout[(cutout > limits[0])
                                & (cutout < limits[1])].sum()
    total_flux = total_flux_perbeam / ppbeam.value
    print("Total flux: {0}".format(total_flux))

    rad = reg[0].coord_list[-1] * u.deg
    rad_pc = (rad * masscalc.distance).to(u.pc, u.dimensionless_angles())

    print("Total mass(20K): {0}".format(
        total_flux * masscalc.mass_conversion_factor(TK=20)))
    print("Total mass(50K): {0}".format(
        total_flux * masscalc.mass_conversion_factor(TK=50)))
    print("Assumed radius: {0}".format(rad_pc))
    print("Total density(50K): {0}".format(
        (total_flux * masscalc.mass_conversion_factor(TK=50) /
         (4 / 3 * np.pi * rad_pc**3) / (2.8 * u.Da)).to(u.cm**-3)))

Qlyc = 1e49 * 1 / u.s
alpha_b = 3e-13 * u.cm**3 * u.s**-1
n_h = 5e5 * u.cm**-3
rstrom = (3 * Qlyc / (4 * np.pi * alpha_b * n_h**2))**(1 / 3.)
print("Stromgren radius: {0}".format(rstrom))

# sound speed at 8500K
cii = 7.1 * u.km / u.s
def make_rprof(regions, ploteach=False):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    size = u.Quantity([1.25, 1.25], u.arcsec)

    if ploteach:
        nplots = len(names)
        for ii in range(nplots):
            pl.figure(ii, figsize=figsize).clf()
            pl.figure(nplots + ii, figsize=figsize).clf()
            pl.figure(nplots * 2 + ii, figsize=figsize).clf()

        linestyles = {
            name: itertools.cycle(['-'] + ['--'] + [':'] + ['-.'])
            for name in names
        }

        for fn in ffiles:
            fh = fits.open(paths.dpath("12m/continuum/" + fn))
            mywcs = wcs.WCS(fh[0].header)

            if 'BMAJ' not in fh[0].header:
                #print("File {0} does not have BMAJ".format(fn))
                continue
            try:
                beam = radio_beam.Beam.from_fits_header(fh[0].header)
            except KeyError:
                #print("File {0} doesn't have beam info in the header".format(fn))
                continue

            pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
            ppbeam = (beam.sr /
                      (pixscale**2 * u.deg**2)).decompose().value / u.beam
            #print("fn  {0} ppbeam={1:0.2f}".format(fn, ppbeam))

            for jj, (name, position) in enumerate(zip(names,
                                                      center_positions)):
                cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

                nr, bins, rprof = azimuthalAverage(cutout.data,
                                                   binsize=1.0,
                                                   return_nr=True)

                linestyle = next(linestyles[name])

                pl.figure(jj, figsize=figsize)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        rprof / ppbeam,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Azimuthally Averaged Flux (Jy)")
                pl.xlabel("Radius [arcsec]")

                cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

                pl.figure(nplots + jj, figsize=figsize)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        cumul_rprof,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                if jj == 0:
                    pl.fill_between([0, beam.major.to(u.arcsec).value],
                                    [100, 100], [0, 0],
                                    zorder=-5,
                                    alpha=0.1,
                                    color='k')
                pl.ylabel("Cumulative Flux (Jy)")
                pl.xlabel("Radius [arcsec]")
                if jj == 0:
                    ax = pl.gca()
                    ax2 = ax.twiny()
                    ax3 = ax.twinx()

                    def tick_function(old_x):
                        newx = (old_x * u.arcsec * masscalc.distance).to(
                            u.pc, u.dimensionless_angles()).value
                        return ["%.1f" % z for z in newx]

                    new_tick_locations = [0.005, 0.01, 0.015, 0.02, 0.025
                                          ] * u.pc
                    new_tick_locs_as = (new_tick_locations /
                                        masscalc.distance).to(
                                            u.arcsec, u.dimensionless_angles())
                    ax2.set_xlim(ax.get_xlim())
                    ax2.set_xticks(new_tick_locs_as.value)
                    ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
                    ax2.set_xlabel(r"Radius (pc)")
                    ax3.set_ylim(ax.get_ylim())
                    yticks_mass = np.arange(0, 6000, 1000)
                    yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                    ).value
                    ax3.set_yticks(yticks_Jy)
                    ax3.set_yticklabels(yticks_mass)
                    ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")

                pl.figure(nplots * 2 + jj, figsize=figsize)
                pl.title(name)
                pl.plot(((bins * pixscale * u.deg) * masscalc.distance).to(
                    u.pc, u.dimensionless_angles()),
                        cumul_rprof * masscalc.mass_conversion_factor(),
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                if jj == 0:
                    pl.fill_between([0, beam.major.to(u.arcsec).value],
                                    [100, 100], [0, 0],
                                    zorder=-5,
                                    alpha=0.1,
                                    color='k')
                pl.ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")
                pl.xlabel("Radius (pc)")

        for ii in range(nplots):
            for xtra in (0, nplots * 2):
                ax = pl.figure(ii + xtra, figsize=figsize).gca()
                box = ax.get_position()
                ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

                # Put a legend to the right of the current axis
                ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    else:
        nplots = 0

    for jj in range(nplots * 3 + 1, nplots * 3 + 15 + 1):
        pl.figure(jj, figsize=figsize).clf()
    # $ find ~/work/w51/alma/FITS/ -samefile ~/work/w51/alma/FITS/W51_te_continuum_best.fits
    # /Users/adam/work/w51/alma/FITS//12m/continuum/selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits
    # /Users/adam/work/w51/alma/FITS//W51_te_continuum_best.fits
    fn = "selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits"
    fh = fits.open(paths.dpath("12m/continuum/" + fn))
    mywcs = wcs.WCS(fh[0].header)
    beam = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
    ppbeam = (beam.sr / (pixscale**2 * u.deg**2)).decompose().value / u.beam
    for ii, (name, position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        nr, bins, rprof = azimuthalAverage(cutout.data,
                                           binsize=1.0,
                                           return_nr=True)

        pl.figure(nplots * 3 + 1, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., rprof / ppbeam, label=name)
        pl.ylabel("Azimuthally Averaged Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

        pl.figure(nplots * 3 + 2, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., cumul_rprof, label=name)
        pl.ylabel("Cumulative Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            ax3 = ax.twinx()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            ax3.set_ylim(ax.get_ylim())
            yticks_mass = np.arange(0, 6000, 1000)
            yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                TK=40).value
            ax3.set_yticks(yticks_Jy)
            ax3.set_yticklabels(yticks_mass)
            ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        radii = ((bins * pixscale * u.deg) * masscalc.distance).to(
            u.pc, u.dimensionless_angles())
        mass_40k_profile = (cumul_rprof *
                            masscalc.mass_conversion_factor(TK=40) /
                            u.beam).to(u.M_sun)

        pl.figure(nplots * 3 + 3, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(radii, mass_40k_profile, label=name)
        pl.ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        density_40k_profile = (mass_40k_profile / (4 / 3. * np.pi * radii**3) /
                               (2.8 * u.Da)).to(u.cm**-3)
        #print(density_40k_profile)
        #print(radii)

        pl.figure(nplots * 3 + 4, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.semilogy(radii, density_40k_profile, label=name)
        pl.ylabel("Cumulative Density [n(H$_2$), $T=40$ K]")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        angular_radii = bins * pixscale * 3600.
        azimuthal_average_flux = rprof / ppbeam
        azimuthal_average_mass_40K = azimuthal_average_flux * masscalc.mass_conversion_factor(
            TK=40) / u.beam
        bindiff_as = np.diff(bins).mean() * pixscale * 3600.
        bindiff_cm = bindiff_as * masscalc.distance / 206265.
        bins_cm = (angular_radii * masscalc.distance / 206265.).to(u.cm)
        sqdiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**2] +
                                   (bins_cm.to(u.cm)[1:]**2 -
                                    bins_cm.to(u.cm)[:-1]**2).value.tolist(),
                                   u.cm**2)
        cudiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**3] +
                                   (bins_cm.to(u.cm)[1:]**3 -
                                    bins_cm.to(u.cm)[:-1]**3).value.tolist(),
                                   u.cm**3)
        sqdiffbins_pix = [bins[0]**2] + (bins[1:]**2 - bins[:-1]**2).tolist()
        azimuthal_average_density_40K = (azimuthal_average_mass_40K *
                                         sqdiffbins_pix / (2.8 * u.Da) /
                                         (4 / 3. * np.pi *
                                          (cudiffbins_cm))).to(u.cm**-3)

        pl.figure(nplots * 3 + 5, figsize=figsize)
        pl.semilogy(angular_radii, azimuthal_average_density_40K, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat 40K [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        c_s_40k = ((constants.k_B * 40 * u.K / (2.4 * u.Da))**0.5).to(u.km /
                                                                      u.s)
        azimuthal_average_MJ_40k = (
            np.pi / 6. * c_s_40k**3 /
            (constants.G**1.5 *
             (2.8 * u.Da * azimuthal_average_density_40K)**0.5)).to(u.M_sun)

        pl.figure(nplots * 3 + 6, figsize=figsize)
        pl.semilogy(angular_radii, azimuthal_average_MJ_40k, label=name)
        pl.ylabel("Azimuthally Averaged $M_J$\nat $T=40$K")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        source = 'e2' if name == 'e2e' else name
        temperature_map_fn = paths.dpath(
            '12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        ch3ohN_hdul = fits.open(
            paths.dpath(
                '12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        ch3ohT_hdul = fits.open(
            paths.dpath(
                '12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(
                    source)))
        bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**
                       2).sum()**0.5 * u.deg
        ch3ohN = ch3ohN_hdul[0].data
        ch3ohT = ch3ohT_hdul[0].data
        dust_brightness, wts = reproject.reproject_interp(
            fits.open(paths.dpath('W51_te_continuum_best.fits')),
            ch3ohN_hdul[0].header)
        contbm = radio_beam.Beam.from_fits_header(
            paths.dpath("W51_te_continuum_best.fits"))

        yy, xx = np.indices(ch3ohN.shape)
        if source == 'north':
            center = [84., 38.]
        else:
            center = [ch3ohN.shape[0] / 2., ch3ohN.shape[1] / 2.]
        yyc = (yy - center[0])
        xxc = (xx - center[1])
        rr = (yyc**2 + xxc**2)**0.5
        rr_as = (rr * bigpixscale).to(u.arcsec)
        theta = np.arctan2(yyc, xxc) * u.rad

        dust_column = dust_emissivity.dust.colofsnu(
            225 * u.GHz,
            dust_brightness * u.Jy / contbm,
            #beamomega=contbm,
            temperature=ch3ohT * u.K)
        ch3oh_abundance = ch3ohN / dust_column.value
        mask = (ch3oh_abundance > 1e-10) & (ch3oh_abundance < 1e-5)
        if source == 'e2':
            mask = mask & (((theta > 15 * u.deg) & (theta < 345 * u.deg)) |
                           (theta < -15 * u.deg))
        mask = mask & np.isfinite(ch3oh_abundance)
        # exclude high-abundance, low-column regions: likely to be div-by-zero zones
        mask = mask & (~((ch3ohN < 1e18) & (ch3oh_abundance > 5e-6)))
        mask = mask & (~((dust_brightness < 1e-2) & (ch3ohT > 500) &
                         (ch3oh_abundance > 1e-6)))

        #mask = mask & (~((ch3ohT > 250) &
        #                 (ch3ohN < 1e18) &
        #                 (rr_as>1.5*u.arcsec))
        #               )# these are low-column,

        temwcs = wcs.WCS(temperature_map_fh[0].header)

        temcutout = Cutout2D(temperature_map_fh[0].data,
                             position,
                             size,
                             wcs=temwcs)
        maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)

        tem_nr, tem_bins, tem_rprof = azimuthalAverage(
            temcutout.data,
            weights=(maskcutout.data > 0).astype('float'),
            binsize=1.0,
            return_nr=True,
            interpnan=True,
        )
        azimuthal_average_temperature = tem_rprof

        mass_map = (cutout.data *
                    masscalc.mass_conversion_factor(TK=temcutout.data)).to(
                        u.M_sun)
        yy, xx = np.indices(cutout.data.shape)
        rr_map = ((xx - cutout.data.shape[1] / 2.)**2 +
                  (yy - cutout.data.shape[0] / 2.)**2)
        mass_profile = (cumul_rprof *
                        masscalc.mass_conversion_factor(TK=tem_rprof) /
                        u.beam).to(u.M_sun)
        density_profile = (mass_profile / (4 / 3. * np.pi * radii**3) /
                           (2.8 * u.Da)).to(u.cm**-3)

        azimuthal_average_mass = (
            azimuthal_average_flux *
            masscalc.mass_conversion_factor(TK=tem_rprof) / u.beam)

        # how accurate is this?  We are measuring mass in cylindrical annuli,
        # but we are assuming the underlying source structure is spherical
        # See Cores.ipynb (in notes/, not in this repo) for a detailed
        # analysis...
        azimuthal_average_density = (azimuthal_average_mass * sqdiffbins_pix /
                                     (2.8 * u.Da) / (4 / 3. * np.pi *
                                                     (cudiffbins_cm))).to(
                                                         u.cm**-3)

        # this is not a good approximation for the spherial density profile...
        # see cores.ipynb.
        # Really should be this number +1 (so see the +1 below)
        # Also, negatived...
        density_alpha_ = 1 - (
            (np.log(density_profile[1:].value) -
             np.log(density_profile[:-1].value)) /
            (np.log(angular_radii[1:]) - np.log(angular_radii[:-1])))
        # from cores.ipynb, this actually gets (close to) the right answer
        density_alpha = -(
            (np.log(azimuthal_average_density[1:].value) -
             np.log(azimuthal_average_density[:-1].value)) /
            (np.log(angular_radii[1:]) - np.log(angular_radii[:-1])))

        c_s = ((constants.k_B * tem_rprof * u.K / (2.4 * u.Da))**0.5).to(u.km /
                                                                         u.s)
        azimuthal_average_MJ = (
            np.pi / 6. * c_s**3 /
            (constants.G**1.5 *
             (2.8 * u.Da * azimuthal_average_density)**0.5)).to(u.M_sun)

        cumulative_mass_weighted_temperature = (
            (azimuthal_average_mass * azimuthal_average_temperature).cumsum() /
            mass_profile)
        cumulative_c_s = ((constants.k_B *
                           cumulative_mass_weighted_temperature * u.K /
                           (2.4 * u.Da))**0.5).to(u.km / u.s)
        cumulative_profile_MJ = (np.pi / 6. * cumulative_c_s**3 /
                                 (constants.G**1.5 *
                                  (2.8 * u.Da * density_profile)**0.5)).to(
                                      u.M_sun)

        pl.figure(nplots * 3 + 7, figsize=figsize)
        line, = pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        # WRONG pl.plot(angular_radii, azimuthal_average_mass, linestyle='--',
        # WRONG         alpha=0.75, color=line.get_color())
        #pl.plot(rr_map*pixscale*3600., mass_map, 'k.', alpha=0.25)
        pl.axis([0, 1.2, 0.0, 5.0])
        pl.ylabel(
            "Azimuthally Averaged $M_J$\nat $T(\\mathrm{CH}_3\\mathrm{OH})$ [$M_\\odot$]"
        )
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots * 3 + 8, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., mass_profile, label=name)
        if ii == 0:
            pl.fill_between([0, beam.major.to(u.arcsec).value], [100, 100],
                            [0, 0],
                            zorder=-5,
                            alpha=0.1,
                            color='k')
        pl.ylabel("Cumulative Mass at T(CH$_3$OH) [M$_\\odot$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='upper left')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots * 3 + 9, figsize=figsize)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., tem_rprof, label=name)
        pl.legend(loc='best')
        pl.ylabel("CH$_3$OH temperature")
        pl.xlabel("Radius [as]")

        # Jeans length (radius = length/2)
        azimuthal_average_RJ = (
            c_s**1 /
            (constants.G**0.5 *
             (2.8 * u.Da * azimuthal_average_density)**0.5)).to(u.au) / 2.

        pl.figure(nplots * 3 + 10, figsize=figsize)
        pl.plot(angular_radii, azimuthal_average_RJ, label=name)
        pl.plot([
            0, (7000 * u.au / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles()).value
        ], [0, 7000],
                'k--',
                alpha=0.5)
        pl.plot([
            beam.major.to(u.arcsec).value,
            (7000 * u.au / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles()).value
        ], [1000, 1000],
                'k:',
                alpha=0.5)
        if ii == 0:
            pl.fill_between([0, beam.major.to(u.arcsec).value], [8000, 8000],
                            zorder=-5,
                            alpha=0.1,
                            color='k')
        pl.ylabel(
            "Azimuthally Averaged $R_\\mathrm{J}$\nat $T(\\mathrm{CH}_3\\mathrm{OH})$ [au]"
        )
        pl.xlabel("Radius [arcsec]")
        pl.ylim(0, 8000)
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots * 3 + 11, figsize=figsize)
        line, = pl.plot((angular_radii[1:] + angular_radii[:-1]) / 2.,
                        density_alpha)
        pl.plot((angular_radii[1:] + angular_radii[:-1]) / 2.,
                density_alpha_,
                '--',
                color=line.get_color(),
                alpha=0.5)
        pl.xlabel("Radius [as]")
        pl.ylabel("Density Profile Exponent $\\kappa_\\rho$")

        pl.figure(nplots * 3 + 12, figsize=figsize)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat T(CH$_3$OH) [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e6, 2e9)
            ax.set_xlim(0, 1.2)
            ax2 = ax.twiny()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 7000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

            ax3 = ax.twinx()

            def tick_function(old_x):
                newx = ((constants.G * 2.8 * u.Da *
                         (old_x * u.cm**-3))**-0.5).to(u.kyr).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = [1.3, 1.5, 2, 3, 5] * u.kyr
            new_tick_locs_dens = ((new_tick_locations**2 * constants.G * 2.8 *
                                   u.Da)**-1).to(u.cm**-3)
            ax3.set_ylim(ax.get_ylim())
            ax3.set_yticks(new_tick_locs_dens.value)
            ax3.set_yticklabels(tick_function(new_tick_locs_dens.value))
            ax3.set_ylabel(r"$t_{ff}$ [kyr]")

            # start from 0.05 arcsec
            xlim = u.Quantity([0.05, ax.get_xlim()[1]], u.arcsec)
            xax_as = np.linspace(xlim[0], xlim[1], 100)
            xax_m = (xax_as * masscalc.distance).to(u.m,
                                                    u.dimensionless_angles())
            yax_s = ((ax.get_ylim() * u.cm**-3 * 2.8 * u.Da *
                      constants.G)**-0.5).to(u.s)

            # plot 1 km/s line
            line_1 = (((xax_m / (7.5 * u.km / u.s))**2 * constants.G * 2.8 *
                       u.Da)**-1).to(u.cm**-3)
            line_2 = (((xax_m / (5 * u.km / u.s))**2 * constants.G * 2.8 *
                       u.Da)**-1).to(u.cm**-3)
            line_3 = (((xax_m / (10 * u.km / u.s))**2 * constants.G * 2.8 *
                       u.Da)**-1).to(u.cm**-3)

            line, = pl.plot(xax_as.value,
                            line_1.value,
                            'k:',
                            label='7.5 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.45, "7.5 km s$^{-1}$")
            line, = pl.plot(xax_as.value,
                            line_2.value,
                            'k:',
                            label='5 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.6, "5 km s$^{-1}$")
            line, = pl.plot(xax_as.value,
                            line_3.value,
                            'k-.',
                            label='10 km s$^{-1}$',
                            zorder=-10)
            labelLine(line, 0.7, "10 km s$^{-1}$")

            #ax.set_xlim(0,1.2)

            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        pl.figure(nplots * 3 + 13, figsize=figsize)
        pl.plot(angular_radii, cumulative_profile_MJ, label=name)
        pl.ylabel("$M_J(r<R)$ at T(CH$_3$OH) [$M_\odot$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(0, 2)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        pl.figure(nplots * 3 + 14)
        line, = pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        pl.plot(angular_radii,
                azimuthal_average_mass,
                linestyle='--',
                color=line.get_color())
        if ii == 0:
            pl.fill_between([0, beam.major.to(u.arcsec).value], [100, 100],
                            [0, 0],
                            zorder=-5,
                            alpha=0.1,
                            color='k')
        pl.ylabel("Mass at T(CH$_3$OH) [$M_\odot$]")
        pl.xlabel("Radius [arcsec]")

        handles, labels = ax.get_legend_handles_labels()
        if '$\\bar{M}$' not in labels:
            handles.append(
                pl.matplotlib.lines.Line2D([], [], color='k', linestyle='--'))
            labels.append('$\\bar{M}$')
        if '$M_J$' not in labels:
            handles.append(
                pl.matplotlib.lines.Line2D([], [], color='k', linestyle='-'))
            labels.append('$M_J$')

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(0, 5)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%i" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 1.0, box.height])
            ax2.set_position([box.x0, box.y0, box.width * 1.0, box.height])

            # Put a legend to the right of the current axis
            ax.legend(handles,
                      labels,
                      loc='center left',
                      bbox_to_anchor=(1, 0.5))

        pl.figure(nplots * 3 + 15, figsize=figsize)
        pl.subplot(2, 2, 1)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density\nat T(CH$_3$OH) [cm$^{-3}$]")
        pl.subplot(2, 2, 3)
        pl.semilogy(angular_radii, density_profile, label=name)
        pl.ylabel("Cumulative Average Density\nat T(CH$_3$OH) [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        pl.subplot(2, 2, 2)
        pl.plot(azimuthal_average_density, density_profile, label=name)
        pl.plot(sorted(azimuthal_average_density.value),
                sorted(azimuthal_average_density.value), 'k--')
        pl.xlabel("Azimuthally Averaged Density\nat T(CH$_3$OH) [cm$^{-3}$]")
        pl.ylabel("Cumulative Average Density\nat T(CH$_3$OH) [cm$^{-3}$]")
        pl.subplot(2, 2, 4)
        pl.ylabel("Azimuthal / Cumulative")
        pl.plot(angular_radii,
                azimuthal_average_density / density_profile,
                label=name)
        #pl.plot(angular_radii, [1.0] * len(angular_radii), 'k--')
        pl.xlabel("Radius [arcsec]")

    return locals()
def make_rprof(regions, ploteach=False):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list
                                             for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    size = u.Quantity([1.25,1.25], u.arcsec)

    if ploteach:
        nplots = len(names)
        for ii in range(nplots):
            pl.figure(ii).clf()
            pl.figure(nplots+ii).clf()
            pl.figure(nplots*2+ii).clf()

        linestyles = {name: itertools.cycle(['-'] + ['--'] + [':'] + ['-.'])
                      for name in names}

        for fn in ffiles:
            fh = fits.open(paths.dpath("12m/continuum/"+fn))
            mywcs = wcs.WCS(fh[0].header)

            if 'BMAJ' not in fh[0].header:
                #print("File {0} does not have BMAJ".format(fn))
                continue
            try:
                beam = radio_beam.Beam.from_fits_header(fh[0].header)
            except KeyError:
                #print("File {0} doesn't have beam info in the header".format(fn))
                continue

            pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
            ppbeam = (beam.sr/(pixscale**2*u.deg**2)).decompose().value / u.beam
            #print("fn  {0} ppbeam={1:0.2f}".format(fn, ppbeam))
            
            for ii,(name,position) in enumerate(zip(names, center_positions)):
                cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

                nr, bins, rprof = azimuthalAverage(cutout.data, binsize=1.0,
                                                   return_nr=True)

                linestyle = next(linestyles[name])

                pl.figure(ii)
                pl.title(name)
                pl.plot(bins*pixscale*3600., rprof/ppbeam,
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Azimuthally Averaged Flux (Jy)")
                pl.xlabel("Radius [arcsec]")

                cumul_rprof = np.nan_to_num(rprof*nr/ppbeam).cumsum()

                pl.figure(nplots+ii)
                pl.title(name)
                pl.plot(bins*pixscale*3600., cumul_rprof,
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Cumulative Flux (Jy)")
                pl.xlabel("Radius [arcsec]")
                if ii == 0:
                    ax = pl.gca()
                    ax2 = ax.twiny()
                    ax3 = ax.twinx()
                    def tick_function(old_x):
                        newx = (old_x*u.arcsec*masscalc.distance).to(u.pc, u.dimensionless_angles()).value
                        return ["%.1f" % z for z in newx]
                    new_tick_locations = [0.005,0.01,0.015,0.02,0.025]*u.pc
                    new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
                    ax2.set_xlim(ax.get_xlim())
                    ax2.set_xticks(new_tick_locs_as.value)
                    ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
                    ax2.set_xlabel(r"Radius (pc)")
                    ax3.set_ylim(ax.get_ylim())
                    yticks_mass = np.arange(0,6000,1000)
                    yticks_Jy = yticks_mass/masscalc.mass_conversion_factor().value
                    ax3.set_yticks(yticks_Jy)
                    ax3.set_yticklabels(yticks_mass)
                    ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")

                pl.figure(nplots*2+ii)
                pl.title(name)
                pl.plot(((bins*pixscale*u.deg)*masscalc.distance).to(u.pc,
                                                                     u.dimensionless_angles()),
                        cumul_rprof * masscalc.mass_conversion_factor(),
                        label=fn.split(".")[0], linestyle=linestyle)
                pl.ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")
                pl.xlabel("Radius (pc)")

        for ii in range(nplots):
            for xtra in (0,nplots*2):
                ax = pl.figure(ii+xtra).gca()
                box = ax.get_position()
                ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

                # Put a legend to the right of the current axis
                ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    else:
        nplots = 0

    pl.matplotlib.rc_file('pubfiguresrc')
    for jj in range(nplots*3+1, nplots*3+11):
        pl.figure(jj).clf()
    # $ find ~/work/w51/alma/FITS/ -samefile ~/work/w51/alma/FITS/W51_te_continuum_best.fits
    # /Users/adam/work/w51/alma/FITS//12m/continuum/selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits
    # /Users/adam/work/w51/alma/FITS//W51_te_continuum_best.fits
    fn = "selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits"
    fh = fits.open(paths.dpath("12m/continuum/"+fn))
    mywcs = wcs.WCS(fh[0].header)
    beam = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
    ppbeam = (beam.sr/(pixscale**2*u.deg**2)).decompose().value / u.beam
    for ii,(name,position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        nr, bins, rprof = azimuthalAverage(cutout.data, binsize=1.0,
                                           return_nr=True)

        pl.figure(nplots*3+1)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., rprof/ppbeam,
                label=name)
        pl.ylabel("Azimuthally Averaged Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        cumul_rprof = np.nan_to_num(rprof*nr/ppbeam).cumsum()

        pl.figure(nplots*3+2)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., cumul_rprof,
                label=name)
        pl.ylabel("Cumulative Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            ax3.set_ylim(ax.get_ylim())
            yticks_mass = np.arange(0,6000,1000)
            yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            ax3.set_yticks(yticks_Jy)
            ax3.set_yticklabels(yticks_mass)
            ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")



        radii = ((bins*pixscale*u.deg)*masscalc.distance).to(u.pc,
                                                             u.dimensionless_angles())
        mass_40k_profile = (cumul_rprof * masscalc.mass_conversion_factor(TK=40) / u.beam).to(u.M_sun)

        pl.figure(nplots*3+3)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(radii, mass_40k_profile, label=name)
        pl.ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))


        density_40k_profile = (mass_40k_profile / (4/3.*np.pi*radii**3) / (2.8*u.Da)).to(u.cm**-3)
        #print(density_40k_profile)
        #print(radii)

        pl.figure(nplots*3+4)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.semilogy(radii, density_40k_profile, label=name)
        pl.ylabel("Cumulative Density [n(H$_2$), $T=40$ K]")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        angular_radii = bins*pixscale*3600.
        azimuthal_average_flux = rprof/ppbeam
        azimuthal_average_mass = azimuthal_average_flux * masscalc.mass_conversion_factor(TK=40) / u.beam
        bindiff_as = np.diff(bins).mean() * pixscale * 3600.
        bindiff_cm = bindiff_as * masscalc.distance / 206265.
        bins_cm = (angular_radii * masscalc.distance / 206265.).to(u.cm)
        sqdiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**2] +
                                   (bins_cm.to(u.cm)[1:]**2 -
                                    bins_cm.to(u.cm)[:-1]**2).value.tolist(),
                                   u.cm**2)
        cudiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**3] +
                                   (bins_cm.to(u.cm)[1:]**3 -
                                    bins_cm.to(u.cm)[:-1]**3).value.tolist(),
                                   u.cm**3)
        sqdiffbins_pix = [bins[0]**2] + (bins[1:]**2 - bins[:-1]**2).tolist()
        azimuthal_average_density = (azimuthal_average_mass * sqdiffbins_pix /
                                     (2.8*u.Da) /
                                     (4/3.*np.pi*(cudiffbins_cm))).to(u.cm**-3)

        pl.figure(nplots*3+5)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")


        c_s_40k = ((constants.k_B * 40*u.K / (2.4*u.Da))**0.5).to(u.km/u.s)
        azimuthal_average_MJ_40k = (np.pi/6. * c_s_40k**3 /
                                    (constants.G**1.5 *
                                     (2.8*u.Da*azimuthal_average_density)**0.5)).to(u.M_sun)

        pl.figure(nplots*3+6)
        pl.semilogy(angular_radii, azimuthal_average_MJ_40k, label=name)
        pl.ylabel("Azimuthally Averaged $M_J$ at $T=40$K")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        source = 'e2' if name == 'e2e' else name
        temperature_map_fn = paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        ch3ohN_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        ch3ohT_hdul = fits.open(paths.dpath('12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source)))
        bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
        ch3ohN = ch3ohN_hdul[0].data
        ch3ohT = ch3ohT_hdul[0].data
        dust_brightness,wts = reproject.reproject_interp(fits.open(paths.dpath('W51_te_continuum_best.fits')),
                                                         ch3ohN_hdul[0].header)
        bm = radio_beam.Beam.from_fits_header(paths.dpath("W51_te_continuum_best.fits"))

        yy,xx = np.indices(ch3ohN.shape)
        if source == 'north':
            center = [84.,38.]
        else:
            center = [ch3ohN.shape[0]/2., ch3ohN.shape[1]/2.]
        yyc = (yy-center[0])
        xxc = (xx-center[1])
        rr = (yyc**2 + xxc**2)**0.5
        rr_as = (rr*bigpixscale).to(u.arcsec)
        theta = np.arctan2(yyc,xxc)*u.rad

        dust_column = dust_emissivity.dust.colofsnu(225*u.GHz, dust_brightness*u.Jy,
                                                    beamomega=bm,
                                                    temperature=ch3ohT*u.K)
        ch3oh_abundance = ch3ohN / dust_column.value
        mask = (ch3oh_abundance > 1e-10) & (ch3oh_abundance < 1e-5)
        if source == 'e2':
            mask = mask & (((theta > 15*u.deg) & (theta < 345*u.deg)) | (theta < -15*u.deg))
        mask = mask & np.isfinite(ch3oh_abundance)
        # exclude high-abundance, low-column regions: likely to be div-by-zero zones
        mask = mask & (~((ch3ohN < 1e18) & (ch3oh_abundance > 5e-6)))
        mask = mask & (~((dust_brightness<1e-2) & (ch3ohT > 500) & (ch3oh_abundance > 1e-6)))

        #mask = mask & (~((ch3ohT > 250) &
        #                 (ch3ohN < 1e18) &
        #                 (rr_as>1.5*u.arcsec))
        #               )# these are low-column,

        temwcs = wcs.WCS(temperature_map_fh[0].header)

        temcutout = Cutout2D(temperature_map_fh[0].data, position, size, wcs=temwcs)
        maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)

        tem_nr, tem_bins, tem_rprof = azimuthalAverage(temcutout.data,
                                                       weights=(maskcutout.data>0).astype('float'),
                                                       binsize=1.0,
                                                       return_nr=True,
                                                       interpnan=True,
                                                      )

        mass_profile = (cumul_rprof * masscalc.mass_conversion_factor(TK=tem_rprof) / u.beam).to(u.M_sun)
        density_profile = (mass_profile / (4/3.*np.pi*radii**3) / (2.8*u.Da)).to(u.cm**-3)

        density_alpha = ((np.log(density_profile[1:].value) -
                          np.log(density_profile[:-1].value)) /
                         (np.log(angular_radii[1:]) -
                          np.log(angular_radii[:-1]))
                        )

        c_s = ((constants.k_B * tem_rprof*u.K / (2.4*u.Da))**0.5).to(u.km/u.s)
        azimuthal_average_MJ = (np.pi/6. * c_s**3 /
                                (constants.G**1.5 *
                                 (2.8*u.Da*azimuthal_average_density)**0.5)
                               ).to(u.M_sun)


        pl.figure(nplots*3+7)
        pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        pl.ylabel("Azimuthally Averaged $M_J$ at $T(\\mathrm{CH}_3\\mathrm{OH})$")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")


        pl.figure(nplots*3+8)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., mass_profile,
                label=name)
        pl.ylabel("Cumulative Mass at T(CH$_3$OH)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='upper left')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots*3+9)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins*pixscale*3600., tem_rprof,
                label=name)
        pl.legend(loc='best')
        pl.ylabel("CH$_3$OH temperature")
        pl.xlabel("Radius [as]")


        azimuthal_average_RJ = (c_s**1 /
                                (constants.G**0.5 *
                                 (2.8*u.Da*azimuthal_average_density)**0.5)
                               ).to(u.au)

        pl.figure(nplots*3+10)
        pl.plot(angular_radii, azimuthal_average_RJ, label=name)
        pl.plot([0,(7000*u.au/masscalc.distance).to(u.arcsec,
                                                    u.dimensionless_angles()).value],
                [0,7000], 'k--', alpha=0.5)
        pl.ylabel("Azimuthally Averaged $R_J$ at $T(\\mathrm{CH}_3\\mathrm{OH})$ [au]")
        pl.xlabel("Radius [arcsec]")
        pl.ylim(0,3000)
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii==len(names)-1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()
            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x*u.arcsec*masscalc.distance).to(u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]
            new_tick_locations = np.arange(0,8000,1000)*u.au
            new_tick_locs_as = (new_tick_locations/masscalc.distance).to(u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")


        pl.figure(nplots*3+11)
        pl.plot((angular_radii[1:]+angular_radii[:-1])/2., density_alpha)
        pl.xlabel("Radius [as]")
        pl.ylabel("Density Profile Exponent $\\kappa_\\rho$")
    shreg = pyregion.ShapeList([reg])
    name = reg.attr[1]['text']
    log.info(name)

    mask = shreg.get_mask(hdu=contfile[0])

    data = contfile[0].data
    results[name] = {'peak': data[mask].max(),
                     'sum': data[mask].sum(),
                     'npix': mask.sum(),
                     'beam_area': beam.sr,
                     'RA': reg.coord_list[0],
                     'Dec': reg.coord_list[1],
                    }
    results[name]['peak_mass'] = masscalc.mass_conversion_factor()*results[name]['peak']
    results[name]['peak_col'] = masscalc.col_conversion_factor(beamomega=beam.sr.value)*results[name]['peak']


    for image, imname in ((contfile,''), (radio_image,'KUband')):
        data = image[0].data.squeeze()
        mywcs = wcs.WCS(image[0].header).celestial

        beam = radio_beam.Beam.from_fits_header(image[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

        keys = ['{1}cont_flux{0}arcsec'.format(rr.value, imname) for rr in radii]
        for k in keys:
            results[name][k] = []
             'Dec': u.deg,
            }

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

    fn_90GHz = paths.tmpath('SgrB2_nocal_TE_continuum_90GHz.image.pbcor.fits')
    results_90GHz = photometry(fits.getdata(fn_90GHz),
                               wcs.WCS(fits.getheader(fn_90GHz)), regs,
                               radio_beam.Beam.from_fits_header(fits.getheader(fn_90GHz)))
    fn_100GHz = paths.tmpath('SgrB2_nocal_TE_continuum_100GHz.image.pbcor.fits')
    results_100GHz = photometry(fits.getdata(fn_100GHz),
                               wcs.WCS(fits.getheader(fn_100GHz)), regs,
                               radio_beam.Beam.from_fits_header(fits.getheader(fn_100GHz)))

    for name in results:
        results[name]['peak_mass_20K'] = masscalc.mass_conversion_factor()*results[name]['peak']
        results[name]['peak_col_20K'] = masscalc.col_conversion_factor(results[name]['peak']*u.Jy, beam.sr)
        results[name]['peak_90GHz'] = results_90GHz[name]['peak']
        results[name]['peak_100GHz'] = results_100GHz[name]['peak']
        results[name]['sum_90GHz'] = results_90GHz[name]['sum']
        results[name]['sum_100GHz'] = results_100GHz[name]['sum']
        results[name]['bgmad_90GHz'] = results_90GHz[name]['bgmad']
        results[name]['bgmad_100GHz'] = results_100GHz[name]['bgmad']

    # invert the table to make it parseable by astropy...
    # (this shouldn't be necessary....)
    results_inv = {'name':{}}
    columns = {'name':[]}
    for k,v in results.items():
        results_inv['name'][k] = k
        columns['name'].append(k)
brightest_line_flux = np.array([cores_merge[y].data for y in ('peak0','peak1','peak2','peak3')])
peak_line_flux = np.nanmax(brightest_line_flux, axis=0)
peak_line_id = np.nanargmax(brightest_line_flux, axis=0)
brightest_line_name = np.array([cores_merge[('peak0species','peak1species','peak2species','peak3species')[y]][ii] for ii,y in enumerate(peak_line_id)])
cores_merge.add_column(Column(peak_line_flux, name='PeakLineFlux', unit=cores_merge['peak0'].unit))
cores_merge.add_column(Column(brightest_line_name, name='PeakLineSpecies'))

peak_line_brightness = (peak_line_flux*u.Jy).to(u.K, u.brightness_temperature(cores_merge['beam_area'], 220*u.GHz))
cores_merge.add_column(Column(peak_line_brightness, name='PeakLineBrightness'))

jtok_eq = u.brightness_temperature(cores_merge['beam_area'], 225*u.GHz)
cont_brightness = Column((u.beam * cores_merge['sum']/cores_merge['npix']).to(u.K, jtok_eq),
                         name='MeanContinuumBrightness')
cores_merge.add_column(cont_brightness)

aperturemass20k = cores_merge['sum'] / ppbeam * masscalc.mass_conversion_factor(20)
cores_merge.add_column(Column(aperturemass20k.value, name='ApertureMass20K', unit=u.M_sun))

temperature_corrected_mass = Column([(masscalc.mass_conversion_factor(20).value
                                      if np.isnan(row['PeakLineBrightness'])
                                      else masscalc.mass_conversion_factor(row['PeakLineBrightness'])).value
                                     * row['peak'] for row in cores_merge],
                                    name='T_corrected_peakmass',
                                    unit=u.M_sun)
cores_merge.add_column(temperature_corrected_mass)

cores_merge = cores_merge['SourceID',
                          'peak_mass',
                          'ApertureMass20K',
                          'T_corrected_peakmass',
                          'PeakLineBrightness',
예제 #22
0
cores_merge.add_column(
    Column(brightest_fitted_brightness,
           'BrightestFittedApMeanBrightness',
           unit=u.K))

# need to add back in continuum because we're concerned with the *absolute*
# brightness
# moved to other merge jtok_eq = u.brightness_temperature(cores_merge['beam_area'], 225*u.GHz)
# moved to other merge cont_brightness = (u.beam * cores_merge['sum']/cores_merge['npix']).to(u.K, jtok_eq)
cont_brightness = cores_merge['MeanContinuumBrightness']
contincluded_line_brightness = cores_merge[
    'BrightestFittedApMeanBrightness'] + cont_brightness
cores_merge.add_column(
    Column(contincluded_line_brightness,
           'BrightestFittedApMeanBrightnessWithcont',
           unit=u.K))

temperature_corrected_aperturemass = Column(
    [(masscalc.mass_conversion_factor(20).value
      if np.isnan(row['BrightestFittedApMeanBrightnessWithcont']) else
      masscalc.mass_conversion_factor(
          row['BrightestFittedApMeanBrightnessWithcont']).value) * row['sum'] /
     ppbeam for row in cores_merge],
    name='T_corrected_aperturemass',
    unit=u.M_sun)
cores_merge.add_column(temperature_corrected_aperturemass)

cores_merge.write(paths.tpath('core_continuum_and_line.ipac'),
                  format='ascii.ipac',
                  overwrite=True)
    dendro_merge['peak{0}freq'.format(pid)][ii] if pid >= 0 else 1.0
    for ii, pid in enumerate(peak_line_id)
], u.GHz)
peak_line_cont = u.Quantity([
    dendro_merge['continuum20pct{0}'.format(pid)][ii] if pid >= 0 else 0.0
    for ii, pid in enumerate(peak_line_id)
], u.Jy)
tbequiv = u.brightness_temperature(peak_line_beam_area, peak_line_freq)
peak_line_brightness = (peak_line_flux * u.Jy).to(u.K, tbequiv)
dendro_merge.add_column(Column(peak_line_brightness,
                               name='PeakLineBrightness'))
continuum20pct_K = (peak_line_cont.to(u.K, tbequiv))
dendro_merge.add_column(Column(continuum20pct_K, name='PeakLineContinuumBG'))

tcm = Column(
    [(masscalc.mass_conversion_factor(20).to(u.M_sun).value if np.isnan(
        row['PeakLineBrightness']) else masscalc.mass_conversion_factor(
            TK=row['PeakLineBrightness']).to(u.M_sun).value) *
     row['peak_cont_flux'] for row in dendro_merge],
    name='T_corrected_mass',
    unit=u.M_sun)
temperature_corrected_mass = tcm
dendro_merge.add_column(temperature_corrected_mass)

columns = [
    'SourceID',
    'peak_cont_mass',
    'T_corrected_mass',
    'PeakLineBrightness',
    'PeakLineFlux',
    'PeakLineSpecies',
예제 #24
0
        fits.getdata(fn_90GHz), wcs.WCS(fits.getheader(fn_90GHz)), regs,
        radio_beam.Beam.from_fits_header(fits.getheader(fn_90GHz)))
    #fn_100GHz = paths.tmpath('SgrB2_nocal_TE_continuum_100GHz.image.pbcor.fits')
    fn_100GHz = paths.mergepath(
        'continuum/SgrB2_selfcal_full_TETC7m_selfcal5_ampphase_continuum_100GHz.image.pbcor.fits'
    )
    results_100GHz = photometry(
        fits.getdata(fn_100GHz), wcs.WCS(fits.getheader(fn_100GHz)), regs,
        radio_beam.Beam.from_fits_header(fits.getheader(fn_100GHz)))

    for name in results:
        results[name]['peak_col_20K'] = masscalc.col_conversion_factor(
            results[name]['peak'] * u.Jy, beam.sr)
        results[name]['peak_mass_20K'] = np.nan * u.g if np.isnan(
            results[name]['peak_col_20K']
        ) else masscalc.mass_conversion_factor() * results[name]['peak']
        results[name]['peak_col_40K'] = masscalc.col_conversion_factor(
            results[name]['peak'] * u.Jy, beam.sr, TK=40 * u.K)
        results[name]['peak_mass_40K'] = (
            np.nan * u.g if np.isnan(results[name]['peak_col_40K']) else
            masscalc.mass_conversion_factor(TK=40 * u.K) *
            results[name]['peak'])
        results[name]['peak_90GHz'] = results_90GHz[name]['peak']
        results[name]['peak_100GHz'] = results_100GHz[name]['peak']
        results[name]['sum_90GHz'] = results_90GHz[name]['sum']
        results[name]['sum_100GHz'] = results_100GHz[name]['sum']
        results[name]['bgmad_90GHz'] = results_90GHz[name]['bgmad']
        results[name]['bgmad_100GHz'] = results_100GHz[name]['bgmad']

    # invert the table to make it parseable by astropy...
    # (this shouldn't be necessary....)
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,
                                                                                     u.dimensionless_angles())))
print("Total pixels > {3}: {0} = {1}; r_eff = {2}, fraction={4}, fraction of signal: {5}"
      .format(definitely_thick_if_20K.sum(), definitely_thick_if_20K.sum()/ppbeam,
              ((definitely_thick_if_20K.sum() *
                (pixel_scale*masscalc.distance)**2)**0.5).to(u.pc,
                                                             u.dimensionless_angles()),
예제 #26
0
                                 u.sr)
peak_line_freq = u.Quantity([dendro_merge['peak{0}freq'.format(pid)][ii]
                             if pid >= 0 else 1.0
                             for ii,pid in enumerate(peak_line_id)],
                            u.GHz)
peak_line_cont = u.Quantity([dendro_merge['continuum20pct{0}'.format(pid)][ii]
                             if pid >= 0 else 0.0
                             for ii,pid in enumerate(peak_line_id)],
                            u.Jy)
tbequiv = u.brightness_temperature(peak_line_beam_area, peak_line_freq)
peak_line_brightness = (peak_line_flux*u.Jy).to(u.K, tbequiv)
dendro_merge.add_column(Column(peak_line_brightness, name='PeakLineBrightness'))
continuum20pct_K = (peak_line_cont.to(u.K, tbequiv))
dendro_merge.add_column(Column(continuum20pct_K, name='PeakLineContinuumBG'))

tcm = Column([(masscalc.mass_conversion_factor(20).to(u.M_sun).value if
               np.isnan(row['PeakLineBrightness']) else
               masscalc.mass_conversion_factor(TK=row['PeakLineBrightness']).to(u.M_sun).value)
              * row['peak_cont_flux'] for row in dendro_merge],
             name='T_corrected_mass', unit=u.M_sun)
temperature_corrected_mass = tcm
dendro_merge.add_column(temperature_corrected_mass)

columns = ['SourceID',
           'peak_cont_mass',
           'T_corrected_mass',
           'PeakLineBrightness',
           'PeakLineFlux',
           'PeakLineSpecies',
           'peak_cont_col',
           'mean_velo',
integ_north_lores = (cutout_north_lores[cutout_north_lores > 3 * u.mJy /
                                        u.beam]).sum() * u.beam / ppbeam_lores

print(
    "Integrated intensity of    e2: {0:0.2f}  /  {1:0.2f} -> {2:0.1f}% recovered"
    .format(integ_e2, integ_e2_lores, integ_e2 / integ_e2_lores * 100))
print(
    "Integrated intensity of    e8: {0:0.2f}  /  {1:0.2f} -> {2:0.1f}% recovered"
    .format(integ_e8, integ_e8_lores, integ_e8 / integ_e8_lores * 100))
print(
    "Integrated intensity of north: {0:0.2f}  /  {1:0.2f} -> {2:0.1f}% recovered"
    .format(integ_north, integ_north_lores,
            integ_north / integ_north_lores * 100))
print()

integmass_e2 = integ_e2 * masscalc.mass_conversion_factor(e2etbpeak) / u.Jy
integmass_e8 = integ_e8 * masscalc.mass_conversion_factor(e8tbpeak) / u.Jy
integmass_north = integ_north * masscalc.mass_conversion_factor(
    northtbpeak) / u.Jy

print("Integrated mass of e2: {0}".format(integmass_e2))
print("Integrated mass of e8: {0}".format(integmass_e8))
print("Integrated mass of north: {0}".format(integmass_north))
print()

integmass_e2 = integ_e2 * masscalc.mass_conversion_factor(200 * u.K) / u.Jy
integmass_e8 = integ_e8 * masscalc.mass_conversion_factor(200 * u.K) / u.Jy
integmass_north = integ_north * masscalc.mass_conversion_factor(
    200 * u.K) / u.Jy

print("Integrated mass of e2 at T=200K: {0}".format(integmass_e2))