예제 #1
0
def candidate_orientation_matrices(basis_vectors, max_combinations=None):

    # select unique combinations of input vectors to test
    # the order of combinations is such that combinations comprising vectors
    # nearer the beginning of the input list will appear before combinations
    # comprising vectors towards the end of the list
    n = len(basis_vectors)
    # hardcoded limit on number of vectors, fixes issue #72
    # https://github.com/dials/dials/issues/72
    n = min(n, 100)
    basis_vectors = basis_vectors[:n]
    combinations = flex.vec3_int(flex.nested_loop((n, n, n)))
    combinations = combinations.select(
        flex.sort_permutation(combinations.as_vec3_double().norms()))

    # select only those combinations where j > i and k > j
    i, j, k = combinations.as_vec3_double().parts()
    sel = flex.bool(len(combinations), True)
    sel &= j > i
    sel &= k > j
    combinations = combinations.select(sel)

    if max_combinations is not None and max_combinations < len(combinations):
        combinations = combinations[:max_combinations]

    half_pi = 0.5 * math.pi
    min_angle = 20 / 180 * math.pi  # 20 degrees, arbitrary cutoff
    for i, j, k in combinations:
        a = basis_vectors[i]
        b = basis_vectors[j]
        angle = a.angle(b)
        if angle < min_angle or (math.pi - angle) < min_angle:
            continue
        a_cross_b = a.cross(b)
        gamma = a.angle(b)
        if gamma < half_pi:
            # all angles obtuse if possible please
            b = -b
            a_cross_b = -a_cross_b
        c = basis_vectors[k]
        if abs(half_pi - a_cross_b.angle(c)) < min_angle:
            continue
        alpha = b.angle(c, deg=True)
        if alpha < half_pi:
            c = -c
        if a_cross_b.dot(c) < 0:
            # we want right-handed basis set, therefore invert all vectors
            a = -a
            b = -b
            c = -c
        model = Crystal(a, b, c, space_group_symbol="P 1")
        uc = model.get_unit_cell()
        cb_op_to_niggli = uc.change_of_basis_op_to_niggli_cell()
        model = model.change_basis(cb_op_to_niggli)

        uc = model.get_unit_cell()
        params = uc.parameters()
        if uc.volume() > (params[0] * params[1] * params[2] / 100):
            # unit cell volume cutoff from labelit 2004 paper
            yield model
예제 #2
0
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)
예제 #3
0
    def apply_symmetry(self, crystal_model):
        if not (self.target_symmetry_primitive
                and self.target_symmetry_primitive.space_group()):
            return crystal, sgtbx.change_of_basis_op()

        target_space_group = self.target_symmetry_primitive.space_group()

        A = crystal_model.get_A()

        max_delta = self._max_delta
        items = iotbx_converter(crystal_model.get_unit_cell(),
                                max_delta=max_delta)
        target_sg_ref = target_space_group.info().reference_setting().group()
        best_angular_difference = 1e8
        best_subgroup = None
        for item in items:
            if bravais_lattice(group=target_sg_ref) != bravais_lattice(
                    group=item["ref_subsym"].space_group()):
                continue
            if item["max_angular_difference"] < best_angular_difference:
                best_angular_difference = item["max_angular_difference"]
                best_subgroup = item

        if best_subgroup is None:
            return None, None

        cb_op_inp_best = best_subgroup["cb_op_inp_best"]
        orient = crystal_orientation(A, True)
        orient_best = orient.change_basis(
            scitbx.matrix.sqr(
                cb_op_inp_best.c().as_double_array()[0:9]).transpose())
        constrain_orient = orient_best.constrain(best_subgroup["system"])

        best_subsym = best_subgroup["best_subsym"]
        cb_op_best_ref = best_subsym.change_of_basis_op_to_reference_setting()
        target_sg_best = target_sg_ref.change_basis(cb_op_best_ref.inverse())
        ref_subsym = best_subsym.change_basis(cb_op_best_ref)
        cb_op_ref_primitive = ref_subsym.change_of_basis_op_to_primitive_setting(
        )
        cb_op_best_primitive = cb_op_ref_primitive * cb_op_best_ref
        cb_op_inp_primitive = cb_op_ref_primitive * cb_op_best_ref * cb_op_inp_best

        direct_matrix = constrain_orient.direct_matrix()

        a = scitbx.matrix.col(direct_matrix[:3])
        b = scitbx.matrix.col(direct_matrix[3:6])
        c = scitbx.matrix.col(direct_matrix[6:9])
        model = Crystal(a, b, c, space_group=target_sg_best)
        assert target_sg_best.is_compatible_unit_cell(model.get_unit_cell())

        model = model.change_basis(cb_op_best_primitive)
        return model, cb_op_inp_primitive
