├── .gitignore ├── .travis.yml ├── BUGS.txt ├── LICENSE ├── MANIFEST.in ├── NEWS.txt ├── README.md ├── README.txt ├── TODO.txt ├── doc ├── gen_pydoc.sh ├── index.html ├── vtkFileFormats2.3.pdf └── vtkFileFormats4.2.pdf ├── examples ├── example1.py ├── example2.py ├── example3.py └── unstructured.py ├── pyvtk ├── ColorScalars.py ├── Data.py ├── DataSet.py ├── DataSetAttr.py ├── Field.py ├── LookupTable.py ├── Normals.py ├── PolyData.py ├── RectilinearGrid.py ├── Scalars.py ├── StructuredGrid.py ├── StructuredPoints.py ├── Tensors.py ├── TextureCoordinates.py ├── UnstructuredGrid.py ├── Vectors.py ├── __init__.py ├── __version__.py └── common.py ├── setup.py └── test ├── input ├── example1.vtk ├── example1b.vtk ├── example2.vtk ├── example2b.vtk ├── example2f_rg.vtk ├── example2f_sg.vtk ├── example2f_sp.vtk ├── example2f_usg.vtk ├── example3.vtk └── example3b.vtk └── test_pyvtk.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | test/output 3 | build 4 | .ackrc 5 | dist 6 | MANIFEST 7 | examples/*.vtk 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | language: python 5 | 6 | python: 7 | - "3.5" 8 | - "3.4" 9 | - "2.7" 10 | 11 | install: 12 | - pip install . 13 | 14 | script: 15 | - cd test 16 | - python test_pyvtk.py 17 | -------------------------------------------------------------------------------- /BUGS.txt: -------------------------------------------------------------------------------- 1 | 2 | * numpy matrix objects confuses common.is_sequence() functions. 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2001-2017, Pearu Peterson 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include examples *.py 2 | recursive-include pyvtk *.py 3 | include doc/*.html 4 | include BUGS.txt 5 | include TODO.txt 6 | include NEWS.txt 7 | include MANIFEST.in 8 | -------------------------------------------------------------------------------- /NEWS.txt: -------------------------------------------------------------------------------- 1 | 2 | 0.5.14 (20 March, 2016) 3 | * Added Python 3 support (thanks to Thomas Kluyver). 4 | * Maintain the package (thanks to Thomas Kluyver and David Froger). 5 | * Development is moved under Github. 6 | 7 | 0.4.85 (23 July 2014) 8 | * Fixed Bug#401063: python-pyvtk in Debian (note from Steve M. Robbins). 9 | * Fixed numpy scalar testing (thanks to Andrew Straw, David M. Cooke). 10 | * Added numpy array support (thanks to Norbert Nemec). 11 | * Support for different types of Numeric arrays. 12 | * Fixed missing `import common` in Tensors.py. 13 | * Updated vtk file formats link. 14 | * Added MANIFEST.in to MANIFEST.in; 15 | disabled print statements (feature request: Konrad Hinsen) 16 | * Fixed binary writer for UnstructuredGrid. 17 | * Fixed 256 characters limit bug in header of VTK file (bug report and 18 | fix: Steve M. Robbins) 19 | * Fixed interruption of a `while 1: ..` cycle in PolyData.py 20 | * Fixed writing binary files (bug report and fix: Hans Fangohr) 21 | * Support for Python 1.5, 2.0 is dropped until one asks for it. 22 | * Implemented .append(). 23 | * .get_points() returns sequence of 3-tuples of points. 24 | * Introduced .() for constructing VTK data 25 | from VTK data structure. 26 | * Implemented VTK data reader from a file with ASCII format. 27 | Usage: VtkData(, only_structure = 0) 28 | * Finished documentation strings of relevant classes/methods. 29 | * `No data' gives warning (was ValueError). 30 | 31 | 0.3 (21 May 2001) 32 | * First public release. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PyVTK provides the following tools for manipulating Visualization Toolkit (VTK) files in Python: 2 | 3 | > VtkData --- Create VTK file from Python objects. It fully supports VTK File Formats Standard 2.0 (see also VTK File Formats Standard 3.0). The features include: 4 | * ascii and binary output, ascii input from VTK file 5 | * DataSet formats: StructuredPoints, StructuredGrid, RectilinearGrid, PolyData, UnstructuredGrid 6 | * Data formats: PointData, CellData 7 | * DataSetAttr formats: Scalars, ColorScalars, LookupTable, Vectors, Normals, TextureCoordinates, Tensors, Field 8 | 9 | The latest release of PyVTK source distribution can be downloaded from 10 | https://pypi.python.org/pypi/PyVTK 11 | 12 | To install PyVTK, run 13 | ``` 14 | pip install pyvtk 15 | ``` -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | 2 | PyVTK 3 | "Collection of tools for manipulating VTK files in Python" 4 | by 5 | Pearu Peterson 6 | 7 | https://github.com/pearu/pyvtk 8 | 9 | INTRODUCTION 10 | ------------ 11 | 12 | PyVTK provides tools for manipulating VTK files in Python: 13 | 14 | VtkData - Create VTK file from Python objects. It fully 15 | supports VTK File Formats Standard 2.0. The features 16 | includes: 17 | *** ascii and binary output, ascii input 18 | *** DataSet formats: 19 | StructuredPoints, StructuredGrid, RectilinearGrid, 20 | PolyData, UnstructuredGrid 21 | *** Data formats: 22 | PointData, CellData 23 | *** DataSetAttr formats: 24 | Scalars, ColorScalars, LookupTable, Vectors, 25 | Normals, TextureCoordinates, Tensors, Field 26 | 27 | LICENSE 28 | ------- 29 | 30 | New BSD 31 | 32 | REQUIREMENTS 33 | ------------ 34 | 35 | Python - pyvtk is developed under Python 2.1. Currently, it is 36 | tested to work under Python 2.7 and Python 3.x. 37 | 38 | BUILDING and INSTALLING 39 | ----------------------- 40 | 41 | The preferred installation method is to use Python Index: 42 | 43 | pip install --upgrade pyvtk 44 | 45 | USAGE 46 | ----- 47 | >>> import pyvtk 48 | 49 | To learn how to use pyvtk.VtkData, see examples in examples/ directory. 50 | For reference, execute 51 | 52 | pydoc pyvtk.VtkData 53 | 54 | or in Python: 55 | 56 | >>> from pydoc import help 57 | >>> help(pyvtk.VtkData) 58 | 59 | TESTING 60 | ------- 61 | 62 | cd test 63 | python test_pyvtk.py 64 | 65 | To test files under development, install in 'editable' mode: 66 | 67 | pip install -e . 68 | 69 | --- Pearu Peterson, March 20, 2016 70 | 71 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | * April 7, 2003 2 | Implement vtk File Formats 3.0 support 3 | 4 | * May 31, 2001: 5 | Need more efficient VTK data reader. 6 | 7 | * May 21, 2001: 8 | Get binary output working [DONE. Thanks to Hans Fangohr]. 9 | Document relevant classes and relevant methods [DONE]. 10 | Figure out how to use the SCALARS numComp flag and implement its support. 11 | More tests and examples ... 12 | -------------------------------------------------------------------------------- /doc/gen_pydoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pydoc -w pyvtk pyvtk.VtkData pyvtk.StructuredGrid pyvtk.StructuredPoints pyvtk.UnstructuredGrid pyvtk.RectilinearGrid pyvtk.PolyData pyvtk.PointData pyvtk.CellData pyvtk.Scalars pyvtk.ColorScalars pyvtk.LookupTable pyvtk.Vectors pyvtk.Normals pyvtk.TextureCoordinates pyvtk.Tensors pyvtk.Field 4 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | PyVTK - Manipulate VTK files in Python 8 | 9 | 10 | 11 | 12 | 13 |

PyVTK ­ Tools for manipulating VTK files in Python

14 | by Pearu Peterson 15 | 16 |

What's new?

17 | 18 |
19 |
0.4.74 (Feb 22, 2007) 20 |
Minor bug fixes. 21 |
0.4.71 (May 18, 2006) 22 |
Added numpy support. Bug fixes. 23 |
0.4.66 (January 26, 2003) 24 |
Fixed binary write of UnstructuredGrid. 25 |
0.4.62 (November 19, 2002) 26 |
Minor fixes. 27 |
0.4 (September 2, 2002) 28 |
Writing binary files works (thanks to Hans Fangohr). 29 |
0.4 (June 8, 2001) 30 |
VTK files reader (only for Python 2.x). Usage: VtkData(filename) 31 |
0.3 (May 21, 2001) 32 |
First release. 33 |
34 | 35 | 36 |

Introduction

37 | 38 |

39 | PyVTK provides the following tools for manipulating Visualization Toolkit (VTK) files in Python: 41 | 42 |

43 |
VtkData 44 |
Create VTK file from Python objects. It fully 45 | supports VTK 46 | File Formats Standard 2.0 47 | (see also VTK 48 | File Formats Standard 3.0). 49 | The features include: 50 |
    51 |
  • ascii and binary output, ascii input from VTK file 52 |
  • DataSet formats: 53 | StructuredPoints, StructuredGrid, RectilinearGrid, 54 | PolyData, UnstructuredGrid 55 |
  • Data formats: 56 | PointData, CellData 57 |
  • DataSetAttr formats: 58 | Scalars, ColorScalars, LookupTable, Vectors, 59 | Normals, TextureCoordinates, Tensors, Field 60 |
61 |
62 | 63 |

Related software

64 |
    65 |
  • MayaVi - free, easy 66 | to use scientific data visualizer, written in Python by Prabhu 67 | Ramachandran. 68 |
69 | 70 | 71 |

Requirements

72 |
    73 |
  1. Python (PyVTK is developed under Python 2.1, but it is tested to work also with Python 1.5.2 and 2.0) 74 |
75 | 76 |

Download

77 | 78 |
79 |
Snapshots of release: 80 |
rel-0.x/PyVTK-0.latest.tar.gz 81 |
82 | 83 |

Installation

84 | 85 |

86 | To install PyVTK, unpack the source file, change to directory PyVTK-?.?.? and 87 | run python setup.py install, or make install if under Python 1.x. 88 | 89 |

CVS Repository

90 | 91 | PyVTK is being developed under 92 | CVS and those who are 93 | interested in the latest version of PyVTK (possibly 94 | unstable) can get it from the repository as follows: 95 |
    96 |
  1. First you need to login (the password is guest): 97 |
     98 | > cvs -d :pserver:anonymous@cens.ioc.ee:/home/cvs login
     99 | 
    100 |
  2. and then do the checkout: 101 |
    102 | > cvs -z6 -d :pserver:anonymous@cens.ioc.ee:/home/cvs checkout python/pyvtk
    103 | 
    104 |
  3. In the directory pyvtk you can get the updates by hitting 105 |
    106 | > cvs -z6 update -P -d
    107 | 
    108 |
109 | You can browse PyVTK CVS repository here. 110 | 111 | 112 |
113 |
114 | Pearu Peterson 115 | <pearu@cens.ioc.ee>
116 | 117 | Last modified: Fri May 18 16:44:25 EET 2006 118 | 119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /doc/vtkFileFormats2.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pearu/pyvtk/88931a72c954dda7a7d1d4a1e606d0c47cc834a7/doc/vtkFileFormats2.3.pdf -------------------------------------------------------------------------------- /doc/vtkFileFormats4.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pearu/pyvtk/88931a72c954dda7a7d1d4a1e606d0c47cc834a7/doc/vtkFileFormats4.2.pdf -------------------------------------------------------------------------------- /examples/example1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path = ['..']+sys.path 5 | 6 | from pyvtk import * 7 | 8 | structure = PolyData(points=[[0,0,0],[1,0,0],[1,1,0],[0,1,0], 9 | [0,0,1],[1,0,1],[1,1,1],[0,1,1]], 10 | polygons=[[0,1,2,3],[4,5,6,7],[0,1,5,4], 11 | [2,3,7,6],[0,4,7,3],[1,2,6,5]]) 12 | pointdata = PointData(\ 13 | Scalars([0,1,2,3,4,5,6,7], 14 | name='sample_scalars', 15 | lookup_table='my_table'), 16 | LookupTable([[0,0,0,1],[1,0,0,1],[0,1,0,1],[1,1,0,1], 17 | [0,0,1,1],[1,0,1,1],[0,1,1,1],[1,1,1,1]], 18 | name='my_table')) 19 | 20 | celldata = CellData(\ 21 | Scalars([0,1,2,3,4,5], 22 | name='cell_scalars'), 23 | Normals([[0,0,-1],[0,0,1],[0,-1,0], 24 | [0,1,0],[-1,0,0],[1,0,0]], 25 | name='cell_normals'), 26 | Field('FieldData', 27 | cellIds=[[0],[1],[2],[3],[4],[5]], 28 | faceAttributes=[[0,1],[1,2],[2,3],[3,4],[4,5],[5,6]])) 29 | 30 | vtk = VtkData(structure,pointdata,celldata) 31 | vtk.tofile('example1','ascii') 32 | vtk.tofile('example1b','binary') 33 | 34 | vtk2 = VtkData('example1') 35 | -------------------------------------------------------------------------------- /examples/example2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path = ['..']+sys.path 5 | 6 | from pyvtk import * 7 | 8 | vtk = VtkData(StructuredPoints([3,4,6]), 9 | PointData(Scalars([0,0,0,0,0,0,0,0,0,0,0,0, 10 | 0,5,10,15,20,25,25,20,15,10,5,0, 11 | 0,10,20,30,40,50,50,40,30,20,10,0, 12 | 0,10,20,30,40,50,50,40,30,20,10,0, 13 | 0,5,10,15,20,25,25,20,15,10,5,0, 14 | 0,0,0,0,0,0,0,0,0,0,0,0 15 | ]))) 16 | 17 | vtk.tofile('example2') 18 | vtk.tofile('example2b','binary') 19 | 20 | vtk = VtkData('example2',only_structure = 1) 21 | def f(x,y,z): 22 | return x*y*z 23 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 24 | vtk.tofile('example2f_sp') 25 | 26 | pp = [(i,j,k) for k in range(6) for j in range(4) for i in range(3)] 27 | vtk = VtkData(StructuredGrid([3,4,6],pp)) 28 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 29 | vtk.tofile('example2f_sg') 30 | 31 | vtk = VtkData(RectilinearGrid(range(3),range(4),range(6))) 32 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 33 | vtk.tofile('example2f_rg') 34 | 35 | voxels = [] 36 | points = [] 37 | n = 0 38 | for k in range(6): 39 | for j in range(4): 40 | for i in range(3): 41 | points.append((i,j,k)) 42 | if not (k==5 or j==3 or i==2): 43 | voxels.append([n,n+1,n+3,n+3+1,n+3*4,n+3*4+1,n+3*4+3,n+3*4+3+1]) 44 | n += 1 45 | vtk = VtkData(UnstructuredGrid(points,voxel=voxels)) 46 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 47 | vtk.tofile('example2f_usg') 48 | -------------------------------------------------------------------------------- /examples/example3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path = ['..']+sys.path 5 | 6 | from pyvtk import * 7 | 8 | points = [[0,0,0],[1,0,0],[2,0,0],[0,1,0],[1,1,0],[2,1,0], 9 | [0,0,1],[1,0,1],[2,0,1],[0,1,1],[1,1,1],[2,1,1], 10 | [0,1,2],[1,1,2],[2,1,2],[0,1,3],[1,1,3],[2,1,3], 11 | [0,1,4],[1,1,4],[2,1,4],[0,1,5],[1,1,5],[2,1,5], 12 | [0,1,6],[1,1,6],[2,1,6] 13 | ] 14 | vectors = [[1,0,0],[1,1,0],[0,2,0],[1,0,0],[1,1,0],[0,2,0], 15 | [1,0,0],[1,1,0],[0,2,0],[1,0,0],[1,1,0],[0,2,0], 16 | [0,0,1],[0,0,1],[0,0,1],[0,0,1],[0,0,1],[0,0,1], 17 | [0,0,1],[0,0,1],[0,0,1],[0,0,1],[0,0,1],[0,0,1], 18 | [0,0,1],[0,0,1],[0,0,1] 19 | ] 20 | vtk = VtkData(\ 21 | UnstructuredGrid(points, 22 | hexahedron=[[0,1,4,3,6,7,10,9], 23 | [1,2,5,4,7,8,11,10]], 24 | tetra=[[6,10,9,12], 25 | [5,11,10,14]], 26 | polygon=[15,16,17,14,13,12], 27 | triangle_strip=[18,15,19,16,20,17], 28 | quad=[22,23,20,19], 29 | triangle=[[21,22,18], 30 | [22,19,18]], 31 | line=[26,25], 32 | vertex=[24] 33 | ), 34 | PointData(Vectors(vectors),Scalars(range(27))), 35 | 'Unstructured Grid Example' 36 | ) 37 | vtk.tofile('example3') 38 | vtk.tofile('example3b','binary') 39 | 40 | VtkData('example3') 41 | -------------------------------------------------------------------------------- /examples/unstructured.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Test example to generate 2D (embedded in 3D) and 3D Delaunay triangulations that output to VTK 4 | 5 | import pyvtk 6 | import numpy as np 7 | from scipy.spatial import Delaunay 8 | 9 | # Generate the random points 10 | npoints = 1000 11 | np.random.seed(1) 12 | x = np.random.normal(size=npoints)*np.pi 13 | y = np.random.normal(size=npoints)*np.pi 14 | z = np.sin((x))+np.cos((y)) 15 | # Generate random data 16 | pointPressure = np.random.rand(npoints) 17 | 18 | # Compute the 2D Delaunay triangulation in the x-y plane 19 | xTmp=list(zip(x,y)) 20 | tri=Delaunay(xTmp) 21 | 22 | # Generate Cell Data 23 | nCells=tri.nsimplex 24 | cellTemp=np.random.rand(nCells) 25 | 26 | # Zip the point co-ordinates for the VtkData input 27 | points=list(zip(x,y,z)) 28 | 29 | vtk = pyvtk.VtkData(\ 30 | pyvtk.UnstructuredGrid(points, 31 | triangle=tri.simplices 32 | ), 33 | pyvtk.PointData(pyvtk.Scalars(pointPressure,name='Pressure')), 34 | pyvtk.CellData(pyvtk.Scalars(cellTemp,name='Temperature')), 35 | '2D Delaunay Example' 36 | ) 37 | vtk.tofile('Delaunay2D') 38 | vtk.tofile('Delaunay2Db','binary') 39 | 40 | # Compute the 3D Delaunay triangulation in the x-y plane 41 | xTmp=list(zip(x,y,z)) 42 | tri=Delaunay(xTmp) 43 | 44 | # Generate Cell Data 45 | nCells=tri.nsimplex 46 | cellTemp=np.random.rand(nCells) 47 | 48 | # Zip the point co-ordinates for the VtkData input 49 | points=list(zip(x,y,z)) 50 | 51 | vtk = pyvtk.VtkData(\ 52 | pyvtk.UnstructuredGrid(points, 53 | tetra=tri.simplices 54 | ), 55 | pyvtk.PointData(pyvtk.Scalars(pointPressure,name='Pressure')), 56 | pyvtk.CellData(pyvtk.Scalars(cellTemp,name='Temperature')), 57 | '3D Delaunay Example' 58 | ) 59 | vtk.tofile('Delaunay3D') 60 | vtk.tofile('Delaunay3Db','binary') 61 | -------------------------------------------------------------------------------- /pyvtk/ColorScalars.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | ColorScalars 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.common as common 9 | import pyvtk.DataSetAttr as DataSetAttr 10 | 11 | class ColorScalars(DataSetAttr.DataSetAttr): 12 | """Holds VTK color scalars. 13 | Usage: 14 | ColorScalars( ,name = ) 15 | Attributes: 16 | scalars 17 | name 18 | Public methods: 19 | get_size() 20 | to_string(format = 'ascii') 21 | """ 22 | def __init__(self,scalars,name=None): 23 | self.name = self._get_name(name) 24 | self.scalars = self.get_n_seq_seq(scalars,self.default_value) 25 | def to_string(self,format='ascii'): 26 | ret = ['COLOR_SCALARS %s %s'%(self.name,len(self.scalars[0]))] 27 | seq = self.scalars 28 | if format=='binary': 29 | if not common.is_int255(seq): 30 | seq = self.float01_to_int255(seq) 31 | ret.append(self.seq_to_string(seq,format,'unsigned char')) 32 | else: 33 | if not common.is_float01(seq): 34 | seq = self.int255_to_float01(seq) 35 | ret.append(self.seq_to_string(seq,format,'float')) 36 | return '\n'.join(ret) 37 | def get_size(self): 38 | return len(self.scalars) 39 | 40 | def color_scalars_fromfile(f,n,sl): 41 | assert len(sl)==2 42 | dataname = sl[0].strip() 43 | nvals = int(sl[1]) 44 | scalars = [] 45 | while len(scalars)) 53 | Attributes: 54 | data - list of DataSetAttr instances 55 | Public methods: 56 | get_size() 57 | to_string(format = 'ascii') 58 | append() 59 | """ 60 | data_type = 'POINT_DATA' 61 | 62 | class CellData(Data): 63 | """ 64 | Usage: 65 | CellData() 66 | Attributes: 67 | data - list of DataSetAttr instances 68 | Public methods: 69 | get_size() 70 | to_string(format = 'ascii') 71 | append() 72 | """ 73 | data_type = 'CELL_DATA' 74 | 75 | def is_pointdata(obj): 76 | return isinstance(obj,PointData) 77 | def is_celldata(obj): 78 | return isinstance(obj,CellData) 79 | 80 | if __name__ == "__main__": 81 | print(PointData(Scalars.Scalars([2,3]))) 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /pyvtk/DataSet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | DataSet 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | __version__ = "$Id: DataSet.py,v 1.3 2001/05/31 17:48:54 pearu Exp $" 12 | 13 | from functools import reduce 14 | 15 | import pyvtk.common as common 16 | import pyvtk.Scalars as Scalars 17 | import pyvtk.ColorScalars as ColorScalars 18 | import pyvtk.LookupTable as LookupTable 19 | import pyvtk.Vectors as Vectors 20 | import pyvtk.Normals as Normals 21 | import pyvtk.TextureCoordinates as TextureCoordinates 22 | import pyvtk.Tensors as Tensors 23 | import pyvtk.Field as Field 24 | 25 | from numpy import issubdtype,integer 26 | 27 | class DataSet(common.Common): 28 | """Abstract class. 29 | It describes the geometry and topology of VTK dataset. 30 | """ 31 | def get_size(self): 32 | if hasattr(self,'points'): 33 | return len(self.points) 34 | return reduce(lambda x,y:x*y,self.dimensions,1) 35 | def get_cell_size(self): 36 | return 0 37 | def _check_dimensions(self): 38 | for i in range(3): 39 | d = self.dimensions[i] 40 | if not common.is_int(d): 41 | log.error('dimensions[%s] must be int but got %s'%(i,type(d))) 42 | return 1 43 | if d<=0: 44 | log.error('dimensions[%s] must be positive int but got %s'%(i,d)) 45 | return 1 46 | if hasattr(self,'points'): 47 | d = reduce(lambda x,y:x*y,self.dimensions,1) 48 | if len(self.points)!=d: 49 | log.error('mismatch of points length (%s) and dimensions size (%s)'%(len(self.points),d)) 50 | return 1 51 | return 0 52 | def _check_origin(self): 53 | for i in range(3): 54 | d = self.origin[i] 55 | if not common.is_number(d): 56 | log.error('origin[%s] must be number but got %s'%(i,type(d))) 57 | return 1 58 | return 0 59 | def _check_spacing(self): 60 | for i in range(3): 61 | d = self.spacing[i] 62 | if not common.is_number(d): 63 | log.error('spacing[%s] must be number but got %s'%(i,type(d))) 64 | return 1 65 | if d<=0: 66 | log.error('spacing[%s] must be positive number but got %s'%(i,d)) 67 | return 1 68 | return 0 69 | def _check_int_seq(self,obj,mx_int): 70 | if (hasattr(obj,'dtype')): 71 | if issubdtype(obj.dtype,integer): 72 | return 1 if obj.max() >= mx_int else 0 73 | if common.is_sequence(obj): 74 | for o in obj: 75 | if self._check_int_seq(o,mx_int): 76 | return 1 77 | elif not common.is_int(obj) or obj>=mx_int: 78 | return 1 79 | return 0 80 | 81 | def Scalars(self,func,name = None,lookup_table = None): 82 | return Scalars.Scalars([func(*p) for p in self.get_points()],name,lookup_table) 83 | def ColorScalars(self,func,name = None): 84 | return ColorScalars.ColorScalars([func(*p) for p in self.get_points()],name) 85 | def LookupTable(self,func,name = None): 86 | return LookupTable.LookupTable([func(*p) for p in self.get_points()],name) 87 | def Vectors(self,func,name = None): 88 | return Vectors.Vectors([func(*p) for p in self.get_points()],name) 89 | def Normals(self,func,name = None): 90 | return Normals.Normals([func(*p) for p in self.get_points()],name) 91 | def TextureCoordinates(self,func,name = None): 92 | return TextureCoordinates.TextureCoordinates([func(*p) for p in self.get_points()],name) 93 | def Tensors(self,func,name = None): 94 | return Tensors.Tensors([func(*p) for p in self.get_points()],name) 95 | def Field(self,func,name = None, **kws): 96 | return Field.Field([func(*p) for p in self.get_points()],name, **kws) 97 | 98 | def is_dataset(obj): 99 | return isinstance(obj,DataSet) 100 | -------------------------------------------------------------------------------- /pyvtk/DataSetAttr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | DataSetAttr 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | import pyvtk.common as common 12 | 13 | class DataSetAttr(common.Common): 14 | """Abstract class for VTK data.""" 15 | counters = {} 16 | default_value = 0 17 | def _get_default_name(self): 18 | n = self.__class__.__name__ 19 | try: 20 | self.counters[n] += 1 21 | except KeyError: 22 | self.counters[n] = 0 23 | return self.__class__.__name__+str(self.counters[n]) 24 | 25 | def _get_name(self,name): 26 | if name is None: 27 | name = self._get_default_name() 28 | log.info('Using default name=%s'%(repr(name))) 29 | return name 30 | if common.is_string(name): 31 | name = name.strip().replace(' ','_') 32 | if name: 33 | return name 34 | raise ValueError('name=%s must be non-empty string'%(repr(name))) 35 | 36 | def _get_lookup_table(self,name): 37 | if name is None: 38 | name = 'default' 39 | log.info('Using default lookup_table=%s'%(repr(name))) 40 | return name 41 | if common.is_string(name): 42 | name = name.strip().replace(' ','_') 43 | if name: 44 | return name 45 | raise ValueError('lookup_table=%s must be nonempty string'%(repr(name))) 46 | 47 | def is_datasetattr(obj): 48 | return isinstance(obj,DataSetAttr) 49 | 50 | if __name__ == "__main__": 51 | pass 52 | -------------------------------------------------------------------------------- /pyvtk/Field.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Field 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | import pyvtk.DataSetAttr as DataSetAttr 12 | import pyvtk.common as common 13 | 14 | class Field(DataSetAttr.DataSetAttr): 15 | """Holds VTK Field. 16 | Usage: 17 | Field([,] arrname_1=, ..., 18 | arrname_k=) 19 | 20 | Attributes: 21 | data - dictionary of arrays 22 | name 23 | Public methods: 24 | get_size() 25 | to_string(format = 'ascii') 26 | """ 27 | def __init__(self,*args,**kws): 28 | if len(args): name = args[0] 29 | else: name = None 30 | if len(args)>1: 31 | log.warning('Ignoring all arguments except the first') 32 | self.name = self._get_name(name) 33 | data = {} 34 | mx = 0 35 | for k,v in kws.items(): 36 | data[k] = self.get_n_seq_seq(v,self.default_value) 37 | mx = max([len(l) for l in data.values()]) 38 | for k,v in data.items(): 39 | if len(v) ,name = ) 15 | Attributes: 16 | table 17 | name 18 | Public methods: 19 | get_size() 20 | to_string(format = 'ascii') 21 | """ 22 | def __init__(self,table,name=None): 23 | self.name = self._get_name(name) 24 | self.table = self.get_n_seq_seq(table,[0,0,0,0]) 25 | if len(self.table[0])!=4: 26 | raise ValueError('expected sequence of 4-sequences but got %s'%(len(self.table[0]))) 27 | 28 | def to_string(self, format='ascii'): 29 | ret = [('LOOKUP_TABLE %s %s'%(self.name,len(self.table))).encode()] 30 | seq = self.table 31 | if format=='binary': 32 | if not common.is_int255(seq): 33 | seq = self.float01_to_int255(seq) 34 | ret.append(self.seq_to_string(seq,format,'unsigned char')) 35 | else: 36 | if not common.is_float01(seq): 37 | seq = self.int255_to_float01(seq) 38 | ret.append(self.seq_to_string(seq,format,'float')) 39 | return b'\n'.join(ret) 40 | 41 | def get_size(self): 42 | return len(self.table) 43 | 44 | def lookup_table_fromfile(f,n,sl): 45 | tablename = sl[0] 46 | size = int(sl[1]) 47 | table = [] 48 | while len(table)<4*size: 49 | table += map(eval, common._getline(f).decode('ascii').split(' ')) 50 | assert len(table) == 4*size 51 | table2 = [] 52 | for i in range(0,len(table),4): 53 | table2.append(table[i:i+4]) 54 | return LookupTable(table2,tablename) 55 | 56 | if __name__ == "__main__": 57 | print(LookupTable([[3,3],[4,3],240,3,2]).to_string()) 58 | -------------------------------------------------------------------------------- /pyvtk/Normals.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Normals 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | import math 12 | 13 | import pyvtk.DataSetAttr as DataSetAttr 14 | import pyvtk.common as common 15 | 16 | class Normals(DataSetAttr.DataSetAttr): 17 | """Holds VTK Normals. 18 | Usage: 19 | Normals( ,name = ) 20 | Attributes: 21 | normals 22 | name 23 | Public methods: 24 | get_size() 25 | to_string(format = 'ascii') 26 | """ 27 | def __init__(self,normals,name=None): 28 | self.name = self._get_name(name) 29 | seq = [] 30 | for v in self.get_3_tuple_list(normals,(self.default_value,)*3): 31 | n = math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]) 32 | if n==0: 33 | log.warning('cannot normalize zero vector') 34 | seq.append(v) 35 | elif n==1: 36 | seq.append(v) 37 | else: 38 | seq.append(tuple([c/n for c in v])) 39 | self.normals = seq 40 | 41 | def to_string(self,format='ascii'): 42 | t = self.get_datatype(self.normals) 43 | ret = [('NORMALS %s %s'%(self.name,t)).encode(), 44 | self.seq_to_string(self.normals,format,t)] 45 | return b'\n'.join(ret) 46 | 47 | def get_size(self): 48 | return len(self.normals) 49 | 50 | def normals_fromfile(f,n,sl): 51 | dataname = sl[0] 52 | datatype = sl[1].lower() 53 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 54 | normals = [] 55 | while len(normals) < 3*n: 56 | normals += map(eval,common._getline(f).decode('ascii').split(' ')) 57 | assert len(normals) == 3*n 58 | return Normals(normals,dataname) 59 | 60 | if __name__ == "__main__": 61 | print(Normals([[3,3],[4,3.],240,3,2]).to_string()) 62 | -------------------------------------------------------------------------------- /pyvtk/PolyData.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | PolyData 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | import pyvtk.DataSet as DataSet 12 | import pyvtk.common as common 13 | 14 | class PolyData(DataSet.DataSet): 15 | """ 16 | Usage: 17 | PolyData(, 18 | vertices = 19 | lines = , 20 | polygons = 21 | triangle_strips = , 22 | ) 23 | Attributes: 24 | points 25 | vertices 26 | lines 27 | polygons 28 | triangle_strips 29 | Public methods: 30 | get_size() 31 | get_cell_size() 32 | to_string(format = 'ascii') 33 | get_points() 34 | (...) 35 | """ 36 | 37 | def __init__(self,points, 38 | vertices=[],lines=[],polygons=[],triangle_strips=[]): 39 | self.points = self.get_3_tuple_list(points,(0,0,0)) 40 | self.vertices = self.get_seq_seq(vertices,[]) 41 | self.lines = self.get_seq_seq(lines,[]) 42 | self.polygons = self.get_seq_seq(polygons,[]) 43 | self.triangle_strips = self.get_seq_seq(triangle_strips,[]) 44 | sz = len(self.points) 45 | for k in ['vertices','lines','polygons','triangle_strips']: 46 | if self._check_int_seq(getattr(self,k),sz): 47 | raise ValueError('%s must be (seq of seq|seq) integers less than %s'%(k,sz)) 48 | 49 | def to_string(self, format='ascii'): 50 | t = self.get_datatype(self.points) 51 | ret = [b'DATASET POLYDATA', 52 | ('POINTS %s %s'%(self.get_size(),t)).encode(), 53 | self.seq_to_string(self.points,format,t)] 54 | for k in ['vertices','lines','polygons','triangle_strips']: 55 | kv = getattr(self,k) 56 | if kv==[] or kv[0]==[]: continue 57 | sz = self._get_nof_objs(kv)+len(kv) 58 | ret += [('%s %s %s'%(k.upper(),len(kv),sz)).encode(), 59 | self.seq_to_string([[len(v)]+list(v) for v in kv],format,'int')] 60 | return b'\n'.join(ret) 61 | 62 | def get_cell_size(self): 63 | sz = 0 64 | for k in ['vertices','lines','polygons','triangle_strips']: 65 | kv = getattr(self,k) 66 | if kv==[] or kv[0]==[]: continue 67 | sz += len(kv) 68 | return sz 69 | 70 | def get_points(self): 71 | return self.points 72 | 73 | def polydata_fromfile(f, self): 74 | """Use VtkData().""" 75 | points = [] 76 | data = dict(vertices=[], lines=[], polygons=[], triangle_strips=[]) 77 | l = common._getline(f).decode('ascii') 78 | k,n,datatype = [s.strip().lower() for s in l.split(' ')] 79 | if k!='points': 80 | raise ValueError('expected points but got %s'%(repr(k))) 81 | n = int(n) 82 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 83 | 84 | log.debug('\tgetting %s points'%n) 85 | while len(points) < 3*n: 86 | l = common._getline(f).decode('ascii') 87 | points += map(eval,l.split(' ')) 88 | assert len(points)==3*n 89 | while 1: 90 | l = common._getline(f) 91 | if l is None: 92 | break 93 | l = l.decode('ascii') 94 | sl = l.split(' ') 95 | k = sl[0].strip().lower() 96 | if k not in ['vertices','lines','polygons','triangle_strips']: 97 | break 98 | assert len(sl)==3 99 | n = int(sl[1]) 100 | size = int(sl[2]) 101 | lst = [] 102 | while len(lst) < size: 103 | l = common._getline(f).decode('ascii') 104 | lst += map(eval, l.split(' ')) 105 | assert len(lst)==size 106 | lst2 = [] 107 | j = 0 108 | for i in range(n): 109 | lst2.append(lst[j+1:j+lst[j]+1]) 110 | j += lst[j]+1 111 | data[k] = lst2 112 | 113 | return PolyData(points,data['vertices'], data['lines'], data['polygons'], data['triangle_strips']), l.encode() 114 | 115 | if __name__ == "__main__": 116 | print(PolyData([[1,2],[2,4],4,5.4],[[1],[0]],[],[1,2,3])) 117 | -------------------------------------------------------------------------------- /pyvtk/RectilinearGrid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | RectilinearGrid 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSet as DataSet 9 | import pyvtk.common as common 10 | 11 | class RectilinearGrid(DataSet.DataSet): 12 | """ 13 | Usage: 14 | RectilinearGrid(x = , y = , z = ) 15 | Attributes: 16 | x 17 | y 18 | z 19 | dimensions 20 | Public methods: 21 | get_size() 22 | get_cell_size() 23 | to_string(format = 'ascii') 24 | get_points() 25 | (...) 26 | """ 27 | 28 | def __init__(self,x=None,y=None,z=None): 29 | self.x = self.get_seq(x,[0]) 30 | self.y = self.get_seq(y,[0]) 31 | self.z = self.get_seq(z,[0]) 32 | self.dimensions = (len(self.x),len(self.y),len(self.z)) 33 | if self._check_dimensions(): 34 | raise ValueError('dimensions must be 3-tuple of ints >=1') 35 | 36 | def to_string(self, format='ascii'): 37 | tx = self.get_datatype(self.x) 38 | ty = self.get_datatype(self.y) 39 | tz = self.get_datatype(self.z) 40 | ret = [b'DATASET RECTILINEAR_GRID', 41 | ('DIMENSIONS %s %s %s'%self.dimensions).encode(), 42 | ('X_COORDINATES %s %s'%(len(self.x),tx)).encode(), 43 | self.seq_to_string(self.x,format,tx), 44 | ('Y_COORDINATES %s %s'%(len(self.y),ty)).encode(), 45 | self.seq_to_string(self.y,format,ty), 46 | ('Z_COORDINATES %s %s'%(len(self.z),tz)).encode(), 47 | self.seq_to_string(self.z,format,tz)] 48 | return b'\n'.join(ret) 49 | 50 | def get_points(self): 51 | if hasattr(self,'points'): 52 | return self.points 53 | arr = [(x,y,z) for z in self.z for y in self.y for x in self.x] 54 | self.points = arr 55 | return arr 56 | 57 | def rectilinear_grid_fromfile(f,self): 58 | l = common._getline(f).decode('ascii').split(' ') 59 | assert l[0].strip().lower() == 'dimensions' 60 | dims = list(map(int, l[1:])) 61 | assert len(dims)==3 62 | coords = {} 63 | for c in 'xyz': 64 | l = common._getline(f).decode('ascii') 65 | k,n,datatype = [s.strip().lower() for s in l.split(' ')] 66 | if k!=c+'_coordinates': 67 | raise ValueError('expected %s_coordinates but got %s'%(c, repr(k))) 68 | n = int(n) 69 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 70 | points = [] 71 | while len(points) < n: 72 | points += map(eval, common._getline(f).decode('ascii').split(' ')) 73 | assert len(points)==n 74 | coords[c] = points 75 | assert list(map(len, [coords['x'], coords['y'], coords['z']])) == dims 76 | return RectilinearGrid(coords['x'], coords['y'], coords['z']),common._getline(f) 77 | 78 | if __name__ == "__main__": 79 | print(RectilinearGrid([1,2,2,4,4,5.4])) 80 | -------------------------------------------------------------------------------- /pyvtk/Scalars.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Scalars 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSetAttr as DataSetAttr 9 | import pyvtk.common as common 10 | 11 | class Scalars(DataSetAttr.DataSetAttr): 12 | """Holds VTK scalars. 13 | Usage: 14 | Scalars( ,name = , lookup_table = 'default') 15 | Attributes: 16 | scalars 17 | name 18 | lookup_table 19 | Public methods: 20 | get_size() 21 | to_string(format = 'ascii') 22 | """ 23 | def __init__(self,scalars,name=None,lookup_table=None): 24 | self.name = self._get_name(name) 25 | self.lookup_table = self._get_lookup_table(lookup_table) 26 | self.scalars = self.get_seq(scalars,[]) 27 | def to_string(self,format='ascii'): 28 | t = self.get_datatype(self.scalars) 29 | ret = [('SCALARS %s %s %s'%(self.name,t,1)).encode(), 30 | ('LOOKUP_TABLE %s'%(self.lookup_table)).encode(), 31 | self.seq_to_string(self.scalars,format,t)] 32 | return b'\n'.join(ret) 33 | def get_size(self): 34 | return len(self.scalars) 35 | 36 | def scalars_fromfile(f,n,sl): 37 | dataname = sl[0] 38 | datatype = sl[1].lower() 39 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 40 | if len(sl)>2: 41 | numcomp = int(sl[2]) 42 | else: 43 | numcomp = 1 44 | l = common._getline(f).decode('ascii') 45 | l = l.split(' ') 46 | assert len(l)==2 and l[0].lower() == 'lookup_table' 47 | tablename = l[1] 48 | scalars = [] 49 | while len(scalars) < n: 50 | scalars += map(eval,common._getline(f).decode('ascii').split(' ')) 51 | assert len(scalars)==n 52 | return Scalars(scalars,dataname,tablename) 53 | 54 | if __name__ == "__main__": 55 | print(Scalars([3,4,240]).to_string('binary')) 56 | -------------------------------------------------------------------------------- /pyvtk/StructuredGrid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | StructuredGrid 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import logging 9 | log = logging.getLogger(__name__) 10 | 11 | import pyvtk.DataSet as DataSet 12 | import pyvtk.common as common 13 | 14 | class StructuredGrid(DataSet.DataSet): 15 | """ 16 | Usage: 17 | StructuredGrid(<3-tuple of dimensions>, ) 18 | Attributes: 19 | dimensions 20 | points 21 | Public methods: 22 | get_points() 23 | get_size() 24 | get_cell_size() 25 | to_string(format = 'ascii') 26 | get_points() 27 | (...) 28 | """ 29 | 30 | def __init__(self,dimensions,points): 31 | self.dimensions = self.get_3_tuple(dimensions,(1,1,1)) 32 | self.points = self.get_3_tuple_list(points,(0,0,0)) 33 | if self._check_dimensions(): 34 | raise ValueError('dimensions must be 3-tuple of ints >=1 and matching with the size of points') 35 | 36 | def to_string(self, format='ascii'): 37 | t = self.get_datatype(self.points) 38 | ret = [b'DATASET STRUCTURED_GRID', 39 | ('DIMENSIONS %s %s %s'%self.dimensions).encode(), 40 | ('POINTS %s %s'%(self.get_size(),t)).encode(), 41 | self.seq_to_string(self.points,format,t)] 42 | return b'\n'.join(ret) 43 | 44 | def get_points(self): 45 | return self.points 46 | 47 | def get_cell_size(self): 48 | return len(self.points) 49 | 50 | def structured_grid_fromfile(f,self): 51 | l = common._getline(f).split(' ') 52 | assert l[0].strip().lower() == 'dimensions' 53 | dims = list(map(int, l[1:])) 54 | assert len(dims)==3 55 | l = common._getline(f) 56 | k,n,datatype = [s.strip().lower() for s in l.split(' ')] 57 | if k!='points': 58 | raise ValueError( 'expected points but got %s'%(repr(k))) 59 | n = int(n) 60 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 61 | points = [] 62 | log.debug('\tgetting %s points'%n) 63 | while len(points) < 3*n: 64 | l = common._getline(f) 65 | points += map(eval,l.split(' ')) 66 | assert len(points)==3*n 67 | return StructuredGrid(dims,points),common._getline(f) 68 | 69 | if __name__ == "__main__": 70 | print(StructuredGrid((1,2),[1,2,2,4,4,5.4])) 71 | -------------------------------------------------------------------------------- /pyvtk/StructuredPoints.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | StructuredPoints 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSet as DataSet 9 | import pyvtk.common as common 10 | 11 | class StructuredPoints(DataSet.DataSet): 12 | """ 13 | Usage: 14 | StructuredPoints(<3-tuple of dimensions>, origin = <3-tuple>, spacing = <3-tuple>) 15 | Attributes: 16 | dimensions 17 | origin 18 | spacing 19 | Public methods: 20 | get_size() 21 | get_cell_size() 22 | to_string(format = 'ascii') 23 | get_points() 24 | (...) 25 | """ 26 | 27 | def __init__(self,dimensions,origin=(0,0,0),spacing=(1,1,1)): 28 | self.dimensions = self.get_3_tuple(dimensions,(1,1,1)) 29 | if self._check_dimensions(): 30 | raise(ValueError,'dimensions must be 3-tuple of ints >=1') 31 | self.origin = self.get_3_tuple(origin,(1,1,1)) 32 | if self._check_origin(): 33 | raise(ValueError,'origin must be 3-tuple of numbers') 34 | self.spacing = self.get_3_tuple(spacing,(1,1,1)) 35 | if self._check_spacing(): 36 | raise(ValueError,'spacing must be 3-tuple of positive numbers') 37 | 38 | def to_string(self,format = 'ascii'): 39 | ret = ['DATASET STRUCTURED_POINTS', 40 | 'DIMENSIONS %s %s %s'%self.dimensions, 41 | 'ORIGIN %s %s %s'%self.origin, 42 | 'SPACING %s %s %s'%self.spacing] 43 | return '\n'.join(ret).encode() 44 | 45 | def get_points(self): 46 | if hasattr(self,'points'): 47 | return self.points 48 | arr = [] 49 | for k in range(self.dimensions[2]): 50 | z = self.origin[2] + k * self.spacing[2] 51 | for j in range(self.dimensions[1]): 52 | y = self.origin[1] + j * self.spacing[1] 53 | for i in range(self.dimensions[0]): 54 | x = self.origin[0] + i * self.spacing[0] 55 | arr.append((x,y,z)) 56 | self.points = arr 57 | return arr 58 | 59 | def structured_points_fromfile(f,self): 60 | l = common._getline(f).decode('ascii').split(' ') 61 | assert l[0].strip().lower() == 'dimensions' 62 | dims = list(map(int, l[1:])) 63 | assert len(dims)==3 64 | l = common._getline(f).decode('ascii').split(' ') 65 | assert l[0].strip().lower() == 'origin' 66 | origin = list(map(eval,l[1:])) 67 | assert len(origin)==3 68 | l = common._getline(f).decode('ascii').split(' ') 69 | assert l[0].strip().lower() == 'spacing' 70 | spacing = list(map(eval,l[1:])) 71 | assert len(spacing)==3 72 | return StructuredPoints(dims,origin,spacing),common._getline(f) 73 | 74 | if __name__ == "__main__": 75 | print(StructuredPoints((2,3,4))) 76 | print(StructuredPoints((2,3))) 77 | print(StructuredPoints(5)) 78 | print(StructuredPoints([2,3,5,6]).get_size()) 79 | -------------------------------------------------------------------------------- /pyvtk/Tensors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Tensors 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSetAttr as DataSetAttr 9 | import pyvtk.common as common 10 | 11 | class Tensors(DataSetAttr.DataSetAttr): 12 | """Holds VTK Tensors. 13 | Usage: 14 | Tensors( , name = ) 15 | Attributes: 16 | tensors 17 | name 18 | Public methods: 19 | get_size() 20 | to_string(format = 'ascii') 21 | """ 22 | def __init__(self,tensors,name=None): 23 | self.name = self._get_name(name) 24 | self.tensors = self.get_3_3_tuple_list(tensors,(self.default_value,)*3) 25 | def to_string(self,format='ascii'): 26 | t = self.get_datatype(self.tensors) 27 | ret = ['TENSORS %s %s'%(self.name,t), 28 | self.seq_to_string(self.tensors,format,t)] 29 | return '\n'.join(ret) 30 | def get_size(self): 31 | return len(self.tensors) 32 | 33 | def tensors_fromfile(f,n,sl): 34 | assert len(sl)==2 35 | dataname = sl[0].strip() 36 | datatype = sl[1].strip().lower() 37 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 38 | arr = [] 39 | while len(arr)<9*n: 40 | arr += map(eval,common._getline(f).split(' ')) 41 | assert len(arr)==9*n 42 | arr2 = [] 43 | for i in range(0,len(arr),9): 44 | arr2.append(tuple(map(tuple,[arr[i:i+3],arr[i+3:i+6],arr[i+6:i+9]]))) 45 | return Tensors(arr2,dataname) 46 | 47 | if __name__ == "__main__": 48 | print(Tensors([[[3,3]],[4,3.],[[240]],3,2,3]).to_string('ascii')) 49 | print(Tensors(3).to_string('ascii')) 50 | -------------------------------------------------------------------------------- /pyvtk/TextureCoordinates.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | TextureCoordinates 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSetAttr as DataSetAttr 9 | from . import common 10 | 11 | class TextureCoordinates(DataSetAttr.DataSetAttr): 12 | """Holds VTK Texture Coordinates. 13 | Usage: 14 | TextureCoordinates( ,name = ) 15 | Attributes: 16 | coords 17 | name 18 | Public methods: 19 | get_size() 20 | to_string(format = 'ascii') 21 | """ 22 | def __init__(self,scalars,name=None): 23 | self.name = self._get_name(name) 24 | self.coords = self.get_n_seq_seq(scalars,self.default_value) 25 | if not 1<=len(self.coords[0])<=3: 26 | raise ValueError('texture coordinates dimension must be 1, 2, or 3 but got %s'%(len(self.coords[0]))) 27 | def to_string(self,format='ascii'): 28 | t = self.get_datatype(self.coords) 29 | ret = ['TEXTURE_COORDINATES %s %s %s'%(self.name,len(self.coords[0]),t), 30 | self.seq_to_string(self.coords,format,t)] 31 | return '\n'.join(ret) 32 | def get_size(self): 33 | return len(self.coords) 34 | 35 | def texture_coordinates_fromfile(f,n,sl): 36 | assert len(sl)==3 37 | dataname = sl[0].strip() 38 | dim = int(sl[1]) 39 | datatype = sl[2].strip().lower() 40 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 41 | arr = [] 42 | while len(arr), 18 | vertex = 19 | poly_vertex = , 20 | line = , 21 | poly_line = , 22 | triangle = , 23 | triangle_strip = , 24 | polygon = , 25 | pixel = , 26 | quad = , 27 | tetra = , 28 | voxel = , 29 | hexahedron = , 30 | wedge = , 31 | pyramid = , 32 | quadratic_tetra = 33 | ) 34 | Attributes: 35 | points 36 | vertex 37 | poly_vertex, line, poly_line, triangle, triangle_strip, 38 | polygon, pixel, quad, tetra, voxel, hexahedron, wedge, pyramid 39 | Public methods: 40 | get_size() 41 | get_cell_size() 42 | to_string(format = 'ascii') 43 | get_points() 44 | (...) 45 | """ 46 | _vtk_cell_types_map = {'vertex':1,'poly_vertex':2,'line':3,'poly_line':4, 47 | 'triangle':5,'triangle_strip':6,'polygon':7,'pixel':8, 48 | 'quad':9,'tetra':10,'voxel':11,'hexahedron':12, 49 | 'wedge':13,'pyramid':14,'quadratic_tetra':24} 50 | _vtk_cell_nums_map = {'vertex':1,'poly_vertex':-1,'line':2,'poly_line':-1, 51 | 'triangle':3,'triangle_strip':-1,'polygon':-1,'pixel':4, 52 | 'quad':4,'tetra':4,'voxel':8,'hexahedron':8, 53 | 'wedge':6,'pyramid':5, 54 | 'quadratic_tetra':10} 55 | _vtk_cell_types_imap = {1:'vertex',2:'poly_vertex',3:'line',4:'poly_line', 56 | 5:'triangle',6:'triangle_strip',7:'polygon', 57 | 8:'pixel',9:'quad',10:'tetra',11:'voxel',12:'hexahedron', 58 | 13:'wedge',14:'pyramid',24:'quadratic_tetra'} 59 | def __init__(self,points,vertex=[],poly_vertex=[],line=[],poly_line=[], 60 | triangle=[],triangle_strip=[],polygon=[],pixel=[], 61 | quad=[],tetra=[],voxel=[],hexahedron=[],wedge=[],pyramid=[], 62 | quadratic_tetra=[]): 63 | self.points = self.get_3_tuple_list(points,(0,0,0)) 64 | sz = len(self.points) 65 | for k in self._vtk_cell_types_map.keys(): 66 | setattr(self, k, self.get_seq_seq(locals()[k], [])) 67 | if k=='vertex': 68 | r = [] 69 | for v in self.vertex: 70 | r += map(lambda a:[a],v) 71 | self.vertex = r 72 | if self._check_int_seq(getattr(self,k),sz): 73 | raise ValueError('In cell %s: must be (seq of seq|seq) integers less than %s'%(k,sz)) 74 | 75 | for k,n in self._vtk_cell_nums_map.items(): 76 | if n==-1: continue 77 | kv = getattr(self,k) 78 | if kv==[] or kv[0]==[]: continue 79 | for v in kv: 80 | if len(v)!=n: 81 | raise ValueError('Cell %s requires exactly %s points but got %s: %s'%(repr(k),n,len(v),v)) 82 | 83 | def to_string(self,format='ascii'): 84 | t = self.get_datatype(self.points) 85 | ret = [b'DATASET UNSTRUCTURED_GRID', 86 | ('POINTS %s %s'%(self.get_size(),t)).encode(), 87 | self.seq_to_string(self.points,format,t)] 88 | tps = [] 89 | r = [] 90 | sz = 0 91 | for k in self._vtk_cell_types_map.keys(): 92 | kv = getattr(self, k) 93 | if kv==[] or kv[0]==[]: continue 94 | s = self.seq_to_string([[len(v)]+list(v) for v in kv],format,'int') 95 | r.append(s) 96 | for v in kv: 97 | tps.append(self._vtk_cell_types_map[k]) 98 | sz += len(v)+1 99 | sep = b'\n' if (format == 'ascii') else b'' 100 | r = sep.join(r) 101 | ret += [('CELLS %s %s'%(len(tps),sz)).encode(), 102 | r, 103 | ('CELL_TYPES %s'%(len(tps))).encode(), 104 | self.seq_to_string(tps,format,'int')] 105 | return b'\n'.join(ret) 106 | 107 | def get_cell_size(self): 108 | sz = 0 109 | for k in self._vtk_cell_types_map.keys(): 110 | kv = getattr(self,k) 111 | if kv==[] or kv[0]==[]: continue 112 | sz += len(kv) 113 | return sz 114 | def get_points(self): 115 | return self.points 116 | 117 | def unstructured_grid_fromfile(f, self): 118 | l = common._getline(f).decode('ascii') 119 | k,n,datatype = [s.strip().lower() for s in l.split()] 120 | if k != 'points': 121 | raise ValueError( 'expected points but got %s'%(repr(k))) 122 | n = int(n) 123 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 124 | points = [] 125 | log.debug('\tgetting %s points'%n) 126 | while len(points) < 3*n: 127 | points += list(map(eval, common._getline(f).split())) 128 | assert len(points)==3*n 129 | 130 | l = common._getline(f).decode('ascii').split() 131 | assert len(l)==3 and l[0].strip().lower() == 'cells',repr(l) 132 | n = int(l[1]) 133 | size = int(l[2]) 134 | lst = [] 135 | log.debug('\tgetting %s cell indexes'%size) 136 | while len(lst) < size: 137 | line = common._getline(f).decode('ascii') 138 | lst += list(map(eval, line.split())) 139 | assert len(lst)==size 140 | lst2 = [] 141 | j = 0 142 | for i in range(n): 143 | lst2.append(lst[j+1:j+lst[j]+1]) 144 | j += lst[j]+1 145 | l = common._getline(f).decode('ascii').split() 146 | assert len(l)==2 and l[0].strip().lower() == 'cell_types' and int(l[1])==n, repr(l) 147 | tps = [] 148 | log.debug('\tgetting %s cell types'%n) 149 | while len(tps) < n: 150 | tps += list(map(int, common._getline(f).decode('ascii').split())) 151 | assert len(tps)==n 152 | dictionary = {} 153 | for i,t in zip(lst2,tps): 154 | k = UnstructuredGrid._vtk_cell_types_imap[t] 155 | if k not in dictionary: 156 | dictionary[k] = [] 157 | dictionary[k].append(i) 158 | log.debug('unstructured_grid_fromfile done') 159 | return UnstructuredGrid(points,**dictionary), common._getline(f) 160 | 161 | if __name__ == "__main__": 162 | print(UnstructuredGrid([[1,2],[2,4],3,5], 163 | line = [[2,3],[1,2],[2,3]], 164 | vertex=2)) 165 | -------------------------------------------------------------------------------- /pyvtk/Vectors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Vectors 4 | """ 5 | __author__ = "Pearu Peterson " 6 | __license__ = "New BSD" 7 | 8 | import pyvtk.DataSetAttr as DataSetAttr 9 | import pyvtk.common as common 10 | 11 | class Vectors(DataSetAttr.DataSetAttr): 12 | """Holds VTK Vectors. 13 | Usage: 14 | Vectors( ,name = ) 15 | Attributes: 16 | vectors 17 | name 18 | Public methods: 19 | get_size() 20 | to_string(format = 'ascii') 21 | """ 22 | def __init__(self,vectors,name=None): 23 | self.name = self._get_name(name) 24 | self.vectors = self.get_3_tuple_list(vectors,(self.default_value,)*3) 25 | 26 | def to_string(self,format='ascii'): 27 | t = self.get_datatype(self.vectors) 28 | ret = [('VECTORS %s %s'%(self.name,t)).encode(), 29 | self.seq_to_string(self.vectors,format,t)] 30 | return b'\n'.join(ret) 31 | 32 | def get_size(self): 33 | return len(self.vectors) 34 | 35 | def vectors_fromfile(f,n,sl): 36 | dataname = sl[0] 37 | datatype = sl[1].lower() 38 | assert datatype in ['bit','unsigned_char','char','unsigned_short','short','unsigned_int','int','unsigned_long','long','float','double'],repr(datatype) 39 | vectors = [] 40 | while len(vectors) < 3*n: 41 | vectors += map(eval,common._getline(f).split(' ')) 42 | assert len(vectors) == 3*n 43 | return Vectors(vectors,dataname) 44 | 45 | if __name__ == "__main__": 46 | print(Vectors([[3,3],[4,3.],240,3,2]).to_string()) 47 | -------------------------------------------------------------------------------- /pyvtk/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | PyVTK provides tools for manipulating VTK files in Python. 4 | 5 | VtkData - create VTK files from Python / read VTK files to Python 6 | 7 | """ 8 | __author__ = "Pearu Peterson " 9 | __license__ = "New BSD" 10 | 11 | from pyvtk.__version__ import __version__ 12 | 13 | __all__ = ['StructuredPoints','StructuredGrid','UnstructuredGrid', 14 | 'RectilinearGrid','PolyData', 15 | 'Scalars','ColorScalars','LookupTable','Vectors','Normals', 16 | 'TextureCoordinates','Tensors','Field', 17 | 'PointData','CellData', 18 | 'VtkData'] 19 | 20 | import logging 21 | log = logging.getLogger(__name__) 22 | # Silence logs - it's up to applications to do things with them 23 | log.addHandler(logging.NullHandler()) 24 | 25 | import pyvtk.common as common 26 | 27 | from pyvtk.StructuredPoints import StructuredPoints, structured_points_fromfile 28 | from pyvtk.StructuredGrid import StructuredGrid, structured_grid_fromfile 29 | from pyvtk.UnstructuredGrid import UnstructuredGrid, unstructured_grid_fromfile 30 | from pyvtk.RectilinearGrid import RectilinearGrid, rectilinear_grid_fromfile 31 | from pyvtk.PolyData import PolyData, polydata_fromfile 32 | 33 | from pyvtk.Scalars import Scalars, scalars_fromfile 34 | from pyvtk.ColorScalars import ColorScalars, color_scalars_fromfile 35 | from pyvtk.LookupTable import LookupTable, lookup_table_fromfile 36 | from pyvtk.Vectors import Vectors, vectors_fromfile 37 | from pyvtk.Normals import Normals, normals_fromfile 38 | from pyvtk.TextureCoordinates import TextureCoordinates, texture_coordinates_fromfile 39 | from pyvtk.Tensors import Tensors, tensors_fromfile 40 | from pyvtk.Field import Field, field_fromfile 41 | 42 | from pyvtk.Data import PointData,CellData, is_pointdata, is_celldata 43 | from pyvtk.DataSet import is_dataset 44 | 45 | parsers = { 46 | 'structured_points': structured_points_fromfile, 47 | 'structured_grid': structured_grid_fromfile, 48 | 'unstructured_grid': unstructured_grid_fromfile, 49 | 'rectilinear_grid': rectilinear_grid_fromfile, 50 | 'polydata': polydata_fromfile, 51 | 'scalars': scalars_fromfile, 52 | 'color_scalars': color_scalars_fromfile, 53 | 'lookup_table': lookup_table_fromfile, 54 | 'vectors': vectors_fromfile, 55 | 'normals': normals_fromfile, 56 | 'tensors': tensors_fromfile, 57 | 'texture_coordinates': texture_coordinates_fromfile, 58 | 'field': field_fromfile, 59 | } 60 | 61 | class VtkData(common.Common): 62 | """ 63 | VtkData 64 | ======= 65 | 66 | Represents VTK file that has four relevant parts: 67 | header - string up to length 255 68 | format - string: ascii | binary 69 | DataSet - StructuredPoints | StructuredGrid | UnstructuredGrid 70 | | RectilinearGrid | PolyData 71 | Data - PointData | CellData 72 | 73 | Usage: 74 | ------ 75 | v = VtkData( [,
,,..]) 76 | v = VtkData(, only_structure = 0) - read VTK data from file. 77 | v.tofile(filename, format = 'ascii') - save VTK data to file. 78 | Attributes: 79 | header 80 | structure 81 | point_data 82 | cell_data 83 | Public methods: 84 | to_string(format = 'ascii') 85 | tofile(filename, format = 'ascii') 86 | 87 | DataSet 88 | ======= 89 | 90 | StructuredPoints(<3-sequence of dimensions> 91 | [,<3-sequence of origin> [, <3-sequence of spacing>]]) 92 | StructuredGrid(<3-sequence of dimensions>, 93 | ) 94 | UnstructuredGrid( 95 | [, = ]) 96 | cell - vertex | poly_vertex | line | poly_line | triangle 97 | | triangle_strip | polygon | pixel | quad | tetra 98 | | voxel | hexahedron | wedge | pyramid 99 | RectilinearGrid([x = ], 100 | [y = ], 101 | [z = ]) 102 | PolyData(, 103 | [vertices = ], 104 | [lines = ], 105 | [polygons = ], 106 | [triangle_strips = ]) 107 | 108 | Data 109 | ==== 110 | 111 | PointData | CellData ([]) - construct Data instance 112 | 113 | DataSetAttr 114 | =========== 115 | 116 | DataSetAttr - Scalars | ColorScalars | LookupTable | Vectors 117 | | Normals | TextureCoordinates | Tensors | Field 118 | Scalars( [,name[, lookup_table]]) 119 | ColorScalars( [,name]) 120 | LookupTable( [,name]) 121 | Vectors( [,name]) 122 | Normals( [,name]) 123 | TextureCoordinates( [,name]) 124 | Tensors( [,name]) 125 | Field([name,] [arrayname_1 = sequence of n_1-sequences, ... 126 | arrayname_m = sequence of n_m-sequences,]) 127 | where len(array_1) == .. == len(array_m) must hold. 128 | """ 129 | header = None 130 | point_data = None 131 | cell_data = None 132 | def __init__(self,*args,**kws): 133 | assert args,'expected at least one argument' 134 | if type(args[0]) is str: 135 | if 'only_structure' in kws and kws['only_structure']: 136 | self.fromfile(args[0],1) 137 | else: 138 | self.fromfile(args[0]) 139 | return 140 | else: 141 | structure = args[0] 142 | args = list(args)[1:] 143 | if not is_dataset(structure): 144 | raise TypeError('argument structure must be StructuredPoints|StructuredGrid|UnstructuredGrid|RectilinearGrid|PolyData but got %s'%(type(structure))) 145 | self.structure = structure 146 | for a in args: 147 | if common.is_string(a): 148 | if len(a)>255: 149 | log.warning('striping header string to a length =255') 150 | self.header = a[:255] 151 | elif is_pointdata(a): 152 | self.point_data = a 153 | elif is_celldata(a): 154 | self.cell_data = a 155 | else: 156 | log.warning('unexpexted argument %s', type(a)) 157 | if self.header is None: 158 | self.header = 'Really cool data' 159 | log.info('Using default header=%s'%(repr(self.header))) 160 | if self.point_data is None and self.cell_data is None: 161 | log.info('No point/cell data defined') 162 | 163 | if self.point_data is not None: 164 | s = self.structure.get_size() 165 | s1 = self.point_data.get_size() 166 | if s1 != s: 167 | raise ValueError('DataSet (size=%s) and PointData (size=%s) have different sizes'%(s,s1)) 168 | else: 169 | self.point_data = PointData() 170 | if self.cell_data is not None: 171 | s = self.structure.get_cell_size() 172 | s1 = self.cell_data.get_size() 173 | if s1 != s: 174 | raise ValueError('DataSet (cell_size=%s) and CellData (size=%s) have different sizes'%(s,s1)) 175 | else: 176 | self.cell_data = CellData() 177 | 178 | def to_string(self, format = 'ascii'): 179 | ret = [b'# vtk DataFile Version 2.0', 180 | self.header.encode(), 181 | format.upper().encode(), 182 | self.structure.to_string(format) 183 | ] 184 | if self.cell_data.data: 185 | ret.append(self.cell_data.to_string(format)) 186 | if self.point_data.data: 187 | ret.append(self.point_data.to_string(format)) 188 | return b'\n'.join(ret) 189 | 190 | def tofile(self, filename, format = 'ascii'): 191 | """Save VTK data to file. 192 | """ 193 | if not common.is_string(filename): 194 | raise TypeError('argument filename must be string but got %s'%(type(filename))) 195 | if format not in ['ascii','binary']: 196 | raise TypeError('argument format must be ascii | binary') 197 | filename = filename.strip() 198 | if not filename: 199 | raise ValueError('filename must be non-empty string') 200 | if filename[-4:]!='.vtk': 201 | filename += '.vtk' 202 | f = open(filename,'wb') 203 | f.write(self.to_string(format)) 204 | f.close() 205 | 206 | def fromfile(self,filename, only_structure = 0): 207 | filename = filename.strip() 208 | if filename[-4:]!='.vtk': 209 | filename += '.vtk' 210 | f = open(filename,'rb') 211 | l = f.readline() 212 | fileversion = l.strip().replace(b' ',b'').lower() 213 | if not fileversion == b'#vtkdatafileversion2.0': 214 | print('File %s is not in VTK 2.0 format, got %s but continuing anyway..' % (filename, fileversion)) 215 | self.header = f.readline().rstrip().decode('ascii', 'replace') 216 | format = f.readline().strip().lower() 217 | if format not in [b'ascii', b'binary']: 218 | raise ValueError('Expected ascii|binary but got %s'%(repr(format))) 219 | if format == b'binary': 220 | raise NotImplementedError('reading vtk binary format') 221 | l = common._getline(f).decode('ascii').lower().split(' ') 222 | if l[0].strip() != 'dataset': 223 | raise ValueError('expected dataset but got %s'%(l[0])) 224 | try: 225 | ff = parsers[l[1]] 226 | except KeyError: 227 | raise NotImplementedError('%s_fromfile'%(l[1])) 228 | self.structure, l = ff(f,self) 229 | 230 | for i in range(2): 231 | if only_structure: break 232 | if not l: 233 | break 234 | l = [s.strip() for s in l.decode('ascii').lower().split(' ')] 235 | assert len(l)==2 and l[0] in ['cell_data','point_data'], l[0] 236 | data = l[0] 237 | n = int(l[1]) 238 | lst = [] 239 | while 1: 240 | l = common._getline(f) 241 | if not l: 242 | break 243 | sl = [s.strip() for s in l.decode('ascii').split()] 244 | k = sl[0].lower() 245 | if k not in ['scalars','color_scalars','lookup_table','vectors', 246 | 'normals','texture_coordinates','tensors','field']: 247 | break 248 | try: 249 | ff = parsers[k] 250 | except KeyError: 251 | raise NotImplementedError('%s_fromfile'%(k)) 252 | lst.append(ff(f,n,sl[1:])) 253 | if data == 'point_data': 254 | self.point_data = PointData(*lst) 255 | if data == 'cell_data': 256 | self.cell_data = CellData(*lst) 257 | if self.point_data is None: 258 | self.point_data = PointData() 259 | if self.cell_data is None: 260 | self.cell_data = CellData() 261 | f.close() 262 | 263 | if __name__ == "__main__": 264 | vtk = VtkData(StructuredPoints((3,1,1)), 265 | 'This is title', 266 | PointData(Scalars([3,4,5])) 267 | ) 268 | vtk.tofile('test') 269 | -------------------------------------------------------------------------------- /pyvtk/__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.5.18" 2 | -------------------------------------------------------------------------------- /pyvtk/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | """ 4 | Common functions/methods. 5 | """ 6 | __author__ = "Pearu Peterson " 7 | __license__ = "New BSD" 8 | 9 | import sys 10 | import struct 11 | from functools import reduce 12 | import numpy as np 13 | 14 | import logging 15 | log = logging.getLogger(__name__) 16 | 17 | import six 18 | 19 | def is_sequence(obj): 20 | """Check if obj is sequence.""" 21 | try: 22 | len(obj) 23 | return 1 24 | except TypeError: 25 | return 0 26 | def is_sequence2(obj): 27 | """Check if obj is sequence of sequences.""" 28 | return is_sequence(obj) and len(obj) and is_sequence(obj[0]) 29 | 30 | def is_sequence3(obj): 31 | """Check if obj is sequence of sequences of sequences.""" 32 | return is_sequence(obj) and len(obj) and is_sequence2(obj[0]) 33 | 34 | def is_number(obj): 35 | """Check if obj is number.""" 36 | return isinstance(obj, (int, float, np.int_, np.float64)) 37 | 38 | def is_int(obj): 39 | """Check if obj is integer.""" 40 | return isinstance(obj, (int, np.int_)) 41 | 42 | def is_float(obj): 43 | """Check if obj is float.""" 44 | return isinstance(obj, float) 45 | 46 | def is_string(obj): 47 | """Check if obj is string.""" 48 | return isinstance(obj, six.string_types) 49 | 50 | def is_int255(obj): 51 | if is_sequence(obj): 52 | for v in obj: 53 | r = is_int255(v) 54 | if not r: return 0 55 | return 1 56 | return 0<=obj<256 57 | 58 | def is_float01(obj): 59 | if is_sequence(obj): 60 | for v in obj: 61 | r = is_float01(v) 62 | if not r: return 0 63 | return 1 64 | return 0<=obj<=1 65 | 66 | def _getline(f): 67 | l = ' ' 68 | while l: 69 | l = f.readline() 70 | if l.strip(): 71 | return l.strip() 72 | return None 73 | 74 | class Common: 75 | """Abstract class. Defines output, checker, and getter functions.""" 76 | struct_fmt_map = {'char':'c','char':'b', 77 | 'long':'l','double':'d', 78 | 'unsigned long':'L', 79 | 'int':'i','float':'f', 80 | 'unsigned char':'B', 81 | 'unsigned short':'H', 82 | 'short':'h', 83 | 'unsigned int':'I', 84 | } 85 | default_int = 'int' 86 | default_float = 'float' 87 | 88 | def __str__(self): 89 | return self.to_string() 90 | 91 | def get_datatype(self,obj): 92 | typecode = None 93 | if hasattr(obj,'dtype'): # obj is numpy array 94 | typecode = obj.dtype.char 95 | elif hasattr(obj,'typecode'): # obj is Numeric array 96 | typecode = obj.typecode() 97 | 98 | if typecode is not None: 99 | r = {'b':'char', #'bit'?? 100 | 'B':'unsigned_char', 101 | 'f':'float', 102 | 'd':'double', 103 | 'i':'int', 104 | 'l':'long', 105 | 'L':'unsigned_long', 106 | '1':'char', 107 | 's':'short', # Numeric 108 | 'h':'short', 109 | 'w':'unsigned_short', # Numeric 110 | 'H':'unsigned_short', 111 | 'u':'unsigned_int', # Numeric 112 | 'I':'unsigned_int', 113 | }.get(typecode) 114 | if r is not None: 115 | return r 116 | if is_int(obj): return self.default_int 117 | if is_float(obj): return self.default_float 118 | if not is_sequence(obj): 119 | raise ValueError('expected int|float|non-empty sequence but got %s (typecode=%r)'\ 120 | %(type(obj), typecode)) 121 | if not len(obj): 122 | log.warning('no data, no datatype, using int') 123 | r = 'int' 124 | for o in obj: 125 | r = self.get_datatype(o) 126 | if r==self.default_float: 127 | break 128 | return r 129 | 130 | def get_seq(self,obj,default=None): 131 | """Return sequence.""" 132 | if is_sequence(obj): 133 | return obj 134 | if is_number(obj): return [obj] 135 | if obj is None and default is not None: 136 | log.warning('using default value (%s)'%(default)) 137 | return self.get_seq(default) 138 | raise ValueError('expected sequence|number but got %s'%(type(obj))) 139 | def get_seq_seq(self,obj,default=None): 140 | """Return sequence of sequences.""" 141 | if is_sequence2(obj): 142 | return [self.get_seq(o,default) for o in obj] 143 | else: 144 | return [self.get_seq(obj,default)] 145 | def get_n_seq_seq(self,obj,default): 146 | seq = self.get_seq_seq(obj,default) 147 | if is_sequence(default): 148 | n = len(default) 149 | else: 150 | n = max(list(map(len,seq))) 151 | default = [default]*n 152 | ret = [] 153 | flag = 0 154 | for v in seq: 155 | if len(v)!=n: 156 | ret.append(list(v)+default[len(v):]) 157 | flag = 1 158 | else: 159 | ret.append(list(v)) 160 | if flag: 161 | log.warning('Some items were filled with default value (%s) to obtain size=%s'%(default[0],n)) 162 | return ret 163 | def get_3_tuple(self,obj,default=None): 164 | """Return 3-tuple from 165 | number -> (obj,default[1],default[2]) 166 | 0-sequence|None -> default 167 | 1-sequence -> (obj[0],default[1],default[2]) 168 | 2-sequence -> (obj[0],obj[1],default[2]) 169 | (3 or more)-sequence -> (obj[0],obj[1],obj[2]) 170 | """ 171 | if not (default is not None \ 172 | and type(default) is tuple \ 173 | and len(default)==3): 174 | raise ValueError('argument default must be 3-tuple|None but got %s'%(default)) 175 | if is_sequence(obj): 176 | n = len(obj) 177 | if n>3: 178 | log.warning('expected 3-sequence but got %s-%s'%(n,type(obj))) 179 | if n>=3: 180 | return tuple(obj) 181 | log.warning('filling with default value (%s) to obtain size=3'%(default[0])) 182 | if default is not None: 183 | if n==0: 184 | return default 185 | elif n==1: 186 | return (obj[0],default[1],default[2]) 187 | elif n==2: 188 | return (obj[0],obj[1],default[2]) 189 | elif is_number(obj) and default is not None: 190 | log.warning('filling with default value (%s) to obtain size=3'%(default[0])) 191 | return (obj,default[1],default[2]) 192 | elif obj is None and default is not None: 193 | log.warning('filling with default value (%s) to obtain size=3'%(default[0])) 194 | return default 195 | raise ValueError('failed to construct 3-tuple from %s-%s'%(n,type(obj))) 196 | def get_3_tuple_list(self,obj,default=None): 197 | """Return list of 3-tuples from 198 | sequence of a sequence, 199 | sequence - it is mapped to sequence of 3-sequences if possible 200 | number 201 | """ 202 | if is_sequence2(obj): 203 | return [self.get_3_tuple(o,default) for o in obj] 204 | elif is_sequence(obj): 205 | return [self.get_3_tuple(obj[i:i+3],default) for i in range(0,len(obj),3)] 206 | else: 207 | return [self.get_3_tuple(obj,default)] 208 | def get_3_3_tuple(self,obj,default=None): 209 | """Return tuple of 3-tuples 210 | """ 211 | if is_sequence2(obj): 212 | ret = [] 213 | for i in range(3): 214 | if i9: 221 | log.warning('ignoring elements obj[i], i>=9') 222 | r = obj[:9] 223 | r = [self.get_3_tuple(r[j:j+3],default) for j in range(0,len(r),3)] 224 | if len(r)<3: 225 | log.warning('filling with default value (%s) to obtain size=3'%(default[0])) 226 | while len(r)<3: 227 | r.append(self.get_3_tuple(default,default)) 228 | return tuple(r) 229 | log.warning('filling with default value (%s) to obtain size=3'%(default[0])) 230 | r1 = self.get_3_tuple(obj,default) 231 | r2 = self.get_3_tuple(default,default) 232 | r3 = self.get_3_tuple(default,default) 233 | return (r1,r2,r3) 234 | def get_3_3_tuple_list(self,obj,default=None): 235 | """Return list of 3x3-tuples. 236 | """ 237 | if is_sequence3(obj): 238 | return [self.get_3_3_tuple(o,default) for o in obj] 239 | return [self.get_3_3_tuple(obj,default)] 240 | 241 | def _get_nof_objs(self,seq): 242 | if is_sequence2(seq): 243 | return reduce(lambda x,y:x+y,list(map(self._get_nof_objs,seq)),0) 244 | return len(seq) 245 | 246 | def seq_to_string(self,seq,format,datatype): 247 | assert is_sequence(seq),'expected sequence but got %s'%(type(seq)) 248 | if format == 'ascii': 249 | if is_sequence2(seq): 250 | sep = b'\n' 251 | if is_sequence3(seq): 252 | sep = b'\n\n' 253 | return sep.join([self.seq_to_string(v,format,datatype) for v in seq]) 254 | else: 255 | return ' '.join(map(str,seq)).encode() 256 | elif format == 'binary': 257 | if is_sequence2(seq): 258 | r = b''.join([self.seq_to_string(v,format,datatype) for v in seq]) 259 | return r 260 | else: 261 | try: 262 | fmt = self.struct_fmt_map[datatype] 263 | except KeyError: 264 | try: 265 | fmt = self.struct_fmt_map[datatype.replace('_',' ')] 266 | except KeyError: 267 | fmt = None 268 | if fmt: 269 | r = struct.pack('!'+fmt*len(seq),*seq) 270 | return r 271 | raise NotImplementedError('format=%s, datatype=%s'%(format,datatype)) 272 | 273 | def float01_to_int255(self,seq): 274 | assert is_float01(seq) 275 | if is_sequence(seq): 276 | return list(map(self.float01_to_int255,seq)) 277 | #return [self.float01_to_int255(l) for l in seq] 278 | else: 279 | return int(seq*255) 280 | def int255_to_float01(self,seq): 281 | assert is_int255(seq) 282 | if is_sequence(seq): 283 | return list(map(self.int255_to_float01,seq)) 284 | #return [self.int255_to_float01(l) for l in seq] 285 | else: 286 | return round(seq/255.0,6) 287 | 288 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | from distutils.core import setup 5 | 6 | version_file = os.path.join('pyvtk','__version__.py') 7 | if 1 or not os.path.exists(version_file): # disable if block for release! 8 | import subprocess 9 | major_version = 0 10 | minor_version = 5 11 | process = subprocess.Popen(["git", "rev-list", "--count", "--first-parent", "HEAD"], 12 | stdout=subprocess.PIPE) 13 | revision_version = int(process.communicate()[0]) 14 | __version__='%d.%d.%d'%(major_version,minor_version,revision_version) 15 | f = open(version_file, 'w') 16 | f.write('__version__ = "%s"\n'%(__version__)) 17 | f.close() 18 | 19 | exec(open(version_file).read()) 20 | 21 | print("PyVTK Version",__version__) 22 | setup (name = "PyVTK", 23 | version = __version__, 24 | description = "PyVTK - tools for manipulating VTK files in Python", 25 | author = "Pearu Peterson", 26 | author_email = "pearu.peterson@gmail.com", 27 | maintainer = "Pearu Peterson", 28 | maintainer_email = "pearu.peterson@gmail.com", 29 | license = "New BSD", 30 | long_description= """\ 31 | PyVTK provides tools for manipulating VTK (Visualization Toolkit) 32 | files in Python: 33 | VtkData - create VTK files from Python / read VTK files to Python.""", 34 | url = "https://github.com/pearu/pyvtk", 35 | packages = ['pyvtk'], 36 | keywords = ['VTK'], 37 | classifiers=[ 38 | 'Development Status :: 5 - Production/Stable', 39 | 'Intended Audience :: Science/Research', 40 | 'License :: OSI Approved :: BSD License', 41 | 'Natural Language :: English', 42 | 'Operating System :: OS Independent', 43 | 'Programming Language :: Python', 44 | 'Programming Language :: Python :: 2', 45 | 'Programming Language :: Python :: 3', 46 | 'Topic :: Scientific/Engineering :: Visualization', 47 | ], 48 | platforms = 'All', 49 | install_requires = ['six'], 50 | ) 51 | -------------------------------------------------------------------------------- /test/input/example1.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET POLYDATA 5 | POINTS 8 int 6 | 0 0 0 7 | 1 0 0 8 | 1 1 0 9 | 0 1 0 10 | 0 0 1 11 | 1 0 1 12 | 1 1 1 13 | 0 1 1 14 | POLYGONS 6 30 15 | 4 0 1 2 3 16 | 4 4 5 6 7 17 | 4 0 1 5 4 18 | 4 2 3 7 6 19 | 4 0 4 7 3 20 | 4 1 2 6 5 21 | CELL_DATA 6 22 | SCALARS cell_scalars int 1 23 | LOOKUP_TABLE default 24 | 0 1 2 3 4 5 25 | NORMALS cell_normals int 26 | 0 0 -1 27 | 0 0 1 28 | 0 -1 0 29 | 0 1 0 30 | -1 0 0 31 | 1 0 0 32 | FIELD FieldData 2 33 | cellIds 1 6 int 34 | 0 35 | 1 36 | 2 37 | 3 38 | 4 39 | 5 40 | faceAttributes 2 6 int 41 | 0 1 42 | 1 2 43 | 2 3 44 | 3 4 45 | 4 5 46 | 5 6 47 | POINT_DATA 8 48 | SCALARS sample_scalars int 1 49 | LOOKUP_TABLE my_table 50 | 0 1 2 3 4 5 6 7 51 | LOOKUP_TABLE my_table 8 52 | 0 0 0 1 53 | 1 0 0 1 54 | 0 1 0 1 55 | 1 1 0 1 56 | 0 0 1 1 57 | 1 0 1 1 58 | 0 1 1 1 59 | 1 1 1 1 -------------------------------------------------------------------------------- /test/input/example1b.vtk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pearu/pyvtk/88931a72c954dda7a7d1d4a1e606d0c47cc834a7/test/input/example1b.vtk -------------------------------------------------------------------------------- /test/input/example2.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET STRUCTURED_POINTS 5 | DIMENSIONS 3 4 6 6 | ORIGIN 0 0 0 7 | SPACING 1 1 1 8 | POINT_DATA 72 9 | SCALARS Scalars0 int 1 10 | LOOKUP_TABLE default 11 | 0 0 0 0 0 0 0 0 0 0 0 0 0 5 10 15 20 25 25 20 15 10 5 0 0 10 20 30 40 50 50 40 30 20 10 0 0 10 20 30 40 50 50 40 30 20 10 0 0 5 10 15 20 25 25 20 15 10 5 0 0 0 0 0 0 0 0 0 0 0 0 0 -------------------------------------------------------------------------------- /test/input/example2b.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | BINARY 4 | DATASET STRUCTURED_POINTS 5 | DIMENSIONS 3 4 6 6 | ORIGIN 0 0 0 7 | SPACING 1 1 1 8 | POINT_DATA 72 9 | SCALARS Scalars0 int 1 10 | LOOKUP_TABLE default 11 |  12 |  13 |  14 | (22( 15 | 16 | (22( 17 |  18 |  19 |  -------------------------------------------------------------------------------- /test/input/example2f_rg.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET RECTILINEAR_GRID 5 | DIMENSIONS 3 4 6 6 | X_COORDINATES 3 int 7 | 0 1 2 8 | Y_COORDINATES 4 int 9 | 0 1 2 3 10 | Z_COORDINATES 6 int 11 | 0 1 2 3 4 5 12 | POINT_DATA 72 13 | SCALARS x*y*z int 1 14 | LOOKUP_TABLE default 15 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 2 4 0 3 6 0 0 0 0 2 4 0 4 8 0 6 12 0 0 0 0 3 6 0 6 12 0 9 18 0 0 0 0 4 8 0 8 16 0 12 24 0 0 0 0 5 10 0 10 20 0 15 30 -------------------------------------------------------------------------------- /test/input/example2f_sg.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET STRUCTURED_GRID 5 | DIMENSIONS 3 4 6 6 | POINTS 72 int 7 | 0 0 0 8 | 1 0 0 9 | 2 0 0 10 | 0 1 0 11 | 1 1 0 12 | 2 1 0 13 | 0 2 0 14 | 1 2 0 15 | 2 2 0 16 | 0 3 0 17 | 1 3 0 18 | 2 3 0 19 | 0 0 1 20 | 1 0 1 21 | 2 0 1 22 | 0 1 1 23 | 1 1 1 24 | 2 1 1 25 | 0 2 1 26 | 1 2 1 27 | 2 2 1 28 | 0 3 1 29 | 1 3 1 30 | 2 3 1 31 | 0 0 2 32 | 1 0 2 33 | 2 0 2 34 | 0 1 2 35 | 1 1 2 36 | 2 1 2 37 | 0 2 2 38 | 1 2 2 39 | 2 2 2 40 | 0 3 2 41 | 1 3 2 42 | 2 3 2 43 | 0 0 3 44 | 1 0 3 45 | 2 0 3 46 | 0 1 3 47 | 1 1 3 48 | 2 1 3 49 | 0 2 3 50 | 1 2 3 51 | 2 2 3 52 | 0 3 3 53 | 1 3 3 54 | 2 3 3 55 | 0 0 4 56 | 1 0 4 57 | 2 0 4 58 | 0 1 4 59 | 1 1 4 60 | 2 1 4 61 | 0 2 4 62 | 1 2 4 63 | 2 2 4 64 | 0 3 4 65 | 1 3 4 66 | 2 3 4 67 | 0 0 5 68 | 1 0 5 69 | 2 0 5 70 | 0 1 5 71 | 1 1 5 72 | 2 1 5 73 | 0 2 5 74 | 1 2 5 75 | 2 2 5 76 | 0 3 5 77 | 1 3 5 78 | 2 3 5 79 | POINT_DATA 72 80 | SCALARS x*y*z int 1 81 | LOOKUP_TABLE default 82 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 2 4 0 3 6 0 0 0 0 2 4 0 4 8 0 6 12 0 0 0 0 3 6 0 6 12 0 9 18 0 0 0 0 4 8 0 8 16 0 12 24 0 0 0 0 5 10 0 10 20 0 15 30 -------------------------------------------------------------------------------- /test/input/example2f_sp.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET STRUCTURED_POINTS 5 | DIMENSIONS 3 4 6 6 | ORIGIN 0 0 0 7 | SPACING 1 1 1 8 | POINT_DATA 72 9 | SCALARS x*y*z int 1 10 | LOOKUP_TABLE default 11 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 2 4 0 3 6 0 0 0 0 2 4 0 4 8 0 6 12 0 0 0 0 3 6 0 6 12 0 9 18 0 0 0 0 4 8 0 8 16 0 12 24 0 0 0 0 5 10 0 10 20 0 15 30 -------------------------------------------------------------------------------- /test/input/example2f_usg.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Really cool data 3 | ASCII 4 | DATASET UNSTRUCTURED_GRID 5 | POINTS 72 int 6 | 0 0 0 7 | 1 0 0 8 | 2 0 0 9 | 0 1 0 10 | 1 1 0 11 | 2 1 0 12 | 0 2 0 13 | 1 2 0 14 | 2 2 0 15 | 0 3 0 16 | 1 3 0 17 | 2 3 0 18 | 0 0 1 19 | 1 0 1 20 | 2 0 1 21 | 0 1 1 22 | 1 1 1 23 | 2 1 1 24 | 0 2 1 25 | 1 2 1 26 | 2 2 1 27 | 0 3 1 28 | 1 3 1 29 | 2 3 1 30 | 0 0 2 31 | 1 0 2 32 | 2 0 2 33 | 0 1 2 34 | 1 1 2 35 | 2 1 2 36 | 0 2 2 37 | 1 2 2 38 | 2 2 2 39 | 0 3 2 40 | 1 3 2 41 | 2 3 2 42 | 0 0 3 43 | 1 0 3 44 | 2 0 3 45 | 0 1 3 46 | 1 1 3 47 | 2 1 3 48 | 0 2 3 49 | 1 2 3 50 | 2 2 3 51 | 0 3 3 52 | 1 3 3 53 | 2 3 3 54 | 0 0 4 55 | 1 0 4 56 | 2 0 4 57 | 0 1 4 58 | 1 1 4 59 | 2 1 4 60 | 0 2 4 61 | 1 2 4 62 | 2 2 4 63 | 0 3 4 64 | 1 3 4 65 | 2 3 4 66 | 0 0 5 67 | 1 0 5 68 | 2 0 5 69 | 0 1 5 70 | 1 1 5 71 | 2 1 5 72 | 0 2 5 73 | 1 2 5 74 | 2 2 5 75 | 0 3 5 76 | 1 3 5 77 | 2 3 5 78 | CELLS 30 270 79 | 8 0 1 3 4 12 13 15 16 80 | 8 1 2 4 5 13 14 16 17 81 | 8 3 4 6 7 15 16 18 19 82 | 8 4 5 7 8 16 17 19 20 83 | 8 6 7 9 10 18 19 21 22 84 | 8 7 8 10 11 19 20 22 23 85 | 8 12 13 15 16 24 25 27 28 86 | 8 13 14 16 17 25 26 28 29 87 | 8 15 16 18 19 27 28 30 31 88 | 8 16 17 19 20 28 29 31 32 89 | 8 18 19 21 22 30 31 33 34 90 | 8 19 20 22 23 31 32 34 35 91 | 8 24 25 27 28 36 37 39 40 92 | 8 25 26 28 29 37 38 40 41 93 | 8 27 28 30 31 39 40 42 43 94 | 8 28 29 31 32 40 41 43 44 95 | 8 30 31 33 34 42 43 45 46 96 | 8 31 32 34 35 43 44 46 47 97 | 8 36 37 39 40 48 49 51 52 98 | 8 37 38 40 41 49 50 52 53 99 | 8 39 40 42 43 51 52 54 55 100 | 8 40 41 43 44 52 53 55 56 101 | 8 42 43 45 46 54 55 57 58 102 | 8 43 44 46 47 55 56 58 59 103 | 8 48 49 51 52 60 61 63 64 104 | 8 49 50 52 53 61 62 64 65 105 | 8 51 52 54 55 63 64 66 67 106 | 8 52 53 55 56 64 65 67 68 107 | 8 54 55 57 58 66 67 69 70 108 | 8 55 56 58 59 67 68 70 71 109 | CELL_TYPES 30 110 | 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 111 | POINT_DATA 72 112 | SCALARS x*y*z int 1 113 | LOOKUP_TABLE default 114 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 2 4 0 3 6 0 0 0 0 2 4 0 4 8 0 6 12 0 0 0 0 3 6 0 6 12 0 9 18 0 0 0 0 4 8 0 8 16 0 12 24 0 0 0 0 5 10 0 10 20 0 15 30 -------------------------------------------------------------------------------- /test/input/example3.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Unstructured Grid Example 3 | ASCII 4 | DATASET UNSTRUCTURED_GRID 5 | POINTS 27 int 6 | 0 0 0 7 | 1 0 0 8 | 2 0 0 9 | 0 1 0 10 | 1 1 0 11 | 2 1 0 12 | 0 0 1 13 | 1 0 1 14 | 2 0 1 15 | 0 1 1 16 | 1 1 1 17 | 2 1 1 18 | 0 1 2 19 | 1 1 2 20 | 2 1 2 21 | 0 1 3 22 | 1 1 3 23 | 2 1 3 24 | 0 1 4 25 | 1 1 4 26 | 2 1 4 27 | 0 1 5 28 | 1 1 5 29 | 2 1 5 30 | 0 1 6 31 | 1 1 6 32 | 2 1 6 33 | CELLS 11 60 34 | 3 21 22 18 35 | 3 22 19 18 36 | 1 24 37 | 4 22 23 20 19 38 | 2 26 25 39 | 6 15 16 17 14 13 12 40 | 4 6 10 9 12 41 | 4 5 11 10 14 42 | 6 18 15 19 16 20 17 43 | 8 0 1 4 3 6 7 10 9 44 | 8 1 2 5 4 7 8 11 10 45 | CELL_TYPES 11 46 | 5 5 1 9 3 7 10 10 6 12 12 47 | POINT_DATA 27 48 | VECTORS Vectors0 int 49 | 1 0 0 50 | 1 1 0 51 | 0 2 0 52 | 1 0 0 53 | 1 1 0 54 | 0 2 0 55 | 1 0 0 56 | 1 1 0 57 | 0 2 0 58 | 1 0 0 59 | 1 1 0 60 | 0 2 0 61 | 0 0 1 62 | 0 0 1 63 | 0 0 1 64 | 0 0 1 65 | 0 0 1 66 | 0 0 1 67 | 0 0 1 68 | 0 0 1 69 | 0 0 1 70 | 0 0 1 71 | 0 0 1 72 | 0 0 1 73 | 0 0 1 74 | 0 0 1 75 | 0 0 1 76 | SCALARS Scalars0 int 1 77 | LOOKUP_TABLE default 78 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 -------------------------------------------------------------------------------- /test/input/example3b.vtk: -------------------------------------------------------------------------------- 1 | # vtk DataFile Version 2.0 2 | Unstructured Grid Example 3 | BINARY 4 | DATASET UNSTRUCTURED_GRID 5 | POINTS 27 int 6 |  7 | CELLS 11 60 8 |   9 |  10 |  11 |  12 | 13 | CELL_TYPES 11 14 |   15 | 16 |  17 | POINT_DATA 27 18 | VECTORS Vectors0 int 19 |  20 | SCALARS Scalars0 int 1 21 | LOOKUP_TABLE default 22 |  23 |  -------------------------------------------------------------------------------- /test/test_pyvtk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Test reading and writting vtk files. 5 | 6 | Input files are taken from examples/ directory. 7 | """ 8 | 9 | import unittest 10 | from shutil import rmtree 11 | from os.path import isdir, join 12 | from os import mkdir 13 | 14 | from pyvtk import * 15 | 16 | class TestBase(unittest.TestCase): 17 | """ 18 | Manage output and input directories and files. 19 | 20 | Directories hierarchy is as follow: 21 | 22 | output_dir/ 23 | file1 24 | file2 25 | 26 | input_dir/ 27 | file1 28 | file2 29 | """ 30 | # Root directory containing output outputs. 31 | output_dir = "output" 32 | 33 | # Root directory containing input outputs. 34 | input_dir = "input" 35 | 36 | # Diff long strings. 37 | maxDiff = None 38 | 39 | @classmethod 40 | def output(cls, filename): 41 | """filepath in output directory""" 42 | return join(cls.output_dir, filename) 43 | 44 | @classmethod 45 | def input(cls, filename): 46 | """filepath in input directory""" 47 | return join(cls.input_dir, filename) 48 | 49 | def check_output_file(self, filename, binary=False): 50 | """Diff output and input files""" 51 | output_filepath = self.output(filename) 52 | input_filepath = self.input(filename) 53 | 54 | mode = 'rb' if binary else 'r' 55 | output_string = open(output_filepath,mode).read() 56 | input_string = open(input_filepath,mode).read() 57 | 58 | self.assertEqual(output_string, input_string) 59 | 60 | class TestPolyData(TestBase): 61 | 62 | def test_read_write_ascii_file(self): 63 | vtk = VtkData(self.input('example1')) 64 | vtk.tofile(self.output('example1'), 'ascii') 65 | self.check_output_file('example1.vtk') 66 | 67 | def test_read_write_binary_file(self): 68 | vtk = VtkData(self.input('example1')) 69 | vtk.tofile(self.output('example1b'), 'binary') 70 | self.check_output_file('example1b.vtk', binary=True) 71 | 72 | class TestStructuredPoints(TestBase): 73 | 74 | def test_read_write_ascii_file(self): 75 | vtk = VtkData(self.input('example2')) 76 | vtk.tofile(self.output('example2'), 'ascii') 77 | self.check_output_file('example2.vtk') 78 | 79 | def test_read_write_binary_file(self): 80 | vtk = VtkData(self.input('example2')) 81 | vtk.tofile(self.output('example2b'), 'binary') 82 | self.check_output_file('example2b.vtk', binary=True) 83 | 84 | def test_point_data_append(self): 85 | vtk = VtkData(self.input('example2'),only_structure = 1) 86 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 87 | vtk.tofile(self.output('example2f_sp')) 88 | self.check_output_file('example2f_sp.vtk') 89 | 90 | class TestStructuredGrid(TestBase): 91 | 92 | def test_read_write_ascii_file(self): 93 | pp = [(i,j,k) for k in range(6) for j in range(4) for i in range(3)] 94 | vtk = VtkData(StructuredGrid([3,4,6],pp)) 95 | vtk.point_data.append(vtk.structure.Scalars(f,'x*y*z')) 96 | vtk.tofile(self.output('example2f_sg')) 97 | self.check_output_file('example2f_sg.vtk') 98 | 99 | class TestRectilinearGrid(TestBase): 100 | 101 | def test_read_write_ascii_file(self): 102 | vtk = VtkData(self.input('example2f_rg')) 103 | vtk.tofile(self.output('example2f_rg'), 'ascii') 104 | self.check_output_file('example2f_rg.vtk') 105 | 106 | class TestUnstructuredGrid(TestBase): 107 | 108 | def test_read_write_ascii_file(self): 109 | vtk = VtkData(self.input('example2f_usg')) 110 | vtk.tofile(self.output('example2f_usg'), 'ascii') 111 | self.check_output_file('example2f_usg.vtk') 112 | 113 | def f(x,y,z): 114 | return x*y*z 115 | 116 | if __name__ == '__main__': 117 | 118 | # Create a fresh directory for ouptuts 119 | if isdir(TestBase.output_dir): 120 | rmtree(TestBase.output_dir) 121 | mkdir(TestBase.output_dir) 122 | 123 | unittest.main() 124 | --------------------------------------------------------------------------------