Exemplo n.º 1
0
  def real_space_grid_search(self):
    d_min = self.params.refinement_protocol.d_min_start

    sel = (self.reflections['id'] == -1)
    if d_min is not None:
      sel &= (1/self.reflections['rlp'].norms() > d_min)
    reciprocal_lattice_points = self.reflections['rlp'].select(sel)

    logger.info("Indexing from %i reflections" %len(reciprocal_lattice_points))

    def compute_functional(vector):
      two_pi_S_dot_v = 2 * math.pi * reciprocal_lattice_points.dot(vector)
      return flex.sum(flex.cos(two_pi_S_dot_v))

    from rstbx.array_family import flex
    from rstbx.dps_core import SimpleSamplerTool
    assert self.target_symmetry_primitive is not None
    assert self.target_symmetry_primitive.unit_cell() is not None
    SST = SimpleSamplerTool(
      self.params.real_space_grid_search.characteristic_grid)
    SST.construct_hemisphere_grid(SST.incr)
    cell_dimensions = self.target_symmetry_primitive.unit_cell().parameters()[:3]
    unique_cell_dimensions = set(cell_dimensions)
    logger.info(
      "Number of search vectors: %i" %(len(SST.angles) * len(unique_cell_dimensions)))
    vectors = flex.vec3_double()
    function_values = flex.double()
    for i, direction in enumerate(SST.angles):
      for l in unique_cell_dimensions:
        v = matrix.col(direction.dvec) * l
        f = compute_functional(v.elems)
        vectors.append(v.elems)
        function_values.append(f)

    perm = flex.sort_permutation(function_values, reverse=True)
    vectors = vectors.select(perm)
    function_values = function_values.select(perm)

    unique_vectors = []
    i = 0
    while len(unique_vectors) < 30:
      v = matrix.col(vectors[i])
      is_unique = True
      if i > 0:
        for v_u in unique_vectors:
          if v.length() < v_u.length():
            if is_approximate_integer_multiple(v, v_u):
              is_unique = False
              break
          elif is_approximate_integer_multiple(v_u, v):
            is_unique = False
            break
      if is_unique:
        unique_vectors.append(v)
      i += 1

    for i in range(30):
      v = matrix.col(vectors[i])
      logger.debug("%s %s %s" %(str(v.elems), str(v.length()), str(function_values[i])))

    basis_vectors = [v.elems for v in unique_vectors]
    self.candidate_basis_vectors = basis_vectors

    if self.params.optimise_initial_basis_vectors:
      optimised_basis_vectors = optimise_basis_vectors(
        reciprocal_lattice_points, basis_vectors)
      optimised_function_values = flex.double([
        compute_functional(v) for v in optimised_basis_vectors])

      perm = flex.sort_permutation(optimised_function_values, reverse=True)
      optimised_basis_vectors = optimised_basis_vectors.select(perm)
      optimised_function_values = optimised_function_values.select(perm)

      unique_vectors = [matrix.col(v) for v in optimised_basis_vectors]

    logger.info("Number of unique vectors: %i" %len(unique_vectors))

    for i in range(len(unique_vectors)):
      logger.debug("%s %s %s" %(
        str(compute_functional(unique_vectors[i].elems)),
        str(unique_vectors[i].length()),
        str(unique_vectors[i].elems)))

    crystal_models = []
    self.candidate_basis_vectors = unique_vectors
    self.debug_show_candidate_basis_vectors()
    if self.params.debug_plots:
      self.debug_plot_candidate_basis_vectors()
    candidate_orientation_matrices \
      = self.find_candidate_orientation_matrices(
        unique_vectors,
        max_combinations=self.params.basis_vector_combinations.max_try)
    crystal_model, n_indexed = self.choose_best_orientation_matrix(
      candidate_orientation_matrices)
    if crystal_model is not None:
      crystal_models = [crystal_model]
    else:
      crystal_models = []

    #assert len(crystal_models) > 0

    candidate_orientation_matrices = crystal_models

    #for i in range(len(candidate_orientation_matrices)):
      #if self.target_symmetry_primitive is not None:
        ##print "symmetrizing model"
        ##self.target_symmetry_primitive.show_summary()
        #symmetrized_model = self.apply_symmetry(
          #candidate_orientation_matrices[i], self.target_symmetry_primitive)
        #candidate_orientation_matrices[i] = symmetrized_model

    self.candidate_crystal_models = candidate_orientation_matrices
