migrating shell scripts to library

This commit is contained in:
Martin Diehl 2020-08-08 19:42:34 +02:00
parent 5fcff876f9
commit a0e0f28e51
3 changed files with 117 additions and 53 deletions

View File

@ -5,7 +5,6 @@ import sys
from io import StringIO from io import StringIO
from optparse import OptionParser from optparse import OptionParser
from scipy import ndimage
import numpy as np import numpy as np
import damask import damask
@ -15,18 +14,6 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version]) scriptID = ' '.join([scriptName,damask.version])
def taintedNeighborhood(stencil,trigger=[],size=1):
me = stencil[stencil.shape[0]//2]
if len(trigger) == 0:
return np.any(stencil != me)
if me in trigger:
trigger = set(trigger)
trigger.remove(me)
trigger = list(trigger)
return np.any(np.in1d(stencil,np.array(trigger)))
#-------------------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------------------
# MAIN # MAIN
#-------------------------------------------------------------------------------------------------- #--------------------------------------------------------------------------------------------------
@ -67,19 +54,12 @@ options.trigger = np.array(options.trigger, dtype=int)
if filenames == []: filenames = [None] if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name)
offset = np.nanmax(geom.microstructure) if options.offset is None else options.offset damask.util.croak(geom.vicinity_offset(options.vicinity,options.offset,options.trigger,
True if options.mode is 'wrap' else False))
geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:]))
damask.util.croak(geom.update(np.where(ndimage.filters.generic_filter( geom.to_file(sys.stdout if name is None else name,pack=False)
geom.microstructure,
taintedNeighborhood,
size=1+2*options.vicinity,mode=options.mode,
extra_arguments=(),
extra_keywords={"trigger":options.trigger,"size":1+2*options.vicinity}),
geom.microstructure + offset,geom.microstructure)))
geom.add_comments(scriptID + ' ' + ' '.join(sys.argv[1:]))
geom.to_file(sys.stdout if name is None else name,pack=False)

View File

