## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by 

#############################################################################
#
# Author: Anna Omelchenko
#
# Copyright: M. Sanner TSRI
#
#############################################################################

#
#$Header: /opt/cvs/Volume/Pvv/gridToVolumeCommands.py,v 1.4 2007/07/24 17:30:45 vareille Exp $
#
#$Id: gridToVolumeCommands.py,v 1.4 2007/07/24 17:30:45 vareille Exp $
#
"""Module implements a command to create a volume from autogrid data that
has been read by Pmv gridCommands or specified .map file, display the volume
or save it into a file.
GUI description:
    The user can select the type of data scaling(linear or logarithmic)
    by pressing the corresponding radio button and specify the mapping
    intervals by typing in the provided entry fields.
    The actual data has to be mapped to scalars in range
    [scalar_start<=scalar_min,scalar_max<=scalar_limit].
    If mapping intervals are specified by supplying data min (greater or 
    equal to minimum array value) and data max (less or equal to maximum
    array value) values and scalar min and max, then the mapping will
    proceed as follows:
        [data_min , data_max] is mapped to [scalar_min, scalar_max].
    By pressing 'New grid to volume' button the user can obtain a new
    input form (GUI) with data information for converting another AutoGrid
    object or .map data file into a volume."""

from ViewerFramework.VFCommand import Command, CommandGUI
from mglutil.gui.InputForm.Tk.gui import InputFormDescr
from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser
import Tkinter, os, Pmw
import numpy.oldnumeric as Numeric, struct
from math import log
from time import time
try:
    from Pmv.Grid import AutoGrid
except:
    print "Warning: could not import Pmv.Grid.AutoGrid"
from Volume.IO import WriteVolumeToFile
from Volume.Operators.MapData import MapData
from Volume.Operators.MapData import MapGridData
from string import atof, atoi
volGeom = None

