Exemple #1
0
    def mask_out_signal(self, niter=1):
        """
        Sets the mask property of the SpectralCube associated with the noise object
        to exclude the noise through a (iterative) application of the Chauvenet
        rejection criterion (i.e., mask out all points outside of +/- N sigma of zero).

        Parameters
        ----------
        niter : number
            Number of iterations used in estimating the separate
            components of the spatial and spectral noise variations.
            Default=1
        """

        # This needs reworking but is close.

        for count in range(niter):
            if self.spatial_norm is not None:
                noise = self.scale_cube
                snr = self.cube.filled_data[:].value / noise
            else:
                snr = self.cube.filled_data[:].value / self.scale
            # Include negatives in the signal mask or not?
            newmask = BooleanArrayMask(
                np.abs(snr) < sig_n_outliers(self.cube.size), self.cube.wcs)
            self.cube = self.cube.with_mask(newmask)
Exemple #2
0
def test_spectralnorm():
    cube = SpectralCube(data, wcs.WCS(h),
                        mask=BooleanArrayMask(mask, wcs=wcs.WCS(h)))
    noiseobj = noise.Noise(cube)
    noiseobj.estimate_noise()
    expected = np.array([ 1.14898322,  0.71345272,  1.21989125])
    assert np.allclose(noiseobj.spectral_norm, expected)
    def to_object(self, data_or_subset, attribute=None):
        """
        Convert a glue Data object to a SpectralCube object.

        Parameters
        ----------
        data_or_subset : `glue.core.data.Data` or `glue.core.subset.Subset`
            The data to convert to a SpectralCube object
        attribute : `glue.core.component_id.ComponentID`
            The attribute to use for the SpectralCube data
        """

        if data_or_subset.ndim > 0 and data_or_subset.ndim != 3:
            raise ValueError(
                'Data object should have 3 dimensions in order to '
                'be converted to a SpectralCube object.')

        if isinstance(data_or_subset, Subset):
            data = data_or_subset.data
            subset_state = data_or_subset.subset_state
        else:
            data = data_or_subset
            subset_state = None

        if isinstance(data.coords, BaseLowLevelWCS):
            wcs = data.coords
        else:
            raise TypeError(
                'data.coords should be an instance of BaseLowLevelWCS.')

        if isinstance(attribute, str):
            attribute = data.id[attribute]
        elif len(data.main_components) == 0:
            raise ValueError('Data object has no attributes.')
        elif attribute is None:
            if len(data.main_components) == 1:
                attribute = data.main_components[0]
            else:
                raise ValueError(
                    "Data object has more than one attribute, so "
                    "you will need to specify which one to use as "
                    "the flux for the spectral cube using the "
                    "attribute= keyword argument.")

        component = data.get_component(attribute)

        values = data.get_data(attribute)
        if subset_state is None:
            mask = None
        else:
            mask = data.get_mask(subset_state=subset_state)
            values = values.copy()
            values[~mask] = np.nan
            mask = BooleanArrayMask(mask, wcs=wcs)

        values = values * u.Unit(component.units)

        return SpectralCube(values, mask=mask, wcs=wcs)
Exemple #4
0
    def data_to_cube(self):
        """Glue Data -> SpectralCube"""
        if self.component_id is None:
            raise Exception("component_id was not provided.")
        wcs = self.get_glue_wcs()
        data_array = self.data[self.component_id]
        mask = BooleanArrayMask(mask=self.get_glue_mask(), wcs=wcs)

        return SpectralCube(data=data_array, wcs=wcs, mask=mask)
Exemple #5
0
def test_spatialnorm():
    cube = SpectralCube(data, wcs.WCS(h),
                        mask=BooleanArrayMask(mask, wcs=wcs.WCS(h)))
    noiseobj = noise.Noise(cube)
    noiseobj.estimate_noise()
    print noiseobj.spatial_norm
    expected = np.array([[ 0.04430196, 0.78314449, 0.07475047, 0.5494684 , 0.05790756],
                         [ 0.32931213, 0.76450342, 1.33944507, 1.06416389, 0.27999452],
                         [ 0.65174339, 0.24128143, 0.27692018, 0.0244925 , 0.11167775],
                         [ 0.60682872, 0.42536813, 0.20018275, 0.78523107, 0.95516435]])

    assert np.allclose(noiseobj.spatial_norm, expected)
def smooth_mask(mask, wcs, diam):
    
    mask_np = np.asarray( mask.include() * 1 )        
    structure = np.ones((diam, diam, diam))
    dist = ((np.indices((diam, diam)) - (diam - 1) / 2.)**2).sum(axis=0)**0.5
    structure[dist > diam / 2.] = 0
    
    mask_dilation = ndimage.binary_dilation(mask_np, structure=structure)
    mask_erosion = ndimage.binary_erosion(mask_np, structure=structure)
    
    mask_dilation_speccube = BooleanArrayMask(mask=mask_erosion, wcs=wcs)
    
    return mask_dilation_speccube
Exemple #7
0
 def data_to_cube(self, to_qcube=False):
     """
     smooth_cube: Glue Data -> SpectralCube
     multi_threading_smooth: Glue Data -> QSpectralCube
     """
     if self.component_id is None:
         raise Exception("component_id was not provided.")
     wcs = self.get_glue_wcs()
     data_array = self.data[self.component_id]
     mask = BooleanArrayMask(mask=self.get_glue_mask(), wcs=wcs)
     if to_qcube:
         return QSpectralCube(data=data_array, wcs=wcs, mask=mask)
     else:
         return SpectralCube(data=data_array, wcs=wcs, mask=mask)
    def _compose_cube(self):
        """
        Create a :class:`~spectral_cube.SpectralCube` from a Glue data
        component.
        """
        if issubclass(self.data.__class__, Subset):
            wcs = self.data.data.coords.wcs
            data = self.data.data
            mask = self.data.to_mask()
        else:
            wcs = self.data.coords.wcs
            data = self.data
            mask = np.ones(data.shape).astype(bool)

        mask = BooleanArrayMask(mask=mask, wcs=wcs)

        return SpectralCube(data[self.component_id], wcs=wcs, mask=mask)
