Example #1
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)
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)
Example #3
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)
Example #4
0
    def _check_have_similar_crystal_models(self, experiments):
        """
        Checks for similar crystal models.

        Checks whether the most recently added crystal model is similar to previously
        found crystal models, and if so, deletes the last crystal model from the
        experiment list.
        """
        have_similar_crystal_models = False
        cryst_b = experiments.crystals()[-1]
        for i_a, cryst_a in enumerate(experiments.crystals()[:-1]):
            R_ab, axis, angle, cb_op_ab = difference_rotation_matrix_axis_angle(
                cryst_a, cryst_b)
            min_angle = self.params.multiple_lattice_search.minimum_angular_separation
            if abs(angle) < min_angle:  # degrees
                logger.info(
                    "Crystal models too similar, rejecting crystal %i:" %
                    (len(experiments)))
                logger.info(
                    "Rotation matrix to transform crystal %i to crystal %i" %
                    (i_a + 1, len(experiments)))
                logger.info(R_ab)
                logger.info("Rotation of %.3f degrees" % angle +
                            " about axis (%.3f, %.3f, %.3f)" % axis)
                have_similar_crystal_models = True
                del experiments[-1]
                break
        return have_similar_crystal_models
Example #5
0
 def compare_orientation_matrices(image):
     serialno = image.lstrip("noiseimage_").rstrip(".img")
     exp1 = ExperimentListFactory.from_json_file("experiments_" + serialno +
                                                 ".json")
     exp2 = ExperimentListFactory.from_json_file("indexed.expt")
     R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
         exp1[0].crystal, exp2[0].crystal)
     return abs(angle)
def run(args):

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

    usage = "%s [options] experiments.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) <= 1:
        parser.print_help()
        return

    from dials.algorithms.indexing.compare_orientation_matrices import (
        difference_rotation_matrix_axis_angle, )

    crystals = []
    for experiment in experiments:
        crystal = experiment.crystal
        if params.space_group is not None:
            crystal.set_space_group(params.space_group.group())
        crystals.append(crystal)

    angles = flex.double()

    import math

    padding = int(math.ceil(math.log10(len(experiments))))
    output_template = "%s%%0%ii.json" % (params.output.prefix, padding)

    prev_expt = experiments[0]
    for i in range(1, len(experiments)):
        R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
            prev_expt.crystal, experiments[i].crystal)
        angles.append(angle)
        # print i, angle
        if abs(angle) > params.max_deviation:
            continue
        experiments[i].crystal = experiments[i].crystal.change_basis(cb_op)
        prev_expt = experiments[i]

        from dxtbx.serialize import dump

        dump.experiment_list(experiments[i:i + 1], output_template % i)

    from matplotlib import pyplot

    n, bins, patches = pyplot.hist(angles.as_numpy_array(), 100)
    pyplot.show()
Example #7
0
def filter_similar_orientations(crystal_models,
                                other_crystal_models,
                                minimum_angular_separation=5):
    for cryst in crystal_models:
        orientation_too_similar = False
        for i_a, cryst_a in enumerate(other_crystal_models):
            R_ab, axis, angle, cb_op_ab = difference_rotation_matrix_axis_angle(
                cryst_a, cryst)
            if abs(angle) < minimum_angular_separation:  # degrees
                orientation_too_similar = True
                break
        if orientation_too_similar:
            logger.debug("skipping crystal: too similar to other crystals")
            continue
        yield cryst
Example #8
0
def filter_doubled_cell(solutions):
    accepted_solutions = []
    for i1, s1 in enumerate(solutions):
        doubled_cell = False
        for (m1, m2, m3) in (
            (2, 1, 1),
            (1, 2, 1),
            (1, 1, 2),
            (2, 2, 1),
            (2, 1, 2),
            (1, 2, 2),
            (2, 2, 2),
        ):
            if doubled_cell:
                break
            a, b, c = (matrix.col(v)
                       for v in s1.crystal.get_real_space_vectors())
            new_cryst = Crystal(
                real_space_a=1 / m1 * a,
                real_space_b=1 / m2 * b,
                real_space_c=1 / m3 * c,
                space_group=s1.crystal.get_space_group(),
            )
            new_unit_cell = new_cryst.get_unit_cell()
            for s2 in solutions:
                if s2 is s1:
                    continue
                if new_unit_cell.is_similar_to(s2.crystal.get_unit_cell(),
                                               relative_length_tolerance=0.05):
                    R, axis, angle, cb = difference_rotation_matrix_axis_angle(
                        new_cryst, s2.crystal)
                    if (angle < 1) and (s1.n_indexed < (1.1 * s2.n_indexed)):
                        doubled_cell = True
                        break

        if not doubled_cell:
            accepted_solutions.append(s1)

    return accepted_solutions
Example #9
0
def run(args):
    from dials.util.options import OptionParser
    from dials.util.options import flatten_experiments

    # The script usage
    usage = "dials.stereographic_projection [options] [param.phil] experiments.json"

    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 not experiments:
        parser.print_help()
        return

    if not params.hkl and params.hkl_limit is None:
        sys.exit("Please provide hkl or hkl_limit parameters.")

    if params.hkl is not None and len(params.hkl):
        miller_indices = flex.miller_index(params.hkl)
    elif params.hkl_limit is not None:
        limit = params.hkl_limit
        miller_indices = flex.miller_index()
        for h in range(-limit, limit + 1):
            for k in range(-limit, limit + 1):
                for l in range(-limit, limit + 1):
                    if (h, k, l) == (0, 0, 0):
                        continue
                    miller_indices.append((h, k, l))

    crystals = experiments.crystals()

    symmetry = crystal.symmetry(
        unit_cell=crystals[0].get_unit_cell(), space_group=crystals[0].get_space_group()
    )
    miller_set = miller.set(symmetry, miller_indices)
    d_spacings = miller_set.d_spacings()
    if params.eliminate_sys_absent:
        d_spacings = d_spacings.eliminate_sys_absent()
    if params.expand_to_p1:
        d_spacings = d_spacings.as_non_anomalous_array().expand_to_p1()
        d_spacings = d_spacings.generate_bijvoet_mates()
    miller_indices = d_spacings.indices()

    # find the greatest common factor (divisor) between miller indices
    miller_indices_unique = flex.miller_index()
    for hkl in miller_indices:
        gcd = gcd_list(hkl)
        if gcd > 1:
            miller_indices_unique.append(tuple(int(h / gcd) for h in hkl))
        elif gcd < 1:
            pass
        else:
            miller_indices_unique.append(hkl)
    miller_indices = miller_indices_unique
    miller_indices = flex.miller_index(list(set(miller_indices)))

    ref_crystal = crystals[0]
    U = matrix.sqr(ref_crystal.get_U())
    B = matrix.sqr(ref_crystal.get_B())
    R = matrix.identity(3)

    if params.frame == "laboratory":
        reference_poles = reference_poles_perpendicular_to_beam(
            experiments[0].beam, experiments[0].goniometer
        )
        if params.use_starting_angle:
            rotation_axis = matrix.col(experiments[0].goniometer.get_rotation_axis())
            R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
                experiments[0].scan.get_oscillation()[0], deg=True
            )
        elif params.phi_angle != 0:
            rotation_axis = matrix.col(experiments[0].goniometer.get_rotation_axis())
            R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
                params.phi_angle, deg=True
            )
    else:
        if params.plane_normal is not None:
            plane_normal = params.plane_normal
        else:
            plane_normal = (0, 0, 1)
        reference_poles = reference_poles_crystal(
            ref_crystal, plane_normal=plane_normal
        )

    if params.frame == "crystal":
        U = matrix.identity(3)

    reciprocal_space_points = list(R * U * B) * miller_indices.as_vec3_double()
    projections_ref = stereographic_projection(reciprocal_space_points, reference_poles)

    projections_all = [projections_ref]

    if experiments:
        from dials.algorithms.indexing.compare_orientation_matrices import (
            difference_rotation_matrix_axis_angle,
        )

        for expt in experiments[1:]:
            cryst = expt.crystal
            if params.frame == "crystal":
                R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
                    ref_crystal, cryst
                )
                U = R_ij
            elif params.use_starting_angle:
                if params.use_starting_angle:
                    rotation_axis = matrix.col(expt.goniometer.get_rotation_axis())
                    R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
                        expt.scan.get_oscillation()[0], deg=True
                    )
            else:
                U = matrix.sqr(cryst.get_U())
            reciprocal_space_points = (
                list(R * U * matrix.sqr(cryst.get_B()))
                * miller_indices.as_vec3_double()
            )
            projections = stereographic_projection(
                reciprocal_space_points, reference_poles
            )
            projections_all.append(projections)

    if params.save_coordinates:
        with open("projections.txt", "w") as f:
            f.write("crystal h k l x y" + os.linesep)
            for i_cryst, projections in enumerate(projections_all):
                for hkl, proj in zip(miller_indices, projections):
                    f.write("%i " % (i_cryst + 1))
                    f.write("%i %i %i " % hkl)
                    f.write(("%f %f" + os.linesep) % proj)

    if params.plot.show or params.plot.filename:
        epochs = None
        if params.plot.colour_map is not None:
            if experiments[0].scan is not None:
                epochs = [expt.scan.get_epochs()[0] for expt in experiments]
            else:
                epochs = [i for i, expt in enumerate(experiments)]
        plot_projections(
            projections_all,
            filename=params.plot.filename,
            show=params.plot.show,
            colours=params.plot.colours,
            marker_size=params.plot.marker_size,
            font_size=params.plot.font_size,
            gridsize=params.plot.gridsize,
            label_indices=params.plot.label_indices,
            epochs=epochs,
            colour_map=params.plot.colour_map,
        )

    if params.json.filename:
        projections_as_json(projections_all, filename=params.json.filename)
