コード例 #1
0
def test_scan_varying_results_are_close_to_static_prediction_when_model_is_static(
        static_test,  # noqa: F811, not a redefinition
):
    """Test that various modes of scan-varying prediction produce results
    close to static prediction when the supplied models are indeed static"""

    # Get static predictor results

    scan = static_test.experiments[0].scan
    crystal = static_test.experiments[0].crystal
    beam = static_test.experiments[0].beam
    goniometer = static_test.experiments[0].goniometer
    n_scan_points = scan.get_num_images() + 1
    static_preds = static_test.predict_new()
    static_preds.sort("miller_index")

    # Set up scan-varying predictor
    from dials.algorithms.spot_prediction import ScanVaryingReflectionPredictor
    from dials.array_family import flex

    predict = ScanVaryingReflectionPredictor(static_test.experiments[0])

    def compare(refs1, refs2):
        assert len(refs1) == len(refs2)
        for r1, r2 in zip(refs1.rows(), refs2.rows()):
            assert r1["miller_index"] == r2["miller_index"]
            # differences less than one hundredth of a pixel/image
            for e1, e2 in zip(r1["xyzcal.px"], r2["xyzcal.px"]):
                assert e1 == pytest.approx(e2, abs=0.01)

    # Prediction for UB matrix expressed as array of static UB
    A = [crystal.get_A() for i in range(n_scan_points)]
    result1 = predict.for_ub(flex.mat3_double(A))
    result1.sort("miller_index")
    compare(static_preds, result1)

    # Prediction for UB matrix, s0 vectors and goniometer setting rotation
    # matrices expressed as arrays of static model states
    s0 = [beam.get_s0() for i in range(n_scan_points)]
    S = [goniometer.get_setting_rotation() for i in range(n_scan_points)]
    result2 = predict.for_varying_models(flex.mat3_double(A),
                                         flex.vec3_double(s0),
                                         flex.mat3_double(S))
    result2.sort("miller_index")
    compare(static_preds, result2)

    # First frame only, start and end UB
    _, _, z = static_preds["xyzcal.px"].parts()
    static_preds_frame0 = static_preds.select((z >= 0) & (z < 1))
    A = crystal.get_A()
    result3 = predict.for_ub_on_single_image(0, A, A)
    result3.sort("miller_index")
    compare(static_preds_frame0, result3)

    # First frame only, start and end UB, s0 and S
    s0 = beam.get_s0()
    S = goniometer.get_setting_rotation()
    result4 = predict.for_varying_models_on_single_image(0, A, A, s0, s0, S, S)
    result4.sort("miller_index")
    compare(static_preds_frame0, result4)
コード例 #2
0
ファイル: reflection_predictor.py プロジェクト: hattne/dials
    def __init__(
        self, experiment, dmin=None, dmax=None, margin=1, force_static=False, padding=0
    ):
        """
        Initialise a predictor for each experiment.

        :param experiment: The experiment to predict for
        :param dmin: The maximum resolution
        :param dmax: The minimum resolution
        :param margin: The margin of hkl to predict
        :param force_static: force scan varying prediction to be static

        """
        from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor
        from dials.algorithms.spot_prediction import ScanVaryingReflectionPredictor
        from dials.algorithms.spot_prediction import StillsReflectionPredictor
        from dxtbx.imageset import ImageSweep
        from dials.array_family import flex

        class Predictor(object):
            def __init__(self, name, func):
                self.name = name
                self.func = func

            def __call__(self):
                result = self.func()
                if dmax is not None:
                    assert dmax > 0
                    result.compute_d_single(experiment)
                    mask = result["d"] > dmax
                    result.del_selected(mask)
                return result

        # Check prediction to maximum resolution is possible
        wl = experiment.beam.get_wavelength()
        if dmin is not None and dmin < 0.5 * wl:
            raise Sorry(
                "Prediction at d_min of {0} is not possible "
                "with wavelength {1}".format(dmin, wl)
            )

        # Select the predictor class
        if isinstance(experiment.imageset, ImageSweep):
            xl_nsp = experiment.crystal.num_scan_points
            bm_nsp = experiment.beam.num_scan_points
            gn_nsp = experiment.goniometer.num_scan_points
            nim = experiment.scan.get_num_images()

            sv_compatible = (xl_nsp == nim + 1) or (bm_nsp == nim + 1)
            if not force_static and sv_compatible:
                predictor = ScanVaryingReflectionPredictor(
                    experiment, dmin=dmin, margin=margin, padding=padding
                )

                if bm_nsp == 0 and gn_nsp == 0:
                    # Only varying crystal
                    A = [
                        experiment.crystal.get_A_at_scan_point(i)
                        for i in range(experiment.crystal.num_scan_points)
                    ]
                    predict = Predictor(
                        "scan varying crystal prediction",
                        lambda: predictor.for_ub(flex.mat3_double(A)),
                    )

                else:
                    # Any allowed model may vary
                    if xl_nsp == nim + 1:
                        A = [
                            experiment.crystal.get_A_at_scan_point(i)
                            for i in range(experiment.crystal.num_scan_points)
                        ]
                    else:
                        A = [experiment.crystal.get_A() for i in range(nim + 1)]
                    if bm_nsp == nim + 1:
                        s0 = [
                            experiment.beam.get_s0_at_scan_point(i)
                            for i in range(experiment.beam.num_scan_points)
                        ]
                    else:
                        s0 = [experiment.beam.get_s0() for i in range(nim + 1)]
                    if gn_nsp == nim + 1:
                        S = [
                            experiment.goniometer.get_setting_rotation_at_scan_point(i)
                            for i in range(experiment.goniometer.num_scan_points)
                        ]
                    else:
                        S = [
                            experiment.goniometer.get_setting_rotation()
                            for i in range(nim + 1)
                        ]
                    predict = Predictor(
                        "scan varying model prediction",
                        lambda: predictor.for_varying_models(
                            flex.mat3_double(A),
                            flex.vec3_double(s0),
                            flex.mat3_double(S),
                        ),
                    )
            else:
                predictor = ScanStaticReflectionPredictor(
                    experiment, dmin=dmin, padding=padding
                )

                # Choose index generation method based on number of images
                # https://github.com/dials/dials/issues/585
                if experiment.scan.get_num_images() > 50:
                    predict_method = predictor.for_ub_old_index_generator
                else:
                    predict_method = predictor.for_ub

                predict = Predictor(
                    "scan static prediction",
                    lambda: predict_method(experiment.crystal.get_A()),
                )
        else:
            predictor = StillsReflectionPredictor(experiment, dmin=dmin)

            predict = Predictor(
                "stills prediction",
                lambda: predictor.for_ub(experiment.crystal.get_A()),
            )

        # Create and add the predictor class
        self._predict = predict