Example #1
0
def _test_random_axes_and_angles():
    # random axes
    e1, e2, e3 = [random_vector() for i in range(3)]

    # random angles
    phi1 = random.uniform(-math.pi, math.pi)
    phi2 = random.uniform(-math.pi, math.pi)
    phi3 = random.uniform(-math.pi, math.pi)

    # compose rotation matrix
    R1 = e1.axis_and_angle_as_r3_rotation_matrix(phi1, deg=False)
    R2 = e2.axis_and_angle_as_r3_rotation_matrix(phi2, deg=False)
    R3 = e3.axis_and_angle_as_r3_rotation_matrix(phi3, deg=False)
    R = R1 * R2 * R3

    # obtain solution sets
    sol1 = solve_r3_rotation_for_angles_given_axes(R, e1, e2, e3, True)
    sol2 = solve_r3_rotation_for_angles_given_axes(R, e1, e2, e3, False)

    # if either one of the solution sets is not found, indicate that this test
    # was skipped
    if sol1 is None or sol2 is None:
        return "skipped"

    # there are special solutions where rotations 1 and 3 are about the same axis.
    # solve_r3_rotation_for_angles_given_axes provides solutions where phi1 is
    # 0.0 and the rotation is fully expressed by phi3. Skip these degenerate
    # cases too.
    if sol1[0] == 0.0 and sol2[0] == 0.0:
        return "skipped"

    # one of sol1 or sol2 should match
    tst = (phi1, phi2, phi3)
    assert approx_equal(sol1, tst, out=None) or approx_equal(sol2, tst, out=None)
