Skip to content

Commit

Permalink
Improvements in analysis and plotting of microstructure statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
AHartmaier committed Mar 24, 2024
1 parent 6e6263e commit 0e003f8
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 303 deletions.
13 changes: 7 additions & 6 deletions examples/EBSD_analysis/convert_ang2rve.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
raise ModuleNotFoundError('MTEX module not available. Run kanapy setupTexture before using this script.')

fname = 'ebsd_316L_500x500.ang' # name of ang file to be imported
nvox = 30 # number of voxels per side
box_length = 50 # side length of generated RVE in micron
periodic = False # create RVE with periodic structure
nvox = 30 # number of voxels per side
box_length = 50 # side length of generated RVE in micron
periodic = False # create RVE with periodic structure

# read EBSD map and evaluate statistics of microstructural features
ebsd = knpy.EBSDmap(fname)
Expand All @@ -43,8 +43,8 @@

# create dictionary with statistical information obtained from EBSD map
ms_stats = knpy.set_stats(gs_param, ar_param, om_param,
deq_min=8.0, deq_max=19.0, asp_min=0.95, asp_max=3.5,
omega_min=0.0, omega_max=2*np.pi,
deq_min=8.0, deq_max=17.0, asp_min=3.5, asp_max=5.0,
omega_min=0.0, omega_max=np.pi,
voxels=nvox, size=box_length,
periodicity=periodic,
VF=1.0, phasename=matname, phasenum=0)
Expand All @@ -61,7 +61,8 @@
ms.plot_voxels(sliced=False) # plot voxels colored according to grain number
ms.generate_grains() # generate a polyhedral hull around each voxelized grain
ms.plot_grains() # plot polyhedral grains
ms.plot_stats(gs_param=gs_param, ar_param=ar_param) # compare final grain statistics with initial parameters
ms.plot_stats('g', gs_param=gs_param, ar_param=ar_param,
show_plot=False) # compare final grain statistics with initial parameters

# generate and assign grains orientations
ms.generate_orientations(ebsd)
Expand Down
1 change: 0 additions & 1 deletion src/kanapy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from kanapy.plotting import plot_voxels_3D, plot_polygons_3D
from kanapy.input_output import writeAbaqusMat, pickle2microstructure, import_voxels, \
import_stats, write_stats
from kanapy.rve_stats import get_stats_vox, get_stats_part, get_stats_poly
from kanapy.util import ROOT_DIR, MAIN_DIR, MTEX_DIR, poly_scale

log_level = 20 # Levels for logging: 10: DEBUG, 20: INFO, 30: WARNING, 40: ERROR
Expand Down
72 changes: 51 additions & 21 deletions src/kanapy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from scipy.spatial import Delaunay

