casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_immath.py
Go to the documentation of this file.
00001 ########################################################################3
00002 #  task_immath.py
00003 #
00004 # Copyright (C) 2008, 2009
00005 # Associated Universities, Inc. Washington DC, USA.
00006 #
00007 # This script is free software; you can redistribute it and/or modify it
00008 # under the terms of the GNU Library General Public License as published by
00009 # the Free Software Foundation; either version 2 of the License, or (at your
00010 # option) any later version.
00011 #
00012 # This library is distributed in the hope that it will be useful, but WITHOUT
00013 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015 # License for more details.
00016 #
00017 # You should have received a copy of the GNU Library General Public License
00018 # along with this library; if not, write to the Free Software Foundation,
00019 # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00020 #
00021 # Correspondence concerning AIPS++ should be adressed as follows:
00022 #        Internet email: aips2-request@nrao.edu.
00023 #        Postal address: AIPS++ Project Office
00024 #                        National Radio Astronomy Observatory
00025 #                        520 Edgemont Road
00026 #                        Charlottesville, VA 22903-2475 USA
00027 #
00028 # <summary>
00029 # CASA task for smoothing an image, by doing Forier-based convolution
00030 # on a CASA image file.
00031 # </summary>
00032 #
00033 # <reviewed reviwer="" date="" tests="" demos="">
00034 # </reviewed
00035 #
00036 # <author>
00037 # Shannon Jaeger, University of Calgary  (image math) 
00038 # Takeshi Nakazato, National Radio Astronomy Obaservatory (polarization)
00039 # </author>
00040 #
00041 # <prerequisite>
00042 # </prerequisite>
00043 #
00044 # <etymology>
00045 # immath stands for image mathematics
00046 # </etymology>
00047 #
00048 # <synopsis>
00049 #    This task evaluates mathematical expressions involving existing
00050 #    image files. The results of the calculations are stored in the 
00051 #    designated output file.  Options are available to specify mathematical 
00052 #    expression directly or pre-defined expression for calculation of 
00053 #    spectral index image, and polarization intensity and position angle 
00054 #    images are available. The image file names imbedded in the expression or
00055 #    specified in the imagename parameter for the pre-defined calculations may
00056 #    be CASA images or FITS images.
00057 #
00058 #
00059 #    NOTE: Index values for axes start at 0 for the box and chans
00060 #          parameters, but at 1 when used with the indexin function
00061 #          in expression. Use the imhead task to see the range of
00062 #          values for each axes.
00063 #    
00064 #
00065 #    Keyword arguments:
00066 #    outfile -- The file where the results of the image calculations 
00067 #                are stored.  Overwriting an existing outfile is not permitted.
00068 #            Default: none;  Example: outfile='results.im'
00069 #    mode -- mode for mathematical operation
00070 #            Default: evalexpr
00071 #            Options: 'evalexpr' : evalulate a mathematical expression defined in 'expr' 
00072 #                     'spix' : spectalindex image 
00073 #                     'pola' : polarization position angle image 
00074 #                     'poli' : polarization intesity image 
00075 #           mode expandable parameters
00076 #            expr -- (for mode='evalexpr') A mathematical expression, with image file names.
00077 #              Image file names MUST be enclosed in double quotes (&quot;)
00078 #              Default: none 
00079 #              Examples:
00080 #                 Make an image that is image1.im - image2.im
00081 #                   expr=' (&quot;image1.im&quot; - &quot;image2.im&quot; )'
00082 #                 Clip an image below a value (0.5 in this case)
00083 #                   expr = ' iif(&quot;image1.im&quot;>=0.5, &quot;image1.im&quot;, 0.0) '
00084 #                         Note: iif (a, b, c)   a is the boolian expression
00085 #                                               b is the value if true
00086 #                                               c is the value if false
00087 #                 Take the rms value of two images
00088 #                   expr = ' sqrt(&quot;image1.im&quot; * &quot;image1.im&quot; + &quot;image2.im&quot; * &quot;image2.im&quot;) '
00089 #                         Note: No exponentiaion available?
00090 #                 Build an image pixel by pixel from the minimum of (image2.im, 2*image1.im)
00091 #                   expr='min(&quot;image2.im&quot;,2*max(&quot;image1.im&quot;))'
00092 #            imagename -- (for mode='spix','pola','poli') input image names        
00093 #              Default: none;
00094 #              Examples: mode='spix'; imagename=['image1.im','image2.im'] will calculate 
00095 #                       an image of log(S1/S2)/log(f1/f2), where S1 and S2 are fluxes and 
00096 #                       f1 and f2 are frequencies
00097 #                       mode='pola'; imagename=['imageQ.im','imageU.im'] will calculate 
00098 #                       an image of polarization angle distribution, where imageQ.im and 
00099 #                       imageU.im are Stokes Q and U images, respectively. Calculate 0.5*arctan(U/Q).
00100 #                       mode='poli'; imagename=['imageQ.im','imageU.im','imageV.im'] will calculate
00101 #                       total polarization intensity image, where imageQ.im, imageU.im, imageV.im
00102 #                       are Stokes Q, U, and V images, respectively.
00103 #            sigma - (for mode='poli') standard deviation of noise of Stokes images with unit such as
00104 #                    Jy/beam to correct for bias 
00105 #              Default: '0.0Jy/beam' (= no debiasing)
00106 #    mask -- Name of mask applied to each image in the calculation
00107 #            Default '' means no mask;  Example: mask='orion.mask'.  
00108 #    region -- File path to an ImageRegion file.
00109 #            An ImageRegion file can be created with the CASA
00110 #            viewer's region manager.  Typically ImageRegion files
00111 #            will have the suffix '.rgn'.  If a region file is given
00112 #            then the box, chans, and stokes selections whill be 
00113 #            ignored.
00114 #            Default: none
00115 #            Example: region='myimage.im.rgn'
00116 #    box --  A box region on the directional plane
00117 #            Only pixel values acceptable at this time.
00118 #            Default: none (whole 2-D plane);  Example: box='10,10,50,50'
00119 #    chans -- channel numbers, velocity, and/or frequency
00120 #            Only channel numbers acceptable at this time.
00121 #            Default: none (all);  Example: chans='3~20'   
00122 #    stokes -- Stokes parameters to image, may or may not be separated
00123 #            by commas but best if you use commas.
00124 #            Default: none (all); Example: stokes='IQUV';
00125 #            Options: 'I','Q','U','V','RR','RL','LR','LL','XX','YX','XY','YY', ... 
00126 #
00127 #    Available functions in the <i>expr</i> and <i>mask</i> paramters:
00128 #    pi(), e(), sin(), sinh(), asinh(), cos(), cosh(), tan(), tanh(),
00129 #    atan(), exp(), log(), log10(), pow(), sqrt(), complex(), conj()
00130 #    real(), imag(), abs(), arg(), phase(), aplitude(), min(), max()
00131 #    round(), isgn(), floor(), ceil(), rebin(), spectralindex(), pa(), 
00132 #    iif(), indexin(), replace(), ...
00133 #
00134 #    For a full description of the allowed syntax see the 
00135 #    Lattice Expression Language (LEL) documentation on the at:
00136 #    http://aips2.nrao.edu/docs/notes/223/223.html
00137 #
00138 #    NOTE: where indexing and axis numbering are used in the above
00139 #    functions they are 1-based, ie. numbering starts at 1.
00140 #
00141 # </synopsis> 
00142 #
00143 # <example>
00144 # <srcblock>
00145 # </srcblock
00146 #
00147 # </example>
00148 #
00149 # <motivation>
00150 # To provide a user-friendly task interface to imagecalc and ???
00151 # as well as an more user-friendling math syntax then what is
00152 # provided by the CASA Lattice Exprssion Language.
00153 # </motivation>
00154 #
00155 # <todo>
00156 #  Crystal wanted different masks for different inputs
00157 #  but unlikely that its really needed.
00158 #
00159 #  Add an "overwrite" output file parameter
00160 #
00161 #  Add polygon and circle region selection 
00162 # </todo>
00163 ########################################################################3
00164 
00165 
00166 import os
00167 import shutil
00168 from taskinit import *
00169 
00170 def immath(
00171     imagename, mode, outfile, expr, varnames, sigma,
00172     polithresh, mask, region, box, chans, stokes, stretch
00173 ):
00174     # Tell CASA who will be reporting
00175     casalog.origin('immath')
00176     retValue = False
00177     # NOTE: This step likely be eliminated
00178     # 
00179     # Remove any old tmp files that may be left from
00180     # a previous run of immath
00181     tb.clearlocks()    
00182     tmpFilePrefix='_immath_tmp'
00183     try:
00184         _immath_cleanup( tmpFilePrefix )
00185     except Exception, e:
00186         casalog.post( 'Unable to cleanup working directory '+os.getcwd()+'\n'+str(e), 'SEVERE' )
00187         raise Exception, str(e)
00188 
00189 
00190     # Keep track of which LEL functions are upper-case and
00191     # which are lower-case.  For some reason LEL was written
00192     # to be case sensitive!
00193     #
00194     # The values stored are in the opposite case of what we want, 
00195     # because we want to search for the invalid case.
00196     #
00197     # Note these were found in the various LEL*Enums.h files.
00198     lower_case=[ 'SIN(', 'SINH(', 'ASIN(', 'COS(', 'COSH(', 'ACOS(', 'TAN(', \
00199                  'TANH(', 'ATAN(', 'ATAN2(', 'EXP(', 'LOG(', 'LOG10(', 'POW(',\
00200                  'SQRT(', 'ROUND(', 'SIGN(', 'CEIL(', 'FLOOR(', 'ABS(', \
00201                  'ARG(', 'REAL(', 'IMAG(', 'CONJ(', 'COMPLEX(', 'FMOD(' \
00202                  'MIN(', 'MAX(', 'MIN1D(', 'MAX1D(', 'MEAN1D(', 'MEDIAN1D('\
00203                  'FRACTILE1D(', 'FRACTILERANGE1D(', 'SUM(', 'NELEM(', 'ALL('\
00204                  'ANY(', 'IIF(', 'REPLACE(', 'LENGTH(', 'INDEXIN(', 'NDIM' ]
00205     upper_case=[ ]
00206     
00207     # First check to see if the output file exists.  If it
00208     # does then we abort.  CASA doesn't allow files to be
00209     # over-written, just a policy.
00210     if ( len( outfile ) < 1 ):
00211         outfile = 'immath_results.im'
00212         casalog.post( "The outfile paramter is empty, consequently the" \
00213                       +" resultant image will be\nsaved on disk in file, " \
00214                       + outfile, 'WARN' )
00215     if ( len( outfile ) > 0 and os.path.exists( outfile ) ):
00216         raise Exception, 'Output file, '+outfile+\
00217               ' exists. immath can not proceed, please\n'+\
00218               'remove it or change the output file name.'
00219     
00220     # Find the list of filenames in the expression
00221     # also do a quick check to see if all of the files
00222     # exist
00223     #
00224     # TODO add a size check to make sure all images are the
00225     # same size.  Is this
00226     tmpfilenames=''
00227     if mode=='evalexpr':
00228         tmpfilenames=_immath_parse( expr )
00229         filenames=imagename
00230     else:
00231         filenames=imagename
00232     if ( isinstance( filenames, str ) ):
00233         filenames= [ filenames ]
00234     casalog.post( 'List of input files is: '+str(filenames), 'DEBUG1' )
00235     #for i in range( len(filenames) ):
00236     #        if ( not os.path.exists(filenames[i]) ):
00237     #            raise Exception, 'Image data set not found - please verify '+filenames[i]
00238 
00239     # Construct the variable name list.  We append to the list the
00240     # default variable names if the user hasn't supplied a full suite.
00241     if ( not isinstance( varnames, list ) ):
00242         name0=varnames
00243         varnames=[]
00244         if ( len(name0 ) > 0 ):
00245             varnames.append( name0 )
00246     nfile=max(len(filenames),len(tmpfilenames))
00247     #for i in range( len(varnames), len(filenames) ):
00248     for i in range( len(varnames), nfile ):
00249         varnames.append( 'IM'+str(i) )
00250     casalog.post( 'Variable name list is: '+str(varnames), 'DEBUG1' )
00251 
00252     _myia = iatool()
00253 
00254     #file existance check
00255     ignoreimagename=False
00256     if mode=='evalexpr':
00257         varnamesSet=set(varnames)
00258         count = 0
00259         for imname in tmpfilenames:
00260             # check if it is one of varnames, if not check the files in expr exist 
00261             if(not varnamesSet.issuperset(imname)):
00262                if( not os.path.exists(imname)):
00263                    raise Exception, 'Image data set not found - please verify '+imname
00264                else:
00265                    count=count+1            
00266         if len(tmpfilenames)==count:
00267             ignoreimagename=True
00268             filenames=tmpfilenames
00269         #if(tmpfilenames==['']): 
00270         #    for i in range(len(varnames)):
00271         #       if(expr.count(varnames[i])==0):
00272         #           casalog.post('Variable name '+varnames[i]+' not found in the expression.','WARN')
00273     if not ignoreimagename:
00274         for i in range( len(filenames) ):
00275             if ( not os.path.exists(filenames[i]) ):
00276                 raise Exception, 'Image data set not found - please verify '+filenames[i]
00277 
00278        
00279     # Remove spaces from the expression.
00280     expr=expr.replace( ' ', '' )
00281 
00282     doPolThresh = False
00283 
00284     # Construct expressions for the spectral and polarization modes.
00285     # These are common, repetitive calculations that are handled for
00286     # the user.
00287     if mode=='spix':
00288         # calculate a spectral index distribution image
00289         if len(filenames) != 2:
00290             raise Exception, 'Requires two images at different frequencies'
00291         #expr = 'spectralindex("%s","%s")' % (filenames[0],filenames[1])
00292 
00293         expr = 'spectralindex('+varnames[0]+', '+varnames[1]+')'
00294     elif mode=='pola':
00295         expr = _doPolA(filenames, varnames, tmpFilePrefix)
00296         if (polithresh):
00297             if (mask != ""):
00298                 mask = ""
00299                 casalog.post("Ignoring mask parameter in favor of polithresh parameter", 'WARN')
00300             if (qa.getunit(polithresh) != ""):
00301                 initUnit = qa.getunit(polithresh)
00302                 _myia.open(filenames[0])
00303                 bunit = _myia.brightnessunit()
00304                 polithresh = qa.convert(polithresh, bunit)
00305                 _myia.done()
00306                 if (qa.getunit(polithresh) != bunit):
00307                     raise Exception, "Units of polithresh " + initUnit \
00308                     + " do not conform to input image units of " + bunit \
00309                     + " so cannot perform thresholding. Please correct units and try again."
00310                 polithresh = qa.getvalue(polithresh)[0]
00311             doPolThresh = True
00312             [lpolexpr, isLPol, isTPol] = _doPolI(filenames, varnames, tmpFilePrefix, False, False)
00313             lpolexpr = _immath_expr_from_varnames(lpolexpr, varnames, filenames)
00314             lpolexpr = lpolexpr + ")"
00315             lpol = tmpFilePrefix + "_lpol.im"
00316             res = _myia.imagecalc(pixels=lpolexpr, outfile=lpol)
00317             res.done()
00318     elif mode=='poli':
00319         [expr, isLPol, isTPol] = _doPolI(filenames, varnames, tmpFilePrefix, True, True)
00320         sigsq=0
00321         if len(sigma)>0:
00322             qsigma=qa.quantity(sigma)
00323             if qa.getvalue(qsigma)[0] >0:
00324                 sigmaunit=qa.getunit(qsigma)
00325                 try:
00326                     _myia.open(filenames[0])
00327                     iunit = _myia.brightnessunit()
00328                     _myia.done()
00329                 except:
00330                     raise Exception, 'Unable to get brightness unit from image file '+filenames[0]
00331                 if sigmaunit!=iunit:
00332                     newsigma=qa.convert(qsigma,iunit)
00333                 else:
00334                     newsigma=sigma
00335                     sigsq=(qa.getvalue(newsigma)[0])**2
00336                 expr+='-%s' % sigsq
00337             expr+=')'
00338         # reset stokes selection for pola and poli
00339     if (mode=='pola' or mode=='poli') and len(stokes)!=0:
00340         casalog.post( "Ignoring stokes parameters selection." ,'WARN' );
00341         stokes=''
00342 
00343     # PUT TRY BLOCK AROUND THIS PART
00344     #
00345     # NEED TO DO EXPRESSION FOR EXPR MODE
00346 
00347             
00348     # If the user didn't give any region or mask information
00349     # then just evaluated the expression with the filenames in it.
00350     if ( len(box)<1 and len(chans)<1 and len(stokes)<1 and len(region)<1 and len(mask)<1):
00351         expr = _immath_expr_from_varnames(expr, varnames, filenames)
00352         casalog.post( 'Will evaluate expression: '+expr, 'DEBUG1' )
00353         try:
00354             res = _myia.imagecalc(pixels=expr, outfile=outfile)
00355             # need to modify stokes type of output image for pol. intensity image
00356             if ( mode =="poli" ):
00357                 csys = res.coordsys()
00358                 if isTPol:
00359                     csys.setstokes('Ptotal')
00360                 elif isLPol:
00361                     csys.setstokes('Plinear')
00362                 res.setcoordsys(csys.torecord())
00363             res.done()
00364             if (doPolThresh):
00365                 _immath_createPolMask(polithresh, lpol, outfile)
00366             return True
00367         except Exception, error:
00368             try:
00369                 _myia.done()
00370             except:
00371                 pass
00372             casalog.post( 'Unable to do mathematical expression: '\
00373                   +expr+'\n'+str(error), 'SEVERE' )
00374             return False
00375    
00376     # If we've made it here we need to apply masks or extract
00377     # regions from the images before doing the calculations first.
00378     # Warning if user has given a region file plus other region
00379     # selection information
00380                 
00381     # For each file in the list of files, creat a subimage
00382     # of it and store it.  We need to do this only if the user
00383     # specified a region or mask information.
00384     subImages=[]
00385     casalog.post( "SUBIMAGES: "+str(subImages), 'DEBUG2' )
00386     file_map = {}
00387     
00388     i = 0
00389     for image in filenames:
00390         casalog.post( 'Creating tmp image for image ' + image, 'DEBUG2')
00391         
00392         _myia.open(image)
00393         reg = rg.frombcs(csys=_myia.coordsys().torecord(),
00394             shape=_myia.shape(), box=box, chans=chans, stokes=stokes,
00395             stokescontrol="a", region=region
00396         )
00397         _myia.close()
00398             
00399         # TODO see if there are issues when NO region given by user
00400         try:
00401             _myia.open(image)
00402             tmpFile=tmpFilePrefix+str(i)
00403             _myia.subimage( region=reg, mask=mask, outfile=tmpFile, stretch=stretch )
00404             file_map[image] = tmpFile
00405             subImages.append( tmpFile )
00406             _myia.done()
00407             casalog.post( 'Created temporary image '+tmpFile+' from '+\
00408                           image, 'DEBUG1' )
00409             i = i + 1
00410 
00411         except Exception, e:
00412             try:
00413                 _mia.done()
00414             except:
00415                 pass
00416             casalog.post( 'Exception caught is: '+str(e), 'DEBUG2' )
00417             casalog.post( 'Unable to apply region to file: '\
00418                   + image\
00419                   +'.\nUsed region: '+str(reg), 'DEBUG2' )
00420             #raise Exception, 'Unable to apply region to file: '\
00421             #      +filenames[i]
00422             casalog.post( 'Unable to apply region to file: '\
00423                           + image, 'SEVERE' )
00424             return False
00425     # Make sure no problems happened
00426 
00427 
00428     if ( len(filenames) != len(subImages) ) :
00429         #raise Exception, 'Unable to create subimages for all image names given'
00430         casalog.post( 'Unable to create subimages for all image names given',\
00431                       'SEVERE' )
00432         return False
00433     
00434     # because real file names also have to be mapped to a corresponding subimage, CAS-1830
00435     for k in file_map.keys():
00436         # we require actual image names to be in quotes when used in the expression
00437         varnames.extend(["'" + k + "'", '"' + k + '"'])
00438         subImages.extend(2 * [file_map[k]])
00439 
00440     
00441     # Put the subimage names into the expression
00442     try:
00443         expr = _immath_expr_from_varnames(expr, varnames, subImages)
00444 
00445     except Exception, e:
00446         casalog.post(
00447             "Unable to construct pixel expression aborting immath: " + str(e),
00448             'SEVERE'
00449         )
00450         return False
00451     casalog.post( 'Will evaluate expression of subimages: '+expr, 'DEBUG1' )
00452 
00453     try:
00454         # Do the calculation
00455         res = _myia.imagecalc(pixels=expr, outfile=outfile )
00456 
00457         # modify stokes type for polarization intensity image
00458         if (  mode=="poli" ):                
00459             csys=retValue.coordsys()
00460             if isTPol:
00461                 csys.setstokes('Ptotal')
00462             elif isLPol:
00463                 csys.setstokes('Plinear')
00464             res.setcoordsys(csys.torecord())
00465         res.done()
00466         if (doPolThresh):
00467             _immath_createPolMask(polithresh, lpol, outfile)
00468 
00469         #cleanup
00470         _myia.done()                
00471         _immath_cleanup( tmpFilePrefix )
00472                     
00473         return True
00474     except Exception, error:
00475         try:
00476             _myia.done()
00477             _immath_cleanup( tmpFilePrefix )
00478         except:
00479             pass
00480         casalog.post( "Exception caught was: "+str(error), 'DEBUG2')
00481         #raise Exception, 'Unable to evaluate math expression: '\
00482         #      +expr+' on file(s) '+str(filenames)
00483         casalog.post( 'Unable to evaluate math expression: '\
00484                       +expr+' on file(s) '+str(filenames), 'SEVERE' )
00485         return False
00486         
00487 
00488     # Remove any temporary files
00489     try: 
00490         _immath_cleanup( tmpFilePrefix )
00491     except:
00492         casalog.post( 'immath was unable to cleanup temporary files','SEVERE' )
00493         return False
00494     return True
00495 
00496 def _immath_cleanup( filePrefix ):
00497     # Remove any old tmp files that may be left from
00498     # a previous run of immath
00499     fileList=os.listdir( os.getcwd() )
00500     for file in fileList:
00501         if ( file.startswith( filePrefix ) ):
00502             #recursivermdir( file )
00503             shutil.rmtree( file )
00504 
00505 
00506 def _immath_parse( expr='' ):
00507         retValue=[]
00508         
00509         # Find out if the names are surrounded by single or double quotes
00510         quote=''
00511         if ( expr.find('"') > -1 ):
00512             quote='"'
00513         if ( expr.find("'") > -1 ):
00514             quote="'"
00515 
00516         current=expr;
00517         while( current.count(quote) > 1 ):
00518             start = current.index(quote)+1
00519             end   = current[start:].index(quote)+start
00520             if ( retValue.count( current[start:end] ) > 0 ) :
00521                 # We already have this file name so we won't add it
00522                 # to the list again.  This saves us work and disk space.
00523                 current=current[end+1:]
00524                 continue;
00525             
00526             retValue.append( current[start:end] )
00527             current=current[end+1:]
00528 
00529         return retValue
00530 
00531 # check stokes type for the list of images
00532 def __check_stokes(images):
00533         _myia = iatool()
00534         retValue=[]
00535         for fname in images:
00536             _myia.open(fname)
00537             csys = _myia.coordsys()
00538             stks=csys.stokes()
00539             _myia.close()
00540             retValue.extend(stks)
00541         return retValue
00542        
00543 # it is important to sort the varnames in reverse order before doing
00544 # the substitutions to assure the substitution set is performed correctly
00545 # CAS-1678
00546 def _immath_expr_from_varnames(expr, varnames, filenames):
00547         tmpfiles = {}
00548         for i in range(len(filenames)):
00549                 tmpfiles[varnames[i]] = filenames[i]
00550         tmpvars = tmpfiles.keys()
00551 
00552         tmpvars.sort()
00553         tmpvars.reverse()
00554         for varname in tmpvars:
00555                 expr = expr.replace(varname, '"' + tmpfiles[varname] + '"')
00556         return(expr)
00557 
00558 def _doPolA(filenames, varnames, tmpFilePrefix):
00559     # calculate a polarization position angle image
00560     stkslist = __check_stokes(filenames)
00561     Uimage = Qimage = ''
00562     _myia = iatool()
00563     if len(filenames) == 1:
00564         # FIXME I really hate creating subimages like this, the poli and pola routines really belong in the as of now non-existant squah task
00565         if (type(stkslist) != list):
00566             raise Exception, filenames[0] + " is the only image specified but it is not multi-stokes so cannot do pola calculation"
00567         _myia.open(filenames[0])
00568         spixels = _myia.coordsys().findcoordinate('stokes')[1]
00569         if (len(spixels) != 1):
00570             raise Exception, filenames[i] + "does not have exactly one stokes axis, cannot do pola calculation"
00571         stokesPixel = spixels[0]
00572         trc = _myia.shape()
00573         blc = []
00574         for i in range(len(trc)):
00575             blc.append(0)
00576             trc[i] = trc[i] - 1
00577         for stokes in (['Q', 'U']):
00578             if (stkslist.count(stokes) == 0):
00579                 raise Exception, filenames[0] + " is the only image specified but it does not contain stokes " + stokes \
00580                 + " so pola calculation cannot be done"
00581             pixNum = stkslist.index(stokes)
00582             blc[stokesPixel] = pixNum
00583             trc[stokesPixel] = pixNum
00584             myfile = tmpFilePrefix + '_' + stokes
00585             _myia.subimage(outfile=myfile, region=rg.box(blc=blc, trc=trc))
00586             if (stokes == 'Q'):
00587                 Qimage = myfile
00588             elif (stokes == 'U'):
00589                 Uimage = myfile
00590         _myia.done()
00591         # to use pass by reference semantics correctly, we have to use the same objects passed in
00592         # rather than create new objects with the same names
00593         filenames[0:1] = [Qimage, Uimage]
00594         varnames[0:1] = ["IM0", "IM1"]
00595     else:
00596         if len(filenames) > 2:
00597             casalog.post( "More than two images. Take first two and ignore the rest. " ,'WARN' );
00598         for i in range(2):
00599             if type(stkslist[i]) == list:
00600                 raise Exception, filenames[i] + " is a mult-stokes image but multiple images are given for pola calculation. " \
00601                 + "Only a single multi-stokes image *or* multiple single stokes images can be specified for pola calculation"
00602             else:
00603                 if stkslist[i] == 'U':
00604                     Uimage = varnames[i]
00605                 if stkslist[i] == 'Q':
00606                     Qimage = varnames[i]
00607         if len(Uimage)<1 or len(Qimage)<1:
00608             missing = []
00609             if len(Qimage)<1: missing.append('Q')
00610             if len(Uimage)<1: missing.append('U')
00611             raise Exception, 'Missing Stokes %s image(s)' % missing
00612     expr = 'pa(%s,%s)' % (Uimage, Qimage)
00613     return expr
00614 
00615 def _doPolI(filenames, varnames, tmpFilePrefix, createSubims, tpol):
00616     # FIXME good grief, I question that these opcodes should even exist in immath
00617     # there is a polarization image tool (po) that does all of this much more nicely
00618     # calculate a polarization intensity image
00619     # if 3 files (or 1 file with Q, U, V) total pol intensity image
00620     # if 2 files (or file file with Q, U) given linear pol intensity image
00621     # FIXME I really hate creating subimages like this, the poli and pola routines really belong in the as of now non-existant squah task
00622     if len(filenames) < 1 or len(filenames) > 3:
00623         raise Exception, 'poli requires one multistokes with Q, U, and optionally V stokes or two single stokes (Q, U) images or three single Stokes (Q,U,V) images'
00624     isQim = False
00625     isUim = False
00626     isVim = False
00627     isLPol = False
00628     isTPol = False
00629 
00630     stkslist=__check_stokes(filenames)
00631     if len(filenames) == 1:
00632         # do multistokes image
00633         if (len(stkslist) < 2):
00634             raise Exception, filenames[0] + " is the only image specified but it is not multi-stokes so cannot do poli calculation"
00635         _myia = iatool()
00636         _myia.open(filenames[0])
00637         spixels = _myia.coordsys().findcoordinate('stokes')[1]
00638         if (len(spixels) != 1):
00639             _myia.close()
00640             raise Exception, filenames[i] + "does not have exactly one stokes axis, cannot do pola calculation"
00641 
00642         stokesPixel = spixels[0]
00643         trc = _myia.shape()
00644         blc = []
00645 
00646         for i in range(len(trc)):
00647             blc.append(0)
00648             trc[i] = trc[i] - 1
00649         neededStokes = ['Q', 'U']
00650         if (stkslist.count('V')):
00651             neededStokes.append('V')
00652         Qimage = Uimage = Vimage = ''
00653         for stokes in (neededStokes):
00654             if ((stokes == 'Q' or stokes == 'U') and stkslist.count(stokes) == 0):
00655                 _myia.close()
00656                 raise Exception, filenames[0] + " is the only image specified but it does not contain stokes " + stokes \
00657                 + " so poli calculation cannot be done"
00658             myfile = tmpFilePrefix + '_' + stokes
00659             if (stokes == 'Q'):
00660                 Qimage = myfile
00661             elif (stokes == 'U'):
00662                 Uimage = myfile
00663             elif (stokes == 'V' and tpol):
00664                 Vimage = myfile
00665             if createSubims:
00666                 pixNum = stkslist.index(stokes)
00667                 blc[stokesPixel] = pixNum
00668                 trc[stokesPixel] = pixNum
00669                 _myia.subimage(outfile=myfile, region=rg.box(blc=blc, trc=trc))
00670         _myia.done()
00671         isTPol = bool(Vimage)
00672         isLPol = not isTPol
00673         filenames = [Qimage, Uimage]
00674         sum = Qimage + '*' + Qimage + " + " + Uimage + '*' + Uimage
00675         if isTPol:
00676             sum = sum + " + " + Vimage + '*' + Vimage
00677             filenames.append(Vimage)
00678         # close paren gets added after this method has been called.
00679         expr = 'sqrt(' + sum
00680 
00681     elif len(filenames) == 3:
00682         for i in range(len(stkslist)):
00683             if type(stkslist[i])==list:
00684                 casalog.post("stokes " + str(stkslist[i]),'SEVERE')
00685                 raise Exception, 'Cannot handle %s, a multi-Stokes image when more than one image supplied.' % filenames[i]
00686             else:
00687                 if stkslist[i]=='Q':isQim=True
00688                 if stkslist[i]=='U':isUim=True
00689                 if stkslist[i]=='V':isVim=True
00690         if not (isUim and isQim and isVim):
00691             missing = []
00692             if not isQim: missing.append('Q')
00693             if not isUim: missing.append('U')
00694             if not isVim: missing.append('V')
00695             raise Exception, 'Missing Stokes %s image(s)' % missing
00696         expr='sqrt('+varnames[0]+'*'+varnames[0]\
00697                 +'+'+varnames[1]+'*'+varnames[1]\
00698                 +'+'+varnames[2]+'*'+varnames[2]
00699         isTPol = True
00700     elif len(filenames) == 2:
00701         for i in range(len(stkslist)):
00702             if type(stkslist[i])==list:
00703                 raise Exception, 'Cannot handle %s, a multi-Stokes image when multiple images supplied.' % filenames[i]
00704             else:
00705                 if stkslist[i]=='Q':isQim=True
00706                 if stkslist[i]=='U':isUim=True
00707         if not (isUim and isQim):
00708             missing = []
00709             if not isQim: missing.append('Q')
00710             if not isUim: missing.append('U')
00711             raise Exception, 'Missing Stokes %s image(s)' % missing
00712         expr='sqrt('+varnames[0]+'*'+varnames[0]\
00713                 +'+'+varnames[1]+'*'+varnames[1]
00714         isLPol = True
00715     return [expr, isLPol, isTPol]
00716         
00717 def _immath_createPolMask(polithresh, lpol, outfile):
00718     # make the linear polarization threshhold mask CAS-2120
00719     myexpr = "'" + lpol + "' >= " + str(qa.getvalue(polithresh)[0])
00720     _myia = iatool()
00721     _myia.open(outfile)
00722     _myia.calcmask(name='mask0', mask=myexpr)
00723     casalog.post('Calculated mask based on linear polarization threshold ' + str(polithresh),
00724         'INFO')
00725     _myia.done()
00726