class GridToVolume(Command):
    """Command to create a volume from autogrid data that has been
    read by Pmv gridCommands or specified .map file, display the volume
    or save it into a file."""

    def __init__(self):
        Command.__init__(self)
        self.grid = None
        self.lastDir = "."
        self.mapfile = None
        self.savefile = None
        self.arr_min = 0.0 # data array minimum/maximum 
        self.arr_max = 0.0 
        self.data_min = 0.0 # data mapping interval minimum/maximum
        self.data_max = 0.0
        self.scaletype = Tkinter.StringVar()
        self.scaletype.set('linear')
        self.isDisplayed = 0
        self.form = None
        self.arr = None
        self.switch = Tkinter.IntVar()
        self.switch.set(0)
        self.gridSize = (0,0,0)
        self.gridName = None
        self.currScale = 'linear'
        self.set_initvals()
        

    def set_initvals(self):
        """set min/max values"""
        #has to be implemented by a derived class
        self.val_limit = 4095 # the maximum value of the integer array
        self.val_min = 0 # minimum/maximum scalar values of mapping interval
        self.val_max = 4095
        self.val_start = 0
        self.ext = ''
        self.title = ''
        self.dataType = Numeric.Int16
        #self.mapData = MapData(self.val_limit, self.val_start, Numeric.Int16)
        self.mapData = MapGridData()
        self.powerOf2 = 0

    def createVolume(self, arr, nx, ny, nz):
        """ Creates and adds a new volume object to the viewer."""
        # Has to be implemented by a derived class. """
        pass

    def write2file(self):
        """Writes data to a file."""
        # Has to be implemented by a derived class. """
        pass

    def guiCallback(self):
        """ Called each time the 'Grid To Volume' button is pressed"""
        if self.isDisplayed:
            self.form.lift()
            return
        if self.form:
            self.form.deiconify()
            self.isDisplayed = 1
            return
        if not hasattr(self.vf, 'grids'):
            result = self.nogridDialog()
            if result == 'OK':
                self.vf.loadModule("gridCommands","Pmv")
                return
            elif  result == 'Cancel':
                return
            else:
                self.loadMapFile()
        else:
            self.loadGrid()

    def nogridDialog(self):
        """ Pmw Message Dialog is called if there is no grid in the viewer"""
        master = self.vf.GUI.ROOT
        text = "No grid present in the viewer.\n"+ \
               "Press 'OK' and read AutoGrid \n" + \
               "with Pmv Grid Command \n" +\
               "or 'Convert .map' to specify a .map file."
        dialog = Pmw.MessageDialog(master, title="No Grid",
                                   buttons=('OK','Convert .map','Cancel'),
                                   defaultbutton='OK',
                                   message_text=text)
        result=dialog.activate()
        return result

    def loadMapFile(self):
        """Allows the user to select a .map file """
        mapfile=self.vf.askFileOpen(types=[('autogrid data files', '*.map')],
                                     idir = self.lastDir,
                                     title = "Read autogrid data file")
	if mapfile != None:
            if self.form:
                self.form.destroy()
                self.form = None
            if self.mapfile != mapfile:
                self.mapfile = mapfile
                master = Tkinter.Toplevel()
                Tkinter.Message(master, text ="Reading data from file %s..."\
                                % mapfile, aspect = 400,
                                relief = Tkinter.GROOVE).pack(padx=10, pady=10)
                self.vf.GUI.busy()
                t1 = time()
                self.grid = AutoGrid(mapfile)
                self.grid.name = mapfile
                self.readGrid()
                t2 = time()
                self.vf.GUI.idle()
                print "time to read file: ", (t2-t1)
                master.destroy()
            self.switch.set(1) # convert .map file to volume
            self.buildForm()
        return

    def loadGrid(self):
        """Gets data information from AutoGrid object"""
        numgrids = len(self.vf.grids)
        if numgrids == 0:
            # no grids present in the viewer
            result = self.nogridDialog()
            if result == 'OK' or result == 'Cancel':
                return
            else:
                self.loadMapFile()
                return
        if numgrids == 1:
            k = self.vf.grids.keys()[0]
            if self.grid == self.vf.grids[k]:
                # the grid has been piked
                master = self.vf.GUI.ROOT
                text = "There is only one AutoGrid \n" + \
                       "loaded in the viewer."
                dialog = Pmw.MessageDialog(master, title="One Grid",
                                           buttons=('OK',),
                                           defaultbutton='OK',
                                           message_text=text)
                result=dialog.activate()
                if self.form:
                    return
            if self.grid != self.vf.grids[k]:
                self.grid = self.vf.grids[k]
                self.readGrid()
        elif numgrids > 1:
            #there is more than one grid loaded -- need to pick a grid
            objList=[]
            for item in self.vf.grids.keys():
                objList.append((item, None))
            ifd0 = InputFormDescr(title='Choose Grid')
            ifd0.append({'widgetType': ListChooser,
                         'name':'gridObjs',
                         'wcfg' : {'entries':objList,
                                   'title':'Pick grid',
                                   'mode':'single',
                                   'lbwcfg':{'height':4, 'width':50}},
                         'gridcfg':{'sticky':'we'}
                         })
            val = self.vf.getUserInput(ifd0)
            #print "val:" , val
            if len(val)>0 :
                filename = val['gridObjs'][0]
                self.grid = self.vf.grids[filename]
            else: return
            self.readGrid()
        self.switch.set(0)
        if self.form:
            self.form.destroy()
            self.form = None
        self.buildForm()
        self.mapfile = None


    def buildForm(self):
        """Builds a GUI """
        self.isDisplayed = 1
        ifd = InputFormDescr(title = 'Mapping Info')
        gridname = os.path.basename(self.grid.name)
        ifd.append({'widgetType': Tkinter.Label,
                    'wcfg': {'text': 'Grid Name: '+gridname},
                    'gridcfg': {'column':0, 'columnspan': 2,
                                'sticky': 'w'}
                    })

        ifd.append({'widgetType':Tkinter.Radiobutton,
                    'wcfg': {'value': 0,
                             'text': 'AutoGrid to volume',
                             'variable': self.switch},
                    'gridcfg':{'column':0,'sticky':'w'},
                    })
        ifd.append({'widgetType':Tkinter.Radiobutton,
                    'wcfg': {'value': 1,
                             'text': '.map to volume',
                             'variable': self.switch},
                    'gridcfg':{'column':1, 'row':-1, 'sticky':'w'},
                    })

        ifd.append({'widgetType': Tkinter.Label,
                    'wcfg': {'text': 'Specify type of scaling:'},
                    'gridcfg':{'column':0, 'columnspan':2,
                               'sticky':'w'}
                    })
        ifd.append({'widgetType':Tkinter.Radiobutton,
                    'wcfg': {'value': 'linear',
                             'text': 'linear',
                             'variable': self.scaletype},
                    'gridcfg':{'column':0,'sticky':'w'},
                    })
        ifd.append({'widgetType':Tkinter.Radiobutton,
                    'wcfg': {'value': 'log',
                             'text': 'log',
                             'variable': self.scaletype},
                    'gridcfg':{'column':1, 'row': -1, 'sticky':'w'},
                    })
        ifd.append({'widgetType': Tkinter.Label,
                    'wcfg': {'text': 'Mapping intervals for linear scale:'},
                    'gridcfg':{'column':0, 'columnspan':2,
                               'sticky':'w'}
                    })
        ifd.append({'widgetType': Tkinter.Label,
                    'wcfg': {'text': 'source data'},
                    'gridcfg':{'column': 0,
                               'columnspan':1, 'sticky':'w'}
                    })
        ifd.append({'widgetType': Tkinter.Label,
                    'wcfg': {'text': "scalars(%d...%d)"%(self.val_min,
                                                         self.val_limit) },
                    'gridcfg':{'row':-1, 'column': 1,
                               'columnspan':2, 'sticky':'w'}
                    })
        ifd.append({'widgetType':Pmw.EntryField,
                    'name':'data_min',
                    'wcfg':{'labelpos':'w',
                            'label_text':'min:  ',
                            'entry_width': 10,
                            'validate':{'validator':'real',
                                        'max': self.arr_max+1,
                                        'min': self.arr_min-1},
                            'value': str(self.arr_min)},
                            #'modifiedcommand':self.get_data_min_cb},
                    'gridcfg':{'column':0,'sticky':'w'}
                    })
        ifd.append({'widgetType':Pmw.EntryField,
                    'name':'val_min',
                    'wcfg':{'labelpos':'w',
                            'label_text':'min:  ',
                            'entry_width': 10,
                            'validate':{'validator':'numeric',
                                        'max': self.val_limit,
                                        'min': self.val_start},
                            'value': str(self.val_min)},
                           #'modifiedcommand':self.get_val_min_cb },
                    'gridcfg':{'row':-1, 'column':1,'sticky':'w'}
                    })
        ifd.append({'widgetType':Pmw.EntryField,
                    'name':'data_max',
                    'wcfg':{'labelpos':'w',
                            'label_text':'max: ',
                            'entry_width': 10,
                            'validate':{'validator':'real',
                                        'max': self.arr_max+1,
                                        'min': self.arr_min-1},
                            'value': str(self.arr_max)},
                           #'modifiedcommand':self.get_data_max_cb },
                    'gridcfg':{'column':0,'sticky':'w'}
                    })
        ifd.append({'widgetType':Pmw.EntryField,
                    'name':'val_max',
                    'wcfg':{'labelpos':'w',
                            'label_text':'max: ',
                            'entry_width': 10,
                            'validate':{'validator':'numeric',
                                        'max': self.val_limit,
                                        'min': self.val_start},
                            'value': self.val_limit},
                            #'modifiedcommand':self.get_val_max_cb},
                    'gridcfg':{'row':-1, 'column':1,'sticky':'w'}
                    })
        ifd.append({'widgetType':Tkinter.Button,
                    'wcfg': {'text': 'write to file',
                             'relief' : Tkinter.RAISED,
                             'command': self.write2file_cb},
                    'gridcfg':{'column':0,'columnspan':1,
                               'sticky':'ew'},
                    
                    })
        ifd.append({'widgetType':Tkinter.Button,
                    'wcfg':{'text': 'load data',
                            'relief' : Tkinter.RAISED,
                            'command': self.loaddata_cb},
                    'gridcfg':{'column':1,'columnspan':2,
                               'row':-1, 'sticky':'ew'},
                    })
        ifd.append({'widgetType': Tkinter.Button,
                    'wcfg': {'text': 'New grid to volume',
                             'relief' : Tkinter.RAISED,
                             'command': self.chooseNewGrid_cb},
                    'gridcfg':{'column':0,
                               'sticky':'ew'},
                    })
        ifd.append({'widgetType': Tkinter.Button,
                    'wcfg': {'text': 'Reset min/max',
                             'relief' : Tkinter.RAISED,
                             'command': self.resetminmax},
                    'gridcfg':{'column':1, 'row':-1,
                               'sticky':'ew'},
                    })
        ifd.append({'widgetType': Tkinter.Button,
                    'wcfg': {'text': 'Close',
                             'relief' : Tkinter.RAISED,
                             'command': self.close_cb},
                    'gridcfg':{'column':0, 'columnspan':2,
                               'sticky':'ew'},
                    })
        
        self.form = self.vf.getUserInput(ifd, modal = 0, blocking=0)


    def close_cb(self):
        self.isDisplayed = 0
        self.form.withdraw()


    def getminmax(self):
        """gets mapping intervals from the input form"""
        val = self.form.checkValues()
        data_min = atof(val['data_min'])
        data_max = atof(val['data_max'])
        val_min = atoi(val['val_min'])
        val_max = atoi(val['val_max'])
        return [data_min, data_max, val_min, val_max] 

    def get_data_min_cb(self):
        pass
