Ejemplo n.º 1
0
def reeke_model_for_use_case(phi_beg, phi_end, margin):
    """Construct a reeke_model for the geometry of the Use Case Thaumatin
  dataset, taken from the XDS XPARM. The values are hard-
  coded here so that this module does not rely on the location of that
  file."""

    axis = matrix.col([0.0, 1.0, 0.0])

    # original (unrotated) setting
    ub = matrix.sqr([
        -0.0133393674072, -0.00541609051856, -0.00367748834997,
        0.00989309470346, 0.000574825936669, -0.0054505379664,
        0.00475395109417, -0.0163935257377, 0.00102384915696
    ])
    r_beg = matrix.sqr(
        scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis,
                                                         angle=phi_beg,
                                                         deg=True))
    r_osc = matrix.sqr(
        scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis,
                                                         angle=(phi_end -
                                                                phi_beg),
                                                         deg=True))

    ub_beg = r_beg * ub
    ub_end = self._r_osc * ub_mid
    s0 = matrix.col([0.00237878589035, 1.55544539299e-16, -1.09015329696])
    dmin = 1.20117776325

    return reeke_model(ub_beg, ub_end, axis, s0, dmin, margin)
Ejemplo n.º 2
0
def reeke_model_for_use_case(phi_beg, phi_end, margin):
    """Construct a reeke_model for the geometry of the Use Case Thaumatin
  dataset, taken from the XDS XPARM. The values are hard-
  coded here so that this module does not rely on the location of that
  file."""

    axis = matrix.col([0.0, 1.0, 0.0])

    # original (unrotated) setting
    ub = matrix.sqr(
        [
            -0.0133393674072,
            -0.00541609051856,
            -0.00367748834997,
            0.00989309470346,
            0.000574825936669,
            -0.0054505379664,
            0.00475395109417,
            -0.0163935257377,
            0.00102384915696,
        ]
    )
    r_beg = matrix.sqr(scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis, angle=phi_beg, deg=True))
    r_osc = matrix.sqr(
        scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis, angle=(phi_end - phi_beg), deg=True)
    )

    ub_beg = r_beg * ub
    ub_end = self._r_osc * ub_mid
    s0 = matrix.col([0.00237878589035, 1.55544539299e-16, -1.09015329696])
    dmin = 1.20117776325

    return reeke_model(ub_beg, ub_end, axis, s0, dmin, margin)
Ejemplo n.º 3
0
 def generate_python(self, frame):
   from dials.algorithms.spot_prediction.reeke import reeke_model
   ub_beg, ub_end = self.get_ub(frame)
   r = reeke_model(ub_beg, ub_end, self.axis, self.s0, self.dmin, self.margin)
   hkl = r.generate_indices()
   hkl = [h for h in hkl if h != (0, 0, 0)]
   return sorted(hkl)
Ejemplo n.º 4
0
def regression_test():
    """Perform a regression test by comparing to indices generating
  by the brute force method used in the Use Case."""

    from rstbx.diffraction import rotation_angles
    from rstbx.diffraction import full_sphere_indices
    from cctbx.sgtbx import space_group, space_group_symbols
    from cctbx.uctbx import unit_cell

    # cubic, 50A cell, 1A radiation, 1 deg osciillation, everything ideal

    a = 50.0

    ub_beg = matrix.sqr(
        (1.0 / a, 0.0, 0.0, 0.0, 1.0 / a, 0.0, 0.0, 0.0, 1.0 / a))

    axis = matrix.col((0, 1, 0))

    r_osc = matrix.sqr(
        scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=axis,
                                                         angle=1.0,
                                                         deg=True))

    ub_end = r_osc * ub_beg

    uc = unit_cell((a, a, a, 90, 90, 90))
    sg = space_group(space_group_symbols('P23').hall())

    s0 = matrix.col((0, 0, 1))

    wavelength = 1.0
    dmin = 1.5

    indices = full_sphere_indices(unit_cell=uc,
                                  resolution_limit=dmin,
                                  space_group=sg)

    ra = rotation_angles(dmin, ub_beg, wavelength, axis)

    obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range(
        phi_start_rad=0.0 * pi / 180.0,
        phi_end_rad=1.0 * pi / 180.0,
        indices=indices)

    r = reeke_model(ub_beg, ub_end, axis, s0, dmin, 1.0)
    reeke_indices = r.generate_indices()
    #r.visualize_with_rgl()

    for oi in obs_indices:
        assert (tuple(map(int, oi)) in reeke_indices)

    #TODO Tests for an oblique cell

    print "OK"
