Example #1
0
def deconvolve_moments(moments, beam, pa, pixscale):
    if moments['rmsx_ex'] >= moments['rmsy_ex']:
        beam_ex = Beam(major=moments['rmsx_ex'] * pixscale * sig2fwhm,
                       minor=moments['rmsy_ex'] * pixscale * sig2fwhm,
                       pa=pa * u.rad)
    else:
        beam_ex = Beam(major=moments['rmsy_ex'] * pixscale * sig2fwhm,
                       minor=moments['rmsx_ex'] * pixscale * sig2fwhm,
                       pa=(pa + np.pi / 2) * u.rad)
    beam_ex_dc = beam_ex.deconvolve(beam, failure_returns_pointlike=True)

    if moments['rmsx_noex'] >= moments['rmsy_noex']:
        beam_noex = Beam(major=moments['rmsx_noex'] * pixscale * sig2fwhm,
                         minor=moments['rmsy_noex'] * pixscale * sig2fwhm,
                         pa=pa * u.rad)
    else:
        beam_noex = Beam(major=moments['rmsy_noex'] * pixscale * sig2fwhm,
                         minor=moments['rmsx_noex'] * pixscale * sig2fwhm,
                         pa=(pa + np.pi / 2) * u.rad)
    beam_noex_dc = beam_noex.deconvolve(beam, failure_returns_pointlike=True)

    outdict = {}
    outdict['rmsx_ex'] = (beam_ex_dc.major / pixscale / sig2fwhm).to(
        u.dimensionless_unscaled).value
    outdict['rmsy_ex'] = (beam_ex_dc.minor / pixscale / sig2fwhm).to(
        u.dimensionless_unscaled).value
    outdict['pa_ex'] = (beam_ex_dc.pa).to(u.rad).value
    outdict['rmsx_noex'] = (beam_noex.major / pixscale / sig2fwhm).to(
        u.dimensionless_unscaled).value
    outdict['rmsy_noex'] = (beam_noex.minor / pixscale / sig2fwhm).to(
        u.dimensionless_unscaled).value
    outdict['pa_noex'] = (beam_noex.pa).to(u.rad).value
    return (outdict)
Example #2
0
def main(args):
    hdul = fits.open(args.file_in, 'readonly')
    raw_img = np.squeeze(hdul[0].data)
    img_wcs = wcs.WCS(hdul[0].header)
    pixscale = wcs.utils.proj_plane_pixel_area(img_wcs.celestial)**0.5 * u.deg

    raw_beam = Beam(args.beam * u.arcmin)
    new_beam = Beam(args.cbeam * u.arcmin)
    cov_beam = new_beam.deconvolve(raw_beam)
    cov_kernel = cov_beam.as_kernel(pixscale)

    new_img = convolution.convolve_fft(raw_img,
                                       cov_kernel,
                                       normalize_kernel=True,
                                       allow_huge=True)
    print(new_img.shape)

    new_data = np.reshape(new_img, hdul[0].data.shape)

    print(new_data.shape)

    new_hdu = fits.PrimaryHDU(new_data)
    new_hdu.header = hdul[0].header.copy()
    new_hdu.header['NAXIS'] = 4
    new_hdu.writeto(args.fileout, overwrite=True)

    return 0
Example #3
0
def image_sz512as_pl1p5_fwhm2as_scale1as(tmp_path):

    pixel_scale = 1 * units.arcsec
    restfreq = 100 * units.GHz

    highres_major = 2 * units.arcsec

    # Generate input image
    input_hdu = generate_test_fits(imsize=512, powerlaw=1.5,
                                beamfwhm=highres_major,
                                pixel_scale=pixel_scale,
                                restfreq=restfreq,
                                brightness_unit=units.Jy / units.sr)

    input_fn = tmp_path / "input_image_sz512as_pl1.5_fwhm2as_scale1as.fits"
    input_hdu.writeto(input_fn, overwrite=True)

    input_proj = Projection.from_hdu(input_hdu).to(units.Jy / units.beam)

    # Make Interferometric image
    intf_data = interferometrically_observe_image(image=input_hdu.data,
                                                pixel_scale=pixel_scale,
                                                largest_angular_scale=40*units.arcsec,
                                                smallest_angular_scale=highres_major)[0].real
    intf_hdu = fits.PrimaryHDU(data=intf_data.value if hasattr(intf_data, "value") else intf_data,
                                header=input_hdu.header)
    intf_proj = Projection.from_hdu(intf_hdu).to(units.Jy / units.beam)
    intf_fn = tmp_path / "input_image_sz512as_pl1.5_fwhm2as_scale1as_intf2to40as.fits"
    intf_proj.write(intf_fn, overwrite=True)

    # Make SD image
    sd_header = input_hdu.header.copy()

    major = 15*units.arcsec
    # Eff SD diam (to compare with CASA in troubleshooting)

    sd_beam = Beam(major=major)
    sd_header.update(sd_beam.to_header_keywords())

    sd_fn = tmp_path / "input_image_sz512as_pl1.5_fwhm2as_scale1as_sd15as.fits"
    sd_data = singledish_observe_image(input_hdu.data,
                                    pixel_scale=pixel_scale,
                                    beam=sd_beam,
                                    boundary='wrap')

    sd_hdu = fits.PrimaryHDU(data=sd_data.value if hasattr(sd_data, "value") else sd_data,
                            header=sd_header)
    sd_hdu.header.update(sd_beam.to_header_keywords())
    sd_proj = Projection.from_hdu(sd_hdu).to(units.Jy / units.beam)
    sd_proj.write(sd_fn, overwrite=True)

    return tmp_path, input_fn, intf_fn, sd_fn
Example #4
0
def fixJialu(image, beam=15.0):
    '''
    Purpose: fix up Jialu's IC0342 cube so we can use it for analysis for DEGAS
    '''

    #12CO rest frequency
    rest_freq_12co = 115.27120180 * u.GHz

    f = fits.open(image)

    f[0].header['BUNIT'] = 'K'
    f[0].header['RESTFRQ'] = float(rest_freq_12co.to(u.Hz).value)

    f.writeto(image.replace('.fits', '_fixed.fits'), overwrite=True)

    image = image.replace('.fits', '_fixed.fits')

    # open image
    cube = SpectralCube.read(image)

    cube_kms = cube.with_spectral_unit(u.km / u.s)

    ## This should set header
    #cube_ms = cube.with_spectral_unit(u.m / u.s, rest_value=rest_freq_12co)

    # chop off bad edge
    subcube = cube_kms.subcube(xlo=0, xhi=134, ylo=0, yhi=150)

    # add beam
    beamcube = subcube.with_beam(Beam(8.0 * u.arcsec))

    # smooth
    newBeam = Beam(beam * u.arcsec)
    smoothCube = beamcube.convolve_to(newBeam)

    # smooth spectrally.
    smoothFactor = 3.0
    spSmoothCube = smoothCube.spectral_smooth(Box1DKernel(smoothFactor))
    spec_axis = spSmoothCube.spectral_axis
    chan_width = spec_axis[1] - spec_axis[
        0]  # channels are equally spaced in velocity
    new_axis = np.arange(spec_axis[0].value, spec_axis[-1].value,
                         smoothFactor * chan_width.value) * u.km / u.s

    interpCube = spSmoothCube.spectral_interpolate(
        new_axis, suppress_smooth_warning=False)

    # write out
    interpCube.write(image.replace('8arcsec_fixed.fits', '10kms_gauss15.fits'),
                     overwrite=True)
Example #5
0
def test_projection_attach_beam():

    exp_beam = Beam(1.0 * u.arcsec)
    newbeam = Beam(2.0 * u.arcsec)

    proj, hdu = load_projection("55.fits")

    new_proj = proj.with_beam(newbeam)

    assert proj.beam == exp_beam
    assert proj.meta['beam'] == exp_beam

    assert new_proj.beam == newbeam
    assert new_proj.meta['beam'] == newbeam
Example #6
0
def test_projection_from_hdu_with_beam(LDO, data):

    p = LDO(data, copy=False)

    hdu = p.hdu

    beam = Beam(1 * u.arcsec)
    hdu.header = beam.attach_to_header(hdu.header)

    p_new = LDO.from_hdu(hdu)

    assert (p == p_new).all()
    assert beam == p_new.meta['beam']
    assert beam == p_new.beam