def measure_dendrogram_properties(dend=None, cube303=cube303,
                                  cube321=cube321, cube13co=cube13co,
                                  cube18co=cube18co, noise_cube=noise_cube,
                                  sncube=sncube,
                                  suffix="",
                                  last_index=None,
                                  plot_some=True,
                                  line='303',
                                  write=True):

    assert (cube321.shape == cube303.shape == noise_cube.shape ==
            cube13co.shape == cube18co.shape == sncube.shape)
    assert sncube.wcs is cube303.wcs is sncube.mask._wcs

    metadata = {}
    metadata['data_unit'] = u.K
    metadata['spatial_scale'] =  7.2 * u.arcsec
    metadata['beam_major'] =  30 * u.arcsec
    metadata['beam_minor'] =  30 * u.arcsec
    metadata['wavelength'] =  218.22219*u.GHz
    metadata['velocity_scale'] = u.km/u.s
    metadata['wcs'] = cube303.wcs

    keys = [
            'density_chi2',
            'expected_density',
            'dmin1sig_chi2',
            'dmax1sig_chi2',
            'column_chi2',
            'expected_column',
            'cmin1sig_chi2',
            'cmax1sig_chi2',
            'temperature_chi2',
            'expected_temperature',
            'tmin1sig_chi2',
            'tmax1sig_chi2',
            'eratio321303',
            'ratio321303',
            'logh2column',
            'elogh2column',
            'logabundance',
            'elogabundance',
           ]
    obs_keys = [
            'Stot303',
            'Smin303',
            'Smax303',
            'Stot321',
            'Smean303',
            'Smean321',
            'npix',
            'e303',
            'e321',
            'r321303',
            'er321303',
            '13cosum',
            'c18osum',
            '13comean',
            'c18omean',
            's_ntotal',
            'index',
            'is_leaf',
            'parent',
            'root',
            'lon',
            'lat',
            'vcen',
            'higaldusttem',
            'reff',
            'dustmass',
            'dustmindens',
            'bad',
            #'tkin_turb',
    ]
    columns = {k:[] for k in (keys+obs_keys)}

    log.debug("Initializing dendrogram temperature fitting loop")

    # FORCE wcs to match
    # (technically should reproject here)
    cube13co._wcs = cube18co._wcs = cube303.wcs
    cube13co.mask._wcs = cube18co.mask._wcs = cube303.wcs

    if line == '303':
        maincube = cube303
    elif line == '321':
        maincube = cube321
    else:
        raise ValueError("Unrecognized line: {0}".format(line))

    # Prepare an array to hold the fitted temperatures
    tcubedata = np.empty(maincube.shape, dtype='float32')
    tcubedata[:] = np.nan
    tcubeleafdata = np.empty(maincube.shape, dtype='float32')
    tcubeleafdata[:] = np.nan


    nbad = 0

    catalog = ppv_catalog(dend, metadata)
    pb = ProgressBar(len(catalog))
    for ii,row in enumerate(catalog):
        structure = dend[row['_idx']]
        assert structure.idx == row['_idx'] == ii
        dend_obj_mask = BooleanArrayMask(structure.get_mask(), wcs=cube303.wcs)
        dend_inds = structure.indices()

        view = (slice(dend_inds[0].min(), dend_inds[0].max()+1),
                slice(dend_inds[1].min(), dend_inds[1].max()+1),
                slice(dend_inds[2].min(), dend_inds[2].max()+1),)
        #view2 = cube303.subcube_slices_from_mask(dend_obj_mask)
        submask = dend_obj_mask[view]
        #assert np.count_nonzero(submask.include()) == np.count_nonzero(dend_obj_mask.include())

        sn = sncube[view].with_mask(submask)
        sntot = sn.sum().value
        #np.testing.assert_almost_equal(sntot, structure.values().sum(), decimal=0)

        c303 = cube303[view].with_mask(submask)
        c321 = cube321[view].with_mask(submask)
        co13sum = cube13co[view].with_mask(submask).sum().value
        co18sum = cube18co[view].with_mask(submask).sum().value
        if hasattr(co13sum,'__len__'):
            raise TypeError(".sum() applied to an array has yielded a non scalar.")

        npix = submask.include().sum()
        assert npix == structure.get_npix()
        Stot303 = c303.sum().value
        if np.isnan(Stot303):
            raise ValueError("NaN in cube.  This can't happen: the data from "
                             "which the dendrogram was derived can't have "
                             "NaN pixels.")
        Smax303 = c303.max().value
        Smin303 = c303.min().value

        Stot321 = c321.sum().value
        if npix == 0:
            raise ValueError("npix=0. This is impossible.")
        Smean303 = Stot303/npix
        if Stot303 <= 0 and line=='303':
            raise ValueError("The 303 flux is <=0.  This isn't possible because "
                             "the dendrogram was derived from the 303 data with a "
                             "non-zero threshold.")
        elif Stot303 <= 0 and line=='321':
            Stot303 = 0
            Smean303 = 0
        elif Stot321 <= 0 and line=='321':
            raise ValueError("The 321 flux is <=0.  This isn't possible because "
                             "the dendrogram was derived from the 321 data with a "
                             "non-zero threshold.")
        if np.isnan(Stot321):
            raise ValueError("NaN in 321 line")
        Smean321 = Stot321/npix

        #error = (noise_cube[view][submask.include()]).sum() / submask.include().sum()**0.5
        var = ((noise_cube[dend_obj_mask.include()]**2).sum() / npix**2)
        error = var**0.5
        if np.isnan(error):
            raise ValueError("error is nan: this is impossible by definition.")

        if line == '321' and Stot303 == 0:
            r321303 = np.nan
            er321303 = np.nan
        elif Stot321 < 0:
            r321303 = error / Smean303
            er321303 = (r321303**2 * (var/Smean303**2 + 1))**0.5
        else:
            r321303 = Stot321 / Stot303
            er321303 = (r321303**2 * (var/Smean303**2 + var/Smean321**2))**0.5

        for c in columns:
            assert len(columns[c]) == ii

        columns['index'].append(row['_idx'])
        columns['s_ntotal'].append(sntot)
        columns['Stot303'].append(Stot303)
        columns['Smax303'].append(Smax303)
        columns['Smin303'].append(Smin303)
        columns['Stot321'].append(Stot321)
        columns['Smean303'].append(Smean303)
        columns['Smean321'].append(Smean321)
        columns['npix'].append(npix)
        columns['e303'].append(error)
        columns['e321'].append(error)
        columns['r321303'].append(r321303)
        columns['er321303'].append(er321303)
        columns['13cosum'].append(co13sum)
        columns['c18osum'].append(co18sum)
        columns['13comean'].append(co13sum/npix)
        columns['c18omean'].append(co18sum/npix)
        columns['is_leaf'].append(structure.is_leaf)
        columns['parent'].append(structure.parent.idx if structure.parent else -1)
        columns['root'].append(get_root(structure).idx)
        s_main = maincube._data[dend_inds]
        x,y,z = maincube.world[dend_inds]
        lon = ((z.value-(360*(z.value>180)))*s_main).sum()/s_main.sum()
        lat = (y*s_main).sum()/s_main.sum()
        vel = (x*s_main).sum()/s_main.sum()
        columns['lon'].append(lon)
        columns['lat'].append(lat.value)
        columns['vcen'].append(vel.value)

        mask2d = dend_obj_mask.include().max(axis=0)[view[1:]]
        logh2column = np.log10(np.nanmean(column_regridded.data[view[1:]][mask2d]) * 1e22)
        if np.isnan(logh2column):
            log.info("Source #{0} has NaNs".format(ii))
            logh2column = 24
        elogh2column = elogabundance
        columns['higaldusttem'].append(np.nanmean(dusttem_regridded.data[view[1:]][mask2d]))

        r_arcsec = row['radius']*u.arcsec
        reff = (r_arcsec*(8.5*u.kpc)).to(u.pc, u.dimensionless_angles())
        mass = ((10**logh2column*u.cm**-2)*np.pi*reff**2*2.8*constants.m_p).to(u.M_sun)
        density = (mass/(4/3.*np.pi*reff**3)/constants.m_p/2.8).to(u.cm**-3)

        columns['reff'].append(reff.value)
        columns['dustmass'].append(mass.value)
        columns['dustmindens'].append(density.value)
        mindens = np.log10(density.value)
        if mindens < 3:
            mindens = 3

        if (r321303 < 0 or np.isnan(r321303)) and line != '321':
            raise ValueError("Ratio <0: This can't happen any more because "
                             "if either num/denom is <0, an exception is "
                             "raised earlier")
            #for k in columns:
            #    if k not in obs_keys:
            #        columns[k].append(np.nan)
        elif (r321303 < 0 or np.isnan(r321303)) and line == '321':
            for k in keys:
                columns[k].append(np.nan)
        else:
            # Replace negatives for fitting
            if Smean321 <= 0:
                Smean321 = error
            mf.set_constraints(ratio321303=r321303, eratio321303=er321303,
                               #ratio321322=ratio2, eratio321322=eratio2,
                               logh2column=logh2column, elogh2column=elogh2column,
                               logabundance=logabundance, elogabundance=elogabundance,
                               taline303=Smean303, etaline303=error,
                               taline321=Smean321, etaline321=error,
                               mindens=mindens,
                               linewidth=10)
            row_data = mf.get_parconstraints()
            row_data['ratio321303'] = r321303
            row_data['eratio321303'] = er321303

            for k in row_data:
                columns[k].append(row_data[k])

            # Exclude bad velocities from cubes
            if row['v_cen'] < -80e3 or row['v_cen'] > 180e3:
                # Skip: there is no real structure down here
                nbad += 1
                is_bad = True
            else:
                is_bad = False
                tcubedata[dend_obj_mask.include()] = row_data['expected_temperature']
                if structure.is_leaf:
                    tcubeleafdata[dend_obj_mask.include()] = row_data['expected_temperature']

            columns['bad'].append(is_bad)

            width = row['v_rms']*u.km/u.s
            lengthscale = reff

            #REMOVED in favor of despotic version done in dendrograms.py
            # we use the analytic version here; the despotic version is
            # computed elsewhere (with appropriate gcor factors)
            #columns['tkin_turb'].append(heating.tkin_all(10**row_data['density_chi2']*u.cm**-3,
            #                                             width,
            #                                             lengthscale,
            #                                             width/lengthscale,
            #                                             columns['higaldusttem'][-1]*u.K,
            #                                             crir=0./u.s))

        if len(set(len(c) for k,c in columns.items())) != 1:
            print("Columns are different lengths.  This is not allowed.")
            import ipdb; ipdb.set_trace()

        for c in columns:
            assert len(columns[c]) == ii+1

        if plot_some and not is_bad and (ii-nbad % 100 == 0 or ii-nbad < 50):
            try:
                log.info("T: [{tmin1sig_chi2:7.2f},{expected_temperature:7.2f},{tmax1sig_chi2:7.2f}]"
                         "  R={ratio321303:8.4f}+/-{eratio321303:8.4f}"
                         "  Smean303={Smean303:8.4f} +/- {e303:8.4f}"
                         "  Stot303={Stot303:8.2e}  npix={npix:6d}"
                         .format(Smean303=Smean303, Stot303=Stot303,
                                 npix=npix, e303=error, **row_data))

                pl.figure(1)
                pl.clf()
                mf.denstemplot()
                pl.savefig(fpath("dendrotem/diagnostics/{0}_{1}.png".format(suffix,ii)))
                pl.figure(2).clf()
                mf.parplot1d_all(levels=[0.68268949213708585])
                pl.savefig(fpath("dendrotem/diagnostics/1dplot{0}_{1}.png".format(suffix,ii)))
                pl.draw()
                pl.show()
            except Exception as ex:
                print ex
                pass
        else:
            pb.update(ii+1)

        if last_index is not None and ii >= last_index:
            break

    if last_index is not None:
        catalog = catalog[:last_index+1]

    for k in columns:
        if k not in catalog.keys():
            catalog.add_column(table.Column(name=k, data=columns[k]))

    for mid,lo,hi,letter in (('expected_temperature','tmin1sig_chi2','tmax1sig_chi2','t'),
                             ('expected_density','dmin1sig_chi2','dmax1sig_chi2','d'),
                             ('expected_column','cmin1sig_chi2','cmax1sig_chi2','c')):
        catalog.add_column(table.Column(name='elo_'+letter,
                                        data=catalog[mid]-catalog[lo]))
        catalog.add_column(table.Column(name='ehi_'+letter,
                                        data=catalog[hi]-catalog[mid]))

    if write:
        catalog.write(tpath('PPV_H2CO_Temperature{0}.ipac'.format(suffix)), format='ascii.ipac')

    # Note that there are overlaps in the catalog, which means that ORDER MATTERS
    # in the above loop.  I haven't yet checked whether large scale overwrites
    # small or vice-versa; it may be that both views of the data are interesting.
    tcube = SpectralCube(data=tcubedata, wcs=cube303.wcs,
                         mask=cube303.mask, meta={'unit':'K'},
                         header=cube303.header,
                        )
    tcubeleaf = SpectralCube(data=tcubeleafdata, wcs=cube303.wcs,
                         mask=cube303.mask, meta={'unit':'K'},
                         header=cube303.header,
                        )

    if write:
        log.info("Writing TemperatureCube")
        outpath = 'TemperatureCube_DendrogramObjects{0}.fits'
        tcube.write(hpath(outpath.format(suffix)),
                    overwrite=True)

        outpath_leaf = 'TemperatureCube_DendrogramObjects{0}_leaves.fits'
        tcubeleaf.write(hpath(outpath_leaf.format(suffix)),
                    overwrite=True)


    return catalog, tcube