Exemplo n.º 2
0
  def two_color_grid_search(self):
    '''creates candidate reciprocal lattice points based on two beams and performs
    2-D grid search based on maximizing the functional using N_UNIQUE_V candidate
    vectors (N_UNIQUE_V is usually 30 from Guildea paper)'''

    assert len(self.imagesets) == 1
    detector = self.imagesets[0].get_detector()

    mm_spot_pos = self.map_spots_pixel_to_mm_rad(self.reflections,detector,scan=None)

    self.map_centroids_to_reciprocal_space(mm_spot_pos,detector,self.beams[0],
                                           goniometer=None)
    self.reciprocal_lattice_points1 = mm_spot_pos['rlp'].select(
          (self.reflections['id'] == -1))

    rlps1 = mm_spot_pos['rlp'].select(
          (self.reflections['id'] == -1))

    self.map_centroids_to_reciprocal_space(mm_spot_pos,detector,self.beams[1],
                                           goniometer=None)
    self.reciprocal_lattice_points2 = mm_spot_pos['rlp'].select(
          (self.reflections['id'] == -1))
    # assert len(self.beams) == 3
    rlps2 = mm_spot_pos['rlp'].select(
          (self.reflections['id'] == -1))

    self.reciprocal_lattice_points=rlps1.concatenate(rlps2)

    #self.map_centroids_to_reciprocal_space(mm_spot_pos,detector,self.beams[2],goniometer=None)

    #self.reciprocal_lattice_points = mm_spot_pos['rlp'].select(
     #          (self.reflections['id'] == -1)&(1/self.reflections['rlp'].norms() > d_min))

    print "Indexing from %i reflections" %len(self.reciprocal_lattice_points)

    def compute_functional(vector):
      '''computes functional for 2-D grid search'''
      two_pi_S_dot_v = 2 * math.pi * self.reciprocal_lattice_points.dot(vector)
      return flex.sum(flex.cos(two_pi_S_dot_v))

    from rstbx.array_family import flex
    from rstbx.dps_core import SimpleSamplerTool
    assert self.target_symmetry_primitive is not None
    assert self.target_symmetry_primitive.unit_cell() is not None
    SST = SimpleSamplerTool(
      self.params.real_space_grid_search.characteristic_grid)
    SST.construct_hemisphere_grid(SST.incr)
    cell_dimensions = self.target_symmetry_primitive.unit_cell().parameters()[:3]
    unique_cell_dimensions = set(cell_dimensions)

    print("Makring search vecs")
    spiral_method = True
    if spiral_method:
        basis_vec_noise =True
        noise_scale = 2.
        #_N = 200000   # massively oversample the hemisphere so we can apply noise to our search
        _N = 100000
        print "Number of search vectors: %i" %( _N * len(unique_cell_dimensions))
        J = _N*2
        _thetas = [np.arccos( (2.*j - 1. - J)/J)
            for j in range(1,J+1)]
        _phis = [ np.sqrt( np.pi*J) *np.arcsin( (2.*j - 1. - J)/J )
            for j in range(1,J+1)]
        _x = np.sin(_thetas)*np.cos(_phis)
        _y = np.sin(_thetas)*np.sin(_phis)
        _z = np.cos(_thetas)
        nn = int(_N * 1.01)
        _u_vecs = np.array(zip(_x,_y,_z))[-nn:]

        rec_pts = np.array([self.reciprocal_lattice_points[i] for i in range(len(self.reciprocal_lattice_points))])
        N_unique = len(unique_cell_dimensions)

        # much faster to use numpy for massively over-sampled hemisphere..
        func_vals = np.zeros( nn*N_unique)
        vecs = np.zeros( (nn*N_unique, 3) )
        for i, l in enumerate(unique_cell_dimensions):
          # create noise model on top of lattice lengths...
          if basis_vec_noise:
            vec_mag = np.random.normal( l, scale=noise_scale, size=_u_vecs.shape[0] )
            vec_mag = vec_mag[:,None]
          else:
            vec_mag = l

          ul = _u_vecs * vec_mag
          func_slc = slice( i*nn, (i+1)*nn)
          vecs[func_slc] = ul
          func_vals[func_slc] = np.sum( np.cos( 2*np.pi*np.dot(rec_pts, ul.T) ),
                                      axis=0)

        order = np.argsort(func_vals)[::-1]  # sort function values, largest values first
        function_values = func_vals[order]
        vectors = vecs[order]

    else:  # fall back on original flex method
        vectors = flex.vec3_double()
        function_values = flex.double()
        print "Number of search vectors: %i" % (   len(SST.angles)* len(unique_cell_dimensions))
        for i, direction in enumerate(SST.angles):
          for l in unique_cell_dimensions:
            v = matrix.col(direction.dvec) * l
            f = compute_functional(v.elems)
            vectors.append(v.elems)
            function_values.append(f)
        perm = flex.sort_permutation(function_values, reverse=True)
        vectors = vectors.select(perm)
        function_values = function_values.select(perm)

    print("made search vecs")

    unique_vectors = []
    i = 0
    while len(unique_vectors) < N_UNIQUE_V:
      v = matrix.col(vectors[i])
      is_unique = True
      if i > 0:
        for v_u in unique_vectors:
          if v.length() < v_u.length():
            if is_approximate_integer_multiple(v, v_u):
              is_unique = False
              break
          elif is_approximate_integer_multiple(v_u, v):
            is_unique = False
            break
      if is_unique:
        unique_vectors.append(v)
      i += 1

    print ("chose unique basis vecs")
    if self.params.debug:
      for i in range(N_UNIQUE_V):
        v = matrix.col(vectors[i])
        print v.elems, v.length(), function_values[i]

    basis_vectors = [v.elems for v in unique_vectors]
    self.candidate_basis_vectors = basis_vectors

    if self.params.optimise_initial_basis_vectors:
      self.params.optimize_initial_basis_vectors = False
      # todo: verify this reference to self.reciprocal_lattice_points is correct
      optimised_basis_vectors = optimise_basis_vectors(
        self.reciprocal_lattice_points, basis_vectors)
      optimised_function_values = flex.double([
        compute_functional(v) for v in optimised_basis_vectors])

      perm = flex.sort_permutation(optimised_function_values, reverse=True)
      optimised_basis_vectors = optimised_basis_vectors.select(perm)
      optimised_function_values = optimised_function_values.select(perm)

      unique_vectors = [matrix.col(v) for v in optimised_basis_vectors]

    print "Number of unique vectors: %i" %len(unique_vectors)

    if self.params.debug:
      for i in range(len(unique_vectors)):
        print compute_functional(unique_vectors[i].elems), unique_vectors[i].length(), unique_vectors[i].elems
        print

    crystal_models = []
    self.candidate_basis_vectors = unique_vectors

    if self.params.debug:
      self.debug_show_candidate_basis_vectors()
    if self.params.debug_plots:
      self.debug_plot_candidate_basis_vectors()


    candidate_orientation_matrices \
      = self.find_candidate_orientation_matrices(
        unique_vectors)
        # max_combinations=self.params.basis_vector_combinations.max_try)

    FILTER_BY_MAG = True
    if FILTER_BY_MAG:
      print("\n\n FILTERING BY MAG\n\n")
      FILTER_TOL = 10,3   # within 5 percent of params and 1 percent of ang
      target_uc = self.params.known_symmetry.unit_cell.parameters()
      good_mats = []
      for c in candidate_orientation_matrices:
        uc = c.get_unit_cell().parameters()
        comps = []
        for i in range(3):
          tol = 0.01* FILTER_TOL[0] * target_uc[i]
          low = target_uc[i] - tol/2.
          high = target_uc[i] + tol/2
          comps.append(  low < uc[i] < high )
        for i in range(3,6):
          low = target_uc[i] - FILTER_TOL[1]
          high = target_uc[i] + FILTER_TOL[1]
          comps.append( low < uc[i] < high )
        if all( comps):
          print("matrix is ok:", c)
          good_mats.append(c)
        print("\nFilter kept %d / %d mats" % \
              (len(good_mats), len(candidate_orientation_matrices)))
      candidate_orientation_matrices = good_mats

    crystal_model, n_indexed = self.choose_best_orientation_matrix(
      candidate_orientation_matrices)
    orange = 2
    if crystal_model is not None:
      crystal_models = [crystal_model]
    else:
      crystal_models = []

    #assert len(crystal_models) > 0

    candidate_orientation_matrices = crystal_models

    #for i in range(len(candidate_orientation_matrices)):
      #if self.target_symmetry_primitive is not None:
        ##print "symmetrizing model"
        ##self.target_symmetry_primitive.show_summary()
        #symmetrized_model = self.apply_symmetry(
          #candidate_orientation_matrices[i], self.target_symmetry_primitive)
        #candidate_orientation_matrices[i] = symmetrized_model
    self.candidate_crystal_models = candidate_orientation_matrices

    # memory leak somewhere... probably not here.. but just in case...
    del _x, _y, _z, _u_vecs, order, rec_pts, vecs, func_vals, vectors, function_values
