casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
immath_cli.py
Go to the documentation of this file.
00001 #
00002 # This file was generated using xslt from its XML file
00003 #
00004 # Copyright 2008, Associated Universities Inc., Washington DC
00005 #
00006 import sys
00007 import os
00008 #from casac import *
00009 import casac
00010 import string
00011 import time
00012 import inspect
00013 import gc
00014 import numpy
00015 from odict import odict
00016 from taskmanager import tm
00017 from task_immath import immath
00018 class immath_cli_:
00019     __name__ = "immath"
00020     __async__ = {}
00021     rkey = None
00022     i_am_a_casapy_task = None
00023     # The existence of the i_am_a_casapy_task attribute allows help()
00024     # (and other) to treat casapy tasks as a special case.
00025 
00026     def __init__(self) :
00027        self.__bases__ = (immath_cli_,)
00028        self.__doc__ = self.__call__.__doc__
00029 
00030        self.parameters={'imagename':None, 'mode':None, 'outfile':None, 'expr':None, 'varnames':None, 'sigma':None, 'polithresh':None, 'mask':None, 'region':None, 'box':None, 'chans':None, 'stokes':None, 'stretch':None,  'async':None}
00031 
00032 
00033     def result(self, key=None):
00034             #### here we will scan the task-ids in __async__
00035             #### and add any that have completed...
00036             if key is not None and self.__async__.has_key(key) and self.__async__[key] is not None:
00037                ret = tm.retrieve(self.__async__[key])
00038                if ret['state'] == "done" :
00039                   self.__async__[key] = None
00040                elif ret['state'] == 'crashed' :
00041                   self.__async__[key] = None
00042                return ret
00043             return None
00044 
00045 
00046     def __call__(self, imagename=None, mode=None, outfile=None, expr=None, varnames=None, sigma=None, polithresh=None, mask=None, region=None, box=None, chans=None, stokes=None, stretch=None,  async=None):
00047 
00048         """Perform math operations on images
00049 
00050     This task evaluates mathematical expressions involving existing
00051     image files. The results of the calculations are stored in the 
00052     designated output file.  Options are available to specify mathematical 
00053     expression directly or pre-defined expression for calculation of 
00054     spectral index image, and polarization intensity and position angle 
00055     images are available. The image file names imbedded in the expression or
00056     specified in the imagename parameter for the pre-defined calculations may
00057     be CASA images or FITS images.
00058 
00059 
00060     NOTE: Index values start at 0 Use the imhead task to see the range of
00061           index values for each axes.
00062     
00063 
00064     Keyword arguments:
00065     imagename  input image name(s)
00066                Default: none;
00067                Examples: mode='evalexpr'; imagename=['image1.im', 'image2.im' ]
00068                The text 'IM0' is replaced by 'image1.im' in the
00069                expression and 'IM1' is repalced with 'image2.im'
00070                mode='spix'; imagename=['image1.im','image2.im'] will calculate 
00071                an image of log(S1/S2)/log(f1/f2), where S1 and S2 are fluxes and 
00072                f1 and f2 are frequencies
00073                mode='pola'; imagename='multistokes.im' (where that image contains both Q and U
00074                stokes planes) or imagename=['imageQ.im','imageU.im'] will calculate 
00075                an image of polarization angle distribution, where imageQ.im and 
00076                imageU.im are Stokes Q and U images, respectively. Calculate 0.5*arctan(U/Q).
00077                mode='poli'; imagename=['imageQ.im','imageU.im','imageV.im'] will calculate
00078                total polarization intensity image, where imageQ.im, imageU.im, imageV.im
00079                are Stokes Q, U, and V images, respectively. Alternatively, with
00080                imagename = ['imageQ.im','imageU.im'] the linear polarization intensity
00081                image will be calculated. In the case where imagename is a single multi-stokes
00082                image, the total polarization image will be calculated if all of the Q, U, and
00083                V stokes planes are present, and the linear polarization intensity image will
00084                be calculated if the Q and U (but not V) planes are present. 
00085 
00086     mode       mode for mathematical operation
00087                Default: evalexpr
00088                Options: 'evalexpr' : evalulate a mathematical expression defined in 'expr' 
00089                         'spix' : spectalindex image 
00090                         'pola' : polarization position angle image 
00091                         'poli' : polarization intesity image 
00092               >>> mode expandable parameters
00093               sigma       (for mode='poli') standard deviation of noise of Stokes images with unit such as
00094                           Jy/beam to correct for bias 
00095                           Default: '0.0Jy/beam' (= no debiasing)
00096               polithresh  (for mode='pola') Quantity (eg '30uJy/beam') describing the linear (not total;
00097                           the stokes V contribution is not included) polarization threshold. A mask ('mask0')
00098                           is written to the output image and is False for all corresponding linear polarization
00099                           values below this threshold. This parameter overrides the mask input parameter
00100                           (below). Default ('') means use the value given in mask, or no masking if that
00101                           value is empty as well.
00102               expr        (for mode='evalexpr') A LEL expression with images.
00103                               Image file names are specified in the imagenames paramter, and
00104                           the variables IM0, IM1, ... (or optionally via the varnames parameter, see below)
00105                           are used to represent these files
00106                           in the expression. Explicit notations of file names in the 
00107                           expression are also supported, in which cases the file names must
00108                           be enclosed in double quotes (") and imagename is ignored.
00109                               Examples:
00110                           Make an image that is image1.im - image2.im
00111                           expr=' (IM0 - IM1 )'
00112                           or with an explicit notation, 
00113                           expr='("image1.im" - "image2.im")'
00114                           Clip an image below a value (0.5 in this case)
00115                           expr = ' iif( IM0 >=0.5, IM0, 0.0) '
00116                           Note: iif (a, b, c)   a is the boolean expression
00117                                                 b is the value if true
00118                                                 c is the value if false
00119                           Take the rms value of two images
00120                           expr = ' sqrt(IM0 * IM0 + IM1 * IM1) '
00121                           Note: No exponentiaion available?
00122                           Build an image pixel by pixel from the minimum of (image2.im, 2*image1.im)
00123                           expr='min(IM1,2*max(IM0))'
00124                varnames   For mode="evalexpr". Instead of the default variable names IM0, IM1, ..., use
00125                           the names in this array to represent the input images.
00126     outfile    The output image. Overwriting an existing outfile is not permitted.
00127                    Default: immath_results.im;  Example: outfile='results.im'
00128     mask       Mask to use. See help par.mask. Default is none. Also see polithresh.
00129     stretch    Stretch the input mask if necessary and possible. See below.
00130     region     Name of region file, region text description, or region dictionary.
00131     box        A rectangular region on the directional plane expressed in pixels.
00132                Example: box='10,10,50,50'
00133     chans      Channel ranges to use, expressed in pixels. Example: chans='3~20'   
00134     stokes     Stokes parameters. Example: stokes='IQUV';
00135                Options: 'I','Q','U','V','RR','RL','LR','LL','XX','YX','XY','YY', ... 
00136                Not used in for cases of mode='poli' or mode='pola'
00137 
00138     Available functions in the expr and mask paramters:
00139     pi(), e(), sin(), sinh(), asinh(), cos(), cosh(), tan(), tanh(),
00140     atan(), exp(), log(), log10(), pow(), sqrt(), complex(), conj()
00141     real(), imag(), abs(), arg(), phase(), aplitude(), min(), max()
00142     round(), isgn(), floor(), ceil(), rebin(), spectralindex(), pa(), 
00143     iif(), indexin(), replace(), ...
00144 
00145     If the mask has fewer dimensions than the image and if the shape
00146     of the dimensions the mask and image have in common are the same,
00147     the mask will automatically have the missing dimensions added so
00148     it conforms to the image.
00149 
00150     For a full description of the allowed syntax see the 
00151     Lattice Expression Language (LEL) documentation on the at:
00152     http://aips2.nrao.edu/docs/notes/223/223.html
00153 
00154     NOTE: where indexing and axis numbering are used in the above
00155     functions they are 1-based, ie. numbering starts at 1.
00156 
00157     If stretch is true and if the number of mask dimensions is less than
00158     or equal to the number of image dimensions and some axes in the
00159     mask are degenerate while the corresponding axes in the image are not,
00160     the mask will be stetched in the degenerate axis dimensions. For example,
00161     if the input image has shape [100, 200, 10] and the input
00162     mask has shape [100, 200, 1] and stretch is true, the mask will be
00163     stretched along the third dimension to shape [100, 200, 10]. However if
00164     the mask is shape [100, 200, 2], stretching is not possible and an
00165     error will result.
00166 
00167     CAUTION: Note that when multiple image are used in the expression, there is
00168     no garauntee about which of those images will be used to create the header
00169     of the output image. Therefore, one may have to modify the output header as
00170     needed if the input headers differ.
00171 
00172     Examples:
00173     # Double all values in an image.
00174     immath( imagesname='myimage.im', expr='IM0*2', outfile='double.im' )
00175     # or with an explicit notation, 
00176     immath( expr='"myimage.im"*2', outfile='double.im' )
00177 
00178     # Taking the sin of an image and adding it to another
00179     # Note that the images need to be the same size
00180     immath(images=['image1.im', 'image2.im'], expr='sin(IM1)+IM0;',outfile='newImage.im')
00181 
00182     # Adding only the plane associated with the 'V' stokes value and
00183     # the 1st channel together in two images
00184     immath(imagename=[image1', 'image2'], expr='IM0+IM1',chans='1',stokes='V')
00185 
00186 
00187     # Selecting a single plane (5th channel), of the 3-D cube and  
00188     # adding it to the original image.  In this example the 2-D plane
00189     # gets expanded out and the values are applied to each plane in the 
00190     # 3-D cube. 
00191     default('immath')
00192     imagename='ngc7538.image'
00193     outfile='chanFive.im'
00194     expr='IM0'
00195     chans='5'
00196     go
00197     default('immath')
00198     imagename=['ngc7538.image', chanFive.im']
00199     outfile='ngc7538_chanFive.im'
00200     expr='IM0+IM1'
00201     go
00202 
00203     # Selecting and saving the inner 3/4 of an image for channels 40,42,44
00204     # as well as channels less than 10
00205     default('immath')
00206     imagename='my_image.im'
00207     expr='IM0'
00208     box='25,25,123,123'
00209     chans='<10;40,42,44'
00210     outfile='my_image_inner.im' )
00211     go
00212 
00213     # Dividing an image by another, making sure we aren't dividing by zero
00214     default('immath')
00215     imagename=['orion.image', 'my.image']
00216     expr='IM0/iif(IM1==0,1.0,IM1)'
00217     outfile='my_orion.image'
00218     go
00219 
00220     # Applying a mask to all of the images in the expression
00221     default('immath')
00222     imagename=['ngc7538.image','ngc7538_clean.image']
00223     expr='(IM0*10)+IM1'
00224     mask='"ngc7538.mask"'
00225     outfile='really_noisy_ngc7538.image'
00226     go
00227 
00228 
00229     # Applying a pixel mask contained in the image information
00230     default('immath')
00231     imagename='ngc5921.image'
00232     expr='IM0*10'
00233     mask='mask("ngc5921.mask")'
00234     outfile='ngc5921.masked.image'
00235     go
00236 
00237     # Creating a total polarization intensity image from an multi-stokes image
00238     # containing IQUV.
00239     default('immath')
00240     outfile='pol_intensity'
00241     stokes=''
00242     # in imagename, you can also specify a list containing single stokes images
00243     # of Q and U (for linear polarization intensity) and V (for total
00244     # polarization intensity)
00245     imagename='3C138_pcal'
00246     mode='poli'
00247     go
00248 
00249     # Creating a polarization position angle image 
00250     default('immath')
00251     outfile='pol_angle.im'
00252     mode='pola'
00253     # you can also do imagename=['Q.im','U.im'] for single stokes images, order of
00254     # the two Stokes images does not matter
00255     imagename='3C138_pcal' # multi-stokes image containing at least Q and U stokes 
00256     go 
00257 
00258     # same as before but write a mask with values of False for pixels for which the
00259     # corresponding linear polarization ( sqrt(Q*Q+U*U)) is less than 30 microJy/beam
00260     polithresh='30uJy/beam'
00261     go
00262 
00263     # Creating a spectral index image from the images at two different observing frequencies
00264     default('immath')
00265     outfile='mySource_sp.im'
00266     mode='spix'
00267     imagename=['mySource_5GHz.im','mySource_8GHz.im']
00268     go
00269     
00270     TEMPORARY IMAGES
00271 
00272     At this time, it is usually necessary for this task to create intermediate, temporary disk images.
00273     The names of these images start with '_immath' and are created in the directory in which the task
00274     is run. The task makes reasonable attempts to remove these images before it exits, but there are
00275     conceivably instances where the temporary images may not be automatically deleted. It is generally
00276     safe to delete them by hand, assuming no immath instance is currently in progress.
00277 
00278     The hope and plan is that the necessity of these images will decrease in the future (ie the computations
00279     will require only RAM and not temporary persistent storage of intermediate results).
00280 
00281  
00282 
00283         """
00284         if not hasattr(self, "__globals__") or self.__globals__ == None :
00285            self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals
00286         #casac = self.__globals__['casac']
00287         casalog = self.__globals__['casalog']
00288         #casalog = casac.casac.logsink()
00289         self.__globals__['__last_task'] = 'immath'
00290         self.__globals__['taskname'] = 'immath'
00291         ###
00292         self.__globals__['update_params'](func=self.__globals__['taskname'],printtext=False,ipython_globals=self.__globals__)
00293         ###
00294         ###
00295         #Handle globals or user over-ride of arguments
00296         #
00297         function_signature_defaults=dict(zip(self.__call__.func_code.co_varnames,self.__call__.func_defaults))
00298         useLocalDefaults = False
00299 
00300         for item in function_signature_defaults.iteritems():
00301                 key,val = item
00302                 keyVal = eval(key)
00303                 if (keyVal == None):
00304                         #user hasn't set it - use global/default
00305                         pass
00306                 else:
00307                         #user has set it - use over-ride
00308                         if (key != 'self') :
00309                            useLocalDefaults = True
00310 
00311         myparams = {}
00312         if useLocalDefaults :
00313            for item in function_signature_defaults.iteritems():
00314                key,val = item
00315                keyVal = eval(key)
00316                exec('myparams[key] = keyVal')
00317                self.parameters[key] = keyVal
00318                if (keyVal == None):
00319                    exec('myparams[key] = '+ key + ' = self.itsdefault(key)')
00320                    keyVal = eval(key)
00321                    if(type(keyVal) == dict) :
00322                       if len(keyVal) > 0 :
00323                          exec('myparams[key] = ' + key + ' = keyVal[len(keyVal)-1][\'value\']')
00324                       else :
00325                          exec('myparams[key] = ' + key + ' = {}')
00326 
00327         else :
00328             async = self.parameters['async']
00329             myparams['imagename'] = imagename = self.parameters['imagename']
00330             myparams['mode'] = mode = self.parameters['mode']
00331             myparams['outfile'] = outfile = self.parameters['outfile']
00332             myparams['expr'] = expr = self.parameters['expr']
00333             myparams['varnames'] = varnames = self.parameters['varnames']
00334             myparams['sigma'] = sigma = self.parameters['sigma']
00335             myparams['polithresh'] = polithresh = self.parameters['polithresh']
00336             myparams['mask'] = mask = self.parameters['mask']
00337             myparams['region'] = region = self.parameters['region']
00338             myparams['box'] = box = self.parameters['box']
00339             myparams['chans'] = chans = self.parameters['chans']
00340             myparams['stokes'] = stokes = self.parameters['stokes']
00341             myparams['stretch'] = stretch = self.parameters['stretch']
00342 
00343 
00344         result = None
00345 
00346 #
00347 #    The following is work around to avoid a bug with current python translation
00348 #
00349         mytmp = {}
00350 
00351         mytmp['imagename'] = imagename
00352         mytmp['mode'] = mode
00353         mytmp['outfile'] = outfile
00354         mytmp['expr'] = expr
00355         mytmp['varnames'] = varnames
00356         mytmp['sigma'] = sigma
00357         mytmp['polithresh'] = polithresh
00358         mytmp['mask'] = mask
00359         mytmp['region'] = region
00360         mytmp['box'] = box
00361         mytmp['chans'] = chans
00362         mytmp['stokes'] = stokes
00363         mytmp['stretch'] = stretch
00364         pathname='file:///'+os.environ.get('CASAPATH').split()[0]+'/share/xml/'
00365         trec = casac.casac.utils().torecord(pathname+'immath.xml')
00366 
00367         casalog.origin('immath')
00368         try :
00369           #if not trec.has_key('immath') or not casac.casac.utils().verify(mytmp, trec['immath']) :
00370             #return False
00371 
00372           casac.casac.utils().verify(mytmp, trec['immath'], True)
00373           scriptstr=['']
00374           saveinputs = self.__globals__['saveinputs']
00375           saveinputs('immath', 'immath.last', myparams, self.__globals__,scriptstr=scriptstr)
00376           if async :
00377             count = 0
00378             keybase =  time.strftime("%y%m%d.%H%M%S")
00379             key = keybase + "_" + str(count)
00380             while self.__async__.has_key(key) :
00381                count += 1
00382                key = keybase + "_" + str(count)
00383             result = tm.execute('immath', imagename, mode, outfile, expr, varnames, sigma, polithresh, mask, region, box, chans, stokes, stretch)
00384             print "Use: "
00385             print "      tm.retrieve(return_value) # to retrieve the status"
00386             print 
00387             self.rkey = key
00388             self.__async__[key] = result
00389           else :
00390               tname = 'immath'
00391               spaces = ' '*(18-len(tname))
00392               casalog.post('\n##########################################'+
00393                            '\n##### Begin Task: ' + tname + spaces + ' #####')
00394               casalog.post(scriptstr[1][1:]+'\n', 'INFO')
00395               result = immath(imagename, mode, outfile, expr, varnames, sigma, polithresh, mask, region, box, chans, stokes, stretch)
00396               casalog.post('##### End Task: ' + tname + '  ' + spaces + ' #####'+
00397                            '\n##########################################')
00398 
00399         except Exception, instance:
00400           if(self.__globals__.has_key('__rethrow_casa_exceptions') and self.__globals__['__rethrow_casa_exceptions']) :
00401              raise
00402           else :
00403              #print '**** Error **** ',instance
00404              tname = 'immath'
00405              casalog.post('An error occurred running task '+tname+'.', 'ERROR')
00406              pass
00407 
00408         gc.collect()
00409         return result
00410 #
00411 #
00412 #
00413     def paramgui(self, useGlobals=True, ipython_globals=None):
00414         """
00415         Opens a parameter GUI for this task.  If useGlobals is true, then any relevant global parameter settings are used.
00416         """
00417         import paramgui
00418         if not hasattr(self, "__globals__") or self.__globals__ == None :
00419            self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals
00420 
00421         if useGlobals:
00422             if ipython_globals == None:
00423                 myf=self.__globals__
00424             else:
00425                 myf=ipython_globals
00426 
00427             paramgui.setGlobals(myf)
00428         else:
00429             paramgui.setGlobals({})
00430 
00431         paramgui.runTask('immath', myf['_ip'])
00432         paramgui.setGlobals({})
00433 
00434 #
00435 #
00436 #
00437     def defaults(self, param=None, ipython_globals=None, paramvalue=None, subparam=None):
00438         if not hasattr(self, "__globals__") or self.__globals__ == None :
00439            self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals
00440         if ipython_globals == None:
00441             myf=self.__globals__
00442         else:
00443             myf=ipython_globals
00444 
00445         a = odict()
00446         a['imagename']  = ''
00447         a['mode']  = 'evalexpr'
00448         a['outfile']  = 'immath_results.im'
00449         a['mask']  = ''
00450         a['region']  = ''
00451         a['box']  = ''
00452         a['chans']  = ''
00453         a['stokes']  = ''
00454 
00455         a['async']=False
00456         a['mode'] = {
00457                     0:odict([{'value':'evalexpr'}, {'expr':""}, {'varnames':""}]), 
00458                     1:odict([{'value':'poli'}, {'sigma':"0.0mJy/beam"}]), 
00459                     2:odict([{'value':'pola'}, {'polithresh':""}]), 
00460                     3:{'value':'spix'}}
00461         a['mask'] = {
00462                     0:odict([{'notvalue':''}, {'stretch':False}])}
00463 
00464 ### This function sets the default values but also will return the list of
00465 ### parameters or the default value of a given parameter
00466         if(param == None):
00467                 myf['__set_default_parameters'](a)
00468         elif(param == 'paramkeys'):
00469                 return a.keys()
00470         else:
00471             if(paramvalue==None and subparam==None):
00472                if(a.has_key(param)):
00473                   return a[param]
00474                else:
00475                   return self.itsdefault(param)
00476             else:
00477                retval=a[param]
00478                if(type(a[param])==dict):
00479                   for k in range(len(a[param])):
00480                      valornotval='value'
00481                      if(a[param][k].has_key('notvalue')):
00482                         valornotval='notvalue'
00483                      if((a[param][k][valornotval])==paramvalue):
00484                         retval=a[param][k].copy()
00485                         retval.pop(valornotval)
00486                         if(subparam != None):
00487                            if(retval.has_key(subparam)):
00488                               retval=retval[subparam]
00489                            else:
00490                               retval=self.itsdefault(subparam)
00491                      else:
00492                         retval=self.itsdefault(subparam)
00493                return retval
00494 
00495 
00496 #
00497 #
00498     def check_params(self, param=None, value=None, ipython_globals=None):
00499       if ipython_globals == None:
00500           myf=self.__globals__
00501       else:
00502           myf=ipython_globals
00503 #      print 'param:', param, 'value:', value
00504       try :
00505          if str(type(value)) != "<type 'instance'>" :
00506             value0 = value
00507             value = myf['cu'].expandparam(param, value)
00508             matchtype = False
00509             if(type(value) == numpy.ndarray):
00510                if(type(value) == type(value0)):
00511                   myf[param] = value.tolist()
00512                else:
00513                   #print 'value:', value, 'value0:', value0
00514                   #print 'type(value):', type(value), 'type(value0):', type(value0)
00515                   myf[param] = value0
00516                   if type(value0) != list :
00517                      matchtype = True
00518             else :
00519                myf[param] = value
00520             value = myf['cu'].verifyparam({param:value})
00521             if matchtype:
00522                value = False
00523       except Exception, instance:
00524          #ignore the exception and just return it unchecked
00525          myf[param] = value
00526       return value
00527 #
00528 #
00529     def description(self, key='immath', subkey=None):
00530         desc={'immath': 'Perform math operations on images',
00531                'imagename': 'a list of input images ',
00532                'mode': 'mode for math operation (evalexpr, spix, pola, poli)',
00533                'outfile': 'File where the output is saved',
00534                'expr': 'Mathematical expression using images',
00535                'varnames': 'a list of variable names to use with the image files',
00536                'sigma': 'standard deviation of noise for debiasing',
00537                'polithresh': 'Threshold in linear polarization intensity image below which to mask pixels.',
00538                'mask': 'Mask to use. See help par.mask. Default is none.',
00539                'region': 'File path which contains an Image Region',
00540                'box': 'Select one or more box regions in the input images',
00541                'chans': 'Select the channel(spectral) range',
00542                'stokes': 'Stokes params to image (I,IV,IQU,IQUV)',
00543                'stretch': 'Stretch the mask if necessary and possible? See help stretch.par ',
00544 
00545                'async': 'If true the taskname must be started using immath(...)'
00546               }
00547 
00548 #
00549 # Set subfields defaults if needed
00550 #
00551 
00552         if(desc.has_key(key)) :
00553            return desc[key]
00554 
00555     def itsdefault(self, paramname) :
00556         a = {}
00557         a['imagename']  = ''
00558         a['mode']  = 'evalexpr'
00559         a['outfile']  = 'immath_results.im'
00560         a['expr']  = 'IM0'
00561         a['varnames']  = ''
00562         a['sigma']  = '0.0mJy/beam'
00563         a['polithresh']  = ''
00564         a['mask']  = ''
00565         a['region']  = ''
00566         a['box']  = ''
00567         a['chans']  = ''
00568         a['stokes']  = ''
00569         a['stretch']  = False
00570 
00571         #a = sys._getframe(len(inspect.stack())-1).f_globals
00572 
00573         if self.parameters['mode']  == 'evalexpr':
00574             a['expr'] = ""
00575             a['varnames'] = ""
00576 
00577         if self.parameters['mode']  == 'poli':
00578             a['sigma'] = "0.0mJy/beam"
00579 
00580         if self.parameters['mode']  == 'pola':
00581             a['polithresh'] = ""
00582 
00583         if self.parameters['mask']  != '':
00584             a['stretch'] = False
00585 
00586         if a.has_key(paramname) :
00587               return a[paramname]
00588 immath_cli = immath_cli_()