Example #2
0
def _test_vs_euler_angles_xyz_angles(phi1, phi2, phi3):

    from scitbx.math import euler_angles_xyz_angles

    # compose rotation matrix
    R1 = matrix.col((1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(phi1,
                                                                    deg=False)
    R2 = matrix.col((0, 1, 0)).axis_and_angle_as_r3_rotation_matrix(phi2,
                                                                    deg=False)
    R3 = matrix.col((0, 0, 1)).axis_and_angle_as_r3_rotation_matrix(phi3,
                                                                    deg=False)
    R = R1 * R2 * R3

    # get two solution sets for the principal axes
    sol1 = solve_r3_rotation_for_angles_given_axes(R, (1, 0, 0), (0, 1, 0),
                                                   (0, 0, 1),
                                                   smaller_phi2_solution=False,
                                                   deg=True)
    sol2 = solve_r3_rotation_for_angles_given_axes(R, (1, 0, 0), (0, 1, 0),
                                                   (0, 0, 1),
                                                   smaller_phi2_solution=True,
                                                   deg=True)

    # get the solution set provided by euler_angles_xyz_angles
    tst = euler_angles_xyz_angles(R)

    # one of these must match
    assert approx_equal(sol1, tst, out=None) or approx_equal(
        sol2, tst, out=None)
Example #3
0
def test_rotation_matrices(phi1, phi2, phi3):

    # compose rotation matrix
    R1 = matrix.col((1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(phi1,
                                                                    deg=False)
    R2 = matrix.col((0, 1, 0)).axis_and_angle_as_r3_rotation_matrix(phi2,
                                                                    deg=False)
    R3 = matrix.col((0, 0, 1)).axis_and_angle_as_r3_rotation_matrix(phi3,
                                                                    deg=False)
    R = R1 * R2 * R3

    # obtain the solutions
    sol1 = solve_r3_rotation_for_angles_given_axes(R, (1, 0, 0), (0, 1, 0),
                                                   (0, 0, 1),
                                                   smaller_phi2_solution=False)
    sol2 = solve_r3_rotation_for_angles_given_axes(R, (1, 0, 0), (0, 1, 0),
                                                   (0, 0, 1),
                                                   smaller_phi2_solution=True)

    # recompose these into rotation matrices
    tstR1 = matrix.col(
        (1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(sol1[0], deg=False)
    tstR1 *= matrix.col(
        (0, 1, 0)).axis_and_angle_as_r3_rotation_matrix(sol1[1], deg=False)
    tstR1 *= matrix.col(
        (0, 0, 1)).axis_and_angle_as_r3_rotation_matrix(sol1[2], deg=False)

    tstR2 = matrix.col(
        (1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(sol2[0], deg=False)
    tstR2 *= matrix.col(
        (0, 1, 0)).axis_and_angle_as_r3_rotation_matrix(sol2[1], deg=False)
    tstR2 *= matrix.col(
        (0, 0, 1)).axis_and_angle_as_r3_rotation_matrix(sol2[2], deg=False)

    # the two solution sets must reproduce the same rotation matrix
    assert approx_equal(tstR1, tstR2)

    # additionally, this matrix must be equal to the original matrix
    assert approx_equal(tstR1, R)

    # check rotated vectors
    #vec = R * matrix.col((0,0,1))
    #tstvec1 = tstR1 * matrix.col((0,0,1))
    #tstvec2 = tstR2 * matrix.col((0,0,1))
    #print R
    #print tstR1
    #print tstR2
    #print vec
    #print tstvec1
    #print tstvec2
    return
def test_rotation_matrices(phi1, phi2, phi3):

  # compose rotation matrix
  R1 = matrix.col((1,0,0)).axis_and_angle_as_r3_rotation_matrix(phi1, deg=False)
  R2 = matrix.col((0,1,0)).axis_and_angle_as_r3_rotation_matrix(phi2, deg=False)
  R3 = matrix.col((0,0,1)).axis_and_angle_as_r3_rotation_matrix(phi3, deg=False)
  R = R1*R2*R3

  # obtain the solutions
  sol1 = solve_r3_rotation_for_angles_given_axes(R, (1,0,0), (0,1,0), (0,0,1),
    smaller_phi2_solution=False)
  sol2 = solve_r3_rotation_for_angles_given_axes(R, (1,0,0), (0,1,0), (0,0,1),
    smaller_phi2_solution=True)

  # recompose these into rotation matrices
  tstR1 = matrix.col((1,0,0)).axis_and_angle_as_r3_rotation_matrix(sol1[0],
    deg=False)
  tstR1 *= matrix.col((0,1,0)).axis_and_angle_as_r3_rotation_matrix(sol1[1],
    deg=False)
  tstR1 *= matrix.col((0,0,1)).axis_and_angle_as_r3_rotation_matrix(sol1[2],
    deg=False)

  tstR2 = matrix.col((1,0,0)).axis_and_angle_as_r3_rotation_matrix(sol2[0],
    deg=False)
  tstR2 *= matrix.col((0,1,0)).axis_and_angle_as_r3_rotation_matrix(sol2[1],
    deg=False)
  tstR2 *= matrix.col((0,0,1)).axis_and_angle_as_r3_rotation_matrix(sol2[2],
    deg=False)

  # the two solution sets must reproduce the same rotation matrix
  assert approx_equal(tstR1, tstR2)

  # additionally, this matrix must be equal to the original matrix
  assert approx_equal(tstR1, R)

  # check rotated vectors
  #vec = R * matrix.col((0,0,1))
  #tstvec1 = tstR1 * matrix.col((0,0,1))
  #tstvec2 = tstR2 * matrix.col((0,0,1))
  #print R
  #print tstR1
  #print tstR2
  #print vec
  #print tstvec1
  #print tstvec2
  return
def test_vs_euler_angles_xyz_angles(phi1, phi2, phi3):

  from scitbx.math import euler_angles_xyz_angles

  # compose rotation matrix
  R1 = matrix.col((1,0,0)).axis_and_angle_as_r3_rotation_matrix(phi1, deg=False)
  R2 = matrix.col((0,1,0)).axis_and_angle_as_r3_rotation_matrix(phi2, deg=False)
  R3 = matrix.col((0,0,1)).axis_and_angle_as_r3_rotation_matrix(phi3, deg=False)
  R = R1*R2*R3

  # get two solution sets for the principal axes
  sol1 = solve_r3_rotation_for_angles_given_axes(R, (1,0,0), (0,1,0), (0,0,1),
    smaller_phi2_solution=False, deg=True)
  sol2 = solve_r3_rotation_for_angles_given_axes(R, (1,0,0), (0,1,0), (0,0,1),
    smaller_phi2_solution=True, deg=True)

  # get the solution set provided by euler_angles_xyz_angles
  tst = euler_angles_xyz_angles(R)

  # one of these must match
  assert any([approx_equal(sol1, tst, out=None),
              approx_equal(sol2, tst, out=None)])
  return
def test_random_axes_and_angles():

  # random axes
  e1, e2, e3 = [random_vector() for i in range(3)]

  # random angles
  phi1 = random.uniform(-math.pi, math.pi)
  phi2 = random.uniform(-math.pi, math.pi)
  phi3 = random.uniform(-math.pi, math.pi)

  # compose rotation matrix
  R1 = e1.axis_and_angle_as_r3_rotation_matrix(phi1, deg=False)
  R2 = e2.axis_and_angle_as_r3_rotation_matrix(phi2, deg=False)
  R3 = e3.axis_and_angle_as_r3_rotation_matrix(phi3, deg=False)
  R = R1*R2*R3

  # obtain solution sets
  sol1 = solve_r3_rotation_for_angles_given_axes(R, e1, e2, e3, True)
  sol2 = solve_r3_rotation_for_angles_given_axes(R, e1, e2, e3, False)

  # if either one of the solution sets is not found, indicate that this test
  # was skipped
  if sol1 is None or sol2 is None: return "skipped"

  # there are special solutions where rotations 1 and 3 are about the same axis.
  # solve_r3_rotation_for_angles_given_axes provides solutions where phi1 is
  # 0.0 and the rotation is fully expressed by phi3. Skip these degenerate
  # cases too.
  if sol1[0] == 0.0 and sol2[0] == 0.0: return "skipped"

  # one of sol1 or sol2 should match
  tst = (phi1, phi2, phi3)
  assert any([approx_equal(sol1, tst, out=None),
              approx_equal(sol2, tst, out=None)])

  return
Example #7
0
    def __init__(self, experiment, vectors, frame="reciprocal", mode="main"):
        from dials.util import Sorry

        self.experiment = experiment
        self.vectors = vectors
        self.frame = frame
        self.mode = mode

        gonio = experiment.goniometer

        self.s0 = matrix.col(self.experiment.beam.get_s0())
        self.rotation_axis = matrix.col(gonio.get_rotation_axis())

        from dxtbx.model import MultiAxisGoniometer

        if not isinstance(gonio, MultiAxisGoniometer):
            raise Sorry("Only MultiAxisGoniometer models supported")
        axes = gonio.get_axes()
        if len(axes) != 3:
            raise Sorry("Only 3-axis goniometers supported")
        e1, e2, e3 = (matrix.col(e) for e in reversed(axes))

        # fixed_rotation = matrix.sqr(gonio.get_fixed_rotation())
        # setting_rotation = matrix.sqr(gonio.get_setting_rotation())
        # rotation_axis = matrix.col(gonio.get_rotation_axis_datum())
        # rotation_matrix = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
        #    experiment.scan.get_oscillation()[0], deg=True
        # )

        from dials.algorithms.refinement import rotation_decomposition

        results = []

        # from https://github.com/legrandp/xdsme/blob/master/XOalign/XOalign.py#L427
        #  referential_permutations sign permutations for four permutations of
        #        parallel/antiparallel (rotation axis & beam)
        #    y1 // e1, y2 // beamVector;  y1 anti// e1, y2 // beamVector
        #    y1 // e1, y2 anti// beamVector;  y1 anti// e1, y2 anti// beamVector

        ex = matrix.col((1, 0, 0))
        ey = matrix.col((0, 1, 0))
        ez = matrix.col((0, 0, 1))

        referential_permutations = (
            [ex, ey, ez],
            [-ex, -ey, ez],
            [ex, -ey, -ez],
            [-ex, ey, -ez],
        )

        for (v1_, v2_) in self.vectors:
            result_dictionary = collections.OrderedDict()
            results.append((v1_, v2_, result_dictionary))
            space_group = self.experiment.crystal.get_space_group()
            for smx in list(space_group.smx())[:]:
                result_dictionary[smx] = []
                crystal = copy.deepcopy(self.experiment.crystal)
                cb_op = sgtbx.change_of_basis_op(smx)
                crystal = crystal.change_basis(cb_op)

                # Goniometer datum setting [D] at which the orientation was determined
                # D = (setting_rotation * rotation_matrix * fixed_rotation).inverse()

                # The setting matrix [U] will vary with the datum setting according to
                # [U] = [D] [U0]
                U = matrix.sqr(crystal.get_U())

                # XXX In DIALS recorded U is equivalent to U0 - D is applied to U inside
                # prediction
                U0 = U

                B = matrix.sqr(crystal.get_B())

                if self.frame == "direct":
                    B = B.inverse().transpose()

                v1_0 = U0 * B * v1_
                v2_0 = U0 * B * v2_

                # c  (b) The laboratory frame vectors l1 & l2 are normally specified with the
                # c MODE command: MODE MAIN (the default) sets l1 (along which v1 will be
                # c placed) along the principle goniostat axis e1 (Omega), and l2 along
                # c the beam s0. This allows rotation for instance around a principle axis.
                # c The other mode is MODE CUSP, which puts l1 (v1) perpendicular to the
                # c beam (s0) and the e1 (Omega) axis, and l2 (v2) in the plane containing
                # c l1 & e1 (ie l1 = e1 x s0, l2 = e1).

                if self.mode == "cusp":
                    l1 = self.rotation_axis.cross(self.s0)
                    l2 = self.rotation_axis
                else:
                    l1 = self.rotation_axis.normalize()
                    l3 = l1.cross(self.s0).normalize()
                    l2 = l1.cross(l3)

                for perm in referential_permutations:
                    S = matrix.sqr(perm[0].elems + perm[1].elems +
                                   perm[2].elems)
                    from rstbx.cftbx.coordinate_frame_helpers import (
                        align_reference_frame, )

                    R = align_reference_frame(v1_0, S * l1, v2_0, S * l2)

                    solutions = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
                        R, e1, e2, e3, return_both_solutions=True, deg=True)

                    if solutions is None:
                        continue

                    result_dictionary[smx].extend(solutions)

        self.all_solutions = results

        self.unique_solutions = collections.OrderedDict()
        for v1, v2, result in results:
            for solutions in result.values():
                for solution in solutions:
                    k = tuple(round(a, 3) for a in solution[1:])
                    self.unique_solutions.setdefault(k, [])
                    if all(v1 != z1 or v2 != z2
                           for z1, z2 in self.unique_solutions[k]):
                        self.unique_solutions[k].append((v1, v2))
Example #8
0
    def run(self, args=None):
        params, options = self.parser.parse_args(args, show_diff_phil=True)
        log.config(logfile="dials.complete_full_sphere.log")

        model_shadow = params.shadow

        experiments = flatten_experiments(params.input.experiments)

        if len(experiments) != 1:
            self.parser.print_help()
            return

        expt = experiments[0]

        axes = expt.goniometer.get_axes()

        if len(axes) != 3:
            sys.exit("This will only work with 3-axis goniometers")

        if not expt.imageset.reader().get_format():
            sys.exit("This will only work with images available")

        if not expt.imageset.reader().get_format().get_goniometer_shadow_masker():
            model_shadow = False

        beam = expt.beam
        det = expt.detector

        if params.resolution:
            resolution = params.resolution
        else:
            resolution = det.get_max_inscribed_resolution(expt.beam.get_s0())

        # at this point, predict all of the reflections in the scan possible (i.e.
        # extend scan to 360 degrees) - this points back to expt

        self.make_scan_360(expt.scan)

        # now get a full set of all unique miller indices
        all_indices = miller.build_set(
            crystal_symmetry=crystal.symmetry(
                space_group=expt.crystal.get_space_group(),
                unit_cell=expt.crystal.get_unit_cell(),
            ),
            anomalous_flag=True,
            d_min=resolution,
        )

        if model_shadow:
            obs, shadow = self.predict_to_miller_set_with_shadow(expt, resolution)
        else:
            obs = self.predict_to_miller_set(expt, resolution)

        logger.info(
            "Fraction of unique observations at datum: %.1f%%",
            100.0 * len(obs.indices()) / len(all_indices.indices()),
        )

        missing = all_indices.lone_set(other=obs)

        logger.info("%d unique reflections in blind region", len(missing.indices()))

        e1 = matrix.col(axes[0])
        e2 = matrix.col(axes[1])
        e3 = matrix.col(axes[2])

        s0n = matrix.col(beam.get_s0()).normalize()

        # rotate blind region about beam by +/- two theta
        two_theta = 2.0 * math.asin(0.5 * beam.get_wavelength() / resolution)
        R_ptt = s0n.axis_and_angle_as_r3_rotation_matrix(two_theta)
        R_ntt = s0n.axis_and_angle_as_r3_rotation_matrix(-two_theta)

        # now decompose to e3, e2, e1
        sol_plus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
            R_ptt, e3, e2, e1, return_both_solutions=True, deg=True
        )

        sol_minus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
            R_ntt, e3, e2, e1, return_both_solutions=True, deg=True
        )

        solutions = []
        if sol_plus:
            solutions.extend(sol_plus)
        if sol_minus:
            solutions.extend(sol_minus)

        if not solutions:
            sys.exit(f"Impossible two theta: {two_theta * 180.0 / math.pi:.3f},")

        logger.info("Maximum two theta: %.3f,", two_theta * 180.0 / math.pi)
        logger.info("%d solutions found", len(solutions))

        names = tuple(
            [n.replace("GON_", "").lower() for n in expt.goniometer.get_names()]
        )

        logger.info(" %8s %8s %8s  coverage expt.expt" % names)
        self.write_expt(experiments, "solution_0.expt")
        for j, s in enumerate(solutions):
            expt.goniometer.set_angles(s)
            if model_shadow:
                obs, shadow = self.predict_to_miller_set_with_shadow(expt, resolution)
            else:
                obs = self.predict_to_miller_set(expt, resolution)
            new = missing.common_set(obs)
            fout = "solution_%d.expt" % (j + 1)
            f = len(new.indices()) / len(missing.indices())

            logger.info("%8.3f %8.3f %8.3f %4.2f %s", s[0], s[1], s[2], f, fout)
            self.write_expt(experiments, fout)
Example #9
0
  def __init__(self, experiment, vectors, frame='reciprocal', mode='main'):
    from libtbx.utils import Sorry
    self.experiment = experiment
    self.vectors = vectors
    self.frame = frame
    self.mode = mode

    gonio = experiment.goniometer
    scan = experiment.scan

    self.s0 = matrix.col(self.experiment.beam.get_s0())
    self.rotation_axis = matrix.col(gonio.get_rotation_axis())

    from dxtbx.model import MultiAxisGoniometer
    if not isinstance(gonio, MultiAxisGoniometer):
      raise Sorry('Only MultiAxisGoniometer models supported')
    axes = gonio.get_axes()
    if len(axes) != 3:
      raise Sorry('Only 3-axis goniometers supported')
    e1, e2, e3 = (matrix.col(e) for e in axes)

    fixed_rotation = matrix.sqr(gonio.get_fixed_rotation())
    setting_rotation = matrix.sqr(gonio.get_setting_rotation())
    rotation_axis = matrix.col(gonio.get_rotation_axis_datum())
    rotation_matrix = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
      experiment.scan.get_oscillation()[0], deg=True)

    from dials.algorithms.refinement import rotation_decomposition

    results = {}

    for (v1_, v2_) in self.vectors:
      results[(v1_, v2_)] = {}
      crystal = copy.deepcopy(self.experiment.crystal)
      for smx in list(crystal.get_space_group().smx())[:]:
        cb_op = sgtbx.change_of_basis_op(smx)
        crystal = crystal.change_basis(cb_op)

        # Goniometer datum setting [D] at which the orientation was determined
        D = (setting_rotation * rotation_matrix * fixed_rotation).inverse()

        # The setting matrix [U] will vary with the datum setting according to
        # [U] = [D] [U0]
        U = crystal.get_U()

        # XXX In DIALS recorded U is equivalent to U0 - D is applied to U inside
        # prediction
        U0 = U

        B = crystal.get_B()

        if self.frame == 'direct':
          B = B.inverse().transpose()

        v1_0 = U0 * B * v1_
        v2_0 = U0 * B * v2_

        #c  (b) The laboratory frame vectors l1 & l2 are normally specified with the
        #c MODE command: MODE MAIN (the default) sets l1 (along which v1 will be
        #c placed) along the principle goniostat axis e1 (Omega), and l2 along
        #c the beam s0. This allows rotation for instance around a principle axis.
        #c The other mode is MODE CUSP, which puts l1 (v1) perpendicular to the
        #c beam (s0) and the e1 (Omega) axis, and l2 (v2) in the plane containing
        #c l1 & e1 (ie l1 = e1 x s0, l2 = e1).

        if self.mode == 'cusp':
          l1 = self.rotation_axis.cross(s0)
          l2 = self.rotation_axis
        else:
          l1 = self.rotation_axis.normalize()
          l3 = l1.cross(self.s0).normalize()
          l2 = l1.cross(l3)

        from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame
        R = align_reference_frame(v1_0, l1, v2_0, l2)

        solutions = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
          R, e1, e2, e3, return_both_solutions=True, deg=True)

        if solutions is None:
          continue

        results[(v1_, v2_)][smx] = solutions

    self.all_solutions = results

    self.unique_solutions = {}
    for (v1, v2), result in results.iteritems():
      for solutions in result.itervalues():
        for solution in solutions:
          k = tuple(round(a, 2) for a in solution[1:])
          self.unique_solutions.setdefault(k, set())
          self.unique_solutions[k].add((v1, v2))
Example #10
0
scan.set_exposure_times(exposure_times)

write_expt(expts, sys.argv[2])

# now for amusement try decomposing rotation of 90 degrees about beam to
# measure blind region - computer says no if mini kappa :(

e1 = matrix.col((1, 0, 0))
e2 = matrix.col((0.914, 0.279, -0.297))
e3 = matrix.col((1, 0, 0))

R = matrix.sqr((0, 1, 0, -1, 0, 0, 0, 0, 1))

from dials.algorithms.refinement import rotation_decomposition

solutions = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
    R, e1, e2, e3, return_both_solutions=True, deg=True)

assert solutions is None

# now try getting a rotation of two-theta about the beam - this should (i)
# be possible? and (ii) move the blind region into somewhere we can actually
# record...

R_tt = s0n.axis_and_angle_as_r3_rotation_matrix(2 * theta)

s = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
    R_tt, e1, e2, e3, return_both_solutions=False, deg=False)

# use solution

print("Using angles: %.3f %.3f" % (180 * s[1] / math.pi, 180 * s[2] / math.pi))
Example #11
0
def run(args):

  from dials.util.options import OptionParser
  from dials.util.options import flatten_experiments
  import libtbx.load_env

  usage = "%s [options] datablock.json" %(
    libtbx.env.dispatcher_name)

  parser = OptionParser(
    usage=usage,
    phil=phil_scope,
    read_experiments=True,
    check_format=False,
    epilog=help_message)

  params, options = parser.parse_args(show_diff_phil=True)
  experiments = flatten_experiments(params.input.experiments)

  if len(experiments) == 0:
    parser.print_help()
    exit(0)

  imagesets = experiments.imagesets()

  predicted_all = None
  dose = flex.size_t()

  for i_expt, expt in enumerate(experiments):
    if params.space_group is not None:
      expt.crystal.set_space_group(params.space_group.group())
    strategy = Strategy(expt, d_min=params.d_min,
                        unit_cell_scale=params.unit_cell_scale,
                        degrees_per_bin=params.degrees_per_bin,
                        min_frac_new=params.minimum_fraction_new)
    strategy.plot(prefix='strategy1_')

    expt2 = copy.deepcopy(expt)
    scan = expt2.scan
    gonio = expt2.goniometer
    angles = gonio.get_angles()
    theta_max = strategy.theta_max
    fixed_rotation = matrix.sqr(gonio.get_fixed_rotation())
    setting_rotation = matrix.sqr(gonio.get_setting_rotation())
    rotation_axis = matrix.col(gonio.get_rotation_axis_datum())
    rotation_matrix = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
      scan.get_oscillation()[0], deg=True)
    D_p = (setting_rotation * rotation_matrix * fixed_rotation)

    beam = expt2.beam
    s0 = matrix.col(beam.get_unit_s0())

    # rotate crystal by at least 2 * theta_max around axis perpendicular to
    # goniometer rotation axis
    n = rotation_axis.cross(s0)

    solutions = flex.vec3_double()
    rotation_angles = flex.double()
    for sign in (1, -1):
      i = 0
      while True:
        rot_angle = 2 * sign * (theta_max + i)
        i += 1

        R = n.axis_and_angle_as_r3_rotation_matrix(rot_angle, deg=True)

        axes = gonio.get_axes()
        assert len(axes) == 3
        e1, e2, e3 = (matrix.col(e) for e in reversed(axes))

        from dials.algorithms.refinement import rotation_decomposition
        solns = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
          R * D_p, e1, e2, e3, return_both_solutions=True, deg=True)
        if solns is not None:
          solutions.extend(flex.vec3_double(solns))
          for i in range(len(solns)):
            rotation_angles.append(rot_angle)
          break

    for rot_angle, solution in zip(rotation_angles, solutions):
      angles = reversed(solution)
      gonio.set_angles(angles)

      print()
      print("Goniometer settings to rotate crystal by %.2f degrees:" %rot_angle)
      for name, angle in zip(gonio.get_names(), gonio.get_angles()):
        print("%s: %.2f degrees" %(name, angle))
      print()

    strategy2 = Strategy(expt2, d_min=params.d_min,
                         unit_cell_scale=params.unit_cell_scale,
                         degrees_per_bin=params.degrees_per_bin,
                         min_frac_new=params.minimum_fraction_new)
    strategy2.plot(prefix='strategy2_')

    stats = ComputeStats([strategy, strategy2])
    stats.show()
    plot_statistics(stats, prefix='multi_strategy_')

    return