Exemplo n.º 3
0
    def get_finegrained_SST(self, coarse_sampling_grid=0.005):
        d_min = self.params.refinement_protocol.d_min_start
        sel = self.reflections["id"] == -1
        if d_min is not None:
            sel &= 1 / self.reflections["rlp"].norms() > d_min
        reciprocal_lattice_points = self.reflections["rlp"].select(sel)
        print("Indexing from %i reflections COARSE" %
              len(reciprocal_lattice_points))

        from rstbx.array_family import flex
        from rstbx.dps_core import SimpleSamplerTool

        assert self.target_symmetry_primitive is not None
        assert self.target_symmetry_primitive.unit_cell() is not None
        SST = SimpleSamplerTool(coarse_sampling_grid)
        SST.construct_hemisphere_grid(SST.incr)
        cell_dimensions = self.target_symmetry_primitive.unit_cell(
        ).parameters()[:3]
        unique_cell_dimensions = set(cell_dimensions)
        print("Number of search vectors COARSE: %i" %
              (len(SST.angles) * len(unique_cell_dimensions)))
        vectors = flex.vec3_double()
        function_values = flex.double()
        import time
        time1 = time.time()
        SST_all_angles = flex.Direction()
        for i, direction in enumerate(SST.angles):
            for l in unique_cell_dimensions:
                v = matrix.col(direction.dvec) * l
                f = compute_functional(v.elems, reciprocal_lattice_points)
                vectors.append(v.elems)
                function_values.append(f)
                SST_all_angles.append(direction)
        time2 = time.time()
        print('COARSE GRID SEARCH TIME=', time2 - time1)

        perm = flex.sort_permutation(function_values, reverse=True)
        vectors = vectors.select(perm)
        function_values = function_values.select(perm)

        unique_vectors = []
        unique_indices = []
        i = 0
        while len(unique_vectors) < 30:
            v = matrix.col(vectors[i])
            is_unique = True
            if i > 0:
                for v_u in unique_vectors:
                    if v.length() < v_u.length():
                        if is_approximate_integer_multiple(
                                v,
                                v_u,
                                relative_tolerance=0.2,
                                angular_tolerance=5.0):
                            is_unique = False
                            break
                    elif is_approximate_integer_multiple(
                            v_u, v, relative_tolerance=0.2,
                            angular_tolerance=5.0):
                        is_unique = False
                        break
            if is_unique:
                unique_vectors.append(v)
                unique_indices.append(perm[i])
            i += 1

        # Evaluate which SST angles contributed to the unique vectors
        SST_filter = flex.Direction()
        for v in unique_indices:
            direction = SST.angles[v // len(unique_cell_dimensions)]
            SST_filter.append(direction)
        SST.construct_hemisphere_grid_finegrained(0.0001, coarse_sampling_grid,
                                                  SST_filter)
        return SST
Exemplo n.º 4
0
    def real_space_grid_smart_search(self):
        """ overloading the real_space_grid_search method to use a sparser SST with highly fine grid after initially doing
        a sparse grid to evaluate grid points of interest"""
        d_min = self.params.refinement_protocol.d_min_start
        sel = self.reflections["id"] == -1
        if d_min is not None:
            sel &= 1 / self.reflections["rlp"].norms() > d_min
        reciprocal_lattice_points = self.reflections["rlp"].select(sel)
        print("Indexing from %i reflections FINE " %
              len(reciprocal_lattice_points))

        from rstbx.array_family import flex
        from rstbx.dps_core import SimpleSamplerTool

        assert self.target_symmetry_primitive is not None
        assert self.target_symmetry_primitive.unit_cell() is not None

        SST = self.get_finegrained_SST()
        cell_dimensions = self.target_symmetry_primitive.unit_cell(
        ).parameters()[:3]
        unique_cell_dimensions = set(cell_dimensions)
        print("Number of search vectors FINE : %i" %
              (len(SST.finegrained_angles) * len(unique_cell_dimensions)))
        vectors = flex.vec3_double()
        function_values = flex.double()
        # Do a search within the cluster of coarse grids and only return the top few values ?
        find_max_within_cluster = True
        import time
        time1 = time.time()
        if find_max_within_cluster:
            top_n_values = 1  # number of top scoring vectors to return in each coarse grid per unique dimension
            for count in range(len(SST.n_entries_finegrained[:-1])):
                start = SST.n_entries_finegrained[count]
                end = SST.n_entries_finegrained[count + 1]
                for l in unique_cell_dimensions:
                    tmp_vectors = flex.vec3_double()
                    tmp_function_values = flex.double()
                    for i, direction in enumerate(
                            SST.finegrained_angles[start:end]):
                        v = matrix.col(direction.dvec) * l
                        f = compute_functional(v.elems,
                                               reciprocal_lattice_points)
                        tmp_vectors.append(v.elems)
                        tmp_function_values.append(f)
                    perm = flex.sort_permutation(tmp_function_values,
                                                 reverse=True)
                    tmp_vectors = tmp_vectors.select(perm)[0:top_n_values]
                    tmp_function_values = tmp_function_values.select(
                        perm)[0:top_n_values]
                    vectors.extend(tmp_vectors)
                    function_values.extend(tmp_function_values)

        else:
            for i, direction in enumerate(SST.finegrained_angles):
                for l in unique_cell_dimensions:
                    v = matrix.col(direction.dvec) * l
                    f = compute_functional(v.elems, reciprocal_lattice_points)
                    vectors.append(v.elems)
                    function_values.append(f)

        time2 = time.time()
        print('FINE GRID SEARCH TIME=', time2 - time1)

        perm = flex.sort_permutation(function_values, reverse=True)
        vectors = vectors.select(perm)
        function_values = function_values.select(perm)

        unique_vectors = []
        unique_indices = []
        i = 0
        time1 = time.time()
        while len(unique_vectors) < 30:
            v = matrix.col(vectors[i])
            is_unique = True
            if i > 0:
                for v_u in unique_vectors:
                    if v.length() < v_u.length():
                        if is_approximate_integer_multiple(
                                v,
                                v_u,
                                relative_tolerance=0.2,
                                angular_tolerance=5.0):
                            is_unique = False
                            break
                    elif is_approximate_integer_multiple(
                            v_u, v, relative_tolerance=0.2,
                            angular_tolerance=5.0):
                        is_unique = False
                        break
            if is_unique:
                unique_vectors.append(v)
                unique_indices.append(perm[i])
            i += 1
        time2 = time.time()
        print('FINE GRID UNIQUE VECTOR SEARCH TIME = ', time2 - time1)
        #from IPython import embed; embed(); exit()
        # FIXME debugging here
        #for direction in SST.finegrained_angles:
        #  print ('DEBUGGGG = ', direction.phi, direction.psi)

        basis_vectors = [v.elems for v in unique_vectors]
        self.candidate_basis_vectors = basis_vectors

        logger.info("Number of unique vectors: %i" % len(unique_vectors))

        for i in range(len(unique_vectors)):
            logger.debug("%s %s %s" % (str(
                compute_functional(unique_vectors[i].elems,
                                   reciprocal_lattice_points)),
                                       str(unique_vectors[i].length()),
                                       str(unique_vectors[i].elems)))

        crystal_models = []
        self.candidate_basis_vectors = unique_vectors
        self.debug_show_candidate_basis_vectors()
        candidate_orientation_matrices = self.find_candidate_orientation_matrices(
            unique_vectors)
        crystal_model, n_indexed = self.choose_best_orientation_matrix(
            candidate_orientation_matrices)
        if crystal_model is not None:
            crystal_models = [crystal_model]
        else:
            crystal_models = []

        candidate_orientation_matrices = crystal_models
        self.candidate_crystal_models = candidate_orientation_matrices
Exemplo n.º 5
0
    def real_space_grid_search(self):
        d_min = self.params.refinement_protocol.d_min_start

        sel = (self.reflections['id'] == -1)
        if d_min is not None:
            sel &= (1 / self.reflections['rlp'].norms() > d_min)
        reciprocal_lattice_points = self.reflections['rlp'].select(sel)

        logger.info("Indexing from %i reflections" %
                    len(reciprocal_lattice_points))

        def compute_functional(vector):
            two_pi_S_dot_v = 2 * math.pi * reciprocal_lattice_points.dot(
                vector)
            return flex.sum(flex.cos(two_pi_S_dot_v))

        from rstbx.array_family import flex
        from rstbx.dps_core import SimpleSamplerTool
        assert self.target_symmetry_primitive is not None
        assert self.target_symmetry_primitive.unit_cell() is not None
        SST = SimpleSamplerTool(
            self.params.real_space_grid_search.characteristic_grid)
        SST.construct_hemisphere_grid(SST.incr)
        cell_dimensions = self.target_symmetry_primitive.unit_cell(
        ).parameters()[:3]
        unique_cell_dimensions = set(cell_dimensions)
        logger.info("Number of search vectors: %i" %
                    (len(SST.angles) * len(unique_cell_dimensions)))
        vectors = flex.vec3_double()
        function_values = flex.double()
        for i, direction in enumerate(SST.angles):
            for l in unique_cell_dimensions:
                v = matrix.col(direction.dvec) * l
                f = compute_functional(v.elems)
                vectors.append(v.elems)
                function_values.append(f)

        perm = flex.sort_permutation(function_values, reverse=True)
        vectors = vectors.select(perm)
        function_values = function_values.select(perm)

        unique_vectors = []
        i = 0
        while len(unique_vectors) < 30:
            v = matrix.col(vectors[i])
            is_unique = True
            if i > 0:
                for v_u in unique_vectors:
                    if v.length() < v_u.length():
                        if is_approximate_integer_multiple(v, v_u):
                            is_unique = False
                            break
                    elif is_approximate_integer_multiple(v_u, v):
                        is_unique = False
                        break
            if is_unique:
                unique_vectors.append(v)
            i += 1

        for i in range(30):
            v = matrix.col(vectors[i])
            logger.debug(
                "%s %s %s" %
                (str(v.elems), str(v.length()), str(function_values[i])))

        basis_vectors = [v.elems for v in unique_vectors]
        self.candidate_basis_vectors = basis_vectors

        if self.params.optimise_initial_basis_vectors:
            optimised_basis_vectors = optimise_basis_vectors(
                reciprocal_lattice_points, basis_vectors)
            optimised_function_values = flex.double(
                [compute_functional(v) for v in optimised_basis_vectors])

            perm = flex.sort_permutation(optimised_function_values,
                                         reverse=True)
            optimised_basis_vectors = optimised_basis_vectors.select(perm)
            optimised_function_values = optimised_function_values.select(perm)

            unique_vectors = [matrix.col(v) for v in optimised_basis_vectors]

        logger.info("Number of unique vectors: %i" % len(unique_vectors))

        for i in range(len(unique_vectors)):
            logger.debug(
                "%s %s %s" % (str(compute_functional(
                    unique_vectors[i].elems)), str(unique_vectors[i].length()),
                              str(unique_vectors[i].elems)))

        crystal_models = []
        self.candidate_basis_vectors = unique_vectors
        self.debug_show_candidate_basis_vectors()
        if self.params.debug_plots:
            self.debug_plot_candidate_basis_vectors()
        candidate_orientation_matrices \
          = self.find_candidate_orientation_matrices(
            unique_vectors,
            max_combinations=self.params.basis_vector_combinations.max_try)
        crystal_model, n_indexed = self.choose_best_orientation_matrix(
            candidate_orientation_matrices)
        if crystal_model is not None:
            crystal_models = [crystal_model]
        else:
            crystal_models = []

        #assert len(crystal_models) > 0

        candidate_orientation_matrices = crystal_models

        #for i in range(len(candidate_orientation_matrices)):
        #if self.target_symmetry_primitive is not None:
        ##print "symmetrizing model"
        ##self.target_symmetry_primitive.show_summary()
        #symmetrized_model = self.apply_symmetry(
        #candidate_orientation_matrices[i], self.target_symmetry_primitive)
        #candidate_orientation_matrices[i] = symmetrized_model

        self.candidate_crystal_models = candidate_orientation_matrices
Exemplo n.º 6
0
  def find_basis_vector_combinations_cluster_analysis(self):
    # hijack the xray.structure class to facilitate calculation of distances
    xs = xray.structure(crystal_symmetry=self.crystal_symmetry)
    for i, site in enumerate(self.sites):
      xs.add_scatterer(xray.scatterer("C%i" %i, site=site))

    xs = xs.sites_mod_short()
    xs = xs.select(xs.sites_frac().norms() < 0.45)
    cell_multiplier = 10
    xs1 = xs.customized_copy(
      unit_cell=uctbx.unit_cell([xs.unit_cell().parameters()[0]*cell_multiplier]*3))
    xs1.set_sites_cart(xs.sites_cart())
    xs = xs1
    sites_cart = xs.sites_cart()
    lengths = flex.double([matrix.col(sc).length() for sc in sites_cart])
    xs = xs.select(flex.sort_permutation(lengths))
    if self.params.debug:
      with open('peaks.pdb', 'wb') as f:
        print >> f, xs.as_pdb_file()

    vector_heights = flex.double()

    sites_frac = xs.sites_frac()
    pair_asu_table = xs.pair_asu_table(distance_cutoff=self.params.max_cell)
    asu_mappings = pair_asu_table.asu_mappings()
    distances = crystal.calculate_distances(pair_asu_table, sites_frac)
    vectors = []
    difference_vectors = []
    pairs = []
    for di in distances:
      if di.distance < self.params.min_cell: continue
      i_seq, j_seq = di.i_seq, di.j_seq
      if i_seq > j_seq: continue
      pairs.append((i_seq, j_seq))
      rt_mx_ji = di.rt_mx_ji
      site_frac_ji = rt_mx_ji * sites_frac[j_seq]
      site_cart_ji = xs.unit_cell().orthogonalize(site_frac_ji)
      site_cart_i = xs.unit_cell().orthogonalize(sites_frac[i_seq])
      vectors.append(matrix.col(site_cart_ji))
      diff_vec = matrix.col(site_cart_i) - matrix.col(site_cart_ji)
      if diff_vec[0] < 0:
        # only one hemisphere of difference vector space
        diff_vec = -diff_vec
      difference_vectors.append(diff_vec)

    params = self.params.multiple_lattice_search.cluster_analysis
    if params.method == 'dbscan':
      i_cluster = self.cluster_analysis_dbscan(difference_vectors)
      min_cluster_size = 1
    elif params.method == 'hcluster':
      i_cluster = self.cluster_analysis_hcluster(difference_vectors)
      i_cluster -= 1 # hcluster starts counting at 1
      min_cluster_size = params.min_cluster_size

    if self.params.debug_plots:
      self.debug_plot_clusters(
        difference_vectors, i_cluster, min_cluster_size=min_cluster_size)


    clusters = []
    min_cluster_size = params.min_cluster_size
    for i in range(max(i_cluster)+1):
      isel = (i_cluster == i).iselection()
      if len(isel) < min_cluster_size:
        continue
      clusters.append(isel)

    cluster_point_sets = []
    centroids = []
    cluster_sizes = flex.int()

    difference_vectors = flex.vec3_double(difference_vectors)

    from libtbx.utils import flat_list
    for cluster in clusters:
      points = flat_list([pairs[i] for i in cluster])
      cluster_point_sets.append(set(points))
      d_vectors = difference_vectors.select(cluster)
      cluster_sizes.append(len(d_vectors))
      centroids.append(d_vectors.mean())

    # build a graph where each node is a centroid from the difference vector
    # cluster analysis above, and an edge is defined when there is a
    # significant overlap between the sets of peaks in the FFT map that
    # contributed to the difference vectors in two clusters
    import networkx as nx
    G = nx.Graph()
    G.add_nodes_from(range(len(cluster_point_sets)))

    cutoff_frac = 0.25
    for i in range(len(cluster_point_sets)):
      for j in range(i+1, len(cluster_point_sets)):
        intersection_ij = cluster_point_sets[i].intersection(
            cluster_point_sets[j])
        union_ij = cluster_point_sets[i].union(cluster_point_sets[j])
        frac_connected = len(intersection_ij)/len(union_ij)
        if frac_connected > cutoff_frac:
          G.add_edge(i, j)

    # iteratively find the maximum cliques in the graph
    # break from the loop if there are no cliques remaining or there are
    # fewer than 3 vectors in the remaining maximum clique
    # Allow 1 basis vector to be shared between two cliques, to allow for
    # cases where two lattices share one basis vectors (e.g. two plate
    # crystals exactly aligned in one direction, but not in the other two)
    distinct_cliques = []
    cliques = list(nx.find_cliques(G))
    cliques = sorted(cliques, key=len, reverse=True)
    for i, clique in enumerate(cliques):
      clique = set(clique)
      if len(clique) < 3:
        break
      is_distinct = True
      for c in distinct_cliques:
        if len(c.intersection(clique)) > 1:
          is_distinct = False
          break
      if is_distinct:
        distinct_cliques.append(clique)
        this_set = set()
        for i_cluster in clique:
          this_set = this_set.union(cluster_point_sets[i_cluster])
        logger.info("Clique %i: %i lattice points" %(i+1, len(this_set)))

    assert len(distinct_cliques) > 0

    logger.info("Estimated number of lattices: %i" %len(distinct_cliques))

    self.candidate_basis_vectors = []
    self.candidate_crystal_models = []

    for clique in distinct_cliques:
      sel = flex.size_t(list(clique))
      vectors = flex.vec3_double(centroids).select(sel)
      perm = flex.sort_permutation(vectors.norms())
      vectors = [matrix.col(vectors[p]) for p in perm]

      # exclude vectors that are (approximately) integer multiples of a shorter
      # vector
      unique_vectors = []
      for v in vectors:
        is_unique = True
        for v_u in unique_vectors:
          if is_approximate_integer_multiple(v_u, v,
                                             relative_tolerance=0.01,
                                             angular_tolerance=0.5):
            is_unique = False
            break
        if is_unique:
          unique_vectors.append(v)
      vectors = unique_vectors

      self.candidate_basis_vectors.extend(vectors)
      candidate_orientation_matrices \
        = self.find_candidate_orientation_matrices(
          vectors,
          max_combinations=self.params.basis_vector_combinations.max_try)
      if len(candidate_orientation_matrices) == 0:
        continue
      crystal_model, n_indexed = self.choose_best_orientation_matrix(
        candidate_orientation_matrices)
      if crystal_model is None: continue
      # map to minimum reduced cell
      crystal_symmetry = crystal.symmetry(
        unit_cell=crystal_model.get_unit_cell(),
        space_group=crystal_model.get_space_group())
      cb_op = crystal_symmetry.change_of_basis_op_to_minimum_cell()
      crystal_model = crystal_model.change_basis(cb_op)
      self.candidate_crystal_models.append(crystal_model)

    if self.params.debug:
      file_name = "vectors.pdb"
      a = self.params.max_cell
      cs = crystal.symmetry(unit_cell=(a,a,a,90,90,90), space_group="P1")
      xs = xray.structure(crystal_symmetry=cs)
      for v in difference_vectors:
        v = matrix.col(v)
        xs.add_scatterer(xray.scatterer("C", site=v/(a/10)))
      xs.sites_mod_short()
      with open(file_name, 'wb') as f:
        print >> f, xs.as_pdb_file()

    for crystal_model in self.candidate_crystal_models:
      logger.debug(crystal_model)
Exemplo n.º 7
0
  def find_candidate_basis_vectors(self):
    # hijack the xray.structure class to facilitate calculation of distances
    xs = xray.structure(crystal_symmetry=self.crystal_symmetry)
    for i, site in enumerate(self.sites):
      xs.add_scatterer(xray.scatterer("C%i" %i, site=site))

    xs = xs.sites_mod_short()
    sites_cart = xs.sites_cart()
    lengths = flex.double([matrix.col(sc).length() for sc in sites_cart])
    perm = flex.sort_permutation(lengths)
    xs = xs.select(perm)
    volumes = self.volumes.select(perm)
    if self.params.debug:
      with open('peaks.pdb', 'wb') as f:
        print >> f, xs.as_pdb_file()

    sites_frac = xs.sites_frac()
    vectors = xs.sites_cart()
    norms = vectors.norms()
    sel = (norms > self.params.min_cell) & (norms < (2 * self.params.max_cell))
    vectors = vectors.select(sel)
    vectors = [matrix.col(v) for v in vectors]
    volumes = volumes.select(sel)

    # XXX loop over these vectors and sort into groups similar to further down
    # group similar angle and lengths, also catch integer multiples of vectors

    vector_groups = []
    relative_length_tolerance = 0.1
    angle_tolerance = 5 # degrees

    orth = self.fft_cell.orthogonalize
    for v, volume in zip(vectors, volumes):
      length = v.length()
      if length < self.params.min_cell or length > (2 * self.params.max_cell):
        continue
      matched_group = False
      for group in vector_groups:
        mean_v = group.mean()
        mean_v_length = mean_v.length()
        if (abs(mean_v_length - length)/max(mean_v_length, length)
            < relative_length_tolerance):
          angle = mean_v.angle(v, deg=True)
          if angle < angle_tolerance:
            group.append(v, length, volume)
            matched_group = True
            break
          elif abs(180-angle) < angle_tolerance:
            group.append(-v, length, volume)
            matched_group = True
            break
      if not matched_group:
        group = vector_group()
        group.append(v, length, volume)
        vector_groups.append(group)

    vectors = [g.mean() for g in vector_groups]
    volumes = flex.double(max(g.volumes) for g in vector_groups)

    ## sort by length
    #lengths = flex.double([v.length() for v in vectors])
    #perm = flex.sort_permutation(lengths)
    # sort by peak size
    perm = flex.sort_permutation(volumes, reverse=True)
    volumes = volumes.select(perm)
    vectors = [vectors[i] for i in perm]

    for i, (v, volume) in enumerate(zip(vectors, volumes)):
      logger.debug("%s %s %s" %(i, v.length(), volume))

    lengths = flex.double(v.length() for v in vectors)
    perm = flex.sort_permutation(lengths)

    # exclude vectors that are (approximately) integer multiples of a shorter
    # vector
    unique_vectors = []
    unique_volumes = flex.double()
    for p in perm:
      v = vectors[p]
      is_unique = True
      for i, v_u in enumerate(unique_vectors):
        if ((unique_volumes[i] > volumes[p])
            and is_approximate_integer_multiple(v_u, v)):
          logger.debug("rejecting %s: integer multiple of %s" %(v.length(), v_u.length()))
          is_unique = False
          break
      if is_unique:
        unique_vectors.append(v)
        unique_volumes.append(volumes[p])

    # re-sort by peak volume
    perm = flex.sort_permutation(unique_volumes, reverse=True)
    vectors = [unique_vectors[i] for i in perm]
    volumes = unique_volumes.select(perm)

    #for i, (v, volume) in enumerate(zip(vectors, volumes)):
      #logger.debug("%s %s %s" %(i, v.length(), volume))

    self.candidate_basis_vectors = vectors