casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_makemask.py
Go to the documentation of this file.
00001 ################################################
00002 # Task to make masks.
00003 #  reorganized after diesuccsion on Oct1, 2012
00004 #  with Jeurgen and Urvashi
00005 #
00006 #  modified by TT
00007 # based on the original code, 
00008 # v1.0: 2012.03.20, U.Rau
00009 #
00010 ################################################
00011 # Notes (to self) - TT 
00012 # 1. expanding one mask to another 
00013 #    e.g.) expanding a continuum mask (both image mask/boolean mask)
00014 #          channel mask 
00015 # 2. part of copy mode func.: merging of different types of masks 
00016 #    e.g.) inpimage and inpmask are lists of the mask to be merged
00017 #          output mask is written to either outimage or outmask as embedded
00018 #           T/F mask 
00019 # 3. copying mask to another or create a new one
00020 #    regrid if necessary (i.e. if the coords are different) 
00021 # ----------------------------------------------
00022 # basic rules:
00023 # for mask image (1/0 mask): as it is
00024 # for internal mask : parent_imagename:mask_name
00025 #
00026 # For input,
00027 # inpimage is the casa image
00028 # - mode='list': list internal masks of inpimage
00029 # - other mode: used as a template for output
00030 #               if region files are specified -> make mask specifeid with the regions on to inpimage
00031 #               output is '' => modified inpimage unless overwrite=F else exception
00032 #
00033 # if inpmask='': use inpimage as input mask
00034 # if inpmask='mask0' or other embedded mask name of the inpimage, 
00035 # use that T/F mask
00036 # 
00037 # =expand=
00038 # case1: on the same image (outimage=''), expand mask image from 
00039 # prev. run etc. No regriding. Use nearest chan mask
00040 # image to expand.  
00041 # 1.a: inpimage is clean image mask (1s and 0s)
00042 #      i) outimage != inpimage and outmask='' => new expanded mask image to outimage
00043 #     ii) outimage != inpimage and outmask!='' => convert expanded mask image to T/F mask to store inside outimage
00044 #    iii) outimage ==inpimage and outmask='' => update input mask image by expanding it 
00045 #     iv) outimage ==inpimage and outmask!=''=> update input image with the expanded T/F mask
00046 # 1.b: if inpmask!='', do T/F mask to 1/0 image mask conversion, then do as in 1.a 
00047  
00048 # case2: outimage is in diffirent coords. (need to regrid)
00049 #
00050 #################
00051 # tests 
00052 # 1. for input: mask image 
00053 # 2. for input: mask/or regular image with internal mask
00054 # 3. for input: mask image; for output: mask image with different spectral grid
00055 # 4. for input: mask/regular image with internal mask; for output: image with 
00056 #      internal mask with different spectral grid
00057 ###################
00058 import numpy as np
00059 import shutil
00060 from taskinit import *
00061 from recipes.pixelmask2cleanmask import pixelmask2cleanmask
00062 (csys,) = gentools(['cs']) 
00063 
00064 def makemask(mode,inpimage, inpmask, output, overwrite, inpfreqs, outfreqs):
00065     """
00066     make /manipulate masks
00067 
00068     """
00069     (ia,rg,im,) = gentools(['ia','rg','im']) 
00070     casalog.origin('makemask')
00071     #print "params(mode,inpimage,inpmask,output,overwrite)=",mode,inpimage,inpmask,output,overwrite
00072 
00073     try:
00074         # temp files
00075         tmp_maskimage='__tmp_makemaskimage'
00076         tmp_outmaskimage='__tmp_outmakemaskimage'
00077         tmp_regridim='__tmp_regridim'
00078 
00079         # do parameter check first
00080         # check names of inpimage, inpmask check for existance
00081         # inpimage == output (exact match) then check overwrite
00082         #   => T overwrite inpimage
00083         #   => F exception
00084 
00085         # check inpimage 
00086         if (['list','copy','expand'].count(mode)==1):
00087             if inpimage=='': raise Exception, "inpimage is empty"
00088             if not os.path.isdir(inpimage):
00089                 raise Exception, "inpimage=%s does not exist" % inpimage    
00090        
00091         # === list mode ===
00092         if mode == 'list':
00093            inpOK=checkinput(inpimage)
00094            if inpOK: 
00095               
00096                ia.open(inpimage)
00097                inmasklist=ia.maskhandler('get')
00098                # now ia.maskhandler returns ['T'] if no internal mask is there...
00099                if inmasklist.count('T')!=0:
00100                    inmasklist.remove('T')
00101                if len(inmasklist) ==0:
00102                    casalog.post('No internal (T/F) masks were found in %s' % (inpimage),'INFO')
00103                else:
00104                    defaultmaskname=ia.maskhandler('default')[0]
00105                    printinmasks=''
00106                    for mname in inmasklist:
00107                        if mname==defaultmaskname:
00108                            printinmasks+='\''+mname+'\''+'(default)'
00109                        else:
00110                            printinmasks+='\''+mname+'\''
00111                        if mname != inmasklist[-1]:
00112                            printinmasks+=', '
00113                  
00114                    casalog.post('Internal (T/F) masks in %s: %s' % (inpimage, printinmasks),'INFO')
00115                ia.close()
00116  
00117         elif mode == 'setdefaultmask':
00118             inpOK=checkinput(inpmask)
00119             if inpOK:
00120                 (parentimage,bmask)=extractmaskname(inpmask)
00121                 if bmask=='':
00122                     raise Exception, "Missing an internal mask name"
00123                 ia.open(parentimage)
00124                 defaultmaskname=ia.maskhandler('default')[0]
00125                 inmasklist=ia.maskhandler('get')
00126                 if defaultmaskname==bmask:
00127                     casalog.post('No change. %s is already a default internal mask' % bmask, 'INFO')
00128                 else:
00129                     ia.maskhandler('set',bmask)
00130                     casalog.post('Set %s as a default internal mask' % bmask, 'INFO')
00131                     if len(inmasklist)>1:
00132                         casalog.post('Current internal masks are %s' % str(inmasklist), 'INFO')
00133                 ia.close()
00134 
00135         elif mode == 'delete':
00136             inpOK=checkinput(inpmask)
00137             if inpOK:
00138                 (parentimage,bmask)=extractmaskname(inpmask)
00139                 if bmask=='':
00140                     raise Exception, "Missing an internal mask name"
00141                 ia.open(parentimage)
00142                 casalog.post('Deleting the internal mask, %s ' % bmask, 'INFO')
00143                 defaultmaskname=ia.maskhandler('default')[0]
00144                 ia.maskhandler('delete',bmask)
00145                 inmasklist=ia.maskhandler('get')
00146                 if inmasklist.count('T')!=0:
00147                     inmasklist.remove('T')
00148                 if len(inmasklist) !=0 and defaultmaskname==bmask:
00149                     ia.maskhandler('set',inmasklist[0])
00150                     casalog.post('Set %s as a default internal mask' % inmasklist[0], 'INFO')
00151                     if len(inmasklist)>1:
00152                         casalog.post('Current internal masks are %s' % str(inmasklist), 'INFO')
00153           
00154                 ia.close()
00155 
00156         #elif mode != 'merge':
00157         else:
00158            import commands
00159            # copy can have multiple input masks, expand has only one.
00160            # check inpimage, inpmask, output, overwrite
00161            # 
00162            storeinmask = False # used to check if output to a new internal mask
00163            inpOK=checkinput(inpimage)
00164            if inpOK:
00165                (immask,inmask)=extractmaskname(inpimage)
00166           
00167            # seperate text files(region files), images(with full ':'), and direct region 
00168            # input mask(s)
00169            if inpmask=='':
00170               raise Exception, "Input errror. The inpmask parameter is not specified."
00171            if type(inpmask)!=list: 
00172               inpmask=[inpmask]
00173            
00174            # check if contains region file or region specification
00175            rgfiles=[]
00176            imgfiles=[]
00177            rglist=[]
00178            bmasks=[]
00179            for masklet in inpmask:
00180                # is text file?
00181                if type(masklet)==str: # text file or image
00182                    if os.path.exists(masklet):
00183                        if (commands.getoutput('file '+masklet).count('directory')):
00184                           if os.path.exists(masklet+'/table.f1'):
00185                               #casalog.post("%s is not in a recognized format for inpmask, ignored." % masklet, 'WARN') 
00186                               raise Exception, "%s is not in a recognized format for inpmask" % masklet
00187                           else:
00188                           # probably image file (with no mask extension)
00189                               imgfiles.append(masklet)
00190                        elif (commands.getoutput('file '+masklet).count('text')):
00191                           rgfiles.append(masklet)
00192                        else:
00193                           #casalog.post("%s does not recognized format for inpmask, ignored." % masklet, 'WARN')
00194                           raise Exception, "%s is not in a recognized format for inpmask" % masklet
00195                    else:
00196                        if masklet.count('[') and masklet.count(']'): # rough check on region specification 
00197                            rglist.append(masklet) 
00198                        else:
00199                            (parentim, mask)=extractmaskname(masklet)
00200                            if mask!='':
00201                                bmasks.append(masklet)
00202                            else:
00203                                raise Exception, "%s is not an existing file/image or a region format" % masklet
00204       
00205            # expand allows only a string for inpmask
00206            if mode=='expand':
00207                if type(inpmask)==list:
00208                    inpmask=inpmask[0] 
00209            # check for overwrite condition
00210            if output=='':
00211                if overwrite: 
00212                    output=inpimage
00213                else: 
00214                    raise Exception, "output is not specified. If you want to overwrite inpimage, please set overwrite=True"
00215 
00216            if inpimage==output:
00217                if overwrite:
00218                    tmp_outmaskimage=tmp_maskimage
00219                else:
00220                    raise Exception, "output=inpimage. If you want to overwrite inpimage, please set overwrite=True"
00221 
00222            outparentim=output
00223            outbmask=''
00224            if os.path.isdir(output): 
00225                if not overwrite:
00226                     raise Exception, "output=%s exists. If you want to overwrite it, please set overwrite=True" % output
00227            else:
00228                (outparentim, outbmask)=extractmaskname(output)
00229                #print "extractmaskname::: outparentim=",outparentim, "outbmask=",outbmask
00230                if outbmask!='':
00231                    (parentimexist,maskexist)=checkinmask(outparentim,outbmask)    
00232                    if parentimexist and maskexist and not overwrite:
00233                        raise Exception, "output=%s exists. If you want to overwrite it, please set overwrite=True" % output
00234                    if parentimexist and not maskexist:
00235                        storeinmask=True
00236                else:
00237                   outparentim=output
00238                
00239 
00240            #print "param checks before branching out for mode=========="
00241            #print "output=",output, " is exist?=",os.path.isdir(output)
00242            #print "outparentim=",outparentim, " is exist?=",os.path.isdir(outparentim)
00243 
00244     # the following code is somewhat duplicated among the modes but keep separated from each mode
00245     # for now.... copy now handle merge as well
00246     # === old copy mode === NOW combined to 'merge mode'
00247 #        #if mode=='copy':
00248 #           #print "Copy mode"
00249 #           needregrid=True
00250 #           #if outimage=='':
00251 #               #overwrite
00252 #           #    outimage=inpimage
00253 #
00254 #           if not os.path.isdir(outimage):
00255 #               needregrid=False
00256 #
00257 #          if inpmask!='':
00258 #          # need to extract the mask and put in tmp_maskimage
00259 #              pixelmask2cleanmask(imagename=inpimage, maskname=inpmask, maskimage=tmp_maskimage, usemasked=True)    
00260 #          else:
00261 #              shutil.copytree(inpimage, tmp_maskimage)
00262 #           if needregrid:
00263 #               casalog.post("Regridding...",'DEBUG1')
00264 #               regridmask(tmp_maskimage,outimage,tmp_outmaskimage)
00265 #               # regrid may produce <1.0 pixels for mask so be sure to its all in 1.0
00266 #               #ia.open(tmp_outmaskimage) 
00267 #               #ia.calc('iif (%s>0.0 && %s<1.0,1,%s)'%(tmp_outmaskimage,tmp_outmaskimage,tmp_outmaskimage))
00268 #               #ia.close()
00269 #               #print "Copying regrid output=",tmp_outmaskimage
00270 #           else:
00271 #               shutil.copytree(tmp_maskimage,tmp_outmaskimage)
00272 #          if outmask!='':
00273 #          #convert the image mask to T/F mask
00274 #               if not os.path.isdir(outimage):
00275 #                   shutil.copytree(inpimage,outimage)
00276 #               #
00277 #               ia.open(outimage)
00278 #              casalog.post("convert the output image mask to T/F mask")
00279 #              ia.calcmask(mask='%s<0.5' % tmp_outmaskimage,name=outmask,asdefault=True)
00280 #               ia.done()
00281 #           else:
00282 #               # if regridded - tmp_outmaskimage is created by regridmask
00283 #               # if not, tmp_outmaskimage=outimage
00284 #               ia.open(tmp_outmaskimage)
00285 #               ia.rename(outimage,overwrite=True)
00286 #               ia.done()
00287 
00288                 
00289     # === expand mode ===
00290         if mode=='expand':
00291             (rg,) = gentools(['rg']) 
00292             needtoregrid=False
00293             bychanindx=False
00294 
00295             try: 
00296                 #print "expand mode..."
00297                 # do not allow list in this mode (for inpimage and inpmask) - maybe this is redundant now
00298                 if type(inpmask)==list:
00299                     raise TypeError, 'A list for inpmask is not allowed for mode=expand'
00300 
00301                 # input image info, actually this will be output coordinates
00302                 #print "inpimage=",inpimage," is exist?=",os.path.isdir(inpimage)
00303                 ia.open(inpimage)
00304                 inshp = ia.shape()
00305                 incsys = ia.coordsys()
00306                 ia.close() 
00307                 # prepare working input image (tmp_maskiamge)
00308                 if inpmask!='': # inpmask is either image mask or T/F mask now
00309                   # need to extract the mask and put in tmp_maskimage
00310                     (parentimage,bmask)=extractmaskname(inpmask)
00311                     if bmask!='':
00312                         pixelmask2cleanmask(imagename=parentimage, maskname=bmask, maskimage=tmp_maskimage, usemasked=True)    
00313                         #ia.open(tmp_maskimage)
00314                     else:
00315                         #print "parentimage=",parentimage, " exist?=",os.path.isdir(parentimage)
00316                         # copy of inpimage in tmp_maskimage
00317                         ia.fromimage(outfile=tmp_maskimage, infile=parentimage)
00318                 else:
00319                     raise Exception, "inpmask must be specified"
00320                 if ia.isopen(): ia.close() 
00321                 #setting up the output image (copy from inpimage or template)
00322                 if not os.path.isdir(outparentim):
00323                     #shutil.copytree(inpimage,tmp_outmaskimage)
00324                     ia.fromshape(outfile=tmp_outmaskimage,shape=inshp, csys=incsys.torecord()) 
00325                     ia.close() 
00326                     needtoregrid=False
00327                 else:
00328                     shutil.copytree(outparentim,tmp_outmaskimage)
00329                      
00330                 # if inpfreq/outfreq are channel indices (int) then
00331                 # regrid in x y coords only and extract specified channel mask
00332                 # to specified output channels. (no regriding in spectral axis)
00333                 # if inpfreqs/outfreqs are velocity or freqs, 
00334                 # it assumes it is expressed in the range with minval~maxval
00335                 # create subimage of the input mask with the range,
00336                 # do regrid with the subimage to output.
00337           
00338                 # decide to regrid or not
00339                 # 1. the case all channels are selected for input and output, simply regrid
00340                 # 2. if inpfreqs and outfreqs are integers (= channel indices), regrid only in
00341                 #    first and second axes (e.g. ra,dec) and no regridding along spectral axis
00342                 # 3. if inpfreqs and outfreqs are ranges in freq or vel, make subimage and regrid
00343                 
00344                 if inshp[3]!=1 and ((inpfreqs==[] and outfreqs==[]) \
00345                     or (inpfreqs=='' and outfreqs=='')):
00346                     # unless inpimage is continuum, skip chan selection part and regrid 
00347                     needtoregrid=True
00348                     # detach input(tmp) image and open output tmp image
00349                 #    ia.open(tmp_outmaskimage)
00350                 else: 
00351                 #    if ia.isopen():
00352                 #        if ia.name(strippath=True)!=tmp_maskimage:
00353                 #            ia.close()
00354                 #            ia.open(tmp_maskimage)
00355                 #    else:
00356                 #        ia.open(tmp_maskimage)
00357 
00358                     if inshp[3]!=1: casalog.post("inpmask is continuum..","INFO")
00359                     # selection by channel indices (number) 
00360                     # if both inpfreqs and outfreqs are int skip regridding
00361                     # if outfreqs is vel or freq ranges, try regridding 
00362                     if inpfreqs==[[]] or inpfreqs==[]: 
00363                         # select all channels for input
00364                         inpfreqs=range(inshp[3])
00365 
00366                     # check inpfreqs and outfreqs types
00367                     selmode='bychan'
00368                     if type(inpfreqs)==list:
00369                         if type(inpfreqs[0])==int:
00370                             if type(outfreqs)==list and (len(outfreqs)==0 or type(outfreqs[0])==int):
00371                                 selmode='bychan'
00372                             elif type(outfreqs)==str:
00373                                 if inpfreqs[0]==0: #contintuum -allow index-type specification
00374                                     selmode='byvf'
00375                                 else:
00376                                     raise TypeError, "Mixed types in infreqs and outfreqs are not allowed" 
00377                         else:
00378                             raise TypeError, "Non-integer in inpfreq is not supported" 
00379                     elif type(inpfreqs)==str:
00380                         if type(outfreqs)!=str:
00381                             raise TypeError, "Mixed types in infreqs and outfreqs" 
00382                         selmode='byvf'
00383                     else:
00384                         raise TypeError, "Wrong type for infreqs"
00385 
00386                     # inpfreqs and outfreqs are list of int
00387                     # match literally without regridding.
00388                     if selmode=='bychan': 
00389                         casalog.post("selection of input and output ranges by channel")
00390                         
00391                         if ia.isopen():
00392                             ia.close()
00393                         if outfreqs==[] or outfreqs==[[]]:
00394                             outchans=[]
00395                         else:
00396                             outchans=outfreqs
00397                         expandchanmask(tmp_maskimage,inpfreqs,tmp_outmaskimage,outchans)
00398                         #print "done expandchanmask tmp_outmaskimge=",tmp_outmaskimage, " is exist?", os.path.isdir(tmp_outmaskimage)
00399                         ia.open(tmp_outmaskimage)
00400 
00401                     elif selmode=='byvf': # outfreqs are quantities (freq or vel)
00402                         casalog.post("selection of input/output ranges by frequencies/velocities")
00403                         
00404                         inpfreqlist = translatefreqrange(inpfreqs,incsys)
00405                         # close input image
00406                         if ia.isopen():
00407                             ia.close()
00408                         
00409                         #regrid to output image coordinates
00410                         if len(inpfreqlist)==1: # continuum
00411                             #do not regrid, use input image
00412                             shutil.copytree(tmp_maskimage,tmp_regridim)
00413                         else:
00414                             regridmask(tmp_maskimage,inpimage,tmp_regridim,chanrange=inpfreqlist)
00415                             # find edge masks (nonzero planes)
00416                             ia.open(tmp_regridim)
00417                             sh=ia.shape()
00418                             chanlist=range(sh[3])
00419                             indlo=0
00420                             indhi=0
00421                             for i in chanlist:
00422                                 sl1=[0,0,0,i]
00423                                 sl2=[sh[0]-1,sh[1]-1,sh[2]-1,i]
00424                                 psum = ia.getchunk(sl1,sl2).sum()
00425                                 pmsum = ia.getchunk(sl1,sl2,getmask=True).sum()
00426                                 if pmsum!=0 and psum>0.0: 
00427                                     indlo=i
00428                                     break
00429                             chanlist.reverse()
00430                             for i in chanlist:
00431                                 sl1=[0,0,0,i]
00432                                 sl2=[sh[0]-1,sh[1]-1,sh[2]-1,i]
00433                                 psum = ia.getchunk(sl1,sl2).sum()
00434                                 if psum>0.0: 
00435                                     indhi=i
00436                                     break
00437                             if indhi < indlo:
00438                                 raise IOError, "Incorrectly finding edges of input masks! Probably some logic error in the code!!!" 
00439                             else:
00440                                 casalog.post("Determined non-zero channel range to be "+str(indlo)+"~"+str(indhi), 'DEBUG1')
00441 
00442                         # find channel indices for given outfreqs
00443                         ia.open(tmp_outmaskimage)
00444                         ocsys=ia.coordsys()
00445                         oshp=ia.shape() 
00446                         outfreqlist = translatefreqrange(outfreqs,ocsys)
00447                         rtn=ocsys.findcoordinate('spectral')
00448                         px=rtn[1][0]
00449                         wc=rtn[2][0]
00450                         world=ocsys.referencevalue()
00451                         # assume chanrange are in freqs
00452                         world['numeric'][wc]=qa.convert(qa.quantity(outfreqlist[0]),'Hz')['value']
00453                         p1 = ocsys.topixel(world)['numeric'][px]
00454                         world['numeric'][wc]=qa.convert(qa.quantity(outfreqlist[1]),'Hz')['value']
00455                         p2 = ocsys.topixel(world)['numeric'][px]
00456                         casalog.post("translated channel indices:"+qa.tos(outfreqlist[0])+"->p1="+str(p1)+\
00457                         " "+qa.tos(outfreqlist[0])+"->  p2="+str(p2))
00458                         if len(inpfreqs)==1:
00459                             inpfreqchans=inpfreqs
00460                         else:
00461                             inpfreqchans=[indlo,indhi]
00462                         outfreqchans=range(int(round(p1)),int(round(p2))+1)
00463                         #print "inpfreqchans=",inpfreqchans
00464                         #print "outfreqchans=",outfreqchans
00465 
00466                         expandchanmask(tmp_regridim,inpfreqchans,tmp_outmaskimage,outfreqchans)
00467 
00468 #                       usechanims={}  # list of input mask to be use for each outpfreq
00469 #                       for i in outfreqchans:
00470 #                           nearestch = findnearest(inpfreqchans,i)
00471 #                           usechanims[i]=nearestch 
00472 #                        # put masks from inp image channel by channel
00473 #                       for j in outfreqs:
00474 #                           pix = refchanchunk[usechanims[j]-refchanst]
00475 #                           #ia.putchunk(pixels=pix,blc=[inshp[0]-1,inshp[1]-1,0,j])
00476 #                           ia.putchunk(pixels=pix.transpose(),blc=[0,0,0,j])
00477                         needtoregrid=False
00478                         ia.open(tmp_outmaskimage)
00479                 # 
00480                 
00481                 if needtoregrid:
00482                     # closing current output image
00483                     if ia.isopen():
00484                         ia.close()
00485                     #print "tmp_maskimage=",tmp_maskimage, " is exist?", os.path.isdir(tmp_maskimage)
00486                     ia.open(tmp_maskimage)
00487                     #os.system('cp -r %s beforeregrid.im' % tmp_maskimage)
00488                     if os.path.isdir(tmp_outmaskimage):
00489                         #print "Removing %s" % tmp_outmaskimage
00490                         shutil.rmtree(tmp_outmaskimage)
00491                     regridmask(tmp_maskimage,outparentim,tmp_outmaskimage)
00492                     ia.remove()
00493                     #print "closing after regrid"
00494                     ia.open(tmp_outmaskimage) # reopen output tmp image
00495                 
00496                 if outbmask!='':
00497                     #convert the image mask to T/F mask
00498                     casalog.post("Convert the image mask to T/F mask",'INFO')
00499                     #ia.calcmask(mask='%s<0.5' % tmp_outmaskimage,name=outmask,asdefault=True)
00500                     ia.calcmask(mask='%s=0.0' % tmp_outmaskimage,name=outbmask,asdefault=True)
00501 
00502                 if storeinmask:
00503                     ia.open(outparentim)
00504                     ia.maskhandler('copy',[tmp_outmaskimage+':'+outbmask, outbmask])
00505                     ia.maskhandler('set',outbmask)
00506                     ia.done()
00507                     casalog.post("Output the mask to %s in %s" % (outbmask,outparentim) ,"INFO")
00508                 else:
00509                     ow = False
00510                     if  inpimage==output:
00511                         casalog.post("Updating "+output+"with new mask","INFO")
00512                     else:
00513                         if os.path.isdir(outparentim):
00514                             casalog.post(outparentim+" exists, overwriting","INFO")
00515                             ow=True
00516                         else:
00517                             casalog.post("Output the mask to "+outparentim ,"INFO")
00518                     ia.rename(outparentim,ow)
00519                     ia.done()
00520 
00521             except Exception, instance:
00522                 print "*** Error ***", instance
00523                 if ia.isopen():
00524                     ia.close()
00525                 ia.done()
00526                 raise Exception, instance
00527             finally:
00528                 if os.path.exists(tmp_maskimage):
00529                     shutil.rmtree(tmp_maskimage)
00530                 if os.path.exists(tmp_regridim):
00531                     shutil.rmtree(tmp_regridim)
00532 
00533     # === now called copy mode: copy/merge mode ===
00534         # copy is a just special case of merge mode
00535         # CHANGE:
00536         # all input masks should be specified in inpmask 
00537         # type of inpmask accepted: 1/0 mask, T/F mask, region file, and region expression in a string 
00538         # already stored internally in seperate lists
00539         #   rgfiles - region files
00540         #   imgfiles - 1/0 image masks
00541         #   rglist - region expression in strings
00542         #   bmasks - T/F internal masks
00543         #
00544         # avaialble parameters: inpimage (string) , inpmask (list/string), output(string)
00545         # input inpimage as a template or image used for defining regions when it is given in inpmask 
00546         # inpmask as list of all the masks to be merged (image masks, T/F internal masks, regions)
00547 
00548         #was: if mode=='merge':
00549         if mode=='copy':
00550             #print "new copy mode..."
00551             sum_tmp_outfile='__tmp_outputmask'
00552             tmp_inmask='__tmp_frominmask'
00553             usedimfiles=[]
00554             usedbmasks=[]
00555             usedrgfiles=[]
00556             usedrglist=[]
00557             try:
00558                 # check outparentim - image part of output and set as a template image
00559                 if not os.path.isdir(outparentim) or (outparentim==inpimage):
00560                     # figure out which input mask to be used as template
00561                     # if inpimage is defined use the first one else try the first one
00562                     # inpmask
00563                     #if output=='':
00564                     #    if type(inpimage)==list:
00565                     #         raise Exception, "inputimage must be a string"
00566                     #    elif type(inpimage)==str:
00567                     #         outimage=inpimage
00568                     #    casalog.post("No outimage is specified. Will overwrite input image: "+outimage,'INFO')
00569 
00570                     #if type(inpimage)==list and len(inpimage)!=0:
00571                     #    tmp_template=inpimage[0]
00572                     #elif inpimage!='' and inpimage!=[]:
00573                     #    tmp_template=inpimage # string
00574                     #tmp_template=inpimage # string
00575                     #else:
00576                     #     if type(inpmask)==list and len(inpmask)!=0:
00577                     #         fsep=inpmask[0].rfind(':')
00578                     #         if fsep ==-1:
00579                     #            raise IOError, "Cannot resolve inpmask name, check the format"
00580                     #        else:
00581                     #            tmp_template=inpmask[0][:inpmask[0].rfind(':')]
00582                     #    elif inpmask!='' and inpmask!=[]:
00583                     #        # this is equivalent to 'copy' the inpmask
00584                     #        tmp_template=inpmask #string
00585                     
00586                     # create an empty image with the coords from inpimage
00587                     makeEmptyimage(inpimage,sum_tmp_outfile)    
00588                     #print "making an empty image from inpimage to sum_tmp_outfile"
00589                 else:
00590                     #use output image - does not do zeroeing out, so output image is only modified     
00591                     shutil.copytree(outparentim,sum_tmp_outfile)
00592                     #print "Using outpaarentim=",outparentim, " as sum_tmp_outfile=",sum_tmp_outfile
00593      
00594                 #if type(inpimage)==str:
00595                 #    inpimage=[inpimage]
00596                 #if type(inpmask)==str:
00597                 #    inpmask=[inpmask]
00598 
00599                 if len(imgfiles)>0:
00600                     # summing all the images
00601                     casalog.post('Summing all mask images in inpimage and  normalized to 1 for mask','INFO')
00602                     for img in imgfiles:
00603                         tmpregrid='__tmp_regrid.'+img
00604                         # regrid to output image coords
00605                         regridmask(img,sum_tmp_outfile,tmpregrid)
00606                         #print "addimagemask... for ",tmpregrid
00607                         addimagemask(sum_tmp_outfile,tmpregrid)
00608                         usedimfiles.append(img)
00609                         shutil.rmtree(tmpregrid)
00610                     # get boolean masks
00611                     #  will work in image(1/0) masks
00612                 
00613                 if len(bmasks)>0:
00614                     casalog.post('Summing all T/F mask in inpmask and normalized to 1 for mask','INFO')
00615                     for msk in bmasks:
00616                         (imname,mskname) = extractmaskname(msk)
00617                         #if msk.find(':')<0:
00618                         #    # assume default mask
00619                         #    msk=msk+':mask0'
00620                         #imname=msk[:msk.rfind(':')]
00621                         ia.open(imname)
00622                         inmasks=ia.maskhandler('get')
00623                         ia.close()
00624                         #print "inmasks=",str(inmasks)
00625                         if not inmasks.count(mskname):
00626                             raise TypeError, mskname+" does not exist in "+imname+" -available masks:"+str(inmasks)
00627                         # move T/F mask to image mask
00628                         pixelmask2cleanmask(imname, mskname, tmp_inmask, True)    
00629                         regridmask(tmp_inmask,sum_tmp_outfile,'__tmp_fromTFmask')
00630                         addimagemask(sum_tmp_outfile,'__tmp_fromTFmask')
00631                         usedbmasks.append(msk)
00632                         shutil.rmtree('__tmp_fromTFmask') 
00633                         # if overwriting to inpimage, delete the boolean mask
00634                         if outparentim==inpimage and inpimage==imname:
00635                             ia.open(imname)
00636                             ia.maskhandler('delete',[mskname])
00637                             ia.close()
00638                         ia.open(imname)
00639                         ia.close()
00640                       
00641 
00642                 if len(rgfiles)>0 or len(rglist)>0:
00643                     tmp_allrgmaskim='__tmp_fromAllRgn'
00644                     tmp_rgmaskim='__tmp_fromRgn'
00645                     # create an empty image with input image coords.
00646                     #print "Using %s as a template for regions" % inpimage 
00647                     ia.open(inpimage)
00648                     tshp=ia.shape()
00649                     tcsys=ia.coordsys() 
00650                     ia.fromshape(tmp_allrgmaskim,shape=tshp, csys=tcsys.torecord(),overwrite=True)
00651                     ia.done()    
00652                     if os.path.isdir(tmp_rgmaskim):
00653                        shutil.rmtree(tmp_rgmaskim)
00654                     shutil.copytree(tmp_allrgmaskim,tmp_rgmaskim)
00655 
00656                     if len(rgfiles)>0:
00657                         #print "Has rgfiles..."
00658                         nrgn=0
00659                         for rgn in rgfiles:
00660                             firstline=True
00661                             subnrgn=0
00662                             with open(rgn) as f:
00663                                 for line in f:
00664                                     if firstline:
00665                                         if line.count('#CRTF')==0:
00666                                             raise Exception, "Input text file does not seems to be in a correct format \
00667                                                               (must contains #CRTF)"
00668                                         firstline=False
00669                                     else:     
00670                                         try:
00671                                             if line.count('^#'):
00672                                                 pass
00673                                             else:
00674                                                if len(line)!=0:
00675                                                   # reset temp mask image
00676                                                   ia.open(tmp_rgmaskim)
00677                                                   ia.set(pixels=0.0)
00678                                                   ia.close()
00679                                                   #print "tshp=",tshp
00680                                                   #print "tcsys.torecord=",tcsys.torecord()
00681                                                   inrgn=rg.fromtext(line, tshp, tcsys.torecord())
00682                                                   #print "inrgn=",inrgn
00683                                                   im.regiontoimagemask(tmp_rgmaskim,region=inrgn)
00684                                                   addimagemask(tmp_allrgmaskim,tmp_rgmaskim)
00685                                                   #shutil.rmtree(tmp_rgmaskim)
00686                                                   subnrgn +=1
00687                                                   nrgn +=1
00688                                         except:
00689                                             break
00690                             if subnrgn>0:
00691                                 usedrgfiles.append(rgn)    
00692                         casalog.post("Converted %s regions from %s region files to image mask" % (nrgn,len(rgfiles)),"INFO")
00693                                                 
00694                     if len(rglist)>0:
00695                         #print "Has rglist..."
00696                         nrgn=0
00697                         for rgn in rglist:
00698                             # reset temp mask image
00699                             ia.open(tmp_rgmaskim)
00700                             ia.set(pixels=0.0)
00701                             ia.close()
00702                             inrgn=rg.fromtext(rgn, tshp, tcsys.torecord())
00703                             im.regiontoimagemask(tmp_rgmaskim,region=inrgn)
00704                             addimagemask(tmp_allrgmaskim,tmp_rgmaskim)
00705                             #shutil.rmtree(tmp_rgmaskim)
00706                             usedrglist.append(rgn)
00707                             nrgn+=1
00708                         casalog.post("Converted %s regions to image mask" % (nrgn),"INFO")
00709                 
00710                         
00711                     # regrid if necessary
00712                     regridded_mask='__tmp_regrid_allrgnmask'
00713                     regridmask(tmp_allrgmaskim, sum_tmp_outfile,regridded_mask)
00714                     addimagemask(sum_tmp_outfile,regridded_mask)
00715                     #shutil.rmtree('__tmp_regridded_allrgnmask')
00716                     casalog.post("Added mask based on regions to output mask","INFO")
00717                     #cleanup
00718                     for tmpfile in [tmp_allrgmaskim,tmp_rgmaskim,regridded_mask]:
00719                         if os.path.isdir(tmpfile):
00720                             shutil.rmtree(tmpfile)
00721 
00722                                         
00723                 if outbmask!='':
00724                     casalog.post('Putting mask in T/F','INFO')
00725                     ia.open(sum_tmp_outfile)
00726                     #ia.calcmask(mask='%s<0.5' % sum_tmp_outfile,name=outmask,asdefault=True)
00727                     # mask only pixel != 0.0 
00728                     ia.calcmask(mask='%s==0.0' % sum_tmp_outfile,name=outbmask,asdefault=True)
00729                     ia.done()
00730                 # if outfile exists initially outfile is copied to sum_tmp_outfile
00731                 # if outfile does not exist initially sum_tmp_outfile is a copy of inpimage
00732                 # so rename it with overwrite=T all the cases
00733                 #print "open sum_tmp_outfile=",sum_tmp_outfile
00734                 if storeinmask:
00735                     ia.open(outparentim)
00736                     ia.maskhandler('copy',[sum_tmp_outfile+':'+outbmask, outbmask])    
00737                     ia.maskhandler('set',outbmask)
00738                     ia.done()
00739                     outputmsg="to create an output mask: %s in %s" % (outbmask,outparentim)
00740                 else:
00741                     ia.open(sum_tmp_outfile) 
00742                     ia.rename(outparentim,overwrite=True) 
00743                     ia.done()
00744                     outputmsg="to create an output mask: %s " % outparentim
00745 
00746                 casalog.post("Merged masks from:","INFO")
00747                 if len(usedimfiles)>0:
00748                     casalog.post("mask image(s): "+str(usedimfiles),"INFO")
00749                 if len(usedbmasks)>0:
00750                     casalog.post("internal mask(s): "+str(usedbmasks),"INFO")
00751                 if len(usedrgfiles)>0:
00752                     casalog.post("region txt file(s): "+str(usedrgfiles),"INFO")
00753                 if len(usedrglist)>0:
00754                     casalog.post("region(s) from direct input: "+str(usedrglist),"INFO")
00755                 casalog.post(outputmsg,"INFO")
00756                 
00757 
00758             except Exception, instance:
00759                 print "*** Error ***", instance
00760                 raise Exception, instance
00761             finally:
00762                 if os.path.exists(sum_tmp_outfile):
00763                     shutil.rmtree(sum_tmp_outfile)
00764                 if os.path.exists(tmp_inmask):
00765                     shutil.rmtree(tmp_inmask)
00766                 if type(inpimage)==list:
00767                    for im in inpimage:
00768                        if os.path.isdir('__tmp_regrid.'+im):
00769                             shutil.rmtree('__tmp_regrid.'+im)
00770                        
00771              
00772                  
00773     # === draw mode ===
00774     # disabled - drawmaskinimage (working with viewer) a bit flaky
00775     # when run in succession.
00776     #    if mode=='draw':
00777     #        #call drawmaskinimage
00778     #        from recipes.drawmaskinimage import drawmaskinimage
00779     #        drawmaskinimage(inpimage,outmask)
00780             
00781 
00782     except Exception, instance:
00783         print '*** Error ****', instance
00784         raise Exception, instance
00785 
00786     finally:
00787         # final clean up 
00788         if os.path.isdir(tmp_maskimage):
00789             shutil.rmtree(tmp_maskimage)
00790         if os.path.isdir(tmp_outmaskimage):
00791             shutil.rmtree(tmp_outmaskimage)
00792         if os.path.isdir(tmp_regridim):
00793             shutil.rmtree(tmp_regridim)
00794 
00795 def findnearest(arr, val):
00796     import numpy as np
00797     if type(arr)==list:
00798         arr = np.array(arr) 
00799     indx = np.abs(arr - val).argmin()
00800     return arr[indx] 
00801 
00802 def regridmask(inputmask,template,outputmask,axes=[3,0,1],method='linear',chanrange=None):
00803     '''
00804     Regrid input mask (image) to output mask using a template.
00805     Currently the template must be a CASA image.
00806     The default interpolation method is set to 'linear' (since 'nearest'
00807     sometime fails).
00808     '''
00809     #print "Regrid.."
00810     #print "inputmask=",inputmask," template=",template," outputmask=",outputmask
00811     if not os.path.isdir(template):
00812         raise IOError, "template image %s does not exist" % template
00813     
00814     (ia,) = gentools(['ia']) 
00815     ia.open(template)
00816     ocsys = ia.coordsys()
00817     oshp = ia.shape()
00818     ia.done()
00819     ia.open(inputmask)
00820     # check axis order, if necessary re-interprete input axes correctly 
00821     # assumed order of axes 
00822     reforder=['Right Ascension', 'Declination', 'Stokes', 'Frequency']
00823     axisorder=ia.summary(list=False)['axisnames'].tolist()
00824     tmp_axes=[]
00825     for axi in axes:
00826         tmp_axes.append(axisorder.index(reforder[axi]))        
00827     axes=tmp_axes
00828     if type(chanrange)==list and len(chanrange)==2:
00829         incsys=ia.coordsys()
00830         spaxis=incsys.findcoordinate('spectral')[2]
00831         # create subimage based on the inpfreqs range
00832         inblc=chanrange[0]
00833         intrc=chanrange[1]
00834         casalog.post("Regridmask: spaxis=%s, inblc=%s, intrc=%s" % (spaxis,inblc,intrc), 'DEBUG1')
00835         rgn = rg.wbox(blc=inblc,trc=intrc,pixelaxes=spaxis.tolist(),csys=incsys.torecord())
00836     else:
00837         rgn={}     
00838     # for continuum case
00839     if oshp[tmp_axes[0]]==1:
00840        axes=[0,1]
00841     ir=ia.regrid(outfile=outputmask,shape=oshp,csys=ocsys.torecord(),axes=axes,region=rgn,method=method)       
00842     ia.done()
00843     # to ensure to create 1/0 mask image
00844     #ir.calc('iif (%s>0.0 && %s<1.0,1,%s)'%(outputmask,outputmask,outputmask))
00845     # treat everything not = 0.0 to be mask
00846     ir.calc('iif (abs(%s)>0.0,1,%s)'%(outputmask,outputmask))
00847     ir.done()
00848 
00849 def addimagemask(sumimage, imagetoadd, threshold=0.0):
00850     """
00851     add image masks (assumed the images are already in the same coordinates)
00852     """
00853     (ia,) = gentools(['ia']) 
00854     #print "addimagemask: sumimage=",sumimage," imagetoadd=",imagetoadd
00855     ia.open(sumimage)
00856     ia.calc('iif ('+imagetoadd+'>'+str(threshold)+',('+sumimage+'+'+imagetoadd+')/('+sumimage+'+'+imagetoadd+'),'+sumimage+')')
00857     ia.close()  
00858 
00859 def expandchanmask(inimage,inchans,outimage,outchans):
00860     """
00861     expand masks in channel direction,and insert then
00862     to output image with the same coordinates (post-regridded)
00863     only differ by channels
00864     """
00865     # input image
00866     ia.open(inimage)
00867     inshp=ia.shape()
00868     refchanst=inchans[0]
00869     refchanen=inchans[-1]
00870     slst = [0,0,0,refchanst]
00871     slen = [inshp[0]-1,inshp[1]-1,0,refchanen]
00872     casalog.post("getting chunk at blc="+str(slst)+" trc="+str(slen),'DEBUG1')
00873     refchanchunk=ia.getchunk(blc=slst,trc=slen)
00874     refchanchunk=refchanchunk.transpose()
00875     ia.close()
00876     #print "refchanchunk:shape=",refchanchunk.shape
00877 
00878     ia.open(outimage)
00879     # need find nearest inchan
00880     # store by chan indices (no regrid)
00881     outshp=ia.shape()
00882     if outchans==[]:
00883         #select all channels
00884         outchans=range(outshp[3])
00885     usechanims={}  # list of input mask to be use for each outpfreq
00886     for i in outchans:
00887         nearestch = findnearest(inchans,i)
00888         usechanims[i]=nearestch
00889     casalog.post("Mapping of channels: usechanims="+str(usechanims),'DEBUG1')
00890     for j in outchans:
00891         pix = refchanchunk[usechanims[j]-refchanst]
00892         #print "pix=",pix
00893         #print "pix.shape=",pix.shape
00894         #print "inshp=",inshp, ' j=',j
00895         #ia.putchunk(pixels=pix,blc=[inshp[0]-1,inshp[1]-1,0,j])
00896         ia.putchunk(pixels=pix.transpose(),blc=[0,0,0,j])
00897         #print "DONE putchunk for j=", j
00898     ia.done()
00899 
00900 def translatefreqrange(freqrange,csys):
00901     """
00902     convert the range in list
00903     mainly for frequeny and velocity range determination
00904     """
00905     if type(freqrange)==list and type(freqrange[0])==int:
00906         #do nothing
00907         return freqrange
00908     elif type(freqrange)==str:
00909         freqlist=freqrange.split('~') 
00910         for i in range(len(freqlist)):
00911             if freqlist[i].find('m/s') > -1:
00912                fq = qa.quantity(freqlist[i])
00913                vf=csys.velocitytofrequency(value=fq['value'],velunit=fq['unit'])
00914                freqlist[i]=str(vf[0])+'Hz'
00915         return freqlist
00916     else:
00917         raise TypeError, "Cannot understand frequency range"
00918 
00919 def checkinput(inpname):
00920     """
00921     do existance check on image and internal mask 
00922     """
00923     (parentimage,tfmaskname)=extractmaskname(inpname)
00924     (parentimexist,tfmaskexist)=checkinmask(parentimage,tfmaskname)
00925     if parentimexist:
00926         if tfmaskname=='':
00927             return True # only the image
00928         else:
00929             if not tfmaskexist: 
00930                 ia.open(parentimage)
00931                 inmasklist=ia.maskhandler('get')
00932                 raise Exception, "Cannot find the internal mask, %s. Candidate mask(s) are %s" % (tfmaskname, str(inmasklist))
00933             else:
00934                 return True # image mask and internal mask
00935     else:
00936         raise Exception, "Cannot find the image=%s" % parentimage 
00937    
00938 
00939 def checkinmask(parentimage,tfmaskname):
00940     """
00941     check existance of the internal mask
00942     """
00943     if os.path.isdir(parentimage):
00944         if tfmaskname!='':
00945             ia.open(parentimage)
00946             inmasks=ia.maskhandler('get')
00947             ia.close()
00948             if not any(tfmaskname in msk for msk in inmasks):
00949                return (True, False)
00950             else:
00951                return (True, True) # image mask and internal mask
00952         else:
00953             return (True, False)
00954     else:
00955        return (False,False) 
00956 
00957 def extractmaskname(maskname):
00958     """
00959     split out imagename and maskname from a maskname string
00960     returns (parentimage, internalmask)
00961     """
00962     # the image file name may contains ':' some cases
00963     # take last one in split list as an internal mask name
00964 
00965     indx = maskname.find(':') 
00966     for i in range(len(maskname)):
00967         if indx>-1:
00968             indx += maskname[indx+1:].find(':') 
00969             indx +=1
00970         else:
00971             break
00972     if indx != -1: 
00973         parentimage=maskname[:indx]
00974         maskn=maskname[indx+1:]
00975         return (parentimage,maskn) 
00976     else:
00977         parentimage=maskname
00978         return (parentimage, '')
00979 
00980 def makeEmptyimage(template,outimage):
00981     """
00982     make an empty image with the coords
00983     from template
00984     """
00985     (ia,) = gentools(['ia'])
00986     ia.open(template)
00987     inshp=ia.shape()
00988     incsys=ia.coordsys()
00989     ia.fromshape(outimage,shape=inshp,csys=incsys.torecord())
00990     ia.done()