Exemple #1
0
def test_index_after_search(dials_data, run_in_tmpdir):
    """Integrate the beam centre search with the rest of the toolchain

    Do the following:
    1. Take a known good experiment and perturbate the beam centre
    2. Run dials.search_beam_centre on the perturbated beam centre and original
    reflection table, check for expected output;
    3. Run dials.index with the found beam centre and check that the expected
    unit cell is obtained and that the RMSDs are smaller than or equal to some
    expected values."""

    insulin = dials_data("insulin_processed")

    # load the original experiment and perturbate the beam centre by a small offset
    experiments = load.experiment_list(insulin / "imported.expt",
                                       check_format=False)
    original_origin = experiments[0].detector.hierarchy().get_origin()
    shifted_origin = (
        original_origin[0] - 1.3,
        original_origin[1] + 1.5,
        original_origin[2],
    )
    experiments[0].detector.hierarchy().set_local_frame(
        experiments[0].detector.hierarchy().get_fast_axis(),
        experiments[0].detector.hierarchy().get_slow_axis(),
        shifted_origin,
    )
    assert experiments[0].detector.hierarchy().get_origin() == shifted_origin
    experiments.as_file(run_in_tmpdir / "shifted.expt")

    # search the beam centre
    search_beam_position.run([
        run_in_tmpdir.join("shifted.expt").strpath,
        insulin.join("strong.refl").strpath,
    ])
    assert os.path.exists("optimised.expt")

    # check we can actually index the resulting optimized experiments
    expected_unit_cell = uctbx.unit_cell(
        (67.655, 67.622, 67.631, 109.4583, 109.4797, 109.485))
    expected_rmsds = (0.3, 0.3, 0.005)
    expected_hall_symbol = " P 1"
    run_indexing(
        insulin / "strong.refl",
        run_in_tmpdir / "optimised.expt",
        run_in_tmpdir,
        [],
        expected_unit_cell,
        expected_rmsds,
        expected_hall_symbol,
    )
Exemple #2
0
def test_run(dials_regression, tmpdir):
    expected_unit_cell = uctbx.unit_cell(
        (11.624, 13.550, 30.103, 89.964, 93.721, 90.132))
    expected_rmsds = (0.039, 0.035, 0.002)

    experiments_old = os.path.join(dials_regression, "indexing_test_data",
                                   "phi_scan", "datablock_old.json")
    experiments_new = os.path.join(dials_regression, "indexing_test_data",
                                   "phi_scan", "datablock.json")
    strong_pickle = os.path.join(dials_regression, "indexing_test_data",
                                 "phi_scan", "strong.pickle")

    from dxtbx.serialize import load

    imageset_old = load.experiment_list(experiments_old,
                                        check_format=False).imagesets()[0]
    imageset_new = load.experiment_list(experiments_new,
                                        check_format=False).imagesets()[0]

    gonio_old = imageset_old.get_goniometer()
    gonio_new = imageset_new.get_goniometer()

    assert gonio_old.get_rotation_axis() == pytest.approx(
        (0.7497646259807715, -0.5517923303436749, 0.36520984351713554))
    assert gonio_old.get_setting_rotation() == pytest.approx(
        (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0))
    assert gonio_old.get_fixed_rotation() == pytest.approx((
        0.7497646259807748,
        -0.20997265900532208,
        -0.6275065641872948,
        -0.5517923303436731,
        0.3250014637526764,
        -0.7680490041218182,
        0.3652098435171313,
        0.9221092836691605,
        0.12781329809272568,
    ))

    assert gonio_new.get_rotation_axis() == pytest.approx(
        gonio_old.get_rotation_axis())
    assert gonio_new.get_rotation_axis_datum() == pytest.approx((1, 0, 0))
    assert gonio_new.get_setting_rotation() == pytest.approx((
        0.7497646259807705,
        -0.20997265900532142,
        -0.6275065641873,
        -0.5517923303436786,
        0.3250014637526763,
        -0.768049004121814,
        0.3652098435171315,
        0.9221092836691607,
        0.12781329809272335,
    ))
    assert gonio_new.get_fixed_rotation() == pytest.approx(
        (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0))

    result_old = run_indexing(
        strong_pickle,
        experiments_old,
        tmpdir,
        extra_args=[],
        expected_unit_cell=expected_unit_cell,
        expected_rmsds=expected_rmsds,
        expected_hall_symbol=" P 1",
    )

    result_new = run_indexing(
        strong_pickle,
        experiments_new,
        tmpdir,
        extra_args=[],
        expected_unit_cell=expected_unit_cell,
        expected_rmsds=expected_rmsds,
        expected_hall_symbol=" P 1",
    )

    assert result_old.rmsds == pytest.approx(result_new.rmsds, abs=1e-6)
    assert result_old.experiments[0].crystal.get_unit_cell().parameters(
    ) == pytest.approx(
        result_new.experiments[0].crystal.get_unit_cell().parameters(),
        abs=1e-6)

    # Now test refinement gradients are correct
    from dxtbx.model.experiment_list import Experiment, ExperimentList

    old_exps = ExperimentList([
        Experiment(
            beam=imageset_old.get_beam(),
            detector=imageset_old.get_detector(),
            goniometer=gonio_old,
            scan=imageset_old.get_scan(),
            crystal=result_old.experiments[0].crystal,
            imageset=None,
        )
    ])
    new_exps = ExperimentList([
        Experiment(
            beam=imageset_new.get_beam(),
            detector=imageset_new.get_detector(),
            goniometer=gonio_new,
            scan=imageset_new.get_scan(),
            crystal=result_new.experiments[0].crystal,
            imageset=None,
        )
    ])

    from libtbx.phil import parse

    from dials.algorithms.refinement.refiner import phil_scope

    params = phil_scope.fetch(source=parse("")).extract()
    from dials.algorithms.refinement.refiner import RefinerFactory

    refiner_old = RefinerFactory.from_parameters_data_experiments(
        params, result_old.indexed_reflections, old_exps)
    refiner_new = RefinerFactory.from_parameters_data_experiments(
        params, result_new.indexed_reflections, new_exps)

    # Analytical gradients should be approximately the same in either case
    an_grads_old = refiner_old._pred_param.get_gradients(
        refiner_old.get_matches())
    an_grads_new = refiner_new._pred_param.get_gradients(
        refiner_new.get_matches())
    for g1, g2 in zip(an_grads_old, an_grads_new):
        assert g1["dX_dp"] == pytest.approx(g2["dX_dp"], abs=1.0e-6)
        assert g1["dY_dp"] == pytest.approx(g2["dY_dp"], abs=1.0e-6)
        assert g1["dphi_dp"] == pytest.approx(g2["dphi_dp"], abs=1.0e-6)

    # Analytical gradients should be approximately equal to finite difference
    # gradients in either case
    fd_grads_old = calc_fd_grads(refiner_old)
    for g1, g2 in zip(fd_grads_old, an_grads_old):
        assert g1["dX_dp"] == pytest.approx(g2["dX_dp"], abs=5.0e-6)
        assert g1["dY_dp"] == pytest.approx(g2["dY_dp"], abs=5.0e-6)
        assert g1["dphi_dp"] == pytest.approx(g2["dphi_dp"], abs=5.0e-6)
    fd_grads_new = calc_fd_grads(refiner_new)
    for g1, g2 in zip(fd_grads_new, an_grads_new):
        assert g1["dX_dp"] == pytest.approx(g2["dX_dp"], abs=5.0e-6)
        assert g1["dY_dp"] == pytest.approx(g2["dY_dp"], abs=5.0e-6)
        assert g1["dphi_dp"] == pytest.approx(g2["dphi_dp"], abs=5.0e-6)