Example #12
0
    def run(self):
        """Run the script."""
        from dials.util.options import flatten_experiments

        params, options = self.parser.parse_args()
        if len(params.input.experiments) == 0:
            self.parser.print_help()
            raise Sorry("No experiments found in the input")
        experiments = flatten_experiments(params.input.experiments)

        # Determine output path
        self._directory = os.path.join(params.output.directory, "scan-varying_crystal")
        self._directory = os.path.abspath(self._directory)
        ensure_directory(self._directory)
        self._format = "." + params.output.format

        self._debug = params.output.debug

        # Decomposition axes
        self._e1 = params.orientation_decomposition.e1
        self._e2 = params.orientation_decomposition.e2
        self._e3 = params.orientation_decomposition.e3

        # cell plot
        dat = []
        for iexp, exp in enumerate(experiments):

            crystal = exp.crystal
            scan = exp.scan

            if crystal.num_scan_points == 0:
                print "Ignoring scan-static crystal"
                continue

            scan_pts = range(crystal.num_scan_points)
            cells = [crystal.get_unit_cell_at_scan_point(t) for t in scan_pts]
            cell_params = [e.parameters() for e in cells]
            a, b, c, aa, bb, cc = zip(*cell_params)
            phi = [scan.get_angle_from_array_index(t) for t in scan_pts]
            vol = [e.volume() for e in cells]
            cell_dat = {"phi": phi, "a": a, "b": b, "c": c, "alpha": aa, "beta": bb, "gamma": cc, "volume": vol}
            if self._debug:
                print "Crystal in Experiment {0}".format(iexp)
                print "Phi\ta\tb\tc\talpha\tbeta\tgamma\tVolume"
                msg = "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}"
                line_dat = zip(phi, a, b, c, aa, bb, cc, vol)
                for line in line_dat:
                    print msg.format(*line)
            dat.append(cell_dat)
        self.plot_cell(dat)

        # orientation plot
        dat = []
        for iexp, exp in enumerate(experiments):

            crystal = exp.crystal
            scan = exp.scan

            if crystal.num_scan_points == 0:
                print "Ignoring scan-static crystal"
                continue

            scan_pts = range(crystal.num_scan_points)
            phi = [scan.get_angle_from_array_index(t) for t in scan_pts]
            Umats = [crystal.get_U_at_scan_point(t) for t in scan_pts]
            if params.orientation_decomposition.relative_to_static_orientation:
                # factor out static U
                Uinv = crystal.get_U().inverse()
                Umats = [U * Uinv for U in Umats]
            # NB e3 and e1 definitions for the crystal are swapped compared
            # with those used inside the solve_r3_rotation_for_angles_given_axes
            # method
            angles = [solve_r3_rotation_for_angles_given_axes(U, self._e3, self._e2, self._e1, deg=True) for U in Umats]
            phi3, phi2, phi1 = zip(*angles)
            angle_dat = {"phi": phi, "phi3": phi3, "phi2": phi2, "phi1": phi1}
            if self._debug:
                print "Crystal in Experiment {0}".format(iexp)
                print "Image\tphi3\tphi2\tphi1"
                msg = "{0}\t{1}\t{2}\t{3}"
                line_dat = zip(phi, phi3, phi2, phi1)
                for line in line_dat:
                    print msg.format(*line)
            dat.append(angle_dat)
        self.plot_orientation(dat)