@ -278,7 +278,7 @@ class Geom:
Parameters Parameters
---------- ----------
fname : str or file handle fname : str or file handle
geometry file to read. Geometry file to read.
""" """
try: try:
@ -345,15 +345,15 @@ class Geom:
Parameters Parameters
---------- ----------
grid : numpy.ndarray of shape (3) grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction. Number of grid points in x,y,z direction.
size : list or numpy.ndarray of shape (3) size : list or numpy.ndarray of shape (3)
physical size of the microstructure in meter. Physical size of the microstructure in meter.
seeds : numpy.ndarray of shape (:,3) seeds : numpy.ndarray of shape (:,3)
position of the seed points in meter. All points need to lay within the box. Position of the seed points in meter. All points need to lay within the box.
weights : numpy.ndarray of shape (seeds.shape[0]) weights : numpy.ndarray of shape (seeds.shape[0])
weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation. Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation.
periodic : Boolean, optional periodic : Boolean, optional
perform a periodic tessellation. Defaults to True. Perform a periodic tessellation. Defaults to True.
""" """
if periodic: if periodic:
@ -391,13 +391,13 @@ class Geom:
Parameters Parameters
---------- ----------
grid : numpy.ndarray of shape (3) grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction. Number of grid points in x,y,z direction.
size : list or numpy.ndarray of shape (3) size : list or numpy.ndarray of shape (3)
physical size of the microstructure in meter. Physical size of the microstructure in meter.
seeds : numpy.ndarray of shape (:,3) seeds : numpy.ndarray of shape (:,3)
position of the seed points in meter. All points need to lay within the box. Position of the seed points in meter. All points need to lay within the box.
periodic : Boolean, optional periodic : Boolean, optional
perform a periodic tessellation. Defaults to True. Perform a periodic tessellation. Defaults to True.
""" """
coords = grid_filters.cell_coord0(grid,size).reshape(-1,3) coords = grid_filters.cell_coord0(grid,size).reshape(-1,3)
@ -415,9 +415,9 @@ class Geom:
Parameters Parameters
---------- ----------
fname : str or file handle fname : str or file handle
geometry file to write. Geometry file to write.
pack : bool, optional pack : bool, optional
compress geometry with 'x of y' and 'a to b'. Compress geometry with 'x of y' and 'a to b'.
""" """
header = self.get_header() header = self.get_header()
@ -481,7 +481,7 @@ class Geom:
Parameters Parameters
---------- ----------
fname : str, optional fname : str, optional
vtk file to write. If no file is given, a string is returned. Vtk file to write. If no file is given, a string is returned.
""" """
v = VTK.from_rectilinearGrid(self.grid,self.size,self.origin) v = VTK.from_rectilinearGrid(self.grid,self.size,self.origin)
@ -508,9 +508,9 @@ class Geom:
Parameters Parameters
---------- ----------
directions : iterable containing str directions : iterable containing str
direction(s) along which the microstructure is mirrored. Valid entries are 'x', 'y', 'z'. Direction(s) along which the microstructure is mirrored. Valid entries are 'x', 'y', 'z'.
reflect : bool, optional reflect : bool, optional
reflect (include) outermost layers. Reflect (include) outermost layers.
""" """
valid = {'x','y','z'} valid = {'x','y','z'}
@ -540,7 +540,7 @@ class Geom:
Parameters Parameters
---------- ----------
grid : numpy.ndarray of shape (3) grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction. Number of grid points in x,y,z direction.
""" """
#ToDo: self.add_comments('geom.py:scale v{}'.format(version) #ToDo: self.add_comments('geom.py:scale v{}'.format(version)
@ -563,7 +563,7 @@ class Geom:
Parameters Parameters
---------- ----------
stencil : int, optional stencil : int, optional
size of smoothing stencil. Size of smoothing stencil.
""" """
def mostFrequent(arr): def mostFrequent(arr):
@ -596,9 +596,9 @@ class Geom:
Parameters Parameters
---------- ----------
R : damask.Rotation R : damask.Rotation
rotation to apply to the microstructure. Rotation to apply to the microstructure.
fill : int or float, optional fill : int or float, optional
microstructure index to fill the corners. Defaults to microstructure.max() + 1. Microstructure index to fill the corners. Defaults to microstructure.max() + 1.
""" """
if fill is None: fill = np.nanmax(self.microstructure) + 1 if fill is None: fill = np.nanmax(self.microstructure) + 1
@ -631,11 +631,11 @@ class Geom:
Parameters Parameters
---------- ----------
grid : numpy.ndarray of shape (3) grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction. Number of grid points in x,y,z direction.
offset : numpy.ndarray of shape (3) offset : numpy.ndarray of shape (3)
offset (measured in grid points) from old to new microstructue[0,0,0]. Offset (measured in grid points) from old to new microstructure[0,0,0].
fill : int or float, optional fill : int or float, optional
microstructure index to fill the corners. Defaults to microstructure.max() + 1. Microstructure index to fill the corners. Defaults to microstructure.max() + 1.
""" """
if fill is None: fill = np.nanmax(self.microstructure) + 1 if fill is None: fill = np.nanmax(self.microstructure) + 1
@ -658,14 +658,14 @@ class Geom:
def substitute(self,from_microstructure,to_microstructure): def substitute(self,from_microstructure,to_microstructure):
""" """
Substitude microstructure indices. Substitute microstructure indices.
Parameters Parameters
---------- ----------
from_microstructure : iterable of ints from_microstructure : iterable of ints
microstructure indices to be substituted. Microstructure indices to be substituted.
to_microstructure : iterable of ints to_microstructure : iterable of ints
new microstructure indices. New microstructure indices.
""" """
substituted = self.get_microstructure() substituted = self.get_microstructure()
@ -674,3 +674,50 @@ class Geom:
#ToDo: self.add_comments('geom.py:substitute v{}'.format(version) #ToDo: self.add_comments('geom.py:substitute v{}'.format(version)
return self.update(substituted) return self.update(substituted)
def vicinity_offset(self,vicinity=1,offset=None,trigger=[],periodic=True):
"""
Offset microstructure index of points in the vicinity of xxx.
Different from themselves (or listed as triggers) within a given (cubic) vicinity,
i.e. within the region close to a grain/phase boundary.
ToDo: use include/exclude as in seeds.from_geom
Parameters
----------
vicinity : int, optional
Voxel distance checked for presence of other microstructure.
Defaults to 1.
offset : int, optional
Offset (positive or negative) to tag microstructure indices,
defaults to microstructure.max() + 1.
trigger : list of ints, optional
List of microstructure indices triggering a change.
Defaults to [], meaning that different neigboors trigger a change.
periodic : Boolean, optional
Assume geometry to be periodic. Defaults to True.
"""
def tainted_neighborhood(stencil,trigger):
me = stencil[stencil.shape[0]//2]
if len(trigger) == 0:
return np.any(stencil != me)
if me in trigger:
trigger = set(trigger)
trigger.remove(me)
trigger = list(trigger)
return np.any(np.in1d(stencil,np.array(trigger)))
offset_ = np.nanmax(self.microstructure) if offset is None else offset
mask = ndimage.filters.generic_filter(self.microstructure,
tainted_neighborhood,
size=1+2*vicinity,
mode=('wrap' if periodic else 'nearest'),
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)

View File

@ -77,9 +77,19 @@ class TestGeom:
with pytest.raises(ValueError): with pytest.raises(ValueError):
default.update(default.microstructure[1:,1:,1:],size=np.ones(2)) default.update(default.microstructure[1:,1:,1:],size=np.ones(2))
def test_invalid_microstructure(self,default): def test_invalid_origin(self,default):
with pytest.raises(ValueError): with pytest.raises(ValueError):
default.update(default.microstructure[1]) default.update(default.microstructure[1:,1:,1:],origin=np.ones(4))
def test_invalid_microstructure_size(self,default):
microstructure=np.ones((3,3))
with pytest.raises(ValueError):
default.update(microstructure)
def test_invalid_microstructure_type(self,default):
microstructure=np.random.randint(1,300,(3,4,5))==1
with pytest.raises(TypeError):
default.update(microstructure)
def test_invalid_homogenization(self,default): def test_invalid_homogenization(self,default):
with pytest.raises(TypeError): with pytest.raises(TypeError):
@ -172,6 +182,33 @@ class TestGeom:
e = default.grid e = default.grid
assert np.all(modified.microstructure[:e[0],:e[1],:e[2]] == default.microstructure) assert np.all(modified.microstructure[:e[0],:e[1],:e[2]] == default.microstructure)
@pytest.mark.parametrize('trigger',[[1],[]])
def test_vicinity_offset(self,trigger):
offset = np.random.randint(2,4)
vicinity = np.random.randint(2,4)
g=np.random.randint(28,40,(3))
m=np.ones(g,'i')
x=(g*np.random.permutation(np.array([.5,1,1]))).astype('i')
m[slice(0,x[0]),slice(0,x[1]),slice(0,x[2])]=2
m2=copy.deepcopy(m)
for i in [0,1,2]:
m2[(np.roll(m,+vicinity,i)-m)!=0] +=offset
m2[(np.roll(m,-vicinity,i)-m)!=0] +=offset
if len(trigger) > 0:
m2[m==1]=1
geom = Geom(m,np.random.rand(3))
geom.vicinity_offset(vicinity,offset,trigger=trigger)
assert np.all(m2==geom.microstructure)
@pytest.mark.parametrize('periodic',[True,False])
def test_vicinity_offset_invariant(self,default,periodic):
old = default.get_microstructure()
default.vicinity_offset(trigger=[old.max()+1,old.min()-1])
assert np.all(old==default.microstructure)
@pytest.mark.parametrize('periodic',[True,False]) @pytest.mark.parametrize('periodic',[True,False])
def test_tessellation_approaches(self,periodic): def test_tessellation_approaches(self,periodic):
grid = np.random.randint(10,20,3) grid = np.random.randint(10,20,3)