def put_rms(imagename, box=''): rms = imhead(imagename=imagename, mode='get', hdkey='rms') if rms is not False: casalog.post('rms already in header') casalog.post('Image rms: %f mJy/beam' % (rms * 1E3, )) return # Get rms casalog.post('Computing rms for: ' + imagename) for dummy in range(5): try: stats = imstat(imagename=imagename, box=box, stokes='I') if box == '': rms = 1.482602219 * stats['medabsdevmed'][0] else: rms = 1. * stats['rms'][0] break except TypeError: casalog.post('Imstat failed, trying again ...') continue # Put in header imhead(imagename=imagename, mode='put', hdkey='rms', hdvalue=rms) casalog.post('Image rms: %f mJy/beam' % (rms * 1E3, ))
def computerms(imagename, lower=0, upper=-1): """ Computes the rms over a given range of channels """ return imstat(imagename,axes=[0,1])['rms'][lower:upper].mean()
def run_makecleancube(vis, imagename, imsize, pixelsize, phasecenter='', restfreq='', specmode='cube', nchan=-1, width='', start=0, datacolumn='data', outframe='LSRK', gridder='mosaic', deconvolver='multiscale', scales=[0, 7, 21, 63], niter=100000, tp_model='', usetpmodel=False, n_cycles=5, nsigma_max=10, nsigma_min=1, parallel=False): """ Code for staggered non-interactive CLEANing in casa. This code employs an automasking technique to identify data above a given threshold. CLEANing commences and stops when this threshold is hit. In the next iteration the previous CLEAN is used as a model for the next cycle. The number of steps in the CLEANing process can be finetuned to avoid divergence. Note that this code requires a dirty cube to be located in the same directory as "imagename". This can be produced using run_makedirtycube. Parameters ---------- vis : casa ms visibility file input visibilities imagename : string w/o extension output file name for the dirty cube. Will be appended with _dirty imsize : array array or x,y list for the size of the output image pixelsize : number size of the pixels. Hard coded for arcseconds tp_model : CASA image single dish model to use for the CLEANing. Must already be tweaked into a useable format usetpmodel : bool Do you want to use this as a model for the CLEANing? default=no - Will use the previous CLEAN image as an input model n_cycles : number number of cycles for the CLEANing nsigma_max : number starting threshold for mask creation. Given as an integer multiple of the rms nsigma_min : number end threshold for mask creation. i.e. CLEAN down to nsigma_min * rms remaining parameters are those sent to tclean """ import os import masking import numpy as np from tasks import tclean, imhead, imstat # define thresholds, from 10 to 1 threshs = np.linspace(nsigma_max, nsigma_min, n_cycles) dirtyimage = '%s_dirty' % imagename #Makes mask and cleans for cycle in range(n_cycles): print '' if usetpmodel: previmage = '%s_cycle%i_tpmodel' % (imagename, cycle - 1) outimage = '%s_cycle%i_tpmodel' % (imagename, cycle) else: previmage = '%s_cycle%i' % (imagename, cycle - 1) outimage = '%s_cycle%i' % (imagename, cycle) print '[INFO] Cleaning cycle %i' % cycle print '[INFO] Making image: %s' % outimage print '' header = imhead(imagename=dirtyimage + '.image', mode='list') major = header['perplanebeams']['median area beam']['major']['value'] minor = header['perplanebeams']['median area beam']['minor']['value'] beam_area = major * minor pixel_area = pixelsize**2 beam_pixel_ratio = beam_area / pixel_area thresh = threshs[cycle] print '' print '[INFO] Cycle thresh: %0.2f rms' % thresh print '' if cycle == 0: dirtyimage_ = '%s.image' % dirtyimage stats = imstat(imagename=dirtyimage_) mad = stats['medabsdevmed'][0] print '' print '[INFO] Cycle rms: %g Jy/beam' % mad print '' mask = masking.make_mask_3d(imagename=dirtyimage, thresh=thresh * mad, fl=False, useimage=True, pixelmin=beam_pixel_ratio * 3, major=major, minor=minor, pixelsize=pixelsize, line=True, overwrite_old=False) if usetpmodel: startmodel = [tp_model] else: startmodel = '' print '[INFO] No model - okay?' else: print '' previmage_ = '%s.image' % previmage stats = imstat(imagename=previmage_) mad = stats['medabsdevmed'][0] print '' print '[INFO] Cycle rms: %g Jy/beam' % mad print '' mask = masking.make_mask_3d(imagename=previmage, thresh=thresh * mad, fl=True, useimage=False, pixelmin=beam_pixel_ratio * 3, major=major, minor=minor, pixelsize=pixelsize, line=True, overwrite_old=False) if usetpmodel: startmodel = [tp_model] else: startmodel = ['%s.model' % previmage] print '' print '[INFO] Using model: %s' % startmodel print '' tclean(vis=vis, datacolumn=datacolumn, imagename=outimage, imsize=imsize, cell=str(pixelsize) + 'arcsec', phasecenter=phasecenter, specmode=specmode, nchan=nchan, start=start, width=width, outframe=outframe, restfreq=restfreq, gridder=gridder, deconvolver=deconvolver, scales=scales, niter=niter, threshold=thresh * mad, interactive=False, mask=mask, startmodel=startmodel, parallel=parallel) #os.system('rm -rf %s.weight' %outimage) #os.system('rm -rf %s.model' %outimage) #os.system('rm -rf %s.psf' %outimage) #os.system('rm -rf %s.sumwt' %outimage) #os.system('rm -rf %s.threshmask' %previmage) #os.system('rm -rf %s.fullmask' %previmage) #os.system('rm -rf %s.fullmask.nopb' %previmage) return
def make_mask_python(image_name, masked_beam=2.0, masked_spec_width=3, masked_snr=2.0, reject_area_in_beams=2): """ image_name: trial_name + '.image' masked_beam: ratio of convolved/origin bmaj/bmin masked_spec_width: num of channels to boxcar. Change in parent script masked_snr: sigma level to keep/remove reject_area_in_beams: Masked area rejected in unit of beam """ image_spat_smo = image_name + '.spat_smo' image_spat_spec_smo = image_name + '.spat_spec_smo' image_snr_cut = image_name + '.spat_spec_smo.snr_cut' image_mask = image_name + '.pymask' # FWHM_TO_AREA = 2 * np.pi / (8 * np.log(2)) # Adapted from Dyas and Adam's script print(" ::z0mgs:: Make mask for the image cube") # # 1) Spatially smooth the cube # # 1-1) Read bmaj, bmin, bpa temp_beam = imhead(image_name)['restoringbeam'] bmaj = temp_beam['major'] bmin = temp_beam['minor'] bpa = temp_beam['positionangle'] bmaj_smo = str(masked_beam*bmaj['value']) + bmaj['unit'] bmin_smo = str(masked_beam*bmin['value']) + bmin['unit'] bpa_smo = str(bpa['value']) + bpa['unit'] # 1-2) Calculate beam area for later use assert imhead(image_name)['axisnames'][0] == 'Right Ascension' assert imhead(image_name)['axisnames'][1] == 'Declination' assert imhead(image_name)['axisunits'][0] == 'rad' assert imhead(image_name)['axisunits'][1] == 'rad' assert bmaj['unit'] == 'arcsec' assert bmin['unit'] == 'arcsec' incr_arcsec = Angle(np.mean(np.abs(imhead(image_name)['incr'][:2])) * u.rad).arcsec bmaj_pix = bmaj['value'] / incr_arcsec bmin_pix = bmin['value'] / incr_arcsec beam_area_pix = bmaj_pix * bmin_pix * FWHM_TO_AREA # 1-3) Convolve the image print(' ::z0mgs:: Smoothed bmaj: ' + bmaj_smo) print(' ::z0mgs:: Smoothed bmin: ' + bmin_smo) print(' ::z0mgs:: Smoothed bpa: ' + bpa_smo) if os.path.isdir(image_spat_smo): rmtree(image_spat_smo) imsmooth( imagename=image_name, targetres=True, major=bmaj_smo, minor=bmin_smo, pa=bpa_smo, outfile=image_spat_smo, overwrite=True) # # 2) Spectrally smooth the cube # # 2-1) Locate the spectral axis im_head = imhead(image_spat_smo) try: freq_axis = np.argwhere(im_head['axisnames'] == 'Frequency')[0, 0] except IndexError: print(' ::z0mgs:: Cannot find the frequency axis!!') print(' ::z0mgs:: Here are the axisnames:') print(' ::z0mgs::', im_head['axisnames']) sys.exit() # 2-2) Read the casa image into numpy array ia.open(image_spat_smo) array_spat_smo = ia.getchunk() # 2-3) boxcar the spectral image according to spectral axis found array_spat_smo_swap = np.moveaxis(array_spat_smo, freq_axis, -1) array_spat_spec_smo_swap = np.empty_like(array_spat_smo_swap) s = array_spat_smo_swap.shape assert len(s) == 4 # Haven't design for other cases if masked_spec_width > 1: if masked_spec_width % 2: w = np.full(masked_spec_width, 1.0 / masked_spec_width) else: w = np.ones(masked_spec_width + 1, dtype=float) w[0] = 0.5 w[-1] = 0.5 w = w / w.sum() for i in range(s[0]): for j in range(s[1]): for k in range(s[2]): array_spat_spec_smo_swap[i, j, k] = \ convolve(array=array_spat_smo_swap[i, j, k], kernel=w, boundary='extend') else: array_spat_spec_smo_swap = array_spat_smo_swap array_spat_spec_smo = np.moveaxis(array_spat_spec_smo_swap, -1, freq_axis) del array_spat_spec_smo_swap, array_spat_smo_swap if os.path.isdir(image_spat_spec_smo): rmtree(image_spat_spec_smo) ia2 = ia.subimage(outfile=image_spat_spec_smo) ia2.putchunk(array_spat_spec_smo) ia.close() ia2.close() # # 3) Estimate the noise level # # 3-1) For comparison, print the directly calculated rms values temp_stats = imstat(image_spat_smo) temp_rms = temp_stats['medabsdevmed'][0] / 0.6745 print(' ::z0mgs:: RMS from spat_smo: ' + str(temp_rms)) temp_stats = imstat(image_spat_spec_smo, algorithm='classic') temp_rms = temp_stats['medabsdevmed'][0] / 0.6745 print(' ::z0mgs:: RMS from spat_spec_smo: ' + str(temp_rms)) # # *) Remove these things first. Make sure I don't use them again # rmtree(image_spat_smo) del image_spat_smo, temp_stats, temp_rms # work_stats = imstat(image_spat_spec_smo, algorithm='chauvenet', zscore=5) work_rms = work_stats['medabsdevmed'][0] / 0.6745 print(' ::z0mgs:: RMS from spat_spec_smo: ' + str(work_rms)) # # 3-2) Finding pixels above the noise level # if os.path.isdir(image_snr_cut): rmtree(image_snr_cut) immath( imagename=image_spat_spec_smo, outfile=image_snr_cut, expr='iif(IM0 >= ' + str(masked_snr*work_rms) + ',1.0,0.0)') # # 4) Reject small region # ia.open(image_snr_cut) mask = ia.getchunk() # ia.done() regions, n_regions = ndimage.label(mask) myhistogram = ndimage.measurements.histogram(regions, 0, n_regions + 1, n_regions + 1) object_slices = ndimage.find_objects(regions) for i in range(n_regions): if myhistogram[i + 1] < reject_area_in_beams * beam_area_pix: mask[object_slices[i]] = 0 # # 4-1) Convert the numpy array into casa image # if os.path.isdir(image_mask): rmtree(image_mask) ia2 = ia.subimage(outfile=image_mask) ia2.putchunk(mask) ia.close() ia2.close() # # Removing junks # rmtree(image_spat_spec_smo) rmtree(image_snr_cut) return image_mask, work_rms
def imaging(vis, trial_name, interactive, imsize, cellsize, glx_ctr, restfreq, specmode, outframe, veltype, restoringbeam, weighting, robust, scales, smallscalebias, dogrowprune, growiterations, noisethreshold, minbeamfrac, sidelobethreshold, gridder, pbmask, pblimit, threshold, niter_in, nsigma, cyclefactor, minpsffraction, gain, w, nchan): # titles = ['.dirty', '', '.2.strong'] # for i in range(2): # niter niter = 0 if i == 0 else niter_in # masking method usemask = 'auto-multithresh' if i == 2 else 'pb' # deconvolver deconvolver = 'multiscale' # tclean(vis=vis, imagename=trial_name, interactive=interactive, intent='*TARGET*', # datacolumn='data', nchan=nchan, start=str(w * nchan / (-2)) + 'km/s', width=str(w) + 'km/s', # Image dimension imsize=imsize, cell=cellsize, phasecenter=glx_ctr, restfreq=restfreq, specmode=specmode, outframe=outframe, veltype=veltype, # Restore to common beam? restoringbeam=restoringbeam, # Weighting weighting=weighting, robust=robust, # Methods deconvolver=deconvolver, scales=scales, gain=gain, smallscalebias=smallscalebias, usemask=usemask, dogrowprune=dogrowprune, growiterations=growiterations, noisethreshold=noisethreshold, minbeamfrac=minbeamfrac, sidelobethreshold=sidelobethreshold, gridder=gridder, pbmask=pbmask, pblimit=pblimit, pbcor=True, # Stopping criteria threshold=threshold, niter=niter, nsigma=nsigma, cyclefactor=cyclefactor, minpsffraction=minpsffraction) # nonpbcube = trial_name + '.image' pbcube = trial_name + '.image.pbcor' cubename = trial_name + '.image.pb' tempcube = trial_name + titles[i] + '.cube.fits' residualname = trial_name + '.residual' tempresidual = trial_name + titles[i] + '.residual.fits' m0name = cubename + '.integrated' tempm0 = trial_name + titles[i] + '.m0.fits' m1name = cubename + '.weighted_coord' tempm1 = trial_name + titles[i] + '.m1.fits' m2name = cubename + '.weighted_dispersion_coord' tempm2 = trial_name + titles[i] + '.m2.fits' for mxname in [m0name, m1name, m2name]: if os.path.isdir(mxname): rmtree(mxname) # print("...Calculating moment maps") if i == 0: rms = imstat(pbcube)['rms'][0] excludepix = [-1000, (2 * rms)] immoments(imagename=pbcube, moments=[0], axis='spectral', excludepix=excludepix, outfile=m0name) else: # calculate mask here # change masked_spec_width according to w if w > 10: spec_width = 1 else: spec_width = 3 mask_dir, work_rms = \ make_mask_python(nonpbcube, masked_beam=2.0, masked_spec_width=spec_width, masked_snr=2.0, reject_area_in_beams=2) # Use the PB corrected image! immoments(imagename=pbcube, moments=[0, 1, 2], axis='spectral', mask=mask_dir, excludepix=-1, outfile=cubename) print("#\n") print("...Exporting fits files of " + titles[i]) for (mxname, fitsname) in zip([pbcube, residualname, m0name, m1name, m2name], [tempcube, tempresidual, tempm0, tempm1, tempm2]): if (mxname in [residualname, m1name, m2name]) and i == 0: continue exportfits(imagename=mxname, fitsimage=fitsname) # Blocking nan pixels if mxname == pbcube: data = fits.getdata(tempcube) nanmask = np.any(np.isnan(data), axis=(0, 1)) del data if mxname in [m0name, m1name, m2name]: print("...Setting " + mxname + " NaNs to zeros") data, hdr = fits.getdata(fitsname, header=True) data[np.isnan(data)] = 0.0 data[0, 0][nanmask] = np.nan fits.writeto(fitsname, data, hdr, overwrite=True) with open(fitsname, 'rb') as f_in: with gzip.open(fitsname + '.gz', 'wb') as f_out: shutil.copyfileobj(f_in, f_out) os.remove(fitsname) if mxname in [m0name, m1name, m2name]: rmtree(mxname) """ print("...Plotting weighted m1 image") plt.ioff() m0 = fits.getdata(tempm0 + '.gz')[0, 0] m1 = fits.getdata(tempm1 + '.gz')[0, 0] # cmap = cm.bwr_r norm = mpl.colors.Normalize(vmin=np.nanmin(m1), vmax=np.nanmax(m1)) m = cm.ScalarMappable(norm=norm, cmap=cmap) with np.errstate(invalid='ignore'): mm = m.to_rgba(m1)[:, :, :3] temp = np.sum(mm, axis=2) for i in range(3): mm[:, :, i] /= temp m0[m0 <= 0] = np.min(m0[m0 > 0]) m0 = np.log10(m0) m0 -= m0.min() m0 /= m0.max() for i in range(3): mm[:, :, i] *= m0 mm /= mm.max() # fig1, ax1 = plt.subplots(figsize=(12, 10)) fig2, ax2 = plt.subplots() mpb = ax2.imshow(m1, cmap='bwr_r', origin='lower') ax1.imshow(mm, origin='lower') ax1.set_xticklabels([]) ax1.set_yticklabels([]) plt.colorbar(mpb, ax=ax1) fig1.savefig(trial_name + titles[i] + '.m1.m0-weighted.png') plt.close('all') """ if i == 1: target = os.getcwd().split('/')[-1] no_detection_check(image=pbcube, pbimage=trial_name + '.pb', target=target, work_rms=work_rms, chanwidth=w)
weighting='briggs', robust=robust, pbcor=False, antenna=antennae, pblimit=0.1) exportfits(imname + ".image.tt0", imname + ".image.tt0.fits", overwrite=True) else: logprint("Skipping completed file {0}".format(imname), origin='almaimf_cont_3sigtemplate') # Get noise statistics: threshold1 = 8 * imstat(imname + ".image.tt0")['rms'] box = ",".join( map(str, [ imsize[0] * 0.7, imsize[1] * 0.7, imsize[0] * 0.8, imsize[1] * 0.8 ])) threshold2 = 8 * imstat(imname + ".image.tt0", box=box)['rms'] # First iteration: clean down to 8*rms with pblimit imname = imname_base + "_shallow_pblimit" if not os.path.exists(imname + ".image.tt0"): tclean(vis=continuum_ms_all, field=field.encode(), imagename=imname, gridder='mosaic', specmode='mfs',