Exemple #1
0
def get_psf_secondpeak_old(fn, neighborhood_size=5, threshold=0.01):

    from scipy import ndimage
    from scipy.ndimage import filters

    if fn.endswith('fits'):
        data = fits.getdata(fn)
    else:
        from casatools import image
        ia = image()
        ia.open(fn)
        data = ia.getchunk()
        ia.close()

    if data.ndim > 2:
        data = data.squeeze()
    if data.ndim > 2:
        data = data[0, :, :]

    data_max = filters.maximum_filter(data, neighborhood_size)

    maxima = (data == data_max)
    data_min = filters.minimum_filter(data, neighborhood_size)
    diff = ((data_max - data_min) > threshold)
    maxima[diff == 0] = 0

    labeled, num_objects = ndimage.label(maxima)
    slices = ndimage.find_objects(labeled)
    pkval = [data[slc].max() for slc in slices]

    if len(pkval) >= 2:
        secondmax = sorted(pkval)[-2]
        return secondmax
    else:
        return np.nan
Exemple #2
0
def assert_header_correct(casa_filename):

    fits_filename = tempfile.mktemp()

    # Use CASA to convert back to FITS and use that header as the reference

    ia = image()
    ia.open(casa_filename)
    ia.tofits(fits_filename, stokeslast=False)
    ia.done()
    ia.close()

    # Parse header with WCS - for the purposes of this function
    # we are not interested in keywords/values not in WCS
    reference_wcs = WCS(fits_filename)
    reference_header = reference_wcs.to_header()

    # Now use our wcs_casa2astropy function to create the header and compare
    # the results.
    desc = getdesc(casa_filename)
    actual_wcs = wcs_casa2astropy(desc['_keywords_']['coords'])
    actual_header = actual_wcs.to_header()

    assert sorted(actual_header) == sorted(reference_header)

    for key in reference_header:
        if isinstance(actual_header[key], str):
            assert actual_header[key] == reference_header[key]
        else:
            assert_allclose(actual_header[key], reference_header[key])
Exemple #3
0
def data_vda_beams_image(tmp_path):
    d, h = prepare_adv_data()
    d, h = transpose(d, h, [2, 0, 1])
    d, h = transpose(d, h, [2, 1, 0])
    h['BUNIT'] = ' Jy / beam '
    del h['BMAJ'], h['BMIN'], h['BPA']
    beams = prepare_4_beams()
    hdul = fits.HDUList([fits.PrimaryHDU(data=d, header=h), beams])
    hdul.writeto(tmp_path / 'vda_beams.fits')
    from casatools import image
    ia = image()
    ia.fromfits(infile=tmp_path / 'vda_beams.fits',
                outfile=tmp_path / 'vda_beams.image',
                overwrite=True)
    for (bmaj, bmin, bpa, chan, pol) in beams.data:
        ia.setrestoringbeam(major={
            'unit': 'arcsec',
            'value': bmaj
        },
                            minor={
                                'unit': 'arcsec',
                                'value': bmin
                            },
                            pa={
                                'unit': 'deg',
                                'value': bpa
                            },
                            channel=chan,
                            polarization=pol)
    ia.close()
    return tmp_path / 'vda_beams.image'
Exemple #4
0
def make_casa_testimage(infile, outname):

    infile = str(infile)
    outname = str(outname)

    if not CASA_INSTALLED:
        raise Exception("Attempted to make a CASA test image in a non-CASA "
                        "environment")

    ia = image()

    ia.fromfits(infile=infile, outfile=outname, overwrite=True)
    ia.unlock()
    ia.close()
    ia.done()

    cube = SpectralCube.read(infile)
    if isinstance(cube, VaryingResolutionSpectralCube):
        ia.open(outname)
        # populate restoring beam emptily
        ia.setrestoringbeam(
            major={
                'value': 1.0,
                'unit': 'arcsec'
            },
            minor={
                'value': 1.0,
                'unit': 'arcsec'
            },
            pa={
                'value': 90.0,
                'unit': 'deg'
            },
            channel=len(cube.beams) - 1,
            polarization=-1,
        )
        # populate each beam (hard assumption of 1 poln)
        for channum, beam in enumerate(cube.beams):
            casabdict = {
                'major': {
                    'value': beam.major.to(u.deg).value,
                    'unit': 'deg'
                },
                'minor': {
                    'value': beam.minor.to(u.deg).value,
                    'unit': 'deg'
                },
                'positionangle': {
                    'value': beam.pa.to(u.deg).value,
                    'unit': 'deg'
                }
            }
            ia.setrestoringbeam(beam=casabdict,
                                channel=channum,
                                polarization=0)

        ia.unlock()
        ia.close()
        ia.done()
Exemple #5
0
def image_summary(image):
    """

    Print image summary and returns data and headers

    """
    ia = tools.image()
    ia.open(image)

    # summarize image
    dd = ia.summary()

    npixx, npixy, nch, npol = dd['shape']
    print('Image shape: {0}'.format(dd['shape']))
    imvals = ia.getchunk(0, int(npixx))[:, :, 0, 0]

    ra_inc = dd['incr'][0] * units.radian
    dec_inc = dd['incr'][1] * units.radian

    c = ia.coordmeasures()
    direction = c['measure']['direction']
    az = direction['m0']['value']
    el = direction['m1']['value']
    co0 = coordinates.SkyCoord(ra=np.degrees(az),
                               dec=np.degrees(el),
                               unit=(units.deg, units.deg))
    co0_str = co0.to_string('hmsdms')
    refpix = (dd['refpix'][0], dd['refpix'][1])
    print(f'Coordinates at reference pixel {refpix} are {co0_str}')

    ra_inc = dd['incr'][0] * units.radian
    dec_inc = dd['incr'][1] * units.radian
    print(
        f'RA, Dec increment: {ra_inc.to(units.arcsecond).value}", {dec_inc.to(units.arcsecond).value}"'
    )

    peakx, peaky = np.where(imvals.max() == imvals)
    peakx, peaky = peakx[0], peaky[0]
    print('Peak SNR at pix ({0},{1}) = {2}'.format(peakx, peaky,
                                                   imvals.max() /
                                                   imvals.std()))

    rapeak = co0.ra + (peakx - refpix[0]) * ra_inc
    decpeak = co0.dec + (peaky - refpix[1]) * dec_inc
    copeak = coordinates.SkyCoord(ra=rapeak, dec=decpeak).to_string('hmsdms')
    print(f'Rough coordinates of peak pixel are {copeak}')

    return imvals, dd, c