Ejemplo n.º 5
0
def regression_test():
    """Perform a regression test by comparing to indices generating
  by the brute force method used in the Use Case."""

    from rstbx.diffraction import rotation_angles
    from rstbx.diffraction import full_sphere_indices
    from cctbx.sgtbx import space_group, space_group_symbols
    from cctbx.uctbx import unit_cell

    # cubic, 50A cell, 1A radiation, 1 deg osciillation, everything ideal

    a = 50.0

    ub_beg = matrix.sqr((1.0 / a, 0.0, 0.0, 0.0, 1.0 / a, 0.0, 0.0, 0.0, 1.0 / a))

    axis = matrix.col((0, 1, 0))

    r_osc = matrix.sqr(scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=axis, angle=1.0, deg=True))

    ub_end = r_osc * ub_beg

    uc = unit_cell((a, a, a, 90, 90, 90))
    sg = space_group(space_group_symbols("P23").hall())

    s0 = matrix.col((0, 0, 1))

    wavelength = 1.0
    dmin = 1.5

    indices = full_sphere_indices(unit_cell=uc, resolution_limit=dmin, space_group=sg)

    ra = rotation_angles(dmin, ub_beg, wavelength, axis)

    obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range(
        phi_start_rad=0.0 * pi / 180.0, phi_end_rad=1.0 * pi / 180.0, indices=indices
    )

    r = reeke_model(ub_beg, ub_end, axis, s0, dmin, 1.0)
    reeke_indices = r.generate_indices()
    # r.visualize_with_rgl()

    for oi in obs_indices:
        assert tuple(map(int, oi)) in reeke_indices

    # TODO Tests for an oblique cell

    print "OK"
Ejemplo n.º 6
0
        sys.exit(
            "Expecting either 3 or 4 arguments: path/to/xparm.xds start_phi end_phi margin=3"
        )

    else:
        # take an xparm.xds, phi_beg, phi_end and margin from the command arguments.
        from rstbx.cftbx.coordinate_frame_converter import coordinate_frame_converter

        cfc = coordinate_frame_converter(sys.argv[1])
        phi_beg, phi_end = float(sys.argv[2]), float(sys.argv[3])
        margin = int(sys.argv[4]) if len(sys.argv) == 5 else 3

        # test run for development/debugging.
        u, b = cfc.get_u_b()
        ub = matrix.sqr(u * b)
        axis = matrix.col(cfc.get("rotation_axis"))
        rub_beg = axis.axis_and_angle_as_r3_rotation_matrix(phi_beg) * ub
        rub_end = axis.axis_and_angle_as_r3_rotation_matrix(phi_end) * ub
        wavelength = cfc.get("wavelength")
        sample_to_source_vec = matrix.col(
            cfc.get_c("sample_to_source").normalize())
        s0 = (-1.0 / wavelength) * sample_to_source_vec
        dmin = 1.20117776325

        r = reeke_model(rub_beg, rub_end, axis, s0, dmin, margin)

        indices = r.generate_indices()

        for hkl in indices:
            print("%4d %4d %4d" % hkl)
