Esempio n. 1
0
    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
Esempio n. 2
0
def test_ModelRank():
    results = [
        model_evaluation.Result(
            rmsds=(0.0269546226916153, 0.03159452239902618, 0.004208711548775884),
            fraction_indexed=0.9683976336148051,
            model_likelihood=0.95846970346759,
            n_indexed=19152,
            crystal=Crystal.from_dict(
                dict(
                    [
                        ("__id__", "crystal"),
                        (
                            "real_space_a",
                            (
                                -45.031874961773504,
                                -14.833784919966813,
                                -48.766092343826806,
                            ),
                        ),
                        (
                            "real_space_b",
                            (-32.15263553253188, 3.8725711269478085, 59.82290857456796),
                        ),
                        (
                            "real_space_c",
                            (29.6683003477066, 59.732569113301565, -13.880892871529552),
                        ),
                        ("space_group_hall_symbol", " P 1"),
                    ]
                )
            ),
            hkl_offset=None,
        ),
        model_evaluation.Result(
            rmsds=(0.0341397658828684, 0.027401396596305812, 0.00427723439147068),
            fraction_indexed=0.9849825554937554,
            model_likelihood=0.9562237490188447,
            n_indexed=19480,
            crystal=Crystal.from_dict(
                dict(
                    [
                        ("__id__", "crystal"),
                        (
                            "real_space_a",
                            (29.66830034770662, 59.73256911330157, -13.880892871529573),
                        ),
                        (
                            "real_space_b",
                            (47.516210146598816, -48.77135532028254, 2.824076640788394),
                        ),
                        (
                            "real_space_c",
                            (
                                -45.036407933560845,
                                -14.950807536025826,
                                -49.06808637024198,
                            ),
                        ),
                        ("space_group_hall_symbol", " P 1"),
                    ]
                )
            ),
            hkl_offset=None,
        ),
        model_evaluation.Result(
            rmsds=(0.30456791867888355, 0.15679214175133024, 0.009635577811258947),
            fraction_indexed=0.33629974212469027,
            model_likelihood=0.6574428619874397,
            n_indexed=6651,
            crystal=Crystal.from_dict(
                dict(
                    [
                        ("__id__", "crystal"),
                        (
                            "real_space_a",
                            (
                                -11.907050303571122,
                                34.85499418820148,
                                30.689745759790572,
                            ),
                        ),
                        (
                            "real_space_b",
                            (-56.943458237132, 19.90418665217566, -18.37834061045143),
                        ),
                        (
                            "real_space_c",
                            (-41.63267941211685, -24.82747139443437, 44.5508337593274),
                        ),
                        ("space_group_hall_symbol", " P 1"),
                    ]
                )
            ),
            hkl_offset=None,
        ),
    ]

    ranker = model_evaluation.ModelRankWeighted()
    ranker.extend(results)
    assert list(ranker.score_by_fraction_indexed()) == pytest.approx(
        [0.02449862002620243, 0.0, 1.550350501381241]
    )
    assert list(ranker.score_by_rmsd_xy()) == pytest.approx(
        [0.0, 0.07598423386955666, 3.044108569529155]
    )
    assert list(ranker.score_by_volume()) == pytest.approx(
        [0.44207271296753703, 0.45026641813391066, 0.0]
    )
    assert list(ranker.combined_scores()) == pytest.approx(
        [0.19602846593366663, 0.20851345109588518, 11.670183660213905]
    )
    assert (
        str(ranker)
        == """\
+-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------+
| unit_cell                           |   volume |   volume score |   #indexed |   % indexed |   % indexed score |   rmsd_xy |   rmsd_xy score |   overall score |
|-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------|
| 68.02 68.03 68.12 109.6 109.5 109.3 |   242890 |           0.44 |      19152 |          97 |              0.02 |      0.04 |            0    |            0.2  |
| 68.12 68.15 68.26 109.5 109.4 109.4 |   244274 |           0.45 |      19480 |          98 |              0    |      0.04 |            0.08 |            0.21 |
| 47.94 63.06 65.84 75.2 71.6 74.5    |   178786 |           0    |       6651 |          34 |              1.55 |      0.34 |            3.04 |           11.67 |
+-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------+"""
    )
    best = ranker.best_model()
    assert best.n_indexed == 19152

    ranker = model_evaluation.ModelRankFilter()
    ranker.extend(results)
    best = ranker.best_model()
    assert best.n_indexed == 19152
    assert (
        str(ranker)
        == """\
+-------------------------------------+----------+-------------+--------------------+--------------+
| unit_cell                           |   volume |   n_indexed |   fraction_indexed |   likelihood |
|-------------------------------------+----------+-------------+--------------------+--------------|
| 68.02 68.03 68.12 109.6 109.5 109.3 |   242890 |       19152 |                 97 |         0.96 |
| 68.12 68.15 68.26 109.5 109.4 109.4 |   244274 |       19480 |                 98 |         0.96 |
| 47.94 63.06 65.84 75.2 71.6 74.5    |   178786 |        6651 |                 34 |         0.66 |
+-------------------------------------+----------+-------------+--------------------+--------------+"""
    )