casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_imval.py
Go to the documentation of this file.
00001 import os
00002 from taskinit import *
00003 from odict import odict
00004 import numpy
00005 
00006 # The function that handles the imval task.
00007 def imval(imagename=None,region=None,box=None,chans=None,stokes=None):
00008     # Blank return value.
00009     retValue = { 'blc':[], 'trc':[], 'unit': '', 'data': [], 'mask': []}
00010     casalog.origin('imval')
00011 
00012     try:
00013         axes=getimaxes(imagename)
00014     except:
00015         raise Exception, "Unable to determine the axes of image: "+imagename
00016     
00017 
00018     # Get rid of any white space in the parameters
00019     region = region.replace(' ', '' )
00020     box    = box.replace( ' ', '' )
00021     chans  = chans.replace( ' ', '' )
00022     stokes = stokes.replace( ' ','' )
00023 
00024     # Default for the chans and stokes parameter is all when the
00025     # aren't given.  The easy way is to set them to -1, and let
00026     # the imageregion.py code handle it.
00027     if ( len(chans) < 1 ):
00028         chans='-1'
00029             
00030     if ( len(stokes) < 1 ):
00031         stokes='-1'
00032             
00033         
00034     # If the user hasn't specified any region information then
00035     # find the very last data point -- what ia.getpixelvalue        
00036     # defaults too.
00037     myia = iatool()
00038     if ( len(box)<1 and len(chans)<1 and len(stokes)<1 and len(region)<1 ):
00039         try:
00040             #print "GETTING SINGLE PIXEL VALUE"
00041             # Open the image for processing!
00042             myia.open(imagename)
00043 
00044             # Get the default  pixelvalue() at the referencepixel pos.
00045             csys=myia.coordsys()
00046             ref_values = csys.referencepixel()['numeric']
00047             point=[]
00048             for val in ref_values.tolist():
00049                 point.append( int(round(val) ) )
00050             casalog.post( 'Getting data value at point '+str(point), 'NORMAL' )
00051             results = myia.pixelvalue(point)
00052 
00053             retValue = _imval_process_pixel( results, point )
00054             retValue['axes']=axes
00055             casalog.post( 'imval task complete for point'+str(point), 'NORMAL1' )
00056             myia.done()
00057             return retValue
00058         except Exception, instance:
00059             myia.done()
00060             raise Exception, instance
00061 
00062     # If the box parameter only has two value then we copy
00063     # them.  
00064     if ( box.count(',') == 1 ):
00065         box = box + ','+ box
00066 
00067     # If we are finding the value at a single point this
00068     # is a special case and we use ia.getpixelvalue()
00069 
00070     singlePt = _imval_get_single( box, chans, stokes, axes )
00071     #print "Single point is: ", singlePt, "   ", len(singlePt)
00072     if ( len( singlePt ) == 4 and singlePt.count( -1 ) < 1 ):
00073         try:
00074             casalog.post( 'Getting data value at point '+str(singlePt), 'NORMAL' )
00075             myia.open( imagename )
00076             results = myia.pixelvalue( singlePt )
00077             retValue = _imval_process_pixel( results, singlePt )
00078             myia.done()
00079             retValue['axes']=axes
00080             casalog.post( 'imval task complete for point '+str(singlePt), 'NORMAL1' )
00081             return retValue
00082         except Exception, instance:
00083             myia.done()
00084             raise Exception, instance
00085         
00086         
00087     # If we've made it here then we are finding the stats
00088     # of a region, which could be a set of single points.
00089     axes=getimaxes(imagename)
00090     statAxes=[]
00091     if ( len(box)>0 ):
00092         statAxes.append(axes[0][0])
00093         statAxes.append(axes[1][0])
00094     if ( len(chans)>0 ):
00095         statAxes.append(axes[2][0])
00096 
00097     # If we get to this point and find that nothing was
00098     # given for the box parameter we use the reference
00099     # pixel values.
00100     myia.open(imagename)
00101     mycsys = myia.coordsys()  
00102 
00103     if ( len(box) == 0 and len(region) == 0):
00104         try:
00105             # Open the image for processing!            
00106             ref_values = mycsys.referencepixel()['numeric']
00107             values = ref_values.tolist()
00108             box = str(int(round(values[axes[0][0]])))+','\
00109                   + str(int(round(values[axes[1][0]])))+',' \
00110                   + str(int(round(values[axes[0][0]])))+','\
00111                    +str(int(round(values[axes[1][0]])))
00112         except:
00113             myia.done()
00114             raise Exception, "Unable to find the size of the input image."
00115           
00116     # Because the help file says -1 is valid, apparently that's supported functionality, good grief
00117     
00118     if box.startswith("-1"):
00119         box = ""
00120     if chans.startswith("-1"):
00121         chans = ""
00122     if stokes.startswith("-1"):
00123         stokes = ""
00124     reg = rg.frombcs(
00125         mycsys.torecord(), myia.shape(), box, chans,
00126         stokes, "a", region
00127     )
00128     myia.done()
00129 
00130     # Now that we know which axes we are using, and have the region
00131     # selected, lets get that stats!  NOTE: if you have axes size
00132     # greater then 0 then the maxpos and minpos will not be displayed
00133     if ( reg.has_key( 'regions' ) ):
00134         casalog.post( "Complex region found, only processing the first"\
00135                       " SIMPLE region found", "WARN" )
00136         reg=reg['regions']['*1']
00137 
00138     # Make sure they are sorted first.
00139     reg['blc'].keys().sort()
00140     reg['trc'].keys().sort()        
00141 
00142     zeroblc=[]
00143     blc_keys=reg['blc'].keys()
00144     blc_keys.sort()        
00145 
00146     for key in blc_keys:
00147         value=reg['blc'][key]['value']
00148         if ( reg['oneRel'] ):
00149             #We need to conver to 0 relative!
00150             value=value-1
00151         if ( len( zeroblc ) > 0 ):
00152             zeroblc.append(str(value)+str(reg['blc'][key]['unit'])+',' )
00153         else:
00154             zeroblc.append(str(value)+str(reg['blc'][key]['unit']) )
00155 
00156     zerotrc=[]
00157     trc_keys=reg['trc'].keys()
00158     trc_keys.sort()
00159     for key in trc_keys:
00160         value=reg['trc'][key]['value']
00161         if ( reg['oneRel'] ):
00162             #We need to conver to 0 relative!
00163             value=value-1
00164         if ( len( zerotrc ) > 0 ):
00165             zerotrc.append(str(value)+str(reg['trc'][key]['unit'])+',' )
00166         else:
00167             zerotrc.append(str(value)+str(reg['trc'][key]['unit']) )
00168 
00169     casalog.post( 'Getting data values in region in blc='+str(zeroblc)+' trc='+str(zerotrc), 'NORMAL' )
00170     casalog.post( "Getting data values for region: "+str(reg), 'NORMAL2' )
00171  
00172     retValue = _imval_getregion( imagename, reg )
00173     retValue['axes']=axes
00174 
00175     casalog.post( 'imval task complete for region bound by blc='+str(retValue['blc'])+' and trc='+str(retValue['trc']), 'NORMAL1' )
00176     return retValue
00177                 
00178 
00179 #
00180 # Print out the returned results.
00181 # TODO -- finish this function
00182 def _imval_print( values, name ) :
00183     print 'Results of imval task on ', name
00184     print ''
00185     print 'Region ---'
00186     print '\t --\x1B[94m bottom-left corner (pixel) [blc]:    \x1B[0m', list(values['blc'])
00187     print '\t --\x1B[94m top-right corner (pixel) [trc]:      \x1B[0m', list(values['trc'])
00188 
00189 #
00190 # Take the results from the ia.pixelvalue() function and
00191 # the position given to the function and turn the results
00192 # into the desired values; blc, trc, data, and mask
00193 #
00194 def _imval_process_pixel( results, point ):
00195     retvalue={}
00196     # First check that the results are a dictionary type and that
00197     # it contains the key/value pairs we expect.
00198     if ( not isinstance( results, dict ) ):
00199         casalog.post( "ia.pixelvalue() has returned erroneous data, Python dictionary type expectd.", "WARN" )
00200         casalog.post( "Value returned is: "+str(results), "SEVERE" )
00201         return retvalue
00202     
00203     if ( not results.has_key('mask') ):
00204         casalog.post( "ia.pixelvalue() has returned unexpected results, no mask value present.", "SEVERE" )
00205         return retvalue
00206 
00207     if ( not results.has_key('value') or not results['value'].has_key('unit') or not results['value'].has_key('value') ):
00208         casalog.post( "ia.pixelvalue() has returned unexpected results, data value absent or ill-formed.", "SEVERE" )
00209         return retvalue
00210     
00211     retValue={
00212         'blc':point, 'trc': point, 'unit':results['value']['unit'],
00213         'data': numpy.array([results['value']['value']]),
00214         'mask': numpy.array([results['mask']])
00215     }
00216     return retValue
00217 
00218 #
00219 # Give the box, channel, and stokes values find out
00220 # if we are getting the data from a single point in the
00221 # image, if so then return that point.
00222 def _imval_get_single( box, chans, stokes, axes ):
00223     # If we have more then one point then return an empty list.
00224     try: 
00225         junk=int(chans)
00226         junk=int(stokes)
00227     except:
00228         return []
00229     if ( box.count(';')>0 ):
00230         return []            
00231 
00232     # If the channel wasn't specified use the first one only.
00233     if ( len( chans ) < 1 ):
00234         #chans=0
00235         return []
00236 
00237     # If the stokes values weren't specified use the first one only.
00238     if ( len( stokes ) < 1 ):
00239         #stokes=0
00240         return[]
00241 
00242     # The two x values and two y values need to be the same if its
00243     # a single point.  There may be only two value if its a single
00244     # point too.
00245     x=-1
00246     y=-1
00247     box=box.split(',')
00248     if ( len(box) == 2 ):
00249        x=int(box[0])
00250        y=int(box[1])
00251     elif ( len(box) == 4 and box[0]==box[2] and box[1]==box[3]):
00252         x=int(box[0])
00253         y=int(box[1])
00254     else:
00255         # We have more then one point, return empty list.
00256         return []
00257 
00258     retvalue=[-1,-1,-1,-1]
00259 
00260     retvalue[axes[0][0]]=x
00261     retvalue[axes[1][0]]=y
00262     retvalue[axes[2][0]]=int(chans)
00263     retvalue[axes[3][0]]=int(stokes)
00264     return retvalue
00265 
00266 #
00267 # Use the ia.getregion() function to construct the requested data.
00268 def _imval_getregion( imagename="", region={} ):
00269     retvalue= {}
00270     myia = iatool()
00271     try:
00272         # Open the image for processing!
00273         myia.open(imagename)
00274 
00275         # Find the array of data and mask values.
00276         data_results=myia.getregion( region=region, dropdeg=True, getmask=False )
00277         mask_results=myia.getregion( region=region, dropdeg=True, getmask=True )
00278                 
00279         # Find the bounding box of the region so we can report it back to
00280         # the user.
00281         bbox = myia.boundingbox( region=region )
00282         
00283         if ( not bbox.has_key( 'blc' ) ):
00284             casalog.post( "ia.boundingbox() has returned unexpected results, blc value absent.", "SEVERE" )
00285             myia.done()
00286             return retvalue
00287         if ( not bbox.has_key( 'blc' ) ):
00288             casalog.post( "ia.boundingbox() has returned unexpected results, blc value absent.", "SEVERE" )
00289             myia.done()
00290             return retvalue
00291         
00292         # get the pixel coords
00293         mycsys = myia.coordsys()
00294         myarrays = _imval_iterate(bbox['blc'], bbox['trc'])
00295         mycoords = mycsys.toworldmany(myarrays)
00296         outcoords = _imval_redo(data_results.shape, mycoords['numeric'])
00297         
00298         # Find what units the data values are stored in.
00299         avalue = myia.pixelvalue( bbox['blc'].tolist() )
00300         #print "A VALUE IS: ", avalue
00301         if ( not avalue.has_key('value') or not avalue['value'].has_key('unit') ):
00302             casalog.post( "ia.pixelvalue() has returned unexpected results, data value absent or ill-formed.", "SEVERE" )
00303             myia.done()
00304             return retvalue
00305 
00306         retvalue={
00307             'blc':bbox['blc'].tolist(),'trc':bbox['trc'].tolist(),
00308             'unit':avalue['value']['unit'], 'data':data_results,
00309             'mask': mask_results, 'coords': outcoords
00310         }
00311     except Exception, instance:
00312         myia.done()
00313         raise instance
00314     myia.done()
00315     return retvalue
00316 
00317 def _imval_iterate(begins, ends, arrays=None, place=None, depth=0, count=None):
00318     if (depth == 0):
00319         count = [0]
00320         mylist = []
00321         diff = numpy.array(ends) - numpy.array(begins) + 1
00322         prod = diff.prod()
00323         for i in range(len(begins)):
00324             mylist.append(numpy.zeros([prod]))
00325         arrays = numpy.array(mylist)
00326     for i in range(begins[depth], ends[depth] + 1):
00327         if (depth == 0):
00328             tmpplace = []
00329             for j in range(len(begins)):
00330                 tmpplace.append(0)
00331             place = numpy.array(tmpplace)
00332         place[depth] = i
00333         if (depth == len(begins) - 1):
00334             for k in range(depth + 1):
00335                 arrays[k][count[0]] = place[k]
00336             count[0] = count[0] + 1
00337         else:
00338             mydepth = depth + 1
00339             _imval_iterate(begins, ends, arrays, place, mydepth, count)
00340     return arrays
00341 
00342 def _imval_redo(shape, arrays):
00343     list_of_arrays = []
00344     for x in range(arrays[0].size):
00345         mylist = []
00346         for arr in arrays:
00347             mylist.append(arr[x])
00348         list_of_arrays.append(numpy.array(mylist))
00349     array_of_arrays = numpy.array(list_of_arrays)
00350     # because shape is an immutable tuple
00351     newshape = list(shape)
00352     newshape.append(array_of_arrays.shape[1])
00353     return array_of_arrays.reshape(newshape)
00354