def run(args):

    import libtbx.load_env

    usage = ("""\
%s observations.refl [options]""" % libtbx.env.dispatcher_name)
    from dials.util.options import OptionParser
    from dials.util.options import flatten_reflections
    from dials.util import Sorry

    parser = OptionParser(usage=usage,
                          phil=phil_scope,
                          read_reflections=True,
                          epilog=help_message)

    params, options = parser.parse_args(show_diff_phil=True)
    reflections = flatten_reflections(params.input.reflections)

    if len(reflections) != 1:
        parser.print_help()
        raise Sorry("Please provide a single file of reflections")

    refs = reflections[0]

    # raw periodograms
    ca = CentroidAnalyser(refs)
    results_r = ca(spans=None)

    # smoothed periodograms
    ca = CentroidAnalyser(refs)
    results_s = ca()

    if len(results_r) == 1:
        save_plots(params, results_r[0], results_s[0])
    else:
        for i, (r_r, r_s) in enumerate(zip(results_r, results_s)):
            suffix = "_exp_{0}".format(i)
            save_plots(params, r_r, r_s, suffix=suffix)
Esempio n. 2
0
    def get_centroid_analyser(self, debug=False):
        """Create a CentroidAnalysis object for the current reflections"""

        return CentroidAnalyser(self._reflections, debug=debug)
def test2():
    """Test on simulated data"""

    # Get models for reflection prediction
    import dials.test.algorithms.refinement.setup_geometry as setup_geometry

    from libtbx.phil import parse

    overrides = """geometry.parameters.crystal.a.length.value = 77
  geometry.parameters.crystal.b.length.value = 77
  geometry.parameters.crystal.c.length.value = 37"""

    master_phil = parse(
        """
      include scope dials.test.algorithms.refinement.geometry_phil
      """,
        process_includes=True,
    )

    from dxtbx.model import Crystal

    models = setup_geometry.Extract(master_phil)
    crystal = Crystal(
        real_space_a=(2.62783398111729, -63.387215823567125,
                      -45.751375737456975),
        real_space_b=(15.246640559660356, -44.48254330406616,
                      62.50501032727026),
        real_space_c=(-76.67246874451074, -11.01804131886244,
                      10.861322446352226),
        space_group_symbol="I 2 3",
    )
    detector = models.detector
    goniometer = models.goniometer
    beam = models.beam

    # Build a mock scan for a 180 degree sweep
    from dxtbx.model import ScanFactory

    sf = ScanFactory()
    scan = sf.make_scan(
        image_range=(1, 1800),
        exposure_times=0.1,
        oscillation=(0, 0.1),
        epochs=range(1800),
        deg=True,
    )

    # Build an experiment list
    from dxtbx.model.experiment_list import ExperimentList, Experiment

    experiments = ExperimentList()
    experiments.append(
        Experiment(
            beam=beam,
            detector=detector,
            goniometer=goniometer,
            scan=scan,
            crystal=crystal,
            imageset=None,
        ))

    # Generate all indices in a 1.5 Angstrom sphere
    from dials.algorithms.spot_prediction import IndexGenerator
    from cctbx.sgtbx import space_group, space_group_symbols

    resolution = 1.5
    index_generator = IndexGenerator(
        crystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(),
        resolution,
    )
    indices = index_generator.to_array()

    # Predict rays within the sweep range
    from dials.algorithms.refinement.prediction import ScansRayPredictor

    sweep_range = scan.get_oscillation_range(deg=False)
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    obs_refs = ray_predictor(indices)

    # Take only those rays that intersect the detector
    from dials.algorithms.spot_prediction import ray_intersection

    intersects = ray_intersection(detector, obs_refs)
    obs_refs = obs_refs.select(intersects)

    # Make a reflection predictor and re-predict for all these reflections. The
    # result is the same, but we gain also the flags and xyzcal.px columns
    from dials.algorithms.refinement.prediction import ExperimentsPredictor

    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs["id"] = flex.int(len(obs_refs), 0)
    obs_refs = ref_predictor(obs_refs)

    # Copy 'observed' centroids from the predicted ones, applying sinusoidal
    # offsets
    obs_x, obs_y, obs_z = obs_refs["xyzcal.mm"].parts()

    # obs_z is in range (0, pi). Calculate offsets for phi at twice that
    # frequency
    im_width = scan.get_oscillation(deg=False)[1]
    z_off = flex.sin(2 * obs_z) * im_width
    obs_z += z_off

    # Calculate offsets for x
    pixel_size = detector[0].get_pixel_size()
    x_off = flex.sin(20 * obs_z) * pixel_size[0]

    # Calculate offsets for y with a phase-shifted sine wave
    from math import pi

    y_off = flex.sin(4 * obs_z + pi / 6) * pixel_size[1]

    # Incorporate the offsets into the 'observed' centroids
    obs_z += z_off
    obs_x += x_off
    obs_y += y_off
    obs_refs["xyzobs.mm.value"] = flex.vec3_double(obs_x, obs_y, obs_z)

    # Now do centroid analysis of the residuals
    results = CentroidAnalyser(obs_refs, debug=True)()

    # FIXME this test shows that the suggested interval width heuristic is not
    # yet robust. This simulation function seems a useful direction to proceed
    # in though
    raise RuntimeError("test2 failed")

    print("OK")
    return