def get_uc_consensus(experiments_list,
                     show_plot=False,
                     save_plot=False,
                     return_only_first_indexed_model=False,
                     finalize_method='reindex_with_known_crystal_models',
                     clustering_params=None):
    '''
  Uses the Rodriguez Laio 2014 method to do a hierarchical clustering of the crystal models and
  then vote for the highest consensus crystal mode. Input needs to be a list of experiments object.
  Clustering code taken from github.com/cctbx-xfel/cluster_regression
  Clustering is first done first based on unit cell dimensions. Then for each of the clusters identified,
  a further clustering is done based on orientational matrix A
  '''
    if return_only_first_indexed_model:
        return [experiments_list[0].crystals()[0]], None
    cells = []

    from xfel.clustering.singleframe import CellOnlyFrame
    # Flag for testing Lysozyme data from NKS.Make sure cluster_regression repository is present and configured
    # Program will exit after plots are displayed if this flag is true
    test_nks = False
    if clustering_params is None:
        clustering_params = clustering_iota_scope

    if test_nks:
        from cctbx import crystal
        import libtbx.load_env
        cluster_regression = libtbx.env.find_in_repositories(
            relative_path="cluster_regression", test=os.path.isdir)
        file_name = os.path.join(cluster_regression, 'examples',
                                 'lysozyme1341.txt')
        for line in open(file_name, "r").xreadlines():
            tokens = line.strip().split()
            unit_cell = tuple(float(x) for x in tokens[0:6])
            space_group_symbol = tokens[6]
            crystal_symmetry = crystal.symmetry(
                unit_cell=unit_cell, space_group_symbol=space_group_symbol)
            cells.append(CellOnlyFrame(crystal_symmetry))
    else:
        clustered_experiments_list = flex.int()
        for experiment in experiments_list:
            if len(experiment.crystals()) > 1:
                print('IOTA:Should have only one crystal model')
            crystal_symmetry = experiment.crystals()[0].get_crystal_symmetry()
            cells.append(CellOnlyFrame(crystal_symmetry))
            # Maintain a list which is meaningless right now that will finally contain the
            # final clustering results
            clustered_experiments_list.append(-1)
    MM = [c.mm for c in cells]  # metrical matrices
    MM_double = flex.double()
    for i in range(len(MM)):
        Tup = MM[i]
        for j in range(6):
            MM_double.append(Tup[j])
    print('There are %d cells' % len(MM))
    coord_x = flex.double([c.uc[0] for c in cells])
    coord_y = flex.double([c.uc[1] for c in cells])
    if show_plot or save_plot:
        import matplotlib
        if not show_plot:
            matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        plt.plot([c.uc[0] for c in cells], [c.uc[1] for c in cells],
                 "k.",
                 markersize=3.)
        plt.axes().set_aspect("equal")
    if save_plot:
        plot_name = 'uc_cluster.png'
        plt.savefig(plot_name,
                    size_inches=(10, 10),
                    dpi=300,
                    bbox_inches='tight')
    if show_plot:
        plt.show()
    print('Now constructing a Dij matrix: Starting Unit Cell clustering')
    NN = len(MM)
    from cctbx.uctbx.determine_unit_cell import NCDist_flatten
    Dij = NCDist_flatten(MM_double)
    from scitbx.math import five_number_summary
    d_c = clustering_params.d_c  #five_number_summary(list(Dij))[1]
    d_c = estimate_d_c(Dij)
    #d_c = flex.mean_and_variance(Dij.as_1d()).unweighted_sample_standard_deviation()
    print('d_c = ', d_c)
    if len(cells) < 5:
        return [experiments_list[0].crystals()[0]], None
    CM = clustering_manager(
        Dij=Dij,
        d_c=d_c,
        max_percentile_rho=clustering_params.max_percentile_rho_uc,
        Z_delta=clustering_params.Z_delta,
        strategy='strategy_3')
    n_cluster = 1 + flex.max(CM.cluster_id_final)
    print(len(cells), ' datapoints have been analyzed')
    print('%d CLUSTERS' % n_cluster)
    for i in range(n_cluster):
        item = flex.first_index(CM.cluster_id_maxima, i)
        print('Cluster %d central Unit cell = %d' % (i, item))
        cells[item].crystal_symmetry.show_summary()

    # More plots for debugging
    appcolors = [
        'b', 'r', '#ff7f0e', '#2ca02c', '#9467bd', '#8c564b', '#e377c2',
        '#7f7f7f', '#bcbd22', '#17becf'
    ]
    if show_plot:
        # Decision graph
        import matplotlib.pyplot as plt
        plt.plot(CM.rho, CM.delta, "r.", markersize=3.)
        for x in range(NN):
            if CM.cluster_id_maxima[x] >= 0:
                plt.plot([CM.rho[x]], [CM.delta[x]], "ro")
        plt.show()

    if show_plot:
        import matplotlib.pyplot as plt
        colors = [appcolors[i % 10] for i in CM.cluster_id_full]
        plt.scatter(coord_x,
                    coord_y,
                    marker='o',
                    color=colors,
                    linewidth=0.4,
                    edgecolor='k')
        for i in range(n_cluster):
            item = flex.first_index(CM.cluster_id_maxima, i)
            plt.plot([cells[item].uc[0]], cells[item].uc[1], 'y.')
            plt.axes().set_aspect("equal")
            plt.show()
    if test_nks:
        exit()

    # Now look at each unit cell cluster for orientational clustering
    # idea is to cluster the orientational component in each of the unit cell clusters
    #
    do_orientational_clustering = not return_only_first_indexed_model  # temporary.
    dxtbx_crystal_models = []
    if do_orientational_clustering:
        print('IOTA: Starting orientational clustering')
        Dij_ori = {}  # dictionary to store Dij for each cluster
        uc_experiments_list = {
        }  # dictionary to store experiments_lists for each cluster
        from collections import Counter
        uc_cluster_count = Counter(list(CM.cluster_id_final))
        # instantiate the Dij_ori flat 1-d array
        # Put all experiments list from same uc cluster together
        if True:
            from scitbx.matrix import sqr
            from cctbx_orientation_ext import crystal_orientation
            crystal_orientation_list = []
            all_A = []
            for i in range(len(experiments_list)):
                crystal_orientation_list.append(
                    crystal_orientation(
                        experiments_list[i].crystals()[0].get_A(), True))
                #exit()
                A_direct = sqr(crystal_orientation_list[i].reciprocal_matrix()
                               ).transpose().inverse()
                all_A.append(A_direct[0])
                #print ("Direct A matrix 1st element = %12.6f %12.6f %12.6f"%(A_direct[0], A_direct[1], A_direct[2]))
        #  exit()
        CM_mapping = {}
        for i in range(len(experiments_list)):
            if CM.cluster_id_full[i] not in uc_experiments_list:
                uc_experiments_list[CM.cluster_id_full[i]] = []
                CM_mapping[CM.cluster_id_full[i]] = []
            uc_experiments_list[CM.cluster_id_full[i]].append(
                experiments_list[i])
            # Maintain mapping between original experiments_list and uc_exeriments_list
            # Mapping: key> index_in_experiments_list | value> cluster_id, index_in_uc_cluster
            CM_mapping[CM.cluster_id_full[i]].append(
                (i, len(uc_experiments_list[CM.cluster_id_full[i]]) - 1))
        for cluster in uc_cluster_count:
            # Make sure there are atleast a minimum number of samples in the cluster
            if uc_cluster_count[cluster] < clustering_params.min_datapts:
                continue
            Dij_ori[cluster] = flex.double(
                [[0.0] * uc_cluster_count[cluster]] *
                uc_cluster_count[cluster])
            # Now populate the Dij_ori array
            N_samples_in_cluster = len(uc_experiments_list[cluster])
            for i in range(N_samples_in_cluster - 1):
                for j in range(i + 1, N_samples_in_cluster):
                    dij_ori = get_dij_ori(
                        uc_experiments_list[cluster][i].crystals()[0],
                        uc_experiments_list[cluster][j].crystals()[0])
                    A_direct_i = sqr(
                        uc_experiments_list[cluster][i].crystals()
                        [0].get_A()).transpose().inverse()
                    A_direct_j = sqr(
                        uc_experiments_list[cluster][j].crystals()
                        [0].get_A()).transpose().inverse()
                    #print ("Direct A matrix 1st element = %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f"%(dij_ori, A_direct_i[0], A_direct_j[0], A_direct_i[1],A_direct_j[1], A_direct_i[2], A_direct_j[2] ))
                    Dij_ori[cluster][N_samples_in_cluster * i + j] = dij_ori
                    Dij_ori[cluster][N_samples_in_cluster * j + i] = dij_ori

        # Now do the orientational cluster analysis
        d_c_ori = clustering_params.d_c_ori  # 0.13
        from exafel_project.ADSE13_25.clustering.plot_with_dimensional_embedding import plot_with_dimensional_embedding
        #plot_with_dimensional_embedding(1-Dij_ori[1]/flex.max(Dij_ori[1]), show_plot=True)
        A_matrices = []
        for cluster in Dij_ori:
            #if cluster == 2:
            #  CM_ori = clustering_manager(Dij=Dij_ori[cluster], d_c=d_c_ori, max_percentile_rho=0.85, debug=True)
            d_c_ori = estimate_d_c(Dij_ori[cluster])
            #else:
            #d_c_ori=flex.mean_and_variance(Dij_ori[cluster].as_1d()).unweighted_sample_standard_deviation()
            print('d_c_ori=', d_c_ori)
            CM_ori = clustering_manager(
                Dij=Dij_ori[cluster],
                d_c=d_c_ori,
                max_percentile_rho=clustering_params.max_percentile_rho_ori,
                Z_delta=clustering_params.Z_delta,
                strategy='strategy_3')
            n_cluster_ori = 1 + flex.max(CM_ori.cluster_id_final)
            #from IPython import embed; embed(); exit()
            for i in range(n_cluster_ori):
                if len([zz for zz in CM_ori.cluster_id_final if zz == i
                        ]) < clustering_params.min_datapts:
                    continue
                item = flex.first_index(CM_ori.cluster_id_maxima, i)
                dxtbx_crystal_model = uc_experiments_list[cluster][
                    item].crystals()[0]
                dxtbx_crystal_models.append(dxtbx_crystal_model)
                # Map the orientational clusters to the original experiments_list indices
                # This should be the final list of clusters!
                for j, ori_cluster_id in enumerate(CM_ori.cluster_id_final):
                    if ori_cluster_id == i:
                        xx, yy = CM_mapping[cluster][j]
                        clustered_experiments_list[xx] = len(
                            dxtbx_crystal_models) - 1
                from scitbx.matrix import sqr
                from cctbx_orientation_ext import crystal_orientation
                crystal_orientation = crystal_orientation(
                    dxtbx_crystal_model.get_A(), True)
                A_direct = sqr(crystal_orientation.reciprocal_matrix()
                               ).transpose().inverse()
                A_matrices.append(A_direct)
                print(
                    "IOTA: Direct A matrix 1st element of orientational cluster %d  = %12.6f"
                    % (i, A_direct[0]))
                print(A_direct)
            if show_plot:
                # Decision graph
                stretch_plot_factor = 1.05  # (1+fraction of limits by which xlim,ylim should be set)
                import matplotlib.pyplot as plt
                plt.plot(CM_ori.rho, CM_ori.delta, "r.", markersize=3.)
                for x in range(len(list(CM_ori.cluster_id_final))):
                    if CM_ori.cluster_id_maxima[x] >= 0:
                        plt.plot([CM_ori.rho[x]], [CM_ori.delta[x]], "ro")
                #exit()
                plt.xlim([-10, stretch_plot_factor * flex.max(CM_ori.rho)])
                plt.ylim([-10, stretch_plot_factor * flex.max(CM_ori.delta)])
                plt.show()
    # FIXME Still to be worked out what exactly should be returned
    #if return_only_first_indexed_model:
    #  return [experiments_list[0].crystals()[0]], clustered_experiments_list
    # Make sure the crystal models are not too close to each other
    # FIXME should be a PHIL
    #from IPython import embed; embed(); exit()
    min_angle = 5.0  # taken from indexer.py
    close_models_list = []
    # Not used really; other fixes have been made to code to figure out outliers
    # Still keeping this in case it it useful later on.
    if len(dxtbx_crystal_models) > 10000:
        from dials.algorithms.indexing.compare_orientation_matrices import difference_rotation_matrix_axis_angle
        from cctbx_orientation_ext import crystal_orientation
        from dxtbx.model import Crystal
        for i_a in range(0, len(dxtbx_crystal_models) - 1):
            for i_b in range(i_a + 1, len(dxtbx_crystal_models)):
                cryst_a = dxtbx_crystal_models[i_a]
                cryst_b = dxtbx_crystal_models[i_b]
                cryst_a_ori = crystal_orientation(cryst_a.get_A(), True)
                cryst_b_ori = crystal_orientation(cryst_b.get_A(), True)
                try:
                    best_similarity_transform = cryst_b_ori.best_similarity_transformation(
                        other=cryst_a_ori,
                        fractional_length_tolerance=20.00,
                        unimodular_generator_range=1)
                    cryst_b_ori_best = cryst_b_ori.change_basis(
                        best_similarity_transform)
                except Exception as e:
                    cryst_b_ori_best = cryst_b_ori

                # FIXME hardcoded space group for myoglobin LS49
                cryst_b_best = Crystal(cryst_b_ori_best.direct_matrix()[0:3],
                                       cryst_b_ori_best.direct_matrix()[3:6],
                                       cryst_b_ori_best.direct_matrix()[6:9],
                                       'P 1 21 1')
                R_ab, axis, angle, cb_op_ab = difference_rotation_matrix_axis_angle(
                    cryst_a, cryst_b_best)
                # FIXME
                if abs(angle) < min_angle:  # degrees
                    close_models_list.append((i_a, i_b))

    # Now prune the dxtbx_crystal_models list
        unique_experiments_list = flex.int(range(len(dxtbx_crystal_models)))
        for close_models in close_models_list:
            i_a, i_b = close_models
            if dxtbx_crystal_models[i_a] is not None and dxtbx_crystal_models[
                    i_b] is not None:
                dxtbx_crystal_models[i_b] = None
                unique_experiments_list[i_b] = i_a
                clustered_experiments_list.set_selected(
                    clustered_experiments_list == i_b, i_a)

        counter = -1
        for ii, model in enumerate(dxtbx_crystal_models):
            if model is not None:
                counter += 1
                clustered_experiments_list.set_selected(
                    clustered_experiments_list == unique_experiments_list[ii],
                    counter)
        dxtbx_crystal_models = [
            x for x in dxtbx_crystal_models if x is not None
        ]

    #from IPython import embed; embed(); exit()
    if len(dxtbx_crystal_models) > 0:
        return dxtbx_crystal_models, list(clustered_experiments_list)
    else:
        # If nothing works, atleast return the 1st crystal model that was found
        return [experiments_list[0].crystals()[0]], None
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
""")
Example #12
0
def test_indexed_hkl():
    '''tests the uniqueness of hkl values associated with each experiment for
  100 simulated randomly oriented thermolysin diffraction images indexed using
  two color indexer'''
    flex.set_random_seed(42)
    known_symmetry = crystal.symmetry("78,78,37,90,90,90", "P43212")

    detector = detector_factory.simple('SENSOR_UNKNOWN', 125, (97.075, 97.075),
                                       '+x', '-y', (0.11, 0.11), (1765, 1765))
    wavelength1 = 12398 / 7400  #wavelength for 2 color experiment in Angstroms
    wavelength2 = 12398 / 7500  #wavelength for 2 color experiment in Angstroms

    beam1 = beam_factory.simple_directional((0, 0, 1), wavelength1)
    beam2 = beam_factory.simple_directional((0, 0, 1), wavelength2)

    a_basis = []
    b_basis = []
    c_basis = []

    # refiner resets random number seed so in order to get the same 100 images
    #generated each time the random seed is set
    # the implementation is as follows
    # gets simulated images
    sims = [merge_close_spots.merge_close_spots() for i in range(2)]

    for data in sims:
        A = data.A
        A_inv = A.inverse()

        a = col(A_inv[:3])
        b = col(A_inv[3:6])
        c = col(A_inv[6:])
        crystinp = Crystal(a, b, c, space_group=known_symmetry.space_group())
        a_basis.append(a)
        b_basis.append(b)
        c_basis.append(c)

        res = data.two_color_sim
        info = data.spot_proximity(res)

        refl = info[0]
        result = index(refl, detector, known_symmetry, [beam1, beam2])
        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)

        # 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
        params.indexing.stills.rmsd_min_px = 3.5

        expts = copy.deepcopy(result.refined_experiments)
        expts.crystals()[0].change_basis(change_of_basis)

        reflections_exp0 = result.refined_reflections.select(
            result.refined_reflections['id'] == 0)
        reflections_exp1 = result.refined_reflections.select(
            result.refined_reflections['id'] == 1)

        assert len(reflections_exp0['miller_index']) == len(
            set(reflections_exp0['miller_index']))
        assert len(reflections_exp1['miller_index']) == len(
            set(reflections_exp1['miller_index']))
    print "OK"
Example #13
0
def run(args):
    import libtbx.load_env
    from libtbx.utils import Sorry
    usage = "%s [options] experiments.json indexed.pickle" % libtbx.env.dispatcher_name

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

    params, options = parser.parse_args(show_diff_phil=True)

    reflections = flatten_reflections(params.input.reflections)
    experiments = flatten_experiments(params.input.experiments)
    if len(experiments) == 0 and len(reflections) == 0:
        parser.print_help()
        return
    if params.change_of_basis_op is None:
        raise Sorry("Please provide a change_of_basis_op.")

    reference_crystal = None
    if params.reference is not None:
        from dxtbx.serialize import load
        reference_experiments = load.experiment_list(params.reference,
                                                     check_format=False)
        assert len(reference_experiments.crystals()) == 1
        reference_crystal = reference_experiments.crystals()[0]

    if len(experiments) and params.change_of_basis_op is libtbx.Auto:
        if reference_crystal is not None:
            if len(experiments.crystals()) > 1:
                raise Sorry("Only one crystal can be processed at a time")
            from dials.algorithms.indexing.compare_orientation_matrices \
                 import difference_rotation_matrix_axis_angle

            cryst = experiments.crystals()[0]
            R, axis, angle, change_of_basis_op = difference_rotation_matrix_axis_angle(
                cryst, reference_crystal)
            print("Change of basis op: %s" % change_of_basis_op)
            print("Rotation matrix to transform input crystal to reference::")
            print(R.mathematica_form(format="%.3f", one_row_per_line=True))
            print("Rotation of %.3f degrees" % angle,
                  "about axis (%.3f, %.3f, %.3f)" % axis)

        elif len(reflections):
            assert len(reflections) == 1

            # always re-map reflections to reciprocal space
            from dials.algorithms.indexing import indexer
            refl_copy = flex.reflection_table()
            for i, imageset in enumerate(experiments.imagesets()):
                if 'imageset_id' in reflections[0]:
                    sel = (reflections[0]['imageset_id'] == i)
                else:
                    sel = (reflections[0]['id'] == i)
                refl = indexer.indexer_base.map_spots_pixel_to_mm_rad(
                    reflections[0].select(sel), imageset.get_detector(),
                    imageset.get_scan())

                indexer.indexer_base.map_centroids_to_reciprocal_space(
                    refl, imageset.get_detector(), imageset.get_beam(),
                    imageset.get_goniometer())
                refl_copy.extend(refl)

            # index the reflection list using the input experiments list
            refl_copy['id'] = flex.int(len(refl_copy), -1)
            from dials.algorithms.indexing import index_reflections
            index_reflections(refl_copy, experiments, tolerance=0.2)
            hkl_expt = refl_copy['miller_index']
            hkl_input = reflections[0]['miller_index']

            change_of_basis_op = derive_change_of_basis_op(hkl_input, hkl_expt)

            # reset experiments list since we don't want to reindex this
            experiments = []

    else:
        change_of_basis_op = sgtbx.change_of_basis_op(
            params.change_of_basis_op)

    if len(experiments):
        for crystal in experiments.crystals():
            cryst_orig = copy.deepcopy(crystal)
            cryst_reindexed = cryst_orig.change_basis(change_of_basis_op)
            if params.space_group is not None:
                a, b, c = cryst_reindexed.get_real_space_vectors()
                cryst_reindexed = Crystal(
                    a, b, c, space_group=params.space_group.group())
            crystal.update(cryst_reindexed)

            print("Old crystal:")
            print(cryst_orig)
            print()
            print("New crystal:")
            print(cryst_reindexed)
            print()

        print("Saving reindexed experimental models to %s" %
              params.output.experiments)
        dump.experiment_list(experiments, params.output.experiments)

    if len(reflections):
        assert (len(reflections) == 1)
        reflections = reflections[0]

        miller_indices = reflections['miller_index']

        if params.hkl_offset is not None:
            h, k, l = miller_indices.as_vec3_double().parts()
            h += params.hkl_offset[0]
            k += params.hkl_offset[1]
            l += params.hkl_offset[2]
            miller_indices = flex.miller_index(h.iround(), k.iround(),
                                               l.iround())
        non_integral_indices = change_of_basis_op.apply_results_in_non_integral_indices(
            miller_indices)
        if non_integral_indices.size() > 0:
            print(
                "Removing %i/%i reflections (change of basis results in non-integral indices)"
                % (non_integral_indices.size(), miller_indices.size()))
        sel = flex.bool(miller_indices.size(), True)
        sel.set_selected(non_integral_indices, False)
        miller_indices_reindexed = change_of_basis_op.apply(
            miller_indices.select(sel))
        reflections['miller_index'].set_selected(sel, miller_indices_reindexed)
        reflections['miller_index'].set_selected(~sel, (0, 0, 0))

        print("Saving reindexed reflections to %s" % params.output.reflections)
        easy_pickle.dump(params.output.reflections, reflections)
def get_uc_consensus(experiments_list,
                     show_plot=False,
                     return_only_first_indexed_model=False,
                     finalize_method=None,
                     clustering_params=None):
    '''
  Uses the Rodriguez Laio 2014 method to do a clustering of the unit cells and then vote for the highest
  consensus unit cell. Input needs to be a list of experiments object.
  Clustering code taken from github.com/cctbx-xfel/cluster_regression
  Returns an experiment object with crystal unit cell from the cluster with the most points
  '''
    if return_only_first_indexed_model:
        return [experiments_list[0].crystals()[0]], None
    cells = []
    from xfel.clustering.singleframe import CellOnlyFrame
    save_plot = False
    # Flag for testing Lysozyme data from NKS.Make sure cluster_regression repository is present and configured
    # Program will exit after plots are displayed if this flag is true
    test_nks = False
    if test_nks:
        from cctbx import crystal
        import libtbx.load_env
        cluster_regression = libtbx.env.find_in_repositories(
            relative_path="cluster_regression", test=os.path.isdir)
        file_name = os.path.join(cluster_regression, 'examples',
                                 'lysozyme1341.txt')
        for line in open(file_name, "r").xreadlines():
            tokens = line.strip().split()
            unit_cell = tuple(float(x) for x in tokens[0:6])
            space_group_symbol = tokens[6]
            crystal_symmetry = crystal.symmetry(
                unit_cell=unit_cell, space_group_symbol=space_group_symbol)
            cells.append(CellOnlyFrame(crystal_symmetry))
    else:
        for experiment in experiments_list:
            if len(experiment.crystals()) > 1:
                print('IOTA:Should have only one crystal model')
            crystal_symmetry = experiment.crystals()[0].get_crystal_symmetry()
            cells.append(CellOnlyFrame(crystal_symmetry))
    MM = [c.mm for c in cells]  # metrical matrices
    MM_double = flex.double()
    for i in range(len(MM)):
        Tup = MM[i]
        for j in range(6):
            MM_double.append(Tup[j])
    print('There are %d cells' % len(MM))
    coord_x = flex.double([c.uc[0] for c in cells])
    coord_y = flex.double([c.uc[1] for c in cells])
    if show_plot or save_plot:
        import matplotlib
        if not show_plot:
            matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        #from IPython import embed; embed(); exit()
        plt.plot([c.uc[0] for c in cells], [c.uc[1] for c in cells],
                 "k.",
                 markersize=3.)
        plt.axes().set_aspect("equal")
    if save_plot:
        plot_name = 'uc_cluster.png'
        plt.savefig(plot_name,
                    size_inches=(10, 10),
                    dpi=300,
                    bbox_inches='tight')
    if show_plot:
        plt.show()
    print('Now constructing a Dij matrix: Starting Unit Cell clustering')
    NN = len(MM)
    from cctbx.uctbx.determine_unit_cell import NCDist_flatten
    Dij = NCDist_flatten(MM_double)
    d_c = flex.mean_and_variance(
        Dij.as_1d()).unweighted_sample_standard_deviation()  #6.13
    #FIXME should be a PHIL param
    if len(cells) < 5:
        return [experiments_list[0].crystals()[0]], None
    CM = clustering_manager(Dij=Dij, d_c=d_c, max_percentile_rho=0.95)
    n_cluster = 1 + flex.max(CM.cluster_id_final)
    print(len(cells), ' datapoints have been analyzed')
    print('%d CLUSTERS' % n_cluster)
    for i in range(n_cluster):
        item = flex.first_index(CM.cluster_id_maxima, i)
        print('Cluster %d central Unit cell = %d' % (i, item))
        cells[item].crystal_symmetry.show_summary()

    # More plots for debugging
    appcolors = [
        'b', 'r', '#ff7f0e', '#2ca02c', '#9467bd', '#8c564b', '#e377c2',
        '#7f7f7f', '#bcbd22', '#17becf'
    ]
    if show_plot:
        # Decision graph
        import matplotlib.pyplot as plt
        plt.plot(CM.rho, CM.delta, "r.", markersize=3.)
        for x in range(NN):
            if CM.cluster_id_maxima[x] >= 0:
                plt.plot([CM.rho[x]], [CM.delta[x]], "ro")
        plt.show()

    if show_plot:
        import matplotlib.pyplot as plt
        colors = [appcolors[i % 10] for i in CM.cluster_id_full]
        plt.scatter(coord_x,
                    coord_y,
                    marker='o',
                    color=colors,
                    linewidth=0.4,
                    edgecolor='k')
        for i in range(n_cluster):
            item = flex.first_index(CM.cluster_id_maxima, i)
            plt.plot([cells[item].uc[0]], cells[item].uc[1], 'y.')
            plt.axes().set_aspect("equal")
            plt.show()
    if test_nks:
        exit()

    # Now look at each unit cell cluster for orientational clustering
    # idea is to cluster the orientational component in each of the unit cell clusters
    #
    do_orientational_clustering = not return_only_first_indexed_model  # temporary.
    dxtbx_crystal_models = []
    if do_orientational_clustering:
        print('IOTA: Starting orientational clustering')
        Dij_ori = {}  # dictionary to store Dij for each cluster
        uc_experiments_list = {
        }  # dictionary to store experiments_lists for each cluster
        from collections import Counter
        uc_cluster_count = Counter(list(CM.cluster_id_final))
        # instantiate the Dij_ori flat 1-d array
        # Put all experiments list from same uc cluster together
        if True:
            from scitbx.matrix import sqr
            from cctbx_orientation_ext import crystal_orientation
            #crystal_orientation_list = []
            #for i in range(len(experiments_list)):
            #  crystal_orientation_list.append(crystal_orientation(experiments_list[i].crystals()[0].get_A(), True))
            #from IPython import embed; embed(); exit()
            #A_direct = sqr(crystal_orientation_list[i].reciprocal_matrix()).transpose().inverse()
            #print ("Direct A matrix 1st element = %12.6f"%A_direct[0])
        for i in range(len(experiments_list)):
            if CM.cluster_id_full[i] not in uc_experiments_list:
                uc_experiments_list[CM.cluster_id_full[i]] = []
            uc_experiments_list[CM.cluster_id_full[i]].append(
                experiments_list[i])
        for cluster in uc_cluster_count:
            # Make sure there are atleast a minimum number of samples in the cluster
            if uc_cluster_count[cluster] < 5:
                continue
            Dij_ori[cluster] = flex.double(
                [[0.0] * uc_cluster_count[cluster]] *
                uc_cluster_count[cluster])
            # Now populate the Dij_ori array
            N_samples_in_cluster = len(uc_experiments_list[cluster])
            for i in range(N_samples_in_cluster - 1):
                for j in range(i + 1, N_samples_in_cluster):
                    dij_ori = get_dij_ori(
                        uc_experiments_list[cluster][i].crystals()[0],
                        uc_experiments_list[cluster][j].crystals()[0])
                    Dij_ori[cluster][N_samples_in_cluster * i + j] = dij_ori
                    Dij_ori[cluster][N_samples_in_cluster * j + i] = dij_ori

        # Now do the orientational cluster analysis
        #from IPython import embed; embed(); exit()
        d_c_ori = 0.13
        from exafel_project.ADSE13_25.clustering.plot_with_dimensional_embedding import plot_with_dimensional_embedding
        #plot_with_dimensional_embedding(1-Dij_ori[1]/flex.max(Dij_ori[1]), show_plot=True)
        for cluster in Dij_ori:
            d_c_ori = flex.mean_and_variance(Dij_ori[cluster].as_1d(
            )).unweighted_sample_standard_deviation()
            CM_ori = clustering_manager(Dij=Dij_ori[cluster],
                                        d_c=d_c_ori,
                                        max_percentile_rho=0.85)
            n_cluster_ori = 1 + flex.max(CM_ori.cluster_id_final)
            #from IPython import embed; embed()
            #FIXME should be a PHIL param
            for i in range(n_cluster_ori):
                if len([zz for zz in CM_ori.cluster_id_final if zz == i]) < 5:
                    continue
                item = flex.first_index(CM_ori.cluster_id_maxima, i)
                dxtbx_crystal_model = uc_experiments_list[cluster][
                    item].crystals()[0]
                dxtbx_crystal_models.append(dxtbx_crystal_model)
                from scitbx.matrix import sqr
                from cctbx_orientation_ext import crystal_orientation
                crystal_orientation = crystal_orientation(
                    dxtbx_crystal_model.get_A(), True)
                A_direct = sqr(crystal_orientation.reciprocal_matrix()
                               ).transpose().inverse()
                print(
                    "IOTA: Direct A matrix 1st element of orientational cluster %d  = %12.6f"
                    % (i, A_direct[0]))
            if show_plot:
                # Decision graph
                stretch_plot_factor = 1.05  # (1+fraction of limits by which xlim,ylim should be set)
                import matplotlib.pyplot as plt
                plt.plot(CM_ori.rho, CM_ori.delta, "r.", markersize=3.)
                for x in range(len(list(CM_ori.cluster_id_final))):
                    if CM_ori.cluster_id_maxima[x] >= 0:
                        plt.plot([CM_ori.rho[x]], [CM_ori.delta[x]], "ro")
                #from IPython import embed; embed(); exit()
                plt.xlim([-10, stretch_plot_factor * flex.max(CM_ori.rho)])
                plt.ylim([-10, stretch_plot_factor * flex.max(CM_ori.delta)])
                plt.show()
    # Make sure the crystal models are not too close to each other
    # FIXME should be a PHIL
    min_angle = 5.0  # taken from indexer.py
    close_models_list = []
    if len(dxtbx_crystal_models) > 1:
        from dials.algorithms.indexing.compare_orientation_matrices import difference_rotation_matrix_axis_angle
        for i_a in range(0, len(dxtbx_crystal_models) - 1):
            for i_b in range(i_a, len(dxtbx_crystal_models)):
                cryst_a = dxtbx_crystal_models[i_a]
                cryst_b = dxtbx_crystal_models[i_b]
                R_ab, axis, angle, cb_op_ab = difference_rotation_matrix_axis_angle(
                    cryst_a, cryst_b)
                # FIXME
                if abs(angle) < min_angle:  # degrees
                    close_models_list.append((i_a, i_b))

    # Now prune the dxtbx_crystal_models list
    for close_models in close_models_list:
        i_a, i_b = close_models
        if dxtbx_crystal_models[i_a] is not None and dxtbx_crystal_models[
                i_b] is not None:
            dxtbx_crystal_models[i_a] = None

    dxtbx_crystal_models = [x for x in dxtbx_crystal_models if x is not None]
    if len(dxtbx_crystal_models) > 0:
        return dxtbx_crystal_models, None
    else:
        # If nothing works, atleast return the 1st crystal model that was found
        return [experiments_list[0].crystals()[0]], None
Example #15
0
def run(args):
    import libtbx.load_env
    from dials.util import Sorry

    usage = "dials.reindex [options] indexed.expt indexed.refl"

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

    params, options = parser.parse_args(show_diff_phil=True)

    reflections = flatten_reflections(params.input.reflections)
    experiments = flatten_experiments(params.input.experiments)
    if len(experiments) == 0 and len(reflections) == 0:
        parser.print_help()
        return
    if params.change_of_basis_op is None:
        raise Sorry("Please provide a change_of_basis_op.")

    reference_crystal = None
    if params.reference.experiments is not None:
        from dxtbx.serialize import load

        reference_experiments = load.experiment_list(
            params.reference.experiments, check_format=False)
        assert len(reference_experiments.crystals()) == 1
        reference_crystal = reference_experiments.crystals()[0]

    if params.reference.reflections is not None:
        # First check that we have everything as expected for the reference reindexing
        # Currently only supports reindexing one dataset at a time
        if params.reference.experiments is None:
            raise Sorry(
                """For reindexing against a reference dataset, a reference