## Data summary
# import sdmpy
# file = ''
# sdm = sdmpy.SDM(file, use_xsd=False)
# scan = sdm.scan(1)
# tab = sdm['SpectralWindow']
# for row in tab:
#     print(row.getchildren())
Exemple #6
0
def estimate_noise(imagename, linefree_range,
                   noise_function=np.nanstd):
    '''
    Calculate the noise in a cube in line-free channels.

    Should be run on *non-*pb corrected images so the spatial noise
    is flat!

    Estimate will also skip empty channels that do not have any data.
    '''

    if imagename.endswith(".image"):
        try:
            # CASA 6
            import casatools
            ia = casatools.image()
        except ImportError:
            try:
                from taskinit import iatool
                iatool = iatool()
            except ImportError:
                raise ImportError("Could not import CASA (casac).")


        ia.open(imagename)
        data = ia.getchunk().squeeze()
        ia.close()
        ia.done()

    elif imagename.lower().endswith(".fits"):

        cube = SpectralCube.read(imagename)
        data = cube.filled_data[:].value
        del cube

    else:
        raise ValueError("Unsure what kind of file this is.")

    noise_data = np.empty((1,))

    for chan_range in linefree_range:
        for chan in range(chan_range[0], chan_range[1]):
            if chan >= data.shape[-1]:
                continue

            # Skip empty channels
            if np.isnan(data[..., chan]).all():
                continue

            if (data[..., chan] == 0.).all():
                continue

            valid_mask = np.logical_and(data[..., chan] != 0.,
                                        np.isfinite(data[..., chan]))

            noise_data = np.append(noise_data, data[..., chan][valid_mask])

    return noise_function(noise_data)
Exemple #7
0
def display(imname=None):
    """ Show an image
    """

    im = tools.image()
    im.open(imname)
    data = im.getchunk()
    fig = plt.figure(figsize=(10, 8))
    plt.imshow(data.squeeze(), origin='bottom', interpolation='nearest')
    plt.show()
Exemple #8
0
    def __init__(self):
        import os
        from casatools import image, synthesisimager, synthesisdeconvolver
        from casatools import synthesisnormalizer, iterbotsink
        from casatasks import casalog
        from casatasks.private.imagerhelpers.input_parameters import ImagerParameters

        self.ia = image()
        self.si = synthesisimager()
        self.sd = synthesisdeconvolver()
        self.sn = synthesisnormalizer()
        self.ib = iterbotsink()

        self.imagename = 'imtry'
        print("Initialize")
        os.system('rm -rf '+self.imagename+'.*')


        self.niter=100
        self.cycleniter=10
        self.itercount=0

        self.finished=False
        self.stopcode=0

        params = ImagerParameters(
            msname ='point.ms',
            spw='0:10',
            imagename=self.imagename,
            imsize=100,
            cell='5.0arcsec',
            specmode='mfs',
            gridder='standard',
            niter=self.niter,
            cycleniter=self.cycleniter,
            loopgain=0.05,
            deconvolver='hogbom'
        )
        
        self.selpars = params.getSelPars()['ms0']
        self.impars = params.getImagePars()['0']
        self.gridpars = params.getGridPars()['0']
        self.decpars = params.getDecPars()['0']
        self.normpars = params.getNormPars()['0']
        self.weightpars = params.getWeightPars()
        self.iterpars = params.getIterPars()


        self.iters=[]
        self.peaks=[]
        self.peaks_in_mask=[]
        self.fluxes=[]
        self.majcycle=[]
Exemple #9
0
def test_wcs_casa2astropy_linear(tmp_path):

    # Test that things work properly when the WCS coordinates aren't set

    casa_filename = str(tmp_path / 'test.image')

    data = np.random.random((3, 4, 5, 6, 7))

    ia = image()
    ia.fromarray(outfile=casa_filename, pixels=data, log=False)
    ia.close()

    assert_header_correct(casa_filename)
Exemple #10
0
def test_casa_mask(data_adv, tmp_path):

    # This tests the make_casa_mask function which can be used to create a mask
    # file in an existing image.

    cube = SpectralCube.read(data_adv)

    mask_array = np.array([[True, False], [False, False], [True, True]])
    bool_mask = BooleanArrayMask(mask=mask_array,
                                 wcs=cube._wcs,
                                 shape=cube.shape)
    cube = cube.with_mask(bool_mask)

    make_casa_mask(cube,
                   str(tmp_path / 'casa.mask'),
                   add_stokes=False,
                   append_to_image=False,
                   overwrite=True)

    ia = casatools.image()

    ia.open(str(tmp_path / 'casa.mask'))

    casa_mask = ia.getchunk()

    coords = ia.coordsys()

    ia.unlock()
    ia.close()
    ia.done()

    # Test masks
    # Mask array is broadcasted to the cube shape. Mimic this, switch to ints,
    # and transpose to match CASA image.
    compare_mask = np.tile(mask_array, (4, 1, 1)).astype('int16').T
    assert np.all(compare_mask == casa_mask)

    # Test WCS info

    # Convert back to an astropy wcs object so transforms are dealt with.
    casa_wcs = coordsys_to_astropy_wcs(coords.torecord())
    header = casa_wcs.to_header()  # Invokes transform

    # Compare some basic properties EXCLUDING the spectral axis
    assert_allclose(cube.wcs.wcs.crval[:2], casa_wcs.wcs.crval[:2])
    assert_allclose(cube.wcs.wcs.cdelt[:2], casa_wcs.wcs.cdelt[:2])
    assert np.all(list(cube.wcs.wcs.cunit)[:2] == list(casa_wcs.wcs.cunit)[:2])
    assert np.all(list(cube.wcs.wcs.ctype)[:2] == list(casa_wcs.wcs.ctype)[:2])

    assert_allclose(cube.wcs.wcs.crpix, casa_wcs.wcs.crpix)
