Exemple #1
0
    def loop(self):
        id, grain_params = self._jobs.get(False)

        # skips the first loop if have_estimate is True
        have_estimate = not np.all(grain_params[-9] == [0,0,0,1,1,1,0,0,0])
        iterations = (have_estimate, len(self._p['eta_tol']))
        for iteration in range(*iterations):
            self.pull_spots(id, grain_params, iteration)
            grain_params, compl = self.fit_grains(id, grain_params)
            if compl == 0:
                break

        eMat = logm(np.linalg.inv(vecMVToSymm(grain_params[6:])))

        dFunc, dParams = self._p['distortion']
        resd = objFuncFitGrain(
            grain_params[gFlag], grain_params, gFlag,
            self._p['detector_params'],
            self._p['xyo_det'], self._p['hkls'],
            self._p['bMat'], self._p['wlen'],
            bVec_ref, eta_ref,
            dFunc, dParams,
            self._p['omega_period'],
            simOnly=False
            )

        self._results.append((id, grain_params, compl, eMat, sum(resd**2)))
        self._jobs.task_done()
Exemple #2
0
 def get_residuals(self, grain_params):
     return objFuncFitGrain(grain_params[gFlag_ref],
                            grain_params, gFlag_ref,
                            self._instr,
                            self._culled_results,
                            self._p['bmat'], self._p['wlen'],
                            self._p['omega_period'],
                            simOnly=False, return_value_flag=2)
Exemple #3
0
 def get_residuals(self, grain_params):
     dFunc, dParams = self._p['distortion']
     return objFuncFitGrain(
         grain_params[gFlag], grain_params, gFlag,
         self._p['detector_params'],
         self._p['xyo_det'], self._p['hkls'],
         self._p['bMat'], self._p['wlen'],
         bVec_ref, eta_ref,
         dFunc, dParams,
         self._p['omega_period'],
         simOnly=False, return_value_flag=2)
Exemple #4
0
 def get_residuals(self, grain_params):
     return objFuncFitGrain(grain_params[gFlag_ref],
                            grain_params,
                            gFlag_ref,
                            self._instr,
                            self._culled_results,
                            self._p['bmat'],
                            self._p['wlen'],
                            self._p['omega_period'],
                            simOnly=False,
                            return_value_flag=2)
Exemple #5
0
 def get_residuals(self, grain_params):
     dFunc, dParams = self._p['distortion']
     return objFuncFitGrain(grain_params[gFlag],
                            grain_params,
                            gFlag,
                            self._p['detector_params'],
                            self._p['xyo_det'],
                            self._p['hkls'],
                            self._p['bMat'],
                            self._p['wlen'],
                            bVec_ref,
                            eta_ref,
                            dFunc,
                            dParams,
                            self._p['omega_period'],
                            simOnly=False)
