def tst_crystal_with_scan_points(self): 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)]) 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) assert (c1 == c2) print 'OK'
def test_crystal_with_scan_points(example_crystal): c1 = Crystal(**example_crystal) 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 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_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_crystal_model(): real_space_a = matrix.col((10, 0, 0)) real_space_b = matrix.col((0, 11, 0)) real_space_c = matrix.col((0, 0, 12)) model = Crystal( real_space_a=(10, 0, 0), real_space_b=(0, 11, 0), real_space_c=(0, 0, 12), space_group_symbol="P 1", ) # This doesn't work as python class uctbx.unit_cell(uctbx_ext.unit_cell) # so C++ and python classes are different types # assert isinstance(model.get_unit_cell(), uctbx.unit_cell) assert model.get_unit_cell().parameters() == (10.0, 11.0, 12.0, 90.0, 90.0, 90.0) assert approx_equal(model.get_A(), (1 / 10, 0, 0, 0, 1 / 11, 0, 0, 0, 1 / 12)) assert approx_equal( matrix.sqr(model.get_A()).inverse(), (10, 0, 0, 0, 11, 0, 0, 0, 12)) assert approx_equal(model.get_B(), model.get_A()) assert approx_equal(model.get_U(), (1, 0, 0, 0, 1, 0, 0, 0, 1)) assert approx_equal(model.get_real_space_vectors(), (real_space_a, real_space_b, real_space_c)) assert (model.get_crystal_symmetry().unit_cell().parameters() == model.get_unit_cell().parameters()) assert model.get_crystal_symmetry().space_group() == model.get_space_group( ) model2 = Crystal( real_space_a=(10, 0, 0), real_space_b=(0, 11, 0), real_space_c=(0, 0, 12), space_group_symbol="P 1", ) assert model == model2 model2a = Crystal(model.get_A(), model.get_space_group()) assert model == model2a model2b = Crystal( matrix.sqr(model.get_A()).inverse().elems, model.get_space_group().type().lookup_symbol(), reciprocal=False, ) assert model == model2b # rotate 45 degrees about x-axis R1 = matrix.sqr(( 1, 0, 0, 0, math.cos(math.pi / 4), -math.sin(math.pi / 4), 0, math.sin(math.pi / 4), math.cos(math.pi / 4), )) # rotate 30 degrees about y-axis R2 = matrix.sqr(( math.cos(math.pi / 6), 0, math.sin(math.pi / 6), 0, 1, 0, -math.sin(math.pi / 6), 0, math.cos(math.pi / 6), )) # rotate 60 degrees about z-axis R3 = matrix.sqr(( math.cos(math.pi / 3), -math.sin(math.pi / 3), 0, math.sin(math.pi / 3), math.cos(math.pi / 3), 0, 0, 0, 1, )) R = R1 * R2 * R3 model.set_U(R) # B is unchanged assert approx_equal(model.get_B(), (1 / 10, 0, 0, 0, 1 / 11, 0, 0, 0, 1 / 12)) assert approx_equal(model.get_U(), R) assert approx_equal(model.get_A(), matrix.sqr(model.get_U()) * matrix.sqr(model.get_B())) a_, b_, c_ = model.get_real_space_vectors() assert approx_equal(a_, R * real_space_a) assert approx_equal(b_, R * real_space_b) assert approx_equal(c_, R * real_space_c) assert (str(model).replace("-0.0000", " 0.0000") == """\ Crystal: Unit cell: (10.000, 11.000, 12.000, 90.000, 90.000, 90.000) Space group: P 1 U matrix: {{ 0.4330, -0.7500, 0.5000}, { 0.7891, 0.0474, -0.6124}, { 0.4356, 0.6597, 0.6124}} B matrix: {{ 0.1000, 0.0000, 0.0000}, { 0.0000, 0.0909, 0.0000}, { 0.0000, 0.0000, 0.0833}} A = UB: {{ 0.0433, -0.0682, 0.0417}, { 0.0789, 0.0043, -0.0510}, { 0.0436, 0.0600, 0.0510}} """) model.set_B((1 / 12, 0, 0, 0, 1 / 12, 0, 0, 0, 1 / 12)) assert approx_equal(model.get_unit_cell().parameters(), (12, 12, 12, 90, 90, 90)) U = matrix.sqr((0.3455, -0.2589, -0.9020, 0.8914, 0.3909, 0.2293, 0.2933, -0.8833, 0.3658)) B = matrix.sqr((1 / 13, 0, 0, 0, 1 / 13, 0, 0, 0, 1 / 13)) model.set_A(U * B) assert approx_equal(model.get_A(), U * B) assert approx_equal(model.get_U(), U, 1e-4) assert approx_equal(model.get_B(), B, 1e-5) model3 = Crystal( real_space_a=(10, 0, 0), real_space_b=(0, 11, 0), real_space_c=(0, 0, 12), space_group=sgtbx.space_group_info("P 222").group(), ) assert model3.get_space_group().type().hall_symbol() == " P 2 2" assert model != model3 # sgi_ref = sgtbx.space_group_info(number=230) model_ref = Crystal( real_space_a=(44, 0, 0), real_space_b=(0, 44, 0), real_space_c=(0, 0, 44), space_group=sgi_ref.group(), ) assert approx_equal(model_ref.get_U(), (1, 0, 0, 0, 1, 0, 0, 0, 1)) assert approx_equal(model_ref.get_B(), (1 / 44, 0, 0, 0, 1 / 44, 0, 0, 0, 1 / 44)) assert approx_equal(model_ref.get_A(), model_ref.get_B()) assert approx_equal(model_ref.get_unit_cell().parameters(), (44, 44, 44, 90, 90, 90)) a_ref, b_ref, c_ref = map(matrix.col, model_ref.get_real_space_vectors()) cb_op_to_primitive = sgi_ref.change_of_basis_op_to_primitive_setting() model_primitive = model_ref.change_basis(cb_op_to_primitive) cb_op_to_reference = (model_primitive.get_space_group().info(). change_of_basis_op_to_reference_setting()) a_prim, b_prim, c_prim = map(matrix.col, model_primitive.get_real_space_vectors()) assert (cb_op_to_primitive.as_abc() == "-1/2*a+1/2*b+1/2*c,1/2*a-1/2*b+1/2*c,1/2*a+1/2*b-1/2*c") assert approx_equal(a_prim, -1 / 2 * a_ref + 1 / 2 * b_ref + 1 / 2 * c_ref) assert approx_equal(b_prim, 1 / 2 * a_ref - 1 / 2 * b_ref + 1 / 2 * c_ref) assert approx_equal(c_prim, 1 / 2 * a_ref + 1 / 2 * b_ref - 1 / 2 * c_ref) assert cb_op_to_reference.as_abc() == "b+c,a+c,a+b" assert approx_equal(a_ref, b_prim + c_prim) assert approx_equal(b_ref, a_prim + c_prim) assert approx_equal(c_ref, a_prim + b_prim) assert approx_equal( model_primitive.get_U(), [ -0.5773502691896258, 0.40824829046386285, 0.7071067811865476, 0.5773502691896257, -0.4082482904638631, 0.7071067811865476, 0.5773502691896257, 0.8164965809277259, 0.0, ], ) assert approx_equal( model_primitive.get_B(), [ 0.0262431940540739, 0.0, 0.0, 0.00927837023781507, 0.02783511071344521, 0.0, 0.01607060866333063, 0.01607060866333063, 0.03214121732666125, ], ) assert approx_equal( model_primitive.get_A(), (0, 1 / 44, 1 / 44, 1 / 44, 0, 1 / 44, 1 / 44, 1 / 44, 0), ) assert approx_equal( model_primitive.get_unit_cell().parameters(), [ 38.1051177665153, 38.1051177665153, 38.1051177665153, 109.47122063449069, 109.47122063449069, 109.47122063449069, ], ) assert model_ref != model_primitive model_ref_recycled = model_primitive.change_basis(cb_op_to_reference) assert approx_equal(model_ref.get_U(), model_ref_recycled.get_U()) assert approx_equal(model_ref.get_B(), model_ref_recycled.get_B()) assert approx_equal(model_ref.get_A(), model_ref_recycled.get_A()) assert approx_equal( model_ref.get_unit_cell().parameters(), model_ref_recycled.get_unit_cell().parameters(), ) assert model_ref == model_ref_recycled uc = uctbx.unit_cell( (58.2567, 58.1264, 39.7093, 46.9077, 46.8612, 62.1055)) sg = sgtbx.space_group_info(symbol="P1").group() cs = crystal.symmetry(unit_cell=uc, space_group=sg) cb_op_to_minimum = cs.change_of_basis_op_to_minimum_cell() # the reciprocal matrix B = matrix.sqr(uc.fractionalization_matrix()).transpose() U = random_rotation() direct_matrix = (U * B).inverse() model = Crystal(direct_matrix[:3], direct_matrix[3:6], direct_matrix[6:9], space_group=sg) assert uc.is_similar_to(model.get_unit_cell()) uc_minimum = uc.change_basis(cb_op_to_minimum) model_minimum = model.change_basis(cb_op_to_minimum) assert uc_minimum.is_similar_to(model_minimum.get_unit_cell()) assert model_minimum != model model_minimum.update(model) assert model_minimum == model # lgtm A_static = matrix.sqr(model.get_A()) A_as_scan_points = [A_static] num_scan_points = 11 for i in range(num_scan_points - 1): A_as_scan_points.append( A_as_scan_points[-1] * matrix.sqr(euler_angles.xyz_matrix(0.1, 0.2, 0.3))) model.set_A_at_scan_points(A_as_scan_points) model_minimum = model.change_basis(cb_op_to_minimum) assert model.num_scan_points == model_minimum.num_scan_points == num_scan_points M = matrix.sqr(cb_op_to_minimum.c_inv().r().transpose().as_double()) M_inv = M.inverse() for i in range(num_scan_points): A_orig = matrix.sqr(model.get_A_at_scan_point(i)) A_min = matrix.sqr(model_minimum.get_A_at_scan_point(i)) assert approx_equal(A_min, A_orig * M_inv) assert model.get_unit_cell().parameters() == pytest.approx( (58.2567, 58.1264, 39.7093, 46.9077, 46.8612, 62.1055)) uc = uctbx.unit_cell((10, 11, 12, 91, 92, 93)) model.set_unit_cell(uc) assert model.get_unit_cell().parameters() == pytest.approx(uc.parameters())
def test_check_old_vs_new(): from dxtbx.tests.model.crystal_model_old import crystal_model_old model_1 = Crystal( real_space_a=(10, 0, 0), real_space_b=(0, 11, 0), real_space_c=(0, 0, 12), space_group_symbol="P 1", ) model_2 = crystal_model_old( real_space_a=(10, 0, 0), real_space_b=(0, 11, 0), real_space_c=(0, 0, 12), space_group_symbol="P 1", ) cov_B = matrix.sqr([1] * (9 * 9)) model_1.set_B_covariance(cov_B) model_2.set_B_covariance(cov_B) A_list = [model_1.get_A() for i in range(20)] model_1.set_A_at_scan_points(A_list) model_2.set_A_at_scan_points(A_list) A1 = model_1.get_A() A2 = model_2.get_A() U1 = model_1.get_U() U2 = model_2.get_U() B1 = model_1.get_B() B2 = model_2.get_B() UC1 = model_1.get_unit_cell() UC2 = model_2.get_unit_cell() RSV1 = model_1.get_real_space_vectors() RSV2 = model_2.get_real_space_vectors() SG1 = model_1.get_space_group() SG2 = model_2.get_space_group() assert model_1.num_scan_points == model_2.num_scan_points A_list_1 = [ model_1.get_A_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] A_list_2 = [ model_2.get_A_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] B_list_1 = [ model_1.get_B_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] B_list_2 = [ model_2.get_B_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] U_list_1 = [ model_1.get_U_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] U_list_2 = [ model_2.get_U_at_scan_point(i) for i in range(model_1.get_num_scan_points()) ] assert approx_equal(A1, A2) assert approx_equal(B1, B2) assert approx_equal(U1, U2) assert approx_equal(UC1.parameters(), UC2.parameters()) assert approx_equal(RSV1[0], RSV2[0]) assert approx_equal(RSV1[1], RSV2[1]) assert approx_equal(RSV1[2], RSV2[2]) assert str(SG1.info()) == str(SG2.info()) for i in range(model_1.get_num_scan_points()): assert approx_equal(A_list_1[i], A_list_2[i]) assert approx_equal(B_list_1[i], B_list_2[i]) assert approx_equal(U_list_1[i], U_list_2[i]) cell_sd_1 = model_1.get_cell_parameter_sd() cell_sd_2 = model_2.get_cell_parameter_sd() cell_volume_sd_1 = model_1.get_cell_volume_sd() cell_volume_sd_2 = model_2.get_cell_volume_sd() covB1 = model_1.get_B_covariance() covB2 = model_1.get_B_covariance() assert approx_equal(covB1, covB2) assert approx_equal(cell_volume_sd_1, cell_volume_sd_2) assert approx_equal(cell_sd_1, cell_sd_2)
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 = "%s%s" % (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("Exporting experiment to %s and %s" % (index_mat, 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 write_par_file(file_name, experiment): from scitbx import matrix from dxtbx.model import Crystal from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame from iotbx.mtz.extract_from_symmetry_lib import ccp4_symbol imageset = experiment.imageset detector = imageset.get_detector() goniometer = imageset.get_goniometer() beam = imageset.get_beam() scan = imageset.get_scan() 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()) B_mosflm = matrix.sqr(cryst_mosflm.get_B()) UB_mosflm = U_mosflm * B_mosflm uc_params = cryst_mosflm.get_unit_cell().parameters() assert U_mosflm.is_r3_rotation_matrix(), U_mosflm 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() polarization = R_to_mosflm * matrix.col(beam.get_polarization_normal()) rotation = matrix.col(goniometer.get_rotation_axis()) if (rotation.angle(matrix.col(detector[0].get_fast_axis())) < rotation.angle(matrix.col(detector[0].get_slow_axis()))): direction = 'FAST' else: direction = 'SLOW' rotation = R_to_mosflm * rotation # Calculate average spot diameter for SEPARATION parameter # http://xds.mpimf-heidelberg.mpg.de/html_doc/xds_parameters.html # BEAM_DIVERGENCE= # This value is approximately arctan(spot diameter/DETECTOR_DISTANCE) import math profile = experiment.profile spot_diameter = math.tan(profile.delta_b() * math.pi / 180) * distance spot_diameter_px = spot_diameter * detector[0].get_pixel_size()[0] # determine parameters for RASTER keyword # http://www.mrc-lmb.cam.ac.uk/harry/cgi-bin/keyword2.cgi?RASTER # NXS, NYS (odd integers) define the overall dimensions of the rectangular array of pixels for each spot # NXS and NYS are set to twice the spot size plus 5 pixels nxs = 2 * int(math.ceil(spot_diameter_px)) + 5 nys = nxs # NRX, NRY are the number of columns or rows of points in the background rim # NRX and NRY are set to half the spot size plus 2 pixels nrx = int(math.ceil(0.5 * spot_diameter_px)) + 2 nry = nrx # NC the corner background cut-off which corresponds to a half-square of side NC points # NC is set to the mean of the spot size in X and Y plus 4 nc = int(math.ceil(spot_diameter_px)) + 4 def space_group_symbol(space_group): symbol = ccp4_symbol(space_group.info(), lib_name='syminfo.lib', require_at_least_one_lib=False) if symbol != 'P 1': symbol = symbol.replace(' 1', '') symbol = symbol.replace(' ', '') return symbol logger.info('Saving BEST parameter file to %s' % file_name) with open(file_name, 'wb') as f: # print >> f, '# parameter file for BEST' print >> f, 'TITLE From DIALS' print >> f, 'DETECTOR PILA' print >> f, 'SITE Not set' print >> f, 'DIAMETER %6.2f' % (max( detector[0].get_image_size()) * detector[0].get_pixel_size()[0]) print >> f, 'PIXEL %s' % detector[0].get_pixel_size()[0] print >> f, 'ROTAXIS %4.2f %4.2f %4.2f' % rotation.elems, direction print >> f, 'POLAXIS %4.2f %4.2f %4.2f' % polarization.elems print >> f, 'GAIN 1.00' # correct for Pilatus images # http://strucbio.biologie.uni-konstanz.de/xdswiki/index.php/FAQ#You_said_that_the_XDS_deals_with_high_mosaicity._How_high_mosaicity_is_still_manageable.3F # http://journals.iucr.org/d/issues/2012/01/00/wd5161/index.html # Transform from XDS defintion of sigma_m to FWHM (MOSFLM mosaicity definition) print >> f, 'CMOSAIC %.2f' % (experiment.profile.sigma_m() * 2.355) print >> f, 'PHISTART %.2f' % scan.get_oscillation_range()[0] print >> f, 'PHIWIDTH %.2f' % scan.get_oscillation()[1] print >> f, 'DISTANCE %7.2f' % distance print >> f, 'WAVELENGTH %.5f' % beam.get_wavelength() print >> f, 'POLARISATION %7.5f' % beam.get_polarization_fraction() print >> f, 'SYMMETRY %s' % space_group_symbol( cryst.get_space_group()) print >> f, 'UB %9.6f %9.6f %9.6f' % UB_mosflm[:3] print >> f, ' %9.6f %9.6f %9.6f' % UB_mosflm[3:6] print >> f, ' %9.6f %9.6f %9.6f' % UB_mosflm[6:] print >> f, 'CELL %8.2f %8.2f %8.2f %6.2f %6.2f %6.2f' % uc_params print >> f, 'RASTER %i %i %i %i %i' % (nxs, nys, nc, nrx, nry) print >> f, 'SEPARATION %.3f %.3f' % (spot_diameter, spot_diameter) print >> f, 'BEAM %8.3f %8.3f' % beam_centre print >> f, '# end of parameter file for BEST'
def test_compare_example(): experiments = ExperimentListFactory.from_json(json_is, check_format=False) for experiment in experiments: header = { "DIM": "2", "DENZO_X_BEAM": "97.185", "RANK": "0", "PREFIX": "step5_000009", "BEAM_CENTER_Y": "97.13", "BEAM_CENTER_X": "97.13", "WAVELENGTH": "1.30432", "OSC_START": "0", "ADC_OFFSET": "10", "BYTE_ORDER": "little_endian", "DIRECT_SPACE_ABC": "2.7790989649304656,3.721227037283121,0.616256870237976,-4.231398741367156,1.730877297917864,1.0247061633019547,2.9848502901631253,-4.645083818143041,28.595825588147285", "OSC_RANGE": "0", "DIALS_ORIGIN": "-97.185,97.185,-50", "MOSFLM_CENTER_X": "97.13", "MOSFLM_CENTER_Y": "97.13", "CLOSE_DISTANCE": "50", "BEAMLINE": "fake", "TWOTHETA": "0", "ADXV_CENTER_Y": "96.965", "ADXV_CENTER_X": "97.185", "HEADER_BYTES": "1024", "DETECTOR_SN": "000", "DISTANCE": "50", "PHI": "0", "SIZE1": "1765", "SIZE2": "1765", "XDS_ORGX": "884", "XDS_ORGY": "884", "DENZO_Y_BEAM": "97.185", "TIME": "1", "TYPE": "unsigned_short", "PIXEL_SIZE": "0.11", } # the header of the simulated image, containing ground truth orientation rsabc = (sqr([float(v) for v in header["DIRECT_SPACE_ABC"].split(",")]) * permute.inverse()) rsa = rsabc[0:3] rsb = rsabc[3:6] rsc = rsabc[6:9] header_cryst = Crystal(rsa, rsb, rsc, "P1").change_basis(CB_OP_C_P.inverse()) header_cryst.set_space_group(experiment.crystal.get_space_group()) print("Header crystal") print(header_cryst) expt_crystal = experiment.crystal print("Integrated crystal") print(expt_crystal) header_ori = crystal_orientation.crystal_orientation( header_cryst.get_A(), crystal_orientation.basis_type.reciprocal) expt_ori = crystal_orientation.crystal_orientation( expt_crystal.get_A(), crystal_orientation.basis_type.reciprocal) print("Converted to cctbx") header_ori.show() expt_ori.show() # assert the equivalence between dxtbx crystal object and the cctbx crystal_orientation object assert approx_equal(header_cryst.get_U(), header_ori.get_U_as_sqr()) assert approx_equal(header_cryst.get_A(), header_ori.reciprocal_matrix()) assert approx_equal( header_cryst.get_B(), sqr(header_ori.unit_cell().fractionalization_matrix()).transpose(), ) assert approx_equal(expt_crystal.get_U(), expt_ori.get_U_as_sqr()) assert approx_equal(expt_crystal.get_A(), expt_ori.reciprocal_matrix()) assert approx_equal( expt_crystal.get_B(), sqr(expt_ori.unit_cell().fractionalization_matrix()).transpose(), ) cb_op_align = sqr( expt_ori.best_similarity_transformation(header_ori, 50, 1)) print("XYZ angles", cb_op_align.r3_rotation_matrix_as_x_y_z_angles(deg=True)) aligned_ori = expt_ori.change_basis(cb_op_align) U_integrated = aligned_ori.get_U_as_sqr() U_ground_truth = header_ori.get_U_as_sqr() missetting_rot = U_integrated * U_ground_truth.inverse() print("determinant", missetting_rot.determinant()) assert approx_equal(missetting_rot.determinant(), 1.0) assert missetting_rot.is_r3_rotation_matrix() ( angle, axis, ) = missetting_rot.r3_rotation_matrix_as_unit_quaternion( ).unit_quaternion_as_axis_and_angle(deg=True) print("Angular offset is %13.10f deg." % (angle)) assert approx_equal(angle, 0.2609472065)
class Model(object): 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
def run(space_group_info): datablock_json = os.path.join(dials_regression, "indexing_test_data", "i04_weak_data", "datablock_orig.json") datablock = load.datablock(datablock_json, check_format=False)[0] sweep = datablock.extract_imagesets()[0] sweep._indices = sweep._indices[:20] sweep.set_scan(sweep.get_scan()[:20]) import random space_group = space_group_info.group() unit_cell = space_group_info.any_compatible_unit_cell( volume=random.uniform(1e4, 1e6)) crystal_symmetry = crystal.symmetry(unit_cell=unit_cell, space_group=space_group) crystal_symmetry.show_summary() # the reciprocal matrix B = matrix.sqr(unit_cell.fractionalization_matrix()).transpose() U = random_rotation() A = U * B direct_matrix = A.inverse() cryst_model = Crystal(direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group) experiment = Experiment(imageset=sweep, beam=sweep.get_beam(), detector=sweep.get_detector(), goniometer=sweep.get_goniometer(), scan=sweep.get_scan(), crystal=cryst_model) predicted_reflections = flex.reflection_table.from_predictions(experiment) use_fraction = 0.3 use_sel = flex.random_selection( len(predicted_reflections), int(use_fraction * len(predicted_reflections))) predicted_reflections = predicted_reflections.select(use_sel) miller_indices = predicted_reflections['miller_index'] miller_set = miller.set(crystal_symmetry, miller_indices, anomalous_flag=True) predicted_reflections['xyzobs.mm.value'] = predicted_reflections[ 'xyzcal.mm'] predicted_reflections['id'] = flex.int(len(predicted_reflections), 0) from dials.algorithms.indexing.indexer import indexer_base indexer_base.map_centroids_to_reciprocal_space(predicted_reflections, sweep.get_detector(), sweep.get_beam(), sweep.get_goniometer()) # check that local and global indexing worked equally well in absence of errors result = compare_global_local(experiment, predicted_reflections, miller_indices) assert result.misindexed_local == 0 assert result.misindexed_global == 0 a, b, c = map(matrix.col, cryst_model.get_real_space_vectors()) relative_error = 0.02 a *= (1 + relative_error) b *= (1 + relative_error) c *= (1 + relative_error) cryst_model2 = Crystal(a, b, c, space_group=space_group) experiment.crystal = cryst_model2 result = compare_global_local(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors #assert result.misindexed_local < result.misindexed_global assert result.misindexed_local == 0 assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local)) # the reciprocal matrix A = matrix.sqr(cryst_model.get_A()) A = random_rotation(angle_max=0.03) * A direct_matrix = A.inverse() cryst_model2 = Crystal(direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group) experiment.crystal = cryst_model2 result = compare_global_local(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors assert result.misindexed_local <= result.misindexed_global, ( result.misindexed_local, result.misindexed_global) assert result.misindexed_local < 0.01 * result.correct_local assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local))
def test_compare_example(): experiments = ExperimentListFactory.from_json(json_is, check_format=False) for experiment in experiments: header = { 'DIM': '2', 'DENZO_X_BEAM': '97.185', 'RANK': '0', 'PREFIX': 'step5_000009', 'BEAM_CENTER_Y': '97.13', 'BEAM_CENTER_X': '97.13', 'WAVELENGTH': '1.30432', 'OSC_START': '0', 'ADC_OFFSET': '10', 'BYTE_ORDER': 'little_endian', 'DIRECT_SPACE_ABC': '2.7790989649304656,3.721227037283121,0.616256870237976,-4.231398741367156,1.730877297917864,1.0247061633019547,2.9848502901631253,-4.645083818143041,28.595825588147285', 'OSC_RANGE': '0', 'DIALS_ORIGIN': '-97.185,97.185,-50', 'MOSFLM_CENTER_X': '97.13', 'MOSFLM_CENTER_Y': '97.13', 'CLOSE_DISTANCE': '50', 'BEAMLINE': 'fake', 'TWOTHETA': '0', 'ADXV_CENTER_Y': '96.965', 'ADXV_CENTER_X': '97.185', 'HEADER_BYTES': '1024', 'DETECTOR_SN': '000', 'DISTANCE': '50', 'PHI': '0', 'SIZE1': '1765', 'SIZE2': '1765', 'XDS_ORGX': '884', 'XDS_ORGY': '884', 'DENZO_Y_BEAM': '97.185', 'TIME': '1', 'TYPE': 'unsigned_short', 'PIXEL_SIZE': '0.11' } # the header of the simulated image, containing ground truth orientation rsabc = sqr([float(v) for v in header['DIRECT_SPACE_ABC'].split(',') ]) * permute.inverse() rsa = rsabc[0:3] rsb = rsabc[3:6] rsc = rsabc[6:9] header_cryst = Crystal(rsa, rsb, rsc, 'P1').change_basis(CB_OP_C_P.inverse()) header_cryst.set_space_group(experiment.crystal.get_space_group()) print('Header crystal') print(header_cryst) expt_crystal = experiment.crystal print('Integrated crystal') print(expt_crystal) header_ori = crystal_orientation.crystal_orientation( header_cryst.get_A(), crystal_orientation.basis_type.reciprocal) expt_ori = crystal_orientation.crystal_orientation( expt_crystal.get_A(), crystal_orientation.basis_type.reciprocal) print('Converted to cctbx') header_ori.show() expt_ori.show() # assert the equivalence between dxtbx crystal object and the cctbx crystal_orientation object assert approx_equal(header_cryst.get_U(), header_ori.get_U_as_sqr()) assert approx_equal(header_cryst.get_A(), header_ori.reciprocal_matrix()) assert approx_equal( header_cryst.get_B(), sqr(header_ori.unit_cell().fractionalization_matrix()).transpose()) assert approx_equal(expt_crystal.get_U(), expt_ori.get_U_as_sqr()) assert approx_equal(expt_crystal.get_A(), expt_ori.reciprocal_matrix()) assert approx_equal( expt_crystal.get_B(), sqr(expt_ori.unit_cell().fractionalization_matrix()).transpose()) cb_op_align = sqr( expt_ori.best_similarity_transformation(header_ori, 50, 1)) print('XYZ angles', cb_op_align.r3_rotation_matrix_as_x_y_z_angles(deg=True)) aligned_ori = expt_ori.change_basis(cb_op_align) U_integrated = aligned_ori.get_U_as_sqr() U_ground_truth = header_ori.get_U_as_sqr() missetting_rot = U_integrated * U_ground_truth.inverse() print("determinant", missetting_rot.determinant()) assert approx_equal(missetting_rot.determinant(), 1.0) assert missetting_rot.is_r3_rotation_matrix() angle, axis = missetting_rot.r3_rotation_matrix_as_unit_quaternion( ).unit_quaternion_as_axis_and_angle(deg=True) print("Angular offset is %13.10f deg." % (angle)) assert approx_equal(angle, 0.2609472065)
def test_assign_indices(dials_regression, space_group_symbol): experiments_json = os.path.join(dials_regression, "indexing_test_data", "i04_weak_data", "datablock_orig.json") experiments = load.experiment_list(experiments_json, check_format=False) sweep = experiments.imagesets()[0] sweep = sweep[:20] # set random seeds so tests more reliable seed = 54321 random.seed(seed) flex.set_random_seed(seed) space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) space_group = space_group_info.group() unit_cell = space_group_info.any_compatible_unit_cell( volume=random.uniform(1e4, 1e6)) crystal_symmetry = crystal.symmetry(unit_cell=unit_cell, space_group=space_group) crystal_symmetry.show_summary() # the reciprocal matrix B = matrix.sqr(unit_cell.fractionalization_matrix()).transpose() U = random_rotation() A = U * B direct_matrix = A.inverse() cryst_model = Crystal( direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group, ) experiment = Experiment( imageset=sweep, beam=sweep.get_beam(), detector=sweep.get_detector(), goniometer=sweep.get_goniometer(), scan=sweep.get_scan(), crystal=cryst_model, ) predicted_reflections = flex.reflection_table.from_predictions(experiment) use_fraction = 0.3 use_sel = flex.random_selection( len(predicted_reflections), int(use_fraction * len(predicted_reflections))) predicted_reflections = predicted_reflections.select(use_sel) miller_indices = predicted_reflections["miller_index"] predicted_reflections["xyzobs.mm.value"] = predicted_reflections[ "xyzcal.mm"] predicted_reflections["id"] = flex.int(len(predicted_reflections), 0) predicted_reflections.map_centroids_to_reciprocal_space( sweep.get_detector(), sweep.get_beam(), sweep.get_goniometer()) # check that local and global indexing worked equally well in absence of errors result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) assert result.misindexed_local == 0 assert result.misindexed_global == 0 a, b, c = map(matrix.col, cryst_model.get_real_space_vectors()) relative_error = 0.02 a *= 1 + relative_error b *= 1 + relative_error c *= 1 + relative_error cryst_model2 = Crystal(a, b, c, space_group=space_group) experiment.crystal = cryst_model2 result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors # assert result.misindexed_local < result.misindexed_global assert result.misindexed_local == 0 assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local)) # the reciprocal matrix A = matrix.sqr(cryst_model.get_A()) A = random_rotation(angle_max=0.5) * A direct_matrix = A.inverse() cryst_model2 = Crystal( direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group, ) experiment.crystal = cryst_model2 result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors assert result.misindexed_local <= result.misindexed_global, ( result.misindexed_local, result.misindexed_global, ) assert result.misindexed_local < 0.01 * result.correct_local assert result.correct_local >= result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local))
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 from dxtbx.model import Crystal # 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)) self.crystal = Crystal(a, b, c, space_group_symbol="P 1") if test_nave_model: self.crystal._ML_half_mosaicity_deg = 500 self.crystal._ML_domain_size_ang = 0.2 # 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"
# 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) print("Crystal A") print_matrix(crystal.get_A()) print("cctbx A") print_matrix(co.reciprocal_matrix())