##          w = self.form.descr.entryByName['data_min']['widget']
##          if w.valid():
##              val = w.get()
##              self.data_min = float(val)

    def get_data_max_cb(self):
        pass
##          w = self.form.descr.entryByName['data_max']['widget']
##          if w.valid():
##              val = w.get()
##              self.data_max = float(val)

    def get_val_min_cb(self):
        pass
##          w = self.form.descr.entryByName['val_min']['widget']
##          if w.valid():
##              val = w.get()
##              self.val_min = int(val)

    def get_val_max_cb(self):
        pass
##          w = self.form.descr.entryByName['val_max']['widget']
##          if w.valid():
##              val = w.get()
##              self.val_max = int(val)
        
    def write2file_cb(self):
        """writes data into a file""" 
        vol = None
        data_min, data_max, val_min, val_max = self.getminmax()
        savefile = self.vf.askFileSave(types=[(self.title, '*.'+self.ext)],
                                           title = "Save as ."+self.ext)

        if savefile != None:
            self.savefile = savefile
            scaletype = self.scaletype.get()
            action = 'write'
            gridname = None
            if hasattr(self.vf, 'grids'):
                if len(self.vf.grids)>1:
                    gridname = self.grid.name
            self.wtf.file = self.savefile
            vol = apply(self.doitWrapper, (data_min, data_max,
                                           val_min, val_max ,
                                           None, savefile, gridname,
                                           scaletype, action ), {})
        return vol

    def loaddata_cb(self):
        """called when 'load data' button on the input form is pressed"""
        data_min, data_max, val_min, val_max = self.getminmax()
        scaletype = self.scaletype.get()
        action = 'load'
        gridname = None
        if hasattr(self.vf, 'grids'):
                if len(self.vf.grids)>1:
                    gridname = self.grid.name
        apply(self.doitWrapper,(data_min, data_max, val_min, val_max,
                                None, None, gridname, scaletype, action ), {})
        

    def readGrid(self):
        """reads grid data"""
        nx = self.grid.NELEMENTS[0]
        ny = self.grid.NELEMENTS[1]
        nz = self.grid.NELEMENTS[2]
        self.gridSize = (nx, ny, nz)