Exemple #6
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files

        REFLECTION TABLE

        Cols as follows:
            0:7    ID    PID    H    K    L    sum(int)    max(int)
            7:10   pred tth    pred eta    pred ome
            10:13  meas tth    meas eta    meas ome
            13:17  pred X    pred Y    meas X    meas Y
        """
        # !!! load resuts form spots
        spots_fname_dict = {}
        for det_key in self._instr.detectors.iterkeys():
            spots_fname_dict[det_key] = os.path.join(
                self._p['analysis_directory'],
                os.path.join(
                    det_key,
                    self._p['spots_stem'] % grain_id
                )
            )
        self._culled_results = dict.fromkeys(spots_fname_dict)
        num_refl_tot = 0
        num_refl_valid = 0
        for det_key in self._culled_results:
            panel = self._instr.detectors[det_key]

            presults = np.loadtxt(spots_fname_dict[det_key])

            valid_refl_ids = presults[:, 0] >= 0
            spot_ids = presults[:, 1]

            # find unsaturated spots on this panel
            if panel.saturation_level is None:
                unsat_spots = np.ones(len(valid_refl_ids))
            else:
                unsat_spots = presults[:, 6] < panel.saturation_level

            idx = np.logical_and(valid_refl_ids, unsat_spots)

            # if an overlap table has been written, load it and use it
            overlaps = np.zeros_like(idx, dtype=bool)
            try:
                ot = np.load(
                    os.path.join(
                        self._p['analysis_directory'],
                        'overlap_table.npz'
                    )
                )
                for key in ot.keys():
                    for this_table in ot[key]:
                        these_overlaps = np.where(
                            this_table[:, 0] == grain_id)[0]
                        if len(these_overlaps) > 0:
                            mark_these = np.array(
                                this_table[these_overlaps, 1], dtype=int
                            )
                            otidx = [
                                np.where(spot_ids == mt)[0]
                                for mt in mark_these
                            ]
                            overlaps[otidx] = True
                idx = np.logical_and(idx, ~overlaps)
                # logger.info("found overlap table for '%s'", det_key)
            except(IOError, IndexError):
                # logger.info("no overlap table found for '%s'", det_key)
                pass

            # attach to proper dict entry
            self._culled_results[det_key] = presults[idx, :]
            num_refl_tot += len(valid_refl_ids)
            num_refl_valid += sum(valid_refl_ids)
            pass  # now we have culled data

        # CAVEAT: completeness from pullspots only; incl saturated and overlaps
        # <JVB 2015-12-15>
        completeness = num_refl_valid / float(num_refl_tot)

        # ======= DO LEASTSQ FIT =======

        if num_refl_valid <= min_nrefl:  # exit if not enough refls to fit
            grain_params_fit = grain_params
            return grain_id, completeness, np.inf, grain_params_fit
        else:
            grain_params_fit = fitGrain(
                    grain_params, self._instr, self._culled_results,
                    self._p['bmat'], self._p['wlen']
                )
        # get chisq
        # TODO: do this while evaluating fit???
        chisq = objFuncFitGrain(
                grain_params_fit[gFlag_ref], grain_params_fit, gFlag_ref,
                self._instr,
                self._culled_results,
                self._p['bmat'], self._p['wlen'],
                self._p['omega_period'],
                simOnly=False, return_value_flag=2)

        if self._p['refit_tol'] is not None:
            # first get calculated x, y, ome from previous solution
            # NOTE: this result is a dict
            xyo_det_fit_dict = objFuncFitGrain(
                grain_params_fit[gFlag_ref], grain_params_fit, gFlag_ref,
                self._instr,
                self._culled_results,
                self._p['bmat'], self._p['wlen'],
                self._p['omega_period'],
                simOnly=True, return_value_flag=2)

            # make dict to contain new culled results
            culled_results_r = dict.fromkeys(self._culled_results)
            num_refl_valid = 0
            for det_key in culled_results_r:
                presults = self._culled_results[det_key]

                ims = self._imgsd[det_key]  # !!! must be OmegaImageSeries
                ome_step = sum(np.r_[-1, 1]*ims.metadata['omega'][0, :])

                # measured vals for pull spots
                xyo_det = presults[:, [15, 16, 12]]

                # previous solutions calc vals
                xyo_det_fit = xyo_det_fit_dict[det_key]

                xpix_tol = self._p['refit_tol'][0]*panel.pixel_size_col
                ypix_tol = self._p['refit_tol'][0]*panel.pixel_size_row
                fome_tol = self._p['refit_tol'][1]*ome_step

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit['calc_xy'][:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit['calc_xy'][:, 1])
                ome_diff = np.degrees(
                    xfcapi.angularDifference(xyo_det[:, 2],
                                             xyo_det_fit['calc_omes'])
                    )

                # filter out reflections with centroids more than
                # a pixel and delta omega away from predicted value
                idx_new = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol,
                                   ome_diff <= fome_tol)
                                   )

                # attach to proper dict entry
                culled_results_r[det_key] = presults[idx_new, :]
                num_refl_valid += sum(idx_new)
                pass

            # only execute fit if left with enough reflections
            if num_refl_valid > min_nrefl:
                grain_params_fit = fitGrain(
                    grain_params_fit, self._instr, culled_results_r,
                    self._p['bmat'], self._p['wlen'],
                )
                # get chisq
                # TODO: do this while evaluating fit???
                chisq = objFuncFitGrain(
                        grain_params_fit[gFlag_ref],
                        grain_params_fit, gFlag_ref,
                        self._instr,
                        culled_results_r,
                        self._p['bmat'], self._p['wlen'],
                        self._p['omega_period'],
                        simOnly=False, return_value_flag=2)
                pass  # close check on number of valid refls
            pass  # close refit conditional
        return grain_id, completeness, chisq, grain_params_fit
Exemple #7
0
def fit_grain_FF_reduced(grain_id):
    """
    input parameters are [
    plane_data, instrument, imgser_dict,
    tth_tol, eta_tol, ome_tol, npdiv, threshold
    ]
    """
    grains_table = paramMP['grains_table']
    plane_data = paramMP['plane_data']
    instrument = paramMP['instrument']
    imgser_dict = paramMP['imgser_dict']
    tth_tol = paramMP['tth_tol']
    eta_tol = paramMP['eta_tol']
    ome_tol = paramMP['ome_tol']
    npdiv = paramMP['npdiv']
    refit = paramMP['refit']
    threshold = paramMP['threshold']
    eta_ranges = paramMP['eta_ranges']
    ome_period = paramMP['ome_period']
    analysis_dirname = paramMP['analysis_dirname']
    spots_filename = paramMP['spots_filename']

    grain = grains_table[grain_id]
    grain_params = grain[3:15]

    complvec, results = instrument.pull_spots(plane_data,
                                              grain_params,
                                              imgser_dict,
                                              tth_tol=tth_tol[tol_loop_idx],
                                              eta_tol=eta_tol[tol_loop_idx],
                                              ome_tol=ome_tol[tol_loop_idx],
                                              npdiv=npdiv,
                                              threshold=threshold,
                                              eta_ranges=eta_ranges,
                                              ome_period=ome_period,
                                              dirname=analysis_dirname,
                                              filename=spots_filename %
                                              grain_id,
                                              save_spot_list=False,
                                              quiet=True,
                                              check_only=False,
                                              interp='nearest')

    # ======= DETERMINE VALID REFLECTIONS =======

    culled_results = dict.fromkeys(results)
    num_refl_tot = 0
    num_refl_valid = 0
    for det_key in culled_results:
        panel = instrument.detectors[det_key]

        presults = results[det_key]

        valid_refl_ids = np.array([x[0] for x in presults]) >= 0

        spot_ids = np.array([x[0] for x in presults])

        # find unsaturated spots on this panel
        if panel.saturation_level is None:
            unsat_spots = np.ones(len(valid_refl_ids))
        else:
            unsat_spots = \
                np.array([x[4] for x in presults]) < panel.saturation_level

        idx = np.logical_and(valid_refl_ids, unsat_spots)

        # if an overlap table has been written, load it and use it
        overlaps = np.zeros_like(idx, dtype=bool)
        try:
            ot = np.load(
                os.path.join(analysis_dirname,
                             os.path.join(det_key, 'overlap_table.npz')))
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(this_table[these_overlaps, 1],
                                              dtype=int)
                        otidx = [
                            np.where(spot_ids == mt)[0] for mt in mark_these
                        ]
                        overlaps[otidx] = True
            idx = np.logical_and(idx, ~overlaps)
            # print("found overlap table for '%s'" % det_key)
        except (IOError, IndexError):
            # print("no overlap table found for '%s'" % det_key)
            pass

        # attach to proper dict entry
        culled_results[det_key] = [presults[i] for i in np.where(idx)[0]]
        num_refl_tot += len(valid_refl_ids)
        num_refl_valid += sum(valid_refl_ids)

        pass  # now we have culled data

    # CAVEAT: completeness from pullspots only; incl saturated and overlaps
    # <JVB 2015-12-15>
    completeness = num_refl_valid / float(num_refl_tot)

    # ======= DO LEASTSQ FIT =======

    if num_refl_valid <= 12:  # not enough reflections to fit... exit
        grain_params_fit = grain_params
        return grain_id, completeness, np.inf, grain_params_fit
    else:
        grain_params_fit = fitGrain(grain_params, instrument, culled_results,
                                    plane_data.latVecOps['B'],
                                    plane_data.wavelength)
        # get chisq
        # TODO: do this while evaluating fit???
        chisq = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                grain_params_fit,
                                gFlag_ref,
                                instrument,
                                culled_results,
                                plane_data.latVecOps['B'],
                                plane_data.wavelength,
                                ome_period,
                                simOnly=False,
                                return_value_flag=2)

        if refit is not None:
            # first get calculated x, y, ome from previous solution
            # NOTE: this result is a dict
            xyo_det_fit_dict = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                               grain_params_fit,
                                               gFlag_ref,
                                               instrument,
                                               culled_results,
                                               plane_data.latVecOps['B'],
                                               plane_data.wavelength,
                                               ome_period,
                                               simOnly=True,
                                               return_value_flag=2)

            # make dict to contain new culled results
            culled_results_r = dict.fromkeys(culled_results)
            num_refl_valid = 0
            for det_key in culled_results_r:
                presults = culled_results[det_key]

                ims = imgser_dict[det_key]
                ome_step = sum(np.r_[-1, 1] * ims.metadata['omega'][0, :])

                xyo_det = np.atleast_2d(
                    np.vstack([np.r_[x[7], x[6][-1]] for x in presults]))

                xyo_det_fit = xyo_det_fit_dict[det_key]

                xpix_tol = refit[0] * panel.pixel_size_col
                ypix_tol = refit[0] * panel.pixel_size_row
                fome_tol = refit[1] * ome_step

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit['calc_xy'][:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit['calc_xy'][:, 1])
                ome_diff = np.degrees(
                    xfcapi.angularDifference(xyo_det[:, 2],
                                             xyo_det_fit['calc_omes']))

                # filter out reflections with centroids more than
                # a pixel and delta omega away from predicted value
                idx_new = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol, ome_diff <= fome_tol))

                # attach to proper dict entry
                culled_results_r[det_key] = [
                    presults[i] for i in np.where(idx_new)[0]
                ]

                num_refl_valid += sum(idx_new)
                pass

            # only execute fit if left with enough reflections
            if num_refl_valid > 24:
                grain_params_fit = fitGrain(grain_params_fit, instrument,
                                            culled_results_r,
                                            plane_data.latVecOps['B'],
                                            plane_data.wavelength)
                # get chisq
                # TODO: do this while evaluating fit???
                chisq = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                        grain_params_fit,
                                        gFlag_ref,
                                        instrument,
                                        culled_results_r,
                                        plane_data.latVecOps['B'],
                                        plane_data.wavelength,
                                        ome_period,
                                        simOnly=False,
                                        return_value_flag=2)
                pass
            pass  # close refit conditional

        return grain_id, completeness, chisq, grain_params_fit
Exemple #8
0
def fit_grain_FF_reduced(grain_id):
    """
    input parameters are [
    plane_data, instrument, imgser_dict,
    tth_tol, eta_tol, ome_tol, npdiv, threshold
    ]
    """
    grains_table = paramMP['grains_table']
    plane_data = paramMP['plane_data']
    instrument = paramMP['instrument']
    imgser_dict = paramMP['imgser_dict']
    tth_tol = paramMP['tth_tol']
    eta_tol = paramMP['eta_tol']
    ome_tol = paramMP['ome_tol']
    npdiv = paramMP['npdiv']
    threshold = paramMP['threshold']
    eta_ranges = paramMP['eta_ranges']
    ome_period = paramMP['ome_period']
    analysis_dirname = paramMP['analysis_dirname']
    spots_filename = paramMP['spots_filename']

    grain = grains_table[grain_id]
    grain_params = grain[3:15]

    complvec, results = instrument.pull_spots(
        plane_data, grain_params,
        imgser_dict,
        tth_tol=tth_tol[0], eta_tol=eta_tol[0], ome_tol=ome_tol[0],
        npdiv=npdiv, threshold=threshold,
        eta_ranges=eta_ranges,
        ome_period=ome_period,
        dirname=analysis_dirname, filename=spots_filename % grain_id,
        save_spot_list=False,
        quiet=True, lrank=1, check_only=False)

    # ======= DETERMINE VALID REFLECTIONS =======

    # CAVEAT: in the event of different stauration levels, can't mark saturated
    # spots in aggregated results <JVB 2017-03-26>
    culled_results = dict.fromkeys(results)
    num_refl_tot = 0
    num_refl_valid = 0
    for det_key in culled_results:
        presults = results[det_key]

        valid_refl_ids = np.array([x[0] for x in presults]) >= 0

        # FIXME: spot saturations will have to be handled differently
        unsat_spots = np.ones(len(valid_refl_ids))

        idx = np.logical_and(valid_refl_ids, unsat_spots)

        # TODO: wire in reflection overlap tables
        """
        # if an overlap table has been written, load it and use it
        overlaps = np.zeros(len(refl_table), dtype=bool)
        try:
            ot = np.load(self._p['overlap_table'])
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(
                        this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(
                            this_table[these_overlaps, 1], dtype=int
                        )
                        overlaps[mark_these] = True
            idx = np.logical_and(idx, ~overlaps)
        except IOError, IndexError:
            #print "no overlap table found"
            pass
        """

        # attach to proper dict entry
        culled_results[det_key] = [presults[i] for i in np.where(idx)[0]]
        num_refl_tot += len(valid_refl_ids)
        num_refl_valid += sum(valid_refl_ids)
        pass

    # CAVEAT: completeness from pullspots only; incl saturated and overlaps
    # <JVB 2015-12-15>
    completeness = num_refl_valid / float(num_refl_tot)

    # ======= DO LEASTSQ FIT =======

    if num_refl_valid <= 12:    # not enough reflections to fit... exit
        grain_params_fit = grain_params
        return grain_id, completeness, np.inf, grain_params_fit
    else:
        grain_params_fit = fitGrain(
                grain_params, instrument, culled_results,
                plane_data.latVecOps['B'], plane_data.wavelength
            )
        # get chisq
        # TODO: do this while evaluating fit???
        chisq = objFuncFitGrain(
                grain_params, grain_params, gFlag_ref,
                instrument,
                culled_results,
                plane_data.latVecOps['B'], plane_data.wavelength,
                ome_period,
                simOnly=False, return_value_flag=2)

        return grain_id, completeness, chisq, grain_params_fit
Exemple #9
0
class FitGrainsWorker(object):
    def __init__(self, jobs, results, reader, pkwargs, **kwargs):
        self._jobs = jobs
        self._results = results
        self._reader = reader
        # a dict containing the rest of the parameters
        self._p = pkwargs

        # lets make a couple shortcuts:
        self._p['bMat'] = np.ascontiguousarray(
            self._p['plane_data'].latVecOps['B']
        )  # is it still necessary to re-cast?
        self._p['wlen'] = self._p['plane_data'].wavelength
        self._pbar = kwargs.get('progressbar', None)

    def pull_spots(self, grain_id, grain_params, iteration):
        # need to calc panel dims on the fly
        xdim = self._p['pixel_pitch'][1] * self._p['ncols']
        ydim = self._p['pixel_pitch'][0] * self._p['nrows']
        panel_dims = [(-0.5 * xdim, -0.5 * ydim), (0.5 * xdim, 0.5 * ydim)]
        return pullSpots(
            self._p['plane_data'],
            self._p['detector_params'],
            grain_params,
            self._reader,
            distortion=self._p['distortion'],
            eta_range=self._p['eta_range'],
            ome_period=self._p['omega_period'],
            eta_tol=self._p['eta_tol'][iteration],
            ome_tol=self._p['omega_tol'][iteration],
            tth_tol=self._p['tth_tol'][iteration],
            pixel_pitch=self._p['pixel_pitch'],
            panel_dims=panel_dims,
            panel_buff=self._p['panel_buffer'],
            npdiv=self._p['npdiv'],
            threshold=self._p['threshold'],
            doClipping=False,
            filename=self._p['spots_stem'] % grain_id,
        )

    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop = self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2 * ome_step),
                    pred_ome > np.radians(ome_stop - 2 * ome_step))
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2 * ome_step),
                    pred_ome < np.radians(ome_stop - 2 * ome_step))
            idx = np.logical_and(valid_refl_ids,
                                 np.logical_and(unsat_spots, idx_ome))
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass  # end if edge case

        # if an overlap table has been written, load it and use it
        overlaps = np.zeros(len(refl_table), dtype=bool)
        try:
            ot = np.load(self._p['overlap_table'])
            for key in ot.keys():
                for this_table in ot[key]:
                    these_overlaps = np.where(this_table[:, 0] == grain_id)[0]
                    if len(these_overlaps) > 0:
                        mark_these = np.array(this_table[these_overlaps, 1],
                                              dtype=int)
                        overlaps[mark_these] = True
            idx = np.logical_and(idx, ~overlaps)
        except IOError, IndexError:
            #print "no overlap table found"
            pass

        # completeness from pullspots only; incl saturated and overlaps
        completeness = sum(valid_refl_ids) / float(len(valid_refl_ids))

        # extract data from grain table
        hkls = refl_table[idx, 2:5].T  # must be column vectors
        xyo_det = refl_table[idx,
                             -3:]  # these are the cartesian centroids + ome

        # set in parameter attribute
        self._p['hkls'] = hkls
        self._p['xyo_det'] = xyo_det

        if sum(idx) <= 12:  # not enough reflections to fit... exit
            completeness = 0.
        else:
            grain_params = fitGrain(xyo_det,
                                    hkls,
                                    self._p['bMat'],
                                    self._p['wlen'],
                                    self._p['detector_params'],
                                    grain_params[:3],
                                    grain_params[3:6],
                                    grain_params[6:],
                                    beamVec=bVec_ref,
                                    etaVec=eta_ref,
                                    distortion=self._p['distortion'],
                                    gFlag=gFlag,
                                    gScl=gScl,
                                    omePeriod=self._p['omega_period'])
            if refit_tol is not None:
                xpix_tol = refit_tol[0] * self._p['pixel_pitch'][1]
                ypix_tol = refit_tol[0] * self._p['pixel_pitch'][0]
                fome_tol = refit_tol[1] * self._p['omega_step']

                xyo_det_fit = objFuncFitGrain(grain_params[gFlag],
                                              grain_params,
                                              gFlag,
                                              self._p['detector_params'],
                                              xyo_det,
                                              hkls,
                                              self._p['bMat'],
                                              self._p['wlen'],
                                              bVec_ref,
                                              eta_ref,
                                              self._p['distortion'][0],
                                              self._p['distortion'][1],
                                              self._p['omega_period'],
                                              simOnly=True)

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit[:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit[:, 1])
                ome_diff = np.degrees(
                    angularDifference(xyo_det[:, 2], xyo_det_fit[:, 2]))

                # filter out reflections with centroids more than
                # a pixel and delta omega away from predicted value
                idx_1 = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol, ome_diff <= fome_tol))
                idx_new = np.zeros_like(idx, dtype=bool)
                idx_new[np.where(idx == 1)[0][idx_1]] = True

                if sum(idx_new) > 12 and (sum(idx_new) > 0.5 * sum(idx)):
                    # have enough reflections left
                    #   ** the check that we have more than half of what
                    #      we started with is a hueristic
                    hkls = refl_table[idx_new, 2:5].T
                    xyo_det = refl_table[idx_new, -3:]

                    # set in parameter attribute
                    self._p['hkls'] = hkls
                    self._p['xyo_det'] = xyo_det

                    # do fit
                    grain_params = fitGrain(xyo_det,
                                            hkls,
                                            self._p['bMat'],
                                            self._p['wlen'],
                                            self._p['detector_params'],
                                            grain_params[:3],
                                            grain_params[3:6],
                                            grain_params[6:],
                                            beamVec=bVec_ref,
                                            etaVec=eta_ref,
                                            distortion=self._p['distortion'],
                                            gFlag=gFlag,
                                            gScl=gScl,
                                            omePeriod=self._p['omega_period'])
                    pass  # end check on num of refit refls
                pass  # end refit loop
            pass  # end on num of refls
        return grain_params, completeness
Exemple #10
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files
        
        REFLECTION TABLE
        
        Cols as follows:
            0-6:   ID    PID    H    K    L    sum(int)    max(int)    
            6-9:   pred tth    pred eta    pred ome              
            9-12:  meas tth    meas eta    meas ome              
            12-15: meas X      meas Y      meas ome
        """
        ome_start = self._p['omega_start']
        ome_step = self._p['omega_step']
        ome_stop =  self._p['omega_stop']
        refl_table = np.loadtxt(self._p['spots_stem'] % grain_id)
        valid_refl_ids = refl_table[:, 0] >= 0
        unsat_spots = refl_table[:, 6] < self._p['saturation_level']
        pred_ome = refl_table[:, 9]
        if angularDifference(ome_start, ome_stop, units='degrees') > 0:
            # if here, incomplete have omega range and
            # clip the refelctions very close to the edges to avoid
            # problems with the least squares...
            if np.sign(ome_step) < 0:
                idx_ome = np.logical_and(
                    pred_ome < np.radians(ome_start + 2*ome_step),
                    pred_ome > np.radians(ome_stop - 2*ome_step)
                    )
            else:
                idx_ome = np.logical_and(
                    pred_ome > np.radians(ome_start + 2*ome_step),
                    pred_ome < np.radians(ome_stop - 2*ome_step)
                    )
            idx = np.logical_and(
                valid_refl_ids,
                np.logical_and(unsat_spots, idx_ome)
                )
        else:
            idx = np.logical_and(valid_refl_ids, unsat_spots)
            pass # end if edge case

        # completeness from pullspots only; incl saturated
        completeness = sum(valid_refl_ids)/float(len(valid_refl_ids))

        # extract data from grain table
        hkls = refl_table[idx, 2:5].T # must be column vectors
        xyo_det = refl_table[idx, -3:] # these are the cartesian centroids + ome

        # set in parameter attribute
        self._p['hkls'] = hkls
        self._p['xyo_det'] = xyo_det
        
        if sum(idx) <= 12: # not enough reflections to fit... exit
            completeness = 0.
        else:
            grain_params = fitGrain(
                xyo_det, hkls, self._p['bMat'], self._p['wlen'],
                self._p['detector_params'],
                grain_params[:3], grain_params[3:6], grain_params[6:],
                beamVec=bVec_ref, etaVec=eta_ref,
                distortion=self._p['distortion'],
                gFlag=gFlag, gScl=gScl,
                omePeriod=self._p['omega_period']
                )
            if refit_tol is not None:
                xpix_tol = refit_tol[0]*self._p['pixel_pitch'][1]
                ypix_tol = refit_tol[0]*self._p['pixel_pitch'][0]
                fome_tol = refit_tol[1]*self._p['omega_step']
                
                xyo_det_fit = objFuncFitGrain(
                    grain_params[gFlag], grain_params, gFlag,
                    self._p['detector_params'],
                    xyo_det, hkls, self._p['bMat'], self._p['wlen'],
                    bVec_ref, eta_ref,
                    self._p['distortion'][0], self._p['distortion'][1],
                    self._p['omega_period'], simOnly=True
                    )

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit[:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit[:, 1])
                ome_diff = np.degrees(
                    angularDifference(xyo_det[:, 2], xyo_det_fit[:, 2])
                    )

                # filter out reflections with centroids more than 
                # a pixel and delta omega away from predicted value
                idx_1 = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol,
                                   ome_diff <= fome_tol)
                                   )
                idx_new = np.zeros_like(idx, dtype=bool)
                idx_new[np.where(idx == 1)[0][idx_1]] = True

                if sum(idx_new) > 12 and (sum(idx_new) > 0.5*sum(idx)):
                    # have enough reflections left
                    #   ** the check that we have more than half of what
                    #      we started with is a hueristic
                    hkls = refl_table[idx_new, 2:5].T
                    xyo_det = refl_table[idx_new, -3:]

                    # set in parameter attribute
                    self._p['hkls'] = hkls
                    self._p['xyo_det'] = xyo_det

                    # do fit
                    grain_params = fitGrain(
                        xyo_det, hkls,
                        self._p['bMat'], self._p['wlen'],
                        self._p['detector_params'],
                        grain_params[:3], grain_params[3:6], grain_params[6:],
                        beamVec=bVec_ref, etaVec=eta_ref,
                        distortion=self._p['distortion'],
                        gFlag=gFlag, gScl=gScl,
                        omePeriod=self._p['omega_period']
                        )
                    pass # end check on num of refit refls
                pass # end refit loop
            pass # end on num of refls
        return grain_params, completeness
