def generate_reflections(self):

    # Build a mock scan for a 3 degree sweep
    from dxtbx.model.scan import scan_factory
    sf = scan_factory()
    self.scan = sf.make_scan(image_range = (1,1),
                          exposure_times = 0.1,
                          oscillation = (0, 3.0),
                          epochs = range(1),
                          deg = True)
    sweep_range = self.scan.get_oscillation_range(deg=False)

    # Create a scans ExperimentList, only for generating reflections
    experiments = ExperimentList()
    experiments.append(Experiment(
          beam=self.beam, detector=self.detector, goniometer=self.gonio, scan=self.scan,
          crystal=self.crystal, imageset=None))

    # Create a ScansRayPredictor
    ray_predictor = ScansRayPredictor(experiments, sweep_range)

    # Generate rays - only to work out which hkls are predicted
    resolution = 2.0
    index_generator = IndexGenerator(self.crystal.get_unit_cell(),
                          space_group(space_group_symbols(1).hall()).type(),
                          resolution)
    indices = index_generator.to_array()
    rays = ray_predictor.predict(indices)

    # Make a standard reflection_table and copy in the ray data
    self.reflections = flex.reflection_table.empty_standard(len(rays))
    self.reflections.update(rays)

    return
def ref_gen_static(experiments):
  """Generate some reflections using the static predictor"""

  beam = experiments[0].beam
  crystal = experiments[0].crystal
  goniometer = experiments[0].goniometer
  detector = experiments[0].detector
  scan = experiments[0].scan

  # All indices to the detector max resolution
  dmin = detector.get_max_resolution(beam.get_s0())
  index_generator = IndexGenerator(crystal.get_unit_cell(),
                  space_group(space_group_symbols(1).hall()).type(), dmin)
  indices = index_generator.to_array()

  # Predict rays within the sweep range
  sweep_range = scan.get_oscillation_range(deg=False)
  ray_predictor = ScansRayPredictor(experiments, sweep_range)
  refs = ray_predictor.predict(indices)

  # Take only those rays that intersect the detector
  intersects = ray_intersection(detector, refs)
  refs = refs.select(intersects)

  # Make a reflection predictor and re-predict for these reflections. The
  # result is the same, but we gain also the flags and xyzcal.px columns
  ref_predictor = ExperimentsPredictor(experiments)
  refs['id'] = flex.int(len(refs), 0)
  refs = ref_predictor.predict(refs)

  return refs
def ref_gen_static(experiments):
    """Generate some reflections using the static predictor"""

    beam = experiments[0].beam
    crystal = experiments[0].crystal
    goniometer = experiments[0].goniometer
    detector = experiments[0].detector
    scan = experiments[0].scan

    # All indices to the detector max resolution
    dmin = detector.get_max_resolution(beam.get_s0())
    index_generator = IndexGenerator(
        crystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), dmin)
    indices = index_generator.to_array()

    # Predict rays within the sweep range
    sweep_range = scan.get_oscillation_range(deg=False)
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    refs = ray_predictor(indices)

    # Take only those rays that intersect the detector
    intersects = ray_intersection(detector, refs)
    refs = refs.select(intersects)

    # Make a reflection predictor and re-predict for these reflections. The
    # result is the same, but we gain also the flags and xyzcal.px columns
    ref_predictor = ExperimentsPredictor(experiments)
    refs['id'] = flex.int(len(refs), 0)
    refs = ref_predictor(refs)

    return refs
示例#4
0
    def generate_reflections(self):
        # Build a mock scan for a 3 degree sweep
        from dxtbx.model import ScanFactory
        sf = ScanFactory()
        self.scan = sf.make_scan(image_range=(1, 1),
                                 exposure_times=0.1,
                                 oscillation=(0, 3.0),
                                 epochs=range(1),
                                 deg=True)
        sweep_range = self.scan.get_oscillation_range(deg=False)

        # Create a scans ExperimentList, only for generating reflections
        experiments = ExperimentList()
        experiments.append(
            Experiment(beam=self.beam,
                       detector=self.detector,
                       goniometer=self.gonio,
                       scan=self.scan,
                       crystal=self.crystal,
                       imageset=None))

        # Create a ScansRayPredictor
        ray_predictor = ScansRayPredictor(experiments, sweep_range)

        # Generate rays - only to work out which hkls are predicted
        resolution = 2.0
        index_generator = IndexGenerator(
            self.crystal.get_unit_cell(),
            space_group(space_group_symbols(1).hall()).type(), resolution)
        indices = index_generator.to_array()
        rays = ray_predictor(indices)

        # Make a standard reflection_table and copy in the ray data
        self.reflections = flex.reflection_table.empty_standard(len(rays))
        self.reflections.update(rays)
def generate_reflections(experiments):

  from dials.algorithms.spot_prediction import IndexGenerator
  from dials.algorithms.refinement.prediction import \
    ScansRayPredictor, ExperimentsPredictor
  from dials.algorithms.spot_prediction import ray_intersection
  from cctbx.sgtbx import space_group, space_group_symbols
  from scitbx.array_family import flex

  detector = experiments[0].detector
  crystal = experiments[0].crystal

  # All indices in a 2.0 Angstrom sphere
  resolution = 2.0
  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
  scan = experiments[0].scan
  sweep_range = scan.get_oscillation_range(deg=False)
  ray_predictor = ScansRayPredictor(experiments, sweep_range)
  obs_refs = ray_predictor.predict(indices)

  # Take only those rays that intersect the detector
  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
  ref_predictor = ExperimentsPredictor(experiments)
  obs_refs['id'] = flex.int(len(obs_refs), 0)
  obs_refs = ref_predictor.predict(obs_refs)

  # Set 'observed' centroids from the predicted ones
  obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

  # Invent some variances for the centroid positions of the simulated data
  im_width = 0.1 * pi / 180.
  px_size = detector[0].get_pixel_size()
  var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
  var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
  var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
  obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

  return obs_refs, ref_predictor
def generate_reflections(experiments):

    from dials.algorithms.spot_prediction import IndexGenerator
    from dials.algorithms.refinement.prediction import \
      ScansRayPredictor, ExperimentsPredictor
    from dials.algorithms.spot_prediction import ray_intersection
    from cctbx.sgtbx import space_group, space_group_symbols
    from scitbx.array_family import flex

    detector = experiments[0].detector
    crystal = experiments[0].crystal

    # All indices in a 2.0 Angstrom sphere
    resolution = 2.0
    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
    scan = experiments[0].scan
    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
    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
    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs['id'] = flex.int(len(obs_refs), 0)
    obs_refs = ref_predictor(obs_refs)

    # Set 'observed' centroids from the predicted ones
    obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

    # Invent some variances for the centroid positions of the simulated data
    im_width = 0.1 * pi / 180.
    px_size = detector[0].get_pixel_size()
    var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
    obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

    return obs_refs, ref_predictor
    def generate_reflections(self):
        from cctbx.sgtbx import space_group, space_group_symbols
        from dials.algorithms.spot_prediction import IndexGenerator, ray_intersection
        sweep_range = self.scan.get_oscillation_range(deg=False)
        resolution = 2.0
        index_generator = IndexGenerator(
            self.crystal.get_unit_cell(),
            space_group(space_group_symbols(1).hall()).type(), resolution)
        indices = index_generator.to_array()

        # Predict rays within the sweep range
        ray_predictor = ScansRayPredictor(self.experiments, sweep_range)
        obs_refs = ray_predictor(indices)

        # Take only those rays that intersect the detector
        intersects = ray_intersection(self.detector, obs_refs)
        obs_refs = obs_refs.select(intersects)

        # Re-predict using the Experiments predictor for all these reflections. The
        # result is the same, but we gain also the flags and xyzcal.px columns
        obs_refs['id'] = flex.int(len(obs_refs), 0)
        obs_refs = self.ref_predictor(obs_refs)

        # Set 'observed' centroids from the predicted ones
        obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

        # Invent some variances for the centroid positions of the simulated data
        im_width = 0.1 * pi / 180.
        px_size = self.detector[0].get_pixel_size()
        var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
        var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
        var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
        obs_refs['xyzobs.mm.variance'] = flex.vec3_double(
            var_x, var_y, var_phi)

        # set the flex random seed to an 'uninteresting' number
        flex.set_random_seed(12407)

        # take 5 random reflections for speed
        reflections = obs_refs.select(flex.random_selection(len(obs_refs), 5))

        # use a BlockCalculator to calculate the blocks per image
        from dials.algorithms.refinement.reflection_manager import BlockCalculator
        block_calculator = BlockCalculator(self.experiments, reflections)
        reflections = block_calculator.per_image()

        return reflections