experiments file must also be specified with the option: reference= """)
        if not os.path.exists(params.reference.reflections):
            raise Sorry("Could not locate reference dataset reflection file")
        if len(experiments) != 1 or len(reflections) != 1:
            raise Sorry(
                "Only one dataset can be reindexed to a reference at a time")

        reference_reflections = flex.reflection_table().from_file(
            params.reference.reflections)

        test_reflections = reflections[0]

        if (reference_crystal.get_space_group().type().number() !=
                experiments.crystals()[0].get_space_group().type().number()):
            raise Sorry("Space group of input does not match reference")

        # Set some flags to allow filtering, if wanting to reindex against
        # reference with data that has not yet been through integration
        if (test_reflections.get_flags(
                test_reflections.flags.integrated_sum).count(True) == 0):
            assert (
                "intensity.sum.value"
                in test_reflections), "No 'intensity.sum.value' in reflections"
            test_reflections.set_flags(
                flex.bool(test_reflections.size(), True),
                test_reflections.flags.integrated_sum,
            )
        if (reference_reflections.get_flags(
                reference_reflections.flags.integrated_sum).count(True) == 0):
            assert ("intensity.sum.value" in test_reflections
                    ), "No 'intensity.sum.value in reference reflections"
            reference_reflections.set_flags(
                flex.bool(reference_reflections.size(), True),
                reference_reflections.flags.integrated_sum,
            )

        # Make miller array of the two datasets
        try:
            test_miller_set = filtered_arrays_from_experiments_reflections(
                experiments, [test_reflections])[0]
        except ValueError:
            raise Sorry(
                "No reflections remain after filtering the test dataset")
        try:
            reference_miller_set = filtered_arrays_from_experiments_reflections(
                reference_experiments, [reference_reflections])[0]
        except ValueError:
            raise Sorry(
                "No reflections remain after filtering the reference dataset")

        from dials.algorithms.symmetry.reindex_to_reference import (
            determine_reindex_operator_against_reference, )

        change_of_basis_op = determine_reindex_operator_against_reference(
            test_miller_set, reference_miller_set)

    elif len(experiments) and params.change_of_basis_op is libtbx.Auto:
        if reference_crystal is not None:
            if len(experiments.crystals()) > 1:
                raise Sorry("Only one crystal can be processed at a time")
            from dials.algorithms.indexing.compare_orientation_matrices import (
                difference_rotation_matrix_axis_angle, )

            cryst = experiments.crystals()[0]
            R, axis, angle, change_of_basis_op = difference_rotation_matrix_axis_angle(
                cryst, reference_crystal)
            print("Change of basis op: %s" % change_of_basis_op)
            print("Rotation matrix to transform input crystal to reference::")
            print(R.mathematica_form(format="%.3f", one_row_per_line=True))
            print(
                "Rotation of %.3f degrees" % angle,
                "about axis (%.3f, %.3f, %.3f)" % axis,
            )

        elif len(reflections):
            assert len(reflections) == 1

            # always re-map reflections to reciprocal space
            refl_copy = flex.reflection_table()
            for i, imageset in enumerate(experiments.imagesets()):
                if "imageset_id" in reflections[0]:
                    sel = reflections[0]["imageset_id"] == i
                else:
                    sel = reflections[0]["id"] == i
                refl = reflections[0].select(sel)
                refl.centroid_px_to_mm(imageset.get_detector(),
                                       imageset.get_scan())
                refl.map_centroids_to_reciprocal_space(
                    imageset.get_detector(),
                    imageset.get_beam(),
                    imageset.get_goniometer(),
                )
                refl_copy.extend(refl)

            # index the reflection list using the input experiments list
            refl_copy["id"] = flex.int(len(refl_copy), -1)
            index = AssignIndicesGlobal(tolerance=0.2)
            index(refl_copy, experiments)
            hkl_expt = refl_copy["miller_index"]
            hkl_input = reflections[0]["miller_index"]

            change_of_basis_op = derive_change_of_basis_op(hkl_input, hkl_expt)

            # reset experiments list since we don't want to reindex this
            experiments = []

    else:
        change_of_basis_op = sgtbx.change_of_basis_op(
            params.change_of_basis_op)

    if len(experiments):
        for crystal in experiments.crystals():
            cryst_orig = copy.deepcopy(crystal)
            cryst_reindexed = cryst_orig.change_basis(change_of_basis_op)
            if params.space_group is not None:
                a, b, c = cryst_reindexed.get_real_space_vectors()
                A_varying = [
                    cryst_reindexed.get_A_at_scan_point(i)
                    for i in range(cryst_reindexed.num_scan_points)
                ]
                cryst_reindexed = Crystal(
                    a, b, c, space_group=params.space_group.group())
                cryst_reindexed.set_A_at_scan_points(A_varying)
            crystal.update(cryst_reindexed)

            print("Old crystal:")
            print(cryst_orig)
            print()
            print("New crystal:")
            print(cryst_reindexed)
            print()

        print("Saving reindexed experimental models to %s" %
              params.output.experiments)
        experiments.as_file(params.output.experiments)

    if len(reflections):
        assert len(reflections) == 1
        reflections = reflections[0]

        miller_indices = reflections["miller_index"]

        if params.hkl_offset is not None:
            h, k, l = miller_indices.as_vec3_double().parts()
            h += params.hkl_offset[0]
            k += params.hkl_offset[1]
            l += params.hkl_offset[2]
            miller_indices = flex.miller_index(h.iround(), k.iround(),
                                               l.iround())
        non_integral_indices = change_of_basis_op.apply_results_in_non_integral_indices(
            miller_indices)
        if non_integral_indices.size() > 0:
            print(
                "Removing %i/%i reflections (change of basis results in non-integral indices)"
                % (non_integral_indices.size(), miller_indices.size()))
        sel = flex.bool(miller_indices.size(), True)
        sel.set_selected(non_integral_indices, False)
        miller_indices_reindexed = change_of_basis_op.apply(
            miller_indices.select(sel))
        reflections["miller_index"].set_selected(sel, miller_indices_reindexed)
        reflections["miller_index"].set_selected(~sel, (0, 0, 0))

        print("Saving reindexed reflections to %s" % params.output.reflections)
        easy_pickle.dump(params.output.reflections, reflections)
Example #16
0
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))
Example #17
0
def run(args):
  import libtbx.load_env
  from dials.util.options import OptionParser
  from dials.util.options import flatten_experiments

  # The script usage
  usage = "usage: %s [options] [param.phil] experiments.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 not experiments:
    parser.print_help()
    return

  if not params.hkl and params.hkl_limit is None:
    from libtbx.utils import Sorry
    raise Sorry("Please provide hkl or hkl_limit parameters.")

  if params.hkl is not None and len(params.hkl):
    miller_indices = flex.miller_index(params.hkl)
  elif params.hkl_limit is not None:
    limit = params.hkl_limit
    miller_indices = flex.miller_index()
    for h in range(-limit, limit+1):
      for k in range(-limit, limit+1):
        for l in range(-limit, limit+1):
          if (h,k,l) == (0,0,0): continue
          miller_indices.append((h,k,l))

  crystals = experiments.crystals()

  symmetry = crystal.symmetry(
    unit_cell=crystals[0].get_unit_cell(),
    space_group=crystals[0].get_space_group())
  miller_set = miller.set(symmetry, miller_indices)
  d_spacings = miller_set.d_spacings()
  if params.eliminate_sys_absent:
    d_spacings = d_spacings.eliminate_sys_absent()
  if params.expand_to_p1:
    d_spacings = d_spacings.as_non_anomalous_array().expand_to_p1()
    d_spacings = d_spacings.generate_bijvoet_mates()
  miller_indices = d_spacings.indices()

  # find the greatest common factor (divisor) between miller indices
  miller_indices_unique = flex.miller_index()
  for hkl in miller_indices:
    gcd = gcd_list(hkl)
    if gcd > 1:
      miller_indices_unique.append(tuple(int(h/gcd) for h in hkl))
    elif gcd < 1:
      pass
    else:
      miller_indices_unique.append(hkl)
  miller_indices = miller_indices_unique
  miller_indices = flex.miller_index(list(set(miller_indices)))

  ref_crystal = crystals[0]
  A = ref_crystal.get_A()
  U = ref_crystal.get_U()
  B = ref_crystal.get_B()
  R = matrix.identity(3)

  if params.frame == 'laboratory':
    reference_poles = reference_poles_perpendicular_to_beam(
      experiments[0].beam, experiments[0].goniometer)
    if params.use_starting_angle:
      rotation_axis = matrix.col(
        experiments[0].goniometer.get_rotation_axis())
      R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
        experiments[0].scan.get_oscillation()[0], deg=True)
    elif params.phi_angle != 0:
      rotation_axis = matrix.col(
        experiments[0].goniometer.get_rotation_axis())
      R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
        params.phi_angle, deg=True)
  else:
    if params.plane_normal is not None:
      plane_normal = params.plane_normal
    else:
      plane_normal = (0,0,1)
    reference_poles = reference_poles_crystal(
      ref_crystal, plane_normal=plane_normal)

  if params.frame == 'crystal':
    U = matrix.identity(3)

  reciprocal_space_points = list(R * U * B) * miller_indices.as_vec3_double()
  projections_ref = stereographic_projection(
    reciprocal_space_points, reference_poles)

  projections_all = [projections_ref]

  if experiments:
    from dials.algorithms.indexing.compare_orientation_matrices import \
        difference_rotation_matrix_axis_angle

    for expt in experiments[1:]:
      cryst = expt.crystal
      if params.frame == 'crystal':
        R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
          ref_crystal, cryst)
        U = R_ij
      elif params.use_starting_angle:
        if params.use_starting_angle:
          rotation_axis = matrix.col(
            expt.goniometer.get_rotation_axis())
          R = rotation_axis.axis_and_angle_as_r3_rotation_matrix(
            expt.scan.get_oscillation()[0], deg=True)
      else:
        U = cryst.get_U()
      reciprocal_space_points = list(R * U * cryst.get_B()) * miller_indices.as_vec3_double()
      projections = stereographic_projection(
        reciprocal_space_points, reference_poles)
      projections_all.append(projections)

  if params.save_coordinates:
    with open('projections.txt', 'wb') as f:
      print >> f, "crystal h k l x y"
      for i_cryst, projections in enumerate(projections_all):
        for hkl, proj in zip(miller_indices, projections):
          print >> f, "%i" %(i_cryst+1),
          print >> f, "%i %i %i" %hkl,
          print >> f, "%f %f" %proj

  if params.plot.show or params.plot.filename:
    plot_projections(
      projections_all, filename=params.plot.filename, show=params.plot.show,
      colours=params.plot.colours, marker_size=params.plot.marker_size,
      font_size=params.plot.font_size, label_indices=params.plot.label_indices)
Example #18
0
    def index(self, provided_experiments=None, debug=False):
        ''' This step does  1. find_lattices (via a method like fft1d)
                        2. Assign hkl indices (through index_reflections)
                        3. Housekeeping like apply_symmetry, discard too similar models
    '''

        experiments = ExperimentList()
        have_similar_crystal_models = False

        self.d_min = self.params.refinement_protocol.d_min_start

        # Find lattices i.e the basis vectors & unit cell params
        # Possible to index multiple lattices  ??
        while True:
            max_lattices = self.params.multiple_lattice_search.max_lattices
            if max_lattices is not None and len(experiments) >= max_lattices:
                break
            n_lattices_previous_cycle = len(experiments)
            if len(experiments) == 0:
                experiments.extend(self.find_lattices())
            else:
                try:
                    new = self.find_lattices()
                    experiments.extend(new)
                except Sorry:
                    print('Indexing remaining reflections failed')
                    break

            if len(experiments) == 0:
                raise Sorry("No suitable lattice could be found.")

            # Initialize id values as -1 since no indexing has been done yet
            self.reflections['id'] = flex.int(len(self.reflections), -1)

            # Now index reflections
            self.index_reflections(experiments, self.reflections, debug=debug)

            # Housekeeping. Apply symmetry
            self._apply_symmetry_post_indexing(experiments, self.reflections,
                                               n_lattices_previous_cycle)

            # Aug_Refactor :: probably unnecessary to remove stuff below but still doing so to adapt to new style
            # Never mind, might keep it to have IOTA stuff working
            '''
      target_space_group = self.target_symmetry_primitive.space_group()
      for i_cryst, cryst in enumerate(experiments.crystals()):
        if i_cryst >= n_lattices_previous_cycle:
          new_cryst, cb_op_to_primitive = self.apply_symmetry(
                                        cryst, target_space_group)
          if provided_experiments is None:
            if self.cb_op_primitive_inp is not None:
              new_cryst = new_cryst.change_basis(self.cb_op_primitive_inp)
              logger.info(new_cryst.get_space_group().info())
            cryst.update(new_cryst)
            cryst.set_space_group(
                self.params.known_symmetry.space_group.group())
          for i_expt, expt in enumerate(experiments):
            if expt.crystal is not cryst:
              continue
            if not cb_op_to_primitive.is_identity_op():
              miller_indices = self.reflections['miller_index'].select(
                  self.reflections['id'] == i_expt)

              if provided_experiments is None:
                miller_indices = cb_op_to_primitive.apply(miller_indices)
              self.reflections['miller_index'].set_selected(
                  self.reflections['id'] == i_expt, miller_indices)

            if self.cb_op_primitive_inp is not None:
              miller_indices = self.reflections['miller_index'].select(
                  self.reflections['id'] == i_expt)

              if provided_experiments is None:
                miller_indices = self.cb_op_primitive_inp.apply(miller_indices)
              self.reflections['miller_index'].set_selected(
                  self.reflections['id'] == i_expt, miller_indices)
              # IOTA
              from scitbx.matrix import sqr
              hklfrac=flex.mat3_double(len(miller_indices), sqr(cryst.get_A()).inverse())*self.reflections['rlp'].select(self.reflections['id']==i_expt)
              self.reflections['fractional_miller_index'].set_selected(self.reflections['id']==i_expt, hklfrac)
    '''

        logger.info("\nIndexed crystal models:")
        self.show_experiments(experiments, self.reflections, d_min=self.d_min)

        # Discard nearly overlapping lattices
        # difference_rotation_matrix_axis_angle function is there still in DIALS 2.0 so no need to change anything below
        if len(experiments) > 1:
            from dials.algorithms.indexing.compare_orientation_matrices \
              import difference_rotation_matrix_axis_angle
            cryst_b = experiments.crystals()[-1]
            have_similar_crystal_models = False
            for i_a, cryst_a in enumerate(experiments.crystals()[:-1]):
                R_ab, axis, angle, cb_op_ab = \
                difference_rotation_matrix_axis_angle(cryst_a, cryst_b)
                min_angle = self.params.multiple_lattice_search.minimum_angular_separation
                if abs(angle) < min_angle:  # degrees
                    logger.info(
                        "Crystal models too similar, rejecting crystal %i:" %
                        (len(experiments)))
                    logger.info(
                        "Rotation matrix to transform crystal %i to crystal %i"
                        % (i_a + 1, len(experiments)))
                    logger.info(R_ab)
                    logger.info("Rotation of %.3f degrees" % angle +
                                " about axis (%.3f, %.3f, %.3f)" % axis)
                    have_similar_crystal_models = True
                    del experiments[-1]
                    break

        self.indexed_reflections = (self.reflections['id'] > -1)
        self.experiments = experiments
Example #19
0
            print("Opened %d / %d indexing results" % (i_f, len(fnames)))
        refls_good.append( f)
        Els_good.append(El_f)
        dumps_good.append(dump_f)
        
        idx_cryst_mdl = utils.open_flex(dump_f)["crystalAB"]
        cryst_good.append(idx_cryst_mdl)
        Ex = ExperimentListFactory.from_json_file(El_f, check_format=False)
        img_path = Ex[0].imageset.get_path(0)
        h5 = h5py.File(img_path, "r")
        Atruth = h5["crystalA"][()]
        
        truth_cryst = deepcopy(idx_cryst_mdl)
        truth_cryst.set_A(Atruth)
        
        out = difference_rotation_matrix_axis_angle(idx_cryst_mdl, truth_cryst)
        all_rots.append(out[2])


from IPython import embed
embed()

"""