##          arr = self.grid.array.ravel()
##          arr_max = Numeric.maximum.reduce(arr)
##          arr_min = Numeric.minimum.reduce(arr)
        arr_max = self.grid.max
        arr_min = self.grid.min
        self.arr_min = arr_min
        self.arr_max = arr_max
        #print "min(arr)=%f" % arr_min
        #print "max(arr)=%f" % arr_max
        self.wtf.size = (nx,ny,nz)
        sc = self.grid.SPACING
        self.sc = (sc,sc,sc)
        self.tr = Numeric.array(self.grid.CENTER, 'f')/sc
        
    
    def __call__(self, data_min = None, data_max = None,
             val_min = None, val_max = None,
             mapfile = None, savefile = None, gridname = None,
             scaletype='linear', action = 'load', **kw):
        """ None -> DisplayGrid(data_min = None, data_max = None,
                                val_min = None, val_max = None,
                                mapfile = None, savefile = None,
                                gridname = None,
                                scaletype = 'linear', action = 'load')
        data_min, data_max -- min and max data values to map to
        val_min and val_max of the valid range of volume values(0....4095);
        mapfile -- .map grid file(if None - grid should have been
        loaded with Grid Commands);
        savefile -- volume file;
        gridname -- specify the grid name(file name) if there is more than
        one grid loaded in the viewer;
        scaletype -- can be either 'linear' or 'log';
        action -- 'load' to load data into the viewer;
                  'write' to write data to a file"""
        
        #print "data_min" , data_min, "data_max", data_max,
        #print "val_min", val_min, "val_max", val_max
        if mapfile == None:
            if not hasattr(self.vf, 'grids'):
                print "no grid present in the viewer"
                return 
            numgrids = len(self.vf.grids)
            if numgrids == 0:
                print "no grid present in the viewer"
                return
            elif numgrids > 1:
                if not gridname:
                    print "There is more than one grid loaded in the viewer. Specify 'gridname'"
                    return
                else:
                    names = self.vf.grids.keys()
                    if gridname not in names:
                        print "Grid: ",gridname,"is not in grid names: ", names
                        return
                    self.grid = self.vf.grids[gridname]
            elif numgrids == 1:
                k = self.vf.grids.keys()[0]
                self.grid = self.vf.grids[k]
        else:
            if self.mapfile != mapfile:
                if os.path.exists(mapfile):
                    self.grid = AutoGrid(mapfile)
                    self.grid.name = mapfile
                    self.readGrid()
                else:
                    print "Error: File %s does not exist" % mapfile
                    return
        if action == 'write':
            if not savefile:
                print "No volume filename specified to write data in."
                return
            self.wtf.file = savefile
            if self.wtf.checkIfExists():
                return
        self.readGrid()
        self.savefile = savefile
        self.mapfile = mapfile

        if val_min != None:
            assert val_min >= 0 and val_min < self.val_limit
        else:
            val_min = 0
        if val_max != None:
            assert val_max <= self.val_limit and val_max > 0
        else:
            val_max = self.val_limit
                
        if data_min != None:
            if data_min < self.arr_min: data_min = self.arr_min
        else:
            data_min = self.arr_min
        if data_max != None:
            if data_max > self.arr_max: data_max = self.arr_max
        else:
            data_max = self.arr_max
        assert data_min < data_max
        
        apply( self.doitWrapper, (data_min, data_max, val_min, val_max,
                                  mapfile, savefile, gridname,
                                  scaletype, action), kw )

    def doit(self, data_min = None, data_max = None,
             val_min = None, val_max = None,
             mapfile = None, savefile = None, gridname = None,
             scaletype = 'linear', action = 'load', **kw):

        """Creates a volume out of grid data"""
        #print "data_min, data_max, val_min, val_max:", data_min, data_max, val_min, val_max
        assert data_min < data_max
        assert val_min < val_max  #this should be checked in GUI 
        nx, ny, nz = self.gridSize
        gridsize = nx*ny*nz
        data = self.grid.array
        create_new = 1
        #check if we need to create a new volume:
        if self.arr and self.gridName == self.grid.name:
            #print self.gridName,'==', self.grid.name
            if self.currScale == scaletype:
                if scaletype == "log":
                    create_new = 0
                    if self.form:
                        self.resetminmax()
                else:
                    if abs(data_min-self.data_min) <0.00001:
                        if abs(data_max-self.data_max) < 0.00001:
                            if val_min == self.val_min:
                                if val_max == self.val_max:
                                    create_new = 0

        #print "create_new =", create_new #, "gridName:", self.gridName
        if create_new:
            if scaletype == 'log':
                data_min, data_max, val_min, val_max = self.resetminmax()