def test_ldo_attach_beam(LDO, data):

    exp_beam = Beam(1.0 * u.arcsec)
    newbeam = Beam(2.0 * u.arcsec)

    p = LDO(data, copy=False, beam=exp_beam)

    new_p = p.with_beam(newbeam)

    assert p.beam == exp_beam
    assert p.meta['beam'] == exp_beam

    assert new_p.beam == newbeam
    assert new_p.meta['beam'] == newbeam
def jy_beam_MJy_sr(data, header):
    """Funtion which converts fits data into units of Jy/sr"""

    if header['BUNIT'] == 'Jy/beam':
        beam = Beam.from_fits_header(header)
        SB = ((data * u.Jy / u.beam).to(
            u.MJy / u.sr, equivalencies=u.beam_angular_area(beam))).value
    elif header['BUNIT'] == 'JY/BEAM':
        beam = Beam.from_fits_header(header)
        SB = ((data * u.Jy / u.beam).to(
            u.MJy / u.sr, equivalencies=u.beam_angular_area(beam))).value
    elif header['BUNIT'] == 'MJy/sr':
        SB = data

    return SB
Example #9
0
def fits_reconvolve_psf(fitsfile, newpsf, out=None):
    """ Convolve image with deconvolution of (newpsf, oldpsf) """
    newparams = newpsf.to_header_keywords()
    if out is None:
        logging.debug('fits_reconvolve: Overwriting file %s', fitsfile)
        out = fitsfile
    with fits.open(fitsfile) as hdul:
        hdr = hdul[0].header
        currentpsf = Beam.from_fits_header(hdr)
        if currentpsf != newpsf:
            kmaj1 = (currentpsf.major.to('deg').value/hdr['CDELT2'])
            kmin1 = (currentpsf.minor.to('deg').value/hdr['CDELT2'])
            kpa1 = currentpsf.pa.to('deg').value
            kmaj2 = (newpsf.major.to('deg').value/hdr['CDELT2'])
            kmin2 = (newpsf.minor.to('deg').value/hdr['CDELT2'])
            kpa2 = newpsf.pa.to('deg').value
            norm = newpsf.to_value() / currentpsf.to_value()
            if len(hdul[0].data.shape) == 4:
                conv_data = hdul[0].data[0,0,...]
            elif len(hdul[0].data.shape) == 2:
                conv_data = hdul[0].data
            # deconvolve with the old PSF
            # conv_data = convolve_gaussian_kernel(conv_data, kmaj1, kmin1, kpa1, inverse=True)
            # convolve to the new PSF
            conv_data = norm * reconvolve_gaussian_kernel(conv_data, kmaj1, kmin1, kpa1,
                                                                     kmaj2, kmin2, kpa2)

            if len(hdul[0].data.shape) == 4:
                hdul[0].data[0,0,...] = conv_data
            elif len(hdul[0].data.shape) == 2:
                hdul[0].data = conv_data
            hdr = newpsf.attach_to_header(hdr)
        fits.writeto(out, data=hdul[0].data, header=hdr, overwrite=True)
    return out
Example #10
0
def get_spatialsmooth(cube, res_t):
    """Spatailly smooth data

    Parameters
    ----------
    cube : spectral cube object
    res_t : float
        target *resolusion* (in arcsec)
        *not* channel width - do get_spectralregrid

    Returns
    -------
    smcube = Output cube containing the spatailly smoothed data and updated header
    """

    res_c = cube.header['BMAJ'] * 3600

    print("[INFO] Current resolution of %0.1f arcsec" % (res_c))
    print("[INFO] Target resolution of %0.1f arcsec" % (res_t))

    res_t_ = Beam(major=res_t * au.arcsec,
                  minor=res_t * au.arcsec,
                  pa=0 * au.deg)
    smcube = cube.convolve_to(res_t_)

    return smcube
def test_preserve_beam():

    cube, data = cube_and_raw('advs.fits')

    beam = Beam.from_fits_header(path("advs.fits"))

    assert cube.beam == beam
Example #12
0
def getimdata(cubenm, verbose=False):
    """Get fits image data
    """
    if verbose:
        print(f'Getting image data from {cubenm}')
    with fits.open(cubenm, memmap=True, mode='denywrite') as hdu:

        dxas = hdu[0].header['CDELT1'] * -1 * u.deg
        dyas = hdu[0].header['CDELT2'] * u.deg

        nx, ny = hdu[0].data[0,
                             0, :, :].shape[0], hdu[0].data[0,
                                                            0, :, :].shape[1]

        old_beam = Beam.from_fits_header(hdu[0].header)

        datadict = {
            'image': hdu[0].data[0, 0, :, :],
            'header': hdu[0].header,
            'oldbeam': old_beam,
            'nx': nx,
            'ny': ny,
            'dx': dxas,
            'dy': dxas
        }
    return datadict
Example #13
0
def test_preserve_beam():

    cube, data = cube_and_raw('advs.fits')

    beam = Beam.from_fits_header(path("advs.fits"))

    assert cube.beam == beam
Example #14
0
def conv_model(model_image, clean_beam):
    if isinstance(model_image, BaseSpectralCube):
        model = model_image
    else:
        model = SpectralCube.read(model_image, format='casa_image')
    beam = clean_beam

    pix_scale = model.header['CDELT2'] * u.deg
    pix_scale = pix_scale.to(u.arcsec)
    clean_beam_kernel = beam.as_kernel(pix_scale)

    omega_beam = beam.sr
    omega_pix = pix_scale.to('rad')**2
    npix_beam = (omega_beam / omega_pix).value

    # should we just use a delta function rather than try to hack correct pixel area?
    # alternately, we could deconvolve a pixel size.
    # What is technically correct?
    # What does CASA do?  (scary question)
    fwhm_gauss_pix = (4 * np.log(2) / np.pi)**0.5 * pix_scale
    pix_beam = Beam(fwhm_gauss_pix, fwhm_gauss_pix, 0 * u.deg)
    model = model.with_beam(pix_beam)

    conv = model.convolve_to(beam) * npix_beam

    return conv
Example #15
0
def fixExtraHERAfromAdam(fitsimage, beam=15.0):
    '''
    Purpose: fix up extra HERA data from Adam
    '''

    # switch header from M/S to m/s to fix up wcs read errors with SpectralCube
    f = fits.open(fitsimage)
    f[0].header['CUNIT3'] = 'm/s'
    newimage = fitsimage.replace('.fits', '_fixed.fits')
    f.writeto(newimage, overwrite=True)
    f.close()

    # open image
    cube = SpectralCube.read(newimage)

    # switch to km/s
    cube_kms = cube.with_spectral_unit(u.km / u.s)

    # smooth
    newBeam = Beam(beam * u.arcsec)
    smoothCube = cube_kms.convolve_to(newBeam)

    # write out
    smoothCube.write(newimage.replace('.fits', '_10kms_gauss15.fits'),
                     overwrite=True)
Example #16
0
def test_beams_convolution():
    cube, data = cube_and_raw('455_delta_beams.fits')

    # 1" convolved with 1.5" -> 1.8027....
    target_beam = Beam(1.802775637731995*u.arcsec, 1.802775637731995*u.arcsec,
                       0*u.deg)

    conv_cube = cube.convolve_to(target_beam)

    pixscale = wcs.utils.proj_plane_pixel_area(cube.wcs.celestial)**0.5*u.deg

    for ii,bm in enumerate(cube.beams):
        expected = target_beam.deconvolve(bm).as_kernel(pixscale, x_size=5,
                                                        y_size=5)

        np.testing.assert_almost_equal(expected.array,
                                       conv_cube.filled_data[ii,:,:].value)
Example #17
0
def test_beams_convolution():
    cube, data = cube_and_raw('455_delta_beams.fits')

    # 1" convolved with 1.5" -> 1.8027....
    target_beam = Beam(1.802775637731995*u.arcsec, 1.802775637731995*u.arcsec,
                       0*u.deg)

    conv_cube = cube.convolve_to(target_beam)

    pixscale = wcs.utils.proj_plane_pixel_area(cube.wcs.celestial)**0.5*u.deg

    for ii,bm in enumerate(cube.beams):
        expected = target_beam.deconvolve(bm).as_kernel(pixscale, x_size=5,
                                                        y_size=5)

        np.testing.assert_almost_equal(expected.array,
                                       conv_cube.filled_data[ii,:,:].value)