Example #13
0
e1 = matrix.col((1, 0, 0))
e2 = matrix.col((0.6691306063588582, 0.7431448254773942, 0))
e3 = matrix.col((1, 0, 0))
z = matrix.col((0, 0, 1))

from dials.algorithms.refinement import rotation_decomposition

import math

a = math.pi / 3

Rplus = z.axis_and_angle_as_r3_rotation_matrix(a)
Rminus = z.axis_and_angle_as_r3_rotation_matrix(-a)

Splus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
    Rplus, e1, e2, e3, return_both_solutions=True, deg=True
)
Sminus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
    Rminus, e1, e2, e3, return_both_solutions=True, deg=True
)

s = Splus[0]
F = e2.axis_and_angle_as_r3_rotation_matrix(
    s[1]
) * e3.axis_and_angle_as_r3_rotation_matrix(s[2])

gonio.set_fixed_rotation(F.elems)
gonio.set_angles(s)

write_expt(expts, sys.argv[2])
Example #14
0
    def run(self, args=None):
        """Run the script."""
        from scitbx import matrix

        from dials.util.options import flatten_experiments

        params, options = self.parser.parse_args(args)
        if len(params.input.experiments) == 0:
            self.parser.print_help()
            return
        experiments = flatten_experiments(params.input.experiments)

        # Determine output path
        self._directory = os.path.join(params.output.directory,
                                       "scan-varying_model")
        self._directory = os.path.abspath(self._directory)
        ensure_directory(self._directory)
        self._format = "." + params.output.format

        self._debug = params.output.debug

        # Decomposition axes
        self._e1 = params.orientation_decomposition.e1
        self._e2 = params.orientation_decomposition.e2
        self._e3 = params.orientation_decomposition.e3

        # cell plot
        dat = []
        for iexp, exp in enumerate(experiments):

            crystal = exp.crystal
            scan = exp.scan

            if crystal.num_scan_points == 0:
                print("Ignoring scan-static crystal")
                continue

            scan_pts = list(range(crystal.num_scan_points))
            cells = [crystal.get_unit_cell_at_scan_point(t) for t in scan_pts]
            cell_params = [e.parameters() for e in cells]
            a, b, c, aa, bb, cc = zip(*cell_params)
            phi = [scan.get_angle_from_array_index(t) for t in scan_pts]
            vol = [e.volume() for e in cells]
            cell_dat = {
                "phi": phi,
                "a": a,
                "b": b,
                "c": c,
                "alpha": aa,
                "beta": bb,
                "gamma": cc,
                "volume": vol,
            }
            try:
                cell_esds = [
                    crystal.get_cell_parameter_sd_at_scan_point(t)
                    for t in scan_pts
                ]
                sig_a, sig_b, sig_c, sig_aa, sig_bb, sig_cc = zip(*cell_esds)
                cell_dat["sig_a"] = sig_a
                cell_dat["sig_b"] = sig_b
                cell_dat["sig_c"] = sig_c
                cell_dat["sig_aa"] = sig_aa
                cell_dat["sig_bb"] = sig_bb
                cell_dat["sig_cc"] = sig_cc
            except RuntimeError:
                pass

            if self._debug:
                print("Crystal in Experiment {}".format(iexp))
                print("Phi\ta\tb\tc\talpha\tbeta\tgamma\tVolume")
                msg = "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}"
                line_dat = zip(phi, a, b, c, aa, bb, cc, vol)
                for line in line_dat:
                    print(msg.format(*line))
            dat.append(cell_dat)
        if dat:
            self.plot_cell(dat)

        # orientation plot
        dat = []
        for iexp, exp in enumerate(experiments):

            crystal = exp.crystal
            scan = exp.scan

            if crystal.num_scan_points == 0:
                print("Ignoring scan-static crystal")
                continue

            scan_pts = list(range(crystal.num_scan_points))
            phi = [scan.get_angle_from_array_index(t) for t in scan_pts]
            Umats = [
                matrix.sqr(crystal.get_U_at_scan_point(t)) for t in scan_pts
            ]
            if params.orientation_decomposition.relative_to_static_orientation:
                # factor out static U
                Uinv = matrix.sqr(crystal.get_U()).inverse()
                Umats = [U * Uinv for U in Umats]
            # NB e3 and e1 definitions for the crystal are swapped compared
            # with those used inside the solve_r3_rotation_for_angles_given_axes
            # method
            angles = [
                solve_r3_rotation_for_angles_given_axes(U,
                                                        self._e3,
                                                        self._e2,
                                                        self._e1,
                                                        deg=True)
                for U in Umats
            ]
            phi3, phi2, phi1 = zip(*angles)
            angle_dat = {"phi": phi, "phi3": phi3, "phi2": phi2, "phi1": phi1}
            if self._debug:
                print("Crystal in Experiment {}".format(iexp))
                print("Image\tphi3\tphi2\tphi1")
                msg = "{0}\t{1}\t{2}\t{3}"
                line_dat = zip(phi, phi3, phi2, phi1)
                for line in line_dat:
                    print(msg.format(*line))
            dat.append(angle_dat)
        if dat:
            self.plot_orientation(dat)

        # beam centre plot
        dat = []
        for iexp, exp in enumerate(experiments):

            beam = exp.beam
            detector = exp.detector
            scan = exp.scan

            if beam.num_scan_points == 0:
                print("Ignoring scan-static beam")
                continue

            scan_pts = range(beam.num_scan_points)
            phi = [scan.get_angle_from_array_index(t) for t in scan_pts]
            p = detector.get_panel_intersection(beam.get_s0())
            if p < 0:
                print("Beam does not intersect a panel")
                continue
            panel = detector[p]
            s0_scan_points = [
                beam.get_s0_at_scan_point(i)
                for i in range(beam.num_scan_points)
            ]
            bc_scan_points = [
                panel.get_beam_centre_px(s0) for s0 in s0_scan_points
            ]
            bc_x, bc_y = zip(*bc_scan_points)
            dat.append({
                "phi": phi,
                "beam_centre_x": bc_x,
                "beam_centre_y": bc_y
            })
        if dat:
            self.plot_beam_centre(dat)