Exemple #11
0
def getimage(image):
    """
    
    Loads and summarize the image, Peak SNR and position
    
    """
    # load image
    ia = tools.image()
    ia.open(image)

    # summarize image
    dd = ia.summary()
    npixx, npixy, nch, npol = dd['shape']
    print('Image shape: {0}'.format(dd['shape']))
    imvals = ia.getchunk(0, int(npixx))[:, :, 0, 0]
    return imvals
    def __init__(self):
        from casatasks.private.imagerhelpers.imager_base import PySynthesisImager
        from casatasks.private.imagerhelpers.input_parameters import ImagerParameters
        from casatools import image 
        from casatasks import casalog
        import os

        self.ia = image()

        self.imagename = 'imtry'
        self.niter=100
        self.cycleniter=10
        self.itercount=0

        print("Initialize")

        os.system('rm -rf '+self.imagename+'.*')
    
        ## (2) Set up Input Parameters

        paramList = ImagerParameters(
            msname ='point.ms',
            spw='0:10',
            imagename=self.imagename,
            imsize=100,
            cell='5.0arcsec',
            specmode='mfs',
            gridder='standard',
            niter=self.niter,
            cycleniter=self.cycleniter,
            loopgain=0.05,
            deconvolver='hogbom'
        )

        ## (3) Construct the PySynthesisImager object, with all input parameters

        self.imager = PySynthesisImager(params=paramList)

        self.finished=False
        self.stopcode=0

        self.iters=[]
        self.peaks=[]
        self.peaks_in_mask=[]
        self.fluxes=[]
        self.majcycle=[]
def test_getdminfo(tmp_path, shape):

    filename = str(tmp_path / 'test.image')

    data = np.random.random(shape)

    ia = image()
    ia.fromarray(outfile=filename, pixels=data, log=False)
    ia.close()

    tb = table()
    tb.open(filename)
    reference = tb.getdminfo()
    tb.close()

    actual = getdminfo(filename)

    # We include information about endian-ness in the dminfo but CASA doesn't
    actual['*1'].pop('BIGENDIAN')

    # The easiest way to compare the output is simply to compare the output
    # from pformat (checking for dictionary equality doesn't work because of
    # the Numpy arrays inside).
    assert pformat(actual) == pformat(reference)
import os.path

# set up
msname = 'sim_output.ms'
conf_file = 'LWA352_coordinates_mod.cfg'
if len(sys.argv) > 1:
    fitsimage = sys.argv[1]
else:
    fitsimage = 'SKAMid_B2_8h_v3.fits'

assert os.path.exists(fitsimage)
assert 'fits' in fitsimage
image = fitsimage.replace('.fits', '.image')
if not os.path.exists(image):
    print('creating ms image to be used as sky model')
    im = casatools.image()
    im.fromfits(infile=fitsimage, outfile=image)

# get antenna positions
tabname = 'antenna_positions_' + conf_file.split('.cfg')[0] + '.tab'
tb = casatools.table()
tb.fromascii(tabname,
             conf_file,
             firstline=3,
             sep=' ',
             columnnames=['X', 'Y', 'Z', 'DIAM', 'NAME'],
             datatypes=['D', 'D', 'D', 'D', 'A'])
xx = tb.getcol('X')
yy = tb.getcol('Y')
zz = tb.getcol('Z')
diam = tb.getcol('DIAM')
Exemple #15
0
def create_model(snu_ff,
                 nu0,
                 dust_ff_ratio,
                 bandwidth=7.5,
                 startfreq=35.0,
                 offset_position=[0.0, 0.0],
                 direction="J2000 10h00m00.0s -30d00m00.0s",
                 modelname='skymodel_test'):
    '''

    create an ms with a point source with the given spectrum.

    '''

    from casatasks.private import simutil
    u = simutil.simutil()

    from casatools import quanta
    from casatools import componentlist
    from casatools import image
    from casatools import measures

    qa = quanta()
    cl = componentlist()
    me = measures()
    ia = image()

    obs_freq = np.linspace(startfreq, startfreq + bandwidth, 1000)

    ff_spect = calc_ff_spect(snu_ff, nu0, obs_freq)
    dust_spect = calc_dust_spect(snu_ff, nu0, dust_ff_ratio, obs_freq)

    comb_spect = ff_spect + dust_spect

    xx = u.direction_splitter(direction)
    qra = xx[1]
    qdec = xx[2]

    qra1 = qa.add(qra, str(offset_position[0]) + "arcsec")
    qdec1 = qa.add(qdec, str(offset_position[1]) + "arcsec")

    xx1 = xx[0] + " " + qa.formxxx(qra1, format='hms',
                                   prec=3) + " " + qa.formxxx(
                                       qdec1, format='dms', prec=4)

    cl.done()  #close any open component list

    cl.addcomponent(flux=1.0, dir=xx1, shape='point')

    # tabularfreq in Hz
    # tabularflux in Jy
    obs_freq_Hz = obs_freq * 1e9
    cl.setspectrum(which=0,
                   type='tabular',
                   tabularfreqs=obs_freq_Hz,
                   tabularflux=comb_spect)

    filename = modelname + '.cl'
    if os.path.exists(filename):
        shutil.rmtree(filename)
    cl.rename(filename)

    # make a skymodel from the component list since simobserve
    # doesn't handle the component lists with frequency dependence.
    # Don't need header info. can set that in simobserve
    ia.done()

    filename = modelname + ".image"
    if os.path.exists(filename):
        shutil.rmtree(filename)

    ia.fromshape(filename, [300, 300, 1, len(obs_freq)], overwrite=True)
    cs = ia.coordsys()

    cs.setunits(['deg', 'deg', '', 'GHz'])
    cell_rad = qa.convert(qa.quantity("0.1arcsec"), "deg")['value']
    cs.setincrement([-cell_rad, cell_rad], 'direction')

    cs.setreferencepixel(0, type='Spectral')
    cs.setreferencevalue(str(obs_freq[0]) + "GHz", 'Spectral')
    cs.setincrement("%.5fGHz" % np.diff(obs_freq)[0], 'spectral')

    tmp = cs.referencevalue(format='q')
    tmp['quantity']['*1'] = xx[1]
    tmp['quantity']['*2'] = xx[2]
    cs.setreferencevalue(value=tmp)

    ia.setcoordsys(cs.torecord())
    ia.setbrightnessunit("Jy/pixel")
    ia.modify(cl.torecord(), subtract=False)

    ia.done()
    cl.done()