Example #18
0
    def identify_bad_beams(self,
                           threshold,
                           reference_beam=None,
                           criteria=['sr', 'major', 'minor'],
                           mid_value=np.nanmedian):
        """
        Mask out any layers in the cube that have beams that differ from the
        central value of the beam by more than the specified threshold.

        Parameters
        ----------
        threshold : float
            Fractional threshold
        reference_beam : Beam
            A beam to use as the reference.  If unspecified, ``mid_value`` will
            be used to select a middle beam
        criteria : list
            A list of criteria to compare.  Can include
            'sr','major','minor','pa' or any subset of those.
        mid_value : function
            The function used to determine the 'mid' value to compare to.  This
            will identify the middle-valued beam area/major/minor/pa.

        Returns
        -------
        includemask : np.array
            A boolean array where ``True`` indicates the good beams
        """

        includemask = np.ones(self.unmasked_beams.size, dtype='bool')

        all_criteria = {'sr', 'major', 'minor', 'pa'}
        if not set.issubset(set(criteria), set(all_criteria)):
            raise ValueError("Criteria must be one of the allowed options: "
                             "{0}".format(all_criteria))

        props = {
            prop:
            u.Quantity([getattr(beam, prop) for beam in self.unmasked_beams])
            for prop in all_criteria
        }

        if reference_beam is None:
            reference_beam = Beam(major=mid_value(props['major']),
                                  minor=mid_value(props['minor']),
                                  pa=mid_value(props['pa']))

        for prop in criteria:
            val = props[prop]
            mid = getattr(reference_beam, prop)

            diff = np.abs((val - mid) / mid)

            assert diff.shape == includemask.shape

            includemask[diff > threshold] = False

        return includemask
Example #19
0
def test_single_gray_hole():
    one_gray_hole = add_holes((200, 200), hole_level=100, nholes=1)
    test_gray_hole = Projection(one_gray_hole, wcs=wcs.WCS())

    test_bubble = BubbleFinder2D(test_gray_hole,
                                 beam=Beam(10),
                                 channel=0,
                                 sigma=40)
    test_bubble.multiscale_bubblefind(edge_find=False)
Example #20
0
def fixNRO(fitsimage):
    '''
    fix up NRO data
    '''

    cube = SpectralCube.read(fitsimage)
    # add beam
    beam_cube = cube.with_beam(Beam(15.0 * u.arcsec))
    beam_cube.write(fitsimage.replace('.FITS', '_fixed.fits'), overwrite=True)
Example #21
0
def find_beam_properties(hdr):
    '''
    Try to read beam properties from a header. Uses radio_beam when installed.

    Parameters
    ----------
    hdr : `~astropy.io.fits.Header`
        FITS header.

    Returns
    -------
    bmaj : `~astropy.units.Quantity`
        Major axis of the beam in degrees.
    bmin : `~astropy.units.Quantity`
        Minor axis of the beam in degrees. If this cannot be read from the
        header, assumes `bmaj=bmin`.
    bpa : `~astropy.units.Quantity`
        Position angle of the major axis. If this cannot read from the
        header, assumes an angle of 0 deg.
    '''

    if RADIO_BEAM_INSTALL:
        try:
            beam = Beam.from_fits_header(hdr)
            bmaj = beam.major.to(u.deg)
            bmin = beam.minor.to(u.deg)
            bpa = beam.pa.to(u.deg)
        except NoBeamException:
            bmaj = None
            bmin = None
            bpa = None
    else:
        if not isinstance(hdr, fits.Header):
            raise TypeError("Header is not a FITS header.")

        if "BMAJ" in hdr:
            bmaj = hdr["BMAJ"] * u.deg
        else:
            warn("Cannot find 'BMAJ' in the header. Try installing"
                 " the `radio_beam` package for loading header"
                 " information.")
            bmaj = None

        if "BMIN" in hdr:
            bmin = hdr["BMIN"] * u.deg
        else:
            warn("Cannot find 'BMIN' in the header. Assuming circular beam.")
            bmin = bmaj

        if "BPA" in hdr:
            bpa = hdr["BPA"] * u.deg
        else:
            warn("Cannot find 'BPA' in the header. Assuming PA of 0.")
            bpa = 0 * u.deg

    return bmaj, bmin, bpa
Example #22
0
def convolve_sky_byfactor(cube,
                          factor,
                          savename=None,
                          edgetrim_width=5,
                          downsample=True,
                          **kwargs):

    factor = factor * 1.0

    if not isinstance(cube, SpectralCube):
        cube = SpectralCube.read(cube)

    if edgetrim_width is not None:
        cube = edge_trim(cube, trim_width=edgetrim_width)

    hdr = cube.header

    # sanity check
    if hdr['CUNIT1'] != hdr['CUNIT2']:
        print "[ERROR]: the axis units for the do not match each other!"
        return None

    beamunit = getattr(u, hdr['CUNIT1'])
    bmaj = hdr['BMAJ'] * beamunit * factor
    bmin = hdr['BMIN'] * beamunit * factor
    pa = hdr['BPA']

    beam = Beam(major=bmaj, minor=bmin, pa=pa)

    # convolve
    cnv_cube = convolve_sky(cube, beam, **kwargs)

    if cnv_cube.fill_value is not np.nan:
        cnv_cube = cnv_cube.with_fill_value(np.nan)
    #cnv_cube = cnv_cube.with_fill_value(0.0)

    if downsample:
        # regrid the convolved cube
        nhdr = FITS_tools.downsample.downsample_header(hdr,
                                                       factor=factor,
                                                       axis=1)
        nhdr = FITS_tools.downsample.downsample_header(nhdr,
                                                       factor=factor,
                                                       axis=2)
        nhdr['NAXIS1'] = int(np.rint(hdr['NAXIS1'] / factor))
        nhdr['NAXIS2'] = int(np.rint(hdr['NAXIS2'] / factor))
        newcube = cnv_cube.reproject(nhdr, order='bilinear')
        # newcube = cnv_cube.reproject(nhdr, order='bicubic')
    else:
        newcube = cnv_cube

    if savename is not None:
        newcube.write(savename, overwrite=True)

    return newcube
Example #23
0
def test_nocelestial_convolution_2D_fail(data_255_delta, use_dask):

    cube, data = cube_and_raw(data_255_delta, use_dask=use_dask)

    proj = cube.moment0(axis=1)

    test_beam = Beam(1.0 * u.arcsec)

    with pytest.raises(WCSCelestialError,
                       match="WCS does not contain two spatial axes."):
        proj.convolve_to(test_beam)
Example #24
0
def main(pool, args, verbose=False):
    """Main script
    """

    # Fix up outdir
    outdir = args.outdir
    if outdir is not None:
        if outdir[-1] == '/':
            outdir = outdir[:-1]
    else:
        outdir = '.'

    # Get file list
    files = glob(args.infile)
    if files == []:
        raise Exception('No files found!')

    # Parse args
    bmaj = args.bmaj
    bmin = args.bmin
    bpa = args.bpa

    # Find largest bmax
    big_beam = getmaxbeam(files, verbose=verbose)

    # Set to largest
    if bpa is None and bmin is None and bmaj is None:
        bpa = big_beam.pa.to(u.deg)
    else:
        bpa = 0 * u.deg
    if bmaj is None:
        bmaj = round_up(big_beam.major.to(u.arcsec))
    elif bmaj * u.arcsec < round_up(big_beam.major.to(u.arcsec)):
        raise Exception('Selected BMAJ is too small!')
    else:
        bmaj *= u.arcsec
    if bmin is None:
        bmin = round_up(big_beam.minor.to(u.arcsec))
    elif bmin * u.arcsec < round_up(big_beam.minor.to(u.arcsec)):
        raise Exception('Selected BMIN is too small!')
    else:
        bmin *= u.arcsec

    new_beam = Beam(bmaj, bmin, bpa)
    if verbose:
        print(f'Final beam is', new_beam)

    inputs = [[file, outdir, new_beam, args, verbose]
              for i, file in enumerate(files)]

    output = list(pool.map(worker, inputs))

    if verbose:
        print('Done!')
def convolve_Vlsr(V_lsr, header):
    """ Convolve Vlsr map with beam in header
    """
    pixscale=np.abs(header['cdelt1'])
    if header['cunit1'] == 'arcsec':
        pixscale *= u.arcsec
    else:
        pixscale *= u.deg
    my_beam = Beam.from_fits_header(header)
    my_beam_kernel = my_beam.as_kernel(pixscale)
    return convolve(V_lsr, my_beam_kernel, boundary='fill', fill_value=np.nan)