示例#8
0
def test(args=[]):
    # Python and cctbx imports
    from math import pi
    from scitbx import matrix
    from scitbx.array_family import flex
    from libtbx.phil import parse
    from libtbx.test_utils import approx_equal

    # Get module to build models using PHIL
    import dials.test.algorithms.refinement.setup_geometry as setup_geometry

    # We will set up a mock scan and a mock experiment list
    from dxtbx.model import ScanFactory
    from dxtbx.model.experiment_list import ExperimentList, Experiment

    # Model parameterisations
    from dials.algorithms.refinement.parameterisation.detector_parameters import \
        DetectorParameterisationSinglePanel
    from dials.algorithms.refinement.parameterisation.beam_parameters import \
        BeamParameterisation
    from dials.algorithms.refinement.parameterisation.crystal_parameters import \
        CrystalOrientationParameterisation, CrystalUnitCellParameterisation

    # Symmetry constrained parameterisation for the unit cell
    from cctbx.uctbx import unit_cell
    from rstbx.symmetry.constraints.parameter_reduction import \
        symmetrize_reduce_enlarge

    # Reflection prediction
    from dials.algorithms.spot_prediction import IndexGenerator
    from dials.algorithms.refinement.prediction import ScansRayPredictor, \
      ExperimentsPredictor
    from dials.algorithms.spot_prediction import ray_intersection
    from cctbx.sgtbx import space_group, space_group_symbols

    # Parameterisation of the prediction equation
    from dials.algorithms.refinement.parameterisation.prediction_parameters import \
        XYPhiPredictionParameterisation # implicit import

    # Imports for the target function
    from dials.algorithms.refinement.target import \
        LeastSquaresPositionalResidualWithRmsdCutoff # implicit import

    #############################
    # Setup experimental models #
    #############################

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

    models = setup_geometry.Extract(
        master_phil,
        cmdline_args=args,
        local_overrides="geometry.parameters.random_seed = 1")

    crystal1 = models.crystal

    models = setup_geometry.Extract(
        master_phil,
        cmdline_args=args,
        local_overrides="geometry.parameters.random_seed = 2")

    mydetector = models.detector
    mygonio = models.goniometer
    crystal2 = models.crystal
    mybeam = models.beam

    # Build a mock scan for a 180 degree sweep
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 1800),
                          exposure_times=0.1,
                          oscillation=(0, 0.1),
                          epochs=range(1800),
                          deg=True)
    sweep_range = myscan.get_oscillation_range(deg=False)
    im_width = myscan.get_oscillation(deg=False)[1]
    assert sweep_range == (0., pi)
    assert approx_equal(im_width, 0.1 * pi / 180.)

    # Build an experiment list
    experiments = ExperimentList()
    experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=crystal1,
                   imageset=None))
    experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=crystal2,
                   imageset=None))

    assert len(experiments.detectors()) == 1

    ##########################################################
    # Parameterise the models (only for perturbing geometry) #
    ##########################################################

    det_param = DetectorParameterisationSinglePanel(mydetector)
    s0_param = BeamParameterisation(mybeam, mygonio)
    xl1o_param = CrystalOrientationParameterisation(crystal1)
    xl1uc_param = CrystalUnitCellParameterisation(crystal1)
    xl2o_param = CrystalOrientationParameterisation(crystal2)
    xl2uc_param = CrystalUnitCellParameterisation(crystal2)

    # Fix beam to the X-Z plane (imgCIF geometry), fix wavelength
    s0_param.set_fixed([True, False, True])

    # Fix crystal parameters
    #xluc_param.set_fixed([True, True, True, True, True, True])

    ########################################################################
    # Link model parameterisations together into a parameterisation of the #
    # prediction equation                                                  #
    ########################################################################

    #pred_param = XYPhiPredictionParameterisation(experiments,
    #  [det_param], [s0_param], [xlo_param], [xluc_param])

    ################################
    # Apply known parameter shifts #
    ################################

    # shift detector by 1.0 mm each translation and 2 mrad each rotation
    det_p_vals = det_param.get_param_vals()
    p_vals = [a + b for a, b in zip(det_p_vals, [1.0, 1.0, 1.0, 2., 2., 2.])]
    det_param.set_param_vals(p_vals)

    # shift beam by 2 mrad in free axis
    s0_p_vals = s0_param.get_param_vals()
    p_vals = list(s0_p_vals)

    p_vals[0] += 2.
    s0_param.set_param_vals(p_vals)

    # rotate crystal a bit (=2 mrad each rotation)
    xlo_p_vals = []
    for xlo in (xl1o_param, xl2o_param):
        p_vals = xlo.get_param_vals()
        xlo_p_vals.append(p_vals)
        new_p_vals = [a + b for a, b in zip(p_vals, [2., 2., 2.])]
        xlo.set_param_vals(new_p_vals)

    # change unit cell a bit (=0.1 Angstrom length upsets, 0.1 degree of
    # gamma angle)
    xluc_p_vals = []
    for xluc, xl in ((xl1uc_param, crystal1), ((xl2uc_param, crystal2))):
        p_vals = xluc.get_param_vals()
        xluc_p_vals.append(p_vals)
        cell_params = xl.get_unit_cell().parameters()
        cell_params = [
            a + b for a, b in zip(cell_params, [0.1, 0.1, 0.1, 0.0, 0.0, 0.1])
        ]
        new_uc = unit_cell(cell_params)
        newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
        S = symmetrize_reduce_enlarge(xl.get_space_group())
        S.set_orientation(orientation=newB)
        X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
        xluc.set_param_vals(X)

    #############################
    # Generate some reflections #
    #############################

    #print "Reflections will be generated with the following geometry:"
    #print mybeam
    #print mydetector
    #print crystal1
    #print crystal2

    # All indices in a 2.0 Angstrom sphere for crystal1
    resolution = 2.0
    index_generator = IndexGenerator(
        crystal1.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices1 = index_generator.to_array()

    # All indices in a 2.0 Angstrom sphere for crystal2
    resolution = 2.0
    index_generator = IndexGenerator(
        crystal2.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices2 = index_generator.to_array()

    # Predict rays within the sweep range. Set experiment IDs
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    obs_refs1 = ray_predictor(indices1, experiment_id=0)
    obs_refs1['id'] = flex.int(len(obs_refs1), 0)
    obs_refs2 = ray_predictor(indices1, experiment_id=1)
    obs_refs2['id'] = flex.int(len(obs_refs2), 1)

    # Take only those rays that intersect the detector
    intersects = ray_intersection(mydetector, obs_refs1)
    obs_refs1 = obs_refs1.select(intersects)
    intersects = ray_intersection(mydetector, obs_refs2)
    obs_refs2 = obs_refs2.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
    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs1 = ref_predictor(obs_refs1)
    obs_refs2 = ref_predictor(obs_refs2)

    # Set 'observed' centroids from the predicted ones
    obs_refs1['xyzobs.mm.value'] = obs_refs1['xyzcal.mm']
    obs_refs2['xyzobs.mm.value'] = obs_refs2['xyzcal.mm']

    # Invent some variances for the centroid positions of the simulated data
    im_width = 0.1 * pi / 180.
    px_size = mydetector[0].get_pixel_size()
    var_x = flex.double(len(obs_refs1), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs1), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs1), (im_width / 2.)**2)
    obs_refs1['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)
    var_x = flex.double(len(obs_refs2), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs2), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs2), (im_width / 2.)**2)
    obs_refs2['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

    #print "Total number of reflections excited for crystal1", len(obs_refs1)
    #print "Total number of reflections excited for crystal2", len(obs_refs2)

    # concatenate reflection lists
    obs_refs1.extend(obs_refs2)
    obs_refs = obs_refs1

    ###############################
    # Undo known parameter shifts #
    ###############################

    s0_param.set_param_vals(s0_p_vals)
    det_param.set_param_vals(det_p_vals)
    xl1o_param.set_param_vals(xlo_p_vals[0])
    xl2o_param.set_param_vals(xlo_p_vals[1])
    xl1uc_param.set_param_vals(xluc_p_vals[0])
    xl2uc_param.set_param_vals(xluc_p_vals[1])

    #print "Initial values of parameters are"
    #msg = "Parameters: " + "%.5f " * len(pred_param)
    #print msg % tuple(pred_param.get_param_vals())
    #print

    # make a refiner
    from dials.algorithms.refinement.refiner import phil_scope
    params = phil_scope.fetch(source=parse('')).extract()

    # in case we want a plot
    params.refinement.refinery.journal.track_parameter_correlation = True

    # scan static first
    from dials.algorithms.refinement.refiner import RefinerFactory
    refiner = RefinerFactory.from_parameters_data_experiments(params,
                                                              obs_refs,
                                                              experiments,
                                                              verbosity=0)
    history = refiner.run()

    # scan varying
    params.refinement.parameterisation.scan_varying = True
    refiner = RefinerFactory.from_parameters_data_experiments(params,
                                                              obs_refs,
                                                              experiments,
                                                              verbosity=0)
    history = refiner.run()
def test():
    # Build models, with a larger crystal than default in order to get plenty of
    # reflections on the 'still' image
    overrides = """
  geometry.parameters.crystal.a.length.range=40 50;
  geometry.parameters.crystal.b.length.range=40 50;
  geometry.parameters.crystal.c.length.range=40 50;
  geometry.parameters.random_seed = 42"""

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

    models = Extract(master_phil, overrides)

    mydetector = models.detector
    mygonio = models.goniometer
    mycrystal = models.crystal
    mybeam = models.beam

    # Build a mock scan for a 3 degree sweep
    from dxtbx.model import ScanFactory
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 1),
                          exposure_times=0.1,
                          oscillation=(0, 3.0),
                          epochs=range(1),
                          deg=True)
    sweep_range = myscan.get_oscillation_range(deg=False)

    # Create parameterisations of these models
    det_param = DetectorParameterisationSinglePanel(mydetector)
    s0_param = BeamParameterisation(mybeam, mygonio)
    xlo_param = CrystalOrientationParameterisation(mycrystal)
    xluc_param = CrystalUnitCellParameterisation(mycrystal)

    # Create a scans ExperimentList, only for generating reflections
    experiments = ExperimentList()
    experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=mycrystal,
                   imageset=None))

    # Create a stills ExperimentList
    stills_experiments = ExperimentList()
    stills_experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   crystal=mycrystal,
                   imageset=None))

    # Generate rays - only to work out which hkls are predicted
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    resolution = 2.0
    index_generator = IndexGenerator(
        mycrystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()
    rays = ray_predictor(indices)

    # Make a standard reflection_table and copy in the ray data
    reflections = flex.reflection_table.empty_standard(len(rays))
    reflections.update(rays)

    # Build a standard prediction parameterisation for the stills experiment to do
    # FD calculation (not used for its analytical gradients)
    pred_param = StillsPredictionParameterisation(
        stills_experiments,
        detector_parameterisations=[det_param],
        beam_parameterisations=[s0_param],
        xl_orientation_parameterisations=[xlo_param],
        xl_unit_cell_parameterisations=[xluc_param])

    # Make a managed SphericalRelpStillsReflectionPredictor reflection predictor
    # for the first (only) experiment
    ref_predictor = Predictor(stills_experiments)

    # Predict these reflections in place. Must do this ahead of calculating
    # the analytical gradients so quantities like s1 are correct
    ref_predictor.update()
    ref_predictor.predict(reflections)

    # calculate analytical gradients
    ag = AnalyticalGradients(stills_experiments,
                             detector_parameterisation=det_param,
                             beam_parameterisation=s0_param,
                             xl_orientation_parameterisation=xlo_param,
                             xl_unit_cell_parameterisation=xluc_param)
    an_grads = ag.get_beam_gradients(reflections)
    an_grads.update(ag.get_crystal_orientation_gradients(reflections))
    an_grads.update(ag.get_crystal_unit_cell_gradients(reflections))

    # get finite difference gradients
    p_vals = pred_param.get_param_vals()
    deltas = [1.e-7] * len(p_vals)

    fd_grads = []
    p_names = pred_param.get_param_names()
    for i, delta in enumerate(deltas):

        # save parameter value
        val = p_vals[i]

        # calc reverse state
        p_vals[i] -= delta / 2.
        pred_param.set_param_vals(p_vals)

        ref_predictor.update()
        ref_predictor.predict(reflections)

        x, y, _ = reflections['xyzcal.mm'].deep_copy().parts()
        delpsi = reflections['delpsical.rad'].deep_copy()
        s1 = reflections['s1'].deep_copy()
        rev_state = s1

        # calc forward state
        p_vals[i] += delta
        pred_param.set_param_vals(p_vals)

        ref_predictor.update()
        ref_predictor.predict(reflections)

        x, y, _ = reflections['xyzcal.mm'].deep_copy().parts()
        delpsi = reflections['delpsical.rad'].deep_copy()
        s1 = reflections['s1'].deep_copy()
        fwd_state = s1

        # reset parameter to saved value
        p_vals[i] = val

        # finite difference - currently for s1 only
        fd = (fwd_state - rev_state)
        inv_delta = 1. / delta
        s1_grads = fd * inv_delta

        # store gradients
        fd_grads.append({'name': p_names[i], 'ds1': s1_grads})

    # return to the initial state
    pred_param.set_param_vals(p_vals)

    for i, fd_grad in enumerate(fd_grads):

        ## compare FD with analytical calculations
        print("\n\nParameter {0}: {1}".format(i, fd_grad['name']))

        print("d[s1]/dp for the first reflection")
        print('finite diff', fd_grad['ds1'][0])
        try:
            an_grad = an_grads[fd_grad['name']]
        except KeyError:
            continue

        print('checking analytical vs finite difference gradients for s1')
        for a, b in zip(fd_grad['ds1'], an_grad['ds1']):
            assert a == pytest.approx(b, abs=1e-7)
示例#10
0
def generate_reflections(experiments, xyzvar=(0.0, 0.0, 0.0)):
    """Generate synthetic reflection centroids using the supplied experiments,
    with normally-distributed errors applied the variances in xyzvar"""

    # check input
    if [e >= 0.0 for e in xyzvar].count(False) > 0:
        msg = "negative variance requested in " + str(xyzvar) + "!"
        raise RuntimeError(msg)

    refs = []
    for iexp, exp in enumerate(experiments):

        info("Generating reflections for experiment {0}".format(iexp))

        # All indices in a 1.5 Angstrom sphere
        resolution = 1.5
        index_generator = IndexGenerator(
            exp.crystal.get_unit_cell(),
            space_group(space_group_symbols(1).hall()).type(),
            resolution,
        )
        indices = index_generator.to_array()

        # Predict rays within the sweep range
        ray_predictor = ScansRayPredictor(
            experiments, exp.scan.get_oscillation_range(deg=False)
        )
        obs_refs = ray_predictor.predict(indices, experiment_id=iexp)

        info("Total number of reflections excited: {0}".format(len(obs_refs)))

        # Take only those rays that intersect the detector
        intersects = ray_intersection(exp.detector, obs_refs)
        obs_refs = obs_refs.select(intersects)
        obs_refs["id"] = flex.size_t(len(obs_refs), iexp)
        refs.append(obs_refs)

        info("Total number of impacts: {0}".format(len(obs_refs)))

    # Concatenate reflections
    obs_refs = reduce(lambda x, y: x.extend(y), refs)

    # 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
    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs = ref_predictor.predict(obs_refs)

    # calculate (uncorrelated) errors to offset the centroids
    # this is safe as elts of xyzvar are already tested to be > 0
    sigX, sigY, sigZ = [sqrt(e) for e in xyzvar]
    shift = [
        (random.gauss(0, sigX), random.gauss(0, sigY), random.gauss(0, sigZ))
        for _ in xrange(len(obs_refs))
    ]
    shift = flex.vec3_double(shift)

    # Set 'observed' centroids from the predicted ones
    obs_refs["xyzobs.mm.value"] = obs_refs["xyzcal.mm"] + shift

    # Store variances for the centroid positions of the simulated data. If errors
    # are zero, invent some variances
    if tuple(xyzvar) == (0.0, 0.0, 0.0):
        im_width = exp.scan.get_oscillation()[1] * pi / 180.0
        px_size = exp.detector[0].get_pixel_size()
        xyzvar = (
            (px_size[0] / 2.0) ** 2,
            (px_size[1] / 2.0) ** 2,
            (im_width / 2.0) ** 2,
        )
    var_x = flex.double(len(obs_refs), xyzvar[0])
    var_y = flex.double(len(obs_refs), xyzvar[1])
    var_phi = flex.double(len(obs_refs), xyzvar[2])
    obs_refs["xyzobs.mm.variance"] = flex.vec3_double(var_x, var_y, var_phi)
    info("Total number of observations made: {0}".format(len(obs_refs)))

    return obs_refs
  X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
  xluc_param.set_param_vals(X)

  #############################
  # Generate some reflections #
  #############################

  # All indices in a 2.0 Angstrom sphere
  resolution = 2.0
  index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                  space_group(space_group_symbols(1).hall()).type(), resolution)
  indices = index_generator.to_array()

  # for the reflection predictor, it doesn't matter which experiment list is
  # passed, as the detector is not used
  ref_predictor = ScansRayPredictor(experiments_single_panel, sweep_range)

  # get two sets of identical reflections
  obs_refs = ref_predictor.predict(indices)
  obs_refs2 = ref_predictor.predict(indices)
  for r1, r2 in zip(obs_refs, obs_refs2):
    assert r1['s1'] == r2['s1']

  # get the panel intersections
  sel = ray_intersection(single_panel_detector, obs_refs)
  obs_refs = obs_refs.select(sel)
  sel = ray_intersection(multi_panel_detector, obs_refs2)
  obs_refs2 = obs_refs2.select(sel)
  assert len(obs_refs) == len(obs_refs2)

  # Set 'observed' centroids from the predicted ones
