def find_orientations(cfg, hkls=None, profile=False): """Takes a config dict as input, generally a yml document""" # a goofy call, could be replaced with two more targeted calls pd, reader, detector = initialize_experiment(cfg) logger.info("beginning analysis '%s'", cfg.analysis_name) # load the eta_ome orientation maps eta_ome = load_eta_ome_maps(cfg, pd, reader, detector, hkls) try: # are we searching the full grid of orientation space? qgrid_f = cfg.find_orientations.use_quaternion_grid quats = np.loadtxt(qgrid_f).T logger.info("Using %s for full quaternion search", qgrid_f) except (IOError, ValueError): # or doing a seeded search? logger.info("Defaulting to seeded search") hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds hklseedstr = ', '.join( [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]]) logger.info("Seeding search using hkls from %s: %s", cfg.find_orientations.orientation_maps.file, hklseedstr) quats = generate_orientation_fibers( eta_ome, cfg.find_orientations.threshold, cfg.find_orientations.seed_search.hkl_seeds, cfg.find_orientations.seed_search.fiber_ndiv) np.savetxt(os.path.join(cfg.working_dir, 'trial_orientations.dat'), quats.T, fmt="%.18e", delimiter="\t") # generate the completion maps logger.info("Running paintgrid on %d trial orientations", (quats.shape[1])) if profile: logger.info("Profiling mode active, forcing ncpus to 1") ncpus = 1 else: ncpus = cfg.multiprocessing logger.info("%d of %d available processors requested", ncpus, mp.cpu_count()) compl = idx.paintGrid( quats, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=cfg.find_orientations.threshold, doMultiProc=ncpus > 1, nCPUs=ncpus) np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl) # cluster analysis to identify orientation blobs, the final output: qbar, cl = run_cluster(compl, quats, pd.getQSym(), cfg) np.savetxt(os.path.join(cfg.working_dir, 'accepted_orientations.dat'), qbar.T, fmt="%.18e", delimiter="\t")
def test_GOE(cfg, quat, eta_ome, ome_tol=0.5, eta_tol=0.05): ncpus = cfg.multiprocessing compl = indexer.paintGrid( qball, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(ome_tol), etaTol=np.radians(eta_tol), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=comp_thresh, doMultiProc=ncpus > 1, nCPUs=ncpus) return compl
def find_orientations(cfg, hkls=None, clean=False, profile=False, nsim=100): print('ready to run find_orientations') # %% # ============================================================================= # SEARCH SPACE GENERATION # ============================================================================= hedm = cfg.instrument.hedm plane_data = cfg.material.plane_data ncpus = cfg.multiprocessing # for indexing active_hkls = cfg.find_orientations.orientation_maps.active_hkls fiber_ndiv = cfg.find_orientations.seed_search.fiber_ndiv fiber_seeds = cfg.find_orientations.seed_search.hkl_seeds on_map_threshold = cfg.find_orientations.threshold # for clustering cl_radius = cfg.find_orientations.clustering.radius min_compl = cfg.find_orientations.clustering.completeness compl_thresh = cfg.find_orientations.clustering.completeness eta_ome = get_eta_ome(cfg, clean=clean) print("INFO:\tgenerating search quaternion list using %d processes" % ncpus) start = timeit.default_timer() qfib = generate_orientation_fibers(eta_ome, hedm.chi, on_map_threshold, fiber_seeds, fiber_ndiv, ncpus=ncpus) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) print("INFO: will test %d quaternions using %d processes" % (qfib.shape[1], ncpus)) # %% # ============================================================================= # ORIENTATION SCORING # ============================================================================= scoredq_filename = 'scored_orientations_' + analysis_id(cfg) + '.npz' print("INFO:\tusing map search with paintGrid on %d processes" % ncpus) start = timeit.default_timer() completeness = indexer.paintGrid( qfib, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=on_map_threshold, doMultiProc=ncpus > 1, nCPUs=ncpus) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) completeness = np.array(completeness) # export scored orientations np.savez_compressed(scoredq_filename, quaternions=qfib, completeness=completeness) print("INFO:\tsaved scored orientations to file: '%s'" % (scoredq_filename)) # %% # ============================================================================= # CLUSTERING AND GRAINS OUTPUT # ============================================================================= if not os.path.exists(cfg.analysis_dir): os.makedirs(cfg.analysis_dir) qbar_filename = 'accepted_orientations_' + analysis_id(cfg) + '.dat' print("INFO:\trunning clustering using '%s'" % cfg.find_orientations.clustering.algorithm) start = timeit.default_timer() # Simulate N random grains to get neighborhood size print("INFO:\trunning %d simulations to determine neighborhood size" % nsim) seed_hkl_ids = [ plane_data.hklDataList[active_hkls[i]]['hklID'] for i in fiber_seeds ] # need ome_ranges from imageseries # CAVEAT: assumes that all imageseries have same omega ranges!!! oims = OmegaImageSeries(cfg.image_series.itervalues().next()) ome_ranges = [(np.radians([i['ostart'], i['ostop']])) for i in oims.omegawedges.wedges] if seed_hkl_ids is not None: rand_q = mutil.unitVector(np.random.randn(4, nsim)) rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \ * mutil.unitVector(rand_q[1:, :]) refl_per_grain = np.zeros(nsim) num_seed_refls = np.zeros(nsim) grain_param_list = np.vstack([ rand_e, np.zeros((3, nsim)), np.tile(cnst.identity_6x1, (nsim, 1)).T ]).T sim_results = hedm.simulate_rotation_series( plane_data, grain_param_list, eta_ranges=np.radians(cfg.find_orientations.eta.range), ome_ranges=ome_ranges, ome_period=np.radians(cfg.find_orientations.omega.period)) refl_per_grain = np.zeros(nsim) seed_refl_per_grain = np.zeros(nsim) for sim_result in sim_results.itervalues(): for i, refl_ids in enumerate(sim_result[0]): refl_per_grain[i] += len(refl_ids) seed_refl_per_grain[i] += np.sum( [sum(refl_ids == hkl_id) for hkl_id in seed_hkl_ids]) min_samples = max( int( np.floor(0.5 * cfg.find_orientations.clustering.completeness * min(seed_refl_per_grain))), 2) mean_rpg = int(np.round(np.average(refl_per_grain))) else: min_samples = 1 mean_rpg = 1 print("INFO:\tmean reflections per grain: %d" % mean_rpg) print("INFO:\tneighborhood size: %d" % min_samples) qbar, cl = run_cluster(completeness, qfib, plane_data.getQSym(), cfg, min_samples=min_samples, compl_thresh=compl_thresh, radius=cl_radius) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) print("INFO:\tfound %d grains; saved to file: '%s'" % (qbar.shape[1], qbar_filename)) np.savetxt(qbar_filename, qbar.T, fmt='%.18e', delimiter='\t') gw = instrument.GrainDataWriter( os.path.join(cfg.analysis_dir, 'grains.out')) grain_params_list = [] for gid, q in enumerate(qbar.T): phi = 2 * np.arccos(q[0]) n = xfcapi.unitRowVector(q[1:]) grain_params = np.hstack([phi * n, cnst.zeros_3, cnst.identity_6x1]) gw.dump_grain(gid, 1., 0., grain_params) grain_params_list.append(grain_params) gw.close()
def run_paintGrid(pd, omeEta, seed_hkl_ids, threshold, fiber_ndiv, omeTol=None, etaTol=None, omeRange=None, etaRange=None, omePeriod=(-np.pi, np.pi), qTol=1e-7, doMultiProc=True, nCPUs=multiprocessing.cpu_count(), useGrid=None): """ wrapper for indexer.paintGrid """ del_ome = omeEta.omegas[1] - omeEta.omegas[0] del_eta = omeEta.etas[1] - omeEta.etas[0] # tolerances in degrees... I know, pathological if omeTol is None: omeTol = 360. / float(fiber_ndiv) if etaTol is None: etaTol = 360. / float(fiber_ndiv) # must be consistent pd_hkl_ids = omeEta.iHKLList[seed_hkl_ids] tTh = pd.getTTh() bMat = pd.latVecOps['B'] csym = pd.getLaueGroup() qsym = pd.getQSym() if useGrid is not None: try: print "loading quaternion grid file: %s" % (useGrid) qfib = np.loadtxt(useGrid).T except: raise RuntimeError, "unable to load quaternion grid file" else: structureNDI_label = ndimage.generate_binary_structure(2, 2) qfib = [] ii = 0 jj = fiber_ndiv print "labeling maps..." labels = [] numSpots = [] coms = [] for i in seed_hkl_ids: labels_t, numSpots_t = ndimage.label( omeEta.dataStore[i] > threshold, structureNDI_label) coms_t = np.atleast_2d( ndimage.center_of_mass(omeEta.dataStore[i], labels=labels_t, index=np.arange(1, np.amax(labels_t) + 1))) labels.append(labels_t) numSpots.append(numSpots_t) coms.append(coms_t) pass # second pass for generation print "generating quaternions..." qfib_tmp = np.empty((4, fiber_ndiv * sum(numSpots))) for i in range(len(pd_hkl_ids)): for ispot in range(numSpots[i]): if not np.isnan(coms[i][ispot][0]): ome_c = omeEta.omeEdges[0] + (0.5 + coms[i][ispot][0]) * del_ome eta_c = omeEta.etaEdges[0] + (0.5 + coms[i][ispot][1]) * del_eta gVec_s = xrdutil.makeMeasuredScatteringVectors( tTh[pd_hkl_ids[i]], eta_c, ome_c) qfib_tmp[:, ii:jj] = rot.discreteFiber( pd.hkls[:, pd_hkl_ids[i]].reshape(3, 1), gVec_s, B=bMat, ndiv=fiber_ndiv, invert=False, csym=csym)[0] ii = jj jj += fiber_ndiv pass pass qfib.append(mutil.uniqueVectors(qfib_tmp)) pass qfib = np.hstack(qfib) print "Running paintGrid on %d orientations" % (qfib.shape[1]) complPG = idx.paintGrid(qfib, omeEta, omegaRange=omeRange, etaRange=etaRange, omeTol=d2r * omeTol, etaTol=d2r * etaTol, omePeriod=omePeriod, threshold=threshold, doMultiProc=doMultiProc, nCPUs=nCPUs) return complPG, qfib
def find_orientations(cfg, hkls=None, clean=False, profile=False): """ Takes a config dict as input, generally a yml document NOTE: single cfg instance, not iterator! """ # ...make this an attribute in cfg? analysis_id = '%s_%s' %( cfg.analysis_name.strip().replace(' ', '-'), cfg.material.active.strip().replace(' ', '-'), ) # grab planeData object matl = cPickle.load(open('materials.cpl', 'r')) md = dict(zip([matl[i].name for i in range(len(matl))], matl)) pd = md[cfg.material.active].planeData # make image_series image_series = cfg.image_series.omegaseries # need instrument cfg later on down... instr_cfg = get_instrument_parameters(cfg) detector_params = np.hstack([ instr_cfg['detector']['transform']['tilt_angles'], instr_cfg['detector']['transform']['t_vec_d'], instr_cfg['oscillation_stage']['chi'], instr_cfg['oscillation_stage']['t_vec_s'], ]) rdim = cfg.instrument.detector.pixels.size[0]*cfg.instrument.detector.pixels.rows cdim = cfg.instrument.detector.pixels.size[1]*cfg.instrument.detector.pixels.columns panel_dims = ((-0.5*cdim, -0.5*rdim), ( 0.5*cdim, 0.5*rdim), ) # UGH! hard-coded distortion... if instr_cfg['detector']['distortion']['function_name'] == 'GE_41RT': distortion = (dFuncs.GE_41RT, instr_cfg['detector']['distortion']['parameters'], ) else: distortion = None min_compl = cfg.find_orientations.clustering.completeness # start logger logger.info("beginning analysis '%s'", cfg.analysis_name) # load the eta_ome orientation maps eta_ome = load_eta_ome_maps(cfg, pd, image_series, hkls=hkls, clean=clean) ome_range = ( np.min(eta_ome.omeEdges), np.max(eta_ome.omeEdges) ) try: # are we searching the full grid of orientation space? qgrid_f = cfg.find_orientations.use_quaternion_grid quats = np.load(qgrid_f) logger.info("Using %s for full quaternion search", qgrid_f) hkl_ids = None except (IOError, ValueError, AttributeError): # or doing a seeded search? logger.info("Defaulting to seeded search") hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds hkl_ids = [ eta_ome.planeData.hklDataList[i]['hklID'] for i in hkl_seeds ] hklseedstr = ', '.join( [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]] ) logger.info( "Seeding search using hkls from %s: %s", cfg.find_orientations.orientation_maps.file, hklseedstr ) quats = generate_orientation_fibers( eta_ome, detector_params[6], cfg.find_orientations.threshold, cfg.find_orientations.seed_search.hkl_seeds, cfg.find_orientations.seed_search.fiber_ndiv, ncpus=cfg.multiprocessing, ) if save_as_ascii: np.savetxt( os.path.join(cfg.working_dir, 'trial_orientations.dat'), quats.T, fmt="%.18e", delimiter="\t" ) pass pass # close conditional on grid search # generate the completion maps logger.info("Running paintgrid on %d trial orientations", quats.shape[1]) if profile: logger.info("Profiling mode active, forcing ncpus to 1") ncpus = 1 else: ncpus = cfg.multiprocessing logger.info( "%d of %d available processors requested", ncpus, mp.cpu_count() ) compl = idx.paintGrid( quats, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=cfg.find_orientations.threshold, doMultiProc=ncpus > 1, nCPUs=ncpus ) if save_as_ascii: np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl) else: np.save( os.path.join( cfg.working_dir, 'scored_orientations_%s.npy' %analysis_id ), np.vstack([quats, compl]) ) ########################################################## ## Simulate N random grains to get neighborhood size ## ########################################################## if hkl_ids is not None: ngrains = 100 rand_q = mutil.unitVector(np.random.randn(4, ngrains)) rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \ * mutil.unitVector(rand_q[1:, :]) refl_per_grain = np.zeros(ngrains) num_seed_refls = np.zeros(ngrains) print('fo: hklids = ', hkl_ids) for i in range(ngrains): grain_params = np.hstack([rand_e[:, i], xf.zeroVec.flatten(), xf.vInv_ref.flatten() ]) sim_results = simulateGVecs(pd, detector_params, grain_params, ome_range=(ome_range,), ome_period=(ome_range[0], ome_range[0]+2*np.pi), eta_range=np.radians(cfg.find_orientations.eta.range), panel_dims=panel_dims, pixel_pitch=cfg.instrument.detector.pixels.size, distortion=distortion, ) refl_per_grain[i] = len(sim_results[0]) # lines below fix bug when sim_results[0] is empty if refl_per_grain[i] > 0: num_seed_refls[i] = np.sum([sum(sim_results[0] == hkl_id) for hkl_id in hkl_ids]) else: num_seed_refls[i] = 0 #min_samples = 2 min_samples = max( int(np.floor(0.5*min_compl*min(num_seed_refls))), 2 ) mean_rpg = int(np.round(np.average(refl_per_grain))) else: min_samples = 1 mean_rpg = 1 logger.info("mean number of reflections per grain is %d", mean_rpg) logger.info("neighborhood size estimate is %d points", min_samples) # cluster analysis to identify orientation blobs, the final output: qbar, cl = run_cluster(compl, quats, pd.getQSym(), cfg, min_samples=min_samples) analysis_id = '%s_%s' %( cfg.analysis_name.strip().replace(' ', '-'), cfg.material.active.strip().replace(' ', '-'), ) np.savetxt( os.path.join( cfg.working_dir, 'accepted_orientations_%s.dat' %analysis_id ), qbar.T, fmt="%.18e", delimiter="\t") return
def find_orientations(cfg, hkls=None, clean=False, profile=False): """ Takes a config dict as input, generally a yml document NOTE: single cfg instance, not iterator! """ # ...make this an attribute in cfg? analysis_id = '%s_%s' % ( cfg.analysis_name.strip().replace(' ', '-'), cfg.material.active.strip().replace(' ', '-'), ) # grab planeData object matl = cPickle.load(open('materials.cpl', 'r')) md = dict(zip([matl[i].name for i in range(len(matl))], matl)) pd = md[cfg.material.active].planeData # make image_series image_series = cfg.image_series.omegaseries # need instrument cfg later on down... instr_cfg = get_instrument_parameters(cfg) detector_params = np.hstack([ instr_cfg['detector']['transform']['tilt_angles'], instr_cfg['detector']['transform']['t_vec_d'], instr_cfg['oscillation_stage']['chi'], instr_cfg['oscillation_stage']['t_vec_s'], ]) rdim = cfg.instrument.detector.pixels.size[ 0] * cfg.instrument.detector.pixels.rows cdim = cfg.instrument.detector.pixels.size[ 1] * cfg.instrument.detector.pixels.columns panel_dims = ( (-0.5 * cdim, -0.5 * rdim), (0.5 * cdim, 0.5 * rdim), ) # UGH! hard-coded distortion... if instr_cfg['detector']['distortion']['function_name'] == 'GE_41RT': distortion = ( dFuncs.GE_41RT, instr_cfg['detector']['distortion']['parameters'], ) else: distortion = None min_compl = cfg.find_orientations.clustering.completeness # start logger logger.info("beginning analysis '%s'", cfg.analysis_name) # load the eta_ome orientation maps eta_ome = load_eta_ome_maps(cfg, pd, image_series, hkls=hkls, clean=clean) ome_range = (np.min(eta_ome.omeEdges), np.max(eta_ome.omeEdges)) try: # are we searching the full grid of orientation space? qgrid_f = cfg.find_orientations.use_quaternion_grid quats = np.load(qgrid_f) logger.info("Using %s for full quaternion search", qgrid_f) hkl_ids = None except (IOError, ValueError, AttributeError): # or doing a seeded search? logger.info("Defaulting to seeded search") hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds hkl_ids = [ eta_ome.planeData.hklDataList[i]['hklID'] for i in hkl_seeds ] hklseedstr = ', '.join( [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]]) logger.info("Seeding search using hkls from %s: %s", cfg.find_orientations.orientation_maps.file, hklseedstr) quats = generate_orientation_fibers( eta_ome, detector_params[6], cfg.find_orientations.threshold, cfg.find_orientations.seed_search.hkl_seeds, cfg.find_orientations.seed_search.fiber_ndiv, ncpus=cfg.multiprocessing, ) if save_as_ascii: np.savetxt(os.path.join(cfg.working_dir, 'trial_orientations.dat'), quats.T, fmt="%.18e", delimiter="\t") pass pass # close conditional on grid search # generate the completion maps logger.info("Running paintgrid on %d trial orientations", quats.shape[1]) if profile: logger.info("Profiling mode active, forcing ncpus to 1") ncpus = 1 else: ncpus = cfg.multiprocessing logger.info("%d of %d available processors requested", ncpus, mp.cpu_count()) compl = idx.paintGrid( quats, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=cfg.find_orientations.threshold, doMultiProc=ncpus > 1, nCPUs=ncpus) if save_as_ascii: np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl) else: np.save( os.path.join(cfg.working_dir, 'scored_orientations_%s.npy' % analysis_id), np.vstack([quats, compl])) ########################################################## ## Simulate N random grains to get neighborhood size ## ########################################################## if hkl_ids is not None: ngrains = 100 rand_q = mutil.unitVector(np.random.randn(4, ngrains)) rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \ * mutil.unitVector(rand_q[1:, :]) refl_per_grain = np.zeros(ngrains) num_seed_refls = np.zeros(ngrains) print('fo: hklids = ', hkl_ids) for i in range(ngrains): grain_params = np.hstack( [rand_e[:, i], xf.zeroVec.flatten(), xf.vInv_ref.flatten()]) sim_results = simulateGVecs( pd, detector_params, grain_params, ome_range=(ome_range, ), ome_period=(ome_range[0], ome_range[0] + 2 * np.pi), eta_range=np.radians(cfg.find_orientations.eta.range), panel_dims=panel_dims, pixel_pitch=cfg.instrument.detector.pixels.size, distortion=distortion, ) refl_per_grain[i] = len(sim_results[0]) # lines below fix bug when sim_results[0] is empty if refl_per_grain[i] > 0: num_seed_refls[i] = np.sum( [sum(sim_results[0] == hkl_id) for hkl_id in hkl_ids]) else: num_seed_refls[i] = 0 #min_samples = 2 min_samples = max(int(np.floor(0.5 * min_compl * min(num_seed_refls))), 2) mean_rpg = int(np.round(np.average(refl_per_grain))) else: min_samples = 1 mean_rpg = 1 logger.info("mean number of reflections per grain is %d", mean_rpg) logger.info("neighborhood size estimate is %d points", min_samples) # cluster analysis to identify orientation blobs, the final output: qbar, cl = run_cluster(compl, quats, pd.getQSym(), cfg, min_samples=min_samples) analysis_id = '%s_%s' % ( cfg.analysis_name.strip().replace(' ', '-'), cfg.material.active.strip().replace(' ', '-'), ) np.savetxt(os.path.join(cfg.working_dir, 'accepted_orientations_%s.dat' % analysis_id), qbar.T, fmt="%.18e", delimiter="\t") return
def run_paintGrid(pd, omeEta, seed_hkl_ids, threshold, fiber_ndiv, omeTol=None, etaTol=None, omeRange=None, etaRange=None, omePeriod=(-np.pi, np.pi), qTol=1e-7, doMultiProc=True, nCPUs=multiprocessing.cpu_count(), useGrid=None): """ wrapper for indexer.paintGrid """ del_ome = omeEta.omegas[1] - omeEta.omegas[0] del_eta = omeEta.etas[1] - omeEta.etas[0] # tolerances in degrees... I know, pathological if omeTol is None: omeTol = 360. / float(fiber_ndiv) if etaTol is None: etaTol = 360. / float(fiber_ndiv) # must be consistent pd_hkl_ids = omeEta.iHKLList[seed_hkl_ids] tTh = pd.getTTh() bMat = pd.latVecOps['B'] csym = pd.getLaueGroup() qsym = pd.getQSym() if useGrid is not None: try: print "loading quaternion grid file: %s" % (useGrid) qfib = np.loadtxt(useGrid).T except: raise RuntimeError, "unable to load quaternion grid file" else: structureNDI_label = ndimage.generate_binary_structure(2, 2) qfib = [] ii = 0 jj = fiber_ndiv print "labeling maps..." labels = [] numSpots = [] coms = [] for i in seed_hkl_ids: labels_t, numSpots_t = ndimage.label(omeEta.dataStore[i] > threshold, structureNDI_label) coms_t = np.atleast_2d(ndimage.center_of_mass(omeEta.dataStore[i], labels=labels_t, index=np.arange(1, np.amax(labels_t)+1))) labels.append(labels_t) numSpots.append(numSpots_t) coms.append(coms_t) pass # second pass for generation print "generating quaternions..." qfib_tmp = np.empty((4, fiber_ndiv*sum(numSpots))) for i in range(len(pd_hkl_ids)): for ispot in range(numSpots[i]): if not np.isnan(coms[i][ispot][0]): ome_c = omeEta.omeEdges[0] + (0.5 + coms[i][ispot][0])*del_ome eta_c = omeEta.etaEdges[0] + (0.5 + coms[i][ispot][1])*del_eta gVec_s = xrdutil.makeMeasuredScatteringVectors(tTh[pd_hkl_ids[i]], eta_c, ome_c) qfib_tmp[:, ii:jj] = rot.discreteFiber(pd.hkls[:, pd_hkl_ids[i]].reshape(3, 1), gVec_s, B=bMat, ndiv=fiber_ndiv, invert=False, csym=csym)[0] ii = jj jj += fiber_ndiv pass pass qfib.append(mutil.uniqueVectors(qfib_tmp)) pass qfib = np.hstack(qfib) print "Running paintGrid on %d orientations" % (qfib.shape[1]) complPG = idx.paintGrid(qfib, omeEta, omegaRange=omeRange, etaRange=etaRange, omeTol=d2r*omeTol, etaTol=d2r*etaTol, omePeriod=omePeriod, threshold=threshold, doMultiProc=doMultiProc, nCPUs=nCPUs) return complPG, qfib
npdiv=npdiv, threshold=cfg.fit_grains.threshold) print("INFO:\tusing direct seach") pool = multiprocessing.Pool(ncpus, test_orientation_FF_init, (params, )) completeness = pool.map(test_orientation_FF_reduced, qfib.T) pool.close() else: print("INFO:\tusing map search with paintGrid on %d processes" % ncpus) start = timeit.default_timer() completeness = indexer.paintGrid( qfib, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=on_map_threshold, doMultiProc=ncpus > 1, nCPUs=ncpus) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) completeness = np.array(completeness) # %% # ============================================================================= # CLUSTERING AND GRAINS OUTPUT # ============================================================================= if not os.path.exists(cfg.analysis_dir): os.makedirs(cfg.analysis_dir) qbar_filename = 'accepted_orientations_' + analysis_id + '.dat'
def find_orientations(cfg, hkls=None): """Takes a config dict as input, generally a yml document""" # a goofy call, could be replaced with two more targeted calls pd, reader, detector = initialize_experiment(cfg) logger.info("beginning analysis '%s'", cfg.analysis_name) # load the eta_ome orientation maps eta_ome = load_eta_ome_maps(cfg, pd, reader, detector, hkls) try: # are we searching the full grid of orientation space? qgrid_f = cfg.find_orientations.use_quaternion_grid quats = np.loadtxt(qgrid_f) logger.info("Using %s for full quaternian search", qgrid_f) except (IOError, ValueError): # or doing a seeded search? logger.info("Defaulting to seeded search") hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds hklseedstr = ', '.join( [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]] ) logger.info( "Seeding search using hkls from %s: %s", cfg.find_orientations.orientation_maps.file, hklseedstr ) quats = generate_orientation_fibers( eta_ome, cfg.find_orientations.threshold, cfg.find_orientations.seed_search.hkl_seeds, cfg.find_orientations.seed_search.fiber_ndiv ) np.savetxt( os.path.join(cfg.working_dir, 'trial_orientations.dat'), quats.T, fmt="%.18e", delimiter="\t" ) # generate the completion maps logger.info("Running paintgrid on %d trial orientations", (quats.shape[1])) ncpus = cfg.multiprocessing compl = idx.paintGrid( quats, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=cfg.find_orientations.threshold, doMultiProc=ncpus > 1, nCPUs=ncpus ) np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl) # cluster analysis to identify orientation blobs, the final output: qbar, cl = run_cluster(compl, quats, pd.getQSym(), cfg) np.savetxt( os.path.join(cfg.working_dir, 'accepted_orientations.dat'), qbar.T, fmt="%.18e", delimiter="\t" ) # do the peak extraction now? if cfg.find_orientations.extract_measured_g_vectors: raise ImplementationError('TODO: implement extract gvecs')
def find_orientations(cfg, hkls=None, clean=False, profile=False, nsim=100): print('ready to run find_orientations') # %% # ============================================================================= # SEARCH SPACE GENERATION # ============================================================================= hedm = cfg.instrument.hedm plane_data = cfg.material.plane_data ncpus = cfg.multiprocessing # for indexing active_hkls = cfg.find_orientations.orientation_maps.active_hkls fiber_ndiv = cfg.find_orientations.seed_search.fiber_ndiv fiber_seeds = cfg.find_orientations.seed_search.hkl_seeds on_map_threshold = cfg.find_orientations.threshold # for clustering cl_radius = cfg.find_orientations.clustering.radius min_compl = cfg.find_orientations.clustering.completeness compl_thresh = cfg.find_orientations.clustering.completeness eta_ome = get_eta_ome(cfg, clean=clean) print("INFO:\tgenerating search quaternion list using %d processes" % ncpus) start = timeit.default_timer() qfib = generate_orientation_fibers( eta_ome, hedm.chi, on_map_threshold, fiber_seeds, fiber_ndiv, ncpus=ncpus ) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) print("INFO: will test %d quaternions using %d processes" % (qfib.shape[1], ncpus)) # %% # ============================================================================= # ORIENTATION SCORING # ============================================================================= scoredq_filename = 'scored_orientations_' + analysis_id(cfg) + '.npz' print("INFO:\tusing map search with paintGrid on %d processes" % ncpus) start = timeit.default_timer() completeness = indexer.paintGrid( qfib, eta_ome, etaRange=np.radians(cfg.find_orientations.eta.range), omeTol=np.radians(cfg.find_orientations.omega.tolerance), etaTol=np.radians(cfg.find_orientations.eta.tolerance), omePeriod=np.radians(cfg.find_orientations.omega.period), threshold=on_map_threshold, doMultiProc=ncpus > 1, nCPUs=ncpus ) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) completeness = np.array(completeness) # export scored orientations np.savez_compressed(scoredq_filename, quaternions=qfib, completeness=completeness) print("INFO:\tsaved scored orientations to file: '%s'" % (scoredq_filename)) # %% # ============================================================================= # CLUSTERING AND GRAINS OUTPUT # ============================================================================= if not os.path.exists(cfg.analysis_dir): os.makedirs(cfg.analysis_dir) qbar_filename = 'accepted_orientations_' + analysis_id(cfg) + '.dat' print("INFO:\trunning clustering using '%s'" % cfg.find_orientations.clustering.algorithm ) start = timeit.default_timer() # Simulate N random grains to get neighborhood size print("INFO:\trunning %d simulations to determine neighborhood size" % nsim ) seed_hkl_ids = [ plane_data.hklDataList[active_hkls[i]]['hklID'] for i in fiber_seeds ] # need ome_ranges from imageseries # CAVEAT: assumes that all imageseries have same omega ranges!!! oims = OmegaImageSeries(cfg.image_series.itervalues().next()) ome_ranges = [ (np.radians([i['ostart'], i['ostop']])) for i in oims.omegawedges.wedges ] if seed_hkl_ids is not None: rand_q = mutil.unitVector(np.random.randn(4, nsim)) rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \ * mutil.unitVector(rand_q[1:, :]) refl_per_grain = np.zeros(nsim) num_seed_refls = np.zeros(nsim) grain_param_list = np.vstack([rand_e, np.zeros((3, nsim)), np.tile(cnst.identity_6x1, (nsim, 1)).T]).T sim_results = hedm.simulate_rotation_series( plane_data, grain_param_list, eta_ranges=np.radians(cfg.find_orientations.eta.range), ome_ranges=ome_ranges, ome_period=np.radians(cfg.find_orientations.omega.period) ) refl_per_grain = np.zeros(nsim) seed_refl_per_grain = np.zeros(nsim) for sim_result in sim_results.itervalues(): for i, refl_ids in enumerate(sim_result[0]): refl_per_grain[i] += len(refl_ids) seed_refl_per_grain[i] += np.sum([sum(refl_ids == hkl_id) for hkl_id in seed_hkl_ids]) min_samples = max( int(np.floor(0.5*cfg.find_orientations.clustering.completeness*min(seed_refl_per_grain))), 2 ) mean_rpg = int(np.round(np.average(refl_per_grain))) else: min_samples = 1 mean_rpg = 1 print("INFO:\tmean reflections per grain: %d" % mean_rpg) print("INFO:\tneighborhood size: %d" % min_samples) qbar, cl = run_cluster( completeness, qfib, plane_data.getQSym(), cfg, min_samples=min_samples, compl_thresh=compl_thresh, radius=cl_radius ) print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start)) print("INFO:\tfound %d grains; saved to file: '%s'" % (qbar.shape[1], qbar_filename)) np.savetxt(qbar_filename, qbar.T, fmt='%.18e', delimiter='\t') gw = instrument.GrainDataWriter(os.path.join(cfg.analysis_dir, 'grains.out')) grain_params_list = [] for gid, q in enumerate(qbar.T): phi = 2*np.arccos(q[0]) n = xfcapi.unitRowVector(q[1:]) grain_params = np.hstack([phi*n, cnst.zeros_3, cnst.identity_6x1]) gw.dump_grain(gid, 1., 0., grain_params) grain_params_list.append(grain_params) gw.close()