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

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

#
#$Header: /opt/cvs/Volume/Pvv/numarrtovolCommands.py,v 1.2 2007/07/24 17:30:45 vareille Exp $
#
#$Id: numarrtovolCommands.py,v 1.2 2007/07/24 17:30:45 vareille Exp $
#
"""Module implements a command that converts a Numeric Array to volumetric
data and loads the volume into the viewer."""

from ViewerFramework.VFCommand import Command, CommandGUI
import numpy.oldnumeric as Numeric , struct
from time import time
from Volume.IO import WriteVolumeToFile
from Volume.Operators.MapData import MapData
volGeom = None

class NumarrToVolume(Command):
    """ Non-GUI command to create a volume from a 3D numeric array.
    The numeric array values are mapped to the valid range of volume
    values """
    
    def __init__(self):
        Command.__init__(self)
        
        self.set_initvals()

    def set_initvals(self):
        
        self.val_limit = 4095
        self.val_start = 0
        self.arr = None
        self.data_min = None
        self.data_max = None
        self.val_min = 0
        self.val_max = 4095
        self.mapData = MapData(self.val_limit, self.val_start, Numeric.Int16)
        self.powerOf2 = 0
        self.wtf = WriteVolumeToFile.WriteVolumeToVox(0,0,0)
    
    def __call__(self, data, data_min = None, data_max = None,
                 val_min = None, val_max = None, savefile = None,
                 map_type='linear', **kw):
        """ None -> NumarrToVolume(data, data_min =None, data_max = None,
        val_min = None, val_max = None, map_type='linear')
        Create a volume from numeric array;
        data -- 3D numeric array;
        data_min, data_max -- min and max data values(other than actual
        data minimum/maximum) to map to
        val_min and val_max from the valid range of volume values(0...4095);
        savefile -- name of .vox file for writting the data (if None -
        created volume will be loaded but not saved in a file);
        map_type -- can be 'linear' or 'log';"""

        assert len(data.shape) == 3
        kw['log'] = 0 #log = 0, otherwise the array will be printed
                      #in the message box
        apply( self.doitWrapper, (data, data_min, data_max,
                                  val_min, val_max,savefile, map_type), kw )

    def doit(self, data, data_min, data_max, val_min,
             val_max, savefile, map_type, **kw):
        """Maps the data to the valid range of volume values
        (linear mapping). Creates and loads the volume."""
        arr = self.mapData(data, data_min, data_max,
                 val_min, val_max, map_type, self.powerOf2)
        self.arr = arr
        self.data_min = data_min
        self.data_max = data_max
        self.val_min = val_min
        self.val_max = val_max
        nx, ny, nz = arr.shape
        self.createNewVolume(arr, nx, ny, nz)
        if savefile != None:
            self.write2file(savefile, nx, ny, nz)

    def write2file(self, savefile, nx, ny, nz):
        """writes data into .vox file"""
        # Has to be implemented by a derived class
        pass

    def createNewVolume(self, nx, ny, nz):
        """Creates a new volume object. """
        # Has to be implemented by a derived class
        pass


class VLINumarrToVolume(NumarrToVolume):
    """ Non-GUI command to create a volume from a 3D numeric array.
    The numeric array values are mapped to the valid range of VLI
    values (0 ...4095)"""
    
    def write2file(self, savefile, nx, ny, nz):
        """writes data into .vox file"""
        
        self.wtf.size = (nx,ny,nz)
        self.wtf.file = savefile
        self.wtf.data = self.arr
        self.wtf.write_file()

    def createNewVolume(self, arr, nx, ny, nz):
        """Creates a new volume object. """
        from Volume.Renderers.VLI import vli
        arrPtr = vli.NumByteArrToVoidPt(arr)
        vlivol = vli.VLIVolume_Create( vli.kVLIVoxelFormatUINT12L, arrPtr,
                               nx,ny,nz)
        volGeom.freePointer = 0
        volGeom.AddVolume(vlivol, arrPtr)
        volGeom.dataArr = arr


class UTVolRenNumarrToVolume(NumarrToVolume):
    
    def set_initvals(self):
        self.val_limit = 255
        self.val_start = 1
        self.arr = None
        self.data_min = None
        self.data_max = None
        self.val_min = 1
        self.val_max = 255
        self.mapData = MapData(self.val_limit, self.val_start, Numeric.UnsignedInt8)
        self.powerOf2 = 1
        self.wtf = WriteVolumeToFile.WriteVolumeToRawiv(0,0,0)

    def createNewVolume(self, arr, nx, ny, nz):
        #size of volume in all directions has to be power of 2:
        volGeom.AddVolume(arr.ravel(),nx,ny,nz)
        self.arr = arr

    def write2file(self, savefile, nx, ny, nz):
        """writes data into .rawiv file"""
        
        self.wtf.size = (nx,ny,nz)
        self.wtf.file = savefile
        self.wtf.data = self.arr
        self.wtf.write_file()

    def __call__(self, data, data_min = None, data_max = None,
                 val_min = None, val_max = None, savefile = None, **kw):
        """ None -> NumarrToVolume(data, data_min =None, data_max = None,
        val_min = None, val_max = None, **kw)
        Create a volume from numeric array;
        data -- 3D numeric array;
        data_min, data_max -- min and max data values(other than actual
        data minimum/maximum) to map to
        val_min and val_max from the valid range of volume values(0...255);
        savefile -- name of .rawiv file for writting the data (if None -
        created volume will be loaded but not saved in a file)"""
        apply(NumarrToVolume.__call__, (self, data, data_min, data_max,
                                      val_min, val_max, savefile), kw )

commandGUI = None
commandNames={'vli': 'VLINumarrToVolume', 'utvolren':'UTVolRenNumarrToVolume'}
commandList = [{'name':'', 'cmd':None, 'gui': None}]
menuName = ''
menuIndex = None
        
def initModule(viewer):
    for dict in commandList:
        if dict['name']:
            viewer.addCommand( dict['cmd'], dict['name'], dict['gui'])
