def test_ScanVaryingCrystalOrientationParameterisation_random(plots=False): """Test a ScanVaryingCrystalOrientationParameterisation with random initial orientations, random parameter shifts and random times""" vmp = _TestScanVaryingModelParameterisation() attempts = 100 failures = 0 null_mat = matrix.sqr((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) for i in range(attempts): # make a new P1 random crystal and parameterise it a = random.uniform(10, 50) * vmp.random_direction_close_to( matrix.col((1, 0, 0))) b = random.uniform(10, 50) * vmp.random_direction_close_to( matrix.col((0, 1, 0))) c = random.uniform(10, 50) * vmp.random_direction_close_to( matrix.col((0, 0, 1))) xl = Crystal(a, b, c, space_group_symbol="P 1") xl_op = _TestOrientationModel(50, xl, vmp.image_range, 5) # How many parameters? num_param = xl_op.num_free() # apply random parameter shifts to the orientation (2.0 mrad each # checkpoint) p_vals = xl_op.get_param_vals() sigmas = [2.0] * len(p_vals) new_vals = random_param_shift(p_vals, sigmas) xl_op.set_param_vals(new_vals) # select random time point at which to make comparisons t = random.uniform(*vmp.image_range) xl_op.set_time_point(t) # compare analytical and finite difference derivatives xl_op_an_ds_dp = xl_op.get_ds_dp() xl_op_fd_ds_dp = get_fd_gradients(xl_op, [1.0e-6 * math.pi / 180] * num_param) for j in range(num_param): assert approx_equal((xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j]), null_mat, eps=1.0e-6), textwrap.dedent("""\ 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=xl_op_fd_ds_dp[j], an=xl_op_an_ds_dp[j], diff=xl_op_fd_ds_dp[j] - xl_op_an_ds_dp[j], )
from cctbx import uctbx from dxtbx.model import Crystal from simtbx.nanoBragg.nanoBragg_crystal import NBcrystal import numpy as np import sys if "--cuda" in sys.argv: import os os.environ["DIFFBRAGG_USE_CUDA"] = "1" ucell = (70, 60, 50, 90.0, 110, 90.0) symbol = "C121" a_real, b_real, c_real = sqr( uctbx.unit_cell( ucell).orthogonalization_matrix()).transpose().as_list_of_lists() C = Crystal(a_real, b_real, c_real, symbol) nbr = NBcrystal() nbr.dxtbx_crystal = C S = sim_data.SimData(use_default_crystal=True) S.crystal = nbr S.instantiate_diffBragg(auto_set_spotscale=True) S.D.add_diffBragg_spots() img = S.D.raw_pixels.as_numpy_array() # simulate the primitive cell directly to_p1 = C.get_space_group().info().change_of_basis_op_to_primitive_setting() Cp1 = C.change_basis(to_p1) nbr2 = NBcrystal() nbr2.dxtbx_crystal = Cp1
def dump(experiments, directory): """ Dump the experiments in mosflm format :param experiments: The experiments to dump :param directory: The directory to write to """ for i, experiment in enumerate(experiments): suffix = "" if len(experiments) > 1: suffix = "_%i" % (i + 1) sub_dir = f"{directory}{suffix}" if not os.path.isdir(sub_dir): os.makedirs(sub_dir) detector = experiment.detector beam = experiment.beam goniometer = experiment.goniometer # XXX imageset is getting the experimental geometry from the image files # rather than the input models.expt file imageset = experiment.imageset R_to_mosflm = align_reference_frame( beam.get_s0(), (1.0, 0.0, 0.0), goniometer.get_rotation_axis(), (0.0, 0.0, 1.0), ) cryst = experiment.crystal cryst = cryst.change_basis( cryst.get_space_group().info().change_of_basis_op_to_reference_setting() ) A = matrix.sqr(cryst.get_A()) A_inv = A.inverse() real_space_a = R_to_mosflm * A_inv.elems[:3] real_space_b = R_to_mosflm * A_inv.elems[3:6] real_space_c = R_to_mosflm * A_inv.elems[6:9] cryst_mosflm = Crystal( real_space_a, real_space_b, real_space_c, space_group=cryst.get_space_group(), ) A_mosflm = matrix.sqr(cryst_mosflm.get_A()) U_mosflm = matrix.sqr(cryst_mosflm.get_U()) assert U_mosflm.is_r3_rotation_matrix(), U_mosflm w = beam.get_wavelength() index_mat = os.path.join(sub_dir, "index.mat") mosflm_in = os.path.join(sub_dir, "mosflm.in") print(f"Exporting experiment to {index_mat} and {mosflm_in}") with open(index_mat, "w") as f: f.write(format_mosflm_mat(w * A_mosflm, U_mosflm, cryst.get_unit_cell())) img_dir, template = os.path.split(imageset.get_template()) symmetry = cryst_mosflm.get_space_group().type().number() beam_centre = tuple(reversed(detector[0].get_beam_centre(beam.get_s0()))) distance = detector[0].get_directed_distance() with open(mosflm_in, "w") as f: f.write( write_mosflm_input( directory=img_dir, template=template, symmetry=symmetry, beam_centre=beam_centre, distance=distance, mat_file="index.mat", ) )
def test_stills_indexer_multi_lattice_bug_MosaicSauter2014( dials_regression, tmpdir): """Problem: In stills_indexer, before calling the refine function, the experiment list contains a list of dxtbx crystal models (that are not MosaicSauter2014 models). The conversion to MosaicSauter2014 is made during the refine step when functions from nave_parameters is called. If the experiment list contains more than 1 experiment, for eg. multiple lattices, only the first crystal gets assigned mosaicity. In actuality, all crystal models should be assigned mosaicity. This test only compares whether or not all crystal models have been assigned a MosaicSauter2014 model.""" import dxtbx.model from dxtbx.model import Crystal from dxtbx.model.experiment_list import ( Experiment, ExperimentList, ExperimentListFactory, ) from dials.algorithms.indexing.stills_indexer import StillsIndexer from dials.array_family import flex from dials.command_line.stills_process import ( phil_scope as stills_process_phil_scope, ) experiment_data = os.path.join( dials_regression, "refinement_test_data", "cspad_refinement", "cspad_refined_experiments_step6_level2_300.json", ) reflection_data = os.path.join( dials_regression, "refinement_test_data", "cspad_refinement", "cspad_reflections_step7_300.pickle", ) refl = flex.reflection_table.from_file(reflection_data) explist = ExperimentListFactory.from_json_file(experiment_data, check_format=False)[0:2] reflist = refl.select( refl["id"] < 2) # Only use the first 2 for convenience # Construct crystal models that don't have mosaicity. These A,B,C values are the same # as read in from the dials_regression folder # Crystal-0 cs0 = Crystal(explist[0].crystal) exp0 = Experiment( imageset=explist[0].imageset, beam=explist[0].beam, detector=explist[0].detector, goniometer=None, scan=None, crystal=cs0, ) # Crystal-1 cs1 = Crystal(explist[1].crystal) exp1 = Experiment( imageset=explist[1].imageset, beam=explist[1].beam, detector=explist[1].detector, goniometer=None, scan=None, crystal=cs1, ) # Construct a new experiment_list that will be passed on for refinement unrefined_explist = ExperimentList([exp0, exp1]) # Get default params from stills_process and construct StillsIndexer, then run refinement params = stills_process_phil_scope.extract() SI = StillsIndexer(reflist, unrefined_explist, params=params) refined_explist, new_reflist = SI.refine(unrefined_explist, reflist) # Now check whether the models have mosaicity after stills_indexer refinement # Also check that mosaicity values are within expected limits for ii, crys in enumerate(refined_explist.crystals()): assert isinstance(crys, dxtbx.model.MosaicCrystalSauter2014) if ii == 0: assert crys.get_domain_size_ang() == pytest.approx(2242.0, rel=0.1) if ii == 1: assert crys.get_domain_size_ang() == pytest.approx(2689.0, rel=0.1)
def __init__(self, test_nave_model=False): # Set up experimental models with regular geometry from dxtbx.model import BeamFactory, DetectorFactory, GoniometerFactory # Beam along the Z axis self.beam = BeamFactory.make_beam(unit_s0=matrix.col((0, 0, 1)), wavelength=1.0) # Goniometer (used only for index generation) along X axis self.goniometer = GoniometerFactory.known_axis(matrix.col((1, 0, 0))) # Detector fast, slow along X, -Y; beam in the centre, 200 mm distance dir1 = matrix.col((1, 0, 0)) dir2 = matrix.col((0, -1, 0)) centre = matrix.col((0, 0, 200)) npx_fast = npx_slow = 1000 pix_size = 0.2 origin = centre - (0.5 * npx_fast * pix_size * dir1 + 0.5 * npx_slow * pix_size * dir2) self.detector = DetectorFactory.make_detector( "PAD", dir1, dir2, origin, (pix_size, pix_size), (npx_fast, npx_slow), (0, 1.0e6), ) # Cubic 100 A^3 crystal a = matrix.col((100, 0, 0)) b = matrix.col((0, 100, 0)) c = matrix.col((0, 0, 100)) if test_nave_model: from dxtbx.model import MosaicCrystalSauter2014 self.crystal = MosaicCrystalSauter2014(a, b, c, space_group_symbol="P 1") self.crystal.set_half_mosaicity_deg(500) self.crystal.set_domain_size_ang(0.2) else: from dxtbx.model import Crystal self.crystal = Crystal(a, b, c, space_group_symbol="P 1") # Collect these models in an Experiment (ignoring the goniometer) from dxtbx.model.experiment_list import Experiment self.experiment = Experiment( beam=self.beam, detector=self.detector, goniometer=None, scan=None, crystal=self.crystal, imageset=None, ) # Generate some reflections self.reflections = self.generate_reflections()
class Model: def __init__(self, test_nave_model=False): # Set up experimental models with regular geometry from dxtbx.model import BeamFactory, DetectorFactory, GoniometerFactory # Beam along the Z axis self.beam = BeamFactory.make_beam(unit_s0=matrix.col((0, 0, 1)), wavelength=1.0) # Goniometer (used only for index generation) along X axis self.goniometer = GoniometerFactory.known_axis(matrix.col((1, 0, 0))) # Detector fast, slow along X, -Y; beam in the centre, 200 mm distance dir1 = matrix.col((1, 0, 0)) dir2 = matrix.col((0, -1, 0)) centre = matrix.col((0, 0, 200)) npx_fast = npx_slow = 1000 pix_size = 0.2 origin = centre - (0.5 * npx_fast * pix_size * dir1 + 0.5 * npx_slow * pix_size * dir2) self.detector = DetectorFactory.make_detector( "PAD", dir1, dir2, origin, (pix_size, pix_size), (npx_fast, npx_slow), (0, 1.0e6), ) # Cubic 100 A^3 crystal a = matrix.col((100, 0, 0)) b = matrix.col((0, 100, 0)) c = matrix.col((0, 0, 100)) if test_nave_model: from dxtbx.model import MosaicCrystalSauter2014 self.crystal = MosaicCrystalSauter2014(a, b, c, space_group_symbol="P 1") self.crystal.set_half_mosaicity_deg(500) self.crystal.set_domain_size_ang(0.2) else: from dxtbx.model import Crystal self.crystal = Crystal(a, b, c, space_group_symbol="P 1") # Collect these models in an Experiment (ignoring the goniometer) from dxtbx.model.experiment_list import Experiment self.experiment = Experiment( beam=self.beam, detector=self.detector, goniometer=None, scan=None, crystal=self.crystal, imageset=None, ) # Generate some reflections self.reflections = self.generate_reflections() def generate_reflections(self): """Use reeke_model to generate indices of reflections near to the Ewald sphere that might be observed on a still image. Build a reflection_table of these.""" from cctbx.sgtbx import space_group_info space_group_type = space_group_info("P 1").group().type() # create a ReekeIndexGenerator UB = self.crystal.get_A() axis = self.goniometer.get_rotation_axis() s0 = self.beam.get_s0() # use the same UB at the beginning and end - the margin parameter ensures # we still have indices close to the Ewald sphere generated from dials.algorithms.spot_prediction import ReekeIndexGenerator r = ReekeIndexGenerator(UB, UB, space_group_type, axis, s0, dmin=1.5, margin=1) # generate indices hkl = r.to_array() nref = len(hkl) # create a reflection table from dials.array_family import flex table = flex.reflection_table() table["flags"] = flex.size_t(nref, 0) table["id"] = flex.int(nref, 0) table["panel"] = flex.size_t(nref, 0) table["miller_index"] = flex.miller_index(hkl) table["entering"] = flex.bool(nref, True) table["s1"] = flex.vec3_double(nref) table["xyzcal.mm"] = flex.vec3_double(nref) table["xyzcal.px"] = flex.vec3_double(nref) return table
class Test(object): def __init__(self, test_nave_model = False): # Set up experimental models with regular geometry from dxtbx.model import BeamFactory from dxtbx.model import GoniometerFactory from dxtbx.model import DetectorFactory # Beam along the Z axis self.beam = BeamFactory.make_beam(unit_s0 = matrix.col((0, 0, 1)), wavelength = 1.0) # Goniometer (used only for index generation) along X axis self.goniometer = GoniometerFactory.known_axis(matrix.col((1, 0, 0))) # Detector fast, slow along X, -Y; beam in the centre, 200 mm distance dir1 = matrix.col((1, 0, 0)) dir2 = matrix.col((0, -1, 0)) n = matrix.col((0, 0, 1)) centre = matrix.col((0, 0, 200)) npx_fast = npx_slow = 1000 pix_size = 0.2 origin = centre - (0.5 * npx_fast * pix_size * dir1 + 0.5 * npx_slow * pix_size * dir2) self.detector = DetectorFactory.make_detector("PAD", dir1, dir2, origin, (pix_size, pix_size), (npx_fast, npx_slow), (0, 1.e6)) # Cubic 100 A^3 crystal a = matrix.col((100, 0, 0)) b = matrix.col((0, 100, 0)) c = matrix.col((0, 0, 100)) if test_nave_model: from dxtbx.model import MosaicCrystalSauter2014 self.crystal = MosaicCrystalSauter2014(a, b, c, space_group_symbol = "P 1") self.crystal.set_half_mosaicity_deg(500) self.crystal.set_domain_size_ang(0.2) else: from dxtbx.model import Crystal self.crystal = Crystal(a, b, c, space_group_symbol = "P 1") # Collect these models in an Experiment (ignoring the goniometer) from dxtbx.model.experiment_list import Experiment self.experiment = Experiment(beam=self.beam, detector=self.detector, goniometer=None, scan=None, crystal=self.crystal, imageset=None) # Generate some reflections self.reflections = self.generate_reflections() return def generate_reflections(self): """Use reeke_model to generate indices of reflections near to the Ewald sphere that might be observed on a still image. Build a reflection_table of these.""" from cctbx.sgtbx import space_group_info space_group_type = space_group_info("P 1").group().type() # create a ReekeIndexGenerator UB = self.crystal.get_A() axis = self.goniometer.get_rotation_axis() s0 = self.beam.get_s0() dmin = 1.5 # use the same UB at the beginning and end - the margin parameter ensures # we still have indices close to the Ewald sphere generated from dials.algorithms.spot_prediction import ReekeIndexGenerator r = ReekeIndexGenerator(UB, UB, space_group_type, axis, s0, dmin=1.5, margin=1) # generate indices hkl = r.to_array() nref = len(hkl) # create a reflection table from dials.array_family import flex table = flex.reflection_table() table['flags'] = flex.size_t(nref, 0) table['id'] = flex.int(nref, 0) table['panel'] = flex.size_t(nref, 0) table['miller_index'] = flex.miller_index(hkl) table['entering'] = flex.bool(nref, True) table['s1'] = flex.vec3_double(nref) table['xyzcal.mm'] = flex.vec3_double(nref) table['xyzcal.px'] = flex.vec3_double(nref) return table def run(self): # cache objects from the model UB = matrix.sqr(self.crystal.get_A()) s0 = matrix.col(self.beam.get_s0()) es_radius = s0.length() # create the predictor and predict for reflection table from dials.algorithms.spot_prediction import StillsReflectionPredictor predictor = StillsReflectionPredictor(self.experiment) predictor.for_reflection_table(self.reflections, UB) # for every reflection, reconstruct relp rotated to the Ewald sphere (vector # r) and unrotated relp (vector q), calculate the angle between them and # compare with delpsical.rad from libtbx.test_utils import approx_equal for ref in self.reflections: r = matrix.col(ref['s1']) - s0 q = UB * matrix.col(ref['miller_index']) tst_radius = (s0 + q).length() sgn = -1 if tst_radius > es_radius else 1 delpsi = sgn*r.accute_angle(q) assert approx_equal(delpsi, ref['delpsical.rad']) print "OK" def spherical_relp(self): # cache objects from the model UB = matrix.sqr(self.crystal.get_A()) s0 = matrix.col(self.beam.get_s0()) es_radius = s0.length() # create the predictor and predict for reflection table from dials.algorithms.spot_prediction import StillsReflectionPredictor predictor = StillsReflectionPredictor(self.experiment, spherical_relp=True) predictor.for_reflection_table(self.reflections, UB) # for every reflection, reconstruct relp centre q, calculate s1 according # to the formula in stills_prediction_nave3.pdf and compare from libtbx.test_utils import approx_equal for ref in self.reflections: q = UB * matrix.col(ref['miller_index']) radicand = q.length_sq() + 2.0 * q.dot(s0) + s0.length_sq() assert radicand > 0.0 denom = sqrt(radicand) s1 = es_radius * (q + s0) / denom assert approx_equal(s1, ref['s1']) print "OK"
def test_crystal_with_scan_points(): from dxtbx.model import Crystal, CrystalFactory from scitbx import matrix real_space_a = matrix.col((35.2402102454, -7.60002142787, 22.080026774)) real_space_b = matrix.col((22.659572494, 1.47163505925, -35.6586361881)) real_space_c = matrix.col((5.29417246554, 38.9981792999, 4.97368666613)) c1 = Crystal( real_space_a=real_space_a, real_space_b=real_space_b, real_space_c=real_space_c, space_group_symbol="P 1 2/m 1") A = c1.get_A() c1.set_A_at_scan_points([A for i in range(5)]) # Set the B covariance. The values are nonsense, just ensure they are # all different from scitbx.array_family import flex cov_B = flex.double(range((9*9))) * 1e-5 c1.set_B_covariance(cov_B) cov_B.reshape(flex.grid(1, 9, 9)) cov_B_array = flex.double(flex.grid(5, 9, 9)) for i in range(5): cov_B_array[i:(i+1), :, :] = cov_B c1.set_B_covariance_at_scan_points(cov_B_array) cov_B = c1.get_B_covariance() d = c1.to_dict() c2 = CrystalFactory.from_dict(d) eps = 1e-9 for Acomp in d['A_at_scan_points']: for e1, e2 in zip(A, Acomp): assert abs(e1 - e2) <= eps for covBcomp in d['B_covariance_at_scan_points']: for e1, e2 in zip(cov_B, covBcomp): assert abs(e1 - e2) <= eps assert c1 == c2
def test_map_to_minimum_cell(): # Input and expected output input_ucs = [ (39.7413, 183.767, 140.649, 90, 90, 90), (40.16, 142.899, 92.4167, 90, 102.48, 90), (180.613, 40.1558, 142.737, 90, 90.0174, 90), ] input_sgs = ["C 2 2 21", "P 1 2 1", "C 1 2 1"] input_hkl = [ [(1, -75, -71), (1, -73, -70), (1, -71, -69)], [(14, -37, -36), (-2, -35, -46), (-3, -34, -47)], [(-31, -5, -3), (-25, -3, -3), (-42, -8, -2)], ] expected_ucs = [ (39.7413, 94.00755450320204, 140.649, 90.0, 90.0, 77.79717980856927), (40.16, 92.46399390642911, 142.899, 90.0, 90.0, 77.3882749092846), ( 40.1558, 92.51154528306184, 142.73699999999997, 89.9830147351441, 90.0, 77.46527404307477, ), ] expected_output_hkl = [ [(-1, 37, -71), (-1, 36, -70), (-1, 35, -69)], [(-14, 22, 37), (2, 48, 35), (3, 50, 34)], [(-5, 13, -3), (-3, 11, -3), (-8, 17, -2)], ] # Setup the input experiments and reflection tables expts = ExperimentList() reflections = [] for uc, sg, hkl in zip(input_ucs, input_sgs, input_hkl): uc = uctbx.unit_cell(uc) sg = sgtbx.space_group_info(sg).group() B = scitbx.matrix.sqr(uc.fractionalization_matrix()).transpose() expts.append( Experiment(crystal=Crystal(B, space_group=sg, reciprocal=True))) refl = flex.reflection_table() refl["miller_index"] = flex.miller_index(hkl) reflections.append(refl) # Actually run the method we are testing cb_ops = change_of_basis_ops_to_minimum_cell( expts, max_delta=5, relative_length_tolerance=0.05, absolute_angle_tolerance=2) cb_ops_as_xyz = [cb_op.as_xyz() for cb_op in cb_ops] # Actual cb_ops are machine dependent (sigh) assert (cb_ops_as_xyz == [ "-x+y,-2*y,z", "-x+z,-z,-y", "x+y,-2*x,z", ] or cb_ops_as_xyz == ["x-y,2*y,z", "x-z,z,-y", "-x-y,2*x,z"]) expts_min, reflections = apply_change_of_basis_ops(expts, reflections, cb_ops) # Verify that the unit cells have been transformed as expected for expt, uc in zip(expts, expected_ucs): assert expt.crystal.get_unit_cell().parameters() == pytest.approx( uc, abs=4e-2) # Space group should be set to P1 assert [ expt.crystal.get_space_group().type().number() for expt in expts_min ] == [ 1, 1, 1, ] # Verify that the reflections have been reindexed as expected # Because the exact choice of minimum cell can be platform-dependent, # compare the magnitude, but not the sign of the output hkl values for refl, expected_hkl in zip(reflections, expected_output_hkl): for hkl, e_hkl in zip(refl["miller_index"], expected_hkl): assert [abs(h) for h in hkl] == [abs(eh) for eh in e_hkl]
def test_change_of_basis_ops_to_minimum_cell_1037(mocker): # See https://github.com/dials/dials/issues/1037 input_ucs = [ ( 4.805202948916906, 12.808064769657364, 16.544899201125446, 106.45808502003258, 90.0065567098825, 100.77735674275475, ), ( 4.808011343212577, 12.821894835790472, 16.557339561965573, 106.48431244651402, 90.0252848479048, 100.77252933676507, ), ( 4.8096632137789985, 12.815648858527567, 16.55931712239122, 106.48990701341536, 90.01703141314147, 100.80397887485773, ), ( 4.807294085194974, 12.822386757910516, 16.560411742466663, 106.43185845358086, 90.02067929544215, 100.79522302759383, ), ] # Setup the input experiments and reflection tables expts = ExperimentList() for uc in input_ucs: uc = uctbx.unit_cell(uc) sg = sgtbx.space_group_info("P1").group() B = scitbx.matrix.sqr(uc.fractionalization_matrix()).transpose() expts.append( Experiment(crystal=Crystal(B, space_group=sg, reciprocal=True))) # We want to spy on the return value of this function mocker.spy(symmetry, "unit_cells_are_similar_to") # Actually run the method we are testing cb_ops = change_of_basis_ops_to_minimum_cell( expts, max_delta=5, relative_length_tolerance=0.05, absolute_angle_tolerance=2) import pytest_mock if getattr(pytest_mock, "version", "").startswith("1."): assert symmetry.unit_cells_are_similar_to.return_value is True else: assert symmetry.unit_cells_are_similar_to.spy_return is True cb_ops_as_xyz = [cb_op.as_xyz() for cb_op in cb_ops] assert len(set(cb_ops_as_xyz)) == 1 # Actual cb_ops are machine dependent (sigh) assert cb_ops_as_xyz[0] in ("x,y,z", "-x,y,-z", "x-y,-y,-z")
def test_ModelRank(): results = [ model_evaluation.Result( rmsds=(0.0269546226916153, 0.03159452239902618, 0.004208711548775884), fraction_indexed=0.9683976336148051, model_likelihood=0.95846970346759, n_indexed=19152, crystal=Crystal.from_dict( dict([ ("__id__", "crystal"), ( "real_space_a", ( -45.031874961773504, -14.833784919966813, -48.766092343826806, ), ), ( "real_space_b", (-32.15263553253188, 3.8725711269478085, 59.82290857456796), ), ( "real_space_c", (29.6683003477066, 59.732569113301565, -13.880892871529552), ), ("space_group_hall_symbol", " P 1"), ])), hkl_offset=None, ), model_evaluation.Result( rmsds=(0.0341397658828684, 0.027401396596305812, 0.00427723439147068), fraction_indexed=0.9849825554937554, model_likelihood=0.9562237490188447, n_indexed=19480, crystal=Crystal.from_dict( dict([ ("__id__", "crystal"), ( "real_space_a", (29.66830034770662, 59.73256911330157, -13.880892871529573), ), ( "real_space_b", (47.516210146598816, -48.77135532028254, 2.824076640788394), ), ( "real_space_c", ( -45.036407933560845, -14.950807536025826, -49.06808637024198, ), ), ("space_group_hall_symbol", " P 1"), ])), hkl_offset=None, ), model_evaluation.Result( rmsds=(0.30456791867888355, 0.15679214175133024, 0.009635577811258947), fraction_indexed=0.33629974212469027, model_likelihood=0.6574428619874397, n_indexed=6651, crystal=Crystal.from_dict( dict([ ("__id__", "crystal"), ( "real_space_a", ( -11.907050303571122, 34.85499418820148, 30.689745759790572, ), ), ( "real_space_b", (-56.943458237132, 19.90418665217566, -18.37834061045143), ), ( "real_space_c", (-41.63267941211685, -24.82747139443437, 44.5508337593274), ), ("space_group_hall_symbol", " P 1"), ])), hkl_offset=None, ), ] ranker = model_evaluation.ModelRankWeighted() ranker.extend(results) assert list(ranker.score_by_fraction_indexed()) == pytest.approx( [0.02449862002620243, 0.0, 1.550350501381241]) assert list(ranker.score_by_rmsd_xy()) == pytest.approx( [0.0, 0.07598423386955666, 3.044108569529155]) assert list(ranker.score_by_volume()) == pytest.approx( [0.44207271296753703, 0.45026641813391066, 0.0]) assert list(ranker.combined_scores()) == pytest.approx( [0.19602846593366663, 0.20851345109588518, 11.670183660213905]) assert (str(ranker) == """\ +-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------+ | unit_cell | volume | volume score | #indexed | % indexed | % indexed score | rmsd_xy | rmsd_xy score | overall score | |-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------| | 68.02 68.03 68.12 109.6 109.5 109.3 | 242890 | 0.44 | 19152 | 97 | 0.02 | 0.04 | 0 | 0.2 | | 68.12 68.15 68.26 109.5 109.4 109.4 | 244274 | 0.45 | 19480 | 98 | 0 | 0.04 | 0.08 | 0.21 | | 47.94 63.06 65.84 75.2 71.6 74.5 | 178786 | 0 | 6651 | 34 | 1.55 | 0.34 | 3.04 | 11.67 | +-------------------------------------+----------+----------------+------------+-------------+-------------------+-----------+-----------------+-----------------+""" ) best = ranker.best_model() assert best.n_indexed == 19152 ranker = model_evaluation.ModelRankFilter() ranker.extend(results) best = ranker.best_model() assert best.n_indexed == 19152 assert (str(ranker) == """\ +-------------------------------------+----------+-------------+--------------------+--------------+ | unit_cell | volume | n_indexed | fraction_indexed | likelihood | |-------------------------------------+----------+-------------+--------------------+--------------| | 68.02 68.03 68.12 109.6 109.5 109.3 | 242890 | 19152 | 97 | 0.96 | | 68.12 68.15 68.26 109.5 109.4 109.4 | 244274 | 19480 | 98 | 0.96 | | 47.94 63.06 65.84 75.2 71.6 74.5 | 178786 | 6651 | 34 | 0.66 | +-------------------------------------+----------+-------------+--------------------+--------------+""" )
class Simulation: def __init__(self, override_fdp=None): # Set up detector distance = 100 pixel_size = 0.1 image_size = (1000, 1000) beam_centre_mm = ( pixel_size * image_size[0] / 2, pixel_size * image_size[1] / 2, ) self.detector = DetectorFactory().simple( "CCD", distance, beam_centre_mm, "+x", "-y", (pixel_size, pixel_size), image_size, ) # Set up beam self.beam = BeamFactory().simple(wavelength=1) # Set up scan sequence_width = 90.0 osc_start = 0.0 image_width = 0.2 oscillation = (osc_start, image_width) nframes = int(math.ceil(sequence_width / image_width)) image_range = (1, nframes) exposure_times = 0.0 epochs = [0] * nframes self.scan = ScanFactory().make_scan( image_range, exposure_times, oscillation, epochs, deg=True ) # Set up goniometer self.goniometer = GoniometerFactory.known_axis(self.detector[0].get_fast_axis()) # Set up simulated structure factors self.sfall = self.fcalc_from_pdb( resolution=1.6, algorithm="direct", override_fdp=override_fdp ) # Set up crystal self.crystal = Crystal( real_space_a=(50, 0, 0), real_space_b=(0, 60, 0), real_space_c=(0, 0, 70), space_group_symbol="P1", ) axis = matrix.col( elems=(-0.14480368275412925, -0.6202131724405818, -0.7709523423610766) ) self.crystal.set_U( axis.axis_and_angle_as_r3_rotation_matrix(angle=0.625126343998969) ) def fcalc_from_pdb(self, resolution, algorithm=None, override_fdp=None): pdb_inp = pdb.input(source_info=None, lines=_pdb_lines) xray_structure = pdb_inp.xray_structure_simple() wavelength = self.beam.get_wavelength() # # take a detour to calculate anomalous contribution of every atom scatterers = xray_structure.scatterers() for sc in scatterers: expected_henke = henke.table(sc.element_symbol()).at_angstrom(wavelength) sc.fp = expected_henke.fp() sc.fdp = override_fdp if override_fdp is not None else expected_henke.fdp() # how do we do bulk solvent? primitive_xray_structure = xray_structure.primitive_setting() P1_primitive_xray_structure = primitive_xray_structure.expand_to_p1() fcalc = P1_primitive_xray_structure.structure_factors( d_min=resolution, anomalous_flag=True, algorithm=algorithm ).f_calc() return fcalc.amplitudes() def set_varying_beam(self, along="fast", npixels_drift=5): assert along in ["fast", "slow", "both"] num_scan_points = self.scan.get_num_images() + 1 s0 = matrix.col(self.beam.get_s0()) beam_centre_px = self.detector[0].get_beam_centre_px(s0) if along == "fast": start_beam_centre = ( beam_centre_px[0] - npixels_drift / 2, beam_centre_px[1], ) end_beam_centre = (beam_centre_px[0] + npixels_drift / 2, beam_centre_px[1]) elif along == "slow": start_beam_centre = ( beam_centre_px[0], beam_centre_px[1] - npixels_drift / 2, ) end_beam_centre = (beam_centre_px[0], beam_centre_px[1] + npixels_drift / 2) elif along == "both": offset = math.sqrt(2.0) * npixels_drift / 4.0 start_beam_centre = (beam_centre_px[0] - offset, beam_centre_px[1] - offset) end_beam_centre = (beam_centre_px[0] + offset, beam_centre_px[1] + offset) start_lab = matrix.col(self.detector[0].get_pixel_lab_coord(start_beam_centre)) end_lab = matrix.col(self.detector[0].get_pixel_lab_coord(end_beam_centre)) axis = start_lab.cross(end_lab).normalize() full_angle = start_lab.angle(end_lab) angle_step = full_angle / self.scan.get_num_images() angles = [e * angle_step for e in range(num_scan_points)] start_s0 = start_lab.normalize() * s0.length() s0_list = [start_s0.rotate_around_origin(axis=axis, angle=e) for e in angles] self.beam.set_s0_at_scan_points(s0_list)
# Thermolysin # uc = unit_cell((93,93,131,90,90,120.0)) # sg = space_group_info("P 61 2 2").group() # Lysozyme uc = unit_cell((77, 77, 37, 90, 90, 90)) sg = space_group_info("P 43 21 2").group() print(uc) print(sg.info()) direct_matrix = sqr(uc.orthogonalization_matrix()).transpose() crystal = Crystal( direct_matrix * col((1, 0, 0)), direct_matrix * col((0, 1, 0)), direct_matrix * col((0, 0, 1)), sg, ) co = crystal_orientation(crystal.get_A(), basis_type.reciprocal) print(crystal) print(co) ok_ops = [] bad_ops = [] def test_op(op): print("=" * 80) print("COB:", op)
os.environ["DIFFBRAGG_USE_CUDA"]="1" import numpy as np import pylab as plt from scipy.stats import linregress from scipy.spatial.transform import Rotation from simtbx.nanoBragg import sim_data from scitbx.matrix import sqr, rec from cctbx import uctbx from dxtbx.model import Crystal ucell = (70, 60, 50, 90.0, 110, 90.0) symbol = "C121" a_real, b_real, c_real = sqr(uctbx.unit_cell(ucell).orthogonalization_matrix()).transpose().as_list_of_lists() C = Crystal(a_real, b_real, c_real, symbol) # random raotation rotation = Rotation.random(num=1, random_state=101)[0] Q = rec(rotation.as_quat(), n=(4, 1)) rot_ang, rot_axis = Q.unit_quaternion_as_axis_and_angle() C.rotate_around_origin(rot_axis, rot_ang) S = sim_data.SimData(use_default_crystal=True) S.crystal.dxtbx_crystal = C S.detector = sim_data.SimData.simple_detector(180, 0.1, (1024, 1024)) S.instantiate_diffBragg(verbose=0, oversample=0, auto_set_spotscale=True) S.D.spot_scale = 100000 #S.D.oversample = 5 Ncells_def_id = 21
def test_scale_script_prepare_input(): """Test prepare_input method of scaling script.""" # test the components of the scaling script directly with a test reflection # table, experiments list and params. params, exp, reflections = generate_test_input() # try to pass in unequal number of reflections and experiments reflections.append(generate_test_reflections()) with pytest.raises(Sorry): _ = Script(params, exp, reflections) params, exp, reflections = generate_test_input() # Try to use use_datasets when not identifiers set params.dataset_selection.use_datasets = ["0"] with pytest.raises(Sorry): _ = Script(params, exp, reflections) # Try to use use_datasets when not identifiers set params.dataset_selection.use_datasets = None params.dataset_selection.exclude_datasets = ["0"] with pytest.raises(Sorry): _ = Script(params, exp, reflections) # Now make two experiments with identifiers and select on them params, exp, reflections = generate_test_input(n=2) exp[0].identifier = "0" reflections[0].experiment_identifiers()[0] = "0" exp[1].identifier = "1" reflections[1].experiment_identifiers()[0] = "1" list1 = ExperimentList().append(exp[0]) list2 = ExperimentList().append(exp[1]) reflections[0].assert_experiment_identifiers_are_consistent(list1) reflections[1].assert_experiment_identifiers_are_consistent(list2) params.dataset_selection.use_datasets = ["0"] params, exp, script_reflections = Script.prepare_input( params, exp, reflections) assert len(script_reflections) == 1 # Try again, this time excluding params, exp, reflections = generate_test_input(n=2) exp[0].identifier = "0" reflections[0].experiment_identifiers()[0] = "0" exp[1].identifier = "1" reflections[1].experiment_identifiers()[0] = "1" params.dataset_selection.exclude_datasets = ["0"] params, exp, script_reflections = Script.prepare_input( params, exp, reflections) assert len(script_reflections) == 1 assert script_reflections[0] is reflections[1] # Try having two unequal space groups params, exp, reflections = generate_test_input(n=2) exp_dict = { "__id__": "crystal", "real_space_a": [1.0, 0.0, 0.0], "real_space_b": [0.0, 1.0, 0.0], "real_space_c": [0.0, 0.0, 2.0], "space_group_hall_symbol": " P 1", } crystal = Crystal.from_dict(exp_dict) exp[0].crystal = crystal with pytest.raises(Sorry): _ = Script.prepare_input(params, exp, reflections) # Test cutting data params, exp, reflections = generate_test_input(n=1) params.cut_data.d_min = 1.5 params, _, script_reflections = Script.prepare_input( params, exp, reflections) r = script_reflections[0] assert list(r.get_flags(r.flags.user_excluded_in_scaling)) == [ False, False, True, True, ] params.cut_data.d_max = 2.25 params, _, script_reflections = Script.prepare_input( params, exp, reflections) r = script_reflections[0] assert list(r.get_flags(r.flags.user_excluded_in_scaling)) == [ False, False, True, True, ] params, exp, reflections = generate_test_input(n=1) reflections[0]["partiality"] = flex.double([0.5, 0.8, 1.0, 1.0]) params.cut_data.partiality_cutoff = 0.75 _, __, script_reflections = Script.prepare_input(params, exp, reflections) r = script_reflections[0] assert list(r.get_flags(r.flags.user_excluded_in_scaling)) == [ True, False, False, False, ]
def test_compare_orientation_matrices(): # try and see if we can get back the original rotation matrix and euler angles real_space_a = matrix.col((10, 0, 0)) real_space_b = matrix.col((0, 10, 10)) real_space_c = matrix.col((0, 0, 10)) euler_angles = (1.3, 5.6, 7.8) R = matrix.sqr( euler.xyz_matrix(euler_angles[0], euler_angles[1], euler_angles[2])) crystal_a = Crystal(real_space_a, real_space_b, real_space_c, space_group=sgtbx.space_group("P 1")) crystal_b = Crystal( R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group("P 1"), ) assert (matrix.sqr(crystal_b.get_U()) * matrix.sqr(crystal_a.get_U()).transpose()).elems == pytest.approx( R.elems) ( best_R_ab, best_axis, best_angle, best_cb_op, ) = compare_orientation_matrices.difference_rotation_matrix_axis_angle( crystal_a, crystal_b) best_euler_angles = euler.xyz_angles(best_R_ab) assert best_euler_angles == pytest.approx(euler_angles) assert best_cb_op.is_identity_op() assert best_R_ab.elems == pytest.approx(R.elems) # now see if we can deconvolute the original euler angles after applying # a change of basis to one of the crystals crystal_a = Crystal(real_space_a, real_space_b, real_space_c, space_group=sgtbx.space_group("I 2 3")) cb_op = sgtbx.change_of_basis_op("z,x,y") crystal_b = Crystal( R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group("I 2 3"), ).change_basis(cb_op) ( best_R_ab, best_axis, best_angle, best_cb_op, ) = compare_orientation_matrices.difference_rotation_matrix_axis_angle( crystal_a, crystal_b) best_euler_angles = euler.xyz_angles(best_R_ab) assert best_euler_angles == pytest.approx(euler_angles) assert best_cb_op.c() == cb_op.inverse().c() assert best_R_ab.elems == pytest.approx(R.elems) crystal_c = crystal_b.change_basis(sgtbx.change_of_basis_op("-y,-z,x")) assert crystal_c != crystal_b s = compare_orientation_matrices.rotation_matrix_differences( [crystal_a, crystal_b, crystal_c], comparison="pairwise") s = "\n".join(s.splitlines()[:-1]).replace("-0.000", "0.000") print(s) assert (s == """\ Change of basis op: b,c,a Rotation matrix to transform crystal 1 to crystal 2: {{0.986, -0.135, 0.098}, {0.138, 0.990, -0.023}, {-0.094, 0.036, 0.995}} Rotation of 9.738 degrees about axis (0.172, 0.565, 0.807) Change of basis op: -a,-b,c Rotation matrix to transform crystal 1 to crystal 3: {{0.986, -0.135, 0.098}, {0.138, 0.990, -0.023}, {-0.094, 0.036, 0.995}} Rotation of 9.738 degrees about axis (0.172, 0.565, 0.807) Change of basis op: c,-a,-b Rotation matrix to transform crystal 2 to crystal 3: {{1.000, 0.000, 0.000}, {0.000, 1.000, 0.000}, {0.000, 0.000, 1.000}}""") s = compare_orientation_matrices.rotation_matrix_differences( [crystal_a, crystal_b, crystal_c], comparison="sequential") s = "\n".join(s.splitlines()[:-1]).replace("-0.000", "0.000") print(s) assert (s == """\ Change of basis op: b,c,a Rotation matrix to transform crystal 1 to crystal 2: {{0.986, -0.135, 0.098}, {0.138, 0.990, -0.023}, {-0.094, 0.036, 0.995}} Rotation of 9.738 degrees about axis (0.172, 0.565, 0.807) Change of basis op: c,-a,-b Rotation matrix to transform crystal 2 to crystal 3: {{1.000, 0.000, 0.000}, {0.000, 1.000, 0.000}, {0.000, 0.000, 1.000}}""") s = compare_orientation_matrices.rotation_matrix_differences( (crystal_a, crystal_b), miller_indices=((1, 0, 0), (1, 1, 0))) assert (s == """\ Change of basis op: b,c,a Rotation matrix to transform crystal 1 to crystal 2: {{0.986, -0.135, 0.098}, {0.138, 0.990, -0.023}, {-0.094, 0.036, 0.995}} Rotation of 9.738 degrees about axis (0.172, 0.565, 0.807) (1,0,0): 15.26 deg (1,1,0): 9.12 deg """)
def load_crystal(entry): from dxtbx.model import Crystal from scitbx.array_family import flex from cctbx import uctbx import numpy # Get the sample nx_sample = get_nx_sample(entry, "sample") # Set the space group space_group_symbol = nx_sample["unit_cell_group"][()] # Get depends on if nx_sample["depends_on"][()] != ".": assert nx_sample["depends_on"][()] == str( nx_sample["transformations/phi"].name) # Read the average unit cell data average_unit_cell = flex.double(numpy.array( nx_sample["average_unit_cell"])) assert nx_sample["average_unit_cell"].attrs["angles_units"] == "deg" assert nx_sample["average_unit_cell"].attrs["length_units"] == "angstrom" assert len(average_unit_cell.all()) == 1 assert len(average_unit_cell) == 6 average_orientation_matrix = flex.double( numpy.array(nx_sample["average_orientation_matrix"])) assert len(average_orientation_matrix.all()) == 2 assert average_orientation_matrix.all()[0] == 3 assert average_orientation_matrix.all()[1] == 3 # Get the real space vectors uc = uctbx.unit_cell(tuple(average_unit_cell)) U = matrix.sqr(average_orientation_matrix) B = matrix.sqr(uc.fractionalization_matrix()).transpose() A = U * B A = A.inverse() real_space_a = A[0:3] real_space_b = A[3:6] real_space_c = A[6:9] # Read the unit cell data unit_cell = flex.double(numpy.array(nx_sample["unit_cell"])) assert nx_sample["unit_cell"].attrs["angles_units"] == "deg" assert nx_sample["unit_cell"].attrs["length_units"] == "angstrom" # Read the orientation matrix orientation_matrix = flex.double( numpy.array(nx_sample["orientation_matrix"])) assert len(unit_cell.all()) == 2 assert len(orientation_matrix.all()) == 3 assert unit_cell.all()[0] == orientation_matrix.all()[0] assert unit_cell.all()[1] == 6 assert orientation_matrix.all()[1] == 3 assert orientation_matrix.all()[2] == 3 # Construct the crystal model crystal = Crystal(real_space_a, real_space_b, real_space_c, space_group_symbol) # Sort out scan points if unit_cell.all()[0] > 1: A_list = [] for i in range(unit_cell.all()[0]): uc = uctbx.unit_cell(tuple(unit_cell[i:i + 1, :])) U = matrix.sqr(tuple(orientation_matrix[i:i + 1, :, :])) B = matrix.sqr(uc.fractionalization_matrix()).transpose() A_list.append(U * B) crystal.set_A_at_scan_points(A_list) else: assert unit_cell.all_eq(average_unit_cell) assert orientation_matrix.all_eq(average_orientation_matrix) # Return the crystal return crystal