Exemple #11
0
    def fit_grains(self, grain_id, grain_params, refit_tol=None):
        """
        Executes lsq fits of grains based on spot files

        REFLECTION TABLE

        Cols as follows:
            0:7    ID    PID    H    K    L    sum(int)    max(int)
            7:10   pred tth    pred eta    pred ome
            10:13  meas tth    meas eta    meas ome
            13:17  pred X    pred Y    meas X    meas Y
        """
        # !!! load resuts form spots
        spots_fname_dict = {}
        for det_key in self._instr.detectors.iterkeys():
            spots_fname_dict[det_key] = os.path.join(
                self._p['analysis_directory'],
                os.path.join(det_key, self._p['spots_stem'] % grain_id))
        self._culled_results = dict.fromkeys(spots_fname_dict)
        num_refl_tot = 0
        num_refl_valid = 0
        for det_key in self._culled_results:
            panel = self._instr.detectors[det_key]

            presults = np.loadtxt(spots_fname_dict[det_key])

            valid_refl_ids = presults[:, 0] >= 0
            spot_ids = presults[:, 1]

            # find unsaturated spots on this panel
            if panel.saturation_level is None:
                unsat_spots = np.ones(len(valid_refl_ids))
            else:
                unsat_spots = presults[:, 6] < panel.saturation_level

            idx = np.logical_and(valid_refl_ids, unsat_spots)

            # if an overlap table has been written, load it and use it
            overlaps = np.zeros_like(idx, dtype=bool)
            try:
                ot = np.load(
                    os.path.join(self._p['analysis_directory'],
                                 'overlap_table.npz'))
                for key in ot.keys():
                    for this_table in ot[key]:
                        these_overlaps = np.where(this_table[:,
                                                             0] == grain_id)[0]
                        if len(these_overlaps) > 0:
                            mark_these = np.array(this_table[these_overlaps,
                                                             1],
                                                  dtype=int)
                            otidx = [
                                np.where(spot_ids == mt)[0]
                                for mt in mark_these
                            ]
                            overlaps[otidx] = True
                idx = np.logical_and(idx, ~overlaps)
                # logger.info("found overlap table for '%s'", det_key)
            except (IOError, IndexError):
                # logger.info("no overlap table found for '%s'", det_key)
                pass

            # attach to proper dict entry
            self._culled_results[det_key] = presults[idx, :]
            num_refl_tot += len(valid_refl_ids)
            num_refl_valid += sum(valid_refl_ids)
            pass  # now we have culled data

        # CAVEAT: completeness from pullspots only; incl saturated and overlaps
        # <JVB 2015-12-15>
        completeness = num_refl_valid / float(num_refl_tot)

        # ======= DO LEASTSQ FIT =======

        if num_refl_valid <= min_nrefl:  # exit if not enough refls to fit
            grain_params_fit = grain_params
            return grain_id, completeness, np.inf, grain_params_fit
        else:
            grain_params_fit = fitGrain(grain_params, self._instr,
                                        self._culled_results, self._p['bmat'],
                                        self._p['wlen'])
        # get chisq
        # TODO: do this while evaluating fit???
        chisq = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                grain_params_fit,
                                gFlag_ref,
                                self._instr,
                                self._culled_results,
                                self._p['bmat'],
                                self._p['wlen'],
                                self._p['omega_period'],
                                simOnly=False,
                                return_value_flag=2)

        if self._p['refit_tol'] is not None:
            # first get calculated x, y, ome from previous solution
            # NOTE: this result is a dict
            xyo_det_fit_dict = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                               grain_params_fit,
                                               gFlag_ref,
                                               self._instr,
                                               self._culled_results,
                                               self._p['bmat'],
                                               self._p['wlen'],
                                               self._p['omega_period'],
                                               simOnly=True,
                                               return_value_flag=2)

            # make dict to contain new culled results
            culled_results_r = dict.fromkeys(self._culled_results)
            num_refl_valid = 0
            for det_key in culled_results_r:
                presults = self._culled_results[det_key]

                ims = self._imgsd[det_key]  # !!! must be OmegaImageSeries
                ome_step = sum(np.r_[-1, 1] * ims.metadata['omega'][0, :])

                # measured vals for pull spots
                xyo_det = presults[:, [15, 16, 12]]

                # previous solutions calc vals
                xyo_det_fit = xyo_det_fit_dict[det_key]

                xpix_tol = self._p['refit_tol'][0] * panel.pixel_size_col
                ypix_tol = self._p['refit_tol'][0] * panel.pixel_size_row
                fome_tol = self._p['refit_tol'][1] * ome_step

                # define difference vectors for spot fits
                x_diff = abs(xyo_det[:, 0] - xyo_det_fit['calc_xy'][:, 0])
                y_diff = abs(xyo_det[:, 1] - xyo_det_fit['calc_xy'][:, 1])
                ome_diff = np.degrees(
                    xfcapi.angularDifference(xyo_det[:, 2],
                                             xyo_det_fit['calc_omes']))

                # filter out reflections with centroids more than
                # a pixel and delta omega away from predicted value
                idx_new = np.logical_and(
                    x_diff <= xpix_tol,
                    np.logical_and(y_diff <= ypix_tol, ome_diff <= fome_tol))

                # attach to proper dict entry
                culled_results_r[det_key] = presults[idx_new, :]
                num_refl_valid += sum(idx_new)
                pass

            # only execute fit if left with enough reflections
            if num_refl_valid > min_nrefl:
                grain_params_fit = fitGrain(
                    grain_params_fit,
                    self._instr,
                    culled_results_r,
                    self._p['bmat'],
                    self._p['wlen'],
                )
                # get chisq
                # TODO: do this while evaluating fit???
                chisq = objFuncFitGrain(grain_params_fit[gFlag_ref],
                                        grain_params_fit,
                                        gFlag_ref,
                                        self._instr,
                                        culled_results_r,
                                        self._p['bmat'],
                                        self._p['wlen'],
                                        self._p['omega_period'],
                                        simOnly=False,
                                        return_value_flag=2)
                pass  # close check on number of valid refls
            pass  # close refit conditional
        return grain_id, completeness, chisq, grain_params_fit