예제 #4
0
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 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())
예제 #6
0
파일: symmetry.py 프로젝트: dwpaley/dials
    def apply_symmetry(self, crystal_model):
        """Apply symmetry constraints to a crystal model.

        Returns the crystal model (with symmetry constraints applied) in the same
        setting as provided as input. The cb_op returned by the method is
        that necessary to transform that model to the user-provided
        target symmetry.

        Args:
            crystal_model (dxtbx.model.Crystal): The input crystal model to which to
              apply symmetry constraints.

        Returns: (dxtbx.model.Crystal, cctbx.sgtbx.change_of_basis_op):
        The crystal model with symmetry constraints applied, and the change_of_basis_op
        that transforms the returned model to the user-specified target symmetry.
        """
        if not (
            self.target_symmetry_primitive
            and self.target_symmetry_primitive.space_group()
        ):
            return crystal, sgtbx.change_of_basis_op()

        target_space_group = self.target_symmetry_primitive.space_group()

        A = crystal_model.get_A()

        max_delta = self._max_delta
        items = iotbx_converter(crystal_model.get_unit_cell(), max_delta=max_delta)
        target_sg_ref = target_space_group.info().reference_setting().group()
        best_angular_difference = 1e8

        best_subgroup = None
        for item in items:
            if bravais_lattice(group=target_sg_ref) != item["bravais"]:
                continue
            if item["max_angular_difference"] < best_angular_difference:
                best_angular_difference = item["max_angular_difference"]
                best_subgroup = item

        if best_subgroup is None:
            return None, None

        cb_op_inp_best = best_subgroup["cb_op_inp_best"]
        best_subsym = best_subgroup["best_subsym"]
        ref_subsym = best_subgroup["ref_subsym"]
        cb_op_ref_best = ref_subsym.change_of_basis_op_to_best_cell()
        cb_op_best_ref = cb_op_ref_best.inverse()
        cb_op_inp_ref = cb_op_best_ref * cb_op_inp_best
        cb_op_ref_inp = cb_op_inp_ref.inverse()

        orient = crystal_orientation(A, True)
        orient_ref = orient.change_basis(
            scitbx.matrix.sqr((cb_op_inp_ref).c().as_double_array()[0:9]).transpose()
        )
        constrain_orient = orient_ref.constrain(best_subgroup["system"])
        direct_matrix = constrain_orient.direct_matrix()

        a = scitbx.matrix.col(direct_matrix[:3])
        b = scitbx.matrix.col(direct_matrix[3:6])
        c = scitbx.matrix.col(direct_matrix[6:9])
        model = Crystal(a, b, c, space_group=target_sg_ref)
        assert target_sg_ref.is_compatible_unit_cell(model.get_unit_cell())

        model = model.change_basis(cb_op_ref_inp)

        if self.cb_op_inp_best is not None:
            # Then the unit cell has been provided: this is the cb_op to map to the
            # user-provided input unit cell
            return model, self.cb_op_inp_best.inverse() * cb_op_inp_best
        if not self.cb_op_ref_inp.is_identity_op():
            if self.target_symmetry_inp.space_group() == best_subsym.space_group():
                # Handle where e.g. the user has requested I2 instead of the reference C2
                return model, cb_op_inp_best
            # The user has specified a setting that is not the reference setting
            return model, self.cb_op_ref_inp * cb_op_inp_ref
        # Default to reference setting
        # This change of basis op will ensure that we get the best beta angle without
        # changing the centring (e.g. from C2 to I2)
        cb_op_ref_best = ref_subsym.change_of_basis_op_to_best_cell(
            best_monoclinic_beta=False
        )
        return model, cb_op_ref_best * cb_op_inp_ref
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
""")
예제 #8
0
    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

S2 = sim_data.SimData()
S2.crystal = nbr2
S2.instantiate_diffBragg(auto_set_spotscale=True)
S2.D.add_diffBragg_spots()
img2 = S2.D.raw_pixels.as_numpy_array()

# rescale because currently volume is computed incorrectly
img2 = img2 * S.D.spot_scale / S2.D.spot_scale

assert S.D.Omatrix == tuple(to_p1.c_inv().r().transpose().as_double())
assert S2.D.Omatrix == (1, 0, 0, 0, 1, 0, 0, 0, 1)
assert np.allclose(img, img2)