Els_good
len( refls_good)
len( Els_good)
import dxtbx
ff
E = ff[0]
E.imageset
Example #20
0
def run(args=None):
    from dials.util.options import OptionParser, flatten_experiments

    usage = "dials.goniometer_calibration [options] models.expt"

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

    params, options = parser.parse_args(args, show_diff_phil=True)
    if not params.use_space_group_from_experiments and params.space_group is None:
        parser.print_help()
        return

    experiments = flatten_experiments(params.input.experiments)
    if len(experiments) <= 1:
        parser.print_help()
        return

    from dials.algorithms.indexing.compare_orientation_matrices import (
        difference_rotation_matrix_axis_angle, )

    for experiment in experiments:
        crystal = experiment.crystal
        gonio = experiment.goniometer
        assert len(experiments) == (len(gonio.get_axes()) + 1)
        scan = experiment.scan
        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)
        U = matrix.sqr(crystal.get_U())
        U = setting_rotation * rotation_matrix * fixed_rotation * U
        crystal.set_U(U)
        if params.space_group is not None:
            crystal.set_space_group(params.space_group.group())

    rows = []

    from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame

    R_to_mosflm = align_reference_frame(
        experiments[0].beam.get_s0(),
        (1.0, 0.0, 0.0),
        experiments[0].goniometer.get_rotation_axis(),
        (0.0, 0.0, 1.0),
    )

    axes = []
    angles = []

    for i in range(len(experiments) - 1):
        target_angle = experiments[i + 1].goniometer.get_angles()[i]
        if i == experiments[i].goniometer.get_scan_axis():
            # rotation axis is canonical in our coordinate system
            axis = experiments[i].goniometer.get_axes()[i]
            angle = target_angle
        else:
            R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
                experiments[i].crystal,
                experiments[i + 1].crystal,
                target_angle=target_angle,
            )
        gonio = experiments[i + 1].goniometer
        axis_names = gonio.get_names()
        axes.append(axis)
        angles.append(angle)
        depends_on = "."
        if i + 1 < len(axis_names):
            depends_on = axis_names[i + 1]
        rows.insert(
            0,
            (
                axis_names[i],
                "rotation",
                "goniometer",
                depends_on,
                f"{axis[0]:.4f}",
                f"{axis[1]:.4f}",
                f"{axis[2]:.4f}",
                ".",
                ".",
                ".",
            ),
        )

    axis_names = experiments[0].goniometer.get_names()
    print("Goniometer axes and angles (ImgCIF coordinate system):")
    for axis, angle, name in zip(axes, angles, axis_names):
        print(
            f"{name}: ",
            f"rotation of {angle:.3f} degrees",
            "about axis (%.5f,%.5f,%.5f)" % axis,
        )

    print()
    print("Goniometer axes and angles (MOSFLM coordinate system):")
    for axis, angle, name in zip(axes, angles, axis_names):
        print(
            f"{name}: ",
            f"rotation of {angle:.3f} degrees",
            "about axis (%.5f,%.5f,%.5f)" %
            (R_to_mosflm * matrix.col(axis)).elems,
        )

    print()
    print("ImgCIF _axis loop template:")
    from iotbx import cif

    loop = cif.model.loop(header=[
        "_axis.id",
        "_axis.type",
        "_axis.equipment",
        "_axis.depends_on",
        "_axis.vector[1]",
        "_axis.vector[2]",
        "_axis.vector[3]",
        "_axis.offset[1]",
        "_axis.offset[2]",
        "_axis.offset[3]",
    ])
    for row in rows:
        loop.add_row(row)

    print(loop)

    if params.output.xoalign is not None:
        axes_mosflm = [(R_to_mosflm * matrix.col(axis)).elems for axis in axes]
        write_xoalign_config(params.output.xoalign, reversed(axes_mosflm),
                             reversed(axis_names))
