# HG changeset patch # User ximgchess # Date 1652978902 0 # Node ID 59453ad6e2196822957c764b5db2511512637d23 "planemo upload for repository https://github.com/ximg-chess/galaxytools/tools/hedm_lattice_parameter_correction commit 420bbed5449757711b88200208bb050e0797f5a3" diff -r 000000000000 -r 59453ad6e219 hedm_lattice_parameter_correction.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedm_lattice_parameter_correction.xml Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,62 @@ + + Extract average lattice parameters from grains.out + + macros.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 59453ad6e219 lattice_parameter_correction.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lattice_parameter_correction.py Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 + +import argparse + +import numpy as np + +from hexrd import rotations as rot +from hexrd import matrixutil as mutil +from hexrd import config +from hexrd import material + + +def _lp_calc(v_mat, f_mat, r_mat): + """ + do strained lappi + + Parameters + ---------- + vmat : TYPE + DESCRIPTION. + f_mat : TYPE + DESCRIPTION. + r_mat : TYPE + DESCRIPTION. + + Returns + ------- + lparams : TYPE + DESCRIPTION. + + """ + f_prime = np.dot(v_mat, np.dot(r_mat, f_mat)) + f_prime_hat = mutil.unitVector(f_prime) + + lp_mags = mutil.columnNorm(f_prime) + + lp_angs = np.hstack( + [np.arccos(np.dot(f_prime_hat[:, 1], f_prime_hat[:, 2])), + np.arccos(np.dot(f_prime_hat[:, 2], f_prime_hat[:, 0])), + np.arccos(np.dot(f_prime_hat[:, 0], f_prime_hat[:, 1]))] + ) + return np.hstack([lp_mags, np.degrees(lp_angs)]) + + +def extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=0.90, force_symmetry=False, + materials_out=None + ): + """ + """ + cfg = config.open(cfg_file)[0] + mcfg = cfg.material + m = mcfg.materials[mcfg.active] + # print(f'material.latticeParameters: {m.latticeParameters}') + # print(f'material.planeData: {m.planeData}') + + pd = cfg.material.plane_data + qsym_mats = rot.quatProductMatrix(pd.getQSym()) + + f_mat = pd.latVecOps['F'] + + gt = np.loadtxt(grains_file) + + idx = gt[:, 1] >= min_completeness + + expMaps = gt[idx, 3:6].T + vinv = gt[idx, 9:15] + + lparms = [] + for i in range(sum(idx)): + quat = rot.quatOfExpMap(expMaps[:, i].reshape(3, 1)) + v_mat = np.linalg.inv(mutil.vecMVToSymm(vinv[i, :].reshape(6, 1))) + if force_symmetry: + for qpm in qsym_mats: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(np.dot(qpm, quat))) + ) + else: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(quat)) + ) + lp_avg = np.average(np.vstack(lparms), axis=0) + if materials_out is not None: + m.latticeParameters = lp_avg + # print(f'material.latticeParameters: {m.latticeParameters}') + # print(f'material.latticeParameters: {mcfg.materials[mcfg.active].latticeParameters}') + # print(f'material.planeData: {m.planeData}') + material.save_materials_hdf5(materials_out, mcfg.materials) + return lp_avg, sum(idx), len(idx) + + +if __name__ == '__main__': + """ + maybe make this smart enough to average properly for symmetry? + """ + parser = argparse.ArgumentParser( + description="Extract average lattice parameters from grains.out" + ) + parser.add_argument( + 'cfg', help="ff-HEDM config YAML file", type=str + ) + parser.add_argument( + 'grains_file', help="grains.out file", type=str + ) + parser.add_argument( + '-m', '--min-completeness', help="completeness threshold", type=float, + default=0.75 + ) + parser.add_argument( + '-f', '--force-symmetry', + help="symmetrize results", + action="store_true" + ) + parser.add_argument( + '-a', '--average_lattice', default="None", help="average lattice file" + ) + parser.add_argument( + '-o', '--materials_out', default="None", help="updated material file" + ) + args = parser.parse_args() + + cfg_file = args.cfg + grains_file = args.grains_file + min_completeness = args.min_completeness + force_symmetry = args.force_symmetry + materials_out = args.materials_out + + lp_avg, n_used, n_total = extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=min_completeness, force_symmetry=force_symmetry, + materials_out=materials_out + ) + print("Using %d grains out of %d above %.2f%% completeness threshold:" + % (n_used, n_total, 100*min_completeness)) + print("---------------------------------------------------------------") + print("a \tb \tc " + + "\talpha \tbeta \tgamma \n" + + "%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f" % tuple(lp_avg)) + if args.average_lattice: + with open(args.average_lattice,'w') as fh: + print("%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f" % tuple(lp_avg), file=fh) diff -r 000000000000 -r 59453ad6e219 lattice_parameter_correction.py.orig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lattice_parameter_correction.py.orig Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +import argparse + +import numpy as np + +from hexrd import rotations as rot +from hexrd import matrixutil as mutil +from hexrd import config + + +def _lp_calc(v_mat, f_mat, r_mat): + """ + do strained lappi + + Parameters + ---------- + vmat : TYPE + DESCRIPTION. + f_mat : TYPE + DESCRIPTION. + r_mat : TYPE + DESCRIPTION. + + Returns + ------- + lparams : TYPE + DESCRIPTION. + + """ + f_prime = np.dot(v_mat, np.dot(r_mat, f_mat)) + f_prime_hat = mutil.unitVector(f_prime) + + lp_mags = mutil.columnNorm(f_prime) + + lp_angs = np.hstack( + [np.arccos(np.dot(f_prime_hat[:, 1], f_prime_hat[:, 2])), + np.arccos(np.dot(f_prime_hat[:, 2], f_prime_hat[:, 0])), + np.arccos(np.dot(f_prime_hat[:, 0], f_prime_hat[:, 1]))] + ) + return np.hstack([lp_mags, np.degrees(lp_angs)]) + + +def extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=0.90, force_symmetry=False + ): + """ + """ + cfg = config.open(cfg_file)[0] + + pd = cfg.material.plane_data + qsym_mats = rot.quatProductMatrix(pd.getQSym()) + + f_mat = pd.latVecOps['F'] + + gt = np.loadtxt(grains_file) + + idx = gt[:, 1] >= min_completeness + + expMaps = gt[idx, 3:6].T + vinv = gt[idx, 9:15] + + lparms = [] + for i in range(sum(idx)): + quat = rot.quatOfExpMap(expMaps[:, i].reshape(3, 1)) + v_mat = np.linalg.inv(mutil.vecMVToSymm(vinv[i, :].reshape(6, 1))) + if force_symmetry: + for qpm in qsym_mats: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(np.dot(qpm, quat))) + ) + else: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(quat)) + ) + lp_avg = np.average(np.vstack(lparms), axis=0) + return lp_avg, sum(idx), len(idx) + + +if __name__ == '__main__': + """ + maybe make this smart enough to average properly for symmetry? + """ + parser = argparse.ArgumentParser( + description="Extract average lattice parameters from grains.out" + ) + parser.add_argument( + 'cfg', help="ff-HEDM config YAML file", type=str + ) + parser.add_argument( + 'grains_file', help="grains.out file", type=str + ) + parser.add_argument( + '-m', '--min-completeness', help="completeness threshold", type=float, + default=0.75 + ) + + parser.add_argument( + '-f', '--force-symmetry', + help="symmetrize results", + action="store_true" + ) + + args = parser.parse_args() + + cfg_file = args.cfg + grains_file = args.grains_file + min_completeness = args.min_completeness + force_symmetry = args.force_symmetry + + lp_avg, n_used, n_total = extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=min_completeness, force_symmetry=force_symmetry + ) + print("Using %d grains out of %d above %.2f%% completeness threshold:" + % (n_used, n_total, 100*min_completeness)) + print("---------------------------------------------------------------") + print("a \tb \tc " + + "\talpha \tbeta \tgamma \n" + + "%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f" % tuple(lp_avg)) diff -r 000000000000 -r 59453ad6e219 macros.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/macros.xml Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,50 @@ + + 0.8.19 + 0 + 21.09 + + + hexrd + + + + + + 10.1016/j.matchar.2020.110366 + + + + + +#import re +#import yaml +#def identifier_or_name($input1) + #if hasattr($input1, 'element_identifier') + #return $input1.element_identifier + #elif hasattr($input1, 'name') + #return $input1.name + #else + #return str($input1) + #end if +#end def +#def clean($name1) + #set $name_clean = $re.sub('[^\w\-_]', '_', $re.sub('(?i)[.](npz|hexrd|yml|dat|out)$','', $name1.split()[-1])) + #return $name_clean +#end def +#def ln_name($ds,$ext) + #set $lname = "%s.%s" % ($clean($identifier_or_name($ds)),$ext) + #return $lname +#end def +#def update_config($cfg_in, $mat_path, $inst_path) + #set $cfg = $yaml.safe_load(open(str($cfg_in),'r')) + #if $mat_path and 'material' in $cfg and 'definitions' in $cfg['material'] + #silent $cfg['material']['definitions'] = str($mat_path) + #end if + #if $inst_path and 'instrument' in $cfg + #silent $cfg['instrument'] = str($inst_path) + #end if +#slurp +$yaml.dump($cfg) +#end def + + diff -r 000000000000 -r 59453ad6e219 test-data/config.out.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/config.out.yml Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,37 @@ +analysis_name: analysis +find_orientations: + orientation_maps: + file: analysis_ruby_eta-ome_maps.npz +fit_grains: + do_fit: true + npdiv: 2 + refit: + - 1.5 + - 1.0 + threshold: 25 + tolerance: + eta: + - 2.0 + omega: + - 1.0 + tth: + - 3.0 + tth_max: true +image_series: + data: + - args: {} + file: imageseries/mruby-0129_000004_ff2_000012-cachefile.npz + panel: ff2 + - args: {} + file: imageseries/mruby-0129_000004_ff1_000012-cachefile.npz + panel: ff1 + format: frame-cache +instrument: dexelas_id3a_20200130.yml +material: + active: ruby + definitions: /Users/jj/gx/gh/ximg/galaxytools-2/tools/hedm_lattice_parameter_correction/test-data/materials_h5.h5 + dmin: 1.0 + min_sfac_ratio: 0.05 + tth_width: 0.25 +multiprocessing: -1 + diff -r 000000000000 -r 59453ad6e219 test-data/config.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/config.yml Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,46 @@ + + + +analysis_name: analysis + +multiprocessing: -1 + +material: + definitions: materials_h5.h5 + active: ruby + dmin: 1.0 # defaults to 1.0 angstrom + tth_width: 0.25 # defaults to 0.25 degrees + min_sfac_ratio: 0.05 # min percentage of max |F|^2 to exclude; default None + +image_series: + format: frame-cache + data: + - file: imageseries/mruby-0129_000004_ff2_000012-cachefile.npz + args: {} + panel: ff2 # must match detector key + - file: imageseries/mruby-0129_000004_ff1_000012-cachefile.npz + args: {} + panel: ff1 # must match detector key + +instrument: dexelas_id3a_20200130.yml + + +find_orientations: + orientation_maps: + # A file name must be specified. If it doesn't exist, one will be created + file: analysis_ruby_eta-ome_maps.npz + +fit_grains: + do_fit: true # if false, extracts grains but doesn't fit. defaults to true + # estimate: null + npdiv: 2 # number of polar pixel grid subdivisions, defaults to 2 + threshold: 25 + + tolerance: + tth: [3.0] # tolerance lists must be identical length + eta: [2.0] + omega: [1.0] + + refit: [1.5,1.0] + tth_max: true # true, false, or a non-negative value, defaults to true + diff -r 000000000000 -r 59453ad6e219 test-data/dexelas_id3a_20200130.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/dexelas_id3a_20200130.yml Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,102 @@ +beam: + energy: 41.9906 + vector: + azimuth: 90.0 + polar_angle: 90.0 +calibration_crystal: + 0: + inv_stretch: + - 1.0 + - 1.0 + - 1.0 + - 0.0 + - 0.0 + - 0.0 + orientation: + - 1.2148784044413221 + - 0.6945507909200794 + - 0.765702046701113 + position: + - 0.06060121926310595 + - 0.1312120981443553 + - -0.06694059935413639 + 1: + inv_stretch: + - 1.0 + - 1.0 + - 1.0 + - 0.0 + - 0.0 + - 0.0 + orientation: + - 1.4105172207115466 + - -0.14336674130145605 + - -0.37238882282338215 + position: + - 0.016940740257706914 + - -0.1183857552099456 + - 0.34767784259162654 + 2: + inv_stretch: + - 1.0 + - 1.0 + - 1.0 + - 0.0 + - 0.0 + - 0.0 + orientation: + - 0.34356534660437343 + - 0.8170405732053853 + - -0.01649123635877074 + position: + - 0.01052568572502354 + - -0.11080094260256373 + - -0.33689416855383947 +detectors: + ff1: + buffer: + - 2.0 + - 2.0 + pixels: + columns: 3072 + rows: 3888 + size: + - 0.0748 + - 0.0748 + saturation_level: 15800.0 + transform: + tilt: + - 0.010486950176001908 + - -0.006152055149709758 + - 0.0014922461489979366 + translation: + - 123.3706062259476 + - 3.325955053634411 + - -670.7508650125019 + ff2: + buffer: + - 2.0 + - 2.0 + pixels: + columns: 3072 + rows: 3888 + size: + - 0.0748 + - 0.0748 + saturation_level: 15800.0 + transform: + tilt: + - 0.00991389059922992 + - -0.01010540645355334 + - 0.00026733734489633163 + translation: + - -123.5603890819458 + - 3.186895450085356 + - -671.04758940985 +id: dexelas_id3a_20200130 +oscillation_stage: + chi: 0.0007535217427322955 + translation: + - 0.0 + - 0.0 + - 0.0 diff -r 000000000000 -r 59453ad6e219 test-data/grains.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/grains.out Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,4 @@ +# grain ID completeness chi^2 exp_map_c[0] exp_map_c[1] exp_map_c[2] t_vec_c[0] t_vec_c[1] t_vec_c[2] inv(V_s)[0,0] inv(V_s)[1,1] inv(V_s)[2,2] inv(V_s)[1,2]*sqrt(2) inv(V_s)[0,2]*sqrt(2) inv(V_s)[0,1]*sqrt(2) ln(V_s)[0,0] ln(V_s)[1,1] ln(V_s)[2,2] ln(V_s)[1,2] ln(V_s)[0,2] ln(V_s)[0,1] +0 1.000000 5.369697e-04 1.4105338333495454e+00 -1.4357856278205916e-01 -3.7236476312134781e-01 1.4606505177249375e-02 -1.3140046151347134e-01 3.4060190489934772e-01 1.0003775982839029e+00 9.9944300862177005e-01 1.0002266996126810e+00 -2.0098254132149165e-05 -4.9238869081289537e-05 1.9534109219804900e-04 -3.7751686766115180e-04 5.5715620077280111e-04 -2.2667321347921970e-04 1.4211555470441899e-05 3.4805640272123023e-05 -1.3813916516906802e-04 +1 0.989130 7.511846e-04 1.2147550631708239e+00 6.9402347166184886e-01 7.6543118665132748e-01 5.9612267368878889e-02 1.1405034788195756e-01 -7.2183402157879217e-02 1.0004241448431779e+00 9.9933252120647686e-01 9.9997982101162919e-01 1.4989477496824173e-04 5.2684926604946789e-05 5.1080735497269734e-04 -4.2398900339413604e-04 6.6777254859082887e-04 2.0185504529689508e-05 -1.0602134697524727e-04 -3.7227202925975544e-05 -3.6123737394211304e-04 +2 1.000000 8.138777e-04 3.4401229493783497e-01 8.1672452573494558e-01 -1.6886951921517571e-02 1.3499398451489408e-02 -1.2236493959833296e-01 -3.3233691582841279e-01 9.9982579134269456e-01 9.9996756647100571e-01 1.0002294836828227e+00 3.1419240600766599e-04 -5.3475171509938853e-04 7.6955776196857811e-04 1.7444345183427053e-04 3.2606840387861337e-05 -2.2936117649414523e-04 -2.2224861045200161e-04 3.7817662691540954e-04 -5.4425783361271827e-04 diff -r 000000000000 -r 59453ad6e219 test-data/lattice_parameter_correction.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/lattice_parameter_correction.py Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 + +import argparse + +import numpy as np + +from hexrd import rotations as rot +from hexrd import matrixutil as mutil +from hexrd import config +from hexrd import material + + +def _lp_calc(v_mat, f_mat, r_mat): + """ + do strained lappi + + Parameters + ---------- + vmat : TYPE + DESCRIPTION. + f_mat : TYPE + DESCRIPTION. + r_mat : TYPE + DESCRIPTION. + + Returns + ------- + lparams : TYPE + DESCRIPTION. + + """ + f_prime = np.dot(v_mat, np.dot(r_mat, f_mat)) + f_prime_hat = mutil.unitVector(f_prime) + + lp_mags = mutil.columnNorm(f_prime) + + lp_angs = np.hstack( + [np.arccos(np.dot(f_prime_hat[:, 1], f_prime_hat[:, 2])), + np.arccos(np.dot(f_prime_hat[:, 2], f_prime_hat[:, 0])), + np.arccos(np.dot(f_prime_hat[:, 0], f_prime_hat[:, 1]))] + ) + return np.hstack([lp_mags, np.degrees(lp_angs)]) + + +def extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=0.90, force_symmetry=False, + materials_out=None + ): + """ + """ + cfg = config.open(cfg_file)[0] + mcfg = cfg.material + m = mcfg.materials[mcfg.active] + print(f'material.latticeParameters: {m.latticeParameters}') + print(f'material.planeData: {m.planeData}') + + pd = cfg.material.plane_data + qsym_mats = rot.quatProductMatrix(pd.getQSym()) + + f_mat = pd.latVecOps['F'] + + gt = np.loadtxt(grains_file) + + idx = gt[:, 1] >= min_completeness + + expMaps = gt[idx, 3:6].T + vinv = gt[idx, 9:15] + + lparms = [] + for i in range(sum(idx)): + quat = rot.quatOfExpMap(expMaps[:, i].reshape(3, 1)) + v_mat = np.linalg.inv(mutil.vecMVToSymm(vinv[i, :].reshape(6, 1))) + if force_symmetry: + for qpm in qsym_mats: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(np.dot(qpm, quat))) + ) + else: + lparms.append( + _lp_calc(v_mat, f_mat, rot.rotMatOfQuat(quat)) + ) + lp_avg = np.average(np.vstack(lparms), axis=0) + if materials_out is not None: + m.latticeParameters = lp_avg + print(f'material.latticeParameters: {m.latticeParameters}') + print(f'material.latticeParameters: {mcfg.materials[mcfg.active].latticeParameters}') + print(f'material.planeData: {m.planeData}') + material.save_materials_hdf5(materials_out, mcfg.materials) + return lp_avg, sum(idx), len(idx) + + +if __name__ == '__main__': + """ + maybe make this smart enough to average properly for symmetry? + """ + parser = argparse.ArgumentParser( + description="Extract average lattice parameters from grains.out" + ) + parser.add_argument( + 'cfg', help="ff-HEDM config YAML file", type=str + ) + parser.add_argument( + 'grains_file', help="grains.out file", type=str + ) + parser.add_argument( + '-m', '--min-completeness', help="completeness threshold", type=float, + default=0.75 + ) + parser.add_argument( + '-f', '--force-symmetry', + help="symmetrize results", + action="store_true" + ) + parser.add_argument( + '-a', '--average_lattice', default="None", help="average lattice file" + ) + parser.add_argument( + '-o', '--output', default="None", help="updated material file" + ) + args = parser.parse_args() + + cfg_file = args.cfg + grains_file = args.grains_file + min_completeness = args.min_completeness + force_symmetry = args.force_symmetry + materials_out = args.output + + lp_avg, n_used, n_total = extract_lattice_parameters( + cfg_file, grains_file, + min_completeness=min_completeness, force_symmetry=force_symmetry, + materials_out=materials_out + ) + print("Using %d grains out of %d above %.2f%% completeness threshold:" + % (n_used, n_total, 100*min_completeness)) + print("---------------------------------------------------------------") + print("a \tb \tc " + + "\talpha \tbeta \tgamma \n" + + "%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f" % tuple(lp_avg)) + if args.average_lattice: + with open(args.average_lattice,'w') as fh: + print("%.6f\t%.6f\t%.6f\t%.6f\t%.6f\t%.6f" % tuple(lp_avg), file=fh) diff -r 000000000000 -r 59453ad6e219 test-data/lp_avg.tsv --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/lp_avg.tsv Thu May 19 16:48:22 2022 +0000 @@ -0,0 +1,1 @@ +4.758953 4.759407 12.998517 90.015292 90.002978 120.001436 diff -r 000000000000 -r 59453ad6e219 test-data/m_out.h5 Binary file test-data/m_out.h5 has changed diff -r 000000000000 -r 59453ad6e219 test-data/materials_h5.h5 Binary file test-data/materials_h5.h5 has changed