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 setup_models(args): """setup the experimental models""" # Setup experimental models master_phil = parse(""" include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True) models = setup_geometry.Extract(master_phil, cmdline_args = args) detector = models.detector goniometer = models.goniometer crystal = models.crystal beam = models.beam # Build a mock scan for a 180 degree sweep sf = scan_factory() scan = sf.make_scan(image_range = (1,180), exposure_times = 0.1, oscillation = (0, 1.0), epochs = range(180), deg = True) sweep_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sweep_range == (0., pi) assert approx_equal(im_width, 1.0 * pi / 180.) experiments = ExperimentList() experiments.append(Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None)) return experiments
def create_models(self, cmdline_overrides=None): if cmdline_overrides is None: cmdline_overrides = [] 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) # Extract models models = Extract(master_phil, overrides, cmdline_args = cmdline_overrides) self.detector = models.detector self.goniometer = models.goniometer self.crystal = models.crystal self.beam = models.beam # Make a scan of 1-360 * 0.5 deg images sf = scan_factory() self.scan = sf.make_scan((1,360), 0.5, (0, 0.5), range(360)) # Generate an ExperimentList self.experiments = ExperimentList() self.experiments.append(Experiment( beam=self.beam, detector=self.detector, goniometer=self.goniometer, scan=self.scan, crystal=self.crystal, imageset=None)) # Create a reflection predictor for the experiments self.ref_predictor = ExperimentsPredictor(self.experiments) # Create scan-varying parameterisations of these models, with 5 samples self.det_param = ScanVaryingDetectorParameterisationSinglePanel( self.detector, self.scan.get_array_range(), 5) self.s0_param = ScanVaryingBeamParameterisation( self.beam, self.scan.get_array_range(), 5, self.goniometer) self.xlo_param = ScanVaryingCrystalOrientationParameterisation( self.crystal, self.scan.get_array_range(), 5) self.xluc_param = ScanVaryingCrystalUnitCellParameterisation( self.crystal, self.scan.get_array_range(), 5) return
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(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 test1(): '''Simple test with a single triclinic crystal restrained to a target unit cell''' from math import pi from random import gauss from dials.test.algorithms.refinement.setup_geometry import Extract from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment #### 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 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., pi/5.) from dxtbx.model.scan import scan_factory sf = scan_factory() 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) # Create an ExperimentList experiments = ExperimentList() experiments.append(Experiment( beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None)) # 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]) # Build a restraints parameterisation rp = RestraintsParameterisation(detector_parameterisations = [det_param], beam_parameterisations = [s0_param], xl_orientation_parameterisations = [xlo_param], xl_unit_cell_parameterisations = [xluc_param]) # make a unit cell target sigma = 1. uc = mycrystal.get_unit_cell().parameters() target_uc = [gauss(e, sigma) for e in uc] rp.add_restraints_to_target_xl_unit_cell(experiment_id=0, values=target_uc, sigma=[sigma]*6) # get analytical values and gradients vals, grads, weights = rp.get_residuals_gradients_and_weights() # get finite difference gradients p_vals = pred_param.get_param_vals() deltas = [1.e-7] * len(p_vals) fd_grad=[] for i in range(len(deltas)): val = p_vals[i] p_vals[i] -= deltas[i] / 2. pred_param.set_param_vals(p_vals) rev_state, foo, bar = rp.get_residuals_gradients_and_weights() rev_state = flex.double(rev_state) p_vals[i] += deltas[i] pred_param.set_param_vals(p_vals) fwd_state, foo, bar = rp.get_residuals_gradients_and_weights() fwd_state = flex.double(fwd_state) p_vals[i] = val fd = (fwd_state - rev_state) / deltas[i] fd_grad.append(fd) # for comparison, fd_grad is a list of flex.doubles, each of which corresponds # to a column of the sparse matrix grads. for i, fd in enumerate(fd_grad): # extract dense column from the sparse matrix an = grads.col(i).as_dense_vector() assert approx_equal(an, fd, eps=1e-5) print "OK"
args = sys.argv[1:] 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) mydetector = models.detector mygonio = models.goniometer mycrystal = models.crystal mybeam = models.beam # Build a mock scan for a 180 degree sweep sf = scan_factory() 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) temp = myscan.get_oscillation(deg=False) im_width = temp[1] - temp[0] 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,
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 = scan_factory() 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))
def test_fd_derivatives(): '''Test derivatives of the prediction equation''' from libtbx.phil import parse # Import model builder from setup_geometry import Extract # Imports for reflection prediction from dials.algorithms.spot_prediction import IndexGenerator, ray_intersection from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment from dials.algorithms.refinement.prediction import ScansRayPredictor, \ ExperimentsPredictor # 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., pi/5.) from dxtbx.model.scan import scan_factory sf = scan_factory() myscan = sf.make_scan(image_range = (1,720), exposure_times = 0.1, oscillation = (0, 0.1), epochs = range(720), deg = True) # Create a parameterisation of the crystal unit cell from dials.algorithms.refinement.parameterisation.crystal_parameters import \ CrystalUnitCellParameterisation xluc_param = CrystalUnitCellParameterisation(mycrystal) # Create an ExperimentList experiments = ExperimentList() experiments.append(Experiment( beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None)) # Build a prediction parameterisation for two theta prediction pred_param = TwoThetaPredictionParameterisation(experiments, detector_parameterisations = None, beam_parameterisations = None, xl_orientation_parameterisations = None, xl_unit_cell_parameterisations = [xluc_param]) # Generate some reflections obs_refs, ref_predictor = generate_reflections(experiments) # Build a ReflectionManager with overloads for handling 2theta residuals refman = TwoThetaReflectionManager(obs_refs, experiments, outlier_detector=None) # Build a TwoThetaExperimentsPredictor ref_predictor = TwoThetaExperimentsPredictor(experiments) # Make a target for the least squares 2theta residual target = TwoThetaTarget(experiments, ref_predictor, refman, pred_param) # Keep only 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 in range(len(deltas)): val = p_vals[i] p_vals[i] -= deltas[i] / 2. pred_param.set_param_vals(p_vals) target.predict() reflections = refman.get_matches() rev_state = reflections['2theta_resid'].deep_copy() p_vals[i] += deltas[i] pred_param.set_param_vals(p_vals) target.predict() reflections = refman.get_matches() fwd_state = reflections['2theta_resid'].deep_copy() p_vals[i] = val fd = (fwd_state - rev_state) fd /= deltas[i] # compare with analytical calculation assert approx_equal(fd, an_grads[i]["d2theta_dp"], eps=1.e-6) # return to the initial state pred_param.set_param_vals(p_vals) return
def test_refinement(): '''Test a refinement run''' dials_regression = libtbx.env.find_in_repositories( relative_path="dials_regression", test=os.path.isdir) # Get a beam and detector from a datablock. This one has a CS-PAD, but that # is irrelevant data_dir = os.path.join(dials_regression, "refinement_test_data", "hierarchy_test") datablock_path = os.path.join(data_dir, "datablock.json") assert os.path.exists(datablock_path) # load models from dxtbx.datablock import DataBlockFactory datablock = DataBlockFactory.from_serialized_format(datablock_path, check_format=False) im_set = datablock[0].extract_imagesets()[0] from copy import deepcopy detector = deepcopy(im_set.get_detector()) beam = im_set.get_beam() # Invent a crystal, goniometer and scan for this test from dxtbx.model.crystal import crystal_model crystal = crystal_model((40.,0.,0.) ,(0.,40.,0.), (0.,0.,40.), space_group_symbol = "P1") orig_xl = deepcopy(crystal) from dxtbx.model.experiment import goniometer_factory goniometer = goniometer_factory.known_axis((1., 0., 0.)) # Build a mock scan for a 180 degree sweep from dxtbx.model.scan import scan_factory sf = scan_factory() scan = sf.make_scan(image_range = (1,1800), exposure_times = 0.1, oscillation = (0, 0.1), epochs = range(1800), deg = True) sweep_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sweep_range == (0., pi) assert approx_equal(im_width, 0.1 * pi / 180.) from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment # Build an experiment list experiments = ExperimentList() experiments.append(Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None)) # simulate some reflections refs, _ = generate_reflections(experiments) # change unit cell a bit (=0.1 Angstrom length upsets, 0.1 degree of # alpha and beta angles) from dials.algorithms.refinement.parameterisation.crystal_parameters import \ CrystalUnitCellParameterisation xluc_param = CrystalUnitCellParameterisation(crystal) xluc_p_vals = xluc_param.get_param_vals() cell_params = crystal.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])] from cctbx.uctbx import unit_cell from rstbx.symmetry.constraints.parameter_reduction import \ symmetrize_reduce_enlarge from scitbx import matrix 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) # reparameterise the crystal at the perturbed geometry xluc_param = CrystalUnitCellParameterisation(crystal) # Dummy parameterisations for other models beam_param = None xlo_param = None det_param = None # parameterisation of the prediction equation from dials.algorithms.refinement.parameterisation.parameter_report import \ ParameterReporter pred_param = TwoThetaPredictionParameterisation(experiments, det_param, beam_param, xlo_param, [xluc_param]) param_reporter = ParameterReporter(det_param, beam_param, xlo_param, [xluc_param]) # reflection manager refman = TwoThetaReflectionManager(refs, experiments, nref_per_degree=20, verbosity=2) # reflection predictor ref_predictor = TwoThetaExperimentsPredictor(experiments) # target function target = TwoThetaTarget(experiments, ref_predictor, refman, pred_param) # minimisation engine from dials.algorithms.refinement.engine \ import LevenbergMarquardtIterations as Refinery refinery = Refinery(target = target, prediction_parameterisation = pred_param, log = None, verbosity = 0, track_step = False, track_gradient = False, track_parameter_correlation = False, max_iterations = 20) # Refiner from dials.algorithms.refinement.refiner import Refiner refiner = Refiner(reflections=refs, experiments=experiments, pred_param=pred_param, param_reporter=param_reporter, refman=refman, target=target, refinery=refinery, verbosity=1) history = refiner.run() # compare crystal with original crystal refined_xl = refiner.get_experiments()[0].crystal #print refined_xl assert refined_xl.is_similar_to(orig_xl, uc_rel_length_tolerance=0.001, uc_abs_angle_tolerance=0.01) #print "Unit cell esds:" #print refined_xl.get_cell_parameter_sd() return
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'
def test1(): dials_regression = libtbx.env.find_in_repositories( relative_path="dials_regression", test=os.path.isdir) # use a datablock that contains a CS-PAD detector description data_dir = os.path.join(dials_regression, "refinement_test_data", "hierarchy_test") datablock_path = os.path.join(data_dir, "datablock.json") assert os.path.exists(datablock_path) # load models from dxtbx.datablock import DataBlockFactory datablock = DataBlockFactory.from_serialized_format(datablock_path, check_format=False) im_set = datablock[0].extract_imagesets()[0] from copy import deepcopy detector = deepcopy(im_set.get_detector()) beam = im_set.get_beam() # we'll invent a crystal, goniometer and scan for this test from dxtbx.model.crystal import crystal_model crystal = crystal_model((40.,0.,0.) ,(0.,40.,0.), (0.,0.,40.), space_group_symbol = "P1") from dxtbx.model.experiment import goniometer_factory goniometer = goniometer_factory.known_axis((1., 0., 0.)) # Build a mock scan for a 180 degree sweep from dxtbx.model.scan import scan_factory sf = scan_factory() scan = sf.make_scan(image_range = (1,1800), exposure_times = 0.1, oscillation = (0, 0.1), epochs = range(1800), deg = True) sweep_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sweep_range == (0., pi) assert approx_equal(im_width, 0.1 * pi / 180.) from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment # Build an experiment list experiments = ExperimentList() experiments.append(Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None)) # simulate some reflections refs, ref_predictor = generate_reflections(experiments) # move the detector quadrants apart by 2mm both horizontally and vertically from dials.algorithms.refinement.parameterisation \ import DetectorParameterisationHierarchical det_param = DetectorParameterisationHierarchical(detector, level=1) det_p_vals = det_param.get_param_vals() p_vals = list(det_p_vals) p_vals[1] += 2 p_vals[2] -= 2 p_vals[7] += 2 p_vals[8] += 2 p_vals[13] -= 2 p_vals[14] += 2 p_vals[19] -= 2 p_vals[20] -= 2 det_param.set_param_vals(p_vals) # reparameterise the detector at the new perturbed geometry det_param = DetectorParameterisationHierarchical(detector, level=1) # parameterise other models from dials.algorithms.refinement.parameterisation.beam_parameters import \ BeamParameterisation from dials.algorithms.refinement.parameterisation.crystal_parameters import \ CrystalOrientationParameterisation, CrystalUnitCellParameterisation beam_param = BeamParameterisation(beam, goniometer) xlo_param = CrystalOrientationParameterisation(crystal) xluc_param = CrystalUnitCellParameterisation(crystal) # fix beam beam_param.set_fixed([True]*3) # fix crystal xluc_param.set_fixed([True]*6) xlo_param.set_fixed([True]*3) # parameterisation of the prediction equation from dials.algorithms.refinement.parameterisation.prediction_parameters import \ XYPhiPredictionParameterisation from dials.algorithms.refinement.parameterisation.parameter_report import \ ParameterReporter pred_param = XYPhiPredictionParameterisation(experiments, [det_param], [beam_param], [xlo_param], [xluc_param]) param_reporter = ParameterReporter([det_param], [beam_param], [xlo_param], [xluc_param]) # reflection manager and target function from dials.algorithms.refinement.target import \ LeastSquaresPositionalResidualWithRmsdCutoff from dials.algorithms.refinement.reflection_manager import ReflectionManager refman = ReflectionManager(refs, experiments, nref_per_degree=20) # set a very tight rmsd target of 1/10000 of a pixel target = LeastSquaresPositionalResidualWithRmsdCutoff(experiments, ref_predictor, refman, pred_param, restraints_parameterisation=None, frac_binsize_cutoff=0.0001) # minimisation engine from dials.algorithms.refinement.engine \ import LevenbergMarquardtIterations as Refinery refinery = Refinery(target = target, prediction_parameterisation = pred_param, log = None, verbosity = 0, track_step = False, track_gradient = False, track_parameter_correlation = False, max_iterations = 20) # Refiner from dials.algorithms.refinement.refiner import Refiner refiner = Refiner(reflections=refs, experiments=experiments, pred_param=pred_param, param_reporter=param_reporter, refman=refman, target=target, refinery=refinery, verbosity=0) history = refiner.run() assert history.reason_for_termination == "RMSD target achieved" #compare detector with original detector orig_det = im_set.get_detector() refined_det = refiner.get_experiments()[0].detector from scitbx import matrix import math for op, rp in zip(orig_det, refined_det): # compare the origin vectors by... o1 = matrix.col(op.get_origin()) o2 = matrix.col(rp.get_origin()) # ...their relative lengths assert approx_equal( math.fabs(o1.length() - o2.length()) / o1.length(), 0, eps=1e-5) # ...the angle between them assert approx_equal(o1.accute_angle(o2), 0, eps=1e-5) print "OK" return
def test1(): dials_regression = libtbx.env.find_in_repositories( relative_path="dials_regression", test=os.path.isdir) # use a datablock that contains a CS-PAD detector description data_dir = os.path.join(dials_regression, "refinement_test_data", "hierarchy_test") datablock_path = os.path.join(data_dir, "datablock.json") assert os.path.exists(datablock_path) # load models from dxtbx.datablock import DataBlockFactory datablock = DataBlockFactory.from_serialized_format(datablock_path, check_format=False) im_set = datablock[0].extract_imagesets()[0] from copy import deepcopy detector = deepcopy(im_set.get_detector()) beam = im_set.get_beam() # we'll invent a crystal, goniometer and scan for this test from dxtbx.model.crystal import crystal_model crystal = crystal_model((40., 0., 0.), (0., 40., 0.), (0., 0., 40.), space_group_symbol="P1") from dxtbx.model.experiment import goniometer_factory goniometer = goniometer_factory.known_axis((1., 0., 0.)) # Build a mock scan for a 180 degree sweep from dxtbx.model.scan import scan_factory sf = scan_factory() scan = sf.make_scan(image_range=(1, 1800), exposure_times=0.1, oscillation=(0, 0.1), epochs=range(1800), deg=True) sweep_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sweep_range == (0., pi) assert approx_equal(im_width, 0.1 * pi / 180.) from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment # Build an experiment list experiments = ExperimentList() experiments.append( Experiment(beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None)) # simulate some reflections refs, ref_predictor = generate_reflections(experiments) # move the detector quadrants apart by 2mm both horizontally and vertically from dials.algorithms.refinement.parameterisation \ import DetectorParameterisationHierarchical det_param = DetectorParameterisationHierarchical(detector, level=1) det_p_vals = det_param.get_param_vals() p_vals = list(det_p_vals) p_vals[1] += 2 p_vals[2] -= 2 p_vals[7] += 2 p_vals[8] += 2 p_vals[13] -= 2 p_vals[14] += 2 p_vals[19] -= 2 p_vals[20] -= 2 det_param.set_param_vals(p_vals) # reparameterise the detector at the new perturbed geometry det_param = DetectorParameterisationHierarchical(detector, level=1) # parameterise other models from dials.algorithms.refinement.parameterisation.beam_parameters import \ BeamParameterisation from dials.algorithms.refinement.parameterisation.crystal_parameters import \ CrystalOrientationParameterisation, CrystalUnitCellParameterisation beam_param = BeamParameterisation(beam, goniometer) xlo_param = CrystalOrientationParameterisation(crystal) xluc_param = CrystalUnitCellParameterisation(crystal) # fix beam beam_param.set_fixed([True] * 3) # fix crystal xluc_param.set_fixed([True] * 6) xlo_param.set_fixed([True] * 3) # parameterisation of the prediction equation from dials.algorithms.refinement.parameterisation.prediction_parameters import \ XYPhiPredictionParameterisation from dials.algorithms.refinement.parameterisation.parameter_report import \ ParameterReporter pred_param = XYPhiPredictionParameterisation(experiments, [det_param], [beam_param], [xlo_param], [xluc_param]) param_reporter = ParameterReporter([det_param], [beam_param], [xlo_param], [xluc_param]) # reflection manager and target function from dials.algorithms.refinement.target import \ LeastSquaresPositionalResidualWithRmsdCutoff from dials.algorithms.refinement.reflection_manager import ReflectionManager refman = ReflectionManager(refs, experiments, nref_per_degree=20) # set a very tight rmsd target of 1/10000 of a pixel target = LeastSquaresPositionalResidualWithRmsdCutoff( experiments, ref_predictor, refman, pred_param, restraints_parameterisation=None, frac_binsize_cutoff=0.0001) # minimisation engine from dials.algorithms.refinement.engine \ import LevenbergMarquardtIterations as Refinery refinery = Refinery(target=target, prediction_parameterisation=pred_param, log=None, verbosity=0, track_step=False, track_gradient=False, track_parameter_correlation=False, max_iterations=20) # Refiner from dials.algorithms.refinement.refiner import Refiner refiner = Refiner(reflections=refs, experiments=experiments, pred_param=pred_param, param_reporter=param_reporter, refman=refman, target=target, refinery=refinery, verbosity=0) history = refiner.run() assert history.reason_for_termination == "RMSD target achieved" #compare detector with original detector orig_det = im_set.get_detector() refined_det = refiner.get_experiments()[0].detector from scitbx import matrix import math for op, rp in zip(orig_det, refined_det): # compare the origin vectors by... o1 = matrix.col(op.get_origin()) o2 = matrix.col(rp.get_origin()) # ...their relative lengths assert approx_equal(math.fabs(o1.length() - o2.length()) / o1.length(), 0, eps=1e-5) # ...the angle between them assert approx_equal(o1.accute_angle(o2), 0, eps=1e-5) print "OK" return
def test1(): '''Simple test with a single triclinic crystal restrained to a target unit cell''' from math import pi from random import gauss from dials.test.algorithms.refinement.setup_geometry import Extract from dxtbx.model.experiment.experiment_list import ExperimentList, Experiment #### 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 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., pi / 5.) from dxtbx.model.scan import scan_factory sf = scan_factory() 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) # Create an ExperimentList experiments = ExperimentList() experiments.append( Experiment(beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None)) # 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]) # Build a restraints parameterisation rp = RestraintsParameterisation( detector_parameterisations=[det_param], beam_parameterisations=[s0_param], xl_orientation_parameterisations=[xlo_param], xl_unit_cell_parameterisations=[xluc_param]) # make a unit cell target sigma = 1. uc = mycrystal.get_unit_cell().parameters() target_uc = [gauss(e, sigma) for e in uc] rp.add_restraints_to_target_xl_unit_cell(experiment_id=0, values=target_uc, sigma=[sigma] * 6) # get analytical values and gradients vals, grads, weights = rp.get_residuals_gradients_and_weights() # get finite difference gradients p_vals = pred_param.get_param_vals() deltas = [1.e-7] * len(p_vals) fd_grad = [] for i in range(len(deltas)): val = p_vals[i] p_vals[i] -= deltas[i] / 2. pred_param.set_param_vals(p_vals) rev_state, foo, bar = rp.get_residuals_gradients_and_weights() rev_state = flex.double(rev_state) p_vals[i] += deltas[i] pred_param.set_param_vals(p_vals) fwd_state, foo, bar = rp.get_residuals_gradients_and_weights() fwd_state = flex.double(fwd_state) p_vals[i] = val fd = (fwd_state - rev_state) / deltas[i] fd_grad.append(fd) # for comparison, fd_grad is a list of flex.doubles, each of which corresponds # to a column of the sparse matrix grads. for i, fd in enumerate(fd_grad): # extract dense column from the sparse matrix an = grads.col(i).as_dense_vector() assert approx_equal(an, fd, eps=1e-5) print "OK"