Example #26
0
def test_projection_with_beam():

    exp_beam = Beam(1.0 * u.arcsec)

    proj, hdu = load_projection("55.fits")

    # uses from_hdu, which passes beam as kwarg
    assert proj.beam == exp_beam
    assert proj.meta['beam'] == exp_beam

    # load beam from meta
    exp_beam = Beam(1.5 * u.arcsec)

    meta = {"beam": exp_beam}
    new_proj = Projection(hdu.data, wcs=proj.wcs, meta=meta)

    assert new_proj.beam == exp_beam
    assert new_proj.meta['beam'] == exp_beam

    # load beam from given header
    exp_beam = Beam(2.0 * u.arcsec)
    header = hdu.header.copy()
    header = exp_beam.attach_to_header(header)
    new_proj = Projection(hdu.data, wcs=proj.wcs, header=header,
                          read_beam=True)

    assert new_proj.beam == exp_beam
    assert new_proj.meta['beam'] == exp_beam

    # load beam from beam object
    exp_beam = Beam(3.0 * u.arcsec)
    header = hdu.header.copy()
    del header["BMAJ"], header["BMIN"], header["BPA"]
    new_proj = Projection(hdu.data, wcs=proj.wcs, header=header,
                          beam=exp_beam)

    assert new_proj.beam == exp_beam
    assert new_proj.meta['beam'] == exp_beam

    # Slice the projection with a beam and check it's still there
    assert new_proj[:1, :1].beam == exp_beam
Example #27
0
def test_nocelestial_convolution_2D_fail():

    cube, data = cube_and_raw('255_delta.fits')

    proj = cube.moment0(axis=1)

    test_beam = Beam(1.0 * u.arcsec)

    with pytest.raises(WCSCelestialError) as exc:
        proj.convolve_to(test_beam)

    assert exc.value.args[0] == ("WCS does not contain two spatial axes.")
Example #28
0
def beam_struct(beam, scale, pixscale, return_beam=False):
    '''
    Return a beam structure.
    '''
    if not _radio_beam_flag:
        raise ImportError("radio_beam must be installed to return a beam"
                          " structure.")

    if scale == 1:
        scale_beam = beam
    else:
        scale_beam = Beam(major=scale * beam.major,
                          minor=scale * beam.minor,
                          pa=beam.pa)

    struct = scale_beam.as_tophat_kernel(pixscale).array
    struct = (struct > 0).astype(int)

    if return_beam:
        return struct, scale_beam

    return struct
Example #29
0
def test_gauss_hole():
    one_gauss_hole, params = add_gaussian_holes(np.ones((200, 200)),
                                                nholes=1,
                                                return_info=True)
    test_gauss_hole = Projection(one_gauss_hole, wcs=wcs.WCS())

    test_bubble = BubbleFinder2D(test_gauss_hole,
                                 beam=Beam(10),
                                 channel=0,
                                 sigma=0.05)
    test_bubble.multiscale_bubblefind(edge_find=True)

    test_bubble.visualize_regions(edges=True)
Example #30
0
def smallest_beam(beams, includemask=None):
    """
    Returns the smallest beam (by area) in a list of beams.
    """

    from radio_beam import Beam

    major, minor, pa = beam_props(beams, includemask)
    smallest_idx = (major * minor).argmin()
    new_beam = Beam(major=major[smallest_idx], minor=minor[smallest_idx],
                    pa=pa[smallest_idx])

    return new_beam
Example #31
0
def test_pspec(plotname="pspec_rnoise_beamsmooth_apodizetukey.pdf",
               size=256,
               powerlaw=3.,
               run_kwargs={
                   'verbose': False,
                   'apodize_kernel': 'tukey'
               },
               plot_kwargs={'fit_color': 'black'},
               beam_smooth=True,
               pixel_scale=2 * u.arcsec,
               bmin=8.09 * u.arcsec,
               bmaj=10.01 * u.arcsec,
               bpa=-12.9 * u.deg,
               restfreq=1.4 * u.GHz,
               bunit=u.K):
    from spectral_cube import Projection
    from radio_beam import Beam

    rnoise_img = make_extended(size, powerlaw)
    # Create a FITS HDU
    rnoise_hdu = create_fits_hdu(rnoise_img, 2 * u.arcsec, 2 * u.arcsec,
                                 rnoise_img.shape, 1.4 * u.GHz, u.K)

    pspec = PowerSpectrum(rnoise_hdu)

    if beam_smooth:
        pencil_beam = Beam(0 * u.deg)
        rnoise_proj = Projection.from_hdu(rnoise_hdu).with_beam(pencil_beam)
        new_beam = Beam(bmaj, bmin, bpa)
        rnoise_conv = rnoise_proj.convolve_to(new_beam)

        # hdr = fits.Header(header)
        # rnoise_hdu = fits.PrimaryHDU(rnoise_img, header=hdr)
        pspec = PowerSpectrum(rnoise_conv)

    pspec.run(**run_kwargs)
    pspec.plot_fit(save_name=plotname, **plot_kwargs)

    return pspec
Example #32
0
def test_beams_convolution_equal():
    cube, data = cube_and_raw('522_delta_beams.fits')

    # Only checking that the equal beam case is handled correctly.
    # Fake the beam in the first channel. Then ensure that the first channel
    # has NOT been convolved.
    target_beam = Beam(1.0 * u.arcsec, 1.0 * u.arcsec, 0.0 * u.deg)
    cube.beams[0] = target_beam

    conv_cube = cube.convolve_to(target_beam)

    np.testing.assert_almost_equal(cube.filled_data[0].value,
                                   conv_cube.filled_data[0].value)
Example #33
0
def beam_struct(beam, scale, pixscale, return_beam=False):
    '''
    Return a beam structure.
    '''
    if not _radio_beam_flag:
        raise ImportError("radio_beam must be installed to return a beam"
                          " structure.")

    if scale == 1:
        scale_beam = beam
    else:
        scale_beam = Beam(major=scale * beam.major,
                          minor=scale * beam.minor,
                          pa=beam.pa)

    struct = scale_beam.as_tophat_kernel(pixscale).array
    struct = (struct > 0).astype(int)

    if return_beam:
        return struct, scale_beam

    return struct
Example #34
0
def try_load_beams(data):
    '''
    Try loading a beam table from a FITS HDU list.
    '''
    try:
        from radio_beam import Beam
    except ImportError:
        warnings.warn("radio_beam is not installed. No beam "
                      "can be created.",
                      ImportError
                     )

    if isinstance(data, fits.BinTableHDU):
        if 'BPA' in data.data.names:
            beam_table = data.data
            return beam_table
        else:
            raise ValueError("No beam table found")
    elif isinstance(data, fits.HDUList):

        for ihdu, hdu_item in enumerate(data):
            if isinstance(hdu_item, (fits.PrimaryHDU, fits.ImageHDU)):
                beam = try_load_beams(hdu_item.header)
            elif isinstance(hdu_item, fits.BinTableHDU):
                if 'BPA' in hdu_item.data.names:
                    beam_table = hdu_item.data
                    return beam_table

        try:
            # if there was a beam in a header, but not a beam table
            return beam
        except NameError:
            # if the for loop has completed, we didn't find a beam table
            raise ValueError("No beam table found")
    elif isinstance(data, (fits.PrimaryHDU, fits.ImageHDU)):
        return try_load_beams(data.header)
    elif isinstance(data, fits.Header):
        try:
            beam = Beam.from_fits_header(data)
            return beam
        except Exception as ex:
            # warnings.warn("Could not parse beam information from header."
            #               "  Exception was: {0}".format(ex.__repr__()),
            #               FITSWarning
            #              )

            # Avoid warning since cubes don't have a beam
            # Warning now provided when `SpectralCube.beam` is None
            beam = None
    else:
        raise ValueError("How did you get here?  This is some sort of error.")
Example #35
0
def find_beam_properties(hdr):
    '''
    Try to read beam properties from a header. Uses radio_beam when installed.

    Parameters
    ----------
    hdr : `~astropy.io.fits.Header`
        FITS header.

    Returns
    -------
    bmaj : `~astropy.units.Quantity`
        Major axis of the beam in degrees.
    bmin : `~astropy.units.Quantity`
        Minor axis of the beam in degrees. If this cannot be read from the
        header, assumes `bmaj=bmin`.
    bpa : `~astropy.units.Quantity`
        Position angle of the major axis. If this cannot read from the
        header, assumes an angle of 0 deg.
    '''

    if RADIO_BEAM_INSTALL:
        beam = Beam.from_fits_header(hdr)
        bmaj = beam.major.to(u.deg)
        bmin = beam.minor.to(u.deg)
        bpa = beam.pa.to(u.deg)
    else:
        if not isinstance(hdr, fits.Header):
            raise TypeError("Header is not a FITS header.")

        if "BMAJ" in hdr:
            bmaj = hdr["BMAJ"] * u.deg
        else:
            raise ValueError("Cannot find 'BMAJ' in the header. Try installing"
                             " the `radio_beam` package for loading header"
                             " information.")

        if "BMIN" in hdr:
            bmin = hdr["BMIN"] * u.deg
        else:
            warn("Cannot find 'BMIN' in the header. Assuming circular beam.")
            bmin = bmaj

        if "BPA" in hdr:
            bpa = hdr["BPA"] * u.deg
        else:
            warn("Cannot find 'BPA' in the header. Assuming PA of 0.")
            bpa = 0 * u.deg

    return bmaj, bmin, bpa