##              arr = self.mapData(data, data_min, data_max,
##                                 val_min, val_max, scaletype, self.powerOf2)
            arr = self.mapData(data, datamap = {'src_min':data_min,
                                                'src_max':data_max,
                                                'dst_min':val_min,
                                                'dst_max': val_max,
                                                'map_type': scaletype},
                               datatype=self.dataType,
                               powerOf2=self.powerOf2)
            arr = Numeric.transpose(arr).astype(self.dataType)
            
            if action == 'load':
                self.createVolume(arr, nx, ny, nz)
            elif action == 'write':
                self.wtf.data = arr
                self.write2file()
                self.arr = arr
                volGeom.dataArr = arr
            self.data_min = data_min
            self.data_max = data_max
            self.val_min = val_min
            self.val_max = val_max
            self.currScale = scaletype
            self.gridName = self.grid.name
        else:
            if action == 'write':
                self.wtf.data = self.arr
                self.write2file()
        
    def chooseNewGrid_cb(self):
        """called when 'New grid to volume' button on the input form
        is pressed"""
        val = self.switch.get()
        if val == 0: # chose new AutoGrid already loaded in the viewer
            if not hasattr(self.vf, 'grids'):
                result = self.nogridDialog()
                if result == 'OK':
                    self.vf.loadModule("gridCommands", "Pmv")
                    return
                elif result == 'Cancel':
                    return
                else:
                    self.loadMapFile()
            else:
                self.loadGrid()
        elif val == 1: #chose new. map file
            self.loadMapFile()

    def resetminmax(self):
        """Resets entries on the input form to data min/max and
        scalars min/max"""
        if self.form:
            ent = self.form.descr.entryByName
            ent['data_min']['widget'].setentry(str(self.arr_min))
            ent['data_max']['widget'].setentry(str(self.arr_max))
            ent['val_min']['widget'].setentry(str(self.val_start))
            ent['val_max']['widget'].setentry(str(self.val_limit))
        data_min =  self.arr_min
        data_max =  self.arr_max
        val_min =  self.val_start
        val_max =  self.val_limit
        return [data_min, data_max, val_min, val_max]