Example #15
0
    def write_dyn_cif_pets(self):

        self._set_virtual_frames()

        cif_filename = self.filename_prefix + ".cif_pets"
        cell_params = self.experiment.crystal.get_unit_cell().parameters()
        volume = self.experiment.crystal.get_unit_cell().volume()
        wavelength = self.experiment.beam.get_wavelength()
        UBmatrix = matrix.sqr(self.experiment.crystal.get_A()).as_numpy_array()
        # tilt semi-angle of the virtual frame
        precession_angle = (self.experiment.scan.get_oscillation()[1] *
                            self.n_merged) / 2

        # Some of these values are left as dummy zeroes for DIALS
        comment = f""";
data collection geometry: continuous rotation
dstarmax:  0.000
RC width:  0.00000
mosaicity:  0.000
rotation axis position:  000.000
reflection size:    0.000
Virtual frame settings: number of merged frames:  {self.n_merged}
                        step between frames:      {self.step}
                        sum all intensities:      1
;"""
        uvws = []
        for frame_id, virtual_frame in enumerate(self.virtual_frames):
            u, v, w = virtual_frame["zone_axis"]
            R = virtual_frame["rotated_misset"]
            # Decompose U = Rω * Rα * Rβ, where:
            # α is around 1,0,0
            # β is around 0,1,0
            # ω is around 0,0,1
            omega, alpha, beta = solve_r3_rotation_for_angles_given_axes(
                R, (0, 0, 1), (1, 0, 0), (0, 1, 0), deg=True)
            scale = 1  # dummy value
            uvws += [[
                frame_id + 1, u, v, w, precession_angle, alpha, beta, omega,
                scale
            ]]

        ref_list = []
        for frame_id, virtual_frame in enumerate(self.virtual_frames):
            refs = virtual_frame["reflections"]
            refs["intensity.sigma"] = flex.sqrt(
                refs[self.intensity_variance_column])
            for r in refs.rows():
                h, k, l = r["miller_index"]
                i = r[self.intensity_column]
                sig_i = r["intensity.sigma"]
                ref_list.append([h, k, l, i, sig_i, frame_id + 1])

        self._write_dyn_cif_pets(
            cif_filename,
            cell_params,
            volume,
            wavelength,
            UBmatrix,
            uvws,
            ref_list,
            comment,
        )