Example #36
0
def try_load_beam(header):
    '''
    Try loading a beam from a FITS header.
    '''

    try:
        beam = Beam.from_fits_header(header)
        return beam
    except Exception as ex:
        # We don't emit a warning if no beam was found since it's ok for
        # cubes to not have beams
        if 'No BMAJ' not in str(ex):
            warnings.warn("Could not parse beam information from header."
                          "  Exception was: {0}".format(ex.__repr__()))
Example #37
0
def test_ondespectrum_with_beam():

    exp_beam = Beam(1.0 * u.arcsec)

    test_wcs_1 = WCS(naxis=1)
    spec = OneDSpectrum(twelve_qty_1d, wcs=test_wcs_1)

    # load beam from meta
    meta = {"beam": exp_beam}
    new_spec = OneDSpectrum(spec.data, wcs=spec.wcs, meta=meta)

    assert new_spec.beam == exp_beam
    assert new_spec.meta['beam'] == exp_beam

    # load beam from given header
    hdu = spec.hdu
    exp_beam = Beam(2.0 * u.arcsec)
    header = hdu.header.copy()
    header = exp_beam.attach_to_header(header)
    new_spec = OneDSpectrum(hdu.data, wcs=spec.wcs, header=header,
                            read_beam=True)

    assert new_spec.beam == exp_beam
    assert new_spec.meta['beam'] == exp_beam

    # load beam from beam object
    exp_beam = Beam(3.0 * u.arcsec)
    header = hdu.header.copy()
    new_spec = OneDSpectrum(hdu.data, wcs=spec.wcs, header=header,
                            beam=exp_beam)

    assert new_spec.beam == exp_beam
    assert new_spec.meta['beam'] == exp_beam

    # Slice the spectrum with a beam and check it's still there
    assert new_spec[:1].beam == exp_beam
Example #38
0
    def remove_small_regions(self, area_threshold=None, beam=None,
                             verbose=False):
        '''
        Remove 2D regions (per channel) based on their area. By default, this
        removed regions smaller than the beam area.

        Parameters
        ----------
        area_threshold : float, optional
            Minimum pixel area to keep. Overrides beam argument.
        beam : radio_beam.Beam, optional
            Provide a Beam object to define the area threshold. By default,
            a Beam object will be created from the information in the cube
            WCS. Specifying a Beam object will override using the default
            Beam object from the cube WCS.

        '''

        self.log_and_backup(self.remove_small_regions)

        # Attempt to get beam area from cube WCS info.
        if area_threshold is None:
            if beam is None:
                beam = Beam.from_fits_header(self._linked_data.header)

            # Get pixelscale, add unit on (ignore the per pixel)
            # Eventually the unit should be included in get_pixel_scales
            # but this requires additional workarounds when used for Beam
            # objects
            pixscale = get_pixel_scales(self._wcs)

            # Now get the pixel beam area
            area_threshold = \
                np.count_nonzero(beam.as_tophat_kernel(pixscale).array > 0)

        def area_thresh_func(arr, size_thresh):

            remove_small_objects(arr, min_size=size_thresh,
                                 connectivity=arr.ndim, in_place=True)

            return arr

        self.reject_region(area_thresh_func, iteraxis='spectral',
                           func_args=(area_threshold),
                           log_call=False, verbose=verbose)

        return self
def convolve_Vlsr(V_lsr, header):
    """ 
    It Convolves a pure theoretical Vlsr map with a requested beam.
    The beam is setup using the FITS header of the expected observation.
    The convolution would mimick (at least at first order) the effect of a 
    finite beam size in the observations.
    The header is also used to convert the beam into pixel units before 
    convolving the map

    param :
    Vlsr : image with Velocity map to be convolved. It handles astropy.units.
    header : FITS header with beam and pixel size information

    TODO:
    -pass a Beam structure instead of the FITS header, to make it more flexible
    """
    from astropy.convolution import convolve
    from radio_beam import Beam
    pixscale=np.abs(header['cdelt1'])*u.Unit(header['cunit1'])
    my_beam = Beam.from_fits_header(header)
    my_beam_kernel = my_beam.as_kernel(pixscale)
    return convolve(V_lsr, my_beam_kernel, boundary='fill', fill_value=np.nan)
Example #40
0
    def load_beam(self, beam=None):
        '''
        Try loading the beam from the header or a given object.

        Parameters
        ----------
        beam : `~radio_beam.Beam`, optional
            The beam.
        '''

        if beam is None:
            if hasattr(self, "_header"):
                try:
                    beam = Beam.from_fits_header(self.header)
                    self._beam = beam
                except NoBeamException:
                    warn("Header missing beam information.")
            else:
                warn("No header available. Cannot load beam.")
        else:
            if not isinstance(beam, Beam):
                raise TypeError("beam must be a radio_beam.Beam object.")

            self._beam = beam
Example #41
0
import numpy as np
from astropy.io import fits
from astropy.wcs import WCS
import matplotlib.pyplot as plt
from astropy.visualization import AsinhStretch
from astropy.visualization.mpl_normalize import ImageNormalize
from radio_beam import Beam

from paths import fourteenB_HI_data_path, paper1_figures_path
from constants import moment0_name, moment1_name, hi_freq


moment0 = fits.open(fourteenB_HI_data_path(moment0_name))[0]

beam = Beam.from_fits_header(moment0.header)

moment0_Kkm_s = beam.jtok(hi_freq).value * moment0.data / 1000.

ax = plt.subplot(111, projection=WCS(moment0.header))
im = ax.imshow(moment0_Kkm_s,
          origin='lower',
          interpolation='nearest',
          norm=ImageNormalize(vmin=-0.001,
                              vmax=np.nanmax(moment0_Kkm_s),
                              stretch=AsinhStretch()))
ax.set_ylabel("DEC (J2000)")
ax.set_xlabel("RA (J2000)")

cbar = plt.colorbar(im)
cbar.set_label(r"Intensity (K km s$^{-1}$)")
Example #42
0

if __name__ == "__main__":
    import matplotlib.pyplot as p

    from paths import (fourteenB_HI_data_path, arecibo_HI_data_path,
                       c_hi_analysispath, paper1_figures_path,
                       data_path)

    from constants import moment0_name, lwidth_name
    from galaxy_params import gal

    lwidth_hdu = fits.open(fourteenB_HI_data_path(lwidth_name))[0]
    lwidth = Projection(lwidth_hdu.data, wcs=WCS(lwidth_hdu.header),
                        unit=u.m / u.s)
    lwidth.meta["beam"] = Beam.from_fits_header(lwidth_hdu.header)

    # Create a radial profile of the HI vel disp out to 8 kpc.
    # Beyond 8 kpc, noise is dominant. It may be some reflection of the
    # warp, but I don't trust it right now.
    rs, sd, sd_sigma = radial_profile(gal, lwidth, max_rad=8 * u.kpc)

    sd = sd.to(u.km / u.s)
    sd_sigma = sd_sigma.to(u.km / u.s)

    p.errorbar(rs.value, sd.value,
               yerr=sd_sigma.value, fmt="-", color="b",
               drawstyle='steps-mid')
    p.xlabel("R (kpc)")
    p.ylabel("HI Velocity Dispersion (km/s)")
    p.grid()
Example #43
0
    if fail:
        warn("Fail flag was raised. Check the output")
        # raise ValueError("Fit failed.")

    return fit, err, model, profile