Exemple #10
0
                    cube = SpectralCube.read(hpath(ftemplate.format(smooth)))
                    if weight:
                        wcube = (SpectralCube.read(
                            hpath('APEX_H2CO_303_202_smooth_bl.fits'))
                                 if 'smooth' in smooth else SpectralCube.read(
                                     hpath('APEX_H2CO_303_202_bl.fits')))
                        mcube = (SpectralCube.read(
                            hpath('APEX_H2CO_303_202_smooth_bl_mask.fits'))
                                 if 'smooth' in smooth else SpectralCube.read(
                                     hpath('APEX_H2CO_303_202_bl_mask.fits')))
                        if cube.shape != wcube.shape:
                            log.info("Not weighting {0}".format(fn))
                            continue
                        weighted = copy.copy(cube)
                        weighted._data = wcube._data * cube._data
                        mask = (wcube.mask & cube.mask & BooleanArrayMask(
                            mcube._data == 1, mcube.wcs))
                        weighted = weighted.with_mask(mask)
                        wcube = wcube.with_mask(mask)

                        pv1 = weighted.sum(axis=1)
                        pv2 = wcube.sum(axis=1)
                        pv = pv1 / pv2
                        # Hack to prevent unmatched celestial axis error
                        pv1.wcs.wcs.ctype[0] = 'OFFSET'
                        pv2.wcs.wcs.ctype[0] = 'OFFSET'
                        hdu = copy.copy(pv1.hdu)
                        hdu.data = pv.value
                    else:
                        tproj = cube.mean(axis=1)
                        tproj.wcs.wcs.ctype[0] = 'OFFSET'
                        hdu = tproj.hdu
Exemple #11
0
width = 7 * u.MHz
print(f'Per-pixel mask width: {width}')
#shellcube=sc(data=shell,wcs=wcs).with_spectral_axis('Hz')

print('Begin masking procedure')
for y in range(spatdims[0]):
    print(f'Start Row {y}')
    for x in range(spatdims[1]):
        dopplershift = mom1[y, x]
        #print(f'dopplershift from reference: {dopplershift}')
        v_shifted = v0 + dopplershift
        z_shifted = v_shifted / c
        freq_shifted = restfreq / (1 + z_shifted)
        #print(f'shifted frequency: {freq_shifted}')
        tempmask = np.logical_and(spectraxis < (freq_shifted + width),
                                  spectraxis > (freq_shifted - width))
        shell[:, y, x] = tempmask

