def test_ModelEvaluation(dials_regression, tmpdir): # thaumatin data_dir = os.path.join(dials_regression, "indexing_test_data", "i04_weak_data") pickle_path = os.path.join(data_dir, "full.pickle") sweep_path = os.path.join(data_dir, "experiments_import.json") input_reflections = flex.reflection_table.from_file(pickle_path) input_experiments = load.experiment_list(sweep_path, check_format=False) input_reflections = input_reflections.select( input_reflections["xyzobs.px.value"].parts()[2] < 100) input_reflections.centroid_px_to_mm(input_experiments[0].detector, scan=input_experiments[0].scan) input_reflections.map_centroids_to_reciprocal_space( input_experiments[0].detector, input_experiments[0].beam, goniometer=input_experiments[0].goniometer, ) input_reflections["imageset_id"] = flex.size_t(input_reflections.size(), 0) input_reflections["id"] = flex.int(input_reflections.size(), -1) refine_params = refine_phil.fetch().extract() evaluator = model_evaluation.ModelEvaluation( refinement_params=refine_params) experiments = copy.deepcopy(input_experiments) reflections = copy.deepcopy(input_reflections) experiments[0].crystal = Crystal.from_dict( dict([ ("__id__", "crystal"), ( "real_space_a", (20.007058080503633, 49.721143642677994, 16.636052132572846), ), ( "real_space_b", (-15.182202482876685, 24.93846318493148, -50.7116866438356), ), ( "real_space_c", (-135.23051191036296, 41.14539066294313, 55.41374425160883), ), ("space_group_hall_symbol", " P 1"), ])) assign_indices = AssignIndicesGlobal() assign_indices(reflections, experiments) result = evaluator.evaluate(experiments, reflections) assert result is not None assert result.n_indexed == 7313 assert result.fraction_indexed == pytest.approx(0.341155066244) assert result.rmsds == pytest.approx( (0.10215787570953785, 0.12954412140128563, 0.0010980583382102509))
def choose_best_orientation_matrix(self, candidate_orientation_matrices): from dials.algorithms.indexing import model_evaluation solution_scorer = self.params.basis_vector_combinations.solution_scorer if solution_scorer == "weighted": weighted_params = self.params.basis_vector_combinations.weighted solutions = model_evaluation.ModelRankWeighted( power=weighted_params.power, volume_weight=weighted_params.volume_weight, n_indexed_weight=weighted_params.n_indexed_weight, rmsd_weight=weighted_params.rmsd_weight, ) else: filter_params = self.params.basis_vector_combinations.filter solutions = model_evaluation.ModelRankFilter( check_doubled_cell=filter_params.check_doubled_cell, likelihood_cutoff=filter_params.likelihood_cutoff, volume_cutoff=filter_params.volume_cutoff, n_indexed_cutoff=filter_params.n_indexed_cutoff, ) args = [] for cm in candidate_orientation_matrices: sel = self.reflections["id"] == -1 if self.d_min is not None: sel &= 1 / self.reflections["rlp"].norms() > self.d_min xo, yo, zo = self.reflections["xyzobs.mm.value"].parts() imageset_id = self.reflections["imageset_id"] experiments = ExperimentList() for i_expt, expt in enumerate(self.experiments): # XXX Not sure if we still need this loop over self.experiments if expt.scan is not None: start, end = expt.scan.get_oscillation_range() if (end - start) > 360: # only use reflections from the first 360 degrees of the scan sel.set_selected( (imageset_id == i_expt) & (zo > ((start * math.pi / 180) + 2 * math.pi)), False, ) experiments.append( Experiment( imageset=expt.imageset, beam=expt.beam, detector=expt.detector, goniometer=expt.goniometer, scan=expt.scan, crystal=cm, ) ) refl = self.reflections.select(sel) self.index_reflections(experiments, refl) if refl.get_flags(refl.flags.indexed).count(True) == 0: continue from rstbx.dps_core.cell_assessment import SmallUnitCellVolume from dials.algorithms.indexing import non_primitive_basis threshold = self.params.basis_vector_combinations.sys_absent_threshold if threshold and ( self._symmetry_handler.target_symmetry_primitive is None or self._symmetry_handler.target_symmetry_primitive.unit_cell() is None ): try: non_primitive_basis.correct( experiments, refl, self._assign_indices, threshold ) if refl.get_flags(refl.flags.indexed).count(True) == 0: continue except SmallUnitCellVolume: logger.debug( "correct_non_primitive_basis SmallUnitCellVolume error for unit cell %s:", experiments[0].crystal.get_unit_cell(), ) continue except RuntimeError as e: if "Krivy-Gruber iteration limit exceeded" in str(e): logger.debug( "correct_non_primitive_basis Krivy-Gruber iteration limit exceeded error for unit cell %s:", experiments[0].crystal.get_unit_cell(), ) continue raise if ( experiments[0].crystal.get_unit_cell().volume() < self.params.min_cell_volume ): continue if self.params.known_symmetry.space_group is not None: new_crystal, _ = self._symmetry_handler.apply_symmetry( experiments[0].crystal ) if new_crystal is None: continue experiments[0].crystal.update(new_crystal) args.append((experiments, refl)) if len(args) == self.params.basis_vector_combinations.max_refine: break from libtbx import easy_mp evaluator = model_evaluation.ModelEvaluation(self.all_params) results = easy_mp.parallel_map( evaluator.evaluate, args, iterable_type=easy_mp.posiargs, processes=self.params.nproc, preserve_exception_message=True, ) for soln in results: if soln is None: continue solutions.append(soln) if len(solutions): logger.info("Candidate solutions:") logger.info(str(solutions)) best_model = solutions.best_model() logger.debug("best model_likelihood: %.2f", best_model.model_likelihood) logger.debug("best n_indexed: %i", best_model.n_indexed) self.hkl_offset = best_model.hkl_offset return best_model.crystal, best_model.n_indexed else: return None, None