if __name__ == "__main__":

    from analysis.paths import (fourteenB_HI_data_path, paper1_figures_path,
                                iram_co21_data_path)
    from analysis.constants import moment0_name
    from analysis.galaxy_params import gal

    mom0_fits = fits.open(fourteenB_HI_data_path(moment0_name))[0]
    beam = Beam.from_fits_header(mom0_fits.header)
    mom0 = Projection(mom0_fits.data * beam.jtok(hi_freq) / 1000. *
                      u.km / u.s,
                      wcs=WCS(mom0_fits.header))
    mom0.meta['beam'] = beam

    # Create the bubble mask instead of letting FilFinder to do it.
    bub = BubbleFinder2D(mom0, sigma=80. * beam.jtok(hi_freq) / 1000.)

    # fils = fil_finder_2D(mom0.value, mom0.header, 10, distance=0.84e6)
    # fils.mask = ~(bub.mask.copy())
    # fils.medskel()
    # fils.analyze_skeletons()
    # # So at least on of the radial profiles fails. BUT the second fit is to a
    # # skeleton that is essentially the entire disk, so plot without interactivity
    # # and save the plot and the parameters shown in verbose mode.
from astropy.io import fits
from astropy import coordinates
from astropy import units as u
from astropy import wcs
import FITS_tools
import reproject
import paths
import image_registration
from radio_beam import Beam
from astropy import convolution
import gaussfitter

epoch3 = fits.open(paths.dpath("W51Ku_BDarray_continuum_2048_both_uniform.hires.clean.image.fits"))
beam3 = Beam.from_fits_header(epoch3[0].header)
epoch3[0].data = epoch3[0].data.squeeze()
wcs3 = wcs.WCS(epoch3[0].header).sub([wcs.WCSSUB_CELESTIAL])
epoch3header = wcs3.to_header()
epoch3header['NAXIS'] = 2
epoch3header['NAXIS1'] = epoch3[0].data.shape[1]
epoch3header['NAXIS2'] = epoch3[0].data.shape[0]

kernel = (0.3*u.arcsec).to(u.deg)
pixscale = (wcs3.pixel_scale_matrix.diagonal()**2).sum()**0.5 * u.deg
print('pix kernel size: {0}'.format(kernel/pixscale))
smoothed3 = convolution.convolve_fft(epoch3[0].data,
                                     convolution.Gaussian2DKernel(kernel/pixscale))

diff3sm =  epoch3[0].data - smoothed3
diff3smhdu = fits.PrimaryHDU(data=diff3sm, header=epoch3header)
diff3smhdu.writeto(paths.dpath("Kuband_Epoch3sm-Epoch3.fits"), clobber=True, output_verify='fix')
            p.axvline(np.where(mask[:, i, j])[0][0])
            p.plot(smooth_cube[:, i, j] * mask[:, i, j], 'bD')

            # p.vlines(np.where(mask[:, i, j])[0][-1], 0, np.nanmax(spectrum))
            # p.vlines(np.where(mask[:, i, j])[0][0], 0, np.nanmax(spectrum))
            # p.plot(smoothed * mask[:, i, j], 'bD')
            p.draw()
            raw_input("Next spectrum?")
            p.clf()

    initial_mask = mask.copy()

    # The resolution is about 47 arcsec, but this is just 2 pixels across in
    # the map. I'm going to double this to only include features that are
    # clearly not noise
    beam = Beam(major=2 * 47 * u.arcsec)

    kernel = beam.as_tophat_kernel(pixscale)
    kernel_pix = (kernel.array > 0).sum()

    for i in ProgressBar(mask.shape[0]):
        mask[i] = nd.binary_opening(mask[i], kernel)
        mask[i] = nd.binary_closing(mask[i], kernel)
        mask[i] = mo.remove_small_objects(mask[i], min_size=kernel_pix,
                                          connectivity=2)
        mask[i] = mo.remove_small_holes(mask[i], min_size=kernel_pix,
                                        connectivity=2)

    # Each region must contain a point above the peak_snr
    labels, num = nd.label(mask, np.ones((3, 3, 3)))
    for n in range(1, num + 1):
Example #46
0
def cubefit(region='NGC1333', blorder=1, vmin=5, vmax=15, do_plot=False, 
            snr_min=5.0, multicore=1):
    """
    Fit NH3(1,1), (2,2) and (3,3) cubes for the requested region. 
    It fits all pixels with SNR larger than requested. 
    Initial guess is based on moment maps and neighboring pixels. 
    The fitting can be done in parallel mode using several cores, 
    however, this is dangerous for large regions, where using a 
    good initial guess is important. 
    It stores the result in a FITS cube. 

    TODO:
    -Store results in hdu list
    -Improve initial guess
    
    Parameters
    ----------
    region : str
        Name of region to reduce
    blorder : int
        order of baseline removed
    vmin : numpy.float
        Minimum centroid velocity to plot, in km/s.
    vmax : numpy.float
        Maximum centroid velocity to plot, in km/s.
    do_plot : bool
        If True, then a map of the region to map is shown.
    snr_min : numpy.float
        Minimum signal to noise ratio of the spectrum to be fitted.
    multicore : int
        Numbers of cores to use for parallel processing. 
    """

    OneOneIntegrated = '{0}/{0}_NH3_11_mom0.fits'.format(region,blorder)
    OneOneFile = '{0}/{0}_NH3_11_base{1}.fits'.format(region,blorder)
    RMSFile = '{0}/{0}_NH3_11_base{1}_rms.fits'.format(region,blorder)
    TwoTwoFile = '{0}/{0}_NH3_22_base{1}.fits'.format(region,blorder)
    ThreeThreeFile = '{0}/{0}_NH3_33_base{1}.fits'.format(region,blorder)
        
    beam11 = Beam.from_fits_header(fits.getheader(OneOneFile))
    cube11sc = SpectralCube.read(OneOneFile)
    cube22sc = SpectralCube.read(TwoTwoFile)
    errmap11 = fits.getdata(RMSFile)
    snr = cube11sc.filled_data[:].value/errmap11
    peaksnr = np.max(snr,axis=0)
    rms = np.nanmedian(errmap11)
    planemask = (peaksnr>snr_min) # *(errmap11 < 0.15)
    planemask = remove_small_objects(planemask,min_size=40)
    planemask = opening(planemask,disk(1))
    #planemask = (peaksnr>20) * (errmap11 < 0.2)

    mask = (snr>3)*planemask
    maskcube = cube11sc.with_mask(mask.astype(bool))
    maskcube = maskcube.with_spectral_unit(u.km/u.s,velocity_convention='radio')
    slab = maskcube.spectral_slab( vmax*u.km/u.s, vmin*u.km/u.s)
    w11=slab.moment( order=0, axis=0).value
    peakloc = np.nanargmax(w11)
    ymax,xmax = np.unravel_index(peakloc,w11.shape)
    moment1 = slab.moment( order=1, axis=0).value
    moment2 = (slab.moment( order=2, axis=0).value)**0.5
    moment2[np.isnan(moment2)]=0.2
    moment2[moment2<0.2]=0.2
    maskmap = w11>0.5
    cube11 = pyspeckit.Cube(OneOneFile,maskmap=planemask)
    cube11.unit="K"
    cube22 = pyspeckit.Cube(TwoTwoFile,maskmap=planemask)
    cube22.unit="K"
    cube33 = pyspeckit.Cube(ThreeThreeFile,maskmap=planemask)
    cube33.unit="K"
    cubes = pyspeckit.CubeStack([cube11,cube22,cube33],maskmap=planemask)
    cubes.unit="K"
    guesses = np.zeros((6,)+cubes.cube.shape[1:])
    moment1[moment1<vmin] = vmin+0.2
    moment1[moment1>vmax] = vmax-0.2
    guesses[0,:,:] = 12                    # Kinetic temperature 
    guesses[1,:,:] = 3                     # Excitation  Temp
    guesses[2,:,:] = 14.5                  # log(column)
    guesses[3,:,:] = moment2  # Line width / 5 (the NH3 moment overestimates linewidth)               
    guesses[4,:,:] = moment1  # Line centroid              
    guesses[5,:,:] = 0.5                   # F(ortho) - ortho NH3 fraction (fixed)
    if do_plot:
        import matplotlib.pyplot as plt
        plt.imshow( w11, origin='lower')
        plt.show()
    F=False
    T=True
    print('start fit')
    cubes.fiteach(fittype='ammonia',  guesses=guesses,
                  integral=False, verbose_level=3, 
                  fixed=[F,F,F,F,F,T], signal_cut=2,
                  limitedmax=[F,F,F,F,T,T],
                  maxpars=[0,0,0,0,vmax,1],
                  limitedmin=[T,T,T,T,T,T],
                  minpars=[5,2.8,12.0,0.04,vmin,0],
                  start_from_point=(xmax,ymax),
                  use_neighbor_as_guess=True, 
                  position_order = 1/peaksnr,
                  errmap=errmap11, multicore=multicore)

    fitcubefile = fits.PrimaryHDU(data=np.concatenate([cubes.parcube,cubes.errcube]), header=cubes.header)
    fitcubefile.header.update('PLANE1','TKIN')
    fitcubefile.header.update('PLANE2','TEX')
    fitcubefile.header.update('PLANE3','COLUMN')
    fitcubefile.header.update('PLANE4','SIGMA')
    fitcubefile.header.update('PLANE5','VELOCITY')
    fitcubefile.header.update('PLANE6','FORTHO')
    fitcubefile.header.update('PLANE7','eTKIN')
    fitcubefile.header.update('PLANE8','eTEX')
    fitcubefile.header.update('PLANE9','eCOLUMN')
    fitcubefile.header.update('PLANE10','eSIGMA')
    fitcubefile.header.update('PLANE11','eVELOCITY')
    fitcubefile.header.update('PLANE12','eFORTHO')
    fitcubefile.header.update('CDELT3',1)
    fitcubefile.header.update('CTYPE3','FITPAR')
    fitcubefile.header.update('CRVAL3',0)
    fitcubefile.header.update('CRPIX3',1)
    fitcubefile.writeto("{0}_parameter_maps.fits".format(region),clobber=True)