shellmaskcube = BooleanArrayMask(mask=shell, wcs=wcs)

maskedcube = datacube.with_mask(shellmaskcube)

print('Saving')
datacube.write('unmaskedspw08-7slab.fits', overwrite=True)
maskedcube.write(f'{width.value}mhzmasked_spw08-7slab.fits', overwrite=True)
shellmaskcube.write(f'{width.value}mhz8-7mask.fits', overwrite=True)
print('Done.')
#maskedcube.to_ds9('7f000001:41898')
#condition=restfreq+(0.77*u.km/u.s)#and minus
# dendro_temperature but *much* faster

for sm,cubeA,cubeB,objects in zip(("","_smooth",),
                                  (cube303,cube303sm,),
                                  (cube321,cube321sm,),
                                  (dend,dendsm,),):

    # reset data
    tcubedata = np.empty(cubeA.shape)
    tcubedata[:] = np.nan
    rcubedata = np.empty(cubeA.shape)
    rcubedata[:] = np.nan

    pb = ProgressBar(len(objects))
    for ii,structure in enumerate(objects):
        dend_obj_mask = BooleanArrayMask(structure.get_mask(), wcs=cubeA.wcs)
        view = cubeA.subcube_slices_from_mask(dend_obj_mask)
        submask = dend_obj_mask[view]
        assert submask.include().sum() == dend_obj_mask.include().sum()

        c303 = cubeA[view].with_mask(submask)
        c321 = cubeB[view].with_mask(submask)

        npix = submask.include().sum()
        Stot303 = c303.sum().value
        Stot321 = c321.sum().value
        if npix == 0:
            raise ValueError("npix=0. This is impossible.")
        Smean303 = Stot303/npix
        Smean321 = Stot321/npix
        try:
            logabundance=logabundance,
            elogabundance=elogabundance,
            taline303=ta303.value,
            etaline303=err,
            taline321=ta321.value,
            etaline321=err,
            linewidth=linewidth)
        row_data = mf.get_parconstraints()
        tcube[z, y, x] = row_data['temperature_chi2']
        row_data['ratio303321'] = rat
        row_data['eratio303321'] = erat

        if ii % 100 == 0 or ii < 50:
            log.info(
                "T: [{tmin1sig_chi2:7.2f},{temperature_chi2:7.2f},{tmax1sig_chi2:7.2f}]  R={ratio303321:6.2f}+/-{eratio303321:6.2f}"
                .format(**row_data))
        else:
            pb.update(ii)
        tcube.flush()
    else:
        pb.update(ii)

tcube[tcube == 0] = np.nan
tCube = SpectralCube(tcube,
                     cube303.wcs,
                     mask=BooleanArrayMask(np.isfinite(tcube),
                                           wcs=cube303.wcs))
tCube.write(hpath('chi2_temperature_cube.fits'), overwrite=True)

print()
Exemple #14
0
def test_scalegen():

    cube = SpectralCube(data, wcs.WCS(h),
                        mask=BooleanArrayMask(mask, wcs=wcs.WCS(h)))
    noiseobj = noise.Noise(cube)
    assert np.isclose(noiseobj.scale, 1.1382529312849043)
Exemple #15
0
from pvextractor import extract_pv_slice
from pvextractor.geometry import Path
from spectral_cube import SpectralCube, BooleanArrayMask
from astropy.io import fits
from astropy.wcs import WCS
import numpy as np
import matplotlib.pyplot as p

# Start with the full COMPLETE Perseus cube
# Missing end card in the header, so we have to manually open it

hdu = fits.open(
    "/srv/astro/erickoch/enzo_sims/complete/PerA_13coFCRAO_F_xyv.fits",
    ignore_missing_end=True)

mask = BooleanArrayMask(mask=np.isfinite(hdu[0].data), wcs=WCS(hdu[0].header))

sc = SpectralCube(data=hdu[0].data, wcs=WCS(hdu[0].header), mask=mask)

# Select the region of interest
sc_small = sc[120:300, 156:346, 677:958]

# Ends for the PV slice
# ends = [(107, 74), (151, 76), (220, 54)]
ends = [(105, 70), (145, 80), (227, 28), (238, 1)]

xy = Path(ends, width=10)

pv = extract_pv_slice(sc_small, xy)

p.subplot(121)
Exemple #16
0
    return mask_array


cube303 = SpectralCube.read(
    hpath('APEX_H2CO_303_202_bl.fits')).with_spectral_unit(
        u.km / u.s, velocity_convention='radio')
cube321 = SpectralCube.read(
    hpath('APEX_H2CO_321_220_bl.fits')).with_spectral_unit(
        u.km / u.s, velocity_convention='radio')
maskarr = mask_out_region(
    fits.getdata(hpath('APEX_H2CO_303_202_bl_mask.fits')).astype('bool'),
    cube303)
mask = (maskarr & cube303.mask.include(cube303, cube303.wcs)
        & cube321.mask.include(cube321, cube321.wcs))
bmask = BooleanArrayMask(mask, cube303.wcs)
cube303m = cube303.with_mask(bmask)
cube321m = cube321.with_mask(bmask)

cube303sm = SpectralCube.read(
    hpath('APEX_H2CO_303_202_smooth_bl.fits')).with_spectral_unit(
        u.km / u.s, velocity_convention='radio')
cube321sm = SpectralCube.read(
    hpath('APEX_H2CO_321_220_smooth_bl.fits')).with_spectral_unit(
        u.km / u.s, velocity_convention='radio')
smmaskarr = mask_out_region(
    fits.getdata(
        hpath('APEX_H2CO_303_202_smooth_bl_mask.fits')).astype('bool'),
    cube303sm)
masksm = (smmaskarr & cube303sm.mask.include(cube303sm, cube303sm.wcs)
          & cube321sm.mask.include(cube321sm, cube321sm.wcs))
Exemple #17
0

    # ---------------- #
    # Build the masks. #
    # ---------------- #
    # The masked data and their corresponding masks are returned as dictionaries.
    # Mask where NaNs are TRUE
    trueMask = np.ma.masked_where(data==0,data)
    # Mask where NaNs are FALSE
    falseMask = np.ma.masked_where(data!=0,data)
    # Mask the profile range. NaNs are TRUE
    profileMask = maskProfile(data=trueMask,xarr=vels,
                              minProfIdx=minProfIdx,maxProfIdx=maxProfIdx)
    # Build mask with a WCS that is compatible with SpectralCube.
    # NaNs are FALSE.
    cubeMask = BooleanArrayMask(np.ma.getmask(falseMask),pacsWcs)

    if nFluxes > 350:
        mid = 200
    else:
        mid = 100


    # Make an array of coordinates for the valid spaxels
    validPixels = findValidPixels((nCols,nRows),np.ma.getmask(trueMask[mid,:,:]))


    # --------------------------------------------------- #
    # Find the (col,row) min/max limits of valid spaxels. #
    # Min/max will be used to crop the data and the WCS.  #
    # --------------------------------------------------- #
