making export DREAM3D compatible with results class

This commit is contained in:
Vitesh Shah 2023-04-06 20:56:42 +02:00
parent 12c39c0977
commit f619cf4ff2
1 changed files with 145 additions and 0 deletions

View File

@ -63,6 +63,30 @@ def _empty_like(dataset: np.ma.core.MaskedArray,
fill_value = fill_float if dataset.dtype in np.sctypes['float'] else fill_int,
mask = True)
class AttributeManagerNullterm(h5py.AttributeManager):
"""
Attribute management for DREAM.3D hdf5 files.
String attribute values are stored as fixed-length string with NULLTERM
References
----------
https://stackoverflow.com/questions/38267076
https://stackoverflow.com/questions/52750232
"""
def create(self, name, data, shape=None, dtype=None):
if isinstance(data,str):
tid = h5py.h5t.C_S1.copy()
tid.set_size(len(data + ' '))
super().create(name=name,data=data+' ',dtype = h5py.Datatype(tid))
else:
super().create(name=name,data=data,shape=shape,dtype=dtype)
h5py._hl.attrs.AttributeManager = AttributeManagerNullterm # 'Monkey patch'
class Result:
"""
Add data to and export data from a DADF5 file.
@ -1920,6 +1944,127 @@ class Result:
v.save(vtk_dir/f'{self.fname.stem}_inc{inc.split(prefix_inc)[-1].zfill(N_digits)}',
parallel=parallel)
def export_DREAM3D(self):
"""
Export the visible components to DREAM3D compatible files.
One DREAM3D file per visible increment is created.
The DREAM3D file is based on HDF5 file format.
Without any regridding.
Considers the original grid from DAMASK.
Needs orientation data, O, present in the file.
Parameters
----------
"""
Crystal_structures = {'fcc': 1,
'bcc': 1,
'hcp': 0,
'bct': 7,
'ort': 6} #TODO: is bct Tetragonal low/Tetragonal high?
Phase_types = {'Primary': 0} #further additions to these can be done by looking at 'Create Ensemble Info' filter, other options could be 'Precipitate' and so on.
dx = self.size/self.cells
for inc in util.show_progress(self.visible['increments']):
for label in self.visible['phases']:
try:
data = ma.array(_read(f['/'.join([inc,'phase',label,'mechanical/O'])]))
except ValueError: #check if the exception is correct
print("Orientation data is not present")
exit() # need to check if such a statement would really work.
cell_orientation_array = np.zeros((np.prod(self.cells),3))
phase_ID_array = np.zeros((np.prod(self.cells)),dtype=np.int32) #need to reshape it later
at_cell_ph,in_data_ph,at_cell_ho,in_data_ho = self._mappings()
for c in range(self.N_constituents):
for ph in self.phases:
cell_orientation_array[at_cell_ph[c][ph],:] = data[,:]# need to figure out these mappings a bit
cell_orientation_array[in_data_ph[ph],:] = # need to figure out these mappings a bit
phase_ID_array[phase_index] = count + 1 #need to figure out these mappings a bit
job_file_no_ext = os.path.splitext(self.fname)[0]
o = h5py.File(f'{job_file_no_ext}_increment{inc}.dream3D','w')
o.attrs['DADF5toDREAM3D'] = '1.0'
o.attrs['FileVersion'] = '7.0'
for g in ['DataContainerBundles','Pipeline']: # empty groups (needed)
o.create_group(g)
data_container_label = 'DataContainers/SyntheticVolumeDataContainer'
cell_data_label = data_container_label + '/CellData'
# Data phases
o[cell_data_label + '/Phases'] = np.reshape(phase_ID_array, \
tuple(np.flip(self.cells))+(1,))
# Data eulers
orientation_data = cell_orientation_array.astype(np.float32)
o[cell_data_label + '/Eulers'] = orientation_data.reshape(tuple(np.flip(self.cells))+(3,))
# Attributes to CellData group
o[cell_data_label].attrs['AttributeMatrixType'] = np.array([3],np.uint32)
o[cell_data_label].attrs['TupleDimensions'] = np.array(self.cells,np.uint64)
# Common Attributes for groups in CellData
for group in ['/Phases','/Eulers']:
o[cell_data_label + group].attrs['DataArrayVersion'] = np.array([2],np.int32)
o[cell_data_label + group].attrs['Tuple Axis Dimensions'] = 'x={},y={},z={}'.format(*np.array(self.cells))
# phase attributes
o[cell_data_label + '/Phases'].attrs['ComponentDimensions'] = np.array([1],np.uint64)
o[cell_data_label + '/Phases'].attrs['ObjectType'] = 'DataArray<int32_t>'
o[cell_data_label + '/Phases'].attrs['TupleDimensions'] = np.array(self.cells,np.uint64)
# Eulers attributes
o[cell_data_label + '/Eulers'].attrs['ComponentDimensions'] = np.array([3],np.uint64)
o[cell_data_label + '/Eulers'].attrs['ObjectType'] = 'DataArray<float>'
o[cell_data_label + '/Eulers'].attrs['TupleDimensions'] = np.array(self.cells,np.uint64)
# Create EnsembleAttributeMatrix
ensemble_label = data_container_label + '/CellEnsembleData'
# Data CrystalStructures
o[ensemble_label + '/CrystalStructures'] = np.uint32(np.array([999] + [1]*len(self.phases)))
# assuming only cubic crystal structures
# Damask can give the crystal structure info but need to look into dream3d which crystal structure corresponds to which number
o[ensemble_label + '/PhaseTypes'] = np.uint32(np.array([999] + [Phase_types['Primary']]*len(self.phases))).reshape((len(self.phases)+1,1))
# also assuming Primary phases
# there can be precipitates etc as well
# Attributes Ensemble Matrix
o[ensemble_label].attrs['AttributeMatrixType'] = np.array([11],np.uint32)
o[ensemble_label].attrs['TupleDimensions'] = np.array([len(self.phases) + 1], np.uint64)
# Attributes for data in Ensemble matrix
for group in ['CrystalStructures','PhaseTypes']: # 'PhaseName' not required MD: But would be nice to take the phase name mapping
o[ensemble_label+'/'+group].attrs['ComponentDimensions'] = np.array([1],np.uint64)
o[ensemble_label+'/'+group].attrs['Tuple Axis Dimensions'] = f'x={len(self.phases)+1}'
o[ensemble_label+'/'+group].attrs['DataArrayVersion'] = np.array([2],np.int32)
o[ensemble_label+'/'+group].attrs['ObjectType'] = 'DataArray<uint32_t>'
o[ensemble_label+'/'+group].attrs['TupleDimensions'] = np.array([len(self.phases) + 1],np.uint64)
# Create geometry info
geom_label = data_container_label + '/_SIMPL_GEOMETRY'
o[geom_label + '/DIMENSIONS'] = np.int64(np.array(self.cells))
o[geom_label + '/ORIGIN'] = np.float32(np.zeros(3))
o[geom_label + '/SPACING'] = np.float32(dx)
o[geom_label].attrs['GeometryName'] = 'ImageGeometry'
o[geom_label].attrs['GeometryTypeName'] = 'ImageGeometry'
o[geom_label].attrs['GeometryType'] = np.array([0],np.uint32)
o[geom_label].attrs['SpatialDimensionality'] = np.array([3],np.uint32)
o[geom_label].attrs['UnitDimensionality'] = np.array([3],np.uint32)
def export_DADF5(self,
fname,
output: Union[str, List[str]] = '*'):