def avg_fwhm(beam):
    return np.sqrt(beam.major.to(u.arcsec) * beam.minor.to(u.arcsec))


parameters = ["CASAVer", "Model", "Mask", "AllFields", "MScale", "Tclean"]

# Load in the mask
mask_hdu = fits.open(append_path("M33_14B-088_HI_mask_channel_330.fits"))[0]
mask = mask_hdu.data.squeeze()
mask = mask[::-1, ::-1] == 1

low_hdu = fits.open(append_path("M33_14B-088_HI_model_channel_330.fits"))[0]
model = low_hdu.data.squeeze()
model = model[::-1, ::-1]

sd_beam = Beam.from_fits_header(append_path("M33_14B-088_HI_model_channel_330.fits"))
fft_sd = np.fft.fftshift(np.fft.fft2(np.nan_to_num(model)))

# Also load in the original Arecibo channel that has not been regridded.
low_hdu_orig = \
    fits.open(append_path("M33_14B-088_HI_model_original_arecibo.fits"))[0]

# The commented out sections were for ensuring that the model matched
# regridded versions using FITS_tools and reproject. On the large scales that
# matter, the answer is yes they do match.
# regrid_model, footprint = reproject_interp(low_hdu_orig, low_hdu.header)
# regrid_model_fitstools = hcongrid(low_hdu_orig.data, low_hdu_orig.header,
#                                   low_hdu.header)
regrid_mask = reproject_interp(mask_hdu, low_hdu_orig.header)[0]
regrid_mask[np.isnan(regrid_mask)] = 0.0
regrid_mask = regrid_mask == 1.0
Example #48
0
import pyspeckit
import astropy.io.fits as fits
import numpy as np
import os
from spectral_cube import SpectralCube
import signal_id
from radio_beam import Beam
import astropy.constants as con
import astropy.units as u
OneOneIntegrated = 'NGC1333_W11.fits'
OneOneFile = 'NGC1333_ABCDEFGH_NH3_11_all_blsub.rg.fits'
TwoTwoFile = 'NGC1333_ABCDEFGH_NH3_22_all_blsub.fits'
ThreeThreeFile = 'NGC1333_ABCDEFGH_NH3_33_all_blsub.fits'


beam11 = Beam.from_fits_header(fits.getheader(OneOneFile))
cube11sc = SpectralCube.read(OneOneFile)
cube22sc = SpectralCube.read(TwoTwoFile)

noisy = signal_id.noise.Noise(cube11sc)
noisy.estimate_noise(spectral_flat=True,niter=2)
errmap11 = (noisy.spatial_norm*noisy.scale)
rms = np.nanmedian(errmap11)
mask = (noisy.snr>5)*(noisy.spatial_norm<2.5)
maskcube = cube11sc.with_mask(mask)
maskcube = maskcube.with_spectral_unit(u.km/u.s,velocity_convention='radio')
slab = maskcube#.spectral_slab(5*u.km/u.s,15*u.km/u.s)
w11=slab.moment(0,0).value
peakloc = np.nanargmax(w11)
xmax,ymax = np.unravel_index(peakloc,w11.shape)
moment1 = slab.moment(1,0).value
Example #49
0
# Load in the mask
ia.open(append_path("M33_14B-088_HI_mask_channel_330.image"))
mask = ia.torecord()["imagearray"].squeeze() > 0
ia.close()
# For some reason, both axes need to be reversed
mask = mask[::-1, ::-1]

# Load in the model
ia.open(append_path("M33_14B-088_HI_model_channel_330.image"))
model = ia.torecord()["imagearray"].squeeze()
ia.close()
model = model[::-1, ::-1]
# model[~mask] = np.NaN

sd_beam = \
    Beam.from_casa_image(append_path("M33_14B-088_HI_model_channel_330.image"))

folders = glob(append_path("14B-088_HI_LSRK.ms.contsub_channel_1000.CASAVer*"))

parameter_array = np.zeros((len(parameters), len(folders)))

parameter_table = dict.fromkeys(parameters)

for key in parameter_table:
    parameter_table[key] = []

# Values to extract out.
parameter_table["std"] = []
parameter_table["sum"] = []
parameter_table["median"] = []
parameter_table["peak_res"] = []
def append_path(path):
    return os.path.join(data_path, path)


parameters = ["CASAVer", "Model", "Mask", "AllFields", "MScale", "Tclean"]

# Load in the mask
mask = fits.open(append_path("M33_14B-088_HI_mask_channel_330.fits"))[0].data.squeeze()
mask = mask[::-1, ::-1] == 1

model = fits.open(append_path("M33_14B-088_HI_model_channel_330.fits"))[0].data.squeeze()
low_hdu = fits.open(append_path("M33_14B-088_HI_model_channel_330.fits"))[0]
# For some reason, both axes need to be reversed
model = model[::-1, ::-1]
sd_beam = Beam.from_fits_header(append_path("M33_14B-088_HI_model_channel_330.fits"))
fft_sd = np.fft.fftshift(np.fft.fft2(model))

# Arecibo FWHM
lowresfwhm = (3.8 * u.arcmin).to(u.arcsec)
# Grid scaling used.
pixscale = 3 * u.arcsec
# Image shape
nax2, nax1 = model.shape

# High scale factor
highresscalefactor = 1.0
# Low scale factor
lowresscalefactor = 1.0