class VLIGridToVolume(GridToVolume):
    """Command to create a VLI volume object from autogrid data that has been
    read by Pmv gridCommands or specified .map file, display the volume
    or save it into a file."""
    
    
    def set_initvals(self):
        #set min/max values
        self.val_limit = 4095
        self.val_start = 0
        self.val_min = 0
        self.val_max = 4095
        self.ext = 'vox'
        self.title = 'Vox Files'
        #self.mapData = MapData(self.val_limit, self.val_start, Numeric.Int16)
        self.mapData = MapGridData()
        self.dataType = Numeric.Int16
        self.powerOf2 = 0
        self.wtf  = WriteVolumeToFile.WriteVolumeToVox(0,0,0)
        
    def createVolume(self, arr, nx, ny, nz):
        from Volume.Renderers.VLI import vli
        arrPtr = vli.NumByteArrToVoidPt(arr)
        vlivol = vli.VLIVolume_Create(vli.kVLIVoxelFormatUINT12L,
                                      arrPtr, nx,ny,nz)
        volGeom.Set(volscale = self.sc,
                    voltranslate = (self.tr[0],self.tr[1],self.tr[2]))
        volGeom.freePointer = 0
        volGeom.AddVolume(vlivol, arrPtr)
        volGeom.freePointer = 1
        self.arr = arr
        volGeom.dataArr = arr

    def write2file(self):
        self.wtf.write_file()