Example #21
0
def run(args):

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

  usage = "%s [options] experiments.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) <= 1:
    parser.print_help()
    return

  from dials.algorithms.indexing.compare_orientation_matrices import \
       difference_rotation_matrix_axis_angle
  from scitbx import matrix
  crystals = []
  for experiment in experiments:
    crystal = experiment.crystal
    gonio = experiment.goniometer
    assert len(experiments) == (len(gonio.get_axes())+1)
    scan = experiment.scan
    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)
    U = matrix.sqr(crystal.get_U())
    U = setting_rotation * rotation_matrix * fixed_rotation * U
    crystal.set_U(U)
    if params.space_group is not None:
      crystal.set_space_group(params.space_group.group())

  rows = []

  from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame
  from scitbx import matrix
  R_to_mosflm = align_reference_frame(
    experiments[0].beam.get_s0(), (1.0, 0.0, 0.0),
    experiments[0].goniometer.get_rotation_axis(), (0.0, 0.0, 1.0))

  axes = []
  angles = []

  for i in range(len(experiments) - 1):
    target_angle = experiments[i+1].goniometer.get_angles()[i]
    R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
      experiments[i].crystal, experiments[i+1].crystal, target_angle=target_angle)
    gonio = experiments[i+1].goniometer
    axis_names = gonio.get_names()
    axes.append(axis)
    angles.append(angle)
    depends_on = '.'
    if i+1 < len(axis_names):
      depends_on = axis_names[i+1]
    rows.insert(0, (
      axis_names[i], 'rotation', 'goniometer', depends_on,
      '%.4f' %axis[0], '%.4f' %axis[1], '%.4f' %axis[2], '.', '.', '.'))

  axis_names = experiments[0].goniometer.get_names()
  print "Goniometer axes and angles (ImgCIF coordinate system):"
  for axis, angle, name in zip(axes, angles, axis_names):
    print "%s: " %name, "rotation of %.3f degrees" %angle, "about axis (%.5f, %.5f, %.5f)" %axis

  print
  print "Goniometer axes and angles (MOSFLM coordinate system):"
  for axis, angle, name in zip(axes, angles, axis_names):
    print "%s: " %name, "rotation of %.3f degrees" %angle, "about axis (%.5f, %.5f, %.5f)" %(
      R_to_mosflm * matrix.col(axis)).elems

  print
  print "ImgCIF _axis loop template:"
  from iotbx import cif
  loop = cif.model.loop(
    header=['_axis.id', '_axis.type', '_axis.equipment', '_axis.depends_on',
            '_axis.vector[1]', '_axis.vector[2]', '_axis.vector[3]',
            '_axis.offset[1]', '_axis.offset[2]', '_axis.offset[3]'])
  for row in reversed(rows):
    loop.add_row(row)

  print loop

  if params.output.xoalign is not None:
    write_xoalign_config(params.output.xoalign, axes, axis_names)