Ejemplo n.º 7
0
        from libtbx.utils import Sorry

        raise Sorry("Expecting either 3 or 4 arguments: path/to/xparm.xds start_phi end_phi margin=3")

    else:

        # take an xparm.xds, phi_beg, phi_end and margin from the command arguments.
        from rstbx.cftbx.coordinate_frame_converter import coordinate_frame_converter

        cfc = coordinate_frame_converter(sys.argv[1])
        phi_beg, phi_end = float(sys.argv[2]), float(sys.argv[3])
        margin = int(sys.argv[4]) if len(sys.argv) == 5 else 3

        # test run for development/debugging.
        u, b = cfc.get_u_b()
        ub = matrix.sqr(u * b)
        axis = matrix.col(cfc.get("rotation_axis"))
        rub_beg = axis.axis_and_angle_as_r3_rotation_matrix(phi_beg) * ub
        rub_end = axis.axis_and_angle_as_r3_rotation_matrix(phi_end) * ub
        wavelength = cfc.get("wavelength")
        sample_to_source_vec = matrix.col(cfc.get_c("sample_to_source").normalize())
        s0 = (-1.0 / wavelength) * sample_to_source_vec
        dmin = 1.20117776325

        r = reeke_model(rub_beg, rub_end, axis, s0, dmin, margin)

        indices = r.generate_indices()

        for hkl in indices:
            print "%4d %4d %4d" % hkl
Ejemplo n.º 8
0
def tst_use_in_stills_parameterisation_for_crystal(crystal_param=0):

    # test use of analytical expression in stills prediction parameterisation

    from scitbx import matrix
    from math import pi, sqrt, atan2
    import random

    print
    print "Test use of analytical expressions in stills prediction " + "parameterisation for crystal parameters"

    # crystal model
    from dxtbx.model.crystal import crystal_model
    from dials.algorithms.refinement.parameterisation.crystal_parameters import (
        CrystalOrientationParameterisation,
        CrystalUnitCellParameterisation,
    )

    crystal = crystal_model((20, 0, 0), (0, 30, 0), (0, 0, 40), space_group_symbol="P 1")
    # random reorientation
    e = matrix.col((random.random(), random.random(), random.random())).normalize()
    angle = random.random() * 180
    crystal.rotate_around_origin(e, angle)

    wl = 1.1
    s0 = matrix.col((0, 0, 1 / wl))
    s0u = s0.normalize()

    # these are stills, but need a rotation axis for the Reeke algorithm
    axis = matrix.col((1, 0, 0))

    # crystal parameterisations
    xlop = CrystalOrientationParameterisation(crystal)
    xlucp = CrystalUnitCellParameterisation(crystal)

    # Find some reflections close to the Ewald sphere
    from dials.algorithms.spot_prediction.reeke import reeke_model

    U = crystal.get_U()
    B = crystal.get_B()
    UB = U * B
    dmin = 4
    hkl = reeke_model(UB, UB, axis, s0, dmin, margin=1).generate_indices()

    # choose first reflection for now, calc quantities relating to q
    h = matrix.col(hkl[0])
    q = UB * h
    q0 = q.normalize()
    q_scalar = q.length()
    qq = q_scalar * q_scalar

    # calculate the axis of closest rotation
    e1 = q0.cross(s0u).normalize()

    # calculate c0, a vector orthogonal to s0u and e1
    c0 = s0u.cross(e1).normalize()

    # calculate q1
    q1 = q0.cross(e1).normalize()

    # calculate DeltaPsi
    a = 0.5 * qq * wl
    b = sqrt(qq - a * a)
    r = -1.0 * a * s0u + b * c0
    DeltaPsi = -1.0 * atan2(r.dot(q1), r.dot(q0))

    # Checks on the reflection prediction
    from libtbx.test_utils import approx_equal

    # 1. check r is on the Ewald sphere
    s1 = s0 + r
    assert approx_equal(s1.length(), s0.length())
    # 2. check DeltaPsi is correct
    tst = q.rotate_around_origin(e1, DeltaPsi)
    assert approx_equal(tst, r)

    # choose the derivative with respect to a particular parameter.
    if crystal_param < 3:
        dU_dp = xlop.get_ds_dp()[crystal_param]
        dq = dU_dp * B * h
    else:
        dB_dp = xlucp.get_ds_dp()[crystal_param - 3]
        dq = U * dB_dp * h

    # NKS method of calculating d[q0]/dp
    q_dot_dq = q.dot(dq)
    dqq = 2.0 * q_dot_dq
    dq_scalar = dqq / q_scalar
    dq0_dp = (q_scalar * dq - (q_dot_dq * q0)) / qq
    # orthogonal to q0, as expected.
    print "NKS [q0].(d[q0]/dp) = {0} (should be 0.0)".format(q0.dot(dq0_dp))

    # intuitive method of calculating d[q0]/dp, based on the fact that
    # it must be orthogonal to q0, i.e. in the plane containing q1 and e1
    scaled = dq / q.length()
    dq0_dp = scaled.dot(q1) * q1 + scaled.dot(e1) * e1
    # orthogonal to q0, as expected.
    print "DGW [q0].(d[q0]/dp) = {0} (should be 0.0)".format(q0.dot(dq0_dp))

    # So it doesn't matter which method I use to calculate d[q0]/dp, as
    # both methods give the same results

    # use the fact that -e1 == q0.cross(q1) to redefine the derivative d[e1]/dp
    # from Sauter et al. (2014) (A.22)
    de1_dp = -1.0 * dq0_dp.cross(q1)

    # this *is* orthogonal to e1, as expected.
    print "[e1].(d[e1]/dp) = {0} (should be 0.0)".format(e1.dot(de1_dp))

    # calculate (d[r]/d[e1])(d[e1]/dp) analytically
    from scitbx.array_family import flex
    from dials_refinement_helpers_ext import dRq_de

    dr_de1 = matrix.sqr(dRq_de(flex.double([DeltaPsi]), flex.vec3_double([e1]), flex.vec3_double([q]))[0])
    print "Analytical calculation for (d[r]/d[e1])(d[e1]/dp):"
    print dr_de1 * de1_dp

    # now calculate using finite differences.
    dp = 1.0e-8
    del_e1 = de1_dp * dp
    e1f = e1 + del_e1 * 0.5
    rfwd = q.rotate_around_origin(e1f, DeltaPsi)
    e1r = e1 - del_e1 * 0.5
    rrev = q.rotate_around_origin(e1r, DeltaPsi)

    print "Finite difference estimate for (d[r]/d[e1])(d[e1]/dp):"
    print (rfwd - rrev) * (1 / dp)

    print "These are essentially the same :-)"