class UTVolRenGridToVolume(GridToVolume):
    """Command to create a  OpenGL based ( Univ. of Texas Volume Library)
    volume object from autogrid data that has been
    read by Pmv gridCommands or specified .map file, display the volume
    or save it into a file."""
    
    def set_initvals(self):
        #set min/max values
        self.val_limit = 255
        self.val_start = 1
        self.val_min = 1
        self.val_max = 255
        self.ext = 'rawiv'
        self.title = 'Volume Files'
        ##  self.mapData = MapData(self.val_limit, self.val_start,
##                                 Numeric.UnsignedInt8)
        self.mapData = MapGridData()
        self.dataType = Numeric.UnsignedInt8
        self.powerOf2 = 1
        self.wtf  = WriteVolumeToFile.WriteVolumeToRawiv(0,0,0)

    def createVolume(self, arr, nx, ny, nz):
        #nx1, ny1, nz1 = arr.shape
        nz1, ny1, nx1 = arr.shape
        print "new array shape", nx1, ny1, nz1
        dx, dy, dz = 0, 0, 0
        if nx1 != nx or ny1 != ny or nz1 != nz:
           dx = (nx1-nx)/2. ; dy = (ny1-ny)/2. ; dz = (nz1-nz)/2. 
        ##  volGeom.AddVolume(arr.ravel(),nx1,ny1,nz1)
        self.arr = arr
        self.wtf.size = (nx1,ny1,nz1)
        sc = self.grid.SPACING
        tr = Numeric.array(self.grid.CENTER,'f')+\
             Numeric.array([dx*sc,dy*sc,dz*sc], 'f')
        volGeom.SetTranslation(tr)
        volGeom.SetScale(((nx1-1)*sc, (ny1-1)*sc, (nz1-1)*sc))
        volGeom.AddVolume(arr.ravel(),nx1,ny1,nz1)
        
    def write2file(self):
        self.wtf.write_file()

    def __call__(self, data_min = None, data_max = None,
                 val_min = None, val_max = None,
                 mapfile = None, savefile = None, gridname = None,
                 scaletype = 'linear', action = 'load', **kw):
        """ None -> DisplayGrid(data_min = None, data_max = None,
                                val_min = None, val_max = None,
                                mapfile = None, savefile = None,
                                gridname = None, scaletype = 'linear',
                                action = 'write')
        data_min, data_max -- min and max data values to map to
        val_min and val_max of the valid range of volume values(0...255);
        mapfile -- .map grid file(if None - grid should have been
        loaded with Grid Commands);
        savefile -- volume file;
        gridname -- specify the grid name(file name) if there is more than
        one grid loaded in the viewer;
        scaletype -- can be either 'linear' or 'log';
        action -- 'load' to load data into the viewer;
                  'write' to write data to .rawiv file"""
        apply(GridToVolume.__call__, (self, data_min, data_max,
                                      val_min, val_max , mapfile, savefile,
                                      gridname, scaletype, action), kw )
        
commandGUI = CommandGUI()
menuName = 'Grid To Volume'
menuIndex = 7
commandNames = {'vli':'VLIGridToVolume', 'utvolren': 'UTVolRenGridToVolume'}
commandList = [{'name':'', 'cmd':None, 'gui':None}]
        

def initModule(viewer):

    for dict in commandList:
        if dict['name']:
            viewer.addCommand( dict['cmd'], dict['name'], dict['gui'])