Exemple #16
0
def makePB(
    vis="",
    field="",
    spw="",
    timerange="",
    uvrange="",
    antenna="",
    observation="",
    intent="",
    scan="",
    imtemplate="",
    outimage="",
    pblimit=0.2,
    stokes="",
):
    """
    (modified from casarecipes.makepb to support multiple stokes)

    Make a PB image using the imager tool, onto a specified image coordinate system

    This function can be used along with tclean to make .pb images for gridders that
    do not already do it (i.e. other than mosaic, awproject)

    This script takes an image to use as a template coordinate system,
    attempts to set up an identical coordinate system with the old imager tool,
    makes a PB for the telescope listed in the MS observation subtable, and
    regrids it (just in case) to the target coordinate system). This can be used for
    single fields and mosaics.
    """

    tb = casatools.table()
    im = casatools.imager()
    ia = casatools.image()
    me = casatools.measures()
    qa = casatools.quanta()

    print("MAKEPB : Making a PB image using the imager tool")

    tb.open(vis + "/OBSERVATION")
    tel = tb.getcol("TELESCOPE_NAME")[0]
    tb.close()

    tb.open(vis + "/SPECTRAL_WINDOW")
    mfreqref = tb.getcol("MEAS_FREQ_REF")[0]
    tb.close()
    if mfreqref == 64:
        print(
            "MAKEPB : This function is using old imager tool, Undefined frame may not be handled properly."
        )

    print("MAKEPB : Making PB for ", tel)

    ia.open(imtemplate)
    csysa = ia.coordsys()
    csys = csysa.torecord()
    shp = ia.shape()
    ia.close()
    dirs = csys["direction0"]
    phasecenter = me.direction(
        dirs["system"],
        qa.quantity(dirs["crval"][0], dirs["units"][0]),
        qa.quantity(dirs["crval"][1], dirs["units"][1]),
    )
    cellx = qa.quantity(fabs(dirs["cdelt"][0]), dirs["units"][0])
    celly = qa.quantity(fabs(dirs["cdelt"][1]), dirs["units"][1])
    nchan = shp[3]
    start = qa.quantity(csysa.referencevalue()["numeric"][3],
                        csysa.units()[3])  # assumes refpix is zero
    mestart = me.frequency("LSRK", start)
    step = qa.quantity(csysa.increment()["numeric"][3], csysa.units()[3])

    smode = "mfs"
    if nchan > 1:
        smode = "frequency"

    print("MAKEPB : Starting imager tool")

    im.open(vis)
    im.selectvis(
        field=field,
        spw=spw,
        time=timerange,
        intent=intent,
        scan=scan,
        uvrange=uvrange,
        baseline=antenna,
        observation=observation,
    )
    im.defineimage(
        nx=shp[0],
        ny=shp[0],
        phasecenter=phasecenter,
        cellx=qa.tos(cellx),
        celly=qa.tos(celly),
        nchan=nchan,
        start=mestart,
        step=step,
        mode=smode,
        stokes=stokes,
    )
    im.setvp(dovp=True, telescope=tel)
    im.makeimage(type="pb", image=outimage + ".tmp")
    im.close()

    if mfreqref == 64:  # skip this step if the frame is 'Undefined'

        shutil.copytree(outimage + ".tmp", outimage)

    else:

        print("MAKEPB : Regrid to desired coordinate system")

        imregrid(
            imagename=outimage + ".tmp",
            template=imtemplate,
            output=outimage,
            overwrite=True,
            asvelocity=False,
        )

    shutil.rmtree(outimage + ".tmp")

    print("MAKEPB : Set mask to pblimit")

    ia.open(outimage)
    ia.calcmask("'" + outimage + "'>" + str(pblimit))
    ia.close()