Exemple #12
0
                                           panel_buff=[10, 10],
                                           npdiv=2, threshold=threshold,
                                           use_closest=True, doClipping=False,
                                           filename=fid)
                    fid.close()
                pass
            else:
                g_refined = grain_params
                break
            pass
        eMat = logm(np.linalg.inv(mutil.vecMVToSymm(g_refined[6:])))

        resd_f2 = fitting.objFuncFitGrain(g_refined[gFlag], g_refined, gFlag,
                                          detector_params,
                                          xyo_det, hkls, bMat, wlen,
                                          bVec_ref, eta_ref,
                                          dFunc, dParams,
                                          ome_period,
                                          simOnly=False)
        print >> grains_file, \
          "%d\t%1.7e\t%1.7e\t"                         % (grainID, sum(idx)/float(len(idx)), sum(resd_f2**2)) + \
          "%1.7e\t%1.7e\t%1.7e\t"                      % tuple(g_refined[:3]) + \
          "%1.7e\t%1.7e\t%1.7e\t"                      % tuple(g_refined[3:6]) + \
          "%1.7e\t%1.7e\t%1.7e\t%1.7e\t%1.7e\t%1.7e\t" % tuple(g_refined[6:]) + \
          "%1.7e\t%1.7e\t%1.7e\t%1.7e\t%1.7e\t%1.7e"   % (eMat[0, 0], eMat[1, 1], eMat[2, 2], eMat[1, 2], eMat[0, 2], eMat[0, 1])
        elapsed = (time.clock() - start)
        print "grain %d took %.2f seconds" %(grainID, elapsed)
        pass
    grains_file.close()
    # return