from __future__ import absolute_import import os import shutil import re #import pdb from casatasks.private.casa_transition import is_CASA6 if is_CASA6: from casatools import ctsys from casatasks import concat, imregrid, immath, sdimaging, impbcor, simobserve, simanalyze, feather, casalog from .simutil import * from . import sdbeamutil else: from taskinit import * from simutil import * from simobserve import simobserve from simanalyze import simanalyze from feather import feather from concat import concat from imregrid import imregrid from immath import immath from impbcor import impbcor from sdimaging import sdimaging import sdbeamutil from casa_stack_manip import stack_frame_find def simalma( project=None, dryrun=None, skymodel=None, inbright=None, indirection=None, incell=None, incenter=None, inwidth=None, complist=None, compwidth=None, ######## setpointings=None, ptgfile=None, integration=None, direction=None, mapsize=None, antennalist=None, hourangle=None, totaltime=None, ### tpnant = None, tptime = None, ### pwv=None, image=None, imsize=None, imdirection=None,cell=None, niter=None, threshold=None, graphics=None, verbose=None, overwrite=None ): # Collect a list of parameter values to save inputs in_params = locals() #------------------------- # Create the utility object myutil = simutil(direction) if verbose: myutil.verbose = True msg = myutil.msg try: ########################### # preliminaries ########################### # Predefined parameters pbcoeff = 1.13 ## PB defined as pbcoeff*lambda/d nyquist = 0.5/1.13 ## Nyquist spacing = PB*nyquist maptype_int = 'ALMA' maptype_tp = 'square' # time ratios for 12extended, 12compact,7m, and TP: default_timeratio = [1,0.5,2,4] # pbgridratio_tp = 0.25 # -> would be gridratio_tp = 1/3.4 # the grid spacing is defined in terms of lambda/d times these factors # ALMA OT uses lambda/d/sqrt(3) gridratio_int = 1./pl.sqrt(3) # 0.5 is nyquist gridratio_tp = 1./3 # number of 12m primary beams to pad the total power image during # the gridding stage (i.e. even larger pad than the padding # added for the observation). tppad_npb = 2. # weight of 7m data relative to 12m data weightratio_7_12 = 0.34 # the scale factor to correct expected Gauss PB size to empirical simPB simpb_factor = 0.96 caldirection = "" calflux = "0Jy" tpantid = 0 t_ground = 270. if pwv > 0: thermalnoise = "tsys-atm" else: thermalnoise = "" leakage = 0. weighting = "briggs" antlist_tp_default="aca.tp.cfg" #---------------------------------------- # Save outputs in a directory called "project" fileroot = project # simalma is not supposed to run multiple times. if os.path.exists(fileroot): infomsg = "Project directory, '%s', already exists." % fileroot if overwrite: casalog.post(infomsg) casalog.post("Removing old project directory '%s'" % fileroot) shutil.rmtree(fileroot) else: raise RuntimeError(infomsg) if not os.path.exists(fileroot): os.mkdir(fileroot) concatname=fileroot+"/"+project+".concat" #------------------------- # set up reporting to file, terminal, logger casalog.origin('simalma') if verbose: casalog.filter(level="DEBUG2") v_priority = "INFO" else: v_priority = None simobserr = "simalma caught an exception in task simobserve" simanaerr = "simalma caught an exception in task simanalyze" # open report file myutil.reportfile=fileroot+"/"+project+".simalma.report.txt" myutil.openreport() #---------------------------------------- # Get globals to call saveinputs() # CASA5 only if not is_CASA6: myf = stack_frame_find( ) # Save input parameters of simalma saveinputs = myf['saveinputs'] saveinputs('simalma',fileroot+"/"+project+".simalma.last") # myparams=in_params) else: casalog.post("saveinputs not available in casatasks, skipping saving simalma inputs", priority='WARN') # filename parsing of cfg file here so that the project filenames # can contain the cfg if is_CASA6: repodir = ctsys.resolve("alma/simmos") else: repodir = os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos" #-------------------------- # format mapsize if not is_array_type(mapsize): mapsize = [mapsize, mapsize] elif len(mapsize) < 2: mapsize = [mapsize[0], mapsize[0]] #--------------------------- # Operation flags addnoise = (thermalnoise != '') # Rectangle setup mode multiptg = (not setpointings) \ or (is_array_type(direction) and len(direction) > 1) rectmode = (not multiptg) # Use full model image as a mapsize = ["", ""] fullsize = (len(mapsize[0]) == 0) or (len(mapsize[1]) == 0) ########################### # analyze input sky model ########################### msg("="*60,priority="INFO") msg("Checking the sky model",priority="INFO",origin="simalma") msg(" ",priority="INFO") #---------------------------- # Either skymodel or complist should exist if is_array_type(skymodel): if len(skymodel)>1: msg("You have given more than one skymodel - simalma will only use the first one, "+skymodel[0],priority="INFO") skymodel = skymodel[0] skymodel = skymodel.replace('$project',project) if is_array_type(complist): if len(complist)>1: msg("You have given more than one componentlist - simalma will only use the first one, "+componentlist[0],priority="INFO") complist = complist[0] if((not os.path.exists(skymodel)) and (not os.path.exists(complist))): if len(skymodel)>0: msg("Your skymodel '"+skymodel+"' could not be found.",priority="warn") if len(complist)>0: msg("Your complist '"+complist+"' could not be found.",priority="warn") if len(skymodel)==0 and len(complist)==0: msg("At least one of skymodel or complist must be set.",priority="error") else: msg("No sky input found. At least one of skymodel or complist must exist.",priority="error") #------------------------- # Get model_size and model_center # TODO: check if outmodel==inmodel works (just collect info) if os.path.exists(skymodel): components_only=False outmodel = fileroot+"/"+project+"temp.skymodel" model_vals = myutil.modifymodel(skymodel, outmodel, inbright, indirection, incell, incenter, inwidth, -1, False) shutil.rmtree(outmodel) model_refdir = model_vals[0] model_cell = model_vals[1] model_size = model_vals[2] model_nchan = model_vals[3] model_center = model_vals[4] model_width = model_vals[5] del model_vals msg("You will be simulating from sky model image "+skymodel,priority="info") msg(" pixel(cell) size = "+ qa.tos(model_cell[0]),priority="info") msg(" image size = "+ qa.tos(model_size[0]),priority="info") msg(" reference direction = "+model_refdir,priority="info") if model_nchan>1: msg(" # channels = "+ qa.tos(model_nchan),priority="info") msg(" channel width = "+ qa.tos(model_width),priority="info") else: msg(" single channel / continuum image, with bandwidth = "+qa.tos(model_width),priority="info") if os.path.exists(complist): msg(" ",priority="info") msg("You will also be simulating the components in "+complist,priority="info") msg(" These will get added to a copy of the skymodel image.",priority="info") else: # XXX TODO make sure components AND image work here components_only=True compdirs = [] cl.open(complist) for i in range(cl.length()): compdirs.append(myutil.dir_m2s(cl.getrefdir(i))) model_refdir, coffs = myutil.average_direction(compdirs) model_center = cl.getspectrum(0)['frequency']['m0'] cmax = 0.0014 # ~5 arcsec for i in range(coffs.shape[1]): xc = pl.absolute(coffs[0,i]) # offsets in deg yc = pl.absolute(coffs[1,i]) cmax = max(cmax, xc) cmax = max(cmax, yc) model_size = ["%fdeg" % (2*cmax), "%fdeg" % (2*cmax)] cl.done() model_cell = None model_nchan = 1 del compdirs, coffs, xc, yc, cmax msg("You will be simulating only from component list "+complist,priority="info") msg("Based on the spatial distribution of components, a sky model image will be generated with these parameters:",priority="info") msg(" image size = "+ qa.tos(model_size[0]),priority="info") msg(" reference direction = "+model_refdir,priority="info") msg("and each call to simobserve will chose a skymodel cell size of 1/20 the expected PSF FWHM (to accurately locate components).",priority="info") msg("Simulation from components-only produces a single channel / continuum observation",priority="info") msg(" with bandwidth = "+compwidth,priority="info") #----------------------------------- # determine mapsize - copied code from simobserve # if the user has not input a map size, then use model_size if len(mapsize) == 0: mapsize = model_size msg("setting map size to "+str(model_size)) else: if type(mapsize) == type([]): if len(mapsize[0]) == 0: mapsize = model_size msg("setting map size to "+str(model_size)) if components_only: # if map is greater tham model (defined from components) # then use mapsize as modelsize if type(mapsize) == type([]): map_asec = qa.convert(mapsize[0],"arcsec")['value'] else: map_asec = qa.convert(mapsize,"arcsec")['value'] if type(model_size) == type([]): mod_asec = qa.convert(model_size[0],"arcsec")['value'] else: mod_asec = qa.convert(model_size,"arcsec")['value'] if map_asec>mod_asec: model_size=["%farcsec" % map_asec,"%farcsec" % map_asec] msg(" ",priority="info") msg("You will be mapping an area of size "+qa.tos(mapsize[0])+','+qa.tos(mapsize[1])) ########################### # Calculate 12-m PB and grid spacing for int and tp ########################### Dant = 12. wave_length = 0.2997924/ qa.convert(qa.quantity(model_center),'GHz')['value'] # (wave length)/D_ant in arcsec lambda_D = wave_length / Dant * 3600. * 180 / pl.pi PB12 = qa.quantity(lambda_D*pbcoeff, "arcsec") # Correction factor for PB in simulation # (PS of simulated image is somehow smaller than PB12) PB12sim = qa.mul(PB12, simpb_factor) msg(" primary beam size: %s" % (qa.tos(PB12)),priority="info") # Pointing spacing of observations - define in terms of lambda/d # to avoid ambiguities in primary beam definition. # it would be best for simobserve to accept the shorthand "LD" # but until it does that, we'll divide by pbcoeff and use "PB": # this is a fragile solution since it depends on pbcoeff being # the same in simalma and simobserve. pointingspacing = str(gridratio_int/pbcoeff)+"PB" ptgspacing_tp = qa.tos(qa.mul(PB12sim, (gridratio_tp/pbcoeff))) ########################### # analyze antennalist(s) ########################### if type(antennalist)==type(" "): antennalist=[antennalist] # number of arrays/configurations to run: nconfigs=len(antennalist) msg(" ",priority="info") msg("="*60,priority="info") msg("You are requesting %i configurations:" % nconfigs,origin="simalma",priority="info") configtypes=[] # ALMA, ACA, or ALMASD (latter is special case) cycles=[] resols=[] tp_inconfiglist=False # check filename consistency, get resolution, etc for configfile in antennalist: isalma=0 # antennalist should contain ALMA or ACA if configfile.find(";")>=0: telescopename="BYRES" configparms=configfile.split(";") res=configparms[-1] res_arcsec=-1 if myutil.isquantity(res): if qa.compare(res,"arcsec"): res_arcsec=qa.convert(res,"arcsec")['value'] if res_arcsec>0: resols.append(res_arcsec) else: msg("simalma cannot interpret the antennalist entry '"+configfile+"' as desired array and resolution e.g. ALMA;0.5arcsec",priority="ERROR") else: # we can only verify explicit files right now, not # configs specified as "ALMA;0.5arcsec" # configfile_short = (configfile.split("/"))[-1] # Search order is fileroot/ -> specified path -> repository if len(configfile) > 0: if os.path.exists(fileroot+"/"+configfile): configfile = fileroot + "/" + configfile elif not os.path.exists(configfile) and \ os.path.exists(os.path.join(repodir,configfile)): configfile = os.path.join(repodir,configfile) # Now make sure the configfile exists if not os.path.exists(configfile): msg("Couldn't find configfile: %s" % configfile, priority="error") stnx, stny, stnz, stnd, padnames, antnames, telescopename, posobs = myutil.readantenna(configfile) if telescopename=="ALMASD": resols.append(qa.convert(PB12,'arcsec')['value']) else: psfsize = myutil.approxBeam(configfile,qa.convert(qa.quantity(model_center),'GHz')['value']) resols.append(psfsize) # FWHM in arcsec q = re.compile('CYCLE\d?\d') isCycle = q.search(configfile_short.upper()) if isCycle: whatCycle = isCycle.group()[-1] # will break if cycle>9 cycles.append(whatCycle) else: cycles.append(-1) # -1 is unknown; defaults to full ALMA if configfile_short.upper().find("ALMA") >= 0: if telescopename=="ALMA" or telescopename=="BYRES": configtypes.append("ALMA") isalma=isalma+1 else: msg("Inconsistent antennalist entry '"+configfile_short+"' has ALMA in the name but not set as the observatory",priority="error") if configfile_short.upper().find("ACA") >= 0: if telescopename=="ACA" or telescopename=="BYRES": configtypes.append("ACA") isalma=isalma+1 elif telescopename=="ALMASD" or telescopename=="BYRES": tp_inconfigfile=True configtypes.append("ALMASD") isalma=isalma+1 else: msg("Inconsistent antennalist entry '"+configfile_short+"' has ACA in the name but the observatory is not ACA or ALMASD",priority="error") #if configfile.upper().find("CYCLE0") if isalma==0: s="simalma can't accept antennalist entry '"+configfile_short+"' because it is neither ALMA nor ACA (in the name and the observatory in the file)" msg(s,origin="simalma",priority="error") # raise ValueError, s # not ness - msg2 raises the exception if isalma==2: s="simalma doesn't understand your antennalist entry '"+configfile_short+"'" msg(s,origin="simalma",priority="error") # raise ValueError,s #----------------------------- # total power parameter: tptime_min=0. if myutil.isquantity(tptime,halt=False): if qa.compare(tptime,'s'): tptime_min=qa.convert(tptime,'min')['value'] else: msg("Can't interpret tptime='" +tptime+"' as a time quantity e.g. '3h'", priority="error") else: msg("Can't interpret tptime='" +tptime+"' as a time quantity e.g. '3h'", priority="error") #----------------------------- # is there a mix of cycle0,1,2,etc,full? whatCycle=cycles[0] cyclesInconsistent=False for i in range(nconfigs): if cycles[i]!=whatCycle: cyclesInconsistent=True #----------------------------- # exposure time parameter totaltime totaltime_min=[] if len(totaltime)==1: # scalar input - use defaults totaltime_min0=0. if not myutil.isquantity(totaltime[0],halt=False): raise ValueError("Can't interpret totaltime parameter '"+totaltime[0]+"' as a time quantity - example quantities: '1h', '20min', '3600sec'") if qa.compare(totaltime[0],'s'): totaltime_min0=qa.convert(totaltime[0],'min')['value'] else: raise ValueError("Can't convert totaltime parameter '"+totaltime[0]+"' to minutes - example quantities: '1h', '20min','3600sec'") totaltime_min=pl.zeros(nconfigs) # sort by res'l - TP could still be on here resols=pl.array(resols) intorder=resols.argsort() # assume the scalar user input refers to the highest res 12m totaltime_min[intorder[0]]=totaltime_min0 for j in intorder[1:]: if configtypes[j]=='ALMA': # lower res 12m totaltime_min[j]=totaltime_min0*default_timeratio[1] elif configtypes[j]=='ACA': # 7m totaltime_min[j]=totaltime_min0*default_timeratio[2] elif configtypes[j]=='ALMASD': # tp totaltime_min[j]=totaltime_min0*default_timeratio[3] else: raise ValueError("configuration types = "+str(configtypes)) else: for time in totaltime: if not myutil.isquantity(time,halt=False): raise ValueError("Can't interpret totaltime vector element '"+time+"' as a time quantity - example quantities: '1h', '20min', '3600sec'") if qa.compare(time,'s'): time_min=qa.convert(time,'min')['value'] else: raise ValueError("Can't convert totaltime vector element '"+time+"' to minutes - example quantities: '1h', '20min','3600sec'") totaltime_min.append(time_min) if len(totaltime_min)!=len(antennalist): raise ValueError("totaltime must either be the same length vector as antennalist or a scalar") #----------------------------- # print out what's requested. antlist_tp=None for i in range(nconfigs): configfile=antennalist[i] msg(" ",priority="info") msg(" "+configfile+":",priority="info") if configtypes[i]=="ALMA": msg(" 12m ALMA array",priority="info") elif configtypes[i]=="ACA": msg(" 7m ACA array",priority="info") elif configtypes[i]=="ALMASD": msg(" 12m total power observation",priority="info") if tpnant>0: msg(" This antennalist entry will be ignored in favor of the tpnant requesting %d total power antennas" % tpnant,priority="info") antlist_tp=antlist_tp_default if tptime_min>0: msg(" The total map integration time will be %s minutes as per the tptime parameter." % tptime_min,priority="info") else: tptime_min=totaltime_min[i] msg(" The total map integration time will be %s minutes as per the totaltime parameter." % tptime_min,priority="info") else: # Note: assume the user won't put in >1 TP antlist. msg(" Note: it is preferred to specify total power with the tpnant,tptime parameters so that one can also specify the number of antennas.",priority="info") msg(" Specifying the total power array as one of the antenna configurations will only allow you to use a single antenna for the simulation",priority="info") msg(" simalma will proceed with a single total power antenna observing for %d minutes." % totaltime_min[i],priority="info") tpnant=1 tptime_min=totaltime_min[i] antlist_tp=configfile # print cycle and warn if mixed if cycles[i]>'-1': msg(" This is a cycle "+cycles[i]+" configuration",priority="info") else: msg(" This is a full ALMA configuration",priority="info") if cyclesInconsistent: msg(" WARNING: Your choices of configurations mix different cycles and/or Full ALMA. Assuming you know what you want.",priority="info") if configtypes[i]=='ALMASD': # imsize check for PB: if not components_only: minsize = min(qa.convert(model_size[0],'arcsec')['value'],\ qa.convert(model_size[1],'arcsec')['value']) PB12sec=qa.convert(PB12,"arcsec")['value'] if minsize < 2.5*PB12sec: msg(" WARNING: For TP imaging, skymodel should be larger than 2.5*primary beam. Your skymodel: %.3f arcsec < %.3f arcsec: 2.5*primary beam" % (minsize, 2.5*PB12sec),priority="warn") msg(" Total power imaging when the source is this small is not necessary, and may fail with an error.",priority="warn") del minsize else: # casalog.post resolution for INT, and warn if model_cell too large msg(" approximate synthesized beam FWHM = %f arcsec" % resols[i],priority="info") msg(" (at zenith; the actual beam will depend on declination, hourangle, and uv coverage)",priority="info") if is_array_type(model_cell): cell_asec=qa.convert(model_cell[0],'arcsec')['value'] else: cell_asec=qa.convert(model_cell,'arcsec')['value'] if cell_asec > 0.2*resols[i]: if cell_asec >= resols[i]: # XXX if not dryrun raise exception here msg(" ERROR: your sky model cell %f arcsec is too large to simulate this beam. Simulation will fail" % cell_asec,priority="info") else: msg(" WARNING: your sky model cell %f arcsec does not sample this beam well. Simulation may be unreliable or clean may fail." % cell_asec,priority="info") msg(" Observation time = %f min" % totaltime_min[i],priority="info") if totaltime_min[i]>360: msg(" WARNING: this is longer than 6hr - simalma won't (yet) split the observation into multiple nights, so your results may be unrealistic",priority="info") if not tp_inconfiglist and tpnant>0: msg("",priority="info") if tptime_min>0: msg("You are also requesting Total Power observations:",priority="info") msg(" %d antennas for %f minutes" % (tpnant,tptime_min),priority="info") # imsize check for PB: if not components_only: minsize = min(qa.convert(model_size[0],'arcsec')['value'],\ qa.convert(model_size[1],'arcsec')['value']) PB12sec=qa.convert(PB12,"arcsec")['value'] if minsize < 2.5*PB12sec: msg(" WARNING: For TP imaging, skymodel should be larger than 2.5*primary beam. Your skymodel: %.3f arcsec < %.3f arcsec: 2.5*primary beam" % (minsize, 2.5*PB12sec),priority="warn") msg(" Total power imaging when the source is this small is not necessary, and may fail with an error.",priority="warn") else: msg("You have requested %d total power antennas (tpnant), but no finite integration (tptime) -- check your inputs; no Total Power will be simulated." % tpnant,priority="info") ### WORKAROUND for wrong flux in COMP TP simulations if (tpnant > 0) and os.path.exists(complist): idx_min = pl.where(resols == min(resols))[0] idx = idx_min[0] if len(idx_min) > 0 else 0 dummy_proj = "gen_skymodel" errmsg = "You requested Single dish simulation with components list.\n" errmsg += "Single dish simulation has flux recovery issue "+\ "when using a components list as an input.\n" errmsg += "Please generate compskymodel image first by task "+\ "simobserve and use the image as the skymodel input. " errmsg += "Sorry for the inconvenience.\n\n" errmsg += "How to workaround the issue:\n" errmsg += "1. Generate skymodel image by simobserve\n" errmsg += ("\tsimobserve(project='%s', complist='%s', compwidth='%s', "\ % (dummy_proj, complist, compwidth)) if os.path.exists(skymodel): skysuffix = '.skymodel' errmsg += ( "skymodel='%s', inbright='%s', indirection='%s', " \ % (skymodel, inbright, indirection)) errmsg += ( "incell='%s', incenter='%s', inwidth='%s', " \ % (skymodel, inbright, indirection, incell, incenter, inwidth) ) else: skysuffix = '.compskymodel' errmsg += ("setpointings=True, obsmode='', antennalist='%s', thermalnoise='')\n" \ % antennalist[idx]) errmsg += "2. Use the generated skymodel image in project directory as an input of simalma.\n" errmsg += ("\tsimalma(project='%s', skymodel='%s/%s', complist='', ....)" % \ (project, dummy_proj, \ get_data_prefix(antennalist[idx], dummy_proj)+skysuffix)) msg(errmsg,priority="error") ### End of WORKAROUND # remove tp from configlist antennalist=pl.array(antennalist) configtypes=pl.array(configtypes) totaltime_min=pl.array(totaltime_min) resols=pl.array(resols) z=pl.where(configtypes!='ALMASD')[0] antennalist=antennalist[z] configtypes=configtypes[z] totaltime_min=totaltime_min[z] resols=resols[z] nconfigs=len(antennalist) if nconfigs < 1: msg("No interferometer configuration is requested. At least one interferometer configuration should be selected.", \ origin="simalma", priority="error") # TODO check model_size against mapsize - separately after this? # ########################### # # Resolve prefixes of simulation data (as defined in # # simobserve and simanalyze) # # pref_bl = get_data_prefix(antennalist, project) # pref_aca = get_data_prefix(antlist_aca, project) # Resolve output names (as defined in simobserve and simanalyze) # if addnoise: # msname_bl = pref_bl+".noisy.ms" # msname_aca = pref_aca+".noisy.ms" # msname_tp = pref_tp+".noisy.sd.ms" # #imagename_aca = pref_aca+".noisy.image" # else: # msname_bl = pref_bl+".ms" # msname_aca = pref_aca+".ms" # msname_tp = pref_tp+".sd.ms" # #imagename_aca = pref_aca+".image" # # imagename_tp = project+".sd.image" # imagename_int = project+".concat.image" # msname_concat = project+".concat.ms" # combimage = project+".feather.image" simana_file = project+".simanalyze.last" ############################################################ # run simobserve msg("",priority="info") msg("="*60,priority="info") msg("simalma calls simobserve to simulate each component:",priority="info",origin="simalma") # sort by res'l - save the ptgfile from the max res'l config # for use in TP pointing definition. resols=pl.array(resols) intorder=resols.argsort() pref_bl=get_data_prefix(antennalist[intorder[0]],project) ptgfile_bl=fileroot+"/"+pref_bl+".ptg.txt" step = 0 for i in range(nconfigs): if configtypes[i]=="ALMA": s="12m ALMA array" elif configtypes[i]=='ACA': s="7m ACA array" else: s="12m total power map" if configtypes[i]!='ALMASD': step += 1 msg("",priority="info") msg("-"*60, origin="simalma", priority="warn") msg(("Step %d: simulating " % step)+s, origin="simalma", priority="warn") msg("-"*60, origin="simalma", priority="warn") # filename prefixes pref = get_data_prefix(antennalist[i], project) obsmode_int = 'int' ptgfile_int = fileroot+"/"+pref+".ptg.txt" task_param = {} task_param['project'] = project task_param['skymodel'] = skymodel task_param['inbright'] = inbright task_param['indirection'] = indirection task_param['incell'] = incell task_param['incenter'] = incenter task_param['inwidth'] = inwidth task_param['complist'] = complist task_param['compwidth'] = compwidth task_param['setpointings'] = setpointings task_param['ptgfile'] = ptgfile task_param['integration'] = integration task_param['direction'] = direction task_param['mapsize'] = mapsize task_param['maptype'] = maptype_int # this is approriate for 7m or 12m since its in terms of PB task_param['pointingspacing'] = pointingspacing task_param['caldirection'] = caldirection task_param['calflux'] = calflux task_param['obsmode'] = obsmode_int task_param['hourangle'] = hourangle task_param['totaltime'] = "%fmin" % totaltime_min[i] task_param['antennalist'] = antennalist[i] task_param['sdantlist'] = "" task_param['sdant'] = 0 task_param['thermalnoise'] = thermalnoise task_param['user_pwv'] = pwv task_param['t_ground'] = t_ground task_param['leakage'] = leakage task_param['graphics'] = graphics task_param['verbose'] = verbose task_param['overwrite'] = overwrite msg(get_taskstr('simobserve', task_param), priority="info") if not dryrun: try: simobserve(**task_param) del task_param except: raise RuntimeError(simobserr) finally: casalog.origin('simalma') qimgsize_tp = None if tpnant>0 and tptime_min<=0: raise ValueError("You requested total power (tpnant=%d) but did not specify a valid nonzero tptime" % tpnant) mslist_tp = [] if tptime_min>0: ######################################################## # ACA-TP simulation - always do this last obsmode_sd = "sd" step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="warn") msg(("Step %d: simulating Total Power" % step), origin="simalma", priority="warn") msg("-"*60, origin="simalma", priority="warn") if antlist_tp is None: antlist_tp = antlist_tp_default pref_tp = get_data_prefix(antlist_tp, project) if addnoise: msname_tp = pref_tp+".noisy.sd.ms" else: msname_tp = pref_tp+".sd.ms" ########################### # Resolve pointing directions of ACA-TP. # # Pointing directions of TP simulation is defined as follows: # # [I] if ALMA-12m maps a rectangle region (rectmode=T), # TP maps slightly larger region than ALMA-12m by adding 1 PB to # mapsize (pointing extent of ALMA-12m). # # [II] if a list of pointing deirections are specified for the # ALMA-12m observation (multiptg=T), TP pointings are defined as # rectangle areas of 2PB x 2PB centered at each pointing direction # of ALMA-12m. However, in some cases, it is more efficient to # just map a rectangle region that covers all ALMA-12m pointings. # In such case, ACA-TP maps a rectangle region whose extent is 2PB # larger than the extent of all ALMA-12m pointings. if rectmode: # Add 1PB to mapsize if fullsize: mapx = qa.add(PB12,model_size[0]) # in the unit same as PB mapy = qa.add(PB12,model_size[1]) # in the unit same as PB mapsize_tp = [qa.tos(mapx), qa.tos(mapy)] msg("The full skymodel is being mapped by ALMA 12-m and ACA 7-m arrays. The total power antenna observes 1PB larger extent.", origin="simalma", priority='warn') else: # mapsize is defined. Add 1 PB to mapsize. mapx = qa.add(qa.quantity(mapsize[0]), PB12) mapy = qa.add(qa.quantity(mapsize[1]), PB12) mapsize_tp = [qa.tos(mapx), qa.tos(mapy)] msg("Only part of the skymodel is being mapped by ALMA 12-m and ACA 7-m arrays. The total power antenna observes 1PB larger extent.", priority='warn') else: # multi-pointing mode npts, pointings, time = myutil.read_pointings(ptgfile_bl) center, offsets = myutil.average_direction(pointings) del time qx = qa.quantity(max(offsets[0])-min(offsets[0]),"deg") qy = qa.quantity(max(offsets[1])-min(offsets[1]),"deg") # map extent to cover all pointings + 2PB mapx = qa.add(qa.mul(PB12,2.),qx) # in the unit same as PB mapy = qa.add(qa.mul(PB12,2.),qy) # in the unit same as PB mapsize_tp = [qa.tos(mapx), qa.tos(mapy)] # number of pointings to map vicinity of each pointings qptgspc_tp = qa.quantity(ptgspacing_tp) dirs_multi_tp = myutil.calc_pointings2(qptgspc_tp, qa.tos(qa.mul(PB12,2.)), "square", pointings[0]) npts_multi = npts * len(dirs_multi_tp) msg("Number of pointings to map vicinity of each direction = %d" % npts_multi) del qptgspc_tp, dirs_multi_tp # save imsize for TP image generation # qimgsize_tp = [mapx, mapy] # for imaging later, we need to pad even more! mapx_im = qa.add(mapx, qa.mul(PB12,(2*tppad_npb))) mapy_im = qa.add(mapy, qa.mul(PB12,(2*tppad_npb))) qimgsize_tp = [mapx_im, mapy_im] qptgspc_tp = qa.quantity(ptgspacing_tp) pbunit = PB12['unit'] # number of pointings to map pointing region # TODO: use calc pointings for consistent calculation npts_rect = int(qa.convert(mapx, pbunit)['value'] \ / qa.convert(qptgspc_tp, pbunit)['value']) \ * int(qa.convert(mapy, pbunit)['value'] \ / qa.convert(qptgspc_tp, pbunit)['value']) msg("Number of pointings to map a rect region = %d" % npts_rect, priority="DEBUG2") if rectmode: dir_tp = direction npts_tp = npts_rect msg("Rectangle mode: The total power antenna observes 1PB larger region compared to ALMA 12-m and ACA 7-m arrays", priority='info') else: if npts_multi < npts_rect: # Map 2PB x 2PB extent centered at each pointing direction # need to get a list of pointings dir_tp = [] locsize = qa.mul(2, PB12) for dir in pointings: dir_tp += myutil.calc_pointings2(qa.tos(qptgspc_tp), qa.tos(locsize), "square", dir) mapsize_tp = ["", ""] #npts_tp = npts_multi npts_tp = len(dir_tp) msg("Multi-pointing mode: The total power antenna observes +-1PB of each point", origin="simalma", priority='warn') else: # Map a region that covers all directions dir_tp = center npts_tp = npts_rect msg("Multi-pointing mode: The total power antenna maps a region that covers all pointings", origin="simalma", priority='warn') msg("- Center of poinings: %s" % center, origin="simalma", priority='warn') msg("- Map size: [%s, %s]" % (mapsize_tp[0], mapsize_tp[1]), origin="simalma", priority='warn') # Scale integration time of TP (assure >= 1 visit per direction) tottime_tp = "%dmin" % tptime_min integration_tp = integration ndump = int(qa.convert(tottime_tp, 's')['value'] / qa.convert(integration, 's')['value']) msg("Max number of dump in %s (integration %s): %d" % \ (tottime_tp, integration, ndump), origin="simalma") if ndump < npts_tp: t_scale = float(ndump)/float(npts_tp) integration_tp = qa.tos(qa.mul(integration, t_scale)) msg("Integration time is scaled to cover all pointings in observation time.", origin="simalma", priority='warn') msg("-> Scaled total power integration time: %s" % integration_tp, origin="simalma", priority='warn') ## Sometimes necessary to avoid the effect of round-off error #iunit = qa.quantity(integration_tp)['unit'] #intsec = qa.convert(integration_tp,"s") #totsec = intsec['value']*npts_tp#+0.000000001) ##tottime_tp = qa.tos(qa.convert(qa.quantity(totsec, "s"), iunit)) #tottime_tp = qa.tos(qa.quantity(totsec, "s")) task_param = {} task_param['project'] = project task_param['skymodel'] = skymodel task_param['inbright'] = inbright task_param['indirection'] = indirection task_param['incell'] = incell task_param['incenter'] = incenter task_param['inwidth'] = inwidth task_param['complist'] = complist task_param['compwidth'] = compwidth task_param['setpointings'] = True task_param['ptgfile'] = '$project.ptg.txt' task_param['integration'] = integration_tp task_param['direction'] = dir_tp task_param['mapsize'] = mapsize_tp task_param['maptype'] = maptype_tp task_param['pointingspacing'] = ptgspacing_tp task_param['caldirection'] = caldirection task_param['calflux'] = calflux task_param['obsmode'] = obsmode_sd task_param['hourangle'] = hourangle task_param['totaltime'] = "%dmin" % tptime_min task_param['antennalist'] = "" task_param['sdantlist'] = antlist_tp task_param['sdant'] = tpantid task_param['thermalnoise'] = thermalnoise task_param['user_pwv'] = pwv task_param['t_ground'] = t_ground task_param['leakage'] = leakage task_param['graphics'] = graphics task_param['verbose'] = verbose task_param['overwrite'] = overwrite msg(" ",priority="info") msg("Simulating %d TP antennas" % tpnant, priority="info") for iant in range(tpnant): task_param['sdant'] = iant task_param['seed'] = int(pl.random()*100000) msg(" ",priority=v_priority) msg("Running TP simulation with sdant = %d" % task_param['sdant'], priority=v_priority) msg(get_taskstr('simobserve', task_param), priority="info") if not dryrun: try: simobserve(**task_param) except: raise RuntimeError(simobserr) finally: casalog.origin('simalma') if tpnant == 1: mslist_tp = [msname_tp] else: # copy MSes orig_tp = fileroot + "/" + msname_tp suffix = (".Ant%d" % iant) msg(" ",priority=v_priority) msg("Renaming '%s' to '%s'" % (orig_tp, orig_tp+suffix), priority=v_priority) if not dryrun: shutil.move(orig_tp, orig_tp+suffix) mslist_tp.append(msname_tp+suffix) # noiseless MS if addnoise: orig_tp = orig_tp.replace(".noisy", "") msg("Renaming '%s' to '%s'" % (orig_tp, orig_tp+suffix), priority=v_priority) if not dryrun: shutil.move(orig_tp, orig_tp+suffix) del task_param ################################################################ # Imaging if dryrun: image=True # why not? # for 4.2 print more info v_priority="info" if image: modelimage = "" imagename_tp = project+".sd.image" if tptime_min > 0: ######################################################## # Image ACA-TP step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="info") msg("Step %d: generating a total power image. " % step, origin="simalma", priority="info") msg(" WARNING: Optimal gridding parameters are being analyzed by ALMA and may change.",priority="warn",origin="simalma") msg("-"*60, origin="simalma", priority="info") vis_tp = [] for msname_tp in mslist_tp: if dryrun: vis_tp.append(fileroot+"/"+msname_tp) elif os.path.exists(fileroot+"/"+msname_tp): vis_tp.append(fileroot+"/"+msname_tp) else: msg("Total power MS '%s' is not found" \ % msname_tp, origin="simalma", priority="error") tp_kernel = 'SF' #tp_kernel = 'GJINC' # Define imsize to cover TP map region msg(" ",priority=v_priority) msg("Defining image size to cover map region of total power simulation", priority=v_priority) msg("-> The total power map size: [%s, %s]" % \ (qa.tos(qimgsize_tp[0]), qa.tos(qimgsize_tp[1])), \ priority=v_priority) if tp_kernel.upper() == 'SF': beamsamp=9 pb_asec = sdbeamutil.primaryBeamArcsec(qa.tos(qa.convert(qa.quantity(model_center),'GHz')),12.0,0.75,10.0) qcell=qa.quantity(pb_asec/beamsamp, 'arcsec') cell_tp = [qa.tos(qcell), qa.tos(qcell)] msg("Using fixed cell size for SF grid: %s" % cell_tp[0], \ priority=v_priority) elif cell != '': # user-defined cell size msg("The user defined cell size: %s" % cell, \ priority=v_priority) cell_tp = [qa.tos(cell), qa.tos(cell)] else: if model_cell == None: # components only simulation compmodel = fileroot+"/"+pref_bl+".compskymodel" msg("getting the cell size of input compskymodel", \ priority=v_priority) if not os.path.exists(compmodel): msg("Could not find the skymodel, '%s'" % \ compmodel, priority='error') # modifymodel just collects info if outmodel==inmodel model_vals = myutil.modifymodel(compmodel,compmodel, "","","","","",-1, flatimage=False) model_cell = model_vals[1] model_size = model_vals[2] cell_tp = [qa.tos(model_cell[0]), qa.tos(model_cell[1])] ##################################################### imsize_tp = calc_imsize(mapsize=qimgsize_tp, cell=cell_tp) msg(" ",priority=v_priority) msg("-> The number of pixels needed to cover the map region: [%d, %d]" % \ (imsize_tp[0], imsize_tp[1]), \ priority=v_priority) msg("Compare with interferometer image area and adopt the larger one:", \ priority=v_priority) # Compare with imsize of BL (note: imsize is an intArray) imsize_bl = [] if is_array_type(imsize) and imsize[0] > 0: if len(imsize) > 1: imsize_bl = imsize[0:2] else: imsize_bl = [imsize[0], imsize[0]] if tp_kernel.upper() == 'SF': if len(imsize_bl) > 0: if cell != '': # user defined cell size for INT imarea = [qa.tos(qa.mul(cell, imsize[0])), qa.tos(qa.mul(cell, imsize[1]))] else: # using model_cell for INT imarea = [qa.tos(qa.mul(model_cell[0], imsize[0])), qa.tos(qa.mul(model_cell[1], imsize[1]))] tmpimsize = calc_imsize(mapsize=imarea, cell=cell_tp) else: msg("estimating imsize from input sky model.", \ priority=v_priority) tmpimsize = calc_imsize(mapsize=model_size, cell=cell_tp) msg("-> TP imsize to cover interferometrer image area: [%d, %d]" % \ (tmpimsize[0], tmpimsize[1]), \ priority=v_priority) elif len(imsize_bl) > 0: # User has defined imsize tmpimsize = imsize_bl msg("-> Interferometer imsize (user defined): [%d, %d]" % \ (tmpimsize[0], tmpimsize[1]), \ priority=v_priority) else: # the same as input model (calculate from model_size) msg("estimating imsize of interferometer from input sky model.", \ priority=v_priority) tmpimsize = calc_imsize(mapsize=model_size, cell=cell_tp) msg("-> Estimated interferometer imsize (sky model): [%d, %d]" % \ (tmpimsize[0], tmpimsize[1]), \ priority=v_priority) imsize_tp = [max(imsize_tp[0], tmpimsize[0]), \ max(imsize_tp[1], tmpimsize[1])] msg("The image pixel size of TP: [%d, %d]" % \ (imsize_tp[0], imsize_tp[1]), \ priority=v_priority) # Generate TP image msg(" ",priority=v_priority) temp_out = fileroot+"/"+imagename_tp + '0' task_param = dict(infiles=vis_tp, outfile=temp_out, imsize=imsize, cell=cell_tp, phasecenter=model_refdir, mode='channel', nchan= model_nchan) if tp_kernel.upper() == 'SF': msg("Generating TP image using 'SF' kernel.",\ priority=v_priority) # Parameters for sdimaging task_param['gridfunction'] = 'sf' task_param['convsupport'] = 6 else: msg("Generating TP image using 'GJinc' kernel.",\ priority=v_priority) gfac = 2.52 # b in Mangum et al. (2007) jfac = 1.55 # c in Mangum et al. (2007) convfac = 1.8 # The conversion factor to get HWHM of kernel roughly equal to qhwhm kernelfac = 0.7 # ratio of (kernel HWHM)/(TP pointingspacing) #qfwhm = PB12 # FWHM of GJinc kernel. #gwidth = qa.tos(qa.mul(gfac/3.,qfwhm)) #jwidth = qa.tos(qa.mul(jfac/3.,qfwhm)) qhwhm = qa.mul(qptgspc_tp, kernelfac) # hwhm of GJinc kernel gwidth = qa.tos(qa.mul(qhwhm, convfac)) jwidth = qa.tos(qa.mul(jfac/gfac/pl.log(2.),gwidth)) #casalog.post("Kernel parameter: [qhwhm, gwidth, jwidth] = [%s, %s, %s]" % (qa.tos(qhwhm), gwidth, jwidth)) # Parameters for sdimaging task_param['gridfunction'] = 'gjinc' task_param['gwidth'] = gwidth task_param['jwidth'] = jwidth if not is_CASA6: saveinputs('sdimaging', fileroot+"/"+project+".sd.sdimaging.last", myparams=task_param) else: casalog.post("saveinputs not available in casatasks, skipping saving sdimaging inputs", priority='WARN') msg("Having set up the gridding parameters, the sdimaging task is called to actually creage the image:",priority=v_priority) msg(get_taskstr('sdimaging', task_param), priority="info") if not dryrun: sdimaging(**task_param) #del task_param # TODO: scale TP image # Scale TP image if dryrun: #emulate beam calc in sdimaging bu = sdbeamutil.TheoreticalBeam() bu.set_antenna("12m", "0.75m") bu.set_sampling([ptgspacing_tp, ptgspacing_tp], "0.0deg") bu.set_image_param(task_param['cell'], model_center,task_param['gridfunction'], task_param['convsupport'] if 'convsupport' in task_param else -1, -1, task_param['gwidth'] if 'gwidth' in task_param else -1, task_param['jwidth'] if 'jwidth' in task_param else -1, is_alma=True) #bu.summary() imbeam = bu.get_beamsize_image() else: ia.open(temp_out) imbeam = ia.restoringbeam() ia.close() bmsize = imbeam['major'] beam_area_ratio = qa.getvalue(qa.convert(bmsize, 'arcsec'))**2 \ / qa.getvalue(qa.convert(PB12sim, 'arcsec'))**2 msg(" ",priority=v_priority) msg("Scaling TP image intensity by beam area before and after gridding: %f" % beam_area_ratio) task_param = dict(imagename=temp_out, mode='evalexpr', expr=("IM0*%f" % (beam_area_ratio)), outfile = fileroot+"/"+imagename_tp) if not is_CASA6: saveinputs('immath', fileroot+"/"+project+".sd.immath.last", myparams=task_param) else: casalog.post("saveinputs not available in casatasks, skipping saving inmath inputs", priority='WARN') msg(get_taskstr('immath', task_param), priority="info") if not dryrun: immath(**task_param) del task_param # Analyze TP image tpskymodel = fileroot+"/"+pref_tp+".skymodel" if components_only: tpskymodel = fileroot+"/"+pref_tp+".compskymodel" msg(" ",priority="info") msg("Analyzing TP image", priority="info") task_param = {} task_param['project'] = project task_param['image'] = False task_param['imagename'] = fileroot+"/"+imagename_tp task_param['skymodel'] = tpskymodel task_param['analyze'] = True task_param['showuv'] = False task_param['showpsf'] = False task_param['showconvolved'] = True task_param['graphics'] = graphics task_param['verbose'] = verbose task_param['overwrite'] = overwrite task_param['dryrun'] = dryrun task_param['logfile'] = myutil.reportfile msg(get_taskstr('simanalyze', task_param), priority="info") try: myutil.closereport() simanalyze(**task_param) del task_param myutil.openreport() except: raise RuntimeError(simanaerr) finally: casalog.origin('simalma') # Back up simanalyze.last file if os.path.exists(fileroot+"/"+simana_file): simana_new = imagename_tp.replace(".image",".simanalyze.last") msg("Back up input parameter set to '%s'" % simana_new, \ priority=v_priority) shutil.move(fileroot+"/"+simana_file, fileroot+"/"+simana_new) if not os.path.exists(fileroot+"/"+imagename_tp) and not dryrun: msg("TP image '%s' is not found" \ % imagename_tp, priority="error") #modelimage = imagename_aca ############################################################ # Image each INT array separately nconfig=len(antennalist) for i in range(nconfig): step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="info") msg(("Step %d: imaging and analyzing " % step)+antennalist[i], origin="simalma", priority="info") msg(" This step is optional, but useful to assess the result from just one configuration.",priority="warn",origin="simalma") msg(" WARNING: The example clean shown here uses no mask, may diverge, and almost certainly is not optimal.",priority="warn",origin="simalma") msg(" Users are HIGHLY recommended to use interactive clean masking (in simanalyze or directly in clean)",priority="warn",origin="simalma") msg(" Auto-masking is under development for use in the ALMA pipeline and will be included here in a future release",priority="warn",origin="simalma") msg("-"*60, origin="simalma", priority="info") pref=get_data_prefix(antennalist[i], project) if addnoise: msname = pref+".noisy.ms" imagename_int=pref+".noisy.image" else: msname= pref+".ms" imagename_int=pref+".image" if dryrun: vis_int = msname else: if os.path.exists(fileroot+"/"+msname): vis_int = msname else: msg("Could not find MS to image, '%s'" \ % msname, origin="simalma", priority="error") # i think simanalye is fixed 20130826 # # TMP fix: get correct skymodel file so that simanalyze picks it # if acaratio > 0: # if os.path.exists(tpskymodel): # shutil.move(tpskymodel,tpskymodel+".save") # else: # msg("TP skymodel '%s' is not found" \ # % tpskymodel, origin="simalma", priority="error") # # if os.path.exists(acaskymodel+".save"): # shutil.move(acaskymodel+".save",acaskymodel) # else: # msg("ACA skymodel '%s' is not found" \ # % acaskymodel+".save", origin="simalma", priority="error") # dryrun requires feeding cell and imsize from here. task_param = {} task_param['project'] = project task_param['image'] = image task_param['vis'] = vis_int task_param['modelimage'] = "" if cell: task_param['cell'] = cell else: task_param['cell'] = qa.tos(model_cell[0]) if imsize[0]>0: task_param['imsize'] = imsize else: task_param['imsize'] = int(qa.div(model_size[0],model_cell[0])['value']) if len(imdirection)>0: task_param['imdirection'] = imdirection else: task_param['imdirection'] = model_refdir task_param['niter'] = niter task_param['threshold'] = threshold task_param['weighting'] = weighting task_param['mask'] = [] task_param['outertaper'] = [] task_param['stokes'] = 'I' task_param['analyze'] = True task_param['graphics'] = graphics task_param['verbose'] = verbose task_param['overwrite'] = overwrite task_param['dryrun'] = dryrun task_param['logfile'] = myutil.reportfile msg(get_taskstr('simanalyze', task_param), priority="info") try: myutil.closereport() simanalyze(**task_param) del task_param myutil.openreport() except: raise RuntimeError(simanaerr) finally: casalog.origin('simalma') if nconfig>1: ############################################################ # concat step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="info") msg("Step %d: concatenating interferometric visibilities." % step, origin="simalma", priority="info") msg("-"*60, origin="simalma", priority="info") weights=pl.zeros(nconfig)+1 z=pl.where(configtypes=='ACA')[0] if len(z)>0: weights[z]=weightratio_7_12 mslist=[] for i in range(nconfig): pref=get_data_prefix(antennalist[i],project) if addnoise: msname = fileroot + "/" + pref+".noisy.ms" else: msname = fileroot + "/" + pref+".ms" mslist.append(msname) msg("concat(vis="+str(mslist)+",concatvis="+concatname+".ms,visweightscale="+str(weights.tolist()),priority="info") if not dryrun: try: concat(vis=mslist,concatvis=concatname+".ms",visweightscale=weights) except: raise RuntimeError(simanaerr) finally: casalog.origin('simalma') ############################################################ # Image ALMA-BL + ACA-7m step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="info") msg(("Step %d: imaging and analyzing " % step)+concatname+".ms", origin="simalma", priority="info") msg(" WARNING: The example clean shown here uses no mask, may diverge, and almost certainly is not optimal.",priority="warn",origin="simalma") msg(" Users are HIGHLY recommended to use interactive clean masking (in simanalyze or directly in clean)",priority="warn",origin="simalma") msg(" Auto-masking is under development for use in the ALMA pipeline and will be included here in a future release",priority="warn",origin="simalma") msg("-"*60, origin="simalma", priority="info") if dryrun: vis_int = concatname+".ms" else: if os.path.exists(fileroot+"/"+concatname+".ms"): vis_int = fileroot+"/"+concatname+".ms" elif os.path.exists(concatname+".ms"): vis_int = concatname+".ms" else: msg("Could not find MS to image, "+concatname+".ms", origin="simalma", priority="error") task_param = {} task_param['project'] = project task_param['image'] = image task_param['vis'] = vis_int task_param['modelimage'] = "" if cell: task_param['cell'] = cell else: task_param['cell'] = model_cell if imsize[0]>0: task_param['imsize'] = imsize else: task_param['imsize'] = int(qa.div(model_size[0],model_cell[0])['value']) if len(imdirection)>0: task_param['imdirection'] = imdirection else: task_param['imdirection'] = model_refdir task_param['niter'] = niter task_param['threshold'] = threshold task_param['weighting'] = weighting task_param['mask'] = [] task_param['outertaper'] = [] task_param['stokes'] = 'I' task_param['analyze'] = True task_param['graphics'] = graphics task_param['verbose'] = verbose task_param['overwrite'] = overwrite task_param['dryrun'] = dryrun task_param['logfile'] = myutil.reportfile msg(get_taskstr('simanalyze', task_param), priority="info") imagename_int=os.path.basename(concatname.rstrip("/"))+".image" try: myutil.closereport() simanalyze(**task_param) del task_param myutil.openreport() except: raise RuntimeError(simanaerr) finally: casalog.origin('simalma') if tptime_min > 0: ######################################################## # Combine TP + INT image step += 1 msg(" ",priority="info") msg("-"*60, origin="simalma", priority="info") msg("Step %d: combining a total power and synthesis image. " % step, origin="simalma", priority="info") msg(" WARNING: feathering the two images is only one way to combine them. ",priority="warn",origin="simalma") msg(" Using the total power image as a model in cleaning the interferometric visibilities may work better in some circumstances.",priority="warn",origin="simalma") msg("-"*60, origin="simalma", priority="info") if os.path.exists(fileroot+"/"+imagename_int) or dryrun: highimage0 = fileroot+"/"+imagename_int else: msg("The synthesized image '%s' is not found" \ % imagename_int, origin="simalma", priority="error") if (not os.path.exists(fileroot+"/"+imagename_tp)) and (not dryrun): msg("ACA is requested but total power image '%s' is not found" \ % imagename_tp, origin="simalma", priority="error") #lowimage = fileroot+"/"+imagename_tp # Need to manipulate TP image here outimage0 = fileroot+"/" + combimage+"0" outimage = fileroot+"/" + combimage # CAS-13369 -- imclean call in simanalyze is now imtclean #pbcov = highimage0.rstrip("image") + "flux.pbcoverage" pbcov = highimage0.rstrip("image") + "pb" regridimg = fileroot + "/" + imagename_tp + ".regrid" scaledimg = fileroot + "/" + imagename_tp + ".pbscaled" lowimage = scaledimg msg(" ",priority="info") msg("Regrid total power image to interferometric image grid:",priority=v_priority) # regrid TP image msg("inttemplate = imregrid(imagename = '"+highimage0+"', template='get')",priority=v_priority) if not dryrun: inttemplate = imregrid(imagename = highimage0, template='get') msg("imregrid(imagename = '"+fileroot+"/"+imagename_tp+ "',interpolation='cubic',template = inttemplate, output = '"+regridimg+"')",priority="info") if not dryrun: imregrid(imagename = fileroot+"/"+imagename_tp, interpolation="cubic", template = inttemplate, output = regridimg) # multiply SD image with INT PB coverage if not os.path.exists(pbcov): msg("The flux image '%s' is not found" \ % pbcov, origin="simalma", priority="error") msg(" ",priority="info") msg("Multiply total power image by interferometric sensitivity map:",priority=v_priority) # msg("immath(imagename=['"+regridimg+"','"+pbcov+"'],expr='IM1*IM0',outfile='"+scaledimg+"')",priority="info") # if not dryrun: # immath(imagename=[regridimg, pbcov], # expr='IM1*IM0',outfile=scaledimg) # # msg(" ",priority="info") # msg("Set total power image beam and brightness unit:",priority=v_priority) # msg("ia.open('"+fileroot+"/"+imagename_tp+"')",priority="info") # msg("beam_tp = ia.restoringbeam()",priority="info") # msg("bunit_tp = ia.brightnessunit()",priority="info") # msg("ia.close()",priority="info") # msg("ia.open('"+scaledimg+"')",priority="info") # msg("ia.setrestoringbeam(beam=beam_tp)",priority="info") # msg("ia.setbrightnessunit(bunit_tp)",priority="info") # msg("ia.close()",priority="info") # # if not dryrun: # pdb.set_trace() # # restore TP beam and brightness unit # ia.open(fileroot+"/"+imagename_tp) # beam_tp = ia.restoringbeam() # bunit_tp = ia.brightnessunit() # ia.close() # ia.open(scaledimg) # ia.setrestoringbeam(beam=beam_tp) # ia.setbrightnessunit(bunit_tp) # ia.close() msg("impbcor('"+regridimg+"', '"+pbcov+"', outfile='"+scaledimg+"',mode='multiply')",priority="info") if not dryrun: impbcor(regridimg, pbcov, outfile=scaledimg,mode='multiply') # de-pbcor the INT image # not needed now that imtclean is used and .image from tclean is flat sky by default, see CAS-13370 #highimage = fileroot+"/"+imagename_int+".pbscaled" #immath(imagename=[highimage0, pbcov], # expr='IM1/IM0',outfile=highimage) # msg(" ",priority="info") # msg("Multiply interferometric image by sensitivity map (un-pbcor):",priority="info") # msg("immath(imagename=['"+highimage0+"','"+pbcov+"'],expr='IM1*IM0',outfile='"+highimage+"')",priority="info") # msg("Restore interferometric beam and brightness unit:",priority="info") # msg("ia.open('"+highimage0+"')",priority="info") # msg("beam_int = ia.restoringbeam()",priority="info") # msg("bunit_int = ia.brightnessunit()",priority="info") # msg("ia.close()",priority="info") # msg("ia.open('"+highimage+"')",priority="info") # msg("ia.setrestoringbeam(beam=beam_int)",priority="info") # msg("ia.setbrightnessunit(bunit_int)",priority="info") # msg("ia.close()",priority="info") # # if not dryrun: # immath(imagename=[highimage0, pbcov], # expr='IM1*IM0',outfile=highimage) # # restore INT beam and brightness unit # ia.open(highimage0) # beam_int = ia.restoringbeam() # bunit_int = ia.brightnessunit() # ia.close() # ia.open(highimage) # ia.setrestoringbeam(beam=beam_int) # ia.setbrightnessunit(bunit_int) # ia.close() # # msg("impbcor('"+highimage0+"', '"+pbcov+"', outfile='"+highimage+"',mode='multiply')",priority="info") # if not dryrun: # impbcor(highimage0, pbcov, outfile=highimage,mode='multiply') # Feathering task_param = {} task_param['imagename'] = outimage0 task_param['highres'] = highimage0 task_param['lowres'] = lowimage msg(" ",priority="info") msg(get_taskstr('feather', task_param), priority="info") try: if not is_CASA6: saveinputs('feather', fileroot+"/"+project+".feather.last", myparams=task_param) else: casalog.post("saveinputs not available in casatasks, skipping saving feather inputs", priority='WARN') if not dryrun: feather(**task_param) del task_param # This seems not necessary anymore. ## transfer mask - feather should really do this #ia.open(outimage0) #ia.maskhandler('copy',[highimage+":mask0",'mask0']) #ia.maskhandler('set','mask0') #ia.done() except Exception as exc: raise Exception("simalma caught an exception in task feather: {}". format(exc)) finally: if not dryrun: shutil.rmtree(regridimg) #shutil.rmtree(scaledimg) casalog.origin('simalma') # re-pbcor the result msg(" ",priority="info") msg("Re-apply the primary beam correction to the feathered result:",priority=v_priority) # msg("immath(imagename=['"+outimage0+"','"+pbcov+"'],expr='IM0/IM1',outfile='"+outimage+"')",priority="info") # if not dryrun: # immath(imagename=[outimage0, pbcov], # expr='IM0/IM1',outfile=outimage) msg("impbcor('"+outimage0+"', '"+pbcov+"', outfile='"+outimage+"')",priority="info") if not dryrun: impbcor(outimage0, pbcov, outfile=outimage) ######################################################## # Generate Summary Plot grscreen = False grfile = False if not dryrun: if graphics == "both": grscreen = True grfile = True if graphics == "screen": grscreen = True if graphics == "file": grfile = True if grscreen or grfile: if grfile: file = fileroot + "/" + project + ".combine.png" else: file = "" # check for image pathes if os.path.exists(skymodel): flatsky = pref_bl + ".skymodel.flat" else: flatsky = pref_bl + ".compskymodel.flat" if not os.path.exists(fileroot+"/"+flatsky): raise RuntimeError("Coud not find a skymodel image '%s'" % flatsky) if not os.path.exists(fileroot+"/"+combimage): raise RuntimeError("Coud not find the combined image '%s'" % combimage) if not os.path.exists(fileroot+"/"+imagename_int): raise RuntimeError("Coud not find the synthesized image '%s'" % imagename_int) if not os.path.exists(fileroot+"/"+imagename_tp): raise RuntimeError("Coud not find the total power image '%s'" % (imagename_tp)) # Now the actual plotting disprange = None myutil.newfig(multi=[2,2,1],show=grscreen) # skymodel #discard = myutil.statim(fileroot+"/"+flatsky,disprange=disprange) #disprange = [] # generate flat synthesized (7m+12m) image flatint = fileroot + "/" + imagename_int + ".flat" myutil.flatimage(fileroot+"/"+imagename_int,verbose=verbose) if not os.path.exists(flatint): raise RuntimeError("Failed to generate '%s'" % (flatint)) # generate convolved sky model image myutil.convimage(fileroot+"/"+flatsky, flatint) discard = myutil.statim(fileroot+"/"+flatsky+".regrid.conv",disprange=disprange) shutil.rmtree(fileroot+"/"+flatsky+".regrid") shutil.rmtree(fileroot+"/"+flatsky+".regrid.conv") # total power image flattp = fileroot + "/" + imagename_tp + ".flat" myutil.flatimage(fileroot+"/"+imagename_tp,verbose=verbose) #flattp = scaledimg + ".flat" #myutil.flatimage(scaledimg,verbose=verbose) if not os.path.exists(flattp): raise RuntimeError("Failed to generate '%s'" % (flattp)) myutil.nextfig() discard = myutil.statim(flattp,disprange=disprange) shutil.rmtree(flattp) #disprange = [] # display flat synthesized (7m+12m) image myutil.nextfig() discard = myutil.statim(flatint,disprange=disprange) shutil.rmtree(flatint) # combined image flatcomb = fileroot + "/" + combimage + ".flat" myutil.flatimage(fileroot+"/"+combimage,verbose=verbose) if not os.path.exists(flatcomb): raise RuntimeError("Failed to generate '%s'" % (flatcomb)) myutil.nextfig() discard = myutil.statim(flatcomb,disprange=disprange) myutil.endfig(show=grscreen,filename=file) shutil.rmtree(flatcomb) if myutil.isreport(): myutil.closereport() finalize_tools() finally: finalize_tools() if myutil.isreport(): myutil.closereport() def finalize_tools(): if ia.isopen(): ia.close() sm.close() #cl.close() # crashes casa def get_data_prefix(cfgname, project=""): if str.upper(cfgname[0:4]) == "ALMA": foo=cfgname.replace(';','_') else: foo = cfgname foo=foo.replace(".cfg","") sfoo=foo.split('/') if len(sfoo)>1: foo=sfoo[-1] return project+"."+foo def calc_imsize(mapsize=None, cell=None): if mapsize == None: raise ValueError("mapsize is not defined") if cell == None: raise ValueError("cell is not defined") # get a list of cell size if is_array_type(cell): if len(cell) < 2: cell = [cell[0], cell[0]] else: cell = [cell, cell] for qval in cell: if not qa.compare(qval, "deg"): raise TypeError("cell should be an angular size") qcellx = qa.quantity(cell[0]) qcelly = qa.quantity(cell[1]) # get a list of map size if is_array_type(mapsize): if len(mapsize) < 2: mapsize = [mapsize[0], mapsize[0]] else: mapsize = [mapsize, mapsize] for qval in mapsize: if not qa.compare(qval, "deg"): raise TypeError("mapsize should be an angular size") vsizex = qa.convert(mapsize[0], qcellx['unit'])['value'] vsizey = qa.convert(mapsize[1], qcelly['unit'])['value'] # Calculate the number of pixels to cover the map size npixx = int(pl.ceil(vsizex/qcellx['value'])) npixy = int(pl.ceil(vsizey/qcelly['value'])) return [npixx, npixy]