# x-axis unit
Example #51
0
    from radio_beam import Beam
    from astropy.io import fits

    import os

    from paths import (fourteenB_HI_data_path, arecibo_HI_data_path,
                       c_hi_analysispath, paper1_figures_path,
                       data_path)

    from constants import hi_freq, moment0_name
    from galaxy_params import gal

    mom0_hdu = fits.open(fourteenB_HI_data_path(moment0_name))[0]
    mom0 = Projection(mom0_hdu.data, wcs=WCS(mom0_hdu.header),
                      unit=u.Jy * u.m / u.s)
    mom0.meta["beam"] = Beam.from_fits_header(mom0_hdu.header)

    # Bin size in pc
    dr = 100 * u.pc

    # Create a radial profile of HI
    rs, sd, sd_sigma = surfdens_radial_profile(gal, mom0=mom0, dr=dr,
                                               restfreq=hi_freq)
    rs_n, sd_n, sd_sigma_n = \
        surfdens_radial_profile(gal, mom0=mom0,
                                pa_bounds=Angle([0.5 * np.pi * u.rad,
                                                -0.5 * np.pi * u.rad]),
                                dr=dr, restfreq=hi_freq)
    rs_s, sd_s, sd_sigma_s = \
        surfdens_radial_profile(gal, mom0=mom0,
                                pa_bounds=Angle([-0.5 * np.pi * u.rad,
def cubefit(region='IC348', do_plot=True, 
            snr_min=5.0, multicore=1):
    """
    Fit NH3(1,1) and (2,2) cubes for the requested region. 
    It fits all pixels with SNR larger than requested. 
    Initial guess is based on moment maps and neighboring pixels. 
    The fitting can be done in parallel mode using several cores, 
    however, this is dangerous for large regions, where using a 
    good initial guess is important. 
    It stores the result in a FITS cube. 

    TODO:
    -Store results in hdu list
    -Improve initial guess
    
    Parameters
    ----------
    region : str
        Name of region to reduce
    blorder : int
        order of baseline removed
    do_plot : bool
        If True, then a map of the region to map is shown.
    snr_min : numpy.float
        Minimum signal to noise ratio of the spectrum to be fitted.
    multicore : int
        Numbers of cores to use for parallel processing. 
    """
    if region == 'IC348':
        OneOneFile = 'IC348mm/IC348mm-11_cvel_clean_rob05.fits'
        TwoTwoFile = 'IC348mm/IC348mm-11_cvel_clean_rob05.fits'
        vmin=7.4
        vmax=10.0
        rms=3e-3
    elif region == 'IRAS03282':
        OneOneFile = 'IRAS03282/IRAS03282-11_cvel_clean_rob05.fits'
        TwoTwoFile = 'IRAS03282/IRAS03282-11_cvel_clean_rob05.fits'
        vmin=6.0
        vmax=8.5
        rms=2.5e-3
    elif region == 'L1451mm':
        OneOneFile = 'L1451mm/L1451MM-11_cvel_clean_rob05.fits'
        TwoTwoFile = 'L1451mm/L1451MM-11_cvel_clean_rob05.fits'
        vmin=3.2
        vmax=4.9
        rms=1.6e-3
    else:
        message('Nothing defined here yet... check the regions')
    
    beam11 = Beam.from_fits_header(fits.getheader(OneOneFile))
    beam22 = Beam.from_fits_header(fits.getheader(TwoTwoFile))
    cube11sc = SpectralCube.read(OneOneFile)
    cube22sc = SpectralCube.read(TwoTwoFile)
    xarr11 = SpectroscopicAxis( cube11sc.spectral_axis,
                             refX=freq11,
                             velocity_convention='radio')
    xarr22 = SpectroscopicAxis( cube22sc.spectral_axis,
                             refX=freq22,
                             velocity_convention='radio')

    #errmap11 = fits.getdata(RMSFile)
    vcube11sc = cube11sc.with_spectral_unit(u.km/u.s, rest_value=freq11, velocity_convention='radio')
    vcube22sc = cube22sc.with_spectral_unit(u.km/u.s, rest_value=freq22, velocity_convention='radio')   

    snr = vcube11sc.filled_data[:].value/rms
    peaksnr = np.max(snr,axis=0)
    #rms = np.nanmedian(errmap11)
    errmap11 = np.full( snr.shape[1:], rms)


    planemask = (peaksnr>snr_min) # *(errmap11 < 0.15)
    planemask = remove_small_objects(planemask,min_size=40)
    planemask = opening(planemask,disk(1))
    #planemask = (peaksnr>20) * (errmap11 < 0.2)

    mask = (snr>3)*planemask
    maskcube = vcube11sc.with_mask(mask.astype(bool))
    slab = maskcube.spectral_slab( vmax*u.km/u.s, vmin*u.km/u.s)
    w11=slab.moment( order=0, axis=0).value
    peakloc = np.nanargmax(w11)
    ymax,xmax = np.unravel_index(peakloc,w11.shape)
    moment1 = slab.moment( order=1, axis=0).value
    moment2 = (slab.moment( order=2, axis=0).value)**0.5
    moment2[np.isnan(moment2)]=0.2
    moment2[moment2<0.2]=0.2
    maskmap = w11>0.5
    # PySpecKit cube for NH3(1,1)
    cube11 = pyspeckit.Cube(cube=vcube11sc,maskmap=planemask, xarr=xarr11)
    #cube11 = pyspeckit.Cube(file=OneOneFile,maskmap=planemask)#, xarr=xarr11)
    cube11.cube *= beam11.jtok( freq11)
    cube11.unit="K"
    # PySpecKit cube for NH3(2,2)
    cube22 = pyspeckit.Cube(cube=vcube22sc,maskmap=planemask, xarr=xarr22)
    #cube22 = pyspeckit.Cube(file=TwoTwoFile,maskmap=planemask)#, xarr=xarr22)
    cube22.cube *= beam22.jtok( freq22)
    cube22.unit="K"
#    cubes = pyspeckit.CubeStack([cube11,cube22],maskmap=planemask)
#    cubes.unit="K"
    guesses = np.zeros((6,)+cube11.cube.shape[1:])
    moment1[moment1<vmin] = vmin+0.2
    moment1[moment1>vmax] = vmax-0.2
    guesses[0,:,:] = 12                    # Kinetic temperature 
    guesses[1,:,:] = 8                     # Excitation  Temp
    guesses[2,:,:] = 14.5                  # log(column)
    guesses[3,:,:] = moment2  # Line width / 5 (the NH3 moment overestimates linewidth)               
    guesses[4,:,:] = moment1  # Line centroid              
    guesses[5,:,:] = 0.5                   # F(ortho) - ortho NH3 fraction (fixed)
    if do_plot:
        import matplotlib.pyplot as plt
        plt.imshow( w11, origin='lower')
        plt.show()
    F=False
    T=True
    print('start fit')
    cube11.fiteach(fittype='ammonia',  guesses=guesses,
                  integral=False, verbose_level=3, 
                  fixed=[T,F,F,F,F,T], signal_cut=2,
                  limitedmax=[F,F,T,F,T,T],
                  maxpars=[0,0,17.0,0,vmax,1],
                  limitedmin=[T,T,T,T,T,T],
                  minpars=[5,2.8,12.0,0,vmin,0],
                  start_from_point=(xmax,ymax),
                  use_neighbor_as_guess=True, 
                  position_order = 1/peaksnr,
                  errmap=errmap11, multicore=multicore)

    #fitcubefile = fits.PrimaryHDU(data=np.concatenate([cubes.parcube,cubes.errcube]), header=cubes.header)
    fitcubefile = fits.PrimaryHDU(data=np.concatenate([cube11.parcube,cube11.errcube]), header=cube11.header)
    fitcubefile.header.update('PLANE1','TKIN')
    fitcubefile.header.update('PLANE2','TEX')
    fitcubefile.header.update('PLANE3','COLUMN')
    fitcubefile.header.update('PLANE4','SIGMA')
    fitcubefile.header.update('PLANE5','VELOCITY')
    fitcubefile.header.update('PLANE6','FORTHO')
    fitcubefile.header.update('PLANE7','eTKIN')
    fitcubefile.header.update('PLANE8','eTEX')
    fitcubefile.header.update('PLANE9','eCOLUMN')
    fitcubefile.header.update('PLANE10','eSIGMA')
    fitcubefile.header.update('PLANE11','eVELOCITY')
    fitcubefile.header.update('PLANE12','eFORTHO')
    fitcubefile.header.update('CDELT3',1)
    fitcubefile.header.update('CTYPE3','FITPAR')
    fitcubefile.header.update('CRVAL3',0)
    fitcubefile.header.update('CRPIX3',1)
    fitcubefile.writeto("{0}_parameter_maps_snr{1}.fits".format(region,snr_min),clobber=True)
    convert_param_file(region=region, snr_min=snr_min)
Example #53
0
from uvcombine.uvcombine import feather_kernel, fftmerge, feather_compare


data_path = os.path.expanduser("~/MyRAID/M33/VLA/14B-088/HI/feather_testing")


# high_hdu = fits.open(os.path.join(data_path, "M33_14B-088_HI.clean_channel_820.image_old.fits"))[0]
# high_hdu = fits.open(os.path.join(data_path, "14B-088_HI_LSRK.ms.contsub_channel_1514.clean.image.fits"))[0]
high_hdu = fits.open(os.path.join(data_path, "M33_14B-088_HI.clean_channel_820.image.fits"))[0]
# high_hdu_casa_feather = \
#     fits.open(os.path.join(data_path, "M33_14B-088_HI.clean.image.feathered_channel_820.image.fits"))[0]
low_hdu = fits.open(os.path.join(data_path, "M33_14B-088_HI_model_channel_844.image.fits"))[0]
mask = fits.open(os.path.join(data_path, "M33_14B-088_HI_mask_channel_844.fits"))[0]

high_beam = Beam.from_fits_header(high_hdu.header)
low_beam = Beam.from_fits_header(low_hdu.header)

y_size, x_size = high_hdu.shape

pixscale = (3 * u.arcsec).to(u.deg)

# Try removing all NaNed regions
# slicer = (slice(845, 2133), slice(725, 1615))
slicer = (slice(None), slice(None))

# new_shape = (2133 - 845, 1615 - 725)
new_shape = (2560, 2560)

# Ensure Arecibo doesn't have negative values or power outside of the VLA map
high_data = high_hdu.data.copy()[slicer]