Exemple #17
0
def test_casa_masking():
    with tempfile.TemporaryDirectory() as tmpdir:
        # SIMULATE SOME DATA SET

        # Define antennas
        diam = [25, 25, 25, 25, 25]
        xx = [50, 100, 150, 200, 250]
        yy = [2, -5, -20, -50, -100]
        zz = [-0.5, -1.0, -1.5, -2.0, -2.5]

        sm = simulator()
        sm.open(tmpdir + '/SIM.ms')
        # do configuration
        posvla = me.observatory('VLA')
        sm.setconfig(telescopename='VLA',
                     x=xx,
                     y=yy,
                     z=zz,
                     dishdiameter=diam,
                     mount='alt-az',
                     antname='VLA',
                     coordsystem='local',
                     referencelocation=posvla)

        # Initialize the spectral windows
        sm.setspwindow(spwname='CBand',
                       freq='5GHz',
                       deltafreq='50MHz',
                       freqresolution='50MHz',
                       nchannels=1,
                       stokes='RR RL LR LL')

        # Initialize the source and calibrater
        sm.setfield(sourcename='My cal',
                    sourcedirection=['J2000', '00h0m0.0', '+45.0.0.000'],
                    calcode='A')
        sm.setfield(sourcename='My source',
                    sourcedirection=['J2000', '01h0m0.0', '+47.0.0.000'])

        sm.setlimits(shadowlimit=0.001, elevationlimit='8.0deg')
        sm.setauto(autocorrwt=0.0)

        sm.settimes(integrationtime='10s',
                    usehourangle=False,
                    referencetime=me.epoch('utc', 'today'))

        sm.observe('My cal', 'CBand', starttime='720s', stoptime='1020s')
        sm.observe('My source', 'CBand', starttime='1030s', stoptime='1500s')

        sm.close()

        # Create mask to use during clean
        reg = EllipseSkyRegion(center=coordinates.SkyCoord(0.0 * u.deg,
                                                           45.0 * u.deg,
                                                           frame='fk5'),
                               width=1.0 * u.arcmin,
                               height=2.0 * u.arcmin,
                               angle=45 * u.deg)
        write_crtf([reg], tmpdir + '/SIM.crtf', 'fk5', '.6f', 'deg')

        # Image the dataset
        tclean(vis=tmpdir + '/SIM.ms',
               imagename=tmpdir + '/SIM',
               imsize=100,
               cell='5arcsec',
               niter=1,
               mask=tmpdir + '/SIM.crtf',
               interactive=False)

        ia = image()
        ia.open(tmpdir + '/SIM.mask')
        mask_array = ia.getregion()
        ia.close()

        with open('data/binary_mask.pkl', 'rb') as f:
            ref_mask = pickle.load(f)

        assert all(mask_array == ref_mask)
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:
        import casatools
        ia = casatools.image()
    except ImportError:
        try:
            from taskinit import iatool
            ia = iatool()
        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:
        # CASA data are apparently transposed.
        data = ia.getchunk().transpose()

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

    # transpose is dealt with within the cube object

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

    wcs = wcs_casa2astropy(casa_cs)

    unit = ia.brightnessunit()

    beam_ = ia.restoringbeam()
    if 'major' in beam_:
        beam = Beam(major=u.Quantity(beam_['major']['value'], unit=beam_['major']['unit']),
                    minor=u.Quantity(beam_['minor']['value'], unit=beam_['minor']['unit']),
                    pa=u.Quantity(beam_['positionangle']['value'], unit=beam_['positionangle']['unit']),
                   )
    elif 'beams' in beam_:
        bdict = beam_['beams']
        if beam_['nStokes'] > 1:
            raise NotImplementedError()
        nbeams = len(bdict)
        assert nbeams == beam_['nChannels']
        stokesidx = '*0'

        majors = [u.Quantity(bdict['*{0}'.format(ii)][stokesidx]['major']['value'],
                             bdict['*{0}'.format(ii)][stokesidx]['major']['unit']) for ii in range(nbeams)]
        minors = [u.Quantity(bdict['*{0}'.format(ii)][stokesidx]['minor']['value'],
                             bdict['*{0}'.format(ii)][stokesidx]['minor']['unit']) for ii in range(nbeams)]
        pas = [u.Quantity(bdict['*{0}'.format(ii)][stokesidx]['positionangle']['value'],
                          bdict['*{0}'.format(ii)][stokesidx]['positionangle']['unit']) for ii in range(nbeams)]

        beams = Beams(major=u.Quantity(majors),
                      minor=u.Quantity(minors),
                      pa=u.Quantity(pas))
    else:
        warnings.warn("No beam information found in CASA image.",
                      BeamWarning)


    # 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,
            'BUNIT': unit}


    if wcs.naxis == 3:
        mask = BooleanArrayMask(np.logical_not(valid), wcs)
        if 'beam' in locals():
            cube = SpectralCube(data, wcs, mask, meta=meta, beam=beam)
        elif 'beams' in locals():
            cube = VaryingResolutionSpectralCube(data, wcs, mask, meta=meta, beams=beams)
        else:
            cube = SpectralCube(data, wcs, mask, meta=meta)
        # we've already loaded the cube into memory because of CASA
        # limitations, so there's no reason to disallow operations
        cube.allow_huge_operations = True

    elif wcs.naxis == 4:
        data, wcs = cube_utils._split_stokes(data, wcs)
        mask = {}
        for component in data:
            data_, wcs_slice = cube_utils._orient(data[component], wcs)
            mask[component] = LazyMask(np.isfinite, data=data[component],
                                       wcs=wcs_slice)

            if 'beam' in locals():
                data[component] = SpectralCube(data_, wcs_slice, mask[component],
                                               meta=meta, beam=beam)
            elif 'beams' in locals():
                data[component] = VaryingResolutionSpectralCube(data_,
                                                                wcs_slice,
                                                                mask[component],
                                                                meta=meta,
                                                                beams=beams)
            else:
                data[component] = SpectralCube(data_, wcs_slice, mask[component],
                                               meta=meta)

            data[component].allow_huge_operations = True


        cube = StokesSpectralCube(stokes_data=data)

    return cube