def run(args):

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

    usage = "%s [options] experiments.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) <= 1:
        parser.print_help()
        return

    from dials.algorithms.indexing.compare_orientation_matrices import \
         difference_rotation_matrix_axis_angle
    from scitbx import matrix
    crystals = []
    for experiment in experiments:
        crystal = experiment.crystal
        gonio = experiment.goniometer
        assert len(experiments) == (len(gonio.get_axes()) + 1)
        scan = experiment.scan
        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)
        U = matrix.sqr(crystal.get_U())
        U = setting_rotation * rotation_matrix * fixed_rotation * U
        crystal.set_U(U)
        if params.space_group is not None:
            crystal.set_space_group(params.space_group.group())

    rows = []

    from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame
    from scitbx import matrix
    R_to_mosflm = align_reference_frame(
        experiments[0].beam.get_s0(), (1.0, 0.0, 0.0),
        experiments[0].goniometer.get_rotation_axis(), (0.0, 0.0, 1.0))

    axes = []
    angles = []

    for i in range(len(experiments) - 1):
        target_angle = experiments[i + 1].goniometer.get_angles()[i]
        if i == experiments[i].goniometer.get_scan_axis():
            # rotation axis is canonical in our coordinate system
            axis = experiments[i].goniometer.get_axes()[i]
            angle = target_angle
        else:
            R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle(
                experiments[i].crystal,
                experiments[i + 1].crystal,
                target_angle=target_angle)
        gonio = experiments[i + 1].goniometer
        axis_names = gonio.get_names()
        axes.append(axis)
        angles.append(angle)
        depends_on = '.'
        if i + 1 < len(axis_names):
            depends_on = axis_names[i + 1]
        rows.insert(
            0, (axis_names[i], 'rotation', 'goniometer', depends_on, '%.4f' %
                axis[0], '%.4f' % axis[1], '%.4f' % axis[2], '.', '.', '.'))

    axis_names = experiments[0].goniometer.get_names()
    print "Goniometer axes and angles (ImgCIF coordinate system):"
    for axis, angle, name in zip(axes, angles, axis_names):
        print "%s: " % name, "rotation of %.3f degrees" % angle, "about axis (%.5f,%.5f,%.5f)" % axis

    print
    print "Goniometer axes and angles (MOSFLM coordinate system):"
    for axis, angle, name in zip(axes, angles, axis_names):
        print "%s: " % name, "rotation of %.3f degrees" % angle, "about axis (%.5f,%.5f,%.5f)" % (
            R_to_mosflm * matrix.col(axis)).elems

    print
    print "ImgCIF _axis loop template:"
    from iotbx import cif
    loop = cif.model.loop(header=[
        '_axis.id', '_axis.type', '_axis.equipment', '_axis.depends_on',
        '_axis.vector[1]', '_axis.vector[2]', '_axis.vector[3]',
        '_axis.offset[1]', '_axis.offset[2]', '_axis.offset[3]'
    ])
    for row in rows:
        loop.add_row(row)

    print loop

    if params.output.xoalign is not None:
        axes_mosflm = [(R_to_mosflm * matrix.col(axis)).elems for axis in axes]
        write_xoalign_config(params.output.xoalign, reversed(axes_mosflm),
                             reversed(axis_names))
Example #23
0
def run(args):
  import libtbx.load_env
  from libtbx.utils import Sorry
  usage = "%s [options] experiments.json indexed.pickle" %libtbx.env.dispatcher_name

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

  params, options = parser.parse_args(show_diff_phil=True)

  reflections = flatten_reflections(params.input.reflections)
  experiments = flatten_experiments(params.input.experiments)
  if len(experiments) == 0 and len(reflections) == 0:
    parser.print_help()
    return
  elif len(experiments.crystals()) > 1:
    raise Sorry("Only one crystal can be processed at a time")
  if params.change_of_basis_op is None:
    raise Sorry("Please provide a change_of_basis_op.")

  reference_crystal = None
  if params.reference is not None:
    from dxtbx.serialize import load
    reference_experiments = load.experiment_list(
      params.reference, check_format=False)
    assert len(reference_experiments.crystals()) == 1
    reference_crystal = reference_experiments.crystals()[0]

  if len(experiments) and params.change_of_basis_op is libtbx.Auto:
    if reference_crystal is not None:
      from dials.algorithms.indexing.compare_orientation_matrices \
           import difference_rotation_matrix_axis_angle

      cryst = experiments.crystals()[0]
      R, axis, angle, change_of_basis_op = difference_rotation_matrix_axis_angle(
        cryst, reference_crystal)
      print "Change of basis op: %s" %change_of_basis_op
      print "Rotation matrix to transform input crystal to reference::"
      print R.mathematica_form(format="%.3f", one_row_per_line=True)
      print "Rotation of %.3f degrees" %angle, "about axis (%.3f, %.3f, %.3f)" %axis

    elif len(reflections):
      assert len(reflections) == 1

      # always re-map reflections to reciprocal space
      from dials.algorithms.indexing import indexer
      refl_copy = flex.reflection_table()
      for i, imageset in enumerate(experiments.imagesets()):
        if 'imageset_id' in reflections[0]:
          sel = (reflections[0]['imageset_id'] == i)
        else:
          sel = (reflections[0]['id'] == i)
        refl = indexer.indexer_base.map_spots_pixel_to_mm_rad(
          reflections[0].select(sel),
          imageset.get_detector(), imageset.get_scan())

        indexer.indexer_base.map_centroids_to_reciprocal_space(
          refl, imageset.get_detector(), imageset.get_beam(),
          imageset.get_goniometer())
        refl_copy.extend(refl)

      # index the reflection list using the input experiments list
      refl_copy['id'] = flex.int(len(refl_copy), -1)
      from dials.algorithms.indexing import index_reflections
      index_reflections(refl_copy, experiments, tolerance=0.2)
      hkl_expt = refl_copy['miller_index']
      hkl_input = reflections[0]['miller_index']

      change_of_basis_op = derive_change_of_basis_op(hkl_input, hkl_expt)

      # reset experiments list since we don't want to reindex this
      experiments = []

  else:
    change_of_basis_op = sgtbx.change_of_basis_op(params.change_of_basis_op)

  if len(experiments):
    experiment = experiments[0]
    cryst_orig = copy.deepcopy(experiment.crystal)
    cryst_reindexed = cryst_orig.change_basis(change_of_basis_op)
    if params.space_group is not None:
      a, b, c = cryst_reindexed.get_real_space_vectors()
      cryst_reindexed = crystal_model(
        a, b, c, space_group=params.space_group.group())
    experiment.crystal.update(cryst_reindexed)

    print "Old crystal:"
    print cryst_orig
    print
    print "New crystal:"
    print cryst_reindexed
    print

    print "Saving reindexed experimental models to %s" %params.output.experiments
    dump.experiment_list(experiments, params.output.experiments)

  if len(reflections):
    assert(len(reflections) == 1)
    reflections = reflections[0]

    miller_indices = reflections['miller_index']

    if params.hkl_offset is not None:
      h,k,l = miller_indices.as_vec3_double().parts()
      h += params.hkl_offset[0]
      k += params.hkl_offset[1]
      l += params.hkl_offset[2]
      miller_indices = flex.miller_index(h.iround(), k.iround(), l.iround())
    non_integral_indices = change_of_basis_op.apply_results_in_non_integral_indices(miller_indices)
    if non_integral_indices.size() > 0:
      print "Removing %i/%i reflections (change of basis results in non-integral indices)" %(
      non_integral_indices.size(), miller_indices.size())
    sel = flex.bool(miller_indices.size(), True)
    sel.set_selected(non_integral_indices, False)
    miller_indices_reindexed = change_of_basis_op.apply(
      miller_indices.select(sel))
    reflections['miller_index'].set_selected(sel, miller_indices_reindexed)
    reflections['miller_index'].set_selected(~sel, (0,0,0))

    print "Saving reindexed reflections to %s" %params.output.reflections
    easy_pickle.dump(params.output.reflections, reflections)