Ejemplo n.º 9
0
def tst_use_in_stills_parameterisation_for_crystal(crystal_param=0):

    # test use of analytical expression in stills prediction parameterisation

    from scitbx import matrix
    from math import pi, sqrt, atan2
    import random

    print()
    print("Test use of analytical expressions in stills prediction " +
          "parameterisation for crystal parameters")

    # crystal model
    from dxtbx.model.crystal import crystal_model
    from dials.algorithms.refinement.parameterisation.crystal_parameters import (
        CrystalOrientationParameterisation,
        CrystalUnitCellParameterisation,
    )

    crystal = crystal_model((20, 0, 0), (0, 30, 0), (0, 0, 40),
                            space_group_symbol="P 1")
    # random reorientation
    e = matrix.col(
        (random.random(), random.random(), random.random())).normalize()
    angle = random.random() * 180
    crystal.rotate_around_origin(e, angle)

    wl = 1.1
    s0 = matrix.col((0, 0, 1 / wl))
    s0u = s0.normalize()

    # these are stills, but need a rotation axis for the Reeke algorithm
    axis = matrix.col((1, 0, 0))

    # crystal parameterisations
    xlop = CrystalOrientationParameterisation(crystal)
    xlucp = CrystalUnitCellParameterisation(crystal)

    # Find some reflections close to the Ewald sphere
    from dials.algorithms.spot_prediction.reeke import reeke_model

    U = crystal.get_U()
    B = crystal.get_B()
    UB = U * B
    dmin = 4
    hkl = reeke_model(UB, UB, axis, s0, dmin, margin=1).generate_indices()

    # choose first reflection for now, calc quantities relating to q
    h = matrix.col(hkl[0])
    q = UB * h
    q0 = q.normalize()
    q_scalar = q.length()
    qq = q_scalar * q_scalar

    # calculate the axis of closest rotation
    e1 = q0.cross(s0u).normalize()

    # calculate c0, a vector orthogonal to s0u and e1
    c0 = s0u.cross(e1).normalize()

    # calculate q1
    q1 = q0.cross(e1).normalize()

    # calculate DeltaPsi
    a = 0.5 * qq * wl
    b = sqrt(qq - a * a)
    r = -1.0 * a * s0u + b * c0
    DeltaPsi = -1.0 * atan2(r.dot(q1), r.dot(q0))

    # Checks on the reflection prediction
    from libtbx.test_utils import approx_equal

    # 1. check r is on the Ewald sphere
    s1 = s0 + r
    assert approx_equal(s1.length(), s0.length())
    # 2. check DeltaPsi is correct
    tst = q.rotate_around_origin(e1, DeltaPsi)
    assert approx_equal(tst, r)

    # choose the derivative with respect to a particular parameter.
    if crystal_param < 3:
        dU_dp = xlop.get_ds_dp()[crystal_param]
        dq = dU_dp * B * h
    else:
        dB_dp = xlucp.get_ds_dp()[crystal_param - 3]
        dq = U * dB_dp * h

    # NKS method of calculating d[q0]/dp
    q_dot_dq = q.dot(dq)
    dqq = 2.0 * q_dot_dq
    dq_scalar = dqq / q_scalar
    dq0_dp = (q_scalar * dq - (q_dot_dq * q0)) / qq
    # orthogonal to q0, as expected.
    print("NKS [q0].(d[q0]/dp) = {0} (should be 0.0)".format(q0.dot(dq0_dp)))

    # intuitive method of calculating d[q0]/dp, based on the fact that
    # it must be orthogonal to q0, i.e. in the plane containing q1 and e1
    scaled = dq / q.length()
    dq0_dp = scaled.dot(q1) * q1 + scaled.dot(e1) * e1
    # orthogonal to q0, as expected.
    print("DGW [q0].(d[q0]/dp) = {0} (should be 0.0)".format(q0.dot(dq0_dp)))

    # So it doesn't matter which method I use to calculate d[q0]/dp, as
    # both methods give the same results

    # use the fact that -e1 == q0.cross(q1) to redefine the derivative d[e1]/dp
    # from Sauter et al. (2014) (A.22)
    de1_dp = -1.0 * dq0_dp.cross(q1)

    # this *is* orthogonal to e1, as expected.
    print("[e1].(d[e1]/dp) = {0} (should be 0.0)".format(e1.dot(de1_dp)))

    # calculate (d[r]/d[e1])(d[e1]/dp) analytically
    from scitbx.array_family import flex
    from dials_refinement_helpers_ext import dRq_de

    dr_de1 = matrix.sqr(
        dRq_de(flex.double([DeltaPsi]), flex.vec3_double([e1]),
               flex.vec3_double([q]))[0])
    print("Analytical calculation for (d[r]/d[e1])(d[e1]/dp):")
    print(dr_de1 * de1_dp)

    # now calculate using finite differences.
    dp = 1.0e-8
    del_e1 = de1_dp * dp
    e1f = e1 + del_e1 * 0.5
    rfwd = q.rotate_around_origin(e1f, DeltaPsi)
    e1r = e1 - del_e1 * 0.5
    rrev = q.rotate_around_origin(e1r, DeltaPsi)

    print("Finite difference estimate for (d[r]/d[e1])(d[e1]/dp):")
    print((rfwd - rrev) * (1 / dp))

    print("These are essentially the same :-)")