Exemple #18
0
def load_casa_image(filename,
                    skipdata=False,
                    skipvalid=False,
                    skipcs=False,
                    **kwargs):
    """
    Load a cube (into memory?) from a CASA image. By default it will transpose
    the cube into a 'python' order and drop degenerate axes. These options can
    be suppressed. The object holds the coordsys object from the image in
    memory.
    """

    try:
        from taskinit import ia
    except ImportError:
        raise ImportError(
            "Could not import CASA (casac) and therefore cannot read CASA .image files"
        )

    # use the ia tool to get the file contents
    ia.open(filename)

    # read in the data
    if not skipdata:
        data = ia.getchunk()

    # CASA stores validity of data as a mask
    if not skipvalid:
        valid = ia.getchunk(getmask=True)

    # transpose is dealt with within the cube object

    # read in coordinate system object
    casa_cs = ia.coordsys()

    wcs = wcs_casa2astropy(casa_cs)

    # don't need this yet
    # stokes = get_casa_axis(temp_cs, wanttype="Stokes", skipdeg=False,)

    #    if stokes == None:
    #        order = np.arange(self.data.ndim)
    #    else:
    #        order = []
    #        for ax in np.arange(self.data.ndim+1):
    #            if ax == stokes:
    #                continue
    #            order.append(ax)

    #    self.casa_cs = ia.coordsys(order)

    # This should work, but coordsys.reorder() has a bug
    # on the error checking. JIRA filed. Until then the
    # axes will be reversed from the original.

    # if transpose == True:
    #    new_order = np.arange(self.data.ndim)
    #    new_order = new_order[-1*np.arange(self.data.ndim)-1]
    #    print new_order
    #    self.casa_cs.reorder(new_order)

    # close the ia tool
    ia.close()

    meta = {'filename': filename}

    mask = BooleanArrayMask(wcs, np.logical_not(valid))
    cube = SpectralCube(data, wcs, mask, meta=meta)

    return cube
Exemple #19
0
noisehdr = fits.getheader(noise_fn)

sm_noise = fits.getdata(
    mpath('APEX_H2CO_merge_high_plait_all_smooth_noise.fits'))
sm_noise[nhits < 20] = np.nan
sm_noise_cube = as_strided(sm_noise,
                           shape=cube303msm.shape,
                           strides=(0, ) + sm_noise.strides)

# Cubes masked with noise cube == OK
# (can I make this lazier?)
noisefinite = np.isfinite(noise)  # stride length changes for bools?
sm_noisefinite = np.isfinite(sm_noise)
cube303nm = cube303.with_mask(
    BooleanArrayMask(
        as_strided(noisefinite,
                   shape=cube303.shape,
                   strides=(0, ) + noisefinite.strides), cube303.wcs))
cube303nmsm = cube303sm.with_mask(
    BooleanArrayMask(
        as_strided(sm_noisefinite,
                   shape=cube303sm.shape,
                   strides=(0, ) + sm_noisefinite.strides), cube303sm.wcs))

cube321nm = cube321.with_mask(
    BooleanArrayMask(
        as_strided(noisefinite,
                   shape=cube321.shape,
                   strides=(0, ) + noisefinite.strides), cube321.wcs))
