def config_restraints(params, pred_param): """Given a set of user parameters plus a model parameterisation, create restraints plus a parameterisation of these restraints Params: params: The input PHIL parameters pred_param: A PredictionParameters object Returns: A restraints parameterisation or None """ if not any([ params.crystal.unit_cell.restraints.tie_to_target, params.crystal.unit_cell.restraints.tie_to_group, ]): return None if params.scan_varying: logger.warning("Restraints will be ignored for scan_varying=True") return None det_params = pred_param.get_detector_parameterisations() beam_params = pred_param.get_beam_parameterisations() xl_ori_params = pred_param.get_crystal_orientation_parameterisations() xl_uc_params = pred_param.get_crystal_unit_cell_parameterisations() gon_params = pred_param.get_goniometer_parameterisations() from dials.algorithms.refinement.restraints import RestraintsParameterisation rp = RestraintsParameterisation( detector_parameterisations=det_params, beam_parameterisations=beam_params, xl_orientation_parameterisations=xl_ori_params, xl_unit_cell_parameterisations=xl_uc_params, goniometer_parameterisations=gon_params, ) # Shorten params path # FIXME Only unit cell restraints currently supported # beam_r = params.beam.restraints cell_r = params.crystal.unit_cell.restraints # orientation_r = params.crystal.orientation.restraints # detector_r = params.detector.restraints for tie in cell_r.tie_to_target: if len(tie.values) != 6: raise DialsRefineConfigError( "6 cell parameters must be provided as the tie_to_target.values." ) if len(tie.sigmas) != 6: raise DialsRefineConfigError( "6 sigmas must be provided as the tie_to_target.sigmas. " "Note that individual sigmas of 0.0 will remove " "the restraint for the corresponding cell parameter.") if tie.id is None: # get one experiment id for each parameterisation to apply to all tie.id = [e.get_experiment_ids()[0] for e in xl_uc_params] for exp_id in tie.id: rp.add_restraints_to_target_xl_unit_cell( exp_id, tie.values, tie.sigmas) for tie in cell_r.tie_to_group: if len(tie.sigmas) != 6: raise DialsRefineConfigError( "6 sigmas must be provided as the tie_to_group.sigmas. " "Note that individual sigmas of 0.0 will remove " "the restraint for the corresponding cell parameter.") if tie.id is None: rp.add_restraints_to_group_xl_unit_cell( tie.target, "all", tie.sigmas) else: rp.add_restraints_to_group_xl_unit_cell( tie.target, tie.id, tie.sigmas) return rp
def test_single_crystal_restraints_gradients(): """Simple test with a single triclinic crystal restrained to a target unit cell""" from dxtbx.model.experiment_list import Experiment, ExperimentList from dials.algorithms.refinement.parameterisation.beam_parameters import ( BeamParameterisation, ) from dials.algorithms.refinement.parameterisation.crystal_parameters import ( CrystalOrientationParameterisation, CrystalUnitCellParameterisation, ) from dials.algorithms.refinement.parameterisation.detector_parameters import ( DetectorParameterisationSinglePanel, ) from dials.algorithms.refinement.parameterisation.prediction_parameters import ( XYPhiPredictionParameterisation, ) from dials.test.algorithms.refinement.setup_geometry import Extract 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 sequence from dxtbx.model import ScanFactory sf = ScanFactory() myscan = sf.make_scan( image_range=(1, 720), exposure_times=0.1, oscillation=(0, 0.1), epochs=list(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.0 uc = mycrystal.get_unit_cell().parameters() target_uc = [random.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() assert len(vals) == rp.num_residuals # get finite difference gradients p_vals = pred_param.get_param_vals() deltas = [1.0e-7] * len(p_vals) fd_grad = [] for i, delta in enumerate(deltas): val = p_vals[i] p_vals[i] -= delta / 2.0 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] += delta 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) / delta 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 an == pytest.approx(fd, abs=1e-5)
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"
def test2(): '''Simple test with two triclinic crystals 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 # duplicate the crystal from copy import deepcopy mycrystal2 = deepcopy(mycrystal) 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) xluc_param2 = CrystalUnitCellParameterisation(mycrystal2, experiment_ids=[1]) # Create an ExperimentList with the crystal duplicated experiments = ExperimentList() experiments.append( Experiment(beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None)) experiments.append( Experiment(beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal2, 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, xluc_param2]) # 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, xluc_param2]) # 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) rp.add_restraints_to_target_xl_unit_cell(experiment_id=1, 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"