Пример #1
0
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")
Пример #2
0
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
Пример #3
0
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()
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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
Пример #7
0
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'
Пример #9
0
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')
Пример #10
0
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()