示例#12
0
def test(args=[]):
  # Python and cctbx imports
  from math import pi
  import random
  from scitbx import matrix
  from scitbx.array_family import flex
  from libtbx.phil import parse
  from libtbx.test_utils import approx_equal

  # Experimental model builder
  from dials.test.algorithms.refinement.setup_geometry import Extract

  # We will set up a mock scan and a mock experiment list
  from dxtbx.model import ScanFactory
  from dxtbx.model.experiment_list import ExperimentList, Experiment

  # Model parameterisations
  from dials.algorithms.refinement.parameterisation.detector_parameters import \
      DetectorParameterisationSinglePanel
  from dials.algorithms.refinement.parameterisation.beam_parameters import \
      BeamParameterisation
  from dials.algorithms.refinement.parameterisation.crystal_parameters import \
      CrystalOrientationParameterisation, CrystalUnitCellParameterisation

  # Reflection prediction
  from dials.algorithms.spot_prediction import IndexGenerator, ray_intersection
  from dials.algorithms.refinement.prediction import ScansRayPredictor, \
    ExperimentsPredictor
  from cctbx.sgtbx import space_group, space_group_symbols

  # Parameterisation of the prediction equation
  from dials.algorithms.refinement.parameterisation.prediction_parameters import \
      XYPhiPredictionParameterisation

  # Imports for the target function
  from dials.algorithms.refinement.target import \
    LeastSquaresPositionalResidualWithRmsdCutoff
  from dials.algorithms.refinement.reflection_manager import ReflectionManager

  # Local functions
  def random_direction_close_to(vector, sd = 0.5):
    return vector.rotate_around_origin(matrix.col(
                (random.random(),
                 random.random(),
                 random.random())).normalize(),
                 random.gauss(0, sd),  deg = True)

  #############################
  # Setup experimental models #
  #############################

  # make a small cell to speed up calculations
  overrides = """geometry.parameters.crystal.a.length.range = 10 15
  geometry.parameters.crystal.b.length.range = 10 15
  geometry.parameters.crystal.c.length.range = 10 15"""

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

  models = Extract(master_phil, overrides, cmdline_args = args)

  mydetector = models.detector
  mygonio = models.goniometer
  mycrystal = models.crystal
  mybeam = models.beam

  # Build a mock scan for a 180 degree sweep of 0.1 degree images
  sf = ScanFactory()
  myscan = sf.make_scan(image_range = (1,1800),
                        exposure_times = 0.1,
                        oscillation = (0, 0.1),
                        epochs = range(1800),
                        deg = True)
  sweep_range = myscan.get_oscillation_range(deg=False)
  im_width = myscan.get_oscillation(deg=False)[1]
  assert sweep_range == (0., pi)
  assert approx_equal(im_width, 0.1 * pi / 180.)

  experiments = ExperimentList()
  experiments.append(Experiment(
        beam=mybeam, detector=mydetector, goniometer=mygonio,
        scan=myscan, crystal=mycrystal, imageset=None))

  ###########################
  # Parameterise the models #
  ###########################

  det_param = DetectorParameterisationSinglePanel(mydetector)
  s0_param = BeamParameterisation(mybeam, mygonio)
  xlo_param = CrystalOrientationParameterisation(mycrystal)
  xluc_param = CrystalUnitCellParameterisation(mycrystal)

  ########################################################################
  # Link model parameterisations together into a parameterisation of the #
  # prediction equation                                                  #
  ########################################################################

  pred_param = XYPhiPredictionParameterisation(experiments,
      [det_param], [s0_param], [xlo_param], [xluc_param])

  ################################
  # Apply known parameter shifts #
  ################################

  # shift detector by 0.2 mm each translation and 2 mrad each rotation
  det_p_vals = det_param.get_param_vals()
  p_vals = [a + b for a, b in zip(det_p_vals,
                                   [2.0, 2.0, 2.0, 2.0, 2.0, 2.0])]
  det_param.set_param_vals(p_vals)

  # shift beam by 2 mrad in one axis
  s0_p_vals = s0_param.get_param_vals()
  p_vals = list(s0_p_vals)
  p_vals[1] += 2.0
  s0_param.set_param_vals(p_vals)

  # rotate crystal a bit (=2 mrad each rotation)
  xlo_p_vals = xlo_param.get_param_vals()
  p_vals = [a + b for a, b in zip(xlo_p_vals, [2.0, 2.0, 2.0])]
  xlo_param.set_param_vals(p_vals)

  #############################
  # Generate some reflections #
  #############################

  # All indices in a 2.0 Angstrom sphere
  resolution = 2.0
  index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                  space_group(space_group_symbols(1).hall()).type(), resolution)
  indices = index_generator.to_array()

  # Predict rays within the sweep range
  ray_predictor = ScansRayPredictor(experiments, sweep_range)
  obs_refs = ray_predictor(indices)

  # Take only those rays that intersect the detector
  intersects = ray_intersection(mydetector, 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
  ref_predictor = ExperimentsPredictor(experiments)
  obs_refs['id'] = flex.int(len(obs_refs), 0)
  obs_refs = ref_predictor(obs_refs)

  # Set 'observed' centroids from the predicted ones
  obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

  # Invent some variances for the centroid positions of the simulated data
  im_width = 0.1 * pi / 180.
  px_size = mydetector[0].get_pixel_size()
  var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
  var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
  var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
  obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

  ###############################
  # Undo known parameter shifts #
  ###############################

  s0_param.set_param_vals(s0_p_vals)
  det_param.set_param_vals(det_p_vals)
  xlo_param.set_param_vals(xlo_p_vals)

  #####################################
  # Select reflections for refinement #
  #####################################

  refman = ReflectionManager(obs_refs, experiments)

  ##############################
  # Set up the target function #
  ##############################

  # Redefine the reflection predictor to use the type expected by the Target class
  ref_predictor = ExperimentsPredictor(experiments)

  mytarget = LeastSquaresPositionalResidualWithRmsdCutoff(
      experiments, ref_predictor, refman, pred_param,
      restraints_parameterisation=None)

  # get the functional and gradients
  mytarget.predict()
  L, dL_dp, curvs = mytarget.compute_functional_gradients_and_curvatures()

  ####################################
  # Do FD calculation for comparison #
  ####################################

  # function for calculating finite difference gradients of the target function
  def get_fd_gradients(target, pred_param, deltas):
    """Calculate centered finite difference gradients for each of the
    parameters of the target function.

    "deltas" must be a sequence of the same length as the parameter list, and
    contains the step size for the difference calculations for each parameter.
    """

    p_vals = pred_param.get_param_vals()
    assert len(deltas) == len(p_vals)
    fd_grad = []
    fd_curvs = []

    for i in range(len(deltas)):
      val = p_vals[i]

      p_vals[i] -= deltas[i] / 2.
      pred_param.set_param_vals(p_vals)
      target.predict()

      rev_state = target.compute_functional_gradients_and_curvatures()

      p_vals[i] += deltas[i]
      pred_param.set_param_vals(p_vals)

      target.predict()

      fwd_state = target.compute_functional_gradients_and_curvatures()

      # finite difference estimation of first derivatives
      fd_grad.append((fwd_state[0] - rev_state[0]) / deltas[i])

      # finite difference estimation of curvatures, using the analytical
      # first derivatives
      fd_curvs.append((fwd_state[1][i] - rev_state[1][i]) / deltas[i])

      # set parameter back to centred value
      p_vals[i] = val

    # return to the initial state
    pred_param.set_param_vals(p_vals)

    return fd_grad, fd_curvs

  # test normalised differences between FD and analytical calculations
  fdgrads = get_fd_gradients(mytarget, pred_param, [1.e-7] * len(pred_param))
  diffs = [a - b for a, b in zip(dL_dp, fdgrads[0])]
  norm_diffs = tuple([a / b for a, b in zip(diffs, fdgrads[0])])
  for e in norm_diffs: assert abs(e) < 0.001 # check differences less than 0.1%

  # test normalised differences between FD curvatures and analytical least
  # squares approximation. We don't expect this to be especially close
  if curvs:
    diffs = [a - b for a, b in zip(curvs, fdgrads[1])]
    norm_diffs = tuple([a / b for a, b in zip(diffs, fdgrads[1])])
    for e in norm_diffs: assert abs(e) < 0.1 # check differences less than 10%
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 test(args=[]):
    #############################
    # Setup experimental models #
    #############################
    master_phil = parse("""
      include scope dials.test.algorithms.refinement.geometry_phil
      include scope dials.test.algorithms.refinement.minimiser_phil
      """,
                        process_includes=True)

    models = setup_geometry.Extract(master_phil, cmdline_args=args)

    single_panel_detector = models.detector
    mygonio = models.goniometer
    mycrystal = models.crystal
    mybeam = models.beam

    # Make a 3x3 multi panel detector filling the same space as the existing
    # single panel detector. Each panel of the multi-panel detector has pixels with
    # 1/3 the length dimensions of the single panel.

    multi_panel_detector = Detector()
    for x in range(3):
        for y in range(3):
            new_panel = make_panel_in_array((x, y), single_panel_detector[0])
            multi_panel_detector.add_panel(new_panel)

    # Build a mock scan for a 180 degree sweep
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 1800),
                          exposure_times=0.1,
                          oscillation=(0, 0.1),
                          epochs=range(1800),
                          deg=True)
    sweep_range = myscan.get_oscillation_range(deg=False)
    im_width = myscan.get_oscillation(deg=False)[1]
    assert sweep_range == (0., pi)
    assert approx_equal(im_width, 0.1 * pi / 180.)

    # Build ExperimentLists
    experiments_single_panel = ExperimentList()
    experiments_multi_panel = ExperimentList()
    experiments_single_panel.append(
        Experiment(beam=mybeam,
                   detector=single_panel_detector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=mycrystal,
                   imageset=None))
    experiments_multi_panel.append(
        Experiment(beam=mybeam,
                   detector=multi_panel_detector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=mycrystal,
                   imageset=None))

    ###########################
    # Parameterise the models #
    ###########################

    det_param = DetectorParameterisationSinglePanel(single_panel_detector)
    s0_param = BeamParameterisation(mybeam, mygonio)
    xlo_param = CrystalOrientationParameterisation(mycrystal)
    xluc_param = CrystalUnitCellParameterisation(mycrystal)

    multi_det_param = DetectorParameterisationMultiPanel(
        multi_panel_detector, mybeam)

    # Fix beam to the X-Z plane (imgCIF geometry), fix wavelength
    s0_param.set_fixed([True, False, True])

    # Fix crystal parameters
    #xluc_param.set_fixed([True, True, True, True, True, True])

    ########################################################################
    # Link model parameterisations together into a parameterisation of the #
    # prediction equation                                                  #
    ########################################################################

    pred_param = XYPhiPredictionParameterisation(experiments_single_panel,
                                                 [det_param], [s0_param],
                                                 [xlo_param], [xluc_param])

    pred_param2 = XYPhiPredictionParameterisation(experiments_multi_panel,
                                                  [multi_det_param],
                                                  [s0_param], [xlo_param],
                                                  [xluc_param])

    ################################
    # Apply known parameter shifts #
    ################################

    # shift detectors by 1.0 mm each translation and 2 mrad each rotation
    det_p_vals = det_param.get_param_vals()
    p_vals = [a + b for a, b in zip(det_p_vals, [1.0, 1.0, 1.0, 2., 2., 2.])]
    det_param.set_param_vals(p_vals)

    multi_det_p_vals = multi_det_param.get_param_vals()
    p_vals = [
        a + b for a, b in zip(multi_det_p_vals, [1.0, 1.0, 1.0, 2., 2., 2.])
    ]
    multi_det_param.set_param_vals(p_vals)

    # shift beam by 2 mrad in free axis
    s0_p_vals = s0_param.get_param_vals()
    p_vals = list(s0_p_vals)

    p_vals[0] += 2.
    s0_param.set_param_vals(p_vals)

    # rotate crystal a bit (=2 mrad each rotation)
    xlo_p_vals = xlo_param.get_param_vals()
    p_vals = [a + b for a, b in zip(xlo_p_vals, [2., 2., 2.])]
    xlo_param.set_param_vals(p_vals)

    # change unit cell a bit (=0.1 Angstrom length upsets, 0.1 degree of
    # gamma angle)
    xluc_p_vals = xluc_param.get_param_vals()
    cell_params = mycrystal.get_unit_cell().parameters()
    cell_params = [
        a + b for a, b in zip(cell_params, [0.1, 0.1, 0.1, 0.0, 0.0, 0.1])
    ]
    new_uc = unit_cell(cell_params)
    newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
    S = symmetrize_reduce_enlarge(mycrystal.get_space_group())
    S.set_orientation(orientation=newB)
    X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
    xluc_param.set_param_vals(X)

    #############################
    # Generate some reflections #
    #############################

    # All indices in a 2.0 Angstrom sphere
    resolution = 2.0
    index_generator = IndexGenerator(
        mycrystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()

    # for the reflection predictor, it doesn't matter which experiment list is
    # passed, as the detector is not used
    ref_predictor = ScansRayPredictor(experiments_single_panel, sweep_range)

    # get two sets of identical reflections
    obs_refs = ref_predictor(indices)
    obs_refs2 = ref_predictor(indices)
    for r1, r2 in zip(obs_refs, obs_refs2):
        assert r1['s1'] == r2['s1']

    # get the panel intersections
    sel = ray_intersection(single_panel_detector, obs_refs)
    obs_refs = obs_refs.select(sel)
    sel = ray_intersection(multi_panel_detector, obs_refs2)
    obs_refs2 = obs_refs2.select(sel)
    assert len(obs_refs) == len(obs_refs2)

    # Set 'observed' centroids from the predicted ones
    obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']
    obs_refs2['xyzobs.mm.value'] = obs_refs2['xyzcal.mm']

    # Invent some variances for the centroid positions of the simulated data
    im_width = 0.1 * pi / 180.
    px_size = single_panel_detector[0].get_pixel_size()
    var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)

    # set the variances and frame numbers
    obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)
    obs_refs2['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

    # Add in flags and ID columns by copying into standard reflection tables
    tmp = flex.reflection_table.empty_standard(len(obs_refs))
    tmp.update(obs_refs)
    obs_refs = tmp
    tmp = flex.reflection_table.empty_standard(len(obs_refs2))
    tmp.update(obs_refs2)
    obs_refs2 = tmp

    ###############################
    # Undo known parameter shifts #
    ###############################

    s0_param.set_param_vals(s0_p_vals)
    det_param.set_param_vals(det_p_vals)
    multi_det_param.set_param_vals(det_p_vals)
    xlo_param.set_param_vals(xlo_p_vals)
    xluc_param.set_param_vals(xluc_p_vals)

    #####################################
    # Select reflections for refinement #
    #####################################

    refman = ReflectionManager(obs_refs, experiments_single_panel)
    refman2 = ReflectionManager(obs_refs, experiments_multi_panel)

    ###############################
    # Set up the target functions #
    ###############################

    mytarget = LeastSquaresPositionalResidualWithRmsdCutoff(
        experiments_single_panel,
        ExperimentsPredictor(experiments_single_panel),
        refman,
        pred_param,
        restraints_parameterisation=None)
    mytarget2 = LeastSquaresPositionalResidualWithRmsdCutoff(
        experiments_multi_panel,
        ExperimentsPredictor(experiments_multi_panel),
        refman2,
        pred_param2,
        restraints_parameterisation=None)

    #################################
    # Set up the refinement engines #
    #################################

    refiner = setup_minimiser.Extract(master_phil,
                                      mytarget,
                                      pred_param,
                                      cmdline_args=args).refiner
    refiner2 = setup_minimiser.Extract(master_phil,
                                       mytarget2,
                                       pred_param2,
                                       cmdline_args=args).refiner

    refiner.run()

    # reset parameters and run refinement with the multi panel detector
    s0_param.set_param_vals(s0_p_vals)
    multi_det_param.set_param_vals(det_p_vals)
    xlo_param.set_param_vals(xlo_p_vals)
    xluc_param.set_param_vals(xluc_p_vals)

    refiner2.run()

    # same number of steps
    assert refiner.get_num_steps() == refiner2.get_num_steps()

    # same rmsds
    for rmsd, rmsd2 in zip(refiner.history["rmsd"], refiner2.history["rmsd"]):
        assert approx_equal(rmsd, rmsd2)

    # same parameter values each step
    for params, params2 in zip(refiner.history["parameter_vector"],
                               refiner.history["parameter_vector"]):
        assert approx_equal(params, params2)
def test():
  from cctbx.sgtbx import space_group, space_group_symbols
  from libtbx.phil import parse
  from scitbx.array_family import flex

  ##### Import model builder

  from dials.test.algorithms.refinement.setup_geometry import Extract

  ##### Imports for reflection prediction

  from dials.algorithms.spot_prediction import IndexGenerator, ray_intersection
  from dxtbx.model.experiment_list import ExperimentList, Experiment
  from dials.algorithms.refinement.prediction import ScansRayPredictor, \
    ExperimentsPredictor

  #### Import model parameterisations

  from dials.algorithms.refinement.parameterisation.prediction_parameters import \
      XYPhiPredictionParameterisation
  from dials.algorithms.refinement.parameterisation.detector_parameters import \
      DetectorParameterisationSinglePanel
  from dials.algorithms.refinement.parameterisation.beam_parameters import \
      BeamParameterisation
  from dials.algorithms.refinement.parameterisation.crystal_parameters import \
      CrystalOrientationParameterisation, \
      CrystalUnitCellParameterisation
  from dials.algorithms.refinement.parameterisation.goniometer_parameters import \
      GoniometerParameterisation

  #### Create models

  overrides = """geometry.parameters.crystal.a.length.range = 10 50
  geometry.parameters.crystal.b.length.range = 10 50
  geometry.parameters.crystal.c.length.range = 10 50"""

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

  models = Extract(master_phil, overrides)

  mydetector = models.detector
  mygonio = models.goniometer
  mycrystal = models.crystal
  mybeam = models.beam

  # Build a mock scan for a 72 degree sweep
  sweep_range = (0., math.pi/5.)
  from dxtbx.model import ScanFactory
  sf = ScanFactory()
  myscan = sf.make_scan(image_range = (1,720),
                        exposure_times = 0.1,
                        oscillation = (0, 0.1),
                        epochs = range(720),
                        deg = True)

  #### Create parameterisations of these models

  det_param = DetectorParameterisationSinglePanel(mydetector)
  s0_param = BeamParameterisation(mybeam, mygonio)
  xlo_param = CrystalOrientationParameterisation(mycrystal)
  xluc_param = CrystalUnitCellParameterisation(mycrystal)
  gon_param = GoniometerParameterisation(mygonio, mybeam)

  # Create an ExperimentList
  experiments = ExperimentList()
  experiments.append(Experiment(
        beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan,
        crystal=mycrystal, imageset=None))

  #### Unit tests

  # Build a prediction parameterisation
  pred_param = XYPhiPredictionParameterisation(experiments,
                 detector_parameterisations = [det_param],
                 beam_parameterisations = [s0_param],
                 xl_orientation_parameterisations = [xlo_param],
                 xl_unit_cell_parameterisations = [xluc_param],
                 goniometer_parameterisations = [gon_param])

  # Generate reflections
  resolution = 2.0
  index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                        space_group(space_group_symbols(1).hall()).type(),
                        resolution)
  indices = index_generator.to_array()

  # Predict rays within the sweep range
  ray_predictor = ScansRayPredictor(experiments, sweep_range)
  obs_refs = ray_predictor(indices)

  # Take only those rays that intersect the detector
  intersects = ray_intersection(mydetector, 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
  ref_predictor = ExperimentsPredictor(experiments)
  obs_refs['id'] = flex.int(len(obs_refs), 0)
  obs_refs = ref_predictor(obs_refs)

  # Set 'observed' centroids from the predicted ones
  obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

  # Invent some variances for the centroid positions of the simulated data
  im_width = 0.1 * math.pi / 180.
  px_size = mydetector[0].get_pixel_size()
  var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
  var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
  var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
  obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

  # use a ReflectionManager to exclude reflections too close to the spindle
  from dials.algorithms.refinement.reflection_manager import ReflectionManager
  refman = ReflectionManager(obs_refs, experiments, outlier_detector=None)

  # Redefine the reflection predictor to use the type expected by the Target class
  ref_predictor = ExperimentsPredictor(experiments)

  # make a target to ensure reflections are predicted and refman is finalised
  from dials.algorithms.refinement.target import \
    LeastSquaresPositionalResidualWithRmsdCutoff
  target = LeastSquaresPositionalResidualWithRmsdCutoff(experiments,
      ref_predictor, refman, pred_param, restraints_parameterisation=None)

  # keep only those reflections that pass inclusion criteria and have predictions
  reflections = refman.get_matches()

  # get analytical gradients
  an_grads = pred_param.get_gradients(reflections)

  # get finite difference gradients
  p_vals = pred_param.get_param_vals()
  deltas = [1.e-7] * len(p_vals)

  for i, delta in enumerate(deltas):
    val = p_vals[i]

    p_vals[i] -= delta / 2.
    pred_param.set_param_vals(p_vals)

    ref_predictor(reflections)

    rev_state = reflections['xyzcal.mm'].deep_copy()

    p_vals[i] += delta
    pred_param.set_param_vals(p_vals)

    ref_predictor(reflections)

    fwd_state = reflections['xyzcal.mm'].deep_copy()
    p_vals[i] = val

    fd = (fwd_state - rev_state)
    x_grads, y_grads, phi_grads = fd.parts()
    x_grads /= delta
    y_grads /= delta
    phi_grads /= delta

    # compare with analytical calculation
    assert x_grads == pytest.approx(an_grads[i]["dX_dp"], abs=5.e-6)
    assert y_grads == pytest.approx(an_grads[i]["dY_dp"], abs=5.e-6)
    assert phi_grads == pytest.approx(an_grads[i]["dphi_dp"], abs=5.e-6)

  # return to the initial state
  pred_param.set_param_vals(p_vals)
示例#16
0
from copy import deepcopy
target_crystal = deepcopy(crystal)

#############################
# Generate some reflections #
#############################

# All indices in a 2.0 Angstrom sphere for crystal
resolution = 2.0
index_generator = IndexGenerator(crystal.get_unit_cell(),
                space_group(space_group_symbols(1).hall()).type(), resolution)
indices = index_generator.to_array()

# Build a ray predictor and predict rays close to the Ewald sphere by using
# the narrow rotation scan
ref_predictor = ScansRayPredictor(scans_experiments, sweep_range)
obs_refs = ref_predictor.predict(indices, experiment_id=0)

# Take only those rays that intersect the detector
intersects = ray_intersection(mydetector, obs_refs)
obs_refs = obs_refs.select(intersects)

# Add in flags and ID columns by copying into standard reflection table
tmp = flex.reflection_table.empty_standard(len(obs_refs))
tmp.update(obs_refs)
obs_refs = tmp

# Invent some variances for the centroid positions of the simulated data
im_width = 0.1 * pi / 180.
px_size = mydetector[0].get_pixel_size()
var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
def test():
    from libtbx.phil import parse
    from scitbx import matrix
    from scitbx.array_family import flex

    # Building experimental models
    from dials.test.algorithms.refinement.setup_geometry import Extract
    from dxtbx.model.experiment_list import ExperimentList, Experiment

    # Reflection prediction
    from dials.algorithms.spot_prediction import IndexGenerator
    from dials.algorithms.refinement.prediction import ScansRayPredictor, \
      ExperimentsPredictor
    from cctbx.sgtbx import space_group, space_group_symbols

    # We will set up a mock scan
    from dxtbx.model import ScanFactory

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

    overrides = """geometry.parameters.crystal.a.length.range = 10 50
  geometry.parameters.crystal.b.length.range = 10 50
  geometry.parameters.crystal.c.length.range = 10 50"""

    models = Extract(master_phil, local_overrides=overrides)

    mydetector = models.detector
    mygonio = models.goniometer
    mycrystal = models.crystal
    mybeam = models.beam

    #############################
    # Generate some reflections #
    #############################

    # All indices in a 2.0 Angstrom sphere
    resolution = 2.0
    index_generator = IndexGenerator(
        mycrystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()

    # Build a mock scan for a 30 degree sweep
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 300),
                          exposure_times=0.1,
                          oscillation=(0, 0.1),
                          epochs=range(300),
                          deg=True)
    sweep_range = myscan.get_oscillation_range(deg=False)
    assert sweep_range == pytest.approx((0., math.pi / 6.))
    im_width = myscan.get_oscillation(deg=False)[1]
    assert im_width == pytest.approx(0.1 * math.pi / 180.)

    # Create an ExperimentList for ScansRayPredictor
    experiments = ExperimentList()
    experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=mycrystal,
                   imageset=None))

    # Select those that are excited in a 30 degree sweep and get angles
    UB = mycrystal.get_A()
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    obs_refs = ray_predictor(indices)

    # Set the experiment number
    obs_refs['id'] = flex.int(len(obs_refs), 0)

    # Calculate intersections
    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs = ref_predictor(obs_refs)

    print("Total number of observations made", len(obs_refs))

    mypanel = mydetector[0]
    s0 = matrix.col(mybeam.get_s0())
    spindle = matrix.col(mygonio.get_rotation_axis())

    for ref in obs_refs:

        # get the s1 vector of this reflection
        s1 = matrix.col(ref['s1'])

        r = s1 - s0
        r_orig = r.rotate_around_origin(spindle, -1., deg=True)

        # is it outside the Ewald sphere (i.e. entering)?
        test = (s0 + r_orig).length() > s0.length()
        assert ref['entering'] == test
