From b731b1e7684a6bdfb873b31a04a91d7499bd0081 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 08:49:49 +0200 Subject: [PATCH 01/16] Geom.to_vtk improvements - should be integer - should have a test --- python/damask/_geom.py | 2 +- python/tests/test_Geom.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 0f1c35e42..de0b04c79 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -358,7 +358,7 @@ class Geom: """ g = VTK.from_file(fname).geom N_cells = g.GetNumberOfCells() - microstructure = np.zeros(N_cells) + microstructure = np.zeros(N_cells,'i') grid = np.array(g.GetDimensions())-1 bbox = np.array(g.GetBounds()).reshape(3,2).T size = bbox[1] - bbox[0] diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index 4fb1ae00a..60a4f4fef 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -1,3 +1,6 @@ +import os +import time + import pytest import numpy as np @@ -65,8 +68,14 @@ class TestGeom: new = Geom.from_file(f) assert geom_equal(new,default) - def test_export_vtk(self,default,tmpdir): + def test_read_write_vtk(self,default,tmpdir): default.to_vtk(str(tmpdir.join('default'))) + for _ in range(3): + if os.path.exists(tmpdir.join('default.vtr')): break + time.sleep(1) + new = Geom.from_vtk(str(tmpdir.join('default.vtr'))) + assert geom_equal(new,default) + @pytest.mark.parametrize('pack',[True,False]) def test_pack(self,default,tmpdir,pack): From 5fb2d30ee4a9adc539ce071cbe2defe74fab5e11 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 09:02:17 +0200 Subject: [PATCH 02/16] fast and for arbitrary type --- python/damask/_geom.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index de0b04c79..382ae4d32 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -6,6 +6,7 @@ from functools import partial import numpy as np from scipy import ndimage,spatial +from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np from . import environment from . import Rotation @@ -357,8 +358,6 @@ class Geom: """ g = VTK.from_file(fname).geom - N_cells = g.GetNumberOfCells() - microstructure = np.zeros(N_cells,'i') grid = np.array(g.GetDimensions())-1 bbox = np.array(g.GetBounds()).reshape(3,2).T size = bbox[1] - bbox[0] @@ -366,9 +365,7 @@ class Geom: celldata = g.GetCellData() for a in range(celldata.GetNumberOfArrays()): if celldata.GetArrayName(a) == 'microstructure': - array = celldata.GetArray(a) - for c in range(N_cells): - microstructure[c] = array.GetValue(c) + microstructure = vtk_to_np(celldata.GetArray(a)) return Geom(microstructure.reshape(grid,order='F'),size,bbox[0]) From 975db01f31613d16ae16f4b68912a1c08127f037 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 09:17:08 +0200 Subject: [PATCH 03/16] microstructure -> materialpoint at least for new functionality --- python/damask/_geom.py | 22 ++++++++++++---------- python/tests/test_Geom.py | 37 ++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 382ae4d32..30aebe254 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -46,11 +46,11 @@ class Geom: def __repr__(self): """Basic information on geometry definition.""" return util.srepr([ - f'grid a b c: {util.srepr(self.get_grid ()," x ")}', - f'size x y z: {util.srepr(self.get_size ()," x ")}', - f'origin x y z: {util.srepr(self.get_origin()," ")}', - f'# microstructures: {self.N_microstructure}', - f'max microstructure: {np.nanmax(self.microstructure)}', + f'grid a b c: {util.srepr(self.get_grid ()," x ")}', + f'size x y z: {util.srepr(self.get_size ()," x ")}', + f'origin x y z: {util.srepr(self.get_origin()," ")}', + f'# materialpoints: {self.N_microstructure}', + f'max materialpoint: {np.nanmax(self.microstructure)}', ]) @@ -364,10 +364,12 @@ class Geom: celldata = g.GetCellData() for a in range(celldata.GetNumberOfArrays()): - if celldata.GetArrayName(a) == 'microstructure': - microstructure = vtk_to_np(celldata.GetArray(a)) + if celldata.GetArrayName(a) == 'materialpoint': + materialpoint = vtk_to_np(celldata.GetArray(a)) + return Geom(materialpoint.reshape(grid,order='F'),size,bbox[0]) + + raise ValueError(f'"materialpoint" array not found in {fname}') - return Geom(microstructure.reshape(grid,order='F'),size,bbox[0]) @staticmethod @@ -522,7 +524,7 @@ class Geom: """ v = VTK.from_rectilinearGrid(self.grid,self.size,self.origin) - v.add(self.microstructure.flatten(order='F'),'microstructure') + v.add(self.microstructure.flatten(order='F'),'materialpoint') if fname: v.write(fname) @@ -747,7 +749,7 @@ class Geom: np.nanmax(self.microstructure)+1 if fill is None else fill, dtype) - LL = np.clip( offset, 0,np.minimum(self.grid, grid+offset)) # noqa + LL = np.clip( offset, 0,np.minimum(self.grid, grid+offset)) UR = np.clip( offset+grid, 0,np.minimum(self.grid, grid+offset)) ll = np.clip(-offset, 0,np.minimum( grid,self.grid-offset)) ur = np.clip(-offset+self.grid,0,np.minimum( grid,self.grid-offset)) diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index 60a4f4fef..d037a2a65 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -4,6 +4,7 @@ import time import pytest import numpy as np +from damask import VTK from damask import Geom from damask import Rotation from damask import util @@ -50,37 +51,47 @@ class TestGeom: def test_write_read_str(self,default,tmpdir): - default.to_file(str(tmpdir.join('default.geom'))) - new = Geom.from_file(str(tmpdir.join('default.geom'))) + default.to_file(str(tmpdir/'default.geom')) + new = Geom.from_file(str(tmpdir/'default.geom')) assert geom_equal(new,default) def test_write_read_file(self,default,tmpdir): - with open(tmpdir.join('default.geom'),'w') as f: + with open(tmpdir/'default.geom','w') as f: default.to_file(f) - with open(tmpdir.join('default.geom')) as f: + with open(tmpdir/'default.geom') as f: new = Geom.from_file(f) assert geom_equal(new,default) def test_write_show(self,default,tmpdir): - with open(tmpdir.join('str.geom'),'w') as f: + with open(tmpdir/'str.geom','w') as f: f.write(default.show()) - with open(tmpdir.join('str.geom')) as f: + with open(tmpdir/'str.geom') as f: new = Geom.from_file(f) assert geom_equal(new,default) def test_read_write_vtk(self,default,tmpdir): - default.to_vtk(str(tmpdir.join('default'))) - for _ in range(3): - if os.path.exists(tmpdir.join('default.vtr')): break - time.sleep(1) - new = Geom.from_vtk(str(tmpdir.join('default.vtr'))) + default.to_vtk(tmpdir/'default') + for _ in range(10): + time.sleep(.2) + if os.path.exists(tmpdir/'default.vtr'): break + + new = Geom.from_vtk(tmpdir/'default.vtr') assert geom_equal(new,default) + def test_invalid_vtk(self,tmpdir): + v = VTK.from_rectilinearGrid(np.random.randint(5,10,3)*2,np.random.random(3) + 1.0) + v.write(tmpdir/'no_materialpoint.vtr') + for _ in range(10): + time.sleep(.2) + if os.path.exists(tmpdir/'no_materialpoint.vtr'): break + with pytest.raises(ValueError): + Geom.from_vtk(tmpdir/'no_materialpoint.vtr') + @pytest.mark.parametrize('pack',[True,False]) def test_pack(self,default,tmpdir,pack): - default.to_file(tmpdir.join('default.geom'),pack=pack) - new = Geom.from_file(tmpdir.join('default.geom')) + default.to_file(tmpdir/'default.geom',pack=pack) + new = Geom.from_file(tmpdir/'default.geom') assert geom_equal(new,default) def test_invalid_combination(self,default): From 64e7582e8e621e2bc50c1bf68c661436de40a206 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 10:02:22 +0200 Subject: [PATCH 04/16] consistent interface to ndimage filters Boolean 'periodic' sets mode to 'wrap' or 'nearest' --- python/damask/_geom.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 30aebe254..2f7f18066 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -621,11 +621,10 @@ class Geom: if 'x' in directions: ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) - #ToDo: self.add_comments('geom.py:mirror v{}'.format(version) return self.update(ms,rescale=True) - def scale(self,grid): + def scale(self,grid,periodic=True): """ Scale microstructure to new grid. @@ -633,22 +632,23 @@ class Geom: ---------- grid : numpy.ndarray of shape (3) Number of grid points in x,y,z direction. + periodic : Boolean, optional + Assume geometry to be periodic. Defaults to True. """ - #ToDo: self.add_comments('geom.py:scale v{}'.format(version) return self.update( ndimage.interpolation.zoom( self.microstructure, grid/self.get_grid(), output=self.microstructure.dtype, order=0, - mode='nearest', + mode=('wrap' if periodic else 'nearest'), prefilter=False ) ) - def clean(self,stencil=3,mode='nearest',selection=None): + def clean(self,stencil=3,selection=None,periodic=True): """ Smooth microstructure by selecting most frequent index within given stencil at each location. @@ -656,11 +656,10 @@ class Geom: ---------- stencil : int, optional Size of smoothing stencil. - mode : string, optional - The mode parameter determines how the input array is extended beyond its boundaries. - Default is 'nearest'. See scipy.ndimage.generic_filter for all options. selection : list, optional Field values that can be altered. Defaults to all. + periodic : Boolean, optional + Assume geometry to be periodic. Defaults to True. """ def mostFrequent(arr,selection=None): @@ -671,12 +670,11 @@ class Geom: else: return me - #ToDo: self.add_comments('geom.py:clean v{}'.format(version) return self.update(ndimage.filters.generic_filter( self.microstructure, mostFrequent, size=(stencil if selection is None else stencil//2*2+1,)*3, - mode=mode, + mode=('wrap' if periodic else 'nearest'), extra_keywords=dict(selection=selection), ).astype(self.microstructure.dtype) ) @@ -688,7 +686,6 @@ class Geom: for i, oldID in enumerate(np.unique(self.microstructure)): renumbered = np.where(self.microstructure == oldID, i+1, renumbered) - #ToDo: self.add_comments('geom.py:renumber v{}'.format(version) return self.update(renumbered) @@ -723,7 +720,6 @@ class Geom: origin = self.origin-(np.asarray(microstructure_in.shape)-self.grid)*.5 * self.size/self.grid - #ToDo: self.add_comments('geom.py:rotate v{}'.format(version) return self.update(microstructure_in,origin=origin,rescale=True) @@ -756,7 +752,6 @@ class Geom: canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.microstructure[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] - #ToDo: self.add_comments('geom.py:canvas v{}'.format(version) return self.update(canvas,origin=self.origin+offset*self.size/self.grid,rescale=True) @@ -776,7 +771,6 @@ class Geom: for from_ms,to_ms in zip(from_microstructure,to_microstructure): substituted[self.microstructure==from_ms] = to_ms - #ToDo: self.add_comments('geom.py:substitute v{}'.format(version) return self.update(substituted) @@ -822,5 +816,4 @@ class Geom: extra_keywords={'trigger':trigger}) microstructure = np.ma.MaskedArray(self.microstructure + offset_, np.logical_not(mask)) - #ToDo: self.add_comments('geom.py:vicinity_offset v{}'.format(version) return self.update(microstructure) From 07af7b2f988fb548ad6d134337aecc51984a9f48 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 10:46:15 +0200 Subject: [PATCH 05/16] geom is written to vtr exlcusively, not to general vtk base tests on vtr --- python/damask/_geom.py | 20 +++++++------ python/tests/reference/Geom/clean.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_2_1_False.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_2_1_True.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_2_None_False.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_2_None_True.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_3_1_False.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_3_1_True.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_3_None_False.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_3_None_True.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_4_1_False.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_4_1_True.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_4_None_False.vtr | 25 ++++++++++++++++ .../reference/Geom/clean_4_None_True.vtr | 25 ++++++++++++++++ .../tests/reference/Geom/clean_stencil=1.geom | 25 ---------------- .../tests/reference/Geom/clean_stencil=2.geom | 25 ---------------- .../tests/reference/Geom/clean_stencil=3.geom | 25 ---------------- .../tests/reference/Geom/clean_stencil=4.geom | 25 ---------------- python/tests/test_Geom.py | 30 +++++++++++-------- 19 files changed, 354 insertions(+), 121 deletions(-) create mode 100644 python/tests/reference/Geom/clean.vtr create mode 100644 python/tests/reference/Geom/clean_2_1_False.vtr create mode 100644 python/tests/reference/Geom/clean_2_1_True.vtr create mode 100644 python/tests/reference/Geom/clean_2_None_False.vtr create mode 100644 python/tests/reference/Geom/clean_2_None_True.vtr create mode 100644 python/tests/reference/Geom/clean_3_1_False.vtr create mode 100644 python/tests/reference/Geom/clean_3_1_True.vtr create mode 100644 python/tests/reference/Geom/clean_3_None_False.vtr create mode 100644 python/tests/reference/Geom/clean_3_None_True.vtr create mode 100644 python/tests/reference/Geom/clean_4_1_False.vtr create mode 100644 python/tests/reference/Geom/clean_4_1_True.vtr create mode 100644 python/tests/reference/Geom/clean_4_None_False.vtr create mode 100644 python/tests/reference/Geom/clean_4_None_True.vtr delete mode 100644 python/tests/reference/Geom/clean_stencil=1.geom delete mode 100644 python/tests/reference/Geom/clean_stencil=2.geom delete mode 100644 python/tests/reference/Geom/clean_stencil=3.geom delete mode 100644 python/tests/reference/Geom/clean_stencil=4.geom diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 2f7f18066..722df2524 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -347,17 +347,18 @@ class Geom: @staticmethod - def from_vtk(fname): + def from_vtr(fname): """ - Read a geom from a VTK file. + Read a VTK rectilinear grid. Parameters ---------- - fname : str or file handle + fname : str or or pathlib.Path Geometry file to read. + Valid extension is .vtr, it will be appended if not given. """ - g = VTK.from_file(fname).geom + g = VTK.from_file(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr').geom grid = np.array(g.GetDimensions())-1 bbox = np.array(g.GetBounds()).reshape(3,2).T size = bbox[1] - bbox[0] @@ -513,21 +514,22 @@ class Geom: f.write(f'{reps} of {former}\n') - def to_vtk(self,fname=None): + def to_vtr(self,fname=None): """ - Generates vtk file. + Generates vtk rectilinear grid. Parameters ---------- fname : str, optional - Vtk file to write. If no file is given, a string is returned. + Filename to write. If no file is given, a string is returned. + Valid extension is .vtr, it will be appended if not given. """ v = VTK.from_rectilinearGrid(self.grid,self.size,self.origin) v.add(self.microstructure.flatten(order='F'),'materialpoint') if fname: - v.write(fname) + v.write(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr') else: sys.stdout.write(v.__repr__()) @@ -642,7 +644,7 @@ class Geom: grid/self.get_grid(), output=self.microstructure.dtype, order=0, - mode=('wrap' if periodic else 'nearest'), + mode=('wrap' if periodic else 'nearest'), prefilter=False ) ) diff --git a/python/tests/reference/Geom/clean.vtr b/python/tests/reference/Geom/clean.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_2_1_False.vtr b/python/tests/reference/Geom/clean_2_1_False.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_2_1_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_2_1_True.vtr b/python/tests/reference/Geom/clean_2_1_True.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_2_1_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_2_None_False.vtr b/python/tests/reference/Geom/clean_2_None_False.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_2_None_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_2_None_True.vtr b/python/tests/reference/Geom/clean_2_None_True.vtr new file mode 100644 index 000000000..fe04087d2 --- /dev/null +++ b/python/tests/reference/Geom/clean_2_None_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAMQAAAA==eF7tzCEOADAMxLDr/v/o8pLSaTMwi1JJCoAvnGHrN7f/AAAAAAAAAAAAeE8DQvkLTQ== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_1_False.vtr b/python/tests/reference/Geom/clean_3_1_False.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_3_1_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_1_True.vtr b/python/tests/reference/Geom/clean_3_1_True.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_3_1_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_None_False.vtr b/python/tests/reference/Geom/clean_3_None_False.vtr new file mode 100644 index 000000000..c2ad86f43 --- /dev/null +++ b/python/tests/reference/Geom/clean_3_None_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAOgAAAA==eF7t1CEOACAMBMHS/z8aXwNJSagYMe6y8jIislgNtTW9d9oD/PL6r6b3AAAAAAAAAAAA4MYGlRYLYA== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_None_True.vtr b/python/tests/reference/Geom/clean_3_None_True.vtr new file mode 100644 index 000000000..b4d19ebcf --- /dev/null +++ b/python/tests/reference/Geom/clean_3_None_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANwAAAA==eF7t1KERADAMA7Gk+w9dWpYCswiI+R66q6rDzmPa/kj3ALZK/2m6BwAAAAAAAAAAAJMLZrELTQ== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_1_False.vtr b/python/tests/reference/Geom/clean_4_1_False.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_4_1_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_1_True.vtr b/python/tests/reference/Geom/clean_4_1_True.vtr new file mode 100644 index 000000000..c76ce3988 --- /dev/null +++ b/python/tests/reference/Geom/clean_4_1_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CECACAMxLBj/380fhYwIyK2spWkmnWgt6b3AF65/avfegAAAAAAAAAAAMy0AfYtC2k= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_None_False.vtr b/python/tests/reference/Geom/clean_4_None_False.vtr new file mode 100644 index 000000000..811d7dc8f --- /dev/null +++ b/python/tests/reference/Geom/clean_4_None_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAOQAAAA==eF7t1CESACAMA8HS/z8aX4OgCGDFuszJZERkMTbU1us9gFO6/+q23moPAAAAAAAAAADAnybPzQto + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_None_True.vtr b/python/tests/reference/Geom/clean_4_None_True.vtr new file mode 100644 index 000000000..88a8643d9 --- /dev/null +++ b/python/tests/reference/Geom/clean_4_None_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAJAAAAA==eF7twwEJAAAMBKH7/qWXY6DgqqmqqqqqqqqqqqqqPnhyUwtB + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_stencil=1.geom b/python/tests/reference/Geom/clean_stencil=1.geom deleted file mode 100644 index 3e6f6fe9c..000000000 --- a/python/tests/reference/Geom/clean_stencil=1.geom +++ /dev/null @@ -1,25 +0,0 @@ -4 header -grid a 8 b 5 c 4 -size x 8e-06 y 5e-06 z 4e-06 -origin x 0.0 y 0.0 z 0.0 -homogenization 1 - 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 1 - 1 1 1 1 1 1 1 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 27 28 29 30 31 32 33 -34 35 36 37 38 39 40 41 - 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 - 2 2 2 2 2 2 2 2 - 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 27 28 29 30 31 32 -33 34 35 36 37 38 39 40 diff --git a/python/tests/reference/Geom/clean_stencil=2.geom b/python/tests/reference/Geom/clean_stencil=2.geom deleted file mode 100644 index 14c1fa5e2..000000000 --- a/python/tests/reference/Geom/clean_stencil=2.geom +++ /dev/null @@ -1,25 +0,0 @@ -4 header -grid a 8 b 5 c 4 -size x 8e-06 y 5e-06 z 4e-06 -origin x 0.0 y 0.0 z 0.0 -homogenization 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -1 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 diff --git a/python/tests/reference/Geom/clean_stencil=3.geom b/python/tests/reference/Geom/clean_stencil=3.geom deleted file mode 100644 index 3aea8ffa5..000000000 --- a/python/tests/reference/Geom/clean_stencil=3.geom +++ /dev/null @@ -1,25 +0,0 @@ -4 header -grid a 8 b 5 c 4 -size x 8e-06 y 5e-06 z 4e-06 -origin x 0.0 y 0.0 z 0.0 -homogenization 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -2 2 1 1 1 1 1 1 -2 2 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 diff --git a/python/tests/reference/Geom/clean_stencil=4.geom b/python/tests/reference/Geom/clean_stencil=4.geom deleted file mode 100644 index 595e04b23..000000000 --- a/python/tests/reference/Geom/clean_stencil=4.geom +++ /dev/null @@ -1,25 +0,0 @@ -4 header -grid a 8 b 5 c 4 -size x 8e-06 y 5e-06 z 4e-06 -origin x 0.0 y 0.0 z 0.0 -homogenization 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -2 2 2 2 1 1 1 1 -2 2 2 2 1 1 1 1 -2 2 2 2 1 1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 -2 2 2 2 2 2 2 2 diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index d037a2a65..0ac633152 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -69,23 +69,23 @@ class TestGeom: new = Geom.from_file(f) assert geom_equal(new,default) - def test_read_write_vtk(self,default,tmpdir): - default.to_vtk(tmpdir/'default') + def test_read_write_vtr(self,default,tmpdir): + default.to_vtr(tmpdir/'default') for _ in range(10): time.sleep(.2) if os.path.exists(tmpdir/'default.vtr'): break - new = Geom.from_vtk(tmpdir/'default.vtr') + new = Geom.from_vtr(tmpdir/'default.vtr') assert geom_equal(new,default) - def test_invalid_vtk(self,tmpdir): + def test_invalid_vtr(self,tmpdir): v = VTK.from_rectilinearGrid(np.random.randint(5,10,3)*2,np.random.random(3) + 1.0) v.write(tmpdir/'no_materialpoint.vtr') for _ in range(10): time.sleep(.2) if os.path.exists(tmpdir/'no_materialpoint.vtr'): break with pytest.raises(ValueError): - Geom.from_vtk(tmpdir/'no_materialpoint.vtr') + Geom.from_vtr(tmpdir/'no_materialpoint.vtr') @pytest.mark.parametrize('pack',[True,False]) @@ -136,13 +136,19 @@ class TestGeom: assert geom_equal(modified,Geom.from_file(reference)) @pytest.mark.parametrize('stencil',[1,2,3,4]) - def test_clean(self,default,update,reference_dir,stencil): - modified = default.copy() - modified.clean(stencil) - tag = f'stencil={stencil}' - reference = reference_dir/f'clean_{tag}.geom' - if update: modified.to_file(reference) - assert geom_equal(modified,Geom.from_file(reference)) + @pytest.mark.parametrize('selection',[None,1]) + @pytest.mark.parametrize('periodic',[True,False]) + def test_clean(self,update,reference_dir,stencil,selection,periodic): + current = Geom.from_vtr((reference_dir/'clean').with_suffix('.vtr')) + current.clean(stencil,None if selection is None else [selection],periodic) + reference = reference_dir/f'clean_{stencil}_{selection}_{periodic}' + altered = stencil !=1 and selection is not None + if update and stencil !=1: + current.to_vtr(reference) + for _ in range(10): + time.sleep(.2) + if os.path.exists(reference.with_suffix('.vtr')): break + assert geom_equal(current,Geom.from_vtr(reference if stencil !=1 else reference_dir/'clean')) @pytest.mark.parametrize('grid',[ (10,11,10), From 6f79573140f9a3b601cc94e17e13576c68baab76 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 11:05:56 +0200 Subject: [PATCH 06/16] more test coverage --- python/damask/_geom.py | 4 +-- .../tests/reference/Geom/clean_2_2_False.vtr | 25 +++++++++++++++++++ .../tests/reference/Geom/clean_2_2_True.vtr | 25 +++++++++++++++++++ .../tests/reference/Geom/clean_3_2_False.vtr | 25 +++++++++++++++++++ .../tests/reference/Geom/clean_3_2_True.vtr | 25 +++++++++++++++++++ .../tests/reference/Geom/clean_4_2_False.vtr | 25 +++++++++++++++++++ .../tests/reference/Geom/clean_4_2_True.vtr | 25 +++++++++++++++++++ python/tests/test_Geom.py | 8 ++++-- 8 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 python/tests/reference/Geom/clean_2_2_False.vtr create mode 100644 python/tests/reference/Geom/clean_2_2_True.vtr create mode 100644 python/tests/reference/Geom/clean_3_2_False.vtr create mode 100644 python/tests/reference/Geom/clean_3_2_True.vtr create mode 100644 python/tests/reference/Geom/clean_4_2_False.vtr create mode 100644 python/tests/reference/Geom/clean_4_2_True.vtr diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 722df2524..c8963b616 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -608,9 +608,7 @@ class Geom: """ valid = {'x','y','z'} - if not all(isinstance(d, str) for d in directions): - raise TypeError('Directions are not of type str.') - elif not set(directions).issubset(valid): + if not set(directions).issubset(valid): raise ValueError(f'Invalid direction {set(directions).difference(valid)} specified.') limits = [None,None] if reflect else [-2,0] diff --git a/python/tests/reference/Geom/clean_2_2_False.vtr b/python/tests/reference/Geom/clean_2_2_False.vtr new file mode 100644 index 000000000..c2ad86f43 --- /dev/null +++ b/python/tests/reference/Geom/clean_2_2_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAOgAAAA==eF7t1CEOACAMBMHS/z8aXwNJSagYMe6y8jIislgNtTW9d9oD/PL6r6b3AAAAAAAAAAAA4MYGlRYLYA== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_2_2_True.vtr b/python/tests/reference/Geom/clean_2_2_True.vtr new file mode 100644 index 000000000..b4d19ebcf --- /dev/null +++ b/python/tests/reference/Geom/clean_2_2_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANwAAAA==eF7t1KERADAMA7Gk+w9dWpYCswiI+R66q6rDzmPa/kj3ALZK/2m6BwAAAAAAAAAAAJMLZrELTQ== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_2_False.vtr b/python/tests/reference/Geom/clean_3_2_False.vtr new file mode 100644 index 000000000..c2ad86f43 --- /dev/null +++ b/python/tests/reference/Geom/clean_3_2_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAOgAAAA==eF7t1CEOACAMBMHS/z8aXwNJSagYMe6y8jIislgNtTW9d9oD/PL6r6b3AAAAAAAAAAAA4MYGlRYLYA== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_3_2_True.vtr b/python/tests/reference/Geom/clean_3_2_True.vtr new file mode 100644 index 000000000..b4d19ebcf --- /dev/null +++ b/python/tests/reference/Geom/clean_3_2_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANwAAAA==eF7t1KERADAMA7Gk+w9dWpYCswiI+R66q6rDzmPa/kj3ALZK/2m6BwAAAAAAAAAAAJMLZrELTQ== + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_2_False.vtr b/python/tests/reference/Geom/clean_4_2_False.vtr new file mode 100644 index 000000000..7665bdde2 --- /dev/null +++ b/python/tests/reference/Geom/clean_4_2_False.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAANQAAAA==eF7t1CEOACAMBMGj/380Fk+TQjJi7MqtJHVYlypv9wB+0f2+7h4AAAAAAAAAAABM2HWwC1M= + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/reference/Geom/clean_4_2_True.vtr b/python/tests/reference/Geom/clean_4_2_True.vtr new file mode 100644 index 000000000..88a8643d9 --- /dev/null +++ b/python/tests/reference/Geom/clean_4_2_True.vtr @@ -0,0 +1,25 @@ + + + + + + + + + AQAAAACAAAAALQAAJAAAAA==eF7twwEJAAAMBKH7/qWXY6DgqqmqqqqqqqqqqqqqPnhyUwtB + + + + + AQAAAACAAACoAAAAVQAAAA==eF5jYICAWTNBYKU9hN5pb2IMAoeh/JP2EFUXoOKX7dPTQOAaVP6m/dkzIHAHqu4BVPwhVP1jqPwTqL5nUHUvoOpeQtW9hqp7A1X3Dqrugz0ASSZF3Q== + + + AQAAAACAAACYAAAAVgAAAA==eF5jYIAAmeOFQLTGHkLvsQ8Fg6NQ/hn7IjDjIlT8qr1F32MgugGVv2MPMeUBVN1D+8cQBVD1T+3BymSeQ/W9sF8FBq+g+t/Yg4Ut3kHN+WAPAAVdQE4= + + + AQAAAACAAABIAAAAIgAAAA==eF5jYEAGB+wh9AUofQNKP4DST6D0Cyj9Bkp/sAcAAU8I6Q== + + + + + diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index 0ac633152..479dd43fc 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -135,14 +135,18 @@ class TestGeom: if update: modified.to_file(reference) assert geom_equal(modified,Geom.from_file(reference)) + @pytest.mark.parametrize('directions',[(1,2,'y'),('a','b','x'),[1]]) + def test_mirror_invalid(self,default,directions): + with pytest.raises(ValueError): + default.mirror(directions) + @pytest.mark.parametrize('stencil',[1,2,3,4]) - @pytest.mark.parametrize('selection',[None,1]) + @pytest.mark.parametrize('selection',[None,1,2]) @pytest.mark.parametrize('periodic',[True,False]) def test_clean(self,update,reference_dir,stencil,selection,periodic): current = Geom.from_vtr((reference_dir/'clean').with_suffix('.vtr')) current.clean(stencil,None if selection is None else [selection],periodic) reference = reference_dir/f'clean_{stencil}_{selection}_{periodic}' - altered = stencil !=1 and selection is not None if update and stencil !=1: current.to_vtr(reference) for _ in range(10): From d65371d42f8471ed255d2685a46a913a2100b4b8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 12:55:55 +0200 Subject: [PATCH 07/16] removed unused and untested functionality PEP 20: Explicit is better than implicit. --- python/damask/_geom.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index c8963b616..571ae12eb 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -189,10 +189,7 @@ class Geom: physical size of the microstructure in meter. """ - if size is None: - grid = np.asarray(self.microstructure.shape) - self.size = grid/np.max(grid) - else: + if size is not None: if len(size) != 3 or any(np.array(size) <= 0): raise ValueError(f'Invalid size {size}') else: From a1c78b778a1bed0faf40dd8078a05a2deeb77e21 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 23:22:53 +0200 Subject: [PATCH 08/16] WIP: track history in VTK objects --- python/damask/_vtk.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 00aa2f4e9..d12e80e32 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -232,6 +232,33 @@ class VTK: raise TypeError + def get_comments(self): + """Return the comments.""" + fielddata = self.geom.GetFieldData() + for a in range(fielddata.GetNumberOfArrays()): + if fielddata.GetArrayName(a) == 'comments': + comments = fielddata.GetAbstractArray(a) + return [comments.GetValue(i) for i in range(comments.GetNumberOfValues())] + return [] + + + def set_comments(self,comments): + """ + Add Comments. + + Parameters + ---------- + comments : str or list of str + Comments to add + + """ + s = vtk.vtkStringArray() + s.SetName('comments') + for c in [comments] if isinstance(comments,str) else comments: + s.InsertNextValue(c) + self.geom.GetFieldData().AddArray(s) + + def __repr__(self): """ASCII representation of the VTK data.""" writer = vtk.vtkDataSetWriter() @@ -240,7 +267,10 @@ class VTK: writer.SetInputData(self.geom) writer.Write() return writer.GetOutputString() - + celldata = g.GetCellData() + for a in range(celldata.GetNumberOfArrays()): + if celldata.GetArrayName(a) == 'materialpoint': + materialpoint = vtk_to_np(celldata.GetArray(a)) def show(self): """ From 9867830d684921502f734765aa7f8d0c5340fd67 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 23 Aug 2020 23:23:23 +0200 Subject: [PATCH 09/16] store history of geometry modifications --- python/damask/_geom.py | 20 +++++++++++++++----- python/damask/util.py | 8 ++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 571ae12eb..8039a0038 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -1,7 +1,8 @@ import sys import copy -from io import StringIO +import inspect import multiprocessing +from io import StringIO from functools import partial import numpy as np @@ -416,8 +417,8 @@ class Geom: else: microstructure = microstructure.reshape(grid) - #ToDo: comments = 'geom.py:from_Laguerre_tessellation v{}'.format(version) - return Geom(microstructure+1,size,homogenization=1) + creator = util.edit_info('damask.Result.'+inspect.stack()[0][3]) + return Geom(microstructure+1,size,homogenization=1,comments=creator) @staticmethod @@ -441,8 +442,8 @@ class Geom: KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds) devNull,microstructure = KDTree.query(coords) - #ToDo: comments = 'geom.py:from_Voronoi_tessellation v{}'.format(version) - return Geom(microstructure.reshape(grid)+1,size,homogenization=1) + creator = util.edit_info('damask.Result.'+inspect.stack()[0][3]) + return Geom(microstructure.reshape(grid)+1,size,homogenization=1,comments=creator) def to_file(self,fname,pack=None): @@ -588,6 +589,7 @@ class Geom: fill_ = np.full_like(self.microstructure,np.nanmax(self.microstructure)+1 if fill is None else fill) ms = np.ma.MaskedArray(fill_,np.logical_not(mask) if inverse else mask) + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(ms) @@ -618,6 +620,7 @@ class Geom: if 'x' in directions: ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(ms,rescale=True) @@ -633,6 +636,7 @@ class Geom: Assume geometry to be periodic. Defaults to True. """ + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update( ndimage.interpolation.zoom( self.microstructure, @@ -667,6 +671,7 @@ class Geom: else: return me + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(ndimage.filters.generic_filter( self.microstructure, mostFrequent, @@ -683,6 +688,7 @@ class Geom: for i, oldID in enumerate(np.unique(self.microstructure)): renumbered = np.where(self.microstructure == oldID, i+1, renumbered) + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(renumbered) @@ -717,6 +723,7 @@ class Geom: origin = self.origin-(np.asarray(microstructure_in.shape)-self.grid)*.5 * self.size/self.grid + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(microstructure_in,origin=origin,rescale=True) @@ -749,6 +756,7 @@ class Geom: canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.microstructure[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(canvas,origin=self.origin+offset*self.size/self.grid,rescale=True) @@ -768,6 +776,7 @@ class Geom: for from_ms,to_ms in zip(from_microstructure,to_microstructure): substituted[self.microstructure==from_ms] = to_ms + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(substituted) @@ -813,4 +822,5 @@ class Geom: extra_keywords={'trigger':trigger}) microstructure = np.ma.MaskedArray(self.microstructure + offset_, np.logical_not(mask)) + self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) return self.update(microstructure) diff --git a/python/damask/util.py b/python/damask/util.py index 733fd0010..f83fc4c62 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -9,6 +9,8 @@ from optparse import Option import numpy as np +import damask + # limit visibility __all__=[ 'srepr', @@ -20,6 +22,7 @@ __all__=[ 'scale_to_coprime', 'return_message', 'extendableOption', + 'edit_info' ] #################################################################################################### @@ -175,6 +178,11 @@ def scale_to_coprime(v): return m +def edit_info(who): + now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z') + return f'{who} v{damask.version} ({now})' + + #################################################################################################### # Classes #################################################################################################### From c7cbd961a1e771bd6b925f4a3e7d5a000dd3d767 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 00:31:38 +0200 Subject: [PATCH 10/16] more systematic monkeypatching allows comparison of reference files (log/history does not contain information about damask.version and datetime.datetime.now) --- python/tests/conftest.py | 26 ++++++++++++++++++++++---- python/tests/test_Colormap.py | 8 +++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 87aa9a363..a6f6e62ad 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -1,11 +1,29 @@ from pathlib import Path +import datetime + import numpy as np - import pytest +from _pytest.monkeypatch import MonkeyPatch -# Use to monkeypatch damask.version (for comparsion to reference files that contain version information) -def pytest_configure(): - pytest.dummy_version = '99.99.99-9999-pytest' +import damask + + +patched_version = '99.99.99-9999-pytest' +@pytest.fixture +def patch_damask_version(monkeysession): + """Set damask.version for reproducible tests results.""" + monkeysession.setattr(damask, 'version', patched_version) + +patched_date = datetime.datetime(2019, 11, 2, 11, 58, 0) +@pytest.fixture +def patch_datetime_now(monkeysession): + """Set datetime.datetime.now for reproducible tests results.""" + class mydatetime: + @classmethod + def now(cls): + return patched_date + + monkeysession.setattr(datetime, 'datetime', mydatetime) def pytest_addoption(parser): diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index b3309f12b..4fe0cc9fb 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -17,6 +17,10 @@ def reference_dir(reference_dir_base): class TestColormap: + @pytest.fixture(autouse=True) + def _patch_damask_version(self, patch_damask_version): + print('patched damask.version') + def test_conversion(self): specials = np.array([[0.,0.,0.], @@ -29,7 +33,6 @@ class TestColormap: [1.,1.,1.] ]) rgbs = np.vstack((specials,np.random.rand(100,3))) - pass # class not integrated for rgb in rgbs: print('rgb',rgb) @@ -150,8 +153,7 @@ class TestColormap: ('GOM','.legend'), ('Gmsh','.msh') ]) - def test_compare_reference(self,format,ext,tmpdir,reference_dir,update,monkeypatch): - monkeypatch.setattr(damask, 'version', pytest.dummy_version) + def test_compare_reference(self,format,ext,tmpdir,reference_dir,update): name = 'binary' c = Colormap.from_predefined(name) if update: From 44015082a3b4d3302964ac081a8aebba25473fab Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 00:34:07 +0200 Subject: [PATCH 11/16] dead code (copy and paste error) --- python/damask/_vtk.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index d12e80e32..22621ceaa 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -267,10 +267,7 @@ class VTK: writer.SetInputData(self.geom) writer.Write() return writer.GetOutputString() - celldata = g.GetCellData() - for a in range(celldata.GetNumberOfArrays()): - if celldata.GetArrayName(a) == 'materialpoint': - materialpoint = vtk_to_np(celldata.GetArray(a)) + def show(self): """ From 22da3af92eb4f2fa81d2ae0c2073c44b8bb26138 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 00:42:58 +0200 Subject: [PATCH 12/16] cleaning (prospector complaint) --- python/tests/conftest.py | 10 +++++----- python/tests/test_Colormap.py | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/python/tests/conftest.py b/python/tests/conftest.py index a6f6e62ad..2912373a5 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -3,27 +3,27 @@ import datetime import numpy as np import pytest -from _pytest.monkeypatch import MonkeyPatch import damask patched_version = '99.99.99-9999-pytest' @pytest.fixture -def patch_damask_version(monkeysession): +def patch_damask_version(monkeypatch): """Set damask.version for reproducible tests results.""" - monkeysession.setattr(damask, 'version', patched_version) + monkeypatch.setattr(damask, 'version', patched_version) + patched_date = datetime.datetime(2019, 11, 2, 11, 58, 0) @pytest.fixture -def patch_datetime_now(monkeysession): +def patch_datetime_now(monkeypatch): """Set datetime.datetime.now for reproducible tests results.""" class mydatetime: @classmethod def now(cls): return patched_date - monkeysession.setattr(datetime, 'datetime', mydatetime) + monkeypatch.setattr(datetime, 'datetime', mydatetime) def pytest_addoption(parser): diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 4fe0cc9fb..d3f5e45c8 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -7,7 +7,6 @@ import pytest from PIL import Image from PIL import ImageChops -import damask from damask import Colormap @pytest.fixture @@ -22,7 +21,6 @@ class TestColormap: print('patched damask.version') def test_conversion(self): - specials = np.array([[0.,0.,0.], [1.,0.,0.], [0.,1.,0.], From 507a165733bc351fb9cb1d7bca052100d691199d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 06:40:36 +0200 Subject: [PATCH 13/16] functionality for getting data - handy for Geom class, but could be of general interest - add/set/get comments: follows same functions as for Geom class --- python/damask/_vtk.py | 58 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 22621ceaa..52dd52754 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -6,6 +6,7 @@ import numpy as np import vtk from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray +from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np import damask from . import Table @@ -204,7 +205,18 @@ class VTK: # Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data # Needs support for pd.DataFrame and/or table def add(self,data,label=None): - """Add data to either cells or points.""" + """ + Add data to either cells or points. + + Parameters + ---------- + data : numpy.ndarray + Data to add. First dimension need to match either + number of cells or number of points + label : str + Data label. + + """ N_points = self.geom.GetNumberOfPoints() N_cells = self.geom.GetNumberOfCells() @@ -232,6 +244,33 @@ class VTK: raise TypeError + def get(self,label): + """ + Get either cell or point data. + + Cell data takes precedence over point data, i.e. this + function assumes that labels are unique among cell and + point data. + + Parameters + ---------- + label : str + Data label. + + """ + celldata = self.geom.GetCellData() + for a in range(celldata.GetNumberOfArrays()): + if celldata.GetArrayName(a) == label: + return vtk_to_np(celldata.GetArray(a)) + + pointdata = self.geom.GetPointData() + for a in range(celldata.GetNumberOfArrays()): + if pointdata.GetArrayName(a) == label: + return vtk_to_np(pointdata.GetArray(a)) + + raise ValueError(f'array "{label}" not found') + + def get_comments(self): """Return the comments.""" fielddata = self.geom.GetFieldData() @@ -244,12 +283,12 @@ class VTK: def set_comments(self,comments): """ - Add Comments. + Set Comments. Parameters ---------- comments : str or list of str - Comments to add + Comments. """ s = vtk.vtkStringArray() @@ -259,6 +298,19 @@ class VTK: self.geom.GetFieldData().AddArray(s) + def add_comments(self,comments): + """ + Add Comments. + + Parameters + ---------- + comments : str or list of str + Comments to add. + + """ + self.set_comments(self.get_comments + ([comments] if isinstance(comments,str) else comments)) + + def __repr__(self): """ASCII representation of the VTK data.""" writer = vtk.vtkDataSetWriter() From 0d3ef295548c53b9fa6632154b1bc3887f42d3a3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 06:46:22 +0200 Subject: [PATCH 14/16] more logical encapsulation - getting data out of VTK is a functionality of the VTK class. Need to discuss whether the VTK class should also provide grid and size (works only for rectilinear grid, so hiding VTK type is not possible anymore), but the current situation requires the Geom class to rely on 'internals' of the VTK class - header is specific to *.geom format, not to Geom objects. --- python/damask/_geom.py | 59 ++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 8039a0038..17cd49b08 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -7,7 +7,6 @@ from functools import partial import numpy as np from scipy import ndimage,spatial -from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np from . import environment from . import Rotation @@ -271,16 +270,6 @@ class Geom: return self.comments[:] - def get_header(self): - """Return the full header (grid, size, origin, homogenization, comments).""" - header = [f'{len(self.comments)+4} header'] + self.comments - header.append('grid a {} b {} c {}'.format(*self.get_grid())) - header.append('size x {} y {} z {}'.format(*self.get_size())) - header.append('origin x {} y {} z {}'.format(*self.get_origin())) - header.append(f'homogenization {self.get_homogenization()}') - return header - - @staticmethod def from_file(fname): """ @@ -356,19 +345,12 @@ class Geom: Valid extension is .vtr, it will be appended if not given. """ - g = VTK.from_file(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr').geom - grid = np.array(g.GetDimensions())-1 - bbox = np.array(g.GetBounds()).reshape(3,2).T + v = VTK.from_file(fname if str(fname).endswith('.vtr') else str(fname)+'.vtr') + grid = np.array(v.geom.GetDimensions())-1 + bbox = np.array(v.geom.GetBounds()).reshape(3,2).T size = bbox[1] - bbox[0] - celldata = g.GetCellData() - for a in range(celldata.GetNumberOfArrays()): - if celldata.GetArrayName(a) == 'materialpoint': - materialpoint = vtk_to_np(celldata.GetArray(a)) - return Geom(materialpoint.reshape(grid,order='F'),size,bbox[0]) - - raise ValueError(f'"materialpoint" array not found in {fname}') - + return Geom(v.get('materialpoint').reshape(grid,order='F'),size,bbox[0]) @staticmethod @@ -417,7 +399,7 @@ class Geom: else: microstructure = microstructure.reshape(grid) - creator = util.edit_info('damask.Result.'+inspect.stack()[0][3]) + creator = util.edit_info('damask.Geom.'+inspect.stack()[0][3]) return Geom(microstructure+1,size,homogenization=1,comments=creator) @@ -442,7 +424,7 @@ class Geom: KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds) devNull,microstructure = KDTree.query(coords) - creator = util.edit_info('damask.Result.'+inspect.stack()[0][3]) + creator = util.edit_info('damask.Geom.'+inspect.stack()[0][3]) return Geom(microstructure.reshape(grid)+1,size,homogenization=1,comments=creator) @@ -458,8 +440,13 @@ class Geom: Compress geometry with 'x of y' and 'a to b'. """ - header = self.get_header() - grid = self.get_grid() + header = [f'{len(self.comments)+4} header'] + self.comments + header.append('grid a {} b {} c {}'.format(*self.get_grid())) + header.append('size x {} y {} z {}'.format(*self.get_size())) + header.append('origin x {} y {} z {}'.format(*self.get_origin())) + header.append(f'homogenization {self.get_homogenization()}') + + grid = self.get_grid() if pack is None: plain = grid.prod()/self.N_microstructure < 250 @@ -490,7 +477,7 @@ class Geom: reps += 1 else: if compressType is None: - f.write('\n'.join(self.get_header())+'\n') + f.write('\n'.join(header)+'\n') elif compressType == '.': f.write(f'{former}\n') elif compressType == 'to': @@ -589,7 +576,7 @@ class Geom: fill_ = np.full_like(self.microstructure,np.nanmax(self.microstructure)+1 if fill is None else fill) ms = np.ma.MaskedArray(fill_,np.logical_not(mask) if inverse else mask) - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(ms) @@ -620,7 +607,7 @@ class Geom: if 'x' in directions: ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(ms,rescale=True) @@ -636,7 +623,7 @@ class Geom: Assume geometry to be periodic. Defaults to True. """ - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update( ndimage.interpolation.zoom( self.microstructure, @@ -671,7 +658,7 @@ class Geom: else: return me - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(ndimage.filters.generic_filter( self.microstructure, mostFrequent, @@ -688,7 +675,7 @@ class Geom: for i, oldID in enumerate(np.unique(self.microstructure)): renumbered = np.where(self.microstructure == oldID, i+1, renumbered) - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(renumbered) @@ -723,7 +710,7 @@ class Geom: origin = self.origin-(np.asarray(microstructure_in.shape)-self.grid)*.5 * self.size/self.grid - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(microstructure_in,origin=origin,rescale=True) @@ -756,7 +743,7 @@ class Geom: canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.microstructure[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(canvas,origin=self.origin+offset*self.size/self.grid,rescale=True) @@ -776,7 +763,7 @@ class Geom: for from_ms,to_ms in zip(from_microstructure,to_microstructure): substituted[self.microstructure==from_ms] = to_ms - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(substituted) @@ -822,5 +809,5 @@ class Geom: extra_keywords={'trigger':trigger}) microstructure = np.ma.MaskedArray(self.microstructure + offset_, np.logical_not(mask)) - self.add_comments(util.edit_info('damask.Result.'+inspect.stack()[0][3])) + self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) return self.update(microstructure) From b393da4955cefac766af183c5bd3d59182143de4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 07:28:10 +0200 Subject: [PATCH 15/16] relative imports ... it's all about damask.XXX --- python/tests/test_Orientation.py | 7 +++---- python/tests/test_Result.py | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 4987f1f1f..eb2ccfd56 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -4,7 +4,6 @@ from itertools import permutations import pytest import numpy as np -import damask from damask import Rotation from damask import Orientation from damask import Lattice @@ -68,7 +67,7 @@ class TestOrientation: {'label':'blue', 'RGB':[0,0,1],'direction':[1,1,1]}]) @pytest.mark.parametrize('lattice',['fcc','bcc']) def test_IPF_cubic(self,color,lattice): - cube = damask.Orientation(damask.Rotation(),lattice) + cube = Orientation(Rotation(),lattice) for direction in set(permutations(np.array(color['direction']))): assert np.allclose(cube.IPF_color(np.array(direction)),np.array(color['RGB'])) @@ -112,7 +111,7 @@ class TestOrientation: @pytest.mark.parametrize('lattice',Lattice.lattices) def test_disorientation360(self,lattice): R_1 = Orientation(Rotation(),lattice) - R_2 = Orientation(damask.Rotation.from_Eulers([360,0,0],degrees=True),lattice) + R_2 = Orientation(Rotation.from_Eulers([360,0,0],degrees=True),lattice) assert np.allclose(R_1.disorientation(R_2).as_matrix(),np.eye(3)) @pytest.mark.parametrize('lattice',Lattice.lattices) @@ -127,6 +126,6 @@ class TestOrientation: def test_from_average(self,lattice): R_1 = Orientation(Rotation.from_random(),lattice) eqs = [r for r in R_1.equivalent] - R_2 = damask.Orientation.from_average(eqs) + R_2 = Orientation.from_average(eqs) assert np.allclose(R_1.rotation.quaternion,R_2.rotation.quaternion) diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index 53bcdda9d..6000f50f9 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -8,8 +8,9 @@ import pytest import numpy as np import h5py -import damask from damask import Result +from damask import Rotation +from damask import Orientation from damask import mechanics from damask import grid_filters @@ -174,7 +175,7 @@ class TestResult: crystal_structure = default.get_crystal_structure() in_memory = np.empty((qu.shape[0],3),np.uint8) for i,q in enumerate(qu): - o = damask.Orientation(q,crystal_structure).reduced + o = Orientation(q,crystal_structure).reduced in_memory[i] = np.uint8(o.IPF_color(np.array(d))*255) in_file = default.read_dataset(loc['color']) assert np.allclose(in_memory,in_file) @@ -233,7 +234,7 @@ class TestResult: default.add_pole('orientation',pole,polar) loc = {'orientation': default.get_dataset_location('orientation'), 'pole': default.get_dataset_location('p^{}_[1 0 0)'.format(u'rφ' if polar else 'xy'))} - rot = damask.Rotation(default.read_dataset(loc['orientation']).view(np.double)) + rot = Rotation(default.read_dataset(loc['orientation']).view(np.double)) rotated_pole = rot * np.broadcast_to(pole,rot.shape+(3,)) xy = rotated_pole[:,0:2]/(1.+abs(pole[2])) in_memory = xy if not polar else \ From 9d505c851835eb648feb8c3dd32248cfb2a56a06 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 24 Aug 2020 09:55:41 +0200 Subject: [PATCH 16/16] better readable - more explicit reporting - always relative import for DAMASK --- python/damask/_colormap.py | 6 +++--- python/damask/_geom.py | 23 ++++++++++----------- python/damask/_vtk.py | 7 ++++--- python/damask/solver/_marc.py | 10 ++++----- python/damask/util.py | 10 +++++---- python/tests/conftest.py | 9 ++++++++ python/tests/reference/Colormap/binary.json | 2 +- python/tests/reference/Colormap/binary.txt | 2 +- python/tests/test_Colormap.py | 4 ++-- python/tests/test_Orientation.py | 5 +++-- 10 files changed, 45 insertions(+), 33 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index ec4000018..e2b317d63 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -10,7 +10,7 @@ import matplotlib.pyplot as plt from matplotlib import cm from PIL import Image -import damask +from . import util from . import Table _eps = 216./24389. @@ -280,7 +280,7 @@ class Colormap(mpl.colors.ListedColormap): colors+=[i]+c out = [{ - 'Creator':f'damask.Colormap v{damask.version}', + 'Creator':util.version_date('Colormap'), 'ColorSpace':'RGB', 'Name':colormap.name, 'DefaultMap':True, @@ -296,7 +296,7 @@ class Colormap(mpl.colors.ListedColormap): def _export_ASCII(colormap,fhandle=None): """Write colormap to ASCII table.""" labels = {'RGBA':4} if colormap.colors.shape[1] == 4 else {'RGB': 3} - t = Table(colormap.colors,labels,f'Creator: damask.Colormap v{damask.version}') + t = Table(colormap.colors,labels,f'Creator: {util.version_date("Colormap")}') if fhandle is None: with open(colormap.name.replace(' ','_')+'.txt', 'w') as f: diff --git a/python/damask/_geom.py b/python/damask/_geom.py index 17cd49b08..6632eb5ed 100644 --- a/python/damask/_geom.py +++ b/python/damask/_geom.py @@ -1,6 +1,5 @@ import sys import copy -import inspect import multiprocessing from io import StringIO from functools import partial @@ -399,7 +398,7 @@ class Geom: else: microstructure = microstructure.reshape(grid) - creator = util.edit_info('damask.Geom.'+inspect.stack()[0][3]) + creator = util.version_date('Geom','from_Laguerre_tessellation') return Geom(microstructure+1,size,homogenization=1,comments=creator) @@ -424,7 +423,7 @@ class Geom: KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds) devNull,microstructure = KDTree.query(coords) - creator = util.edit_info('damask.Geom.'+inspect.stack()[0][3]) + creator = util.version_date('Geom','from_Voronoi_tessellation') return Geom(microstructure.reshape(grid)+1,size,homogenization=1,comments=creator) @@ -576,7 +575,7 @@ class Geom: fill_ = np.full_like(self.microstructure,np.nanmax(self.microstructure)+1 if fill is None else fill) ms = np.ma.MaskedArray(fill_,np.logical_not(mask) if inverse else mask) - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','add_primitive')) return self.update(ms) @@ -607,7 +606,7 @@ class Geom: if 'x' in directions: ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','mirror')) return self.update(ms,rescale=True) @@ -623,7 +622,7 @@ class Geom: Assume geometry to be periodic. Defaults to True. """ - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','scale')) return self.update( ndimage.interpolation.zoom( self.microstructure, @@ -658,7 +657,7 @@ class Geom: else: return me - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','clean')) return self.update(ndimage.filters.generic_filter( self.microstructure, mostFrequent, @@ -675,7 +674,7 @@ class Geom: for i, oldID in enumerate(np.unique(self.microstructure)): renumbered = np.where(self.microstructure == oldID, i+1, renumbered) - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','renumber')) return self.update(renumbered) @@ -710,7 +709,7 @@ class Geom: origin = self.origin-(np.asarray(microstructure_in.shape)-self.grid)*.5 * self.size/self.grid - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','rotate')) return self.update(microstructure_in,origin=origin,rescale=True) @@ -743,7 +742,7 @@ class Geom: canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.microstructure[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','canvas')) return self.update(canvas,origin=self.origin+offset*self.size/self.grid,rescale=True) @@ -763,7 +762,7 @@ class Geom: for from_ms,to_ms in zip(from_microstructure,to_microstructure): substituted[self.microstructure==from_ms] = to_ms - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','substitute')) return self.update(substituted) @@ -809,5 +808,5 @@ class Geom: extra_keywords={'trigger':trigger}) microstructure = np.ma.MaskedArray(self.microstructure + offset_, np.logical_not(mask)) - self.add_comments(util.edit_info('damask.Geom.'+inspect.stack()[0][3])) + self.add_comments(util.version_date('Geom','vicinity_offset')) return self.update(microstructure) diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 52dd52754..349e158ca 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -8,7 +8,8 @@ from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray from vtk.util.numpy_support import vtk_to_numpy as vtk_to_np -import damask +from . import util +from . import environment from . import Table @@ -314,7 +315,7 @@ class VTK: def __repr__(self): """ASCII representation of the VTK data.""" writer = vtk.vtkDataSetWriter() - writer.SetHeader(f'# damask.VTK v{damask.version}') + writer.SetHeader(f'# {util.version_date("VTK")}') writer.WriteToOutputStringOn() writer.SetInputData(self.geom) writer.Write() @@ -340,7 +341,7 @@ class VTK: ren.AddActor(actor) ren.SetBackground(0.2,0.2,0.2) - window.SetSize(damask.environment.screen_size[0],damask.environment.screen_size[1]) + window.SetSize(environment.screen_size[0],environment.screen_size[1]) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(window) diff --git a/python/damask/solver/_marc.py b/python/damask/solver/_marc.py index 8e96f1b90..12e36f7ed 100644 --- a/python/damask/solver/_marc.py +++ b/python/damask/solver/_marc.py @@ -3,12 +3,12 @@ import shlex import string from pathlib import Path -import damask +from .. import environment class Marc: """Wrapper to run DAMASK with MSCMarc.""" - def __init__(self,version=damask.environment.options['MARC_VERSION']): + def __init__(self,version=environment.options['MARC_VERSION']): """ Create a Marc solver object. @@ -24,7 +24,7 @@ class Marc: @property def library_path(self): - path_MSC = damask.environment.options['MSC_ROOT'] + path_MSC = environment.options['MSC_ROOT'] path_lib = Path(f'{path_MSC}/mentat{self.version}/shlib/linux64') return path_lib if path_lib.is_dir() else None @@ -33,7 +33,7 @@ class Marc: @property def tools_path(self): - path_MSC = damask.environment.options['MSC_ROOT'] + path_MSC = environment.options['MSC_ROOT'] path_tools = Path(f'{path_MSC}/marc{self.version}/tools') return path_tools if path_tools.is_dir() else None @@ -49,7 +49,7 @@ class Marc: ): - usersub = damask.environment.root_dir/'src/DAMASK_marc' + usersub = environment.root_dir/'src/DAMASK_marc' usersub = usersub.parent/(usersub.name + ('.f90' if compile else '.marc')) if not usersub.is_file(): raise FileNotFoundError("DAMASK4Marc ({}) '{}' not found".format(('source' if compile else 'binary'),usersub)) diff --git a/python/damask/util.py b/python/damask/util.py index f83fc4c62..f7c40416e 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -9,7 +9,7 @@ from optparse import Option import numpy as np -import damask +from . import version # limit visibility __all__=[ @@ -22,7 +22,7 @@ __all__=[ 'scale_to_coprime', 'return_message', 'extendableOption', - 'edit_info' + 'version_date' ] #################################################################################################### @@ -178,9 +178,11 @@ def scale_to_coprime(v): return m -def edit_info(who): +def version_date(class_name,function_name=None): + """tbd.""" + _function_name = '' if function_name is None else f'.{function_name}' now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z') - return f'{who} v{damask.version} ({now})' + return f'damask.{class_name}{_function_name} v{version} ({now})' #################################################################################################### diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 2912373a5..51da90671 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -25,6 +25,15 @@ def patch_datetime_now(monkeypatch): monkeypatch.setattr(datetime, 'datetime', mydatetime) +@pytest.fixture +def version_date(monkeypatch): + """Set damask.util.version_date for reproducible tests results.""" + def version_date(class_name,function_name=None): + _function_name = '' if function_name is None else f'.{function_name}' + return f'damask.{class_name}{_function_name} v{patched_version} ({patched_date})' + + monkeypatch.setattr(damask.util, 'version_date', version_date) + def pytest_addoption(parser): parser.addoption("--update", diff --git a/python/tests/reference/Colormap/binary.json b/python/tests/reference/Colormap/binary.json index c71d3649b..b8b85f80f 100644 --- a/python/tests/reference/Colormap/binary.json +++ b/python/tests/reference/Colormap/binary.json @@ -1,6 +1,6 @@ [ { - "Creator": "damask.Colormap v99.99.99-9999-pytest", + "Creator": "damask.Colormap v99.99.99-9999-pytest (2019-11-02 11:58:00)", "ColorSpace": "RGB", "Name": "binary", "DefaultMap": true, diff --git a/python/tests/reference/Colormap/binary.txt b/python/tests/reference/Colormap/binary.txt index 976c0202a..ca1d2401f 100644 --- a/python/tests/reference/Colormap/binary.txt +++ b/python/tests/reference/Colormap/binary.txt @@ -1,4 +1,4 @@ -# Creator: damask.Colormap v99.99.99-9999-pytest +# Creator: damask.Colormap v99.99.99-9999-pytest (2019-11-02 11:58:00) 1_RGBA 2_RGBA 3_RGBA 4_RGBA 1.0 1.0 1.0 1.0 0.996078431372549 0.996078431372549 0.996078431372549 1.0 diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index d3f5e45c8..870ff9761 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -17,8 +17,8 @@ def reference_dir(reference_dir_base): class TestColormap: @pytest.fixture(autouse=True) - def _patch_damask_version(self, patch_damask_version): - print('patched damask.version') + def _version_date(self, version_date): + print('patched damask.util.version_date') def test_conversion(self): specials = np.array([[0.,0.,0.], diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index eb2ccfd56..636eeb0c4 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -4,6 +4,7 @@ from itertools import permutations import pytest import numpy as np +from damask import Table from damask import Rotation from damask import Orientation from damask import Lattice @@ -103,10 +104,10 @@ class TestOrientation: eu = np.array([o.rotation.as_Eulers(degrees=True) for o in ori.related(model)]) if update: coords = np.array([(1,i+1) for i,x in enumerate(eu)]) - table = damask.Table(eu,{'Eulers':(3,)}) + table = Table(eu,{'Eulers':(3,)}) table.add('pos',coords) table.to_ASCII(reference) - assert np.allclose(eu,damask.Table.from_ASCII(reference).get('Eulers')) + assert np.allclose(eu,Table.from_ASCII(reference).get('Eulers')) @pytest.mark.parametrize('lattice',Lattice.lattices) def test_disorientation360(self,lattice):