DAMASK_EICMD/python/tests/test_VTK.py

245 lines
10 KiB
Python

import os
import filecmp
import time
import string
import pytest
import numpy as np
import numpy.ma as ma
import vtk
from damask import VTK
from damask import Table
from damask import Colormap
@pytest.fixture
def ref_path(ref_path_base):
"""Directory containing reference results."""
return ref_path_base/'VTK'
@pytest.fixture
def default():
"""Simple VTK."""
cells = np.array([5,6,7],int)
size = np.array([.6,1.,.5])
return VTK.from_image_data(cells,size)
class TestVTK:
@pytest.fixture(autouse=True)
def _patch_execution_stamp(self, patch_execution_stamp):
print('patched damask.util.execution_stamp')
@pytest.mark.parametrize('cmap',[Colormap.from_predefined('cividis'),'strain'])
def test_show(sef,default,cmap,monkeypatch):
monkeypatch.delenv('DISPLAY',raising=False)
default.show(colormap=cmap)
def test_imageData(self,tmp_path):
cells = np.random.randint(5,10,3)
size = np.random.random(3) + 0.1
origin = np.random.random(3) - 0.5
v = VTK.from_image_data(cells,size,origin)
string = str(v)
string = v.as_ASCII()
v.save(tmp_path/'imageData',False)
vtr = VTK.load(tmp_path/'imageData.vti')
with open(tmp_path/'imageData.vtk','w') as f:
f.write(string)
vtk = VTK.load(tmp_path/'imageData.vtk','VTK_imageData')
assert (string == vtr.as_ASCII() == vtk.as_ASCII())
def test_rectilinearGrid(self,tmp_path):
grid = np.sort(np.random.random((3,10)))
v = VTK.from_rectilinear_grid(grid)
string = str(v)
string = v.as_ASCII()
v.save(tmp_path/'rectilinearGrid',False)
vtr = VTK.load(tmp_path/'rectilinearGrid.vtr')
with open(tmp_path/'rectilinearGrid.vtk','w') as f:
f.write(string)
vtk = VTK.load(tmp_path/'rectilinearGrid.vtk','VTK_rectilinearGrid')
assert (string == vtr.as_ASCII() == vtk.as_ASCII())
def test_polyData(self,tmp_path):
points = np.random.rand(100,3)
v = VTK.from_poly_data(points)
string = str(v)
string = v.as_ASCII()
v.save(tmp_path/'polyData',False)
vtp = VTK.load(tmp_path/'polyData.vtp')
with open(tmp_path/'polyData.vtk','w') as f:
f.write(string)
vtk = VTK.load(tmp_path/'polyData.vtk','polyData')
assert(string == vtp.as_ASCII() == vtk.as_ASCII())
@pytest.mark.parametrize('cell_type,n',[
('VTK_hexahedron',8),
('TETRA',4),
('quad',4),
('VTK_TRIANGLE',3)
]
)
def test_unstructuredGrid(self,tmp_path,cell_type,n):
nodes = np.random.rand(n,3)
connectivity = np.random.choice(np.arange(n),n,False).reshape(-1,n)
v = VTK.from_unstructured_grid(nodes,connectivity,cell_type)
string = str(v)
string = v.as_ASCII()
v.save(tmp_path/'unstructuredGrid',False)
vtu = VTK.load(tmp_path/'unstructuredGrid.vtu')
with open(tmp_path/'unstructuredGrid.vtk','w') as f:
f.write(string)
vtk = VTK.load(tmp_path/'unstructuredGrid.vtk','unstructuredgrid')
assert(string == vtu.as_ASCII() == vtk.as_ASCII())
def test_parallel_out(self,tmp_path):
points = np.random.rand(102,3)
v = VTK.from_poly_data(points)
fname_s = tmp_path/'single.vtp'
fname_p = tmp_path/'parallel.vtp'
v.save(fname_s,False)
v.save(fname_p,True)
for i in range(10):
if os.path.isfile(fname_p) and filecmp.cmp(fname_s,fname_p):
assert(True)
return
time.sleep(.5)
assert(False)
def test_compress(self,tmp_path):
points = np.random.rand(102,3)
v = VTK.from_poly_data(points)
fname_c = tmp_path/'compressed.vtp'
fname_p = tmp_path/'plain.vtp'
v.save(fname_c,parallel=False,compress=False)
v.save(fname_p,parallel=False,compress=True)
assert(VTK.load(fname_c).as_ASCII() == VTK.load(fname_p).as_ASCII())
@pytest.mark.parametrize('fname',['a','a.vtp','a.b','a.b.vtp'])
def test_filename_variations(self,tmp_path,fname):
points = np.random.rand(102,3)
v = VTK.from_poly_data(points)
v.save(tmp_path/fname)
@pytest.mark.parametrize('fname,dataset_type',[('a_file.vtk', None),
('a_file.vtk','vtk'),
('a_file.vtx', None)])
def test_invalid_dataset_type(self,tmp_path,fname,dataset_type):
open(tmp_path/fname,'a').close()
with pytest.raises(TypeError):
VTK.load(tmp_path/fname,dataset_type)
def test_file_not_found(self):
with pytest.raises(FileNotFoundError):
VTK.load('/dev/null')
def test_add_extension(self,tmp_path,default):
default.save(tmp_path/'default.txt',parallel=False)
assert os.path.isfile(tmp_path/'default.txt.vti')
def test_invalid_get(self,default):
with pytest.raises(KeyError):
default.get('does_not_exist')
def test_invalid_add_shape(self,default):
with pytest.raises(ValueError):
default.add(np.ones(3),'valid')
def test_invalid_add_missing_label(self,default):
data = np.random.randint(9,size=np.prod(np.array(default.vtk_data.GetDimensions())-1))
with pytest.raises(ValueError):
default.add(data)
def test_invalid_add_type(self,default):
with pytest.raises(TypeError):
default.add('invalid_type','valid')
@pytest.mark.parametrize('data_type,shape',[(float,(3,)),
(float,(3,3)),
(float,(1,)),
(int,(4,)),
(str,(1,))])
@pytest.mark.parametrize('N_values',[5*6*7,6*7*8])
def test_add_get(self,default,data_type,shape,N_values):
data = np.squeeze(np.random.randint(0,100,(N_values,)+shape)).astype(data_type)
new = default.add(data,'data')
assert (np.squeeze(data.reshape(N_values,-1)) == new.get('data')).all()
@pytest.mark.parametrize('shapes',[{'scalar':(1,),'vector':(3,),'tensor':(3,3)},
{'vector':(6,),'tensor':(3,3)},
{'tensor':(3,3),'scalar':(1,)}])
def test_add_table(self,default,shapes):
N = np.random.choice([default.N_points,default.N_cells])
d = dict()
for k,s in shapes.items():
d[k] = dict(shape = s,
data = np.random.random(N*np.prod(s)).reshape((N,-1)))
new = default.add(Table(np.column_stack([d[k]['data'] for k in shapes.keys()]),shapes))
for k,s in shapes.items():
assert np.allclose(np.squeeze(d[k]['data']),new.get(k),rtol=1e-7)
def test_add_masked(self,default):
data = np.random.rand(5*6*7,3)
masked = ma.MaskedArray(data,mask=data<.4,fill_value=42.)
mask_auto = default.add(masked,'D')
mask_manual = default.add(np.where(masked.mask,masked.fill_value,masked),'D')
assert mask_manual == mask_auto
@pytest.mark.parametrize('data_type,shape',[(float,(3,)),
(float,(3,3)),
(float,(1,)),
(int,(4,)),
(str,(1,))])
@pytest.mark.parametrize('N_values',[5*6*7,6*7*8])
def test_labels(self,default,data_type,shape,N_values):
data = np.squeeze(np.random.randint(0,100,(N_values,)+shape)).astype(data_type)
ALPHABET = np.array(list(string.ascii_lowercase + ' '))
label = ''.join(np.random.choice(ALPHABET, size=10))
new = default.add(data,label)
if N_values == default.N_points: assert label in new.labels['Point Data']
if N_values == default.N_cells: assert label in new.labels['Cell Data']
def test_comments(self,tmp_path,default):
default.comments += 'this is a comment'
default.save(tmp_path/'with_comments',parallel=False)
new = VTK.load(tmp_path/'with_comments.vti')
assert new.comments == ['this is a comment']
@pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA')
def test_compare_reference_polyData(self,update,ref_path,tmp_path):
points=np.dstack((np.linspace(0.,1.,10),np.linspace(0.,2.,10),np.linspace(-1.,1.,10))).squeeze()
polyData = VTK.from_poly_data(points).add(points,'coordinates')
if update:
polyData.save(ref_path/'polyData')
else:
reference = VTK.load(ref_path/'polyData.vtp')
assert polyData.as_ASCII() == reference.as_ASCII() and \
np.allclose(polyData.get('coordinates'),points)
@pytest.mark.xfail(int(vtk.vtkVersion.GetVTKVersion().split('.')[0])<8, reason='missing METADATA')
def test_compare_reference_rectilinearGrid(self,update,ref_path,tmp_path):
grid = [np.arange(4)**2.,
np.arange(5)**2.,
np.arange(6)**2.] # ParaView renders tetrahedral meshing unless using float coordinates!
coords = np.stack(np.meshgrid(*grid,indexing='ij'),axis=-1)
c = coords[:-1,:-1,:-1,:].reshape(-1,3,order='F')
n = coords[:,:,:,:].reshape(-1,3,order='F')
rectilinearGrid = VTK.from_rectilinear_grid(grid) \
.add(np.ascontiguousarray(c),'cell') \
.add(np.ascontiguousarray(n),'node')
if update:
rectilinearGrid.save(ref_path/'rectilinearGrid')
else:
reference = VTK.load(ref_path/'rectilinearGrid.vtr')
assert rectilinearGrid.as_ASCII() == reference.as_ASCII() and \
np.allclose(rectilinearGrid.get('cell'),c)