Exemple #19
0
def make_casa_mask(SpecCube,
                   outname,
                   append_to_image=True,
                   img=None,
                   add_stokes=True,
                   stokes_posn=None,
                   overwrite=False):
    '''
    Outputs the mask attached to the SpectralCube object as a CASA image, or
    optionally appends the mask to a preexisting CASA image.

    Parameters
    ----------
    SpecCube : SpectralCube
        SpectralCube object containing mask.
    outname : str
        Name of the outputted mask file.
    append_to_image : bool, optional
        Appends the mask to a given image.
    img : str, optional
        Image to be appended to. Must be specified if append_to_image is
        enabled.
    add_stokes: bool, optional
        Adds a Stokes axis onto the wcs from SpecCube.
    stokes_posn : int, optional
        Sets the position of the new Stokes axis. Defaults to the last axis.
    overwrite : bool, optional
        Overwrite the image and mask files if they exist?
    '''

    try:
        from casatools import image
        ia = image()
    except ImportError:
        try:
            from taskinit import ia
        except ImportError:
            raise ImportError(
                "Cannot import casa. Must be run in a CASA environment.")

    # the 'mask name' is distinct from the mask _path_
    maskname = os.path.split(outname)[1]
    maskpath = outname

    # Get the header info from the image
    # There's not wcs_astropy2casa (yet), so create a temporary file for
    # CASA to open.
    temp = tempfile.NamedTemporaryFile()
    # CASA is closing this file at some point so set it to manual delete.
    temp2 = tempfile.NamedTemporaryFile(delete=False)

    # Grab wcs
    # Optionally re-add on the Stokes axis
    if add_stokes:
        my_wcs = SpecCube.wcs
        if stokes_posn is None:
            stokes_posn = my_wcs.wcs.naxis

        new_wcs = add_stokes_axis_to_wcs(my_wcs, stokes_posn)
        header = new_wcs.to_header()
        # Transpose the shape so we're adding the axis at the place CASA will
        # recognize. Then transpose back.
        shape = SpecCube.shape[::-1]
        shape = shape[:stokes_posn] + (1, ) + shape[stokes_posn:]
        shape = shape[::-1]
    else:
        # Just grab the header from SpecCube
        header = SpecCube.header
        shape = SpecCube.shape

    hdu = fits.PrimaryHDU(header=header, data=np.empty(shape, dtype='int16'))

    hdu.writeto(temp.name)

    ia.fromfits(infile=temp.name, outfile=temp2.name, overwrite=overwrite)

    temp.close()

    cs = ia.coordsys()

    ia.close()

    temp2.close()

    mask_arr = SpecCube.mask.include()

    # Reshape mask with possible Stokes axis
    mask_arr = mask_arr.reshape(shape)

    # Transpose to match CASA axes
    mask_arr = mask_arr.T

    ia.newimagefromarray(outfile=maskpath,
                         pixels=mask_arr.astype('int16'),
                         overwrite=overwrite)
    ia.close()

    ia.open(maskpath)
    ia.setcoordsys(cs.torecord())

    ia.close()

    if append_to_image:
        if img is None:
            raise TypeError(
                "img argument must be specified to append the mask.")

        ia.open(maskpath)
        ia.calcmask(maskname + ">0.5")
        ia.close()

        ia.open(img)
        ia.maskhandler('copy', [maskpath + ":mask0", maskname])
        ia.maskhandler('set', maskname)
        ia.close()
Exemple #20
0
import pylab as pl

import os
import time
import numpy as np
from astropy.io import fits
from astropy import units as u
from astropy.stats import mad_std
import pylab as pl
import radio_beam
import glob
from spectral_cube import SpectralCube, DaskSpectralCube
from spectral_cube.lower_dimensional_structures import Projection

from casatools import image
ia = image()

if os.getenv('NO_PROGRESSBAR') is None:
    from dask.diagnostics import ProgressBar
    pbar = ProgressBar()
    pbar.register()

nthreads = 1
scheduler = 'synchronous'

os.environ['TEMPDIR'] = '/blue/adamginsburg/adamginsburg/tmp/'

if os.getenv('DASK_THREADS') is not None:
    try:
        nthreads = int(os.getenv('DASK_THREADS'))
        if nthreads > 1:
Exemple #21
0
def fitimage(image,
             outname='tmp.',
             xmin=None,
             xmax=None,
             ymin=None,
             ymax=None,
             displaywindow=300,
             fitwindow=100,
             returnimfit=False,
             estimates=''):
    """
    
    CASA imfit on the image. Reports peak RA, DEC and errors. 
    
    """
    # load image
    ia = tools.image()
    ia.open(image)

    # summarize image
    dd = ia.summary()
    npixx, npixy, nch, npol = dd['shape']
    if xmin is None:
        xmin = 0
    if xmax is None:
        xmax = npixx
    if ymin is None:
        ymin = 0
    if ymax is None:
        ymax = npixy

    print('Image shape: {0}'.format(dd['shape']))
    imvals = ia.getchunk(0, int(npixx))[xmin:xmax, ymin:ymax, 0, 0]
    peakx, peaky = np.where(imvals.max() == imvals)
    print('Peak SNR at ({0},{1}) = {2}'.format(peakx[0], peaky[0],
                                               imvals.max() / imvals.std()))
    #    print('Beam shape: {0}'.format(ia.history()[1].split('\n')[10].split(':')[5]))

    # fit component and write residual image
    box = '{0},{1},{2},{3}'.format(xmin + peakx[0] - fitwindow // 2,
                                   ymin + peaky[0] - fitwindow // 2,
                                   xmin + peakx[0] + fitwindow // 2,
                                   ymin + peaky[0] + fitwindow // 2)
    imfit = ia.fitcomponents(box=box,
                             residual=outname + 'fitresid',
                             estimates=estimates)

    # report on fit
    if imfit['converged']:
        print('{0} element(s) fit'.format(imfit['results']['nelements']))
        direction = imfit['results']['component0']['shape']['direction']

        az = direction['m0']['value']
        el = direction['m1']['value']
        az_err = direction['error']['longitude']['value']
        el_err = direction['error']['latitude']['value']
        print(direction)

        co0 = coordinates.SkyCoord(ra=np.degrees(az),
                                   dec=np.degrees(el),
                                   unit=(units.deg, units.deg))
        #         peak_ra = qa.unit(qa.angle(qa.quantity(az, unitname='rad'), prec=13)[0], unitname='deg')['value']
        #         peak_dec = qa.unit(qa.angle(qa.quantity(el, unitname='rad'), prec=13)[0], unitname='deg')['value']
        print('{0} +- {1}"'.format(co0.ra.degree, az_err))
        print('{0} +- {1}"'.format(co0.dec.degree, el_err))
        print('Fitpeak flux: {0} Jy'.format(
            imfit['results']['component0']['peak']['value']))
        print(co0.to_string('hmsdms'))
    else:
        print('fitcomponents did not converge')

    # load residuals
    ia = tools.image()
    ia.open(outname + 'fitresid')
    dd = ia.summary()
    npixy, npixx, nch, npol = dd['shape']
    residvals = ia.getchunk(0, int(npixx))[xmin:xmax, ymin:ymax, 0, 0]
    peakx_resid, peaky_resid = np.where(residvals.max() == residvals)
    print('Residual SNR at ({0},{1}) = {2}'.format(
        peakx_resid[0], peaky_resid[0],
        residvals.max() / residvals.std()))

    # show results
    plt.figure(figsize=(25, 15))
    plt.subplot(131)
    plt.imshow(imvals.transpose() - imvals.min(),
               interpolation='nearest',
               origin='bottom')
    plt.colorbar()
    plt.subplot(132)

    plt.imshow(
        imvals[peakx[0] - displaywindow // 2:peakx[0] + displaywindow // 2,
               peaky[0] - displaywindow // 2:peaky[0] +
               displaywindow // 2].transpose(),
        interpolation='nearest',
        origin='bottom')
    plt.colorbar()
    plt.subplot(133)
    plt.imshow(
        residvals[peakx[0] - displaywindow // 2:peakx[0] + displaywindow // 2,
                  peaky[0] - displaywindow // 2:peaky[0] +
                  displaywindow // 2].transpose(),
        interpolation='nearest',
        origin='bottom')
    plt.colorbar()

    if returnimfit:
        return imfit
    else:
        return az, el, az_err, el_err
prefix = '/lustre/cv/users/rloomis/research_tickets/mod_pcwd/'

filenames = [
    prefix + 'r-2_c0.02_pcwdT.psf', prefix + 'r0_c0.02_pcwdT.psf',
    prefix + 'r0.5_c0.02_pcwdT.psf', prefix + 'r1_c0.02_pcwdT.psf',
    prefix + 'r2_c0.02_pcwdT.psf', prefix + 'r-2_c0.02_pcwdMOD.psf',
    prefix + 'r0_c0.02_pcwdMOD.psf', prefix + 'r0.5_c0.02_pcwdMOD.psf',
    prefix + 'r1_c0.02_pcwdMOD.psf', prefix + 'r2_c0.02_pcwdMOD.psf',
    prefix + 'r-2_c0.02_pcwdF.psf', prefix + 'r0_c0.02_pcwdF.psf',
    prefix + 'r0.5_c0.02_pcwdF.psf', prefix + 'r1_c0.02_pcwdF.psf',
    prefix + 'r2_c0.02_pcwdF.psf'
]

#filenames=[prefix + 'r2_c0.02_pcwdF.psf']

ia = casatools.image()
npix_window = 31


# ellipse fitting code from: nicky.vanforeest.com/misc/fitEllipse/fitEllipse.html
# moded a number of typos from original source
def fitEllipse(x, y):
    x = x[:, np.newaxis]
    y = y[:, np.newaxis]
    D = np.hstack((x * x, x * y, y * y, x, y, np.ones_like(x)))
    S = np.dot(D.T, D)
    C = np.zeros([6, 6])
    C[0, 2] = C[2, 0] = 2
    C[1, 1] = -1
    E, V = linalg.eig(np.dot(linalg.inv(S), C))
    n = np.argmax(E)
import pytest
import numpy as np
from numpy.testing import assert_allclose
import os

from astropy import units as u

from ..io.casa_masks import make_casa_mask
from ..io.casa_image import wcs_casa2astropy
from .. import SpectralCube, BooleanArrayMask, VaryingResolutionSpectralCube
from . import path

try:
    import casatools
    ia = casatools.image()
    casaOK = True
except ImportError:
    try:
        from taskinit import ia
        casaOK = True
    except ImportError:
        print("Run in CASA environment.")
        casaOK = False


def make_casa_testimage(infile, outname):

    if not casaOK:
        raise Exception("Attempted to make a CASA test image in a non-CASA "
                        "environment")
Exemple #24
0
def test_casa_image_dask_reader(tmpdir, memmap, shape):

    # Unit tests for the low-level casa_image_dask_reader function which can
    # read a CASA image or mask to a Dask array.

    reference = np.random.random(shape).astype(np.float32)

    # CASA seems to have precision issues when computing masks with values
    # very close to e.g. 0.5 in >0.5. To avoid this, we filter out random
    # values close to the boundaries that we use below.
    reference[np.isclose(reference, 0.2)] += 0.05
    reference[np.isclose(reference, 0.5)] += 0.05
    reference[np.isclose(reference, 0.8)] += 0.05

    os.chdir(tmpdir.strpath)

    # Start off with a simple example with no mask. Note that CASA requires
    # the array to be transposed in order to match what we would expect.

    ia = image()
    ia.fromarray('basic.image', pixels=reference.T, log=False)
    ia.close()

    array1 = casa_image_dask_reader('basic.image', memmap=memmap)
    assert array1.dtype == np.float32
    assert_allclose(array1, reference)

    # Check slicing
    assert_allclose(array1[:2, :1, :3], reference[:2, :1, :3])

    # Try and get a mask - this should fail since there isn't one.

    with pytest.raises(FileNotFoundError):
        casa_image_dask_reader('basic.image', mask=True, memmap=memmap)

    # Now create an array with a simple uniform mask.

    ia = image()
    ia.fromarray('scalar_mask.image', pixels=reference.T, log=False)
    ia.calcmask(mask='T')
    ia.close()

    array2 = casa_image_dask_reader('scalar_mask.image', memmap=memmap)
    assert_allclose(array2, reference)

    mask2 = casa_image_dask_reader('scalar_mask.image',
                                   mask=True,
                                   memmap=memmap)
    assert mask2.dtype is np.dtype('bool')
    assert mask2.shape == array2.shape
    assert np.all(mask2)

    # Check with a full 3-d mask

    ia = image()
    ia.fromarray('array_mask.image', pixels=reference.T, log=False)
    ia.calcmask(mask='array_mask.image>0.5')
    ia.close()

    array3 = casa_image_dask_reader('array_mask.image', memmap=memmap)
    assert_allclose(array3, reference)

    mask3 = casa_image_dask_reader('array_mask.image',
                                   mask=True,
                                   memmap=memmap)
    assert_allclose(mask3, reference > 0.5)

    # Check slicing
    assert_allclose(mask3[:2, :1, :3], (reference > 0.5)[:2, :1, :3])

    # Test specifying the mask name

    ia = image()
    ia.fromarray('array_masks.image', pixels=reference.T, log=False)
    ia.calcmask(mask='array_masks.image>0.5')
    ia.calcmask(mask='array_masks.image>0.2')
    ia.calcmask(mask='array_masks.image>0.8', name='gt08')
    ia.close()

    array4 = casa_image_dask_reader('array_masks.image', memmap=memmap)
    assert_allclose(array4, reference)

    mask4 = casa_image_dask_reader('array_masks.image',
                                   mask=True,
                                   memmap=memmap)
    assert_allclose(mask4, reference > 0.5)

    mask5 = casa_image_dask_reader('array_masks.image',
                                   mask='mask0',
                                   memmap=memmap)
    assert_allclose(mask5, reference > 0.5)

    mask6 = casa_image_dask_reader('array_masks.image',
                                   mask='mask1',
                                   memmap=memmap)
    assert_allclose(mask6, reference > 0.2)

    mask7 = casa_image_dask_reader('array_masks.image',
                                   mask='gt08',
                                   memmap=memmap)
    assert_allclose(mask7, reference > 0.8)

    # Check that things still work if we write the array out with doubles

    reference = np.random.random(shape).astype(np.float64)

    ia = image()
    ia.fromarray('double.image', pixels=reference.T, type='d', log=False)
    ia.close()

    array8 = casa_image_dask_reader('double.image', memmap=memmap)
    assert array8.dtype == np.float64
    assert_allclose(array8, reference)
Exemple #25
0
def make_casa_mask(SpecCube, outname, append_to_image=True,
                   img=None, add_stokes=True, stokes_posn=None,
                   overwrite=False
                  ):
    '''
    Outputs the mask attached to the SpectralCube object as a CASA image, or
    optionally appends the mask to a preexisting CASA image.

    Parameters
    ----------
    SpecCube : SpectralCube
        SpectralCube object containing mask.
    outname : str
        Name of the outputted mask file.
    append_to_image : bool, optional
        Appends the mask to a given image.
    img : str, optional
        Image to be appended to. Must be specified if append_to_image is
        enabled.
    add_stokes: bool, optional
        Adds a Stokes axis onto the wcs from SpecCube.
    stokes_posn : int, optional
        Sets the position of the new Stokes axis. Defaults to the last axis.
    overwrite : bool, optional
        Overwrite the image and mask files if they exist?
    '''

    try:
        from casatools import image
        ia = image()
    except ImportError:
        try:
            from taskinit import ia
        except ImportError:
            raise ImportError("Cannot import casa. Must be run in a CASA environment.")

    # the 'mask name' is distinct from the mask _path_
    maskname = os.path.split(outname)[1]
    maskpath = outname

    # Get the header info from the image
    # There's not wcs_astropy2casa (yet), so create a temporary file for
    # CASA to open.
    temp = tempfile.NamedTemporaryFile()
    # CASA is closing this file at some point so set it to manual delete.
    temp2 = tempfile.NamedTemporaryFile(delete=False)

    # Grab wcs
    # Optionally re-add on the Stokes axis
    if add_stokes:
        my_wcs = SpecCube.wcs
        if stokes_posn is None:
            stokes_posn = my_wcs.wcs.naxis

        new_wcs = add_stokes_axis_to_wcs(my_wcs, stokes_posn)
        header = new_wcs.to_header()
        # Transpose the shape so we're adding the axis at the place CASA will
        # recognize. Then transpose back.
        shape = SpecCube.shape[::-1]
        shape = shape[:stokes_posn] + (1,) + shape[stokes_posn:]
        shape = shape[::-1]
    else:
        # Just grab the header from SpecCube
        header = SpecCube.header
        shape = SpecCube.shape

    hdu = fits.PrimaryHDU(header=header,
                          data=np.empty(shape, dtype='int16'))

    hdu.writeto(temp.name)

    ia.fromfits(infile=temp.name, outfile=temp2.name, overwrite=overwrite)

    temp.close()

    cs = ia.coordsys()

    ia.close()

    temp2.close()

    mask_arr = SpecCube.mask.include()

    # Reshape mask with possible Stokes axis
    mask_arr = mask_arr.reshape(shape)

    # Transpose to match CASA axes
    mask_arr = mask_arr.T

    ia.newimagefromarray(outfile=maskpath,
                         pixels=mask_arr.astype('int16'),
                         overwrite=overwrite)
    ia.close()

    ia.open(maskpath)
    ia.setcoordsys(cs.torecord())

    ia.close()

    if append_to_image:
        if img is None:
            raise TypeError("img argument must be specified to append the mask.")

        ia.open(maskpath)
        ia.calcmask(maskname+">0.5")
        ia.close()

        ia.open(img)
        ia.maskhandler('copy', [maskpath+":mask0", maskname])
        ia.maskhandler('set', maskname)
        ia.close()