Example #24
0
    def index(self):
        # most of this is the same as dials.algorithms.indexing.indexer.indexer_base.index(), with some stills
        # specific modifications (don't re-index after choose best orientation matrix, but use the indexing from
        # choose best orientation matrix, also don't use macrocycles) of refinement after indexing.
        # 2017 update: do accept multiple lattices per shot
        if self.params.refinement_protocol.n_macro_cycles > 1:
            raise Sorry(
                "For stills, please set refinement_protocol.n_macro_cycles = 1"
            )

        experiments = ExperimentList()

        had_refinement_error = False
        have_similar_crystal_models = False

        while True:
            self.d_min = self.params.refinement_protocol.d_min_start
            if had_refinement_error or have_similar_crystal_models:
                break
            max_lattices = self.params.multiple_lattice_search.max_lattices
            if max_lattices is not None and len(experiments) >= max_lattices:
                break
            if len(experiments) > 0:
                cutoff_fraction = \
                  self.params.multiple_lattice_search.recycle_unindexed_reflections_cutoff
                d_spacings = 1 / self.reflections['rlp'].norms()
                d_min_indexed = flex.min(
                    d_spacings.select(self.indexed_reflections))
                min_reflections_for_indexing = \
                  cutoff_fraction * len(self.reflections.select(d_spacings > d_min_indexed))
                crystal_ids = self.reflections.select(
                    d_spacings > d_min_indexed)['id']
                if (crystal_ids
                        == -1).count(True) < min_reflections_for_indexing:
                    logger.info(
                        "Finish searching for more lattices: %i unindexed reflections remaining."
                        % (min_reflections_for_indexing))
                    break

            n_lattices_previous_cycle = len(experiments)

            # index multiple lattices per shot
            if len(experiments) == 0:
                experiments.extend(self.find_lattices())
                if len(experiments) == 0:
                    raise Sorry("No suitable lattice could be found.")
            else:
                try:
                    new = self.find_lattices()
                    experiments.extend(new)
                except Exception as e:
                    logger.info("Indexing remaining reflections failed")
                    logger.debug(
                        "Indexing remaining reflections failed, exception:\n" +
                        str(e))

            # reset reflection lattice flags
            # the lattice a given reflection belongs to: a value of -1 indicates
            # that a reflection doesn't belong to any lattice so far
            self.reflections['id'] = flex.int(len(self.reflections), -1)

            self.index_reflections(experiments, self.reflections)

            if len(experiments) == n_lattices_previous_cycle:
                # no more lattices found
                break

            if not self.params.stills.refine_candidates_with_known_symmetry and self.params.known_symmetry.space_group is not None:
                # now apply the space group symmetry only after the first indexing
                # need to make sure that the symmetrized orientation is similar to the P1 model
                target_space_group = self.target_symmetry_primitive.space_group(
                )
                for i_cryst, cryst in enumerate(experiments.crystals()):
                    if i_cryst >= n_lattices_previous_cycle:
                        new_cryst, cb_op_to_primitive = self.apply_symmetry(
                            cryst, target_space_group)
                        if self.cb_op_primitive_inp is not None:
                            new_cryst = new_cryst.change_basis(
                                self.cb_op_primitive_inp)
                            logger.info(new_cryst.get_space_group().info())
                        cryst.update(new_cryst)
                        cryst.set_space_group(
                            self.params.known_symmetry.space_group.group())
                        for i_expt, expt in enumerate(experiments):
                            if expt.crystal is not cryst:
                                continue
                            if not cb_op_to_primitive.is_identity_op():
                                miller_indices = self.reflections[
                                    'miller_index'].select(
                                        self.reflections['id'] == i_expt)
                                miller_indices = cb_op_to_primitive.apply(
                                    miller_indices)
                                self.reflections['miller_index'].set_selected(
                                    self.reflections['id'] == i_expt,
                                    miller_indices)
                            if self.cb_op_primitive_inp is not None:
                                miller_indices = self.reflections[
                                    'miller_index'].select(
                                        self.reflections['id'] == i_expt)
                                miller_indices = self.cb_op_primitive_inp.apply(
                                    miller_indices)
                                self.reflections['miller_index'].set_selected(
                                    self.reflections['id'] == i_expt,
                                    miller_indices)

            # discard nearly overlapping lattices on the same shot
            if len(experiments) > 1:
                from dials.algorithms.indexing.compare_orientation_matrices \
                     import difference_rotation_matrix_axis_angle
                cryst_b = experiments.crystals()[-1]
                have_similar_crystal_models = False
                for i_a, cryst_a in enumerate(experiments.crystals()[:-1]):
                    R_ab, axis, angle, cb_op_ab = \
                      difference_rotation_matrix_axis_angle(cryst_a, cryst_b)
                    min_angle = self.params.multiple_lattice_search.minimum_angular_separation
                    if abs(angle) < min_angle:  # degrees
                        logger.info(
                            "Crystal models too similar, rejecting crystal %i:"
                            % (len(experiments)))
                        logger.info(
                            "Rotation matrix to transform crystal %i to crystal %i"
                            % (i_a + 1, len(experiments)))
                        logger.info(R_ab)
                        logger.info("Rotation of %.3f degrees" % angle +
                                    " about axis (%.3f, %.3f, %.3f)" % axis)
                        #show_rotation_matrix_differences([cryst_a, cryst_b])
                        have_similar_crystal_models = True
                        del experiments[-1]
                        break
                if have_similar_crystal_models:
                    break

            self.indexed_reflections = (self.reflections['id'] > -1)
            if self.d_min is None:
                sel = self.reflections['id'] <= -1
            else:
                sel = flex.bool(len(self.reflections), False)
                lengths = 1 / self.reflections['rlp'].norms()
                isel = (lengths >= self.d_min).iselection()
                sel.set_selected(isel, True)
                sel.set_selected(self.reflections['id'] > -1, False)
            self.unindexed_reflections = self.reflections.select(sel)

            reflections_for_refinement = self.reflections.select(
                self.indexed_reflections)

            if len(self.params.stills.isoforms) > 0:
                logger.info("")
                logger.info("#" * 80)
                logger.info("Starting refinement")
                logger.info("#" * 80)
                logger.info("")

                import copy
                isoform_experiments = ExperimentList()
                isoform_reflections = flex.reflection_table()
                # Note, changes to params after initial indexing. Cannot use tie to target when fixing the unit cell.
                self.all_params.refinement.reflections.outlier.algorithm = "null"
                self.all_params.refinement.parameterisation.crystal.fix = "cell"
                self.all_params.refinement.parameterisation.crystal.unit_cell.restraints.tie_to_target = []

                for expt_id, experiment in enumerate(experiments):
                    reflections = reflections_for_refinement.select(
                        reflections_for_refinement['id'] == expt_id)
                    reflections['id'] = flex.int(len(reflections), 0)
                    refiners = []
                    for isoform in self.params.stills.isoforms:
                        iso_experiment = copy.deepcopy(experiment)
                        crystal = iso_experiment.crystal
                        if isoform.lookup_symbol != crystal.get_space_group(
                        ).type().lookup_symbol():
                            logger.info(
                                "Crystal isoform lookup_symbol %s does not match isoform %s lookup_symbol %s"
                                % (crystal.get_space_group().type(
                                ).lookup_symbol(), isoform.name,
                                   isoform.lookup_symbol))
                            continue
                        crystal.set_B(isoform.cell.fractionalization_matrix())

                        logger.info("Refining isoform %s" % isoform.name)
                        refiners.append(
                            e_refine(params=self.all_params,
                                     experiments=ExperimentList(
                                         [iso_experiment]),
                                     reflections=reflections,
                                     graph_verbose=False))

                    if len(refiners) == 0:
                        raise Sorry(
                            "No isoforms had a lookup symbol that matched")
                    positional_rmsds = [
                        math.sqrt(P.rmsds()[0]**2 + P.rmsds()[1]**2)
                        for P in refiners
                    ]
                    logger.info("Positional rmsds for all isoforms:" +
                                str(positional_rmsds))
                    minrmsd_mm = min(positional_rmsds)
                    minindex = positional_rmsds.index(minrmsd_mm)
                    logger.info(
                        "The smallest rmsd is %5.1f um from isoform %s" %
                        (1000. * minrmsd_mm,
                         self.params.stills.isoforms[minindex].name))
                    if self.params.stills.isoforms[
                            minindex].rmsd_target_mm is not None:
                        logger.info("Asserting %f < %f" %
                                    (minrmsd_mm, self.params.stills.
                                     isoforms[minindex].rmsd_target_mm))
                        assert minrmsd_mm < self.params.stills.isoforms[
                            minindex].rmsd_target_mm
                    logger.info("Acceptable rmsd for isoform %s." %
                                (self.params.stills.isoforms[minindex].name))
                    if len(self.params.stills.isoforms) == 2:
                        logger.info(
                            "Rmsd gain over the other isoform %5.1f um." %
                            (1000. *
                             abs(positional_rmsds[0] - positional_rmsds[1])))
                    R = refiners[minindex]
                    # Now one last check to see if direct beam is out of bounds
                    if self.params.stills.isoforms[
                            minindex].beam_restraint is not None:
                        from scitbx import matrix
                        refined_beam = matrix.col(
                            R.get_experiments()
                            [0].detector[0].get_beam_centre_lab(
                                experiments[0].beam.get_s0())[0:2])
                        known_beam = matrix.col(
                            self.params.stills.isoforms[minindex].
                            beam_restraint)
                        logger.info(
                            "Asserting difference in refined beam center and expected beam center %f < %f"
                            %
                            ((refined_beam - known_beam).length(), self.params.
                             stills.isoforms[minindex].rmsd_target_mm))
                        assert (refined_beam - known_beam
                                ).length() < self.params.stills.isoforms[
                                    minindex].rmsd_target_mm
                        # future--circle of confusion could be given as a separate length in mm instead of reusing rmsd_target

                    experiment = R.get_experiments()[0]
                    experiment.crystal.identified_isoform = self.params.stills.isoforms[
                        minindex].name

                    isoform_experiments.append(experiment)
                    reflections['id'] = flex.int(len(reflections), expt_id)
                    isoform_reflections.extend(reflections)
                experiments = isoform_experiments
                reflections_for_refinement = isoform_reflections

            try:
                refined_experiments, refined_reflections = self.refine(
                    experiments, reflections_for_refinement)
            except Exception as e:
                s = str(e)
                if len(experiments) == 1:
                    raise Sorry(e)
                had_refinement_error = True
                logger.info("Refinement failed:")
                logger.info(s)
                del experiments[-1]
                break

            # sanity check for unrealistic unit cell volume increase during refinement
            # usually this indicates too many parameters are being refined given the
            # number of observations provided.
            if not self.params.refinement_protocol.disable_unit_cell_volume_sanity_check:
                for orig_expt, refined_expt in zip(experiments,
                                                   refined_experiments):
                    uc1 = orig_expt.crystal.get_unit_cell()
                    uc2 = refined_expt.crystal.get_unit_cell()
                    volume_change = abs(uc1.volume() -
                                        uc2.volume()) / uc1.volume()
                    cutoff = 0.5
                    if volume_change > cutoff:
                        msg = "\n".join((
                            "Unrealistic unit cell volume increase during refinement of %.1f%%.",
                            "Please try refining fewer parameters, either by enforcing symmetry",
                            "constraints (space_group=) and/or disabling experimental geometry",
                            "refinement (detector.fix=all and beam.fix=all). To disable this",
                            "sanity check set disable_unit_cell_volume_sanity_check=True."
                        )) % (100 * volume_change)
                        raise Sorry(msg)

            self.refined_reflections = refined_reflections.select(
                refined_reflections['id'] > -1)

            for i, imageset in enumerate(self.imagesets):
                ref_sel = self.refined_reflections.select(
                    self.refined_reflections['imageset_id'] == i)
                ref_sel = ref_sel.select(ref_sel['id'] >= 0)
                for i_expt in set(ref_sel['id']):
                    expt = refined_experiments[i_expt]
                    imageset.set_detector(expt.detector)
                    imageset.set_beam(expt.beam)
                    imageset.set_goniometer(expt.goniometer)
                    imageset.set_scan(expt.scan)
                    expt.imageset = imageset

            if not (self.all_params.refinement.parameterisation.beam.fix
                    == 'all' and
                    self.all_params.refinement.parameterisation.detector.fix
                    == 'all'):
                # Experimental geometry may have changed - re-map centroids to
                # reciprocal space

                spots_mm = self.reflections
                self.reflections = flex.reflection_table()
                for i, imageset in enumerate(self.imagesets):
                    spots_sel = spots_mm.select(spots_mm['imageset_id'] == i)
                    self.map_centroids_to_reciprocal_space(
                        spots_sel, imageset.get_detector(),
                        imageset.get_beam(), imageset.get_goniometer())
                    self.reflections.extend(spots_sel)

            # update for next cycle
            experiments = refined_experiments
            self.refined_experiments = refined_experiments

        if not 'refined_experiments' in locals():
            raise Sorry("None of the experiments could refine.")

        # discard experiments with zero reflections after refinement
        id_set = set(self.refined_reflections['id'])
        if len(id_set) < len(self.refined_experiments):
            filtered_refined_reflections = flex.reflection_table()
            for i in xrange(len(self.refined_experiments)):
                if i not in id_set:
                    del self.refined_experiments[i]
            for old, new in zip(sorted(id_set), range(len(id_set))):
                subset = self.refined_reflections.select(
                    self.refined_reflections['id'] == old)
                subset['id'] = flex.int(len(subset), new)
                filtered_refined_reflections.extend(subset)
            self.refined_reflections = filtered_refined_reflections

        if len(self.refined_experiments) > 1:
            from dials.algorithms.indexing.compare_orientation_matrices \
                 import show_rotation_matrix_differences
            show_rotation_matrix_differences(
                self.refined_experiments.crystals(), out=info_handle)

        logger.info("Final refined crystal models:")
        for i, crystal_model in enumerate(self.refined_experiments.crystals()):
            n_indexed = 0
            for i_expt in experiments.where(crystal=crystal_model):
                n_indexed += (self.reflections['id'] == i).count(True)
            logger.info("model %i (%i reflections):" % (i + 1, n_indexed))
            logger.info(crystal_model)

        if 'xyzcal.mm' in self.refined_reflections:  # won't be there if refine_all_candidates = False and no isoforms
            self.refined_reflections['xyzcal.px'] = flex.vec3_double(
                len(self.refined_reflections))
            for i, imageset in enumerate(self.imagesets):
                imgset_sel = self.refined_reflections['imageset_id'] == i
                # set xyzcal.px field in self.refined_reflections
                refined_reflections = self.refined_reflections.select(
                    imgset_sel)
                panel_numbers = flex.size_t(refined_reflections['panel'])
                xyzcal_mm = refined_reflections['xyzcal.mm']
                x_mm, y_mm, z_rad = xyzcal_mm.parts()
                xy_cal_mm = flex.vec2_double(x_mm, y_mm)
                xy_cal_px = flex.vec2_double(len(xy_cal_mm))
                for i_panel in range(len(imageset.get_detector())):
                    panel = imageset.get_detector()[i_panel]
                    sel = (panel_numbers == i_panel)
                    isel = sel.iselection()
                    ref_panel = refined_reflections.select(
                        panel_numbers == i_panel)
                    xy_cal_px.set_selected(
                        sel, panel.millimeter_to_pixel(xy_cal_mm.select(sel)))
                x_px, y_px = xy_cal_px.parts()
                scan = imageset.get_scan()
                if scan is not None:
                    z_px = scan.get_array_index_from_angle(z_rad, deg=False)
                else:
                    # must be a still image, z centroid not meaningful
                    z_px = z_rad
                xyzcal_px = flex.vec3_double(x_px, y_px, z_px)
                self.refined_reflections['xyzcal.px'].set_selected(
                    imgset_sel, xyzcal_px)
