ImageDataの記述

ImageDataの例

VTKにおいて,与えられたデータをImageDataとして記述してみる. ImageDataのサンプルは次のようになる.

<?xml version="1.0"?>
  <VTKFile type="ImageData">
    <ImageData WholeExtent="0 4 0 4 0 0" Origin="0.0 0.0 0.0" Spacing="1.0 1.0 1.0">
      <Piece Extent="0 4 0 4 0 0">
        <PointData Scalars="Data1">
          <DataArray type="Float64" NumberOfComponents="1" Name="Data1" format="ascii">
            2.718 1.868 1.648 1.868 2.718
            1.868 1.284 1.133 1.284 1.868
            1.648 1.133 1.0   1.133 1.648
            1.868 1.284 1.133 1.284 1.868
            2.718 1.868 1.648 1.868 2.718
          </DataArray>
        </PointData>
      </Piece>
  </ImageData>
</VTKFile>

Paraviewを用いた表示結果は以下の通り.

../_images/screenshot_ImageData_ParaView_sample.png

ImageData出力用クラス

Python上のnumpy配列データを引数として渡し, データセット要素 ImageData のXML形式VTKファイル(.vti) を出力するクラスを以下に示す.

import sys, subprocess
import numpy as np

# ========================================================= #
# ===  vtk_makeImageData class                          === #
# ========================================================= #
class vtk_makeImageData():
    # ------------------------------------------------- #
    # --- class Initiator                           --- #
    # ------------------------------------------------- #
    def __init__( self, vtkFile=None, Data=None, Spacing=[1.,1.,1.], Origin=[0.,0.,0.,], \
                  VectorData=False, DataFormat="ascii", ):
        # --- [1-1] Arguments                       --- #
        if ( vtkFile is None ): vtkFile = "out.vti"
        # --- [1-2] Variables Settings              --- #
        self.vtkFile     = vtkFile
        self.vtkContents = ''
        self.vtkEndTags  = ''
        self.Data        = Data
        self.Origin      = Origin
        self.Spacing     = Spacing
        self.DataFormat  = DataFormat
        self.VectorData  = VectorData
        self.DataDims    = None
        self.LILJLK      = None
        # --- [1-3] Routines                        --- #
        self.vtk_add_VTKFileTag  ( datatype="ImageData" )
        self.vtk_add_ImageDataTag( Data=self.Data, VectorData=self.VectorData )
        self.vtk_writeFile()

        
    # ------------------------------------------------- #
    # --- vtk_add_VTKFileTag                        --- #
    # ------------------------------------------------- #
    def vtk_add_VTKFileTag( self, datatype=None ):
        # ------------------------------------------------- #
        # --- [1] Add XML Definition & VTKFile Tag      --- #
        # ------------------------------------------------- #
        if ( datatype is None ): datatype = "ImageData"
        self.vtkContents  += '<?xml version="1.0"?>\n'
        self.vtkContents  += '<VTKFile type="{0}">\n'.format( datatype )
        self.vtkEndTags    = '</VTKFile>'     + '\n' + self.vtkEndTags

        
    # ------------------------------------------------- #
    # --- vtk_add_ImageDataTag                      --- #
    # ------------------------------------------------- #
    def vtk_add_ImageDataTag( self, Data=None, LILJLK=None, Origin=None, Spacing=None, \
                              DataName=None, VectorData=False, WholeExtent=None, Point_or_Cell="point" ):
        # ------------------------------------------------- #
        # --- [1] Arguments                             --- #
        # ------------------------------------------------- #
        if ( DataName is None ): DataName = "Data"
        self.prepareData( Data=Data, VectorData=VectorData )
        if   ( VectorData is True  ):
            Scl_or_Vec   = "Vectors"
        elif ( VectorData is False ):
            Scl_or_Vec   = "Scalars"
        if ( WholeExtent is None   ):
            WholeExtent  = " ".join( [ "0 {0}".format( max(s-1,0) ) for s in list( self.LILJLK ) ] )
        if ( Origin      is None   ):
            Origin       = " ".join( [ str(Opt) for Opt in self.Origin    ] )
        if ( Spacing     is None   ):
            Spacing      = " ".join( [ str(Spc) for Spc in self.Spacing   ] )
        # ------------------------------------------------- #
        # --- [2] ImageDataTag                          --- #
        # ------------------------------------------------- #
        self.vtkContents  += '<ImageData WholeExtent="{0}" Origin="{1}" Spacing="{2}">\n'\
            .format( WholeExtent, Origin, Spacing )
        self.vtkContents  += '<Piece Extent="{0}">\n'.format( WholeExtent )
        # ------------------------------------------------- #
        # --- [3] PointData / CellData                  --- #
        # ------------------------------------------------- #
        if ( Point_or_Cell.lower() == "point" ):
            self.vtkContents  += '<PointData {0}="{1}">\n'.format( Scl_or_Vec, DataName )
            self.vtkContents  += self.vtk_add_DataArray( Data=Data, DataName=DataName )
            self.vtkContents  += '</PointData>\n'
        if ( Point_or_Cell.lower() == "cell"  ):
            self.vtkContents  += '<CellData {0}="{1}">\n'.format( Scl_or_Vec, DataName )
            self.vtkContents  += self.vtk_add_DataArray( Data=Data, DataName=DataName )
            self.vtkContents  += '</CellData>\n'
        # ------------------------------------------------- #
        # --- [4] Close ImageData Tag                   --- #
        # ------------------------------------------------- #
        self.vtkContents += '</Piece>\n'    
        self.vtkContents += '</ImageData>\n'

        
    # ------------------------------------------------- #
    # --- vtk_add_DataArray                         --- #
    # ------------------------------------------------- #
    def vtk_add_DataArray( self, Data=None, DataName=None, DataFormat=None, DataType=None, nComponents=None, nData=None, VectorData=False ):
        if ( Data        is None ): sys.exit( "[vtk_add_DataArray -@makeStructuredGrid-] Data     == ??? " )
        if ( DataName    is None ): sys.exit( "[vtk_add_DataArray -@makeStructuredGrid-] DataName == ??? " )
        if ( DataFormat  is None ): DataFormat  = self.DataFormat
        if ( DataType    is None ): DataType    = self.inquiryData( Data=Data, ret_DataType   =True, VectorData=VectorData )
        if ( nComponents is None ): nComponents = self.inquiryData( Data=Data, ret_nComponents=True, VectorData=VectorData )
        if ( nData       is None ): nData       = self.inquiryData( Data=Data, ret_nData      =True, VectorData=VectorData )
        ret  = ""
        ret += '<DataArray Name="{0}" type="{1}" NumberOfComponents="{2}" format="{3}">\n'\
                                 .format( DataName, DataType, nComponents, DataFormat )
        lines = ""
        if ( nComponents == 1 ):
            for line in np.ravel( Data ):
                lines += "{0} ".format( line )
            lines += "\n"
        else:
            for line in Data:
                lines += ( " ".join( [ str( val ) for val in line ] ) + "\n" )
        ret += lines
        ret += '</DataArray>\n'
        return( ret )
        
    
    # ------------------------------------------------- #
    # --- vtk_writeFile                             --- #
    # ------------------------------------------------- #
    def vtk_writeFile( self, vtkFile=None ):
        if ( vtkFile is None ): vtkFile = self.vtkFile
        with open( vtkFile, "w" ) as f:
            f.write( self.vtkContents )
            f.write( self.vtkEndTags  )
        subprocess.call( ( "xmllint --format --encode utf-8 {0} -o {0}"\
                           .format( vtkFile ) ).split() )
        print( "[vtk_writeFile-@makeImageData-] VTK File output :: {0}".format( vtkFile ) )


    # ------------------------------------------------- #
    # --- inquiryData                               --- #
    # ------------------------------------------------- #
    def inquiryData( self, Data=None, VectorData=False, ret_DataType=False, ret_nComponents=False, ret_nData=False ):
        if ( Data is None ): sys.exit( "[inquiryData-@vtk_makeImageData-] Data  == ??? " )
        # ------------------------------------------------- #
        # --- [1] DataType Check                        --- #
        # ------------------------------------------------- #
        if ( type(Data) is not np.ndarray ):
            sys.exit( "[inquiryData-@vtk_makeImageData-] Data should be np.ndarray [ERROR]" )
        if ( Data.dtype == np.int32   ): DataType = "Int32"
        if ( Data.dtype == np.int64   ): DataType = "Int64"
        if ( Data.dtype == np.float32 ): DataType = "Float32"
        if ( Data.dtype == np.float64 ): DataType = "Float64"
        # ------------------------------------------------- #
        # --- [2] Data Shape Check                      --- #
        # ------------------------------------------------- #
        if ( VectorData is True ):
            nComponents = Data.shape[-1]
            nData       = np.size( Data[-1][:] )
        else:
            nComponents = 1
            nData       = np.size( Data[:]    )
        # ------------------------------------------------- #
        # --- [3] Return                                --- #
        # ------------------------------------------------- #
        if ( ret_DataType    ): return( DataType    )
        if ( ret_nComponents ): return( nComponents )
        if ( ret_nData       ): return( nData       )
        return( { "DataType":DataType, "nComponents":nComponents, "nData":nData } )


    # ------------------------------------------------- #
    # --- prepareData                               --- #
    # ------------------------------------------------- #
    def prepareData( self, Data=None, VectorData=False ):
        # ------------------------------------------------- #
        # --- [1] Data Array Type/Shape Check           --- #
        # ------------------------------------------------- #
        if ( Data is None   ): return()
        if ( type(Data) is not np.ndarray ):
            sys.exit( "[prepareData-@vtk_makeImageData-] Data should be np.ndarray [ERROR]" )
        if ( Data.ndim >= 5 ):
            sys.exit( "[prepareData-@vtk_makeImageData-] incorrect Data size ( ndim >= 5 ) [ERROR]" )
        # ------------------------------------------------- #
        # --- [2] DataDims & LILJLK Check               --- #
        # ------------------------------------------------- #
        if ( VectorData is True ):
            self.DataDims   = Data.shape[-1]
            self.LILJLK     = Data.shape[:-1]
        else:
            self.DataDims   = 1
            self.LILJLK     = Data.shape[:]
        # ------------------------------------------------- #
        # --- [3] for 2D Data                           --- #
        # ------------------------------------------------- #
        if ( len( self.LILJLK ) == 2 ):
            self.LILJLK = self.LILJLK + (1,)
            Data        = Data.reshape( self.LILJLK )
        if ( len( self.LILJLK ) == 1 ):
            self.LILJLK = self.LILJLK + (1,1,)
            Data        = Data.reshape( self.LILJLK )

    
# ======================================== #
# ===  実行部                          === #
# ======================================== #
if ( __name__=="__main__" ):
    x1Range = [-1.0,+1.0]
    x2Range = [-1.0,+1.0]
    size    = (5,5)
    import genGrid.Gaussian2D as gs2
    gau     = gs2.Gaussian2D( x1Range=x1Range, x2Range=x2Range, size=size )
    vtk     = vtk_makeImageData( Data=gau )