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 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
# 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) obs_refs2 = ref_predictor.predict(obs_refs2)
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.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'] # Invent some variances for the centroid positions of the simulated data
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
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) var_y = flex.double(len(obs_refs), (px_size[1] / 2.)**2)
############################# # 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 obs_refs['xyzobs.mm.value'] = obs_refs['xyzcal.mm'] obs_refs2['xyzobs.mm.value'] = obs_refs2['xyzcal.mm']
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