# Generate some reflections #
#############################

# All indices in a 2.0 Angstrom sphere
resolution = 2.0
index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                space_group(space_group_symbols(1).hall()).type(), resolution)
indices = index_generator.to_array()

sweep_range = myscan.get_oscillation_range(deg=False)
im_width = myscan.get_oscillation(deg=False)[1]
assert sweep_range == (0., pi)
assert approx_equal(im_width, 0.1 * pi / 180.)

# Predict rays within the sweep range
ray_predictor = ScansRayPredictor(experiments, sweep_range)
obs_refs = ray_predictor.predict(indices)

# Take only those rays that intersect the detector
intersects = ray_intersection(mydetector, 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
ref_predictor = ExperimentsPredictor(experiments)
obs_refs['id'] = flex.int(len(obs_refs), 0)
obs_refs = ref_predictor.predict(obs_refs)

# Set 'observed' centroids from the predicted ones
obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']
示例#19
0
target_crystal = deepcopy(crystal)

#############################
# Generate some reflections #
#############################

# All indices in a 2.0 Angstrom sphere for crystal
resolution = 2.0
index_generator = IndexGenerator(
    crystal.get_unit_cell(),
    space_group(space_group_symbols(1).hall()).type(), resolution)
indices = index_generator.to_array()

# Build a ray predictor and predict rays close to the Ewald sphere by using
# the narrow rotation scan
ref_predictor = ScansRayPredictor(scans_experiments, sweep_range)
obs_refs = ref_predictor(indices, experiment_id=0)

# Take only those rays that intersect the detector
intersects = ray_intersection(mydetector, obs_refs)
obs_refs = obs_refs.select(intersects)

# Add in flags and ID columns by copying into standard reflection table
tmp = flex.reflection_table.empty_standard(len(obs_refs))
tmp.update(obs_refs)
obs_refs = tmp

# Invent some variances for the centroid positions of the simulated data
im_width = 0.1 * pi / 180.
px_size = mydetector[0].get_pixel_size()
var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
def run(verbose = False):

  # Build models, with a larger crystal than default in order to get plenty of
  # reflections on the 'still' image
  overrides = """
  geometry.parameters.crystal.a.length.range=40 50;
  geometry.parameters.crystal.b.length.range=40 50;
  geometry.parameters.crystal.c.length.range=40 50;
  geometry.parameters.random_seed = 42"""

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

  models = Extract(master_phil, overrides)

  mydetector = models.detector
  mygonio = models.goniometer
  mycrystal = models.crystal
  mybeam = models.beam

  # Build a mock scan for a 3 degree sweep
  from dxtbx.model.scan import scan_factory
  sf = scan_factory()
  myscan = sf.make_scan(image_range = (1,1),
                        exposure_times = 0.1,
                        oscillation = (0, 3.0),
                        epochs = range(1),
                        deg = True)
  sweep_range = myscan.get_oscillation_range(deg=False)

  # Create parameterisations of these models
  det_param = DetectorParameterisationSinglePanel(mydetector)
  s0_param = BeamParameterisation(mybeam, mygonio)
  xlo_param = CrystalOrientationParameterisation(mycrystal)
  xluc_param = CrystalUnitCellParameterisation(mycrystal)

  # Create a scans ExperimentList, only for generating reflections
  experiments = ExperimentList()
  experiments.append(Experiment(
        beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan,
        crystal=mycrystal, imageset=None))

  # Create a stills ExperimentList
  stills_experiments = ExperimentList()
  stills_experiments.append(Experiment(
        beam=mybeam, detector=mydetector, crystal=mycrystal, imageset=None))

  # Generate rays - only to work out which hkls are predicted
  ray_predictor = ScansRayPredictor(experiments, sweep_range)
  resolution = 2.0
  index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                        space_group(space_group_symbols(1).hall()).type(),
                        resolution)
  indices = index_generator.to_array()
  rays = ray_predictor.predict(indices)

  # Make a standard reflection_table and copy in the ray data
  reflections = flex.reflection_table.empty_standard(len(rays))
  reflections.update(rays)

  # Build a standard prediction parameterisation for the stills experiment to do
  # FD calculation (not used for its analytical gradients)
  pred_param = StillsPredictionParameterisation(stills_experiments,
                 detector_parameterisations = [det_param],
                 beam_parameterisations = [s0_param],
                 xl_orientation_parameterisations = [xlo_param],
                 xl_unit_cell_parameterisations = [xluc_param])

  # Make a managed SphericalRelpStillsReflectionPredictor reflection predictor
  # for the first (only) experiment
  ref_predictor = Predictor(stills_experiments)

  # Predict these reflections in place. Must do this ahead of calculating
  # the analytical gradients so quantities like s1 are correct
  ref_predictor.update()
  ref_predictor.predict(reflections)

  # calculate analytical gradients
  ag = AnalyticalGradients(stills_experiments,
                 detector_parameterisation=det_param,
                 beam_parameterisation=s0_param,
                 xl_orientation_parameterisation=xlo_param,
                 xl_unit_cell_parameterisation=xluc_param)
  an_grads = ag.get_beam_gradients(reflections)
  an_grads.update(ag.get_crystal_orientation_gradients(reflections))
  an_grads.update(ag.get_crystal_unit_cell_gradients(reflections))

  # get finite difference gradients
  p_vals = pred_param.get_param_vals()
  deltas = [1.e-7] * len(p_vals)

  fd_grads = []
  p_names = pred_param.get_param_names()
  for i in range(len(deltas)):

    # save parameter value
    val = p_vals[i]

    # calc reverse state
    p_vals[i] -= deltas[i] / 2.
    pred_param.set_param_vals(p_vals)

    ref_predictor.update()
    ref_predictor.predict(reflections)

    x, y, _ = reflections['xyzcal.mm'].deep_copy().parts()
    delpsi = reflections['delpsical.rad'].deep_copy()
    s1 = reflections['s1'].deep_copy()
    rev_state = s1

    # calc forward state
    p_vals[i] += deltas[i]
    pred_param.set_param_vals(p_vals)

    ref_predictor.update()
    ref_predictor.predict(reflections)

    x, y, _ = reflections['xyzcal.mm'].deep_copy().parts()
    delpsi = reflections['delpsical.rad'].deep_copy()
    s1 = reflections['s1'].deep_copy()
    fwd_state = s1

    # reset parameter to saved value
    p_vals[i] = val

    # finite difference - currently for s1 only
    fd = (fwd_state - rev_state)
    inv_delta = 1. / deltas[i]
    s1_grads = fd * inv_delta

    # store gradients
    fd_grads.append({'name':p_names[i], 'ds1':s1_grads})

  # return to the initial state
  pred_param.set_param_vals(p_vals)

  for i, fd_grad in enumerate(fd_grads):

    ## compare FD with analytical calculations
    if verbose: print "\n\nParameter {0}: {1}". format(i,  fd_grad['name'])

    print "d[s1]/dp for the first reflection"
    print 'finite diff', fd_grad['ds1'][0]
    try:
      an_grad = an_grads[fd_grad['name']]
    except KeyError:
      continue

    print 'checking analytical vs finite difference gradients for s1'
    for a, b in zip(fd_grad['ds1'], an_grad['ds1']):
      assert approx_equal(a, b)
    print 'OK'