from kanapy.grains import calc_polygons
from kanapy.rve_stats import get_stats
from kanapy.entities import Simulation_Box
from kanapy.input_output import export2abaqus, writeAbaqusMat, read_dump
from kanapy.initializations import RVE_creator, mesh_creator
Expand Down Expand Up @@ -68,6 +67,9 @@ class Microstructure(object):
Dict keys: "Vertices", "Points", "Simplices", "Facets", "Grains", "GBnodes", GBarea" "GBfaces"
"Grains" : dictionary with key grain_number
Keys:"Vertices", "Points", "Center", "Simplices", "Volume", "Area", "Phase", "eqDia", "majDia", "minDia"
rve_stats : list
List of dictionaries containing statistical information on different RVE types: particles, voxels,
polyhedral grains
"""

def __init__(self, descriptor=None, file=None, name='Microstructure'):
Expand All @@ -81,6 +83,7 @@ def __init__(self, descriptor=None, file=None, name='Microstructure'):
self.geometry = None
self.simbox = None
self.mesh = None
self.rve_stats = None
self.from_voxels = False
self.ialloy = None

Expand Down Expand Up @@ -415,11 +418,13 @@ def plot_grains(self, geometry=None, cmap='prism', alpha=0.4,
def plot_stats(self, data=None,
gs_data=None, gs_param=None,
ar_data=None, ar_param=None,
particles=True,
save_files=False,
show_plot=True, verbose=False, ax_max=None):
show_plot=True, verbose=False):
""" Plots the particle- and grain diameter attributes for statistical
comparison."""
ax_max = np.prod(self.rve.size) ** (1 / 3)
stats_list = []
labels = []
if self.precipit and 0 in self.mesh.grain_dict.keys():
# in case of precipit, remove irregular grain 0 from analysis
nphases = self.nphases - 1
Expand All @@ -429,47 +434,72 @@ def plot_stats(self, data=None,
(type(data) is str and 'p' in data.lower()):
# analyse particle statistics
if self.particles is None:
logging.error('Particle statistics requested, but no particles defined.')
logging.error('Particle statistics requested, but no particles defined. '
'Run "pack()" first.')
return
part_stats = get_stats_part(self.particles, show_plot=show_plot,
verbose=verbose, ax_max=ax_max, save_files=save_files)
stats_list.append(part_stats)
labels.append("Partcls")

if data is None or \
(type(data) is str and 'v' in data.lower()):
# analyse voxel statistics
if self.mesh is None:
logging.error('Particle statistics requested, but no particles defined.')
logging.error('Voxel statistics requested, but no voxel mesh defined. '
'Run "voxelize()" first.')
return
vox_stats = get_stats_vox(self.mesh, show_plot=show_plot,
verbose=verbose, ax_max=ax_max, save_files=save_files)

if self.rve.particle_data is not None:
# analyse grains w.r.t. statistical descriptors
data = get_stats(self.rve.particle_data, self.geometry, self.rve.units,
nphases, self.mesh.ngrains_phase)
if data is None:
raise ValueError('No microstructure data created yet. Run generate_grains() first.')
elif type(data) is not list:
data = [data]
stats_list.append(vox_stats)
labels.append('Voxels')
if data is None or \
(type(data) is str and 'g' in data.lower()):
# analyse voxel statistics
if self.geometry is None:
logging.error('Geometry statistics requested, but no polyhedral grains defined. '
'Run "generate_grains()" first.')
return
grain_stats = get_stats_poly(self.geometry['Grains'], show_plot=show_plot,
verbose=verbose, ax_max=ax_max, save_files=save_files)
stats_list.append(grain_stats)
labels.append('Grains')
print('\nStatistical microstructure parameters of RVE')
print('--------------------------------------------')
print(f'Type\t| a (µm) \t| b (µm) \t| c (µm) \t| std.dev\t| rot.axis\t| asp.ratio\t| std.dev\t|'
f' equ.dia. (µm)\t| std.dev')
for i, sd in enumerate(stats_list):
av_std = np.mean([sd['a_sig'], sd['b_sig'], sd['c_sig']])
print(f'{labels[i]}\t| {sd["a_scale"]:.3f}\t| {sd["b_scale"]:.3f}\t| {sd["c_scale"]:.3f}\t| '
f'{av_std:.4f}\t| {sd["ind_rot"]} \t| {sd["ar_scale"]:.3f}\t| {sd["ar_sig"]:.4f}\t| '
f'{sd["eqd_scale"]:.3f} \t| {sd["eqd_sig"]:.4f}')
self.rve_stats = stats_list
self.rve_stats_labels = labels
# analyse grains w.r.t. statistical descriptors
cdat = [stats_list]
ldat = [labels]
if type(cdat) is not list:
cdat = [data]
if gs_data is None or type(gs_data) is not list:
gs_data = [gs_data] * len(data)
gs_data = [gs_data] * len(cdat)
if gs_param is None or type(gs_param) is not list:
gs_param = [gs_param] * len(data)
gs_param = [gs_param] * len(cdat)
if ar_data is None or type(ar_data) is not list:
ar_data = [ar_data] * len(data)
ar_data = [ar_data] * len(cdat)
if ar_param is None or type(ar_param) is not list:
ar_param = [ar_param] * len(data)
ar_param = [ar_param] * len(cdat)
"""
gs_data = [ebsd.ms_data[i]['gs_data'] for i in range(Nphases)]
gs_param = [ebsd.ms_data[i]['gs_param'] for i in range(Nphases)]
ar_data = [ebsd.ms_data[i]['ar_data'] for i in range(Nphases)]
ar_param = [ebsd.ms_data[i]['ar_param'] for i in range(Nphases)]
"""

for i, ds in enumerate(data):
for i, ds in enumerate(cdat):
print(f'Plotting input & output statistics for phase {i}')
plot_output_stats(ds, gs_data=gs_data[i], gs_param=gs_param[i],
plot_output_stats(ds, ldat[i],
gs_data=gs_data[i], gs_param=gs_param[i],
ar_data=ar_data[i], ar_param=ar_param[i],
plot_particles=particles,
save_files=save_files)

def plot_stats_init(self, descriptor=None, gs_data=None, ar_data=None,
Expand Down
Loading

0 comments on commit 0e003f8

Please sign in to comment.