def difference_rotation_matrix_and_euler_angles(crystal_a, crystal_b): from cctbx import sgtbx #assert crystal_a.get_space_group() == crystal_b.get_space_group() space_group = crystal_b.get_space_group() min_sum_euler_angles = 1e8 best_R_ab = None best_cb_op = None # iterate over space group ops to find smallest differences for i_op, op in enumerate(space_group.build_derived_laue_group().all_ops()): if op.r().determinant() < 0: continue elif not op.t().is_zero(): continue cb_op = sgtbx.change_of_basis_op(op.inverse()) crystal_b_sym = crystal_b.change_basis(cb_op) U_a = crystal_a.get_U() U_b = crystal_b_sym.get_U() assert U_a.is_r3_rotation_matrix() assert U_b.is_r3_rotation_matrix() # the rotation matrix to transform from U_a to U_b R_ab = U_b * U_a.transpose() euler_angles = euler.xyz_angles(R_ab) sum_euler_angles = sum(abs(ea) for ea in euler_angles) if sum_euler_angles < min_sum_euler_angles: min_sum_euler_angles = sum_euler_angles best_R_ab = R_ab best_cb_op = cb_op best_euler_angles = euler.xyz_angles(best_R_ab) return best_R_ab, best_euler_angles, best_cb_op
def exercise(): from dials.algorithms.indexing import compare_orientation_matrices from dxtbx.model import Crystal from cctbx import sgtbx from scitbx import matrix from scitbx.math import euler_angles as euler # 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 approx_equal( matrix.sqr(crystal_b.get_U()) * matrix.sqr(crystal_a.get_U()).transpose(), R) 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 approx_equal(best_euler_angles, euler_angles) assert best_cb_op.is_identity_op() assert approx_equal(best_R_ab, R) # 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')) crystal_b = Crystal(R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group('I 2 3')) cb_op = sgtbx.change_of_basis_op('z,x,y') crystal_b = crystal_b.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 approx_equal(best_euler_angles, euler_angles) assert best_cb_op.c() == cb_op.inverse().c() assert approx_equal(best_R_ab, R)
def exercise(): from dials.algorithms.indexing import compare_orientation_matrices from dxtbx.model.crystal import crystal_model from cctbx import sgtbx from scitbx import matrix from scitbx.math import euler_angles as euler # 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_model(real_space_a, real_space_b, real_space_c, space_group=sgtbx.space_group('P 1')) crystal_b = crystal_model(R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group('P 1')) assert approx_equal(crystal_b.get_U() * crystal_a.get_U().transpose(), R) 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 approx_equal(best_euler_angles, euler_angles) assert best_cb_op.is_identity_op() assert approx_equal(best_R_ab, R) # now see if we can deconvolute the original euler angles after applying # a change of basis to one of the crystals crystal_a = crystal_model(real_space_a, real_space_b, real_space_c, space_group=sgtbx.space_group('I 2 3')) crystal_b = crystal_model(R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group('I 2 3')) cb_op = sgtbx.change_of_basis_op('z,x,y') crystal_b = crystal_b.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 approx_equal(best_euler_angles, euler_angles) assert best_cb_op.c() == cb_op.inverse().c() assert approx_equal(best_R_ab, R)
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')) crystal_b = Crystal(R * real_space_a, R * real_space_b, R * real_space_c, space_group=sgtbx.space_group('I 2 3')) cb_op = sgtbx.change_of_basis_op('z,x,y') crystal_b = crystal_b.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)
def ersatz_misset(integrate_lp): a_s = [] b_s = [] c_s = [] for record in open(integrate_lp): if 'COORDINATES OF UNIT CELL A-AXIS' in record: a = map(float, record.split()[-3:]) a_s.append(matrix.col(a)) elif 'COORDINATES OF UNIT CELL B-AXIS' in record: b = map(float, record.split()[-3:]) b_s.append(matrix.col(b)) elif 'COORDINATES OF UNIT CELL C-AXIS' in record: c = map(float, record.split()[-3:]) c_s.append(matrix.col(c)) assert(len(a_s) == len(b_s) == len(c_s)) ub0 = matrix.sqr(a_s[0].elems + b_s[0].elems + c_s[0].elems).inverse() for j in range(len(a_s)): ub = matrix.sqr(a_s[j].elems + b_s[j].elems + c_s[j].elems).inverse() print '%7.3f %7.3f %7.3f' % tuple(xyz_angles(ub.inverse() * ub0)) return
def ersatz_misset(integrate_lp): a_s = [] b_s = [] c_s = [] for record in open(integrate_lp): if 'COORDINATES OF UNIT CELL A-AXIS' in record: a = map(float, record.split()[-3:]) a_s.append(matrix.col(a)) elif 'COORDINATES OF UNIT CELL B-AXIS' in record: b = map(float, record.split()[-3:]) b_s.append(matrix.col(b)) elif 'COORDINATES OF UNIT CELL C-AXIS' in record: c = map(float, record.split()[-3:]) c_s.append(matrix.col(c)) assert (len(a_s) == len(b_s) == len(c_s)) ub0 = matrix.sqr(a_s[0].elems + b_s[0].elems + c_s[0].elems).inverse() for j in range(len(a_s)): ub = matrix.sqr(a_s[j].elems + b_s[j].elems + c_s[j].elems).inverse() print '%7.3f %7.3f %7.3f' % tuple(xyz_angles(ub.inverse() * ub0)) return
def missets(self, phi): """Calculate the missetting angles for the given rotation angle.""" P = self._z.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) R = self._r.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) M = P.inverse() * R * self._M0 return xyz_angles(M)
def missets(self, phi): '''Calculate the missetting angles for the given rotation angle.''' P = self._z.axis_and_angle_as_r3_rotation_matrix(phi, deg = True) R = self._r.axis_and_angle_as_r3_rotation_matrix(phi, deg = True) M = P.inverse() * R * self._M0 return xyz_angles(M)
def dump_mtz_orientation(mtz_file): from iotbx import mtz from scitbx import matrix from scitbx.math.euler_angles import xyz_angles m = mtz.object(mtz_file) for b in m.batches(): rxyz = tuple(xyz_angles(matrix.sqr(b.umat()))) print(b.num(), '%7.4f %7.4f %7.4f' % rxyz)
def dump_mtz_orientation(mtz_file): from iotbx import mtz from scitbx import matrix from scitbx.math.euler_angles import xyz_angles import os.path m = mtz.object(mtz_file) for b in m.batches(): rxyz = tuple(xyz_angles(matrix.sqr(b.umat()))) print b.num(), '%7.4f %7.4f %7.4f' % rxyz return
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 ersatz_misset_predict(xparm_xds, spot_xds): '''As well as possible, try to predict the misorientation angles as a function of frame # from the indexed spots from the XDS IDXREF step. Calculation will be performed in CBF coordinae frame.''' cfc = coordinate_frame_converter(xparm_xds) axis = cfc.get_c('rotation_axis') wavelength = cfc.get('wavelength') beam = (1.0 / wavelength) * cfc.get_c('sample_to_source').normalize() U, B = cfc.get_u_b() UB = U * B detector_origin = cfc.get_c('detector_origin') detector_fast = cfc.get_c('detector_fast') detector_slow = cfc.get_c('detector_slow') pixel_size_fast, pixel_size_slow = cfc.get('detector_pixel_size_fast_slow') size_fast, size_slow = cfc.get('detector_size_fast_slow') img_start, osc_start, osc_range = parse_xds_xparm_scan_info(xparm_xds) rx_s = {} ry_s = {} rz_s = {} for record in open(spot_xds): values = map(float, record.split()) if len(values) != 7: continue hkl = tuple(map(nint, values[-3:])) if hkl == (0, 0, 0): continue x, y, f = values[:3] phi = ((f - img_start + 1) * osc_range + osc_start) * math.pi / 180.0 lab_xyz = detector_origin + \ detector_fast * x * pixel_size_fast + \ detector_slow * y * pixel_size_slow rec_xyz = ((1.0 / wavelength) * lab_xyz.normalize() + beam).rotate( axis, - phi) calc_xyz = UB * hkl # now compute vector and angle to overlay calculated position on # observed position, then convert this to a matrix shift_axis = calc_xyz.cross(rec_xyz) shift_angle = calc_xyz.angle(rec_xyz) M = matrix.sqr(r3_rotation_axis_and_angle_as_matrix( shift_axis, shift_angle)) rx, ry, rz = xyz_angles(M) j = int(f) if not j in rx_s: rx_s[j] = [] if not j in ry_s: ry_s[j] = [] if not j in rz_s: rz_s[j] = [] rx_s[j].append(rx) ry_s[j].append(ry) rz_s[j].append(rz) j = min(rx_s) ms_x0 = meansd(rx_s[j])[0] ms_y0 = meansd(ry_s[j])[0] ms_z0 = meansd(rz_s[j])[0] for j in sorted(rx_s)[1:]: ms_x = meansd(rx_s[j]) ms_y = meansd(ry_s[j]) ms_z = meansd(rz_s[j]) print '%4d %6.3f %6.3f %6.3f' % \ (j, ms_x[0] - ms_x0, ms_y[0] - ms_y0, ms_z[0] - ms_z0)
def ersatz_misset_predict(xparm_xds, spot_xds): '''As well as possible, try to predict the misorientation angles as a function of frame # from the indexed spots from the XDS IDXREF step. Calculation will be performed in CBF coordinae frame.''' cfc = coordinate_frame_converter(xparm_xds) axis = cfc.get_c('rotation_axis') wavelength = cfc.get('wavelength') beam = (1.0 / wavelength) * cfc.get_c('sample_to_source').normalize() U, B = cfc.get_u_b() UB = U * B detector_origin = cfc.get_c('detector_origin') detector_fast = cfc.get_c('detector_fast') detector_slow = cfc.get_c('detector_slow') pixel_size_fast, pixel_size_slow = cfc.get('detector_pixel_size_fast_slow') size_fast, size_slow = cfc.get('detector_size_fast_slow') img_start, osc_start, osc_range = parse_xds_xparm_scan_info(xparm_xds) rx_s = {} ry_s = {} rz_s = {} for record in open(spot_xds): values = map(float, record.split()) if len(values) != 7: continue hkl = tuple(map(nint, values[-3:])) if hkl == (0, 0, 0): continue x, y, f = values[:3] phi = ((f - img_start + 1) * osc_range + osc_start) * math.pi / 180.0 lab_xyz = detector_origin + \ detector_fast * x * pixel_size_fast + \ detector_slow * y * pixel_size_slow rec_xyz = ((1.0 / wavelength) * lab_xyz.normalize() + beam).rotate( axis, -phi) calc_xyz = UB * hkl # now compute vector and angle to overlay calculated position on # observed position, then convert this to a matrix shift_axis = calc_xyz.cross(rec_xyz) shift_angle = calc_xyz.angle(rec_xyz) M = matrix.sqr( r3_rotation_axis_and_angle_as_matrix(shift_axis, shift_angle)) rx, ry, rz = xyz_angles(M) j = int(f) if not j in rx_s: rx_s[j] = [] if not j in ry_s: ry_s[j] = [] if not j in rz_s: rz_s[j] = [] rx_s[j].append(rx) ry_s[j].append(ry) rz_s[j].append(rz) j = min(rx_s) ms_x0 = meansd(rx_s[j])[0] ms_y0 = meansd(ry_s[j])[0] ms_z0 = meansd(rz_s[j])[0] for j in sorted(rx_s)[1:]: ms_x = meansd(rx_s[j]) ms_y = meansd(ry_s[j]) ms_z = meansd(rz_s[j]) print '%4d %6.3f %6.3f %6.3f' % \ (j, ms_x[0] - ms_x0, ms_y[0] - ms_y0, ms_z[0] - ms_z0)
def run(): random_seed = 35 flex.set_random_seed(random_seed) random.seed(random_seed) data = merge_close_spots.merge_close_spots() # unit cell and space group for lysozyme known_symmetry = crystal.symmetry("78,78,37,90,90,90", "P43212") sim = data.two_color_sim merged_spot_info = data.spot_proximity(sim) merged_refl = merged_spot_info[0] detector = data.detector beams = data.beams # to make sure input crystal and indexed crystal model are the same # orientation before using the refiner A = sim['input_orientation'] A_inv = A.inverse() a = A_inv[:3] b = A_inv[3:6] c = A_inv[6:] crystinp = Crystal(a, b, c, space_group=known_symmetry.space_group()) result = index(merged_refl, detector, known_symmetry, beams) print("RESULTS ARE IN") cm = result.refined_experiments.crystals()[0] R, best_axis, best_angle, change_of_basis = difference_rotation_matrix_axis_angle( crystal_a=cm, crystal_b=crystinp) euler_angles = euler.xyz_angles(R) print "input crystal: %s" % crystinp print "Indexed crystal: %s" % cm print "rotation of: %s" % R print "euler angles:", euler_angles print "change of basis:", change_of_basis.as_hkl() # cmd_line = command_line.argument_interpreter(master_params=master_phil_scope) # working_phil = cmd_line.process_and_fetch(args=[]) params = master_phil_scope.extract() params.refinement.parameterisation.beam.fix = "all" params.refinement.parameterisation.detector.fix = "all" params.indexing.known_symmetry.space_group = known_symmetry.space_group_info( ) params.refinement.verbosity = 3 params.indexing.refinement_protocol.d_min_start = 3 params.indexing.refinement_protocol.n_macro_cycles = 1 params.indexing.known_symmetry.unit_cell = known_symmetry.unit_cell() params.indexing.multiple_lattice_search.max_lattices = 1 params.indexing.debug = True params.indexing.known_symmetry.absolute_angle_tolerance = 5.0 params.indexing.known_symmetry.relative_length_tolerance = 0.3 expts = copy.deepcopy(result.refined_experiments) expts.crystals()[0].change_basis(change_of_basis) print(expts.crystals()[0]) refined = refine(params, result.reflections, expts, verbosity=1) print(refined[0].get_experiments().crystals()[0]) # from annlib_ext import AnnAdaptor # ann = AnnAdaptor(merged_refl['xyzobs.px.value'].as_double(), dim=3, k=1) # ann.query(result.reflections['xyzobs.px.value'].as_double()+1e-6) indices_sim = change_of_basis.apply(merged_refl['set_miller_index']) id_sim = merged_refl['set_id'] # only get those that refined: idx = align_merged_and_refined_refl(merged_refl, result.refined_reflections) indices_sim = flex.miller_index([indices_sim[i] for i in idx]) id_sim = flex.int([id_sim[i] for i in idx]) indices_result = result.refined_reflections['miller_index'] id_result = result.refined_reflections['id'] correct_ind = (indices_sim == indices_result) wrong_wavelength = (id_sim != id_result) & (id_sim != 2) wrong_index = (indices_sim != indices_result) correct_wavelength = (id_sim == id_result) | (id_sim == 2) correct = correct_ind & correct_wavelength print "Correct index and wavelength: %i/%i" % (correct.count(True), len(correct)) print "Correct index but wrong wavelength: %i/%i" % ( wrong_wavelength.count(True), len(wrong_wavelength)) print "Wrong index but correct wavelength: %i/%i" % ( wrong_index.count(True), len(correct_wavelength))