casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_imview.py
Go to the documentation of this file.
00001 import sys
00002 import os
00003 import inspect
00004 import string
00005 import time
00006 from taskinit import *
00007 import viewertool
00008 
00009 
00010 class __imview_class(object):
00011         "imview() task with local state for created viewer tool"
00012 
00013         def __init__( self ):
00014                 self.local_vi = None
00015                 self.local_ving = None
00016                 self.__dirstack = [ ]
00017 
00018         def __call__( self, raster=None, contour=None, zoom=None, axes=None, out=None ):
00019                 """ Old parameters:
00020                        infile=None,displaytype=None,channel=None,zoom=None,outfile=None,
00021                        outscale=None,outdpi=None,outformat=None,outlandscape=None,gui=None
00022                 The imview task will display images in raster, contour, vector or
00023                 marker form.  Images can be blinked, and movies are available
00024                 for spectral-line image cubes.  For measurement sets, many
00025                 display and editing options are available.
00026 
00027                 examples of usage:
00028 
00029                 imview
00030                 imview "myimage.im"
00031                 imview "myrestorefile.rstr"
00032                 
00033                 imview "myimage.im", "contour"
00034 
00035                 imview "'myimage1.im' - 2 * 'myimage2.im'", "lel"
00036         
00037                 Executing imview( ) will bring up a display panel
00038                 window, which can be resized.  If no data file was specified,
00039                 a Load Data window will also appear.  Click on the desired data
00040                 file and choose the display type; the rendered data should appear
00041                 on the display panel.
00042 
00043                 A Data Display Options window will also appear.  It has drop-down
00044                 subsections for related options, most of which are self-explanatory.
00045           
00046                 The state of the imview task -- loaded data and related display
00047                 options -- can be saved in a 'restore' file for later use.
00048                 You can provide the restore filename on the command line or
00049                 select it from the Load Data window.
00050 
00051                 See the cookbook for more details on using the imview task.
00052         
00053                 Keyword arguments:
00054                 infile -- Name of file to visualize
00055                         default: ''
00056                         example: infile='ngc5921.image'
00057                         If no infile is specified the Load Data window
00058                         will appear for selecting data.
00059                 displaytype -- (optional): method of rendering data
00060                         visually (raster, contour, vector or marker).  
00061                         You can also set this parameter to 'lel' and
00062                         provide an lel expression for infile (advanced).
00063                         default: 'raster'
00064                         example: displaytype='contour'
00065 
00066                 Note: the filetype parameter is optional; typing of
00067                 data files is now inferred.
00068                         example:  imview infile='my.im'
00069                         implies:  imview infile='my.im', filetype='raster'
00070                 the filetype is still used to load contours, etc.
00071 
00072 
00073                 """
00074                 a=inspect.stack()
00075                 stacklevel=0
00076                 for k in range(len(a)):
00077                         if a[k][1] == "<string>" or (string.find(a[k][1], 'ipython console') > 0 or string.find(a[k][1],"casapy.py") > 0):
00078                                 stacklevel=k
00079 
00080                 myf=sys._getframe(stacklevel).f_globals
00081 
00082                 if (type(out) == str and len(out) != 0) or \
00083                        (type(out) == dict and len(out) != 0) :
00084                         gui = False
00085                         (out_file, out_format, out_scale, out_dpi, out_orientation) = self.__extract_outputinfo( out )
00086                 else:
00087                         gui = True
00088 
00089                 if gui and self.local_vi is None or \
00090                    not gui and self.local_ving is None:
00091                         try:
00092                                 ## vi/ving might not be defined in taskinit if
00093                                 ## loading directly from python via casa.py...
00094                                 vwr = vi if gui else ving
00095 
00096                                 if type(vwr) == type(None) or type(vwr.cwd( )) != str:
00097                                         vwr = viewertool.viewertool( gui, True, (type(myf) == dict and myf.has_key('casa') and type(myf['casa']) == type(os)) )
00098                         except:
00099                                 vwr = None
00100 
00101                         if gui:
00102                                 self.local_vi = vwr
00103                         else:
00104                                 self.local_ving = vwr
00105                 else:
00106                         vwr = self.local_vi if gui else self.local_ving
00107 
00108                 if type(vwr) == type(None):
00109                         raise Exception, "failed to find a viewertool..."
00110 
00111                 self.__pushd( vwr, os.path.abspath(os.curdir) )
00112                 panel = vwr.panel("viewer")
00113                 vwr.freeze( panel )
00114                 self.__load_files( "raster", vwr, panel, raster )
00115                 self.__load_files( "contour", vwr, panel, contour )
00116                 self.__set_axes( vwr, panel, axes )
00117                 self.__zoom( vwr, panel, zoom )
00118                 vwr.unfreeze( panel )
00119 
00120                 if not gui:
00121                         vwr.output(out,scale=out_scale,dpi=out_dpi,format=out_format,orientation=out_orientation,panel=panel)
00122                         vwr.close(panel)
00123 
00124                 self.__popd( vwr )
00125 
00126                 return None
00127 
00128         def __load_raster( self, vwr, panel, raster ):
00129                 ## here we can assume we have a dictionary
00130                 ## that specifies what needs to be done...
00131                 data = None
00132                 if not raster.has_key('file'):
00133                         return 0
00134 
00135                 if  type(raster['file']) != str or not os.path.exists(raster['file']) or \
00136                            vwr.fileinfo(raster['file'])['type'] != 'image':
00137                                 raise Exception, raster['file'] + " does not exist or is not an image"
00138 
00139                 scaling = 0.0
00140                 if raster.has_key('scaling'):
00141                         scaling = self.__checknumeric(raster['scaling'], float, "raster scaling")
00142 
00143                 data = vwr.load( raster['file'], 'raster', panel=panel, scaling=scaling )
00144                 
00145                 if raster.has_key('range'):
00146                         vwr.datarange( self.__checknumeric(raster['range'], float, "data range", array_size=2), data=data )
00147 
00148                 if raster.has_key('colormap'):
00149                         if type(raster['colormap']) == str:
00150                                 vwr.colormap( raster['colormap'], data )
00151                         else:
00152                                 raise Exception, "raster colormap must be a string"
00153 
00154                 if raster.has_key('colorwedge'):
00155                         if type(raster['colorwedge']) == bool:
00156                                 vwr.colorwedge( raster['colorwedge'], data )
00157                         else:
00158                                 raise Exception, "colorwedge must be a boolean"
00159 
00160                 return data
00161 
00162         def __load_contour( self, vwr, panel, contour ):
00163                 ## here we can assume we have a dictionary
00164                 ## that specifies what needs to be done...
00165                 data = None
00166                 if not contour.has_key('file'):
00167                         return 0
00168 
00169                 if type(contour['file']) != str or not os.path.exists(contour['file']) or \
00170                            vwr.fileinfo(contour['file'])['type'] != 'image':
00171                                 raise Exception, contour['file'] + " does not exist or is not an image"
00172 
00173                 data = vwr.load( contour['file'], 'contour', panel=panel )
00174 
00175                 if contour.has_key('levels'):
00176                         vwr.contourlevels( self.__checknumeric(contour['levels'], float, "contour levels", array_size=0), data=data )
00177                 if contour.has_key('unit'):
00178                         vwr.contourlevels( unitlevel=self.__checknumeric(contour['unit'], float, "contour unitlevel"), data=data )
00179                 if contour.has_key('base'):
00180                         vwr.contourlevels( baselevel=self.__checknumeric(contour['base'], float, "contour baselevel"), data=data )
00181 
00182                 return data
00183 
00184         def __set_axes( self, vwr, panel, axes ):
00185                 x=''
00186                 y=''
00187                 z=''
00188                 invoke = False
00189                 if type(axes) == list and len(axes) == 3 and \
00190                    all( map( lambda x: type(x) == str, axes ) ) :
00191                         x = axes[0]
00192                         y = axes[1]
00193                         z = axes[2]
00194                         invoke = True
00195                 elif type(axes) == dict :
00196                         if axes.has_key('x'):
00197                                 if type(axes['x']) != str:
00198                                         raise Exception, "dimensions of axes must be strings (x is not)"
00199                                 x = axes['x']
00200                                 invoke = True
00201                         if axes.has_key('y'):
00202                                 if type(axes['y']) != str:
00203                                         raise Exception, "dimensions of axes must be strings (y is not)"
00204                                 y = axes['y']
00205                                 invoke = True
00206                         if axes.has_key('z'):
00207                                 if type(axes['z']) != str:
00208                                         raise Exception, "dimensions of axes must be strings (z is not)"
00209                                 z = axes['z']
00210                                 invoke = True
00211                 else :
00212                         raise Exception, "'axes' must either be a string list of 3 dimensions or a dictionary"
00213 
00214                 result = False
00215                 if invoke:
00216                         vwr.axes( x, y, z, panel=panel )
00217                         result = True
00218 
00219                 return result
00220 
00221 
00222         def __zoom( self, vwr, panel, zoom ) :          
00223 
00224                 channel = -1
00225                 if type(zoom) == dict and zoom.has_key('channel') :
00226                         channel = self.__checknumeric(zoom['channel'], int, "channel")
00227 
00228                 if type(zoom) == int :
00229                         vwr.zoom(level=zoom,panel=panel)
00230                 elif type(zoom) == str and os.path.isfile( zoom ):
00231                         vwr.zoom(region=zoom,panel=panel)
00232                 elif type(zoom) == dict and zoom.has_key('blc') and zoom.has_key('trc'):
00233                         blc = zoom['blc']
00234                         trc = zoom['trc']
00235                         if type(blc) == list and type(trc) == list:
00236                                 blc = self.__checknumeric( blc, float, "zoom blc", array_size=2 )
00237                                 trc = self.__checknumeric( trc, float, "zoom trc", array_size=2 )
00238 
00239                                 coord = "pixel"
00240                                 if zoom.has_key('coordinates'):
00241                                         if zoom.has_key('coord'):
00242                                                 raise Exception, "cannot specify both 'coord' and 'coordinates' for zoom"
00243                                         if type(zoom['coordinates']) != str:
00244                                                 raise Exception, "zoom coordinates must be a string"
00245                                         coord = zoom['coordinates']
00246                                         if coord != 'world' and coord != 'pixel' :
00247                                                 raise Exception, "zoom coordinates must be either 'world' or 'pixel'"
00248                                 elif zoom.has_key('coord'):
00249                                         if type(zoom['coord']) != str:
00250                                                 raise Exception, "zoom coord must be a string"
00251                                         coord = zoom['coord']
00252                                         if coord != 'world' and coord != 'pixel' :
00253                                                 raise Exception, "zoom coord must be either 'world' or 'pixel'"
00254                                 if channel >= 0:
00255                                         vwr.channel( channel, panel=panel )
00256                                 vwr.zoom(blc=blc,trc=trc, coordinates=coord, panel=panel)
00257                         elif type(blc) == dict and type(trc) == dict and \
00258                              blc.has_key( '*1' ) and trc.has_key( '*1' ) :
00259                                 if channel >= 0:
00260                                         vwr.channel( channel, panel=panel )
00261                                 vwr.zoom(region=zoom,panel=panel)
00262                         else:
00263                                 raise Exception, "zoom blc & trc must be either lists or dictionaries" 
00264 
00265                 elif type(zoom) == dict and zoom.has_key('regions'):
00266                         if channel >= 0:
00267                                 vwr.channel( channel, panel=panel )
00268                         vwr.zoom(region=zoom,panel=panel)
00269                 elif type(zoom) == dict and zoom.has_key('file') and type(zoom['file']) == str and os.path.isfile( zoom['file'] ):
00270                         if channel >= 0:
00271                                 vwr.channel( channel, panel=panel )
00272                         vwr.zoom(region=zoom['file'],panel=panel)
00273                 else:
00274                         if channel < 0:
00275                                 raise Exception, "invalid zoom parameters"
00276                         else:
00277                                 vwr.channel( channel, panel=panel )
00278 
00279         def __load_files( self, filetype, vwr, panel, files ):
00280 
00281                 if filetype != "raster" and filetype != "contour":
00282                         raise Exception, "internal error __load_files( )..."
00283 
00284                 if type(files) == str:
00285                         self.__load_raster( vwr, panel, { 'file': files } ) if filetype == 'raster' else \
00286                                             self.__load_contour( vwr, panel, { 'file': files } )
00287                 elif type(files) == dict:
00288                         self.__load_raster( vwr, panel, files ) if filetype == 'raster' else \
00289                                             self.__load_contour( vwr, panel, files )
00290                 elif type(files) == list:
00291                         if all(map( lambda x: type(x) == dict, files )):
00292                                 for f in files:
00293                                         self.__load_raster( vwr, panel, f ) if filetype == 'raster' else \
00294                                                             self.__load_contour( vwr, panel, f )
00295                         elif all(map( lambda x: type(x) == str, files )):
00296                                 for f in files:
00297                                         self.__load_raster( vwr, panel, { 'file': f } ) if filetype == 'raster' else \
00298                                                             self.__load_contour( vwr, panel, { 'file': f } )
00299                         else:
00300                                 raise Exception, "multiple " + filetype + " specifications must be either all dictionaries or all strings"
00301                 else:
00302                         raise Exception, filetype + "s can be a single file path (string), a single specification (dictionary), or a list containing all strings or all dictionaries"
00303 
00304 
00305         def __extract_outputinfo( self, out ):
00306                 output_file=None
00307                 output_format=None
00308                 output_scale=1.0
00309                 output_dpi=300
00310                 output_orientation="portrait"
00311                 
00312                 if type(out) == str:
00313                         output_format = self.__check_filename(out)
00314                         output_file = out
00315 
00316                 elif type(out) == dict:
00317                         if out.has_key('file'):
00318                                 if type(out['file']) != str:
00319                                         raise Exception, "output filename must be a string"
00320                                 if out.has_key('format'):
00321                                         if type(out['format']) != str:
00322                                                 raise Exception, "output format must be a string"
00323                                         output_format = self.__check_fileformat( out['format'] )
00324                                         self.__check_filename( out['file'], False )
00325                                 else:
00326                                         output_format = self.__check_filename( out['file'] )
00327 
00328                                 output_file = out['file']
00329 
00330                         else:
00331                                 raise Exception, "an output dictionary must include a 'file' field"
00332 
00333                         if out.has_key('scale'):
00334                                 output_scale = self.__checknumeric(out['scale'], float, "output scale")
00335 
00336                         if out.has_key('dpi'):
00337                                 output_dpi = self.__checknumeric(out['dpi'], int, "output dpi")
00338                                 output_dpi = int(out['dpi'])
00339 
00340                         if out.has_key('orientation'):
00341                                 if out.has_key('orient'):
00342                                         raise Exception, "output dictionary cannot have both 'orient' and 'orientation' fields"
00343                                 if type(out['orientation']) != str:
00344                                         raise Exception, "output orientation must be a string"
00345                                 if out['orientation'] != 'portrait' and out['orientation'] != 'landscape':
00346                                         raise Exception, "output orientation must be either 'portrait' or 'landscape'"
00347                                 output_orientation = out['orientation']
00348 
00349                         if out.has_key('orient'):
00350                                 if type(out['orient']) != str:
00351                                         raise Exception, "output orient field must be a string"
00352                                 if out['orient'] != 'portrait' and out['orient'] != 'landscape':
00353                                         raise Exception, "output orient field must be either 'portrait' or 'landscape'"
00354                                 output_orientation = out['orient']
00355 
00356                 return (output_file, output_format, output_scale, output_dpi, output_orientation)
00357 
00358         def __checknumeric( self, value, otype, error_string, array_size=None ):
00359                 if array_size is not None:
00360                         if type(array_size) != int:
00361                                 raise Exception, "internal error: array_size is expected to be of type int"
00362                         if type(value) != list:
00363                                 raise Exception, error_string + " must be a list"
00364                         if array_size > 0 and len(value) != array_size:
00365                                 numbers = { '1': 'one', '2': 'two', '3': 'three' }
00366                                 raise Exception, error_string + " can only be a " + numbers[str(array_size)] + " element numeric list"
00367                         if not all(map( lambda x: type(x) == int or type(x) == float, value )):
00368                                 raise Exception, error_string + " must be a numeric list"
00369                         return map( lambda x: otype(x), value )
00370                                     
00371                 if type(value) != int and type(value) != float:
00372                         raise Exception, error_string + " must be numeric"
00373 
00374                 return otype(value)
00375 
00376         def __check_fileformat( self, ext ):
00377                 supported_files = [ 'jpg', 'pdf', 'eps', 'ps', 'png', 'xbm', 'xpm', 'ppm' ]
00378                 if supported_files.count(ext.lower( )) == 0:
00379                         raise Exception, "output format '" + str(ext) + "' not supported; supported types are: " + str(supported_files)
00380                 return ext.lower( )
00381 
00382 
00383         def __check_filename( self, out, check_extension = True ):
00384                 dir = os.path.dirname(out)
00385                 if len(dir) > 0 and not os.path.isdir(dir):
00386                         raise Exception, "output directory (" + str(dir) + ") does not exist"
00387                 file = os.path.basename(out)
00388                 if len(file) == 0:
00389                         raise Exception, "could not find a valid file name in '" + str(out) + "'"
00390                 (base,ext) = os.path.splitext(file)
00391                 if len(ext) == 0:
00392                         raise Exception, "could not infer the ouput type from file name '" + str(file) + "'"
00393                 return self.__check_fileformat(ext[1:]) if check_extension else ''
00394 
00395         def __pushd( self, vwr, newdir ):
00396                 try:
00397                         old_path = vwr.cwd( )
00398                 except:
00399                         raise Exception, "imview() failed to get the current working directory [" + str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]) + "]"
00400 
00401                 self.__dirstack.append(old_path)
00402                 try:
00403                         vwr.cwd(newdir)
00404                 except:
00405                         raise Exception, "imview() failed to change to the new working directory (" + os.path.abspath(os.curdir) + ") [" + str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]) + "]"
00406 
00407 
00408         def __popd( self, vwr ):
00409                 try:
00410                         vwr.cwd(self.__dirstack.pop( ))
00411                 except:
00412                         raise Exception, "imview() failed to restore the old working directory (" + old_path + ") [" + str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]) + "]"
00413 
00414 
00415 imview = __imview_class( )