cube321nmsm = cube321sm.with_mask(
    BooleanArrayMask(
        as_strided(sm_noisefinite,
im2 = fits.getdata(hpath('H2CO_321220_to_303202_bl_integ_temperature_dens1e4.fits'))
im3 = fits.getdata(hpath('H2CO_321220_to_303202_bl_integ_weighted_temperature_dens1e4_masked.fits'))

tcube = tcube_direct
tcube_mean = tcube.mean(axis=0)

wcube = SpectralCube.read(hpath('APEX_H2CO_303_202_bl.fits'))
mcube = SpectralCube.read(hpath('APEX_H2CO_303_202_bl_mask.fits'))

if tcube.shape != wcube.shape:
    raise

weighted = copy.copy(tcube)
weighted._data = wcube._data * tcube._data
mask = (wcube.mask & tcube.mask &
        BooleanArrayMask(weighted.filled_data[...] != 0, weighted.wcs) &
        BooleanArrayMask(wcube.filled_data[...] != 0, wcube.wcs) &
        BooleanArrayMask(mcube._data==1, mcube.wcs)
       )
weighted = weighted.with_mask(mask)
wcube = wcube.with_mask(mask)

tcube_wmean = tcube.mean(axis=0)

pl.figure(14, figsize=(12,20)).clf()
pl.subplot(5,1,1).imshow(im1)
pl.subplot(5,1,2).imshow(im2)
pl.subplot(5,1,3).imshow(im3)
pl.subplot(5,1,4).imshow(tcube_mean.value)
pl.subplot(5,1,5).imshow(tcube_wmean.value)
#                          .with_spectral_unit(u.km/u.s,
#                                              velocity_convention='radio',
#                                              rest_value=restfreqs[mol])
#         for mol in molecules}
cubes = {
    mol: SpectralCube.read(
        'feathered/Feathered_{0}.fits'.format(mol)).with_spectral_unit(
            u.km / u.s, velocity_convention='radio',
            rest_value=restfreqs[mol]).spectral_slab(-20 * u.km / u.s,
                                                     137 * u.km / u.s)
    for mol in molecules
}
hc3nmean = cubes['HC3N'].mean(axis=(1, 2))
bad = np.abs(hc3nmean) > 1
mhc3n = cubes['HC3N'].with_mask(
    BooleanArrayMask(~bad[:, None, None], cubes['HC3N'].wcs))
cubes['HC3N'] = mhc3n
for cube in cubes.values():
    cube._data -= cube.mean(axis=0).value

ytcubes = {mol: cubes[mol][::2, ::2, ::2].to_yt() for mol in molecules}

for ytc in ytcubes.values():
    ytc.dataset.periodicity = (True, ) * 3

try:
    os.mkdir("IsoSurfs")
except:
    pass

#for ii,(level,transparency) in enumerate(zip((2, 3, 4), (0.1,0.3,0.6))):
Exemple #22
0
molecules = ('HNC','HC3N','HCOp','HCN',)
molecules = ('HC3N',)

colors = {'HNC': red,
          'HCN': green,
          'HC3N': brown,
          'HCOp': blue,
         }

cubes = {mol: SpectralCube.read('Feathered_{0}.fits'.format(mol))
                          .with_spectral_unit(u.km/u.s,
                                              velocity_convention='radio')
         for mol in molecules}
hc3nmean = cubes['HC3N'].mean(axis=(1,2))
bad = np.abs(hc3nmean)>1
mh3cn = cubes['HC3N'].with_mask(BooleanArrayMask(bad[:,None,None],
                                                 cubes['HC3N'].wcs))
cubes['HC3N'] = mh3cn

ytcubes = {mol: cubes[mol].to_yt() for mol in molecules}

try:
    os.mkdir("ChemMovie")
except:
    pass

def ramp(vals, minval, maxval):
    v = (vals)**0.25
    return (v - v.min())/(v.max() - v.min())

nframes = 60
size = 512
    print(fn, cube)
    m0 = cube.moment0(axis=0)
    max = cube.max(axis=0)
    m0.hdu.writeto('moment0/{0}_moment0.fits'.format(pfx), clobber=True)
    max.hdu.writeto('max/{0}_max.fits'.format(pfx), clobber=True)

    std = cube.std(axis=0)
    mask = cube > std
    mcube = cube.with_mask(mask)
    m0mask = mcube.moment0(axis=0)
    m1mask = mcube.moment1(axis=0)
    m0mask.hdu.writeto('moment0/{0}_moment0_mask.fits'.format(pfx),
                       clobber=True)
    m1mask.hdu.writeto('moment1/{0}_moment1_mask.fits'.format(pfx),
                       clobber=True)

    if False:
        rendermask_arr = std.value < np.percentile(std.ravel(), 75)
        rendermask = BooleanArrayMask(rendermask_arr, mcube.wcs, mcube.shape)
        rcube = mcube.with_mask(rendermask).minimal_subcube()
        print("Minimal rendering cube: ", fn, rcube)
        ytc = rcube.to_yt()
        ytc.quick_isocontour(
            level=3 * np.nanmean(std.value),
            title='Sgr B2 12mTC {0}'.format(pfx),
            description='ALMA observations of Sgr B2.  File {0}'.format(pfx),
            filename=pfx + ".ply")

        del mask
        del cube
    def to_object(self, data_or_subset, attribute=None):
        """
        Convert a glue Data object to a SpectralCube object.

        Parameters
        ----------
        data_or_subset : `glue.core.data.Data` or `glue.core.subset.Subset`
            The data to convert to a SpectralCube object
        attribute : `glue.core.component_id.ComponentID`
            The attribute to use for the SpectralCube data
        """

        if data_or_subset.ndim > 0 and data_or_subset.ndim != 3 and data_or_subset.ndim != 4:
            raise ValueError('Data object should have 3 or 4 dimensions in order to '
                             'be converted to a SpectralCube object.')

        if isinstance(data_or_subset, Subset):
            data = data_or_subset.data
            subset_state = data_or_subset.subset_state
        else:
            data = data_or_subset
            subset_state = None

        if isinstance(data.coords, BaseLowLevelWCS):
            wcs = data.coords
        else:
            raise TypeError('data.coords should be an instance of BaseLowLevelWCS.')

        if isinstance(attribute, str):
            attribute = data.id[attribute]
        elif len(data.main_components) == 0:
            raise ValueError('Data object has no attributes.')
        elif attribute is None:
            if len(data.main_components) == 1:
                attribute = data.main_components[0]
            else:
                raise ValueError("Data object has more than one attribute, so "
                                 "you will need to specify which one to use as "
                                 "the flux for the spectral cube using the "
                                 "attribute= keyword argument.")

        component = data.get_component(attribute)

        values = data.get_data(attribute)
        if subset_state is None:
            mask = None
        else:
            mask = data.get_mask(subset_state=subset_state)
            values = values.copy()
            mask = BooleanArrayMask(mask, wcs=wcs)

        values = values * u.Unit(component.units)

        # Drop Stokes axis if there is one for FITS WCS
        if isinstance(wcs, WCS) and wcs.sub([WCSSUB_STOKES]).naxis > 0:
            types = [axistype['coordinate_type'] for axistype in wcs.get_axis_types()]
            # For now we only ever get the first stokes element. We could in
            # principle allow this to be customized, or return a StokesSpectralCube
            slc = tuple([0 if tp == 'stokes' else slice(None) for tp in types])
            subkeep = tuple([index + 1 for index, tp in enumerate(types) if tp != 'stokes'])
            values = values[slc[::-1]]
            wcs = wcs.sub(subkeep)

        return SpectralCube(values, mask=mask, wcs=wcs, meta=data.meta)
    ),
    (
        dend,
        dendsm,
    ),
):

    # reset data
    tcubedata = np.empty(cubeA.shape)
    tcubedata[:] = np.nan
    rcubedata = np.empty(cubeA.shape)
    rcubedata[:] = np.nan

    pb = ProgressBar(len(objects))
    for ii, structure in enumerate(objects):
        dend_obj_mask = BooleanArrayMask(structure.get_mask(), wcs=cubeA.wcs)
        view = cubeA.subcube_slices_from_mask(dend_obj_mask)
        submask = dend_obj_mask[view]
        assert submask.include().sum() == dend_obj_mask.include().sum()

        c303 = cubeA[view].with_mask(submask)
        c321 = cubeB[view].with_mask(submask)

        npix = submask.include().sum()
        Stot303 = c303.sum().value
        Stot321 = c321.sum().value
        if npix == 0:
            raise ValueError("npix=0. This is impossible.")
        Smean303 = Stot303 / npix
        Smean321 = Stot321 / npix
        try:
def measure_dendrogram_properties(dend=None,
                                  cube303=cube303,
                                  cube321=cube321,
                                  cube13co=cube13co,
                                  cube18co=cube18co,
                                  noise_cube=noise_cube,
                                  sncube=sncube,
                                  suffix="",
                                  last_index=None,
                                  plot_some=True,
                                  line='303',
                                  write=True):

    assert (cube321.shape == cube303.shape == noise_cube.shape ==
            cube13co.shape == cube18co.shape == sncube.shape)
    assert sncube.wcs is cube303.wcs is sncube.mask._wcs

    metadata = {}
    metadata['data_unit'] = u.K
    metadata['spatial_scale'] = 7.2 * u.arcsec
    metadata['beam_major'] = 30 * u.arcsec
    metadata['beam_minor'] = 30 * u.arcsec
    metadata['wavelength'] = 218.22219 * u.GHz
    metadata['velocity_scale'] = u.km / u.s
    metadata['wcs'] = cube303.wcs

    keys = [
        'density_chi2',
        'expected_density',
        'dmin1sig_chi2',
        'dmax1sig_chi2',
        'column_chi2',
        'expected_column',
        'cmin1sig_chi2',
        'cmax1sig_chi2',
        'temperature_chi2',
        'expected_temperature',
        'tmin1sig_chi2',
        'tmax1sig_chi2',
        'eratio321303',
        'ratio321303',
        'logh2column',
        'elogh2column',
        'logabundance',
        'elogabundance',
    ]
    obs_keys = [
        'Stot303',
        'Smin303',
        'Smax303',
        'Stot321',
        'Smean303',
        'Smean321',
        'npix',
        'e303',
        'e321',
        'r321303',
        'er321303',
        '13cosum',
        'c18osum',
        '13comean',
        'c18omean',
        's_ntotal',
        'index',
        'is_leaf',
        'parent',
        'root',
        'lon',
        'lat',
        'vcen',
        'higaldusttem',
        'reff',
        'dustmass',
        'dustmindens',
        'bad',
        #'tkin_turb',
    ]
    columns = {k: [] for k in (keys + obs_keys)}

    log.debug("Initializing dendrogram temperature fitting loop")

    # FORCE wcs to match
    # (technically should reproject here)
    cube13co._wcs = cube18co._wcs = cube303.wcs
    cube13co.mask._wcs = cube18co.mask._wcs = cube303.wcs

    if line == '303':
        maincube = cube303
    elif line == '321':
        maincube = cube321
    else:
        raise ValueError("Unrecognized line: {0}".format(line))

    # Prepare an array to hold the fitted temperatures
    tcubedata = np.empty(maincube.shape, dtype='float32')
    tcubedata[:] = np.nan
    tcubeleafdata = np.empty(maincube.shape, dtype='float32')
    tcubeleafdata[:] = np.nan

    nbad = 0

    catalog = ppv_catalog(dend, metadata)
    pb = ProgressBar(len(catalog))
    for ii, row in enumerate(catalog):
        structure = dend[row['_idx']]
        assert structure.idx == row['_idx'] == ii
        dend_obj_mask = BooleanArrayMask(structure.get_mask(), wcs=cube303.wcs)
        dend_inds = structure.indices()

        view = (
            slice(dend_inds[0].min(), dend_inds[0].max() + 1),
            slice(dend_inds[1].min(), dend_inds[1].max() + 1),
            slice(dend_inds[2].min(), dend_inds[2].max() + 1),
        )
        #view2 = cube303.subcube_slices_from_mask(dend_obj_mask)
        submask = dend_obj_mask[view]
        #assert np.count_nonzero(submask.include()) == np.count_nonzero(dend_obj_mask.include())

        sn = sncube[view].with_mask(submask)
        sntot = sn.sum().value
        #np.testing.assert_almost_equal(sntot, structure.values().sum(), decimal=0)

        c303 = cube303[view].with_mask(submask)
        c321 = cube321[view].with_mask(submask)
        co13sum = cube13co[view].with_mask(submask).sum().value
        co18sum = cube18co[view].with_mask(submask).sum().value
        if hasattr(co13sum, '__len__'):
            raise TypeError(
                ".sum() applied to an array has yielded a non scalar.")

        npix = submask.include().sum()
        assert npix == structure.get_npix()
        Stot303 = c303.sum().value
        if np.isnan(Stot303):
            raise ValueError("NaN in cube.  This can't happen: the data from "
                             "which the dendrogram was derived can't have "
                             "NaN pixels.")
        Smax303 = c303.max().value
        Smin303 = c303.min().value

        Stot321 = c321.sum().value
        if npix == 0:
            raise ValueError("npix=0. This is impossible.")
        Smean303 = Stot303 / npix
        if Stot303 <= 0 and line == '303':
            raise ValueError(
                "The 303 flux is <=0.  This isn't possible because "
                "the dendrogram was derived from the 303 data with a "
                "non-zero threshold.")
        elif Stot303 <= 0 and line == '321':
            Stot303 = 0
            Smean303 = 0
        elif Stot321 <= 0 and line == '321':
            raise ValueError(
                "The 321 flux is <=0.  This isn't possible because "
                "the dendrogram was derived from the 321 data with a "
                "non-zero threshold.")
        if np.isnan(Stot321):
            raise ValueError("NaN in 321 line")
        Smean321 = Stot321 / npix

        #error = (noise_cube[view][submask.include()]).sum() / submask.include().sum()**0.5
        var = ((noise_cube[dend_obj_mask.include()]**2).sum() / npix**2)
        error = var**0.5
        if np.isnan(error):
            raise ValueError("error is nan: this is impossible by definition.")

        if line == '321' and Stot303 == 0:
            r321303 = np.nan
            er321303 = np.nan
        elif Stot321 < 0:
            r321303 = error / Smean303
            er321303 = (r321303**2 * (var / Smean303**2 + 1))**0.5
        else:
            r321303 = Stot321 / Stot303
            er321303 = (r321303**2 *
                        (var / Smean303**2 + var / Smean321**2))**0.5

        for c in columns:
            assert len(columns[c]) == ii

        columns['index'].append(row['_idx'])
        columns['s_ntotal'].append(sntot)
        columns['Stot303'].append(Stot303)
        columns['Smax303'].append(Smax303)
        columns['Smin303'].append(Smin303)
        columns['Stot321'].append(Stot321)
        columns['Smean303'].append(Smean303)
        columns['Smean321'].append(Smean321)
        columns['npix'].append(npix)
        columns['e303'].append(error)
        columns['e321'].append(error)
        columns['r321303'].append(r321303)
        columns['er321303'].append(er321303)
        columns['13cosum'].append(co13sum)
        columns['c18osum'].append(co18sum)
        columns['13comean'].append(co13sum / npix)
        columns['c18omean'].append(co18sum / npix)
        columns['is_leaf'].append(structure.is_leaf)
        columns['parent'].append(
            structure.parent.idx if structure.parent else -1)
        columns['root'].append(get_root(structure).idx)
        s_main = maincube._data[dend_inds]
        x, y, z = maincube.world[dend_inds]
        lon = ((z.value - (360 *
                           (z.value > 180))) * s_main).sum() / s_main.sum()
        lat = (y * s_main).sum() / s_main.sum()
        vel = (x * s_main).sum() / s_main.sum()
        columns['lon'].append(lon)
        columns['lat'].append(lat.value)
        columns['vcen'].append(vel.value)

        mask2d = dend_obj_mask.include().max(axis=0)[view[1:]]
        logh2column = np.log10(
            np.nanmean(column_regridded.data[view[1:]][mask2d]) * 1e22)
        if np.isnan(logh2column):
            log.info("Source #{0} has NaNs".format(ii))
            logh2column = 24
        elogh2column = elogabundance
        columns['higaldusttem'].append(
            np.nanmean(dusttem_regridded.data[view[1:]][mask2d]))

        r_arcsec = row['radius'] * u.arcsec
        reff = (r_arcsec * (8.5 * u.kpc)).to(u.pc, u.dimensionless_angles())
        mass = ((10**logh2column * u.cm**-2) * np.pi * reff**2 * 2.8 *
                constants.m_p).to(u.M_sun)
        density = (mass / (4 / 3. * np.pi * reff**3) / constants.m_p / 2.8).to(
            u.cm**-3)

        columns['reff'].append(reff.value)
        columns['dustmass'].append(mass.value)
        columns['dustmindens'].append(density.value)
        mindens = np.log10(density.value)
        if mindens < 3:
            mindens = 3

        if (r321303 < 0 or np.isnan(r321303)) and line != '321':
            raise ValueError("Ratio <0: This can't happen any more because "
                             "if either num/denom is <0, an exception is "
                             "raised earlier")
            #for k in columns:
            #    if k not in obs_keys:
            #        columns[k].append(np.nan)
        elif (r321303 < 0 or np.isnan(r321303)) and line == '321':
            for k in keys:
                columns[k].append(np.nan)
        else:
            # Replace negatives for fitting
            if Smean321 <= 0:
                Smean321 = error
            mf.set_constraints(
                ratio321303=r321303,
                eratio321303=er321303,
                #ratio321322=ratio2, eratio321322=eratio2,
                logh2column=logh2column,
                elogh2column=elogh2column,
                logabundance=logabundance,
                elogabundance=elogabundance,
                taline303=Smean303,
                etaline303=error,
                taline321=Smean321,
                etaline321=error,
                mindens=mindens,
                linewidth=10)
            row_data = mf.get_parconstraints()
            row_data['ratio321303'] = r321303
            row_data['eratio321303'] = er321303

            for k in row_data:
                columns[k].append(row_data[k])

            # Exclude bad velocities from cubes
            if row['v_cen'] < -80e3 or row['v_cen'] > 180e3:
                # Skip: there is no real structure down here
                nbad += 1
                is_bad = True
            else:
                is_bad = False
                tcubedata[
                    dend_obj_mask.include()] = row_data['expected_temperature']
                if structure.is_leaf:
                    tcubeleafdata[dend_obj_mask.include(
                    )] = row_data['expected_temperature']

            columns['bad'].append(is_bad)

            width = row['v_rms'] * u.km / u.s
            lengthscale = reff

            #REMOVED in favor of despotic version done in dendrograms.py
            # we use the analytic version here; the despotic version is
            # computed elsewhere (with appropriate gcor factors)
            #columns['tkin_turb'].append(heating.tkin_all(10**row_data['density_chi2']*u.cm**-3,
            #                                             width,
            #                                             lengthscale,
            #                                             width/lengthscale,
            #                                             columns['higaldusttem'][-1]*u.K,
            #                                             crir=0./u.s))

        if len(set(len(c) for k, c in columns.items())) != 1:
            print("Columns are different lengths.  This is not allowed.")
            import ipdb
            ipdb.set_trace()

        for c in columns:
            assert len(columns[c]) == ii + 1

        if plot_some and not is_bad and (ii - nbad % 100 == 0
                                         or ii - nbad < 50):
            try:
                log.info(
                    "T: [{tmin1sig_chi2:7.2f},{expected_temperature:7.2f},{tmax1sig_chi2:7.2f}]"
                    "  R={ratio321303:8.4f}+/-{eratio321303:8.4f}"
                    "  Smean303={Smean303:8.4f} +/- {e303:8.4f}"
                    "  Stot303={Stot303:8.2e}  npix={npix:6d}".format(
                        Smean303=Smean303,
                        Stot303=Stot303,
                        npix=npix,
                        e303=error,
                        **row_data))

                pl.figure(1)
                pl.clf()
                mf.denstemplot()
                pl.savefig(
                    fpath("dendrotem/diagnostics/{0}_{1}.png".format(
                        suffix, ii)))
                pl.figure(2).clf()
                mf.parplot1d_all(levels=[0.68268949213708585])
                pl.savefig(
                    fpath("dendrotem/diagnostics/1dplot{0}_{1}.png".format(
                        suffix, ii)))
                pl.draw()
                pl.show()
            except Exception as ex:
                print ex
                pass
        else:
            pb.update(ii + 1)

        if last_index is not None and ii >= last_index:
            break

    if last_index is not None:
        catalog = catalog[:last_index + 1]

    for k in columns:
        if k not in catalog.keys():
            catalog.add_column(table.Column(name=k, data=columns[k]))

    for mid, lo, hi, letter in (('expected_temperature', 'tmin1sig_chi2',
                                 'tmax1sig_chi2', 't'),
                                ('expected_density', 'dmin1sig_chi2',
                                 'dmax1sig_chi2', 'd'),
                                ('expected_column', 'cmin1sig_chi2',
                                 'cmax1sig_chi2', 'c')):
        catalog.add_column(
            table.Column(name='elo_' + letter,
                         data=catalog[mid] - catalog[lo]))
        catalog.add_column(
            table.Column(name='ehi_' + letter,
                         data=catalog[hi] - catalog[mid]))

    if write:
        catalog.write(tpath('PPV_H2CO_Temperature{0}.ipac'.format(suffix)),
                      format='ascii.ipac')

    # Note that there are overlaps in the catalog, which means that ORDER MATTERS
    # in the above loop.  I haven't yet checked whether large scale overwrites
    # small or vice-versa; it may be that both views of the data are interesting.
    tcube = SpectralCube(
        data=tcubedata,
        wcs=cube303.wcs,
        mask=cube303.mask,
        meta={'unit': 'K'},
        header=cube303.header,
    )
    tcubeleaf = SpectralCube(
        data=tcubeleafdata,
        wcs=cube303.wcs,
        mask=cube303.mask,
        meta={'unit': 'K'},
        header=cube303.header,
    )

    if write:
        log.info("Writing TemperatureCube")
        outpath = 'TemperatureCube_DendrogramObjects{0}.fits'
        tcube.write(hpath(outpath.format(suffix)), overwrite=True)

        outpath_leaf = 'TemperatureCube_DendrogramObjects{0}_leaves.fits'
        tcubeleaf.write(hpath(outpath_leaf.format(suffix)), overwrite=True)

    return catalog, tcube
Exemple #27
0
    # ---------------- #
    # Build the masks. #
    # ---------------- #
    # The masked data and their corresponding masks are returned as dictionaries.
    # Mask where NaNs are TRUE
    trueMask = maskTrue(data=data)
    # Mask where NaNs are FALSE
    falseMask = maskFalse(data=data)
    # Mask the profile range. NaNs are TRUE
    profileMask = maskProfile(data=trueMask['maskedData'],
                              xarr=vels,
                              minProfIdx=minProfIdx,
                              maxProfIdx=maxProfIdx)
    # Build mask with a WCS that is compatible with SpectralCube.
    # NaNs are FALSE.
    cubeMask = BooleanArrayMask(falseMask['mask'], pacsWcs)

    # Make an array of coordinates for the valid spaxels
    validPixels = findValidPixels((nCols, nRows), trueMask['mask'][0, :, :])

    # --------------------------------------------------- #
    # Find the (col,row) min/max limits of valid spaxels. #
    # Min/max will be used to crop the data and the WCS.  #
    # --------------------------------------------------- #
    wcsMinMax = pixMinMax(validPixels)

    # ------------------------------------------------------------- #
    # Fit the continuum with a polynomial and subtract from fluxes. #
    # ------------------------------------------------------------- #
    # The edges of the spectrum and the velocity region
    # of the line profile is masked as TRUE. Data which
noise_flat = noise_cube[mask]
var_flat = noise_flat**2

ratio303321 = cube321m.flattened().value / cube303m.flattened().value
eratio303321 = ((ratio303321**2 *
                 (var_flat / cube303m.flattened().value**2 +
                  var_flat / cube321m.flattened().value**2))**0.5)
ratioOK = ratio303321 > eratio303321 * 1
#ratioOK = cube303m.mask.include()

data = np.zeros(cube303m.shape, dtype='float32') * np.nan
mask[mask] = ratioOK
data[mask] = ratio303321[ratioOK]
ratiocube_303321 = SpectralCube(data,
                                mask=BooleanArrayMask(np.isfinite(data),
                                                      wcs=cube303m.wcs),
                                wcs=cube303m.wcs)

noise_flat_sm = sm_noise_cube[masksm]
var_flat_sm = noise_flat_sm**2

ratio303321sm = cube321msm.flattened().value / cube303msm.flattened().value
eratio303321sm = ((ratio303321sm**2 *
                   (var_flat_sm / cube303msm.flattened().value**2 +
                    var_flat_sm / cube321msm.flattened().value**2))**0.5)
ratioOKsm = ratio303321sm > eratio303321sm * 1
#ratioOKsm = cube303msm.mask.include()

datasm = np.zeros(cube303msm.shape, dtype='float32') * np.nan
masksm[masksm] = ratioOKsm
datasm[masksm] = ratio303321sm[ratioOKsm]
Exemple #29
0
         ratiocube_303321, ratiocubesm_303321),
        ('dend', 'dendsm', 'direct', 'directsm', 'ratio', 'ratiosm')):

        log.info("Starting {0} {1}".format(name, weight))

        mask = (cube303sm > 0.2 if 'sm' in name else cube303 > 0.3)

        if weight:
            wcube = (cube303msm if 'sm' in name else cube303m)
            if tcube.shape != wcube.shape:
                log.info("Not weighting {0}".format(fn))
                continue

            weighted = copy.copy(tcube).with_mask(mask)
            weighted._data = wcube._data * tcube._data
            mask = (wcube.mask & tcube.mask & mask & BooleanArrayMask(
                weighted.filled_data[...] != 0, weighted.wcs)
                    & BooleanArrayMask(wcube.filled_data[...] != 0, wcube.wcs))
            wcube = wcube.with_mask(mask)
            pv1 = weighted.sum(axis=1)
            pv2 = wcube.sum(axis=1)
            pv = pv1 / pv2
            bmean = pv.value
        else:
            bmean = tcube.with_mask(mask).mean(axis=1)

        ds = 10 if 'sm' in name else 20

        tcube_ds = tcube[::ds, :, :]  # for the WCS
        tcube_ds.data = downsample.downsample_axis(tcube._data, ds, axis=0)

        bmeands = downsample.downsample_axis(bmean, ds, axis=0)