def mfs_dirty_spws(img, spws, chans): """ Dirty image each supplied spw (MFS) Inputs: img :: Imaging object The Imaging object spws, chans :: lists spectral windows and channels to image Returns: Nothing """ for spw, chan in zip(spws, chans): imagename = "{0}.spw{1}.{2}.mfs".format(img.imfield, spw, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" imagename = os.path.join(img.outdir, imagename) img.logger.info( "Generating dirty image of spw {0} (MFS)...".format(spw)) cleanspw = spw if chan: cleanspw = "{0}:{1}".format(spw, chan) casa.tclean( vis=img.vis, imagename=imagename, phasecenter=img.cp["phasecenter"], field=img.field, spw=cleanspw, specmode="mfs", gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], threshold="0mJy", niter=0, deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, pbcor=False, parallel=img.parallel, ) img.logger.info("Done.") # Generate primary beam image img.logger.info( "Generating primary beam image of spw {0} (MFS)...".format(spw)) makePB( vis=img.vis, field=img.field, spw=spw, uvrange=img.uvrange, stokes=img.stokes, imtemplate="{0}.image".format(imagename), outimage="{0}.pb.image".format(imagename), pblimit=img.cp["pblimit"], ) img.logger.info("Done.") # Primary beam correction img.logger.info("Performing primary beam correction...") casa.impbcor( imagename="{0}.image".format(imagename), pbimage="{0}.pb.image".format(imagename), outfile="{0}.pbcor.image".format(imagename), overwrite=True, ) img.logger.info("Done.") # Export to fits img.logger.info("Exporting fits file...") casa.exportfits( imagename="{0}.pb.image".format(imagename), fitsimage="{0}.pb.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.image".format(imagename), fitsimage="{0}.dirty.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual".format(imagename), fitsimage="{0}.dirty.residual.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image".format(imagename), fitsimage="{0}.dirty.pbcor.image.fits".format(imagename), overwrite=True, history=False, ) img.logger.info("Done.")
def mfs_clean_spws(img, spws, chans, spwtype): """ Clean each supplied spw (MFS) Inputs: img :: Imaging object The Imaging object spws, chans :: lists spectral windows and channels to image spwtype :: string 'line' or 'cont', to determine which clean params to use Returns: Nothing """ for spw, chan in zip(spws, chans): # If not interactive, Lightly clean to get threshold imagename = "{0}.spw{1}.{2}.mfs".format(img.imfield, spw, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" imagename = os.path.join(img.outdir, imagename) cleanspw = spw if chan: cleanspw = "{0}:{1}".format(spw, chan) if not img.interactive: # Save model if necessary savemodel = "none" if img.savemodel == "light": savemodel = "modelcolumn" img.logger.info("Lightly cleaning spw {0} (MFS)...".format(spw)) casa.tclean( vis=img.vis, imagename=imagename, phasecenter=img.cp["phasecenter"], field=img.field, spw=cleanspw, specmode="mfs", gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], threshold="0mJy", niter=img.cp["lightniter"] * len(img.stokes), usemask="auto-multithresh", pbmask=img.cp[spwtype + "pbmask"], sidelobethreshold=img.cp[spwtype + "sidelobethreshold"], noisethreshold=img.cp[spwtype + "noisethreshold"], lownoisethreshold=img.cp[spwtype + "lownoisethreshold"], negativethreshold=img.cp[spwtype + "negativethreshold"], smoothfactor=img.cp[spwtype + "smoothfactor"], minbeamfrac=img.cp[spwtype + "minbeamfrac"], cutthreshold=img.cp[spwtype + "cutthreshold"], growiterations=img.cp[spwtype + "growiterations"], deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, savemodel=savemodel, pbcor=False, restart=True, calcres=False, calcpsf=False, parallel=img.parallel, ) img.logger.info("Done.") # Get RMS of residuals dat = casa.imstat( imagename="{0}.residual".format(imagename), axes=[0, 1], mask="'{0}.mask' == 0".format(imagename), ) img.logger.info("Max un-masked RMS: {0:.2f} mJy/beam".format( 1000.0 * np.max(dat["rms"]))) img.logger.info( "Max un-masked MAD*1.4826: {0:.2f} mJy/beam".format( 1000.0 * 1.4826 * np.max(dat["medabsdevmed"]))) img.logger.info( "Using max(MAD) x 1.4826 x {0} as threshold".format( img.cp["nrms"])) threshold = "{0:.2f}mJy".format(img.cp["nrms"] * 1000.0 * 1.4826 * np.max(dat["medabsdevmed"])) else: threshold = "0.0mJy" # Clean to threshold # Save model if necessary savemodel = "none" if img.savemodel == "clean": savemodel = "modelcolumn" img.logger.info("Cleaning spw {0} (MFS) to threshold: {1}...".format( spw, threshold)) casa.tclean( vis=img.vis, imagename=imagename, field=img.field, phasecenter=img.cp["phasecenter"], spw=cleanspw, gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], specmode="mfs", threshold=threshold, niter=img.cp["maxniter"] * len(img.stokes), usemask="auto-multithresh", pbmask=img.cp[spwtype + "pbmask"], sidelobethreshold=img.cp[spwtype + "sidelobethreshold"], noisethreshold=img.cp[spwtype + "noisethreshold"], lownoisethreshold=img.cp[spwtype + "lownoisethreshold"], negativethreshold=img.cp[spwtype + "negativethreshold"], smoothfactor=img.cp[spwtype + "smoothfactor"], minbeamfrac=img.cp[spwtype + "minbeamfrac"], cutthreshold=img.cp[spwtype + "cutthreshold"], growiterations=img.cp[spwtype + "growiterations"], deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, pbcor=False, stokes=img.stokes, savemodel=savemodel, interactive=img.interactive, restart=True, calcres=False, calcpsf=False, parallel=img.parallel, ) img.logger.info("Done.") # Primary beam correction img.logger.info("Performing primary beam correction...") casa.impbcor( imagename="{0}.image".format(imagename), pbimage="{0}.pb.image".format(imagename), outfile="{0}.pbcor.image".format(imagename), overwrite=True, ) img.logger.info("Done.") # Export to fits img.logger.info("Exporting fits file...") casa.exportfits( imagename="{0}.image".format(imagename), fitsimage="{0}.clean.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.mask".format(imagename), fitsimage="{0}.clean.mask.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual".format(imagename), fitsimage="{0}.clean.residual.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image".format(imagename), fitsimage="{0}.clean.pbcor.image.fits".format(imagename), overwrite=True, history=False, ) img.logger.info("Done.")
def mfs_clean_cont(img): """ Clean combined spws using multi-frequency synthesis Inputs: img :: Imaging object The Imaging object Returns: Nothing """ # If not cleaning interactively, lightly clean to get RMS # threshold imagename = "{0}.cont.{1}.mfs".format(img.imfield, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" cleanspw = ",".join([ "{0}:{1}".format(spw, chan) if chan else spw for spw, chan in zip(img.cont_spws, img.cont_chans) ]) if not img.interactive: savemodel = "none" if img.savemodel == "light": savemodel = "modelcolumn" img.logger.info("Lightly cleaning continuum image (MFS)...") casa.tclean( vis=img.vis, imagename=os.path.join(img.outdir, imagename), phasecenter=img.cp["phasecenter"], field=img.field, spw=cleanspw, gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], specmode="mfs", threshold="0mJy", niter=img.cp["lightniter"] * len(img.stokes), usemask="auto-multithresh", pbmask=img.cp["contpbmask"], sidelobethreshold=img.cp["contsidelobethreshold"], noisethreshold=img.cp["contnoisethreshold"], lownoisethreshold=img.cp["contlownoisethreshold"], negativethreshold=img.cp["contnegativethreshold"], smoothfactor=img.cp["contsmoothfactor"], minbeamfrac=img.cp["contminbeamfrac"], cutthreshold=img.cp["contcutthreshold"], growiterations=img.cp["contgrowiterations"], nterms=img.cp["nterms"], deconvolver="mtmfs", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, pbcor=False, restart=True, calcres=False, calcpsf=False, savemodel=savemodel, parallel=img.parallel, ) img.logger.info("Done.") # Get RMS of residuals outside of clean mask dat = casa.imstat( imagename="{0}.residual.tt0".format( os.path.join(img.outdir, imagename)), axes=[0, 1], mask="'{0}.mask' == 0".format(os.path.join(img.outdir, imagename)), ) img.logger.info("Max un-masked RMS: {0:.2f} mJy/beam".format( 1000.0 * np.max(dat["rms"]))) img.logger.info("Max un-masked MAD*1.4826: {0:.2f} mJy/beam".format( 1000.0 * 1.4826 * np.max(dat["medabsdevmed"]))) img.logger.info("Using max(MAD) x 1.4826 x {0} as threshold".format( img.cp["nrms"])) threshold = "{0:.2f}mJy".format(img.cp["nrms"] * 1000.0 * 1.4826 * np.max(dat["medabsdevmed"])) else: # No threshold for interactive clean threshold = "0.0mJy" # Clean to threshold savemodel = "none" if img.savemodel == "clean": savemodel = "modelcolumn" img.logger.info( "Cleaning continuum image (MFS) to threshold: {0}...".format( threshold)) casa.tclean( vis=img.vis, imagename=os.path.join(img.outdir, imagename), phasecenter=img.cp["phasecenter"], field=img.field, spw=cleanspw, gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], specmode="mfs", threshold=threshold, niter=img.cp["maxniter"] * len(img.stokes), usemask="auto-multithresh", pbmask=img.cp["contpbmask"], sidelobethreshold=img.cp["contsidelobethreshold"], noisethreshold=img.cp["contnoisethreshold"], lownoisethreshold=img.cp["contlownoisethreshold"], negativethreshold=img.cp["contnegativethreshold"], smoothfactor=img.cp["contsmoothfactor"], minbeamfrac=img.cp["contminbeamfrac"], cutthreshold=img.cp["contcutthreshold"], growiterations=img.cp["contgrowiterations"], nterms=img.cp["nterms"], deconvolver="mtmfs", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, pbcor=False, stokes=img.stokes, interactive=img.interactive, restart=True, calcres=False, calcpsf=False, savemodel=savemodel, parallel=img.parallel, ) img.logger.info("Done.") # Primary beam correction using PB of center channel img.logger.info("Performing primary beam correction...") # Due to widebandpbcor limitiations, need to go into outdir os.chdir(img.outdir) spwlist = [ int(spw) for chan in img.cp["contpbchan"].split(",") for spw in img.cont_spws ] chanlist = [ int(chan) for chan in img.cp["contpbchan"].split(",") for spw in img.cont_spws ] weightlist = [1.0 for _ in spwlist] casa.widebandpbcor( vis=os.path.join("..", img.vis), imagename=imagename, nterms=img.cp["nterms"], pbmin=img.cp["pblimit"], threshold="0.1mJy", spwlist=spwlist, weightlist=weightlist, chanlist=chanlist, ) img.logger.info("Done.") os.chdir("..") # Export to fits img.logger.info("Exporting fits file...") imagename = os.path.join(img.outdir, imagename) casa.exportfits( imagename="{0}.image.tt0".format(imagename), fitsimage="{0}.clean.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.mask".format(imagename), fitsimage="{0}.clean.mask.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual.tt0".format(imagename), fitsimage="{0}.clean.residual.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.tt0".format(imagename), fitsimage="{0}.clean.pbcor.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.alpha".format(imagename), fitsimage="{0}.clean.pbcor.image.alpha.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.alpha.error".format(imagename), fitsimage="{0}.clean.pbcor.image.alpha.error.fits".format(imagename), overwrite=True, history=False, ) img.logger.info("Done.")
def mfs_dirty_cont(img): """ Dirty image combined spws using multi-frequency synthesis Inputs: img :: Imaging object The Imaging object Returns: Nothing """ imagename = "{0}.cont.{1}.mfs".format(img.imfield, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" img.logger.info("Generating dirty continuum image (MFS)...") cleanspw = ",".join([ "{0}:{1}".format(spw, chan) if chan else spw for spw, chan in zip(img.cont_spws, img.cont_chans) ]) casa.tclean( vis=img.vis, imagename=os.path.join(img.outdir, imagename), phasecenter=img.cp["phasecenter"], field=img.field, spw=cleanspw, gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], specmode="mfs", threshold="0mJy", niter=0, nterms=img.cp["nterms"], deconvolver="mtmfs", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, pbcor=False, parallel=img.parallel, ) img.logger.info("Done.") # Primary beam correction img.logger.info("Performing primary beam correction...") # Due to widebandpbcor limitiations, need to go into outdir os.chdir(img.outdir) spwlist = [ int(spw) for chan in img.cp["contpbchan"].split(",") for spw in img.cont_spws ] chanlist = [ int(chan) for chan in img.cp["contpbchan"].split(",") for spw in img.cont_spws ] weightlist = [1.0 for _ in spwlist] casa.widebandpbcor( vis=os.path.join("..", img.vis), imagename=imagename, nterms=img.cp["nterms"], pbmin=img.cp["pblimit"], threshold="0.1mJy", spwlist=spwlist, weightlist=weightlist, chanlist=chanlist, ) img.logger.info("Done.") os.chdir("..") # Export to fits img.logger.info("Exporting fits file...") casa.exportfits( imagename="{0}/{1}.pbcor.workdirectory/{1}.pb.tt0".format( img.outdir, imagename), fitsimage="{0}/{1}.pb.fits".format(img.outdir, imagename), overwrite=True, history=False, ) imagename = os.path.join(img.outdir, imagename) casa.exportfits( imagename="{0}.image.tt0".format(imagename), fitsimage="{0}.dirty.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual.tt0".format(imagename), fitsimage="{0}.dirty.residual.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.tt0".format(imagename), fitsimage="{0}.dirty.pbcor.image.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.alpha".format(imagename), fitsimage="{0}.dirty.pbcor.image.alpha.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image.alpha.error".format(imagename), fitsimage="{0}.dirty.pbcor.image.alpha.error.fits".format(imagename), overwrite=True, history=False, ) img.logger.info("Done.")
def smooth_all(field,my_line_spws='',config=None,overwrite=False, linetype='clean',conttype='clean'): """ Smooth all line and continuum images to worst resolution of any individual image Inputs: field = field to analyze my_line_spws = comma separated string of line spws config = ConfigParser object for this project overwrite = if True, overwrite steps as necessary if False, skip steps if output already exists linetype = 'clean' or 'dirty', etc. conttype = 'clean' or 'dirty', etc. Returns: Nothing """ # # start logger # logger = logging.getLogger("main") # # check config # if config is None: logger.critical("Error: Need to supply a config") raise ValueError("Config is None") # # Find beam major axes, minor axes, and position angles for all # available images # logger.info("Finding largest synthesized beam") bmajs = [] bmins = [] bpas = [] contimage = '{0}.cont.mfs.{1}.image.tt0'.format(field,conttype) contpbimage = '{0}.cont.mfs.{1}.pbcor.image.tt0'.format(field,conttype) contresimage = '{0}.cont.mfs.{1}.residual.tt0'.format(field,conttype) if not os.path.isdir(contimage): logger.warn("{0} not found!".format(contimage)) else: bmajs.append(casa.imhead(imagename=contimage,mode='get', hdkey='beammajor')['value']) bmins.append(casa.imhead(imagename=contimage,mode='get', hdkey='beamminor')['value']) bpas.append(casa.imhead(imagename=contimage,mode='get', hdkey='beampa')['value']) for spw in my_line_spws.split(','): lineimage = '{0}.spw{1}.channel.{2}.combeam.pbcor'.format(field,spw,linetype) if not os.path.isdir(lineimage): logger.warn("{0} not found!".format(lineimage)) continue bmajs.append(casa.imhead(imagename=lineimage,mode='get', hdkey='beammajor')['value']) bmins.append(casa.imhead(imagename=lineimage,mode='get', hdkey='beamminor')['value']) bpas.append(casa.imhead(imagename=lineimage,mode='get', hdkey='beampa')['value']) # # Smooth available images to maximum (circular) beam size # + 0.1 pixel size (otherwise imsmooth will complain) # cell_size = float(config.get("Clean","cell").replace('arcsec','')) bmaj_target = np.max(bmajs)+0.1*cell_size bmin_target = np.max(bmajs)+0.1*cell_size bpa_target = 0. logger.info("Smoothing all images to") logger.info("Major axis: {0} arcsec".format(bmaj_target)) logger.info("Minor axis: {0} arcsec".format(bmin_target)) logger.info("Position angle: {0} degs".format(bpa_target)) bmaj_target = {'unit':'arcsec','value':bmaj_target} bmin_target = {'unit':'arcsec','value':bmin_target} bpa_target = {'unit':'deg','value':bpa_target} # Smooth continuum if os.path.isdir(contimage): logger.info("Working on continuum image") outfile='{0}.cont.mfs.{1}.imsmooth'.format(field,conttype) casa.imsmooth(imagename=contimage,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), overwrite=True,history=False) logger.info("Done!") if os.path.isdir(contpbimage): logger.info("Working on continuum PBCorr image") outfile='{0}.cont.mfs.{1}.imsmooth.pbcor'.format(field,conttype) casa.imsmooth(imagename=contpbimage,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), overwrite=True,history=False) logger.info("Done!") if os.path.isdir(contresimage): logger.info("Working on continuum residual image") outfile='{0}.cont.mfs.{1}.imsmooth.residual'.format(field,conttype) casa.imsmooth(imagename=contresimage,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), overwrite=True,history=False) logger.info("Done!") # Smooth lines for spw in my_line_spws.split(','): lineimage = '{0}.spw{1}.channel.{2}.combeam.pbcor'.format(field,spw,linetype) if os.path.isdir(lineimage): logger.info("Working on spw {0}".format(spw)) outfile = '{0}.spw{1}.channel.{2}.imsmooth.pbcor'.format(field,spw,linetype) casa.imsmooth(imagename=lineimage,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), overwrite=True,history=False,velocity=True) logger.info("Done!") logger.info("Done!")
def smooth_all(field, my_line_spws='', config=None, overwrite=False, linetype='clean', conttype='clean'): """ Smooth all line and continuum images to worst resolution of any individual image Inputs: field = field to analyze my_line_spws = comma separated string of line spws config = ConfigParser object for this project overwrite = if True, overwrite steps as necessary if False, skip steps if output already exists linetype = 'clean' or 'dirty', etc. conttype = 'clean' or 'dirty', etc. Returns: Nothing """ # # start logger # logger = logging.getLogger("main") # # check config # if config is None: logger.critical("Error: Need to supply a config") raise ValueError("Config is None") # # Find beam major axes, minor axes, and position angles for all # available images # logger.info("Finding largest synthesized beam") bmajs = [] bmins = [] bpas = [] contimage = '{0}.cont.mfs.{1}.image.tt0'.format(field, conttype) contpbimage = '{0}.cont.mfs.{1}.pbcor.image.tt0'.format(field, conttype) contresimage = '{0}.cont.mfs.{1}.residual.tt0'.format(field, conttype) if not os.path.isdir(contimage): logger.warn("{0} not found!".format(contimage)) else: bmajs.append( casa.imhead(imagename=contimage, mode='get', hdkey='beammajor')['value']) bmins.append( casa.imhead(imagename=contimage, mode='get', hdkey='beamminor')['value']) bpas.append( casa.imhead(imagename=contimage, mode='get', hdkey='beampa')['value']) for spw in my_line_spws.split(','): lineimage = '{0}.spw{1}.channel.{2}.combeam.pbcor'.format( field, spw, linetype) if not os.path.isdir(lineimage): logger.warn("{0} not found!".format(lineimage)) continue bmajs.append( casa.imhead(imagename=lineimage, mode='get', hdkey='beammajor')['value']) bmins.append( casa.imhead(imagename=lineimage, mode='get', hdkey='beamminor')['value']) bpas.append( casa.imhead(imagename=lineimage, mode='get', hdkey='beampa')['value']) # # Smooth available images to maximum (circular) beam size # + 0.1 pixel size (otherwise imsmooth will complain) # cell_size = float(config.get("Clean", "cell").replace('arcsec', '')) bmaj_target = np.max(bmajs) + 0.1 * cell_size bmin_target = np.max(bmajs) + 0.1 * cell_size bpa_target = 0. logger.info("Smoothing all images to") logger.info("Major axis: {0} arcsec".format(bmaj_target)) logger.info("Minor axis: {0} arcsec".format(bmin_target)) logger.info("Position angle: {0} degs".format(bpa_target)) bmaj_target = {'unit': 'arcsec', 'value': bmaj_target} bmin_target = {'unit': 'arcsec', 'value': bmin_target} bpa_target = {'unit': 'deg', 'value': bpa_target} # Smooth continuum if os.path.isdir(contimage): logger.info("Working on continuum image") outfile = '{0}.cont.mfs.{1}.imsmooth'.format(field, conttype) casa.imsmooth(imagename=contimage, kernel='gauss', targetres=True, major=bmaj_target, minor=bmin_target, pa=bpa_target, outfile=outfile, overwrite=overwrite) casa.exportfits(imagename=outfile, fitsimage='{0}.fits'.format(outfile), overwrite=True, history=False) logger.info("Done!") if os.path.isdir(contpbimage): logger.info("Working on continuum PBCorr image") outfile = '{0}.cont.mfs.{1}.imsmooth.pbcor'.format(field, conttype) casa.imsmooth(imagename=contpbimage, kernel='gauss', targetres=True, major=bmaj_target, minor=bmin_target, pa=bpa_target, outfile=outfile, overwrite=overwrite) casa.exportfits(imagename=outfile, fitsimage='{0}.fits'.format(outfile), overwrite=True, history=False) logger.info("Done!") if os.path.isdir(contresimage): logger.info("Working on continuum residual image") outfile = '{0}.cont.mfs.{1}.imsmooth.residual'.format(field, conttype) casa.imsmooth(imagename=contresimage, kernel='gauss', targetres=True, major=bmaj_target, minor=bmin_target, pa=bpa_target, outfile=outfile, overwrite=overwrite) casa.exportfits(imagename=outfile, fitsimage='{0}.fits'.format(outfile), overwrite=True, history=False) logger.info("Done!") # Smooth lines for spw in my_line_spws.split(','): lineimage = '{0}.spw{1}.channel.{2}.combeam.pbcor'.format( field, spw, linetype) if os.path.isdir(lineimage): logger.info("Working on spw {0}".format(spw)) outfile = '{0}.spw{1}.channel.{2}.imsmooth.pbcor'.format( field, spw, linetype) casa.imsmooth(imagename=lineimage, kernel='gauss', targetres=True, major=bmaj_target, minor=bmin_target, pa=bpa_target, outfile=outfile, overwrite=overwrite) casa.exportfits(imagename=outfile, fitsimage='{0}.fits'.format(outfile), overwrite=True, history=False, velocity=True) logger.info("Done!") logger.info("Done!")
def channel_clean_spws(img, spws, spwtype): """ Clean all supplied spws by channel using clean mask from MFS images. Inputs: img :: Imaging object The imaging object spws :: string comma-separated string of spws to image spwtype :: string 'line' or 'cont', to determine which clean params to use Returns: Nothing """ # # Set channel parameters # if spwtype == "cont": restfreqs = [None for spw in spws] start = None width = img.cp["contwidth"] nchans = [None for spw in spws] outframe = img.cp["contoutframe"] veltype = None interpolation = None elif spwtype == "line": spw_inds = [ img.config.get("Spectral Windows", "Line").split(",").index(spw) for spw in spws ] restfreqs = [ img.config.get("Clean", "restfreqs").split(",")[spw_ind] for spw_ind in spw_inds ] outframe = img.cp["lineoutframe"] veltype = img.cp["veltype"] interpolation = img.cp["interpolation"] # Determine velocity-gridding parameter start, width, nchans = grid_parameters(img, spws) else: img.logger.critical("Error: spwtype {0} not supported".format(spwtype)) raise ValueError("Invalid spwtype") # Loop over spws for spw, restfreq, nchan in zip(spws, restfreqs, nchans): # Get niters if nchan is None: # get number of channels from dirty image imagename = "{0}.spw{1}.{2}.channel".format(img.imfield, spw, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" imagename = os.path.join(img.outdir, imagename) imagename = imagename + ".dirty.image.fits" if not os.path.exists(imagename): raise ValueError( "Must create dirty channel cube first: {0}".format(imagename) ) dirty_hdr = fits.getheader(imagename) lightniter = img.cp["lightniter"] * dirty_hdr["NAXIS3"] * len(img.stokes) niter = img.cp["maxniter"] * dirty_hdr["NAXIS3"] * len(img.stokes) else: lightniter = img.cp["lightniter"] * nchan * len(img.stokes) niter = img.cp["maxniter"] * nchan * len(img.stokes) # If not interactive, Lightly clean spw imagename = "{0}.spw{1}.{2}.channel".format(img.imfield, spw, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" mask = "{0}.spw{1}.{2}.mfs.uvtaper.mask".format( img.imfield, spw, img.stokes ) else: mask = "{0}.spw{1}.{2}.mfs.mask".format(img.imfield, spw, img.stokes) imagename = os.path.join(img.outdir, imagename) mask = os.path.join(img.outdir, mask) if not os.path.isdir(mask): img.logger.critical("Error: {0} does not exist".format(mask)) raise ValueError("{0} does not exist".format(mask)) if not img.interactive: img.logger.info( "Lightly cleaning spw {0} (restfreq: {1})...".format(spw, restfreq) ) img.logger.info("Using mask: {0}".format(mask)) casa.tclean( vis=img.vis, imagename=imagename, phasecenter=img.cp["phasecenter"], field=img.field, spw=spw, gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], specmode="cube", threshold="0mJy", niter=lightniter, mask=mask, deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], restfreq=restfreq, start=start, width=width, nchan=nchan, outframe=outframe, veltype=veltype, interpolation=interpolation, uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, pbcor=False, restart=True, calcres=False, calcpsf=False, parallel=img.parallel, ) # This generates a channel mask, so next clean can't # have mfs mask mask = "" # Get RMS of residuals dat = casa.imstat( imagename="{0}.residual".format(imagename), axes=[0, 1], mask="'{0}.mask' == 0".format(imagename), ) img.logger.info( "Max un-masked RMS: {0:.2f} mJy/beam".format( 1000.0 * np.max(dat["rms"]) ) ) img.logger.info( "Max un-masked MAD*1.4826: {0:.2f} mJy/beam".format( 1000.0 * 1.4826 * np.max(dat["medabsdevmed"]) ) ) img.logger.info( "Using max(MAD) x 1.4826 x {0} as threshold".format(img.cp["nrms"]) ) threshold = "{0:.2f}mJy".format( img.cp["nrms"] * 1000.0 * 1.4826 * np.max(dat["medabsdevmed"]) ) else: threshold = "0.0mJy" # Deep clean to threshold img.logger.info( "Cleaning spw {0} (restfreq: {1}) to threshold: {2}...".format( spw, restfreq, threshold ) ) if mask: img.logger.info("Using mask: {0}".format(mask)) casa.tclean( vis=img.vis, imagename=imagename, phasecenter=img.cp["phasecenter"], field=img.field, spw=spw, specmode="cube", gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], threshold=threshold, niter=niter, mask=mask, deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], restfreq=restfreq, start=start, width=width, nchan=nchan, outframe=outframe, veltype=veltype, interpolation=interpolation, uvtaper=img.outertaper, uvrange=img.uvrange, pbcor=False, stokes=img.stokes, interactive=img.interactive, restart=True, calcres=False, calcpsf=False, parallel=img.parallel, ) img.logger.info("Done.") # Primary beam correction pbimage = "{0}.pb.image".format(imagename) img.logger.info("Performing primary beam correction...") if not os.path.exists(pbimage): raise ValueError( "Could not find {0}. Did you dirty MFS first?".format(pbimage) ) casa.impbcor( imagename="{0}.image".format(imagename), pbimage=pbimage, outfile="{0}.pbcor.image".format(imagename), overwrite=True, ) img.logger.info("Done.") # Export to fits img.logger.info("Exporting fits file...") velocity = spwtype == "line" casa.exportfits( imagename="{0}.image".format(imagename), fitsimage="{0}.clean.image.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) casa.exportfits( imagename="{0}.mask".format(imagename), fitsimage="{0}.clean.mask.fits".format(imagename), overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual".format(imagename), fitsimage="{0}.clean.residual.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image".format(imagename), fitsimage="{0}.clean.pbcor.image.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) img.logger.info("Done.")
def channel_dirty_spws(img, spws, spwtype): """ Dirty image each supplied spectral window (channel cube) Inputs: img :: Imaging object The Imaging object spws :: string comma-separated string of spws to image spwtype :: string 'line' or 'cont', to determine which clean params to use Returns: Nothing """ # Set channel parameters if spwtype == "cont": restfreqs = [None for spw in spws] start = None width = img.cp["contwidth"] nchans = [None for spw in spws] outframe = img.cp["contoutframe"] veltype = None interpolation = None elif spwtype == "line": spw_inds = [ img.config.get("Spectral Windows", "Line").split(",").index(spw) for spw in spws ] restfreqs = [ img.config.get("Clean", "restfreqs").split(",")[spw_ind] for spw_ind in spw_inds ] outframe = img.cp["lineoutframe"] veltype = img.cp["veltype"] interpolation = img.cp["interpolation"] # Determine velocity-gridding parameter start, width, nchans = grid_parameters(img, spws) else: img.logger.critical("Error: spwtype {0} not supported".format(spwtype)) raise ValueError("Invalid spwtype") # Loop over spws for spw, restfreq, nchan in zip(spws, restfreqs, nchans): imagename = "{0}.spw{1}.{2}.channel".format(img.imfield, spw, img.stokes) if img.uvtaper: imagename = imagename + ".uvtaper" imagename = os.path.join(img.outdir, imagename) img.logger.info( "Dirty imaging spw {0} (restfreq: {1})...".format(spw, restfreq) ) casa.tclean( vis=img.vis, imagename=imagename, phasecenter=img.cp["phasecenter"], field=img.field, spw=spw, specmode="cube", gridder=img.cp["gridder"], wprojplanes=img.cp["wprojplanes"], threshold="0mJy", niter=0, deconvolver="multiscale", scales=img.cp["scales"], gain=img.cp["gain"], cyclefactor=img.cp["cyclefactor"], imsize=img.cp["imsize"], pblimit=-1.0, cell=img.cp["cell"], weighting=img.cp["weighting"], robust=img.cp["robust"], restfreq=restfreq, start=start, width=width, nchan=nchan, outframe=outframe, veltype=veltype, interpolation=interpolation, uvtaper=img.outertaper, uvrange=img.uvrange, stokes=img.stokes, pbcor=False, parallel=img.parallel, ) img.logger.info("Done.") # Generate primary beam image img.logger.info( "Generating primary beam image of spw {0} (channel)...".format(spw) ) makePB( vis=img.vis, field=img.field, spw=spw, uvrange=img.uvrange, stokes=img.stokes, imtemplate="{0}.image".format(imagename), outimage="{0}.pb.image".format(imagename), pblimit=img.cp["pblimit"], ) # Primary beam correction pbimage = "{0}.pb.image".format(imagename) img.logger.info("Performing primary beam correction...") if not os.path.exists(pbimage): raise ValueError( "Could not find {0}. Did you dirty MFS first?".format(pbimage) ) casa.impbcor( imagename="{0}.image".format(imagename), pbimage=pbimage, outfile="{0}.pbcor.image".format(imagename), overwrite=True, ) img.logger.info("Done.") # Export to fits img.logger.info("Exporting fits file...") velocity = spwtype == "line" casa.exportfits( imagename="{0}.pb.image".format(imagename), fitsimage="{0}.pb.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) casa.exportfits( imagename="{0}.image".format(imagename), fitsimage="{0}.dirty.image.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) casa.exportfits( imagename="{0}.residual".format(imagename), fitsimage="{0}.dirty.residual.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) casa.exportfits( imagename="{0}.pbcor.image".format(imagename), fitsimage="{0}.dirty.pbcor.image.fits".format(imagename), velocity=velocity, overwrite=True, history=False, ) img.logger.info("Done.")
def smooth_all(field, spws='', stokes='', imagetype='clean', mosaic=False, overwrite=False): """ Smooth all line and continuum images/cubes to largest beam size of any individual image/cube. Inputs: field :: string The field to analyze spws :: string comma separated string of spws to smooth stokes :: string The Stokes parameters in the image imagetype :: string What images to process. For example, 'dirty', 'clean', 'dirty.uvtaper', or 'clean.uvtaper' mosaic :: boolean if True, these are mosaic images (.linmos.fits) overwrite :: boolean if True, overwrite existing images Returns: Nothing """ myspws = ['spw{0}'.format(spw) if spw != 'cont' else spw for spw in spws.split(',')] # # Find beam major axes, minor axes, and position angles for all # available images # print("Finding largest synthesized beam") bmajs = [] bmins = [] # images imname = '{0}.{1}.{2}.mfs.{3}.image.fits' if mosaic: imname = '{0}.{1}.{2}.mfs.{3}.image.linmos.fits' images = [imname.format(field, spw, stokes, imagetype) for spw in myspws if os.path.exists(imname.format(field,spw,stokes,imagetype))] # residual images resimages = [image.replace('.image.', '.residual.') for image in images] # cubes imname = '{0}.{1}.{2}.channel.{3}.image.fits' if mosaic: imname = '{0}.{1}.{2}.channel.{3}.image.linmos.fits' cubes = [imname.format(field, spw, stokes, imagetype) for spw in myspws if os.path.exists(imname.format(field,spw,stokes,imagetype))] # residual cubes rescubes = [image.replace('.image.', '.residual.') for image in cubes] for imagename, resimagename in zip(images+cubes, resimages+rescubes): with fits.open(imagename) as imhdulist: bunit = imhdulist[0].header['BUNIT'] if len(imhdulist) > 1: bmaj = imhdulist[1].data['BMAJ'][0] # arcsec bmin = imhdulist[1].data['BMIN'][0] # arcsec bpa = imhdulist[1].data['BPA'][0] else: bmaj = imhdulist[0].header['BMAJ'] * 3600. # arcsec bmin = imhdulist[0].header['BMIN'] * 3600. # arcsec bpa = imhdulist[0].header['BPA'] # check that residual images have beams and units with fits.open(resimagename, 'update') as reshdulist: if 'BMIN' not in reshdulist[0].header: reshdulist[0].header['BMIN'] = bmin/3600. # deg reshdulist[0].header['BMAJ'] = bmaj/3600. # deg reshdulist[0].header['BPA'] = bpa if not reshdulist[0].header['BUNIT']: reshdulist[0].header['BUNIT'] = bunit # check that residual images have units # append bmajs.append(bmaj) bmins.append(bmin) # # Smooth available images to maximum (circular) beam size # + pixel diagonal size (otherwise imsmooth will complain) # cell_size = abs(casa.imhead(imagename)['incr'][0]) * 206265. bmaj_target = np.max(bmajs)+1.42*cell_size bmin_target = np.max(bmajs)+1.42*cell_size bpa_target = 0. print("Smoothing all images to") print("Major axis: {0:.2f} arcsec".format(bmaj_target)) print("Minor axis: {0:.2f} arcsec".format(bmin_target)) print("Position angle: {0:.2f} degs".format(bpa_target)) bmaj_target = {'unit':'arcsec','value':bmaj_target} bmin_target = {'unit':'arcsec','value':bmin_target} bpa_target = {'unit':'deg','value':bpa_target} for imagename, resimagename in zip(images+cubes, resimages+rescubes): # export velocity axis if this is a cube velocity = 'channel' in imagename # smooth image outfile = imagename.replace('.image.fits','.imsmooth.image') if mosaic: outfile = imagename.replace('.image.linmos.fits', '.imsmooth.image.linmos') casa.imsmooth(imagename=imagename,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), velocity=velocity,overwrite=True,history=False) # primary beam correct if not mosaic: smoimagename = outfile pbimage = imagename.replace('.{0}.image.fits'.format(imagetype), '.pb.fits') outfile = imagename.replace('.image.fits', '.pbcor.imsmooth.image') casa.impbcor(imagename=smoimagename, pbimage=pbimage, outfile=outfile, overwrite=True) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), velocity=velocity,overwrite=True,history=False) # check that residual image has beam size, if not add it with fits.open(resimagename, 'update') as hdulist: hdu = hdulist[0] if 'BMIN' not in hdu.header: hdu.header['BMIN'] = bmin_target['value']/3600. hdu.header['BMAJ'] = bmaj_target['value']/3600. hdu.header['BPA'] = bpa_target['value'] # smooth residual image outfile = resimagename.replace('.residual.fits','.imsmooth.residual') if mosaic: outfile = resimagename.replace('.residual.linmos.fits', '.imsmooth.residual.linmos') casa.imsmooth(imagename=resimagename,kernel='gauss', targetres=True,major=bmaj_target,minor=bmin_target, pa=bpa_target,outfile=outfile,overwrite=overwrite) casa.exportfits(imagename=outfile,fitsimage='{0}.fits'.format(outfile), velocity=velocity,overwrite=True,history=False) print("Done!")