Example #16
0
def run(args):

  from dials.util.options import OptionParser
  from dials.util.options import flatten_experiments
  import libtbx.load_env

  usage = "%s [options] datablock.json" %(
    libtbx.env.dispatcher_name)

  parser = OptionParser(
    usage=usage,
    phil=phil_scope,
    read_experiments=True,
    check_format=False,
    epilog=help_message)

  params, options = parser.parse_args(show_diff_phil=True)
  experiments = flatten_experiments(params.input.experiments)

  if len(experiments) == 0:
    parser.print_help()
    exit(0)

  imagesets = experiments.imagesets()

  predicted_all = None
  dose = flex.size_t()

  for i_expt, expt in enumerate(experiments):
    if params.space_group is not None:
      expt.crystal.set_space_group(params.space_group.group())
    strategy = Strategy(expt, d_min=params.d_min,
                        unit_cell_scale=params.unit_cell_scale,
                        degrees_per_bin=params.degrees_per_bin,
                        min_frac_new=params.minimum_fraction_new)
    strategy.plot(prefix='strategy1_')

    expt2 = copy.deepcopy(expt)
    scan = expt2.scan
    gonio = expt2.goniometer
    angles = gonio.get_angles()
    theta_max = strategy.theta_max
    fixed_rotation = matrix.sqr(gonio.get_fixed_rotation())
    setting_rotation = matrix.sqr(gonio.get_setting_rotation())
    rotation_axis = matrix.col(gonio.get_rotation_axis_datum())
    rotation_matrix = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
      scan.get_oscillation()[0], deg=True)
    D_p = (setting_rotation * rotation_matrix * fixed_rotation)

    beam = expt2.beam
    s0 = matrix.col(beam.get_unit_s0())

    # rotate crystal by at least 2 * theta_max around axis perpendicular to
    # goniometer rotation axis
    n = rotation_axis.cross(s0)

    i = 0
    while True:
      for sign in (1, -1):
        rot_angle = 2 * theta_max + i
        i += 1

        R = n.axis_and_angle_as_r3_rotation_matrix(rot_angle, deg=True)

        axes = gonio.get_axes()
        assert len(axes) == 3
        e1, e2, e3 = (matrix.col(e) for e in axes)

        from dials.algorithms.refinement import rotation_decomposition
        solutions = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
          R * D_p, e1, e2, e3, return_both_solutions=True, deg=True)
        if solutions is not None:
          break
      if solutions is not None:
        break

    angles = solutions[0]
    gonio.set_angles(angles)

    print
    print "Goniometer settings to rotate crystal by %.2f degrees:" %rot_angle,
    print "(%.2f, %.2f, %.2f)" %angles
    print

    strategy2 = Strategy(expt2, d_min=params.d_min,
                         unit_cell_scale=params.unit_cell_scale,
                         degrees_per_bin=params.degrees_per_bin,
                         min_frac_new=params.minimum_fraction_new)
    strategy2.plot(prefix='strategy2_')

    stats = ComputeStats([strategy, strategy2])
    stats.show()
    plot_statistics(stats, prefix='multi_strategy_')

    return
    def run(self):
        params, options = self.parser.parse_args(show_diff_phil=True)
        from dials.util import log

        log.config(info="dials.complete_full_sphere.log",
                   debug="dials.complete_full_sphere.debug.log")

        import math
        from scitbx import matrix
        from dials.algorithms.refinement import rotation_decomposition
        from dials.util.options import flatten_experiments
        from dials.array_family import flex

        model_shadow = params.shadow

        experiments = flatten_experiments(params.input.experiments)

        if len(experiments) != 1:
            self.parser.print_help()
            return

        expt = experiments[0]

        axes = expt.goniometer.get_axes()

        if len(axes) != 3:
            from libtbx.utils import Sorry
            raise Sorry("This will only work with 3-axis goniometers")

        if not expt.imageset.reader().get_format():
            from libtbx.utils import Sorry
            raise Sorry("This will only work with images available")

        if not expt.imageset.reader().get_format(
        ).get_goniometer_shadow_masker():
            model_shadow = False

        beam = expt.beam
        det = expt.detector

        if params.resolution:
            resolution = params.resolution
        else:
            resolution = det.get_max_inscribed_resolution(expt.beam.get_s0())

        # at this point, predict all of the reflections in the scan possible (i.e.
        # extend scan to 360 degrees) - this points back to expt

        scan = self.make_scan_360(expt.scan)

        # now get a full set of all unique miller indices
        from cctbx import miller
        from cctbx import crystal

        all = miller.build_set(crystal_symmetry=crystal.symmetry(
            space_group=expt.crystal.get_space_group(),
            unit_cell=expt.crystal.get_unit_cell()),
                               anomalous_flag=True,
                               d_min=resolution)

        if model_shadow:
            obs, shadow = self.predict_to_miller_set_with_shadow(
                expt, resolution)
        else:
            obs = self.predict_to_miller_set(expt, resolution)

        logger.info('Fraction of unique observations at datum: %.1f%%' %
                    (100. * len(obs.indices()) / len(all.indices())))

        missing = all.lone_set(other=obs)

        logger.info('%d unique reflections in blind region' %
                    len(missing.indices()))

        e1 = matrix.col(axes[0])
        e2 = matrix.col(axes[1])
        e3 = matrix.col(axes[2])

        s0n = matrix.col(beam.get_s0()).normalize()

        # rotate blind region about beam by +/- two theta
        two_theta = 2.0 * math.asin(0.5 * beam.get_wavelength() / resolution)
        R_ptt = s0n.axis_and_angle_as_r3_rotation_matrix(two_theta)
        R_ntt = s0n.axis_and_angle_as_r3_rotation_matrix(-two_theta)

        # now decompose to e3, e2, e1
        sol_plus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
            R_ptt, e3, e2, e1, return_both_solutions=True, deg=True)

        sol_minus = rotation_decomposition.solve_r3_rotation_for_angles_given_axes(
            R_ntt, e3, e2, e1, return_both_solutions=True, deg=True)

        solutions = []
        if sol_plus:
            solutions.extend(sol_plus)
        if sol_minus:
            solutions.extend(sol_minus)

        if not solutions:
            from libtbx.utils import Sorry
            raise Sorry('Impossible two theta: %.3f,' %
                        (two_theta * 180.0 / math.pi))

        logger.info('Maximum two theta: %.3f,' % (two_theta * 180.0 / math.pi))
        logger.info('%d solutions found' % len(solutions))

        names = tuple([n.replace('GON_', '').lower() for n in \
                       expt.goniometer.get_names()])

        logger.info(' %8s %8s %8s  coverage expt.json' % names)
        self.write_expt(experiments, 'solution_0.json')
        for j, s in enumerate(solutions):
            expt.goniometer.set_angles(s)
            if model_shadow:
                obs, shadow = self.predict_to_miller_set_with_shadow(
                    expt, resolution)
            else:
                obs = self.predict_to_miller_set(expt, resolution)
            new = missing.common_set(obs)
            fout = 'solution_%d.json' % (j + 1)
            f = len(new.indices()) / len(missing.indices())

            logger.info('%8.3f %8.3f %8.3f %4.2f %s' %
                        (s[0], s[1], s[2], f, fout))
            self.write_expt(experiments, fout)