#############################

# All indices in a 2.0 Angstrom sphere
resolution = 2.0
index_generator = IndexGenerator(
    mycrystal.get_unit_cell(),
    space_group(space_group_symbols(1).hall()).type(), resolution)
indices = index_generator.to_array()

sweep_range = myscan.get_oscillation_range(deg=False)
im_width = myscan.get_oscillation(deg=False)[1]
assert sweep_range == (0., pi)
assert approx_equal(im_width, 0.1 * pi / 180.)

# Predict rays within the sweep range
ray_predictor = ScansRayPredictor(experiments, sweep_range)
obs_refs = ray_predictor(indices)

# Take only those rays that intersect the detector
intersects = ray_intersection(mydetector, 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
ref_predictor = ExperimentsPredictor(experiments)
obs_refs['id'] = flex.int(len(obs_refs), 0)
obs_refs = ref_predictor(obs_refs)

# Set 'observed' centroids from the predicted ones
obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']
示例#22
0
def test(args=[]):
    # Python and cctbx imports
    from math import pi
    from scitbx import matrix
    from libtbx.phil import parse
    from libtbx.test_utils import approx_equal

    # Import for surgery on reflection_tables
    from dials.array_family import flex

    # Get module to build models using PHIL
    import dials.test.algorithms.refinement.setup_geometry as setup_geometry

    # We will set up a mock scan and a mock experiment list
    from dxtbx.model import ScanFactory
    from dxtbx.model.experiment_list import ExperimentList, Experiment

    # Crystal parameterisations
    from dials.algorithms.refinement.parameterisation.crystal_parameters import \
        CrystalOrientationParameterisation, CrystalUnitCellParameterisation

    # Symmetry constrained parameterisation for the unit cell
    from cctbx.uctbx import unit_cell
    from rstbx.symmetry.constraints.parameter_reduction import \
        symmetrize_reduce_enlarge

    # Reflection prediction
    from dials.algorithms.spot_prediction import IndexGenerator
    from dials.algorithms.refinement.prediction import ScansRayPredictor, \
      ExperimentsPredictor
    from dials.algorithms.spot_prediction import ray_intersection
    from cctbx.sgtbx import space_group, space_group_symbols

    #############################
    # Setup experimental models #
    #############################

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

    # build models, with a larger crystal than default in order to get enough
    # reflections on the 'still' image
    param = """
  geometry.parameters.crystal.a.length.range=40 50;
  geometry.parameters.crystal.b.length.range=40 50;
  geometry.parameters.crystal.c.length.range=40 50;
  geometry.parameters.random_seed = 42"""
    models = setup_geometry.Extract(master_phil,
                                    cmdline_args=args,
                                    local_overrides=param)

    crystal = models.crystal
    mydetector = models.detector
    mygonio = models.goniometer
    mybeam = models.beam

    # Build a mock scan for a 1.5 degree wedge. Only used for generating indices near
    # the Ewald sphere
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 1),
                          exposure_times=0.1,
                          oscillation=(0, 1.5),
                          epochs=range(1),
                          deg=True)
    sweep_range = myscan.get_oscillation_range(deg=False)
    im_width = myscan.get_oscillation(deg=False)[1]
    assert approx_equal(im_width, 1.5 * pi / 180.)

    # Build experiment lists
    stills_experiments = ExperimentList()
    stills_experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   crystal=crystal,
                   imageset=None))
    scans_experiments = ExperimentList()
    scans_experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   crystal=crystal,
                   goniometer=mygonio,
                   scan=myscan,
                   imageset=None))

    ##########################################################
    # Parameterise the models (only for perturbing geometry) #
    ##########################################################

    xlo_param = CrystalOrientationParameterisation(crystal)
    xluc_param = CrystalUnitCellParameterisation(crystal)

    ################################
    # Apply known parameter shifts #
    ################################

    # rotate crystal (=5 mrad each rotation)
    xlo_p_vals = []
    p_vals = xlo_param.get_param_vals()
    xlo_p_vals.append(p_vals)
    new_p_vals = [a + b for a, b in zip(p_vals, [5., 5., 5.])]
    xlo_param.set_param_vals(new_p_vals)

    # change unit cell (=1.0 Angstrom length upsets, 0.5 degree of
    # gamma angle)
    xluc_p_vals = []
    p_vals = xluc_param.get_param_vals()
    xluc_p_vals.append(p_vals)
    cell_params = crystal.get_unit_cell().parameters()
    cell_params = [
        a + b for a, b in zip(cell_params, [1.0, 1.0, -1.0, 0.0, 0.0, 0.5])
    ]
    new_uc = unit_cell(cell_params)
    newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
    S = symmetrize_reduce_enlarge(crystal.get_space_group())
    S.set_orientation(orientation=newB)
    X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
    xluc_param.set_param_vals(X)

    # keep track of the target crystal model to compare with refined
    from copy import deepcopy
    target_crystal = deepcopy(crystal)

    #############################
    # Generate some reflections #
    #############################

    # All indices in a 2.0 Angstrom sphere for crystal
    resolution = 2.0
    index_generator = IndexGenerator(
        crystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()

    # Build a ray predictor and predict rays close to the Ewald sphere by using
    # the narrow rotation scan
    ref_predictor = ScansRayPredictor(scans_experiments, sweep_range)
    obs_refs = ref_predictor(indices, experiment_id=0)

    # Take only those rays that intersect the detector
    intersects = ray_intersection(mydetector, obs_refs)
    obs_refs = obs_refs.select(intersects)

    # Add in flags and ID columns by copying into standard reflection table
    tmp = flex.reflection_table.empty_standard(len(obs_refs))
    tmp.update(obs_refs)
    obs_refs = tmp

    # Invent some variances for the centroid positions of the simulated data
    im_width = 0.1 * pi / 180.
    px_size = mydetector[0].get_pixel_size()
    var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
    obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

    # Re-predict using the stills reflection predictor
    stills_ref_predictor = ExperimentsPredictor(stills_experiments)
    obs_refs_stills = stills_ref_predictor(obs_refs)

    # Set 'observed' centroids from the predicted ones
    obs_refs_stills['xyzobs.mm.value'] = obs_refs_stills['xyzcal.mm']

    ###############################
    # Undo known parameter shifts #
    ###############################

    xlo_param.set_param_vals(xlo_p_vals[0])
    xluc_param.set_param_vals(xluc_p_vals[0])

    # make a refiner
    from dials.algorithms.refinement.refiner import phil_scope
    params = phil_scope.fetch(source=parse('')).extract()

    # Change this to get a plot
    do_plot = False
    if do_plot:
        params.refinement.refinery.journal.track_parameter_correlation = True

    from dials.algorithms.refinement.refiner import RefinerFactory
    # decrease bin_size_fraction to terminate on RMSD convergence
    params.refinement.target.bin_size_fraction = 0.01
    params.refinement.parameterisation.beam.fix = "all"
    params.refinement.parameterisation.detector.fix = "all"
    refiner = RefinerFactory.from_parameters_data_experiments(
        params, obs_refs_stills, stills_experiments, verbosity=0)

    # run refinement
    history = refiner.run()

    # regression tests
    assert len(history["rmsd"]) == 9

    refined_crystal = refiner.get_experiments()[0].crystal
    uc1 = refined_crystal.get_unit_cell()
    uc2 = target_crystal.get_unit_cell()
    assert uc1.is_similar_to(uc2)

    if do_plot:
        plt = refiner.parameter_correlation_plot(
            len(history["parameter_correlation"]) - 1)
        plt.show()
示例#23
0
def test():
    # Python and cctbx imports
    from math import pi
    from scitbx import matrix
    from scitbx.array_family import flex
    from libtbx.phil import parse
    from libtbx.test_utils import approx_equal

    # Get modules to build models and minimiser using PHIL
    import dials.test.algorithms.refinement.setup_geometry as setup_geometry
    import dials.test.algorithms.refinement.setup_minimiser as setup_minimiser

    # We will set up a mock scan and a mock experiment list
    from dxtbx.model import ScanFactory
    from dxtbx.model.experiment_list import ExperimentList, Experiment

    # Model parameterisations
    from dials.algorithms.refinement.parameterisation.detector_parameters import \
        DetectorParameterisationSinglePanel
    from dials.algorithms.refinement.parameterisation.beam_parameters import \
        BeamParameterisation
    from dials.algorithms.refinement.parameterisation.crystal_parameters import \
        CrystalOrientationParameterisation, CrystalUnitCellParameterisation

    # Symmetry constrained parameterisation for the unit cell
    from cctbx.uctbx import unit_cell
    from rstbx.symmetry.constraints.parameter_reduction import \
        symmetrize_reduce_enlarge

    # Reflection prediction
    from dials.algorithms.spot_prediction import IndexGenerator, ray_intersection
    from dials.algorithms.refinement.prediction import ScansRayPredictor, \
      ExperimentsPredictor
    from cctbx.sgtbx import space_group, space_group_symbols

    # Parameterisation of the prediction equation
    from dials.algorithms.refinement.parameterisation.prediction_parameters import \
        XYPhiPredictionParameterisation

    # Imports for the target function
    from dials.algorithms.refinement.target import \
        LeastSquaresPositionalResidualWithRmsdCutoff
    from dials.algorithms.refinement.reflection_manager import ReflectionManager

    #############################
    # Setup experimental models #
    #############################

    override = """geometry.parameters
  {
    beam.wavelength.random=False
    beam.wavelength.value=1.0
    beam.direction.inclination.random=False
    crystal.a.length.random=False
    crystal.a.length.value=12.0
    crystal.a.direction.method=exactly
    crystal.a.direction.exactly.direction=1.0 0.002 -0.004
    crystal.b.length.random=False
    crystal.b.length.value=14.0
    crystal.b.direction.method=exactly
    crystal.b.direction.exactly.direction=-0.002 1.0 0.002
    crystal.c.length.random=False
    crystal.c.length.value=13.0
    crystal.c.direction.method=exactly
    crystal.c.direction.exactly.direction=0.002 -0.004 1.0
    detector.directions.method=exactly
    detector.directions.exactly.dir1=0.99 0.002 -0.004
    detector.directions.exactly.norm=0.002 -0.001 0.99
    detector.centre.method=exactly
    detector.centre.exactly.value=1.0 -0.5 199.0
  }"""

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

    models = setup_geometry.Extract(master_phil,
                                    local_overrides=override,
                                    verbose=False)

    mydetector = models.detector
    mygonio = models.goniometer
    mycrystal = models.crystal
    mybeam = models.beam

    ###########################
    # Parameterise the models #
    ###########################

    det_param = DetectorParameterisationSinglePanel(mydetector)
    s0_param = BeamParameterisation(mybeam, mygonio)
    xlo_param = CrystalOrientationParameterisation(mycrystal)
    xluc_param = CrystalUnitCellParameterisation(mycrystal)

    # Fix beam to the X-Z plane (imgCIF geometry), fix wavelength
    s0_param.set_fixed([True, False, True])

    ########################################################################
    # Link model parameterisations together into a parameterisation of the #
    # prediction equation                                                  #
    ########################################################################

    # Build a mock scan for a 180 degree sweep
    sf = ScanFactory()
    myscan = sf.make_scan(image_range=(1, 1800),
                          exposure_times=0.1,
                          oscillation=(0, 0.1),
                          epochs=range(1800),
                          deg=True)

    # Build an ExperimentList
    experiments = ExperimentList()
    experiments.append(
        Experiment(beam=mybeam,
                   detector=mydetector,
                   goniometer=mygonio,
                   scan=myscan,
                   crystal=mycrystal,
                   imageset=None))

    # Create the PredictionParameterisation
    pred_param = XYPhiPredictionParameterisation(experiments, [det_param],
                                                 [s0_param], [xlo_param],
                                                 [xluc_param])

    ################################
    # Apply known parameter shifts #
    ################################

    # shift detector by 1.0 mm each translation and 4 mrad each rotation
    det_p_vals = det_param.get_param_vals()
    p_vals = [a + b for a, b in zip(det_p_vals, [1.0, 1.0, 1.0, 4., 4., 4.])]
    det_param.set_param_vals(p_vals)

    # shift beam by 4 mrad in free axis
    s0_p_vals = s0_param.get_param_vals()
    p_vals = list(s0_p_vals)

    p_vals[0] += 4.
    s0_param.set_param_vals(p_vals)

    # rotate crystal a bit (=3 mrad each rotation)
    xlo_p_vals = xlo_param.get_param_vals()
    p_vals = [a + b for a, b in zip(xlo_p_vals, [3., 3., 3.])]
    xlo_param.set_param_vals(p_vals)

    # change unit cell a bit (=0.1 Angstrom length upsets, 0.1 degree of
    # alpha and beta angles)
    xluc_p_vals = xluc_param.get_param_vals()
    cell_params = mycrystal.get_unit_cell().parameters()
    cell_params = [
        a + b for a, b in zip(cell_params, [0.1, -0.1, 0.1, 0.1, -0.1, 0.0])
    ]
    new_uc = unit_cell(cell_params)
    newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose()
    S = symmetrize_reduce_enlarge(mycrystal.get_space_group())
    S.set_orientation(orientation=newB)
    X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
    xluc_param.set_param_vals(X)

    #############################
    # Generate some reflections #
    #############################

    # All indices in a 2.0 Angstrom sphere
    resolution = 2.0
    index_generator = IndexGenerator(
        mycrystal.get_unit_cell(),
        space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()

    sweep_range = myscan.get_oscillation_range(deg=False)
    im_width = myscan.get_oscillation(deg=False)[1]
    assert sweep_range == (0., pi)
    assert approx_equal(im_width, 0.1 * pi / 180.)

    # Predict rays within the sweep range
    ray_predictor = ScansRayPredictor(experiments, sweep_range)
    obs_refs = ray_predictor(indices)

    # Take only those rays that intersect the detector
    intersects = ray_intersection(mydetector, 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
    ref_predictor = ExperimentsPredictor(experiments)
    obs_refs['id'] = flex.int(len(obs_refs), 0)
    obs_refs = ref_predictor(obs_refs)

    # Set 'observed' centroids from the predicted ones
    obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm']

    # Invent some variances for the centroid positions of the simulated data
    im_width = 0.1 * pi / 180.
    px_size = mydetector[0].get_pixel_size()
    var_x = flex.double(len(obs_refs), (px_size[0] / 2.)**2)
    var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
    var_phi = flex.double(len(obs_refs), (im_width / 2.)**2)
    obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)

    # The total number of observations should be 1128
    assert len(obs_refs) == 1128

    ###############################
    # Undo known parameter shifts #
    ###############################

    s0_param.set_param_vals(s0_p_vals)
    det_param.set_param_vals(det_p_vals)
    xlo_param.set_param_vals(xlo_p_vals)
    xluc_param.set_param_vals(xluc_p_vals)

    #####################################
    # Select reflections for refinement #
    #####################################

    refman = ReflectionManager(obs_refs,
                               experiments,
                               outlier_detector=None,
                               close_to_spindle_cutoff=0.1)

    ##############################
    # Set up the target function #
    ##############################

    # The current 'achieved' criterion compares RMSD against 1/3 the pixel size and
    # 1/3 the image width in radians. For the simulated data, these are just made up
    mytarget = LeastSquaresPositionalResidualWithRmsdCutoff(
        experiments,
        ref_predictor,
        refman,
        pred_param,
        restraints_parameterisation=None)

    ######################################
    # Set up the LSTBX refinement engine #
    ######################################

    overrides = """minimiser.parameters.engine=GaussNewton
  minimiser.parameters.verbosity=0
  minimiser.parameters.logfile=None"""
    refiner = setup_minimiser.Extract(master_phil,
                                      mytarget,
                                      pred_param,
                                      local_overrides=overrides).refiner

    refiner.run()

    assert mytarget.achieved()
    assert refiner.get_num_steps() == 1
    assert approx_equal(
        mytarget.rmsds(),
        (0.00508252354876, 0.00420954552156, 8.97303428289e-05))

    ###############################
    # Undo known parameter shifts #
    ###############################

    s0_param.set_param_vals(s0_p_vals)
    det_param.set_param_vals(det_p_vals)
    xlo_param.set_param_vals(xlo_p_vals)
    xluc_param.set_param_vals(xluc_p_vals)

    ######################################################
    # Set up the LBFGS with curvatures refinement engine #
    ######################################################

    overrides = """minimiser.parameters.engine=LBFGScurvs
  minimiser.parameters.verbosity=0
  minimiser.parameters.logfile=None"""
    refiner = setup_minimiser.Extract(master_phil,
                                      mytarget,
                                      pred_param,
                                      local_overrides=overrides).refiner

    refiner.run()

    assert mytarget.achieved()
    assert refiner.get_num_steps() == 9
    assert approx_equal(mytarget.rmsds(),
                        (0.0558857700305, 0.0333446685335, 0.000347402754278))
  X = tuple([e * 1.e5 for e in S.forward_independent_parameters()])
  xluc_param.set_param_vals(X)

  #############################
  # Generate some reflections #
  #############################

  # All indices in a 2.0 Angstrom sphere
  resolution = 2.0
  index_generator = IndexGenerator(mycrystal.get_unit_cell(),
                  space_group(space_group_symbols(1).hall()).type(), resolution)
  indices = index_generator.to_array()

  # for the reflection predictor, it doesn't matter which experiment list is
  # passed, as the detector is not used
  ref_predictor = ScansRayPredictor(experiments_single_panel, sweep_range)

  # get two sets of identical reflections
  obs_refs = ref_predictor(indices)
  obs_refs2 = ref_predictor(indices)
  for r1, r2 in zip(obs_refs, obs_refs2):
    assert r1['s1'] == r2['s1']

  # get the panel intersections
  sel = ray_intersection(single_panel_detector, obs_refs)
  obs_refs = obs_refs.select(sel)
  sel = ray_intersection(multi_panel_detector, obs_refs2)
  obs_refs2 = obs_refs2.select(sel)
  assert len(obs_refs) == len(obs_refs2)

  # Set 'observed' centroids from the predicted ones
#print crystal2

# All indices in a 2.0 Angstrom sphere for crystal1
resolution = 2.0
index_generator = IndexGenerator(crystal1.get_unit_cell(),
                space_group(space_group_symbols(1).hall()).type(), resolution)
indices1 = index_generator.to_array()

# All indices in a 2.0 Angstrom sphere for crystal2
resolution = 2.0
index_generator = IndexGenerator(crystal2.get_unit_cell(),
                space_group(space_group_symbols(1).hall()).type(), resolution)
indices2 = index_generator.to_array()

# Predict rays within the sweep range. Set experiment IDs
ray_predictor = ScansRayPredictor(experiments, sweep_range)
obs_refs1 = ray_predictor.predict(indices1, experiment_id=0)
obs_refs1['id'] = flex.int(len(obs_refs1), 0)
obs_refs2 = ray_predictor.predict(indices1, experiment_id=1)
obs_refs2['id'] = flex.int(len(obs_refs2), 1)

# Take only those rays that intersect the detector
intersects = ray_intersection(mydetector, obs_refs1)
obs_refs1 = obs_refs1.select(intersects)
intersects = ray_intersection(mydetector, obs_refs2)
obs_refs2 = obs_refs2.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
ref_predictor = ExperimentsPredictor(experiments)
obs_refs1 = ref_predictor.predict(obs_refs1)
示例#26
0
def generate_reflections(experiments, xyzvar=(0., 0., 0.)):
  '''Generate synthetic reflection centroids using the supplied experiments,
  with normally-distributed errors applied the variances in xyzvar'''

  # check input
  if [e >= 0. for e in xyzvar].count(False) > 0:
    msg = "negative variance requested in " + str(xyzvar) + "!"
    raise RuntimeError(msg)

  refs = []
  for iexp, exp in enumerate(experiments):

    info("Generating reflections for experiment {0}".format(iexp))

    # All indices in a 1.5 Angstrom sphere
    resolution = 1.5
    index_generator = IndexGenerator(exp.crystal.get_unit_cell(),
                    space_group(space_group_symbols(1).hall()).type(), resolution)
    indices = index_generator.to_array()

    # Predict rays within the sweep range
    ray_predictor = ScansRayPredictor(experiments,
      exp.scan.get_oscillation_range(deg=False))
    obs_refs = ray_predictor.predict(indices, experiment_id=iexp)

    info("Total number of reflections excited: {0}".format(len(obs_refs)))

    # Take only those rays that intersect the detector
    intersects = ray_intersection(exp.detector, obs_refs)
    obs_refs = obs_refs.select(intersects)
    obs_refs['id'] = flex.size_t(len(obs_refs), iexp)
    refs.append(obs_refs)

    info("Total number of impacts: {0}".format(len(obs_refs)))

  # Concatenate reflections
  obs_refs = reduce(lambda x, y: x.extend(y), refs)

  # 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
  ref_predictor = ExperimentsPredictor(experiments)
  obs_refs = ref_predictor.predict(obs_refs)

  # calculate (uncorrelated) errors to offset the centroids
  # this is safe as elts of xyzvar are already tested to be > 0
  sigX, sigY, sigZ = [sqrt(e) for e in xyzvar]
  shift = [(random.gauss(0, sigX),
            random.gauss(0, sigY),
            random.gauss(0, sigZ)) for _ in xrange(len(obs_refs))]
  shift = flex.vec3_double(shift)

  # Set 'observed' centroids from the predicted ones
  obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm'] + shift

  # Store variances for the centroid positions of the simulated data. If errors
  # are zero, invent some variances
  if tuple(xyzvar) == (0., 0., 0.):
    im_width = exp.scan.get_oscillation()[1] * pi / 180.
    px_size = exp.detector[0].get_pixel_size()
    xyzvar = ((px_size[0] / 2.)**2, (px_size[1] / 2.)**2, (im_width / 2.)**2)
  var_x = flex.double(len(obs_refs), xyzvar[0])
  var_y = flex.double(len(obs_refs), xyzvar[1])
  var_phi = flex.double(len(obs_refs), xyzvar[2])
  obs_refs['xyzobs.mm.variance'] = flex.vec3_double(var_x, var_y, var_phi)
  info("Total number of observations made: {0}".format(len(obs_refs)))

  return obs_refs