def test1():
    """Test centroid analysis on an indexed.pickle"""

    if not libtbx.env.has_module("dials_regression"):
        print("Skipping test1 in " + __file__ +
              " as dials_regression not present")
        return

    dials_regression = libtbx.env.find_in_repositories(
        relative_path="dials_regression", test=os.path.isdir)

    # Use dials_regression/indexing_test_data/i04_weak_data/indexed.pickle for
    # this test. This file is somewhat malformed, in that the observed and
    # calculated phi centroids are identical. We should not produce a phi
    # periodogram in that case
    data_dir = os.path.join(dials_regression, "indexing_test_data",
                            "i04_weak_data")
    pickle_path = os.path.join(data_dir, "indexed.pickle")

    # load the reflections and do analysis
    rt = flex.reflection_table.from_pickle(pickle_path)
    results = CentroidAnalyser(rt)()

    #### Check that results are as we expect ####

    # Only one experiment id
    assert len(results) == 1
    results = results[0]

    # Residuals per block
    assert results["nblocks"] == 80
    assert approx_equal(results["block_size"], 1.010557248)
    expected = [
        0.335558,
        0.335558,
        0.329863,
        0.331119,
        0.330501,
        0.331638,
        0.342241,
        0.326378,
        0.333448,
        0.336584,
        0.326387,
        0.331208,
        0.324562,
        0.333608,
        0.331141,
        0.325593,
        0.336456,
        0.333159,
        0.323751,
        0.340046,
        0.327231,
        0.321859,
        0.331268,
        0.331076,
        0.320894,
        0.323385,
        0.326196,
        0.320985,
        0.327399,
        0.324754,
        0.324914,
        0.329531,
        0.328205,
        0.330763,
        0.324561,
        0.32797,
        0.331537,
        0.32979,
        0.332977,
        0.334632,
        0.324989,
        0.32758,
        0.333216,
        0.339781,
        0.311982,
        0.327621,
        0.34168,
        0.322333,
        0.321525,
        0.3229,
        0.324373,
        0.329953,
        0.324727,
        0.320513,
        0.332656,
        0.319292,
        0.322898,
        0.316097,
        0.319094,
        0.33926,
        0.316256,
        0.335599,
        0.319271,
        0.321485,
        0.332974,
        0.31678,
        0.333504,
        0.323779,
        0.326404,
        0.334334,
        0.334769,
        0.329136,
        0.327918,
        0.334443,
        0.333598,
        0.316668,
        0.317806,
        0.319651,
        0.326678,
        0.326678,
    ]
    assert approx_equal(results["av_x_resid_per_block"], expected, eps=5.0e-6)
    expected = [
        0.140451,
        0.140451,
        0.134973,
        0.133594,
        0.138062,
        0.13792,
        0.142743,
        0.135466,
        0.139534,
        0.140333,
        0.136268,
        0.138599,
        0.142424,
        0.137319,
        0.139688,
        0.14409,
        0.140079,
        0.146143,
        0.135093,
        0.134561,
        0.141375,
        0.142994,
        0.143815,
        0.129358,
        0.151952,
        0.136534,
        0.137577,
        0.14513,
        0.136317,
        0.142892,
        0.138412,
        0.142925,
        0.131937,
        0.142954,
        0.144306,
        0.134972,
        0.143383,
        0.129731,
        0.139279,
        0.13215,
        0.137761,
        0.142486,
        0.135102,
        0.122229,
        0.155227,
        0.134371,
        0.129951,
        0.151823,
        0.130035,
        0.143184,
        0.143669,
        0.139766,
        0.143137,
        0.141744,
        0.134653,
        0.144242,
        0.14377,
        0.152644,
        0.140361,
        0.13361,
        0.137553,
        0.133924,
        0.149607,
        0.155575,
        0.149489,
        0.146792,
        0.14263,
        0.148653,
        0.139416,
        0.132103,
        0.131738,
        0.13657,
        0.144084,
        0.140233,
        0.137387,
        0.133706,
        0.138388,
        0.14073,
        0.138223,
        0.138223,
    ]
    assert approx_equal(results["av_y_resid_per_block"], expected, eps=5.0e-6)

    # For this data no interval widths have been suggested
    assert results["x_interval"] is None
    assert results["y_interval"] is None
    assert results["phi_interval"] is None

    # It isn't necessary to test the content of the periodograms here, as this is
    # tested in scitbx/math. However, do check that the phi periodogram has been
    # skipped whilst the others exist
    assert results["x_periodogram"] is not None
    assert results["y_periodogram"] is not None
    assert results["phi_periodogram"] is None

    print("OK")
    return
Esempio n. 5
0
    def get_centroid_analyser(self):
        """Create a CentroidAnalysis object for the current reflections"""

        return CentroidAnalyser(self._reflections)