Example #25
0
def run(args=None):
    import libtbx.load_env

    from dials.util import Sorry

    usage = "dials.reindex [options] indexed.expt indexed.refl"

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

    params, options = parser.parse_args(args, show_diff_phil=True)

    reflections, experiments = reflections_and_experiments_from_files(
        params.input.reflections, params.input.experiments
    )
    if len(experiments) == 0 and len(reflections) == 0:
        parser.print_help()
        return
    if params.change_of_basis_op is None:
        raise Sorry("Please provide a change_of_basis_op.")

    reference_crystal = None
    if params.reference.experiments is not None:
        from dxtbx.serialize import load

        reference_experiments = load.experiment_list(
            params.reference.experiments, check_format=False
        )
        if len(reference_experiments.crystals()) == 1:
            reference_crystal = reference_experiments.crystals()[0]
        else:
            # first check sg all same
            sgs = [
                expt.crystal.get_space_group().type().number() for expt in experiments
            ]
            if len(set(sgs)) > 1:
                raise Sorry(
                    """The reference experiments have different space groups:
                    space group numbers found: %s
                    Please reanalyse the data so that space groups are consistent,
                    (consider using dials.reindex, dials.symmetry or dials.cosym)"""
                    % ", ".join(map(str, set(sgs)))
                )

            reference_crystal = reference_experiments.crystals()[0]
            reference_crystal.unit_cell = determine_best_unit_cell(
                reference_experiments
            )

    if params.reference.reflections is not None:
        # First check that we have everything as expected for the reference reindexing
        if params.reference.experiments is None:
            raise Sorry(
                """For reindexing against a reference dataset, a reference
experiments file must also be specified with the option: reference.experiments= """
            )
        if not os.path.exists(params.reference.reflections):
            raise Sorry("Could not locate reference dataset reflection file")

        reference_reflections = flex.reflection_table().from_file(
            params.reference.reflections
        )

        test_reflections = reflections[0]

        if (
            reference_crystal.get_space_group().type().number()
            != experiments.crystals()[0].get_space_group().type().number()
        ):
            raise Sorry("Space group of input does not match reference")

        # Set some flags to allow filtering, if wanting to reindex against
        # reference with data that has not yet been through integration
        if (
            test_reflections.get_flags(test_reflections.flags.integrated_sum).count(
                True
            )
            == 0
        ):
            assert (
                "intensity.sum.value" in test_reflections
            ), "No 'intensity.sum.value' in reflections"
            test_reflections.set_flags(
                flex.bool(test_reflections.size(), True),
                test_reflections.flags.integrated_sum,
            )
        if (
            reference_reflections.get_flags(
                reference_reflections.flags.integrated_sum
            ).count(True)
            == 0
        ):
            assert (
                "intensity.sum.value" in test_reflections
            ), "No 'intensity.sum.value in reference reflections"
            reference_reflections.set_flags(
                flex.bool(reference_reflections.size(), True),
                reference_reflections.flags.integrated_sum,
            )

        # Make miller array of the two datasets
        try:
            test_miller_set = filtered_arrays_from_experiments_reflections(
                experiments, [test_reflections]
            )[0]
        except ValueError:
            raise Sorry("No reflections remain after filtering the test dataset")
        try:
            reference_miller_set = filtered_arrays_from_experiments_reflections(
                reference_experiments, [reference_reflections]
            )[0]
        except ValueError:
            raise Sorry("No reflections remain after filtering the reference dataset")

        from dials.algorithms.symmetry.reindex_to_reference import (
            determine_reindex_operator_against_reference,
        )

        change_of_basis_op = determine_reindex_operator_against_reference(
            test_miller_set, reference_miller_set
        )

    elif len(experiments) and params.change_of_basis_op is libtbx.Auto:
        if reference_crystal is not None:
            if len(experiments.crystals()) > 1:
                raise Sorry("Only one crystal can be processed at a time")
            from dials.algorithms.indexing.compare_orientation_matrices import (
                difference_rotation_matrix_axis_angle,
            )

            cryst = experiments.crystals()[0]
            R, axis, angle, change_of_basis_op = difference_rotation_matrix_axis_angle(
                cryst, reference_crystal
            )
            print(f"Change of basis op: {change_of_basis_op}")
            print("Rotation matrix to transform input crystal to reference::")
            print(R.mathematica_form(format="%.3f", one_row_per_line=True))
            print(
                f"Rotation of {angle:.3f} degrees",
                "about axis (%.3f, %.3f, %.3f)" % axis,
            )

        elif len(reflections):
            assert len(reflections) == 1

            # always re-map reflections to reciprocal space
            refl = reflections.deep_copy()
            refl.centroid_px_to_mm(experiments)
            refl.map_centroids_to_reciprocal_space(experiments)

            # index the reflection list using the input experiments list
            refl["id"] = flex.int(len(refl), -1)
            index = AssignIndicesGlobal(tolerance=0.2)
            index(refl, experiments)
            hkl_expt = refl["miller_index"]
            hkl_input = reflections[0]["miller_index"]

            change_of_basis_op = derive_change_of_basis_op(hkl_input, hkl_expt)

            # reset experiments list since we don't want to reindex this
            experiments = []

    else:
        change_of_basis_op = sgtbx.change_of_basis_op(params.change_of_basis_op)

    if len(experiments):
        space_group = params.space_group
        if space_group is not None:
            space_group = space_group.group()
        try:
            experiments = reindex_experiments(
                experiments, change_of_basis_op, space_group=space_group
            )
        except RuntimeError as e:
            # Only catch specific errors here
            if "Unsuitable value for rational rotation matrix." in str(e):
                original_message = str(e).split(":")[-1].strip()
                sys.exit(f"Error: {original_message} Is your change_of_basis_op valid?")
            raise

        print(f"Saving reindexed experimental models to {params.output.experiments}")
        experiments.as_file(params.output.experiments)

    if len(reflections):
        assert len(reflections) == 1
        reflections = reflections[0]

        miller_indices = reflections["miller_index"]

        if params.hkl_offset is not None:
            h, k, l = miller_indices.as_vec3_double().parts()
            h += params.hkl_offset[0]
            k += params.hkl_offset[1]
            l += params.hkl_offset[2]
            miller_indices = flex.miller_index(h.iround(), k.iround(), l.iround())
        non_integral_indices = change_of_basis_op.apply_results_in_non_integral_indices(
            miller_indices
        )
        if non_integral_indices.size() > 0:
            print(
                "Removing %i/%i reflections (change of basis results in non-integral indices)"
                % (non_integral_indices.size(), miller_indices.size())
            )
        sel = flex.bool(miller_indices.size(), True)
        sel.set_selected(non_integral_indices, False)
        miller_indices_reindexed = change_of_basis_op.apply(miller_indices.select(sel))
        reflections["miller_index"].set_selected(sel, miller_indices_reindexed)
        reflections["miller_index"].set_selected(~sel, (0, 0, 0))

        print(f"Saving reindexed reflections to {params.output.reflections}")
        reflections.as_file(params.output.reflections)