def test_index_after_search(dials_data, tmpdir):
    """Integrate the beam centre search with the rest of the toolchain

    Do the following:
    1. Run dials.import with a specified beam centre, check for expected output;
    2. Run dials.find_spots, check for expected output;
    3. Run dials.search_beam_centre on the resultant datablock and pickled
    reflection table, check for expected output;
    4. Run dials.index, using the datablock from the beam centre search,
    and check that the expected unit ecll is obtained and that the RMSDs are
    smaller than or equal to some expected values."""

    dials_data = dials_data("thaumatin_i04").listdir(sort=True)
    g = [f.strpath for f in dials_data if f.ext == ".cbf"]

    # beam centre from image headers: 205.28,210.76 mm
    args = ["dials.import", "mosflm_beam_centre=207,212"] + g
    print(args)
    if os.name != "nt":
        result = procrunner.run(args, working_directory=tmpdir)
        assert not result.returncode and not result.stderr
    else:
        # Can't run this command on Windows,
        # as it will exceed the maximum Windows command length limits.
        # So, instead:
        import mock
        import sys

        with tmpdir.as_cwd():
            with mock.patch.object(sys, "argv", args):
                import dials.command_line.dials_import

                dials.command_line.dials_import.Script().run()
    assert tmpdir.join("imported.expt").check()

    # spot-finding, just need a subset of the data
    args = [
        "dials.find_spots",
        "imported.expt",
        "scan_range=1,10",
        "scan_range=531,540",
    ]
    print(args)
    result = procrunner.run(args, working_directory=tmpdir)
    assert not result.returncode and not result.stderr
    assert tmpdir.join("strong.refl").check()

    # actually run the beam centre search
    args = ["dials.search_beam_position", "imported.expt", "strong.refl"]
    print(args)
    result = procrunner.run(args, working_directory=tmpdir)
    assert not result.returncode and not result.stderr
    assert tmpdir.join("optimised.expt").check()

    # look at the results
    from dxtbx.serialize import load

    experiments = load.experiment_list(tmpdir.join("imported.expt").strpath,
                                       check_format=False)
    original_imageset = experiments.imagesets()[0]
    optimized_experiments = load.experiment_list(
        tmpdir.join("optimised.expt").strpath, check_format=False)
    detector_1 = original_imageset.get_detector()
    detector_2 = optimized_experiments.detectors()[0]
    shift = scitbx.matrix.col(detector_1[0].get_origin()) - scitbx.matrix.col(
        detector_2[0].get_origin())
    print(shift)

    # check we can actually index the resulting optimized experiments
    from cctbx import uctbx
    from dials.algorithms.indexing.test_index import run_indexing

    expected_unit_cell = uctbx.unit_cell(
        (57.780, 57.800, 150.017, 89.991, 89.990, 90.007))
    expected_rmsds = (0.06, 0.05, 0.001)
    expected_hall_symbol = " P 1"
    run_indexing(
        "strong.refl",
        "optimised.expt",
        tmpdir,
        [],
        expected_unit_cell,
        expected_rmsds,
        expected_hall_symbol,
    )