def test_equivalence_of_python_and_cpp_multipanel_algorithms(init_test): multi_panel_detector = init_test.experiments_multi_panel.detectors()[0] beam = init_test.experiments_single_panel.beams()[0] # Parameterise the models det_param1 = DetectorParameterisationMultiPanel(multi_panel_detector, beam) det_param2 = PyDetectorParameterisationMultiPanel(multi_panel_detector, beam) # shift detectors by 1.0 mm each translation and 2 mrad each rotation for dp in [det_param1, det_param2]: p_vals = dp.get_param_vals() p_vals = [ a + b for a, b in zip(p_vals, [1.0, 1.0, 1.0, 2.0, 2.0, 2.0]) ] dp.set_param_vals(p_vals) dp.compose() for pnl in range(3): derivatives1 = det_param1.get_ds_dp(multi_state_elt=pnl) derivatives2 = det_param2.get_ds_dp(multi_state_elt=pnl) for a, b in zip(derivatives1, derivatives2): for i, j in zip(a, b): assert i == pytest.approx(j)
def test_check_and_remove(): test = _Test() # Override the single panel model and parameterisation. This test function # exercises the code for non-hierarchical multi-panel detectors. The # hierarchical detector version is tested via test_cspad_refinement.py multi_panel_detector = Detector() for x in range(3): for y in range(3): new_panel = make_panel_in_array((x, y), test.detector[0]) multi_panel_detector.add_panel(new_panel) test.detector = multi_panel_detector test.stills_experiments[0].detector = multi_panel_detector test.det_param = DetectorParameterisationMultiPanel(multi_panel_detector, test.beam) # update the generated reflections test.generate_reflections() # Predict the reflections in place and put in a reflection manager ref_predictor = StillsExperimentsPredictor(test.stills_experiments) ref_predictor(test.reflections) test.refman = ReflectionManagerFactory.from_parameters_reflections_experiments( refman_phil_scope.extract(), test.reflections, test.stills_experiments, do_stills=True, ) test.refman.finalise() # Build a prediction parameterisation for the stills experiment test.pred_param = StillsPredictionParameterisation( test.stills_experiments, detector_parameterisations=[test.det_param], beam_parameterisations=[test.s0_param], xl_orientation_parameterisations=[test.xlo_param], xl_unit_cell_parameterisations=[test.xluc_param], ) # A non-hierarchical detector does not have panel groups, thus panels are # not treated independently wrt which reflections affect their parameters. # As before, setting 792 reflections as the minimum should leave all # parameters free, and should not remove any reflections options = ar_phil_scope.extract() options.min_nref_per_parameter = 792 ar = AutoReduce(options, pred_param=test.pred_param, reflection_manager=test.refman) ar.check_and_remove() det_params = test.pred_param.get_detector_parameterisations() beam_params = test.pred_param.get_beam_parameterisations() xl_ori_params = test.pred_param.get_crystal_orientation_parameterisations() xl_uc_params = test.pred_param.get_crystal_unit_cell_parameterisations() assert det_params[0].num_free() == 6 assert beam_params[0].num_free() == 3 assert xl_ori_params[0].num_free() == 3 assert xl_uc_params[0].num_free() == 6 assert len(test.refman.get_obs()) == 823 # Setting 793 reflections as the minimum fixes 3 unit cell parameters, # and removes all those reflections. There are then too few reflections # for any parameterisation and all will be fixed, leaving no free # parameters for refinement. This fails within PredictionParameterisation, # during update so the final 31 reflections are not removed. options = ar_phil_scope.extract() options.min_nref_per_parameter = 793 ar = AutoReduce(options, pred_param=test.pred_param, reflection_manager=test.refman) with pytest.raises( DialsRefineConfigError, match="There are no free parameters for refinement" ): ar.check_and_remove() det_params = test.pred_param.get_detector_parameterisations() beam_params = test.pred_param.get_beam_parameterisations() xl_ori_params = test.pred_param.get_crystal_orientation_parameterisations() xl_uc_params = test.pred_param.get_crystal_unit_cell_parameterisations() assert det_params[0].num_free() == 0 assert beam_params[0].num_free() == 0 assert xl_ori_params[0].num_free() == 0 assert xl_uc_params[0].num_free() == 0 assert len(test.refman.get_obs()) == 823 - 792
def test(): # set the random seed to make the test reproducible random.seed(1337) # set up a simple detector frame with directions aligned with # principal axes and sensor origin located on the z-axis at -110 d1 = matrix.col((1, 0, 0)) d2 = matrix.col((0, -1, 0)) # lim = (0,50) npx_fast = 1475 npx_slow = 1679 pix_size_f = pix_size_s = 0.172 detector = DetectorFactory.make_detector( "PAD", d1, d2, matrix.col((0, 0, -110)), (pix_size_f, pix_size_s), (npx_fast, npx_slow), (0, 2e20), ) dp = DetectorParameterisationSinglePanel(detector) beam = BeamFactory().make_beam( sample_to_source=-1 * (matrix.col((0, 0, -110)) + 10 * d1 + 10 * d2), wavelength=1.0, ) # Test change of parameters # ========================= # 1. shift detector plane so that the z-axis intercepts its centre # at a distance of 100 along the initial normal direction. As the # initial normal is along -z, we expect the frame to intercept the # z-axis at -100. p_vals = dp.get_param_vals() p_vals[0:3] = [100.0, 0.0, 0.0] dp.set_param_vals(p_vals) detector = dp._model assert len(detector) == 1 panel = detector[0] v1 = matrix.col(panel.get_origin()) v2 = matrix.col((0.0, 0.0, 1.0)) assert approx_equal(v1.dot(v2), -100.0) # 2. rotate frame around its initial normal by +90 degrees. Only d1 # and d2 should change. As we rotate clockwise around the initial # normal (-z direction) then d1 should rotate onto the original # direction d2, and d2 should rotate to negative of the original # direction d1 p_vals[3] = 1000.0 * pi / 2 # set tau1 value dp.set_param_vals(p_vals) detector = dp._model assert len(detector) == 1 panel = detector[0] assert approx_equal( matrix.col(panel.get_fast_axis()).dot(dp._initial_state["d1"]), 0.0) assert approx_equal( matrix.col(panel.get_slow_axis()).dot(dp._initial_state["d2"]), 0.0) assert approx_equal( matrix.col(panel.get_normal()).dot(dp._initial_state["dn"]), 1.0) # 3. no rotation around initial normal, +10 degrees around initial # d1 direction and +10 degrees around initial d2. Check d1 and d2 # match paper calculation p_vals[3] = 0.0 # tau1 p_vals[4] = 1000.0 * pi / 18 # tau2 p_vals[5] = 1000.0 * pi / 18 # tau3 dp.set_param_vals(p_vals) # paper calculation values v1 = matrix.col((cos(pi / 18), 0, sin(pi / 18))) v2 = matrix.col(( sin(pi / 18)**2, -cos(pi / 18), sqrt((2 * sin(pi / 36) * sin(pi / 18))**2 - sin(pi / 18)**4) - sin(pi / 18), )) detector = dp._model assert len(detector) == 1 panel = detector[0] assert approx_equal(matrix.col(panel.get_fast_axis()).dot(v1), 1.0) assert approx_equal(matrix.col(panel.get_slow_axis()).dot(v2), 1.0) # 4. Test fixing and unfixing of parameters p_vals = [ 100.0, 0.0, 0.0, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18 ] dp.set_param_vals(p_vals) f = dp.get_fixed() f[0:3] = [True] * 3 dp.set_fixed(f) p_vals2 = [0.0, 0.0, 0.0] dp.set_param_vals(p_vals2) assert dp.get_param_vals(only_free=False) == [ 100.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] an_ds_dp = dp.get_ds_dp() assert len(an_ds_dp) == 3 f[0:3] = [False] * 3 dp.set_fixed(f) p_vals = dp.get_param_vals() p_vals2 = [a + b for a, b in zip(p_vals, [-10.0, 1.0, 1.0, 0.0, 0.0, 0.0])] dp.set_param_vals(p_vals2) assert dp.get_param_vals() == [90.0, 1.0, 1.0, 0.0, 0.0, 0.0] # 5. Tests of the calculation of derivatives # Now using parameterisation in mrad # random initial orientations with a random parameter shift at each attempts = 100 for i in range(attempts): # create random initial position det = Detector(random_panel()) dp = DetectorParameterisationSinglePanel(det) # apply a random parameter shift p_vals = dp.get_param_vals() p_vals = random_param_shift( p_vals, [10, 10, 10, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18]) dp.set_param_vals(p_vals) # compare analytical and finite difference derivatives. an_ds_dp = dp.get_ds_dp(multi_state_elt=0) fd_ds_dp = get_fd_gradients(dp, [1.0e-6] * 3 + [1.0e-4 * pi / 180] * 3) for j in range(6): assert approx_equal( (fd_ds_dp[j] - an_ds_dp[j]), matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)), eps=1.0e-6, ), textwrap.dedent("""\ Failure comparing analytical with finite difference derivatives. Failure in try {i} failure for parameter number {j} of the orientation parameterisation with fd_ds_dp = {fd} and an_ds_dp = {an} so that difference fd_ds_dp - an_ds_dp = {diff} """).format(i=i, j=j, fd=fd_ds_dp[j], an=an_ds_dp[j], diff=fd_ds_dp[j] - an_ds_dp[j]) # 5. Test a multi-panel detector with non-coplanar panels. # place a beam at the centre of the single panel detector (need a # beam to initialise the multi-panel detector parameterisation) lim = det[0].get_image_size_mm() shift1 = lim[0] / 2.0 shift2 = lim[1] / 2.0 beam_centre = (matrix.col(det[0].get_origin()) + shift1 * matrix.col(det[0].get_fast_axis()) + shift2 * matrix.col(det[0].get_slow_axis())) beam = BeamFactory().make_beam(sample_to_source=-1.0 * beam_centre, wavelength=1.0) multi_panel_detector = make_multi_panel(det) # parameterise this detector dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam) # ensure the beam still intersects the central panel intersection = multi_panel_detector.get_ray_intersection(beam.get_s0()) assert intersection[0] == 4 # record the offsets and dir1s, dir2s offsets_before_shift = dp._offsets dir1s_before_shift = dp._dir1s dir2s_before_shift = dp._dir2s # apply a random parameter shift (~10 mm distances, ~50 mrad angles) p_vals = dp.get_param_vals() p_vals = random_param_shift(p_vals, [10, 10, 10, 50, 50, 50]) # reparameterise the detector dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam) # record the offsets and dir1s, dir2s offsets_after_shift = dp._offsets dir1s_after_shift = dp._dir1s dir2s_after_shift = dp._dir2s # ensure the offsets, dir1s and dir2s are the same. This means that # each panel in the detector moved with the others as a rigid body for a, b in zip(offsets_before_shift, offsets_after_shift): assert approx_equal(a, b, eps=1.0e-10) for a, b in zip(dir1s_before_shift, dir1s_after_shift): assert approx_equal(a, b, eps=1.0e-10) for a, b in zip(dir2s_before_shift, dir2s_after_shift): assert approx_equal(a, b, eps=1.0e-10) attempts = 5 for i in range(attempts): multi_panel_detector = make_multi_panel(det) # parameterise this detector dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam) p_vals = dp.get_param_vals() # apply a random parameter shift p_vals = random_param_shift( p_vals, [10, 10, 10, 1000.0 * pi / 18, 1000.0 * pi / 18, 1000.0 * pi / 18]) dp.set_param_vals(p_vals) # compare analytical and finite difference derivatives # get_fd_gradients will implicitly only get gradients for the # 1st panel in the detector, so explicitly get the same for the # analytical gradients for j in range(9): an_ds_dp = dp.get_ds_dp(multi_state_elt=j) fd_ds_dp = get_fd_gradients(dp, [1.0e-7] * dp.num_free(), multi_state_elt=j) for k in range(6): assert approx_equal( (fd_ds_dp[k] - matrix.sqr(an_ds_dp[k])), matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)), eps=1.0e-5, out=None, ), textwrap.dedent("""\ Failure comparing analytical with finite difference derivatives. Failure in try {i} for panel number {j] failure for parameter number {k} of the orientation parameterisation with fd_ds_dp = {fd} and an_ds_dp = {an} so that difference fd_ds_dp - an_ds_dp = {diff} """).format( i=i, j=j, k=k, fd=fd_ds_dp[k], an=an_ds_dp[k], diff=fd_ds_dp[k] - matrix.sqr(an_ds_dp[k]), )
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=list(range(1800)), deg=True, ) sweep_range = myscan.get_oscillation_range(deg=False) im_width = myscan.get_oscillation(deg=False)[1] assert sweep_range == (0.0, pi) assert approx_equal(im_width, 0.1 * pi / 180.0) # 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.0, 2.0, 2.0]) ] 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.0, 2.0, 2.0]) ] 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.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) # 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.0e5 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.0 px_size = single_panel_detector[0].get_pixel_size() var_x = flex.double(len(obs_refs), (px_size[0] / 2.0)**2) var_y = flex.double(len(obs_refs), (px_size[1] / 2.0)**2) var_phi = flex.double(len(obs_refs), (im_width / 2.0)**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, ScansExperimentsPredictor(experiments_single_panel), refman, pred_param, restraints_parameterisation=None, ) mytarget2 = LeastSquaresPositionalResidualWithRmsdCutoff( experiments_multi_panel, ScansExperimentsPredictor(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)
# place a beam at the centre of the single panel detector (need a # beam to initialise the multi-panel detector parameterisation) lim = det[0].get_image_size_mm() shift1 = lim[0] / 2. shift2 = lim[1] / 2. beam_centre = matrix.col(det[0].get_origin()) + \ shift1 * matrix.col(det[0].get_fast_axis()) + \ shift2 * matrix.col(det[0].get_slow_axis()) beam = beam_factory().make_beam(sample_to_source=-1. * beam_centre, wavelength=1.0) multi_panel_detector = make_multi_panel(det) # parameterise this detector dp = DetectorParameterisationMultiPanel(multi_panel_detector, beam) # ensure the beam still intersects the central panel intersection = multi_panel_detector.get_ray_intersection(beam.get_s0()) assert intersection[0] == 4 # record the offsets and dir1s, dir2s offsets_before_shift = dp._offsets dir1s_before_shift = dp._dir1s dir2s_before_shift = dp._dir2s # apply a random parameter shift (~10 mm distances, ~50 mrad angles) p_vals = dp.get_param_vals() p_vals = random_param_shift(p_vals, [10, 10, 10, 50, 50, 50]) # reparameterise the detector
def test(init_test): single_panel_detector = init_test.experiments_single_panel.detectors()[0] multi_panel_detector = init_test.experiments_multi_panel.detectors()[0] beam = init_test.experiments_single_panel.beams()[0] gonio = init_test.experiments_single_panel.goniometers()[0] crystal = init_test.experiments_single_panel.crystals()[0] # Parameterise the models det_param = DetectorParameterisationSinglePanel(single_panel_detector) s0_param = BeamParameterisation(beam, gonio) xlo_param = CrystalOrientationParameterisation(crystal) xluc_param = CrystalUnitCellParameterisation(crystal) multi_det_param = DetectorParameterisationMultiPanel(multi_panel_detector, beam) # 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, first for the single panel detector pred_param = XYPhiPredictionParameterisation( init_test.experiments_single_panel, [det_param], [s0_param], [xlo_param], [xluc_param], ) # ... and now for the multi-panel detector pred_param2 = XYPhiPredictionParameterisation( init_test.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.0, 2.0, 2.0])] 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.0, 2.0, 2.0])] 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.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) # 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 = crystal.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(crystal.get_space_group()) S.set_orientation(orientation=newB) X = tuple([e * 1.0e5 for e in S.forward_independent_parameters()]) xluc_param.set_param_vals(X) ############################### # 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( init_test.observations_single_panel, init_test.experiments_single_panel ) refman2 = ReflectionManager( init_test.observations_multi_panel, init_test.experiments_multi_panel ) ############################### # Set up the target functions # ############################### target = LeastSquaresPositionalResidualWithRmsdCutoff( init_test.experiments_single_panel, ScansExperimentsPredictor(init_test.experiments_single_panel), refman, pred_param, restraints_parameterisation=None, ) target2 = LeastSquaresPositionalResidualWithRmsdCutoff( init_test.experiments_multi_panel, ScansExperimentsPredictor(init_test.experiments_multi_panel), refman2, pred_param2, restraints_parameterisation=None, ) ################################# # Set up the refinement engines # ################################# refiner = setup_minimiser.Extract(master_phil, target, pred_param).refiner refiner2 = setup_minimiser.Extract(master_phil, target2, pred_param2).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)
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])
def test_check_and_remove(): test = _Test() # Override the single panel model and parameterisation. This test function # exercises the code for non-hierarchical multi-panel detectors. The # hierarchical detector version is tested via test_cspad_refinement.py from dxtbx.model import Detector from dials.algorithms.refinement.parameterisation.detector_parameters import ( DetectorParameterisationMultiPanel, ) from dials.test.algorithms.refinement.test_multi_panel_detector_parameterisation import ( make_panel_in_array, ) multi_panel_detector = Detector() for x in range(3): for y in range(3): new_panel = make_panel_in_array((x, y), test.detector[0]) multi_panel_detector.add_panel(new_panel) test.detector = multi_panel_detector test.stills_experiments[0].detector = multi_panel_detector test.det_param = DetectorParameterisationMultiPanel( multi_panel_detector, test.beam) # update the generated reflections test.generate_reflections() # Predict the reflections in place and put in a reflection manager ref_predictor = StillsExperimentsPredictor(test.stills_experiments) ref_predictor(test.reflections) test.refman = ReflectionManagerFactory.from_parameters_reflections_experiments( refman_phil_scope.extract(), test.reflections, test.stills_experiments, do_stills=True, ) test.refman.finalise() # A non-hierarchical detector does not have panel groups, thus panels are # not treated independently wrt which reflections affect their parameters. # As before, setting 137 reflections as the minimum should leave all # parameters free, and should not remove any reflections options = ar_phil_scope.extract() options.min_nref_per_parameter = 137 ar = AutoReduce( options, [test.det_param], [test.s0_param], [test.xlo_param], [test.xluc_param], gon_params=[], reflection_manager=test.refman, ) ar.check_and_remove() assert ar.det_params[0].num_free() == 6 assert ar.beam_params[0].num_free() == 3 assert ar.xl_ori_params[0].num_free() == 3 assert ar.xl_uc_params[0].num_free() == 6 assert len(ar.reflection_manager.get_obs()) == 823 # Setting reflections as the minimum should fix the detector parameters, # which removes that parameterisation. Because all reflections are recorded # on that detector, they will all be removed as well. This then affects all # other parameterisations, which will be removed. options = ar_phil_scope.extract() options.min_nref_per_parameter = 138 ar = AutoReduce( options, [test.det_param], [test.s0_param], [test.xlo_param], [test.xluc_param], gon_params=[], reflection_manager=test.refman, ) ar.check_and_remove() assert not ar.det_params assert not ar.beam_params assert not ar.xl_ori_params assert not ar.xl_uc_params assert len(ar.reflection_manager.get_obs()) == 0