示例#1
0
    def create(cls, vertex_type="vector", edge_type="set"):

        return cls(graph=graph.adjacency_list(
            graph_type="undirected",
            vertex_type=vertex_type,
            edge_type=edge_type,
        ), )
示例#2
0
    def __init__(self, graph, source, sink):

        from boost_adaptbx import graph as graphmod
        dirgraph = graphmod.adjacency_list(
            graph_type="directed",
            vertex_type="vector",
            edge_type="vector",
        )

        vertex_for = {}

        for vertex in graph.vertices():
            vertex_for[vertex] = dirgraph.add_vertex(label=vertex)

        reverse_edge_map = {}

        for edge in graph.edges():
            s = vertex_for[graph.source(edge=edge)]
            t = vertex_for[graph.target(edge=edge)]
            w = graph.edge_weight(edge=edge)
            (ed, success) = dirgraph.add_edge(vertex1=s, vertex2=t, weight=w)
            assert success
            (red, success) = dirgraph.add_edge(vertex1=t, vertex2=s, weight=w)
            assert success
            reverse_edge_map[ed] = red
            reverse_edge_map[red] = ed

        self.result = boykov_kolmogorov_max_flow(
            graph=dirgraph,
            reverse_edge_map=reverse_edge_map,
            source=vertex_for[source],
            sink=vertex_for[sink],
        )
  def test_adjacency_list_undirected_list_vector(self):

    try:
      g = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      reference = self.build_graph( g )
      self.manipulation(
        g,
        reference = reference,
        maxiter = None,
        expected = self.full_count_with_weight,
        )
      self.manipulation(
        g,
        reference = reference,
        maxiter = 24,
        expected = self.truncated_count_with_weight24,
        )
      self.manipulation(
        g,
        reference = reference,
        maxiter = 27,
        expected = self.truncated_count_with_weight27,
        )
  def __init__(self, graph, source, sink):

    from boost_adaptbx import graph as graphmod
    dirgraph = graphmod.adjacency_list(
      graph_type = "directed",
      vertex_type = "vector",
      edge_type = "vector",
      )

    vertex_for = {}

    for vertex in graph.vertices():
      vertex_for[ vertex ] = dirgraph.add_vertex( label = vertex )

    reverse_edge_map = {}

    for edge in graph.edges():
      s = vertex_for[ graph.source( edge = edge ) ]
      t = vertex_for[ graph.target( edge = edge ) ]
      w = graph.edge_weight( edge = edge )
      ( ed, success ) = dirgraph.add_edge( vertex1 = s, vertex2 = t, weight = w )
      assert success
      ( red, success )  = dirgraph.add_edge( vertex1 = t, vertex2 = s, weight = w )
      assert success
      reverse_edge_map[ ed ] = red
      reverse_edge_map[ red ] = ed

    self.result = boykov_kolmogorov_max_flow(
      graph = dirgraph,
      reverse_edge_map = reverse_edge_map,
      source = vertex_for[ source ],
      sink = vertex_for[ sink ],
      )
示例#5
0
def compatibility_graph(
  first,
  second,
  vertex_equality = operator.eq,
  edge_equality = operator.eq,
  output_graph_vertex = "vector",
  output_graph_edge = "vector",
  ):

  from boost_adaptbx import graph
  result = graph.adjacency_list(
    graph_type = "undirected",
    vertex_type = output_graph_vertex,
    edge_type = output_graph_edge,
    )
  vertex_from = {}

  import itertools

  for ( left, right ) in itertools.product( first.vertices(), second.vertices() ):
    if vertex_equality( first.vertex_label( left ), second.vertex_label( right ) ):
      label = ( left, right )
      vertex_from[ label ] = result.add_vertex( label = label )

  edge_weight_first = dict(
    ( frozenset( [ first.source( edge = e ), first.target( edge = e ) ] ), first.edge_weight( edge = e ) )
    for e in first.edges()
    )
  edge_weight_second = dict(
    ( frozenset( [ second.source( edge = e ), second.target( edge = e ) ] ), second.edge_weight( edge = e ) )
    for e in second.edges()
    )

  for ( ( f_l, s_l ), ( f_r, s_r ) ) in itertools.combinations( vertex_from, 2 ):
    if f_l == f_r or s_l == s_r:
      continue

    id_f = frozenset( [ f_l, f_r ] )
    id_s = frozenset( [ s_l, s_r ] )
    present_f = id_f in edge_weight_first
    present_s = id_s in edge_weight_second

    if (
      present_f
      and present_s
      and edge_equality( edge_weight_first[ id_f ], edge_weight_second[ id_s ] )
      ):
      result.add_edge(
        vertex1 = vertex_from[ ( f_l, s_l ) ],
        vertex2 = vertex_from[ ( f_r, s_r ) ],
        )

    elif not present_f and not present_s:
      result.add_edge(
        vertex1 = vertex_from[ ( f_l, s_l ) ],
        vertex2 = vertex_from[ ( f_r, s_r ) ],
        )

  return result
示例#6
0
 def __init__(self, interaction_list,maxnum_residues_in_cluster=20,size=None):
   self.interaction_list = interaction_list
   self.g = graph.adjacency_list(
     graph_type="undirected",
     vertex_type="vector",
     edge_type="set")
   self.maxnum_residues_in_cluster=maxnum_residues_in_cluster
   self.size = size
示例#7
0
def compatibility_graph(
    first,
    second,
    vertex_equality=operator.eq,
    edge_equality=operator.eq,
    output_graph_vertex="vector",
    output_graph_edge="vector",
):

    from boost_adaptbx import graph
    result = graph.adjacency_list(
        graph_type="undirected",
        vertex_type=output_graph_vertex,
        edge_type=output_graph_edge,
    )
    vertex_from = {}

    import itertools

    for (left, right) in itertools.product(first.vertices(),
                                           second.vertices()):
        if vertex_equality(first.vertex_label(left),
                           second.vertex_label(right)):
            label = (left, right)
            vertex_from[label] = result.add_vertex(label=label)

    edge_weight_first = dict(
        (frozenset([first.source(
            edge=e), first.target(edge=e)]), first.edge_weight(edge=e))
        for e in first.edges())
    edge_weight_second = dict(
        (frozenset([second.source(
            edge=e), second.target(edge=e)]), second.edge_weight(edge=e))
        for e in second.edges())

    for ((f_l, s_l), (f_r, s_r)) in itertools.combinations(vertex_from, 2):
        if f_l == f_r or s_l == s_r:
            continue

        id_f = frozenset([f_l, f_r])
        id_s = frozenset([s_l, s_r])
        present_f = id_f in edge_weight_first
        present_s = id_s in edge_weight_second

        if (present_f and present_s and edge_equality(
                edge_weight_first[id_f], edge_weight_second[id_s])):
            result.add_edge(
                vertex1=vertex_from[(f_l, s_l)],
                vertex2=vertex_from[(f_r, s_r)],
            )

        elif not present_f and not present_s:
            result.add_edge(
                vertex1=vertex_from[(f_l, s_l)],
                vertex2=vertex_from[(f_r, s_r)],
            )

    return result
示例#8
0
    def __init__(self, vertex_type="vector", edge_type="set"):

        self.graph = graph.adjacency_list(
            graph_type="undirected",
            vertex_type=vertex_type,
            edge_type=edge_type,
        )
        self.atom_for = {}
        self.xyz_for = {}
示例#9
0
  def __init__(self, vertex_type = "vector", edge_type = "set"):

    self.graph = graph.adjacency_list(
      graph_type = "undirected",
      vertex_type = vertex_type,
      edge_type = edge_type,
      )
    self.atom_for = {}
    self.xyz_for = {}
示例#10
0
  def create(cls, vertex_type = "vector", edge_type = "set"):

    return cls(
      graph = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = vertex_type,
        edge_type = edge_type,
        ),
      )
    def test_adjacency_list_undirected_vector_vector(self):

        try:
            g = graph.adjacency_list(graph_type="undirected", vertex_type="vector", edge_type="vector")

        except NotImplementedError:
            pass

        else:
            self.manipulation(g)
  def test_adjacency_list_undirected_list_vector(self):

    try:
      g1 = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "vector",
        )
      g2 = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulation( left = g1, right = g2 )
  def test_adjacency_list_undirected_list_set(self):

    try:
      leu = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )
      asn = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulate( leu = leu, asn = asn, matchings = 13 )
示例#14
0
    def test_adjacency_list_undirected_list_vector(self):

        try:
            g1 = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="list",
                edge_type="vector",
            )
            g2 = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="list",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            self.manipulation(left=g1, right=g2)
示例#15
0
  def test_adjacency_list_undirected_list_set(self):

    try:
      leu = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )
      asn = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulate( leu = leu, asn = asn, matchings = 13 )
示例#16
0
  def test_adjacency_list_directed_vector_vector(self):

    try:
      leu = graph.adjacency_list(
        graph_type = "directed",
        vertex_type = "vector",
        edge_type = "vector",
        )
      asn = graph.adjacency_list(
        graph_type = "directed",
        vertex_type = "vector",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulate( leu = leu, asn = asn, matchings = 8 )
  def test_adjacency_list_directed_vector_vector(self):

    try:
      leu = graph.adjacency_list(
        graph_type = "directed",
        vertex_type = "vector",
        edge_type = "vector",
        )
      asn = graph.adjacency_list(
        graph_type = "directed",
        vertex_type = "vector",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulate( leu = leu, asn = asn, matchings = 8 )
示例#18
0
  def test_adjacency_list_undirected_list_set(self):

    try:
      g = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulation( g, unique_edge = True, directed = False )
示例#19
0
  def test_adjacency_list_undirected_list_set(self):

    try:
      g = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "set",
        )

    except NotImplementedError:
      pass

    else:
      self.build_and_test( g, self.undirected_results() )
  def test_adjacency_list_undirected_vector_vector(self):

    try:
      g = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "vector",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      self.build_and_test( g, self.undirected_params() )
示例#21
0
    def test_adjacency_list_directed_vector_vector(self):

        try:
            g = graph.adjacency_list(
                graph_type="directed",
                vertex_type="vector",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            self.manipulation(g, unique_edge=False, directed=True)
示例#22
0
    def test_adjacency_list_undirected_list_set(self):

        try:
            g = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="list",
                edge_type="set",
            )

        except NotImplementedError:
            pass

        else:
            self.manipulation(g, unique_edge=True, directed=False)
    def test_adjacency_list_undirected_list_vector(self):

        try:
            g = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="list",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            self.build_and_test(g, self.undirected_params())
示例#24
0
    def test_adjacency_list_directed_vector_vector(self):

        try:
            g = graph.adjacency_list(
                graph_type="directed",
                vertex_type="vector",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            self.build_and_test(g, self.directed_results())
示例#25
0
    def test_adjacency_list_undirected_vector_vector(self):

        try:
            g = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="vector",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            self.manipulation(g)
示例#26
0
  def test_adjacency_list_directed_vector_vector(self):

    try:
      g = graph.adjacency_list(
        graph_type = "directed",
        vertex_type = "vector",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      self.manipulation( g, unique_edge = False, directed = True )
    def test_adjacency_list_undirected_list_vector(self):

        try:
            g = graph.adjacency_list(
                graph_type="undirected",
                vertex_type="list",
                edge_type="vector",
            )

        except NotImplementedError:
            pass

        else:
            reference = self.build_graph(g)
            self.run_all_tests(g, reference=reference)
  def test_adjacency_list_undirected_list_vector(self):

    try:
      g = graph.adjacency_list(
        graph_type = "undirected",
        vertex_type = "list",
        edge_type = "vector",
        )

    except NotImplementedError:
      pass

    else:
      reference = self.build_graph( g )
      self.run_all_tests(g, reference = reference )
示例#29
0
def connected_components(miller_array: cctbx.miller.array, ) -> [{}]:
    """
    Identify connected regions of missing reflections in the asymmetric unit.

    This is achieved by first generating the complete set of possible miller indices,
    then performing connected components analysis on a graph of nearest neighbours in
    the list of missing reflections.

    Args:
        miller_array:  The input list of reflections.

    Returns:
        The list of miller sets for each connected region of missing reflections. The
        first item in the list will be the complete set of all possible miller indices.
    """

    # Map to primitive setting for centred cells, otherwise true missing reflections
    # won't be identified as connected as a result of being separated by systematically
    # absent reflections.
    cb_op_to_primitive = miller_array.change_of_basis_op_to_primitive_setting()
    miller_array = miller_array.change_basis(cb_op_to_primitive)

    # First generate the missing_set of reflections. We want the full sphere of missing
    # reflections to allow us to find connected regions that cross the boundary of the
    # asu.
    unique = miller_array.unique_under_symmetry().map_to_asu()
    unique = unique.generate_bijvoet_mates()
    complete_set = unique.complete_set()
    missing_set = complete_set.lone_set(unique)
    missing_set = missing_set.expand_to_p1().customized_copy(
        crystal_symmetry=missing_set.crystal_symmetry())

    if missing_set.size() == 0:
        return complete_set, []

    # Now find the nearest neighbours.
    mi = missing_set.indices().as_vec3_double().as_double()
    k = 6
    ann = AnnAdaptor(data=mi, dim=3, k=k)
    ann.query(mi)

    # Construct the graph of connected missing reflections
    g = graph.adjacency_list(
        graph_type="undirected",
        vertex_type="vector",
        edge_type="set",
    )
    distance_cutoff = 2**0.5
    for i in range(missing_set.size()):
        ik = i * k
        for i_ann in range(k):
            if ann.distances[ik + i_ann] <= distance_cutoff:
                j = ann.nn[ik + i_ann]
                g.add_edge(i, j)

    # Now do the connected components analysis, filtering out lone missing reflections
    components = [c for c in cca.connected_components(graph=g) if len(c) > 1]

    # Determine the unique miller indices for each component within the asu
    unique_mi = []
    unique_ms = []
    for i, c in enumerate(components):
        ms = (missing_set.select(flex.size_t(list(c))).customized_copy(
            crystal_symmetry=miller_array).as_non_anomalous_set().map_to_asu())
        ms = ms.unique_under_symmetry()
        mi = set(ms.indices())
        if mi not in unique_mi:
            unique_ms.append(ms)
            unique_mi.append(mi)

    # Sort connected regions by size
    unique_ms = sorted(unique_ms, key=lambda ms: ms.size(), reverse=True)

    # Map indices back to input setting
    cb_op_primitive_inp = cb_op_to_primitive.inverse()
    return (
        unique.as_non_anomalous_set().complete_set().change_basis(
            cb_op_primitive_inp),
        [ms.change_basis(cb_op_primitive_inp) for ms in unique_ms],
    )
示例#30
0
 def __init__(self,
              pdb_hierarchy,
              crystal_symmetry,
              angular_difference_threshold_deg=5.,
              sequence_identity_threshold=90.,
              quiet=False):
     h = pdb_hierarchy
     superposition_threshold = 2 * sequence_identity_threshold - 100.
     n_atoms_all = h.atoms_size()
     s_str = "altloc ' ' and (protein or nucleotide)"
     h = h.select(h.atom_selection_cache().selection(s_str))
     h1 = iotbx.pdb.hierarchy.root()
     h1.append_model(h.models()[0].detached_copy())
     unit_cell = crystal_symmetry.unit_cell()
     result = {}
     if not quiet:
         print("Find groups of chains related by translational NCS")
     # double loop over chains to find matching pairs related by pure translation
     for c1 in h1.chains():
         c1.parent().remove_chain(c1)
         nchains = len(h1.models()[0].chains())
         if ([c1.is_protein(), c1.is_na()].count(True) == 0): continue
         r1 = list(c1.residues())
         c1_seq = "".join(c1.as_sequence())
         sc_1_tmp = c1.atoms().extract_xyz()
         h1_p1 = h1.expand_to_p1(crystal_symmetry=crystal_symmetry)
         for (ii, c2) in enumerate(h1_p1.chains()):
             orig_c2 = h1.models()[0].chains()[ii % nchains]
             r2 = list(c2.residues())
             c2_seq = "".join(c2.as_sequence())
             sites_cart_1, sites_cart_2 = None, None
             sc_2_tmp = c2.atoms().extract_xyz()
             # chains are identical
             if (c1_seq == c2_seq and sc_1_tmp.size() == sc_2_tmp.size()):
                 sites_cart_1 = sc_1_tmp
                 sites_cart_2 = sc_2_tmp
                 p_identity = 100.
             # chains are not identical, do alignment
             else:
                 align_obj = mmtbx.alignment.align(seq_a=c1_seq,
                                                   seq_b=c2_seq)
                 alignment = align_obj.extract_alignment()
                 matches = alignment.matches()
                 equal = matches.count("|")
                 total = len(alignment.a) - alignment.a.count("-")
                 p_identity = 100. * equal / max(1, total)
                 if (p_identity > superposition_threshold):
                     sites_cart_1 = flex.vec3_double()
                     sites_cart_2 = flex.vec3_double()
                     for i1, i2, match in zip(alignment.i_seqs_a,
                                              alignment.i_seqs_b, matches):
                         if (i1 is not None and i2 is not None
                                 and match == "|"):
                             r1i, r2i = r1[i1], r2[i2]
                             assert r1i.resname == r2i.resname, [
                                 r1i.resname, r2i.resname, i1, i2
                             ]
                             for a1 in r1i.atoms():
                                 for a2 in r2i.atoms():
                                     if (a1.name == a2.name):
                                         sites_cart_1.append(a1.xyz)
                                         sites_cart_2.append(a2.xyz)
                                         break
             # superpose two sequence-aligned chains
             if ([sites_cart_1, sites_cart_2].count(None) == 0):
                 lsq_fit_obj = superpose.least_squares_fit(
                     reference_sites=sites_cart_1, other_sites=sites_cart_2)
                 angle = lsq_fit_obj.r.rotation_angle()
                 t_frac = unit_cell.fractionalize(
                     (sites_cart_1 - sites_cart_2).mean())
                 t_frac = [math.modf(t)[0]
                           for t in t_frac]  # put into [-1,1]
                 radius = flex.sum(
                     flex.sqrt((sites_cart_1 - sites_cart_1.mean()
                                ).dot())) / sites_cart_1.size() * 4. / 3.
                 fracscat = min(c1.atoms_size(),
                                c2.atoms_size()) / n_atoms_all
                 result.setdefault(frozenset([c1, orig_c2]), []).append([
                     p_identity,
                     [lsq_fit_obj.r, t_frac, angle, radius, fracscat]
                 ])
             else:
                 result.setdefault(frozenset([c1, orig_c2]),
                                   []).append([p_identity, None])
     # Build graph
     g = graph.adjacency_list()
     vertex_handle = {}
     for key in result:
         seqid = result[key][0][0]
         sup = min(result[key],
                   key=lambda s: 0 if s[1] is None else s[1][2])[1]
         result[key] = [seqid, sup]
         if ((seqid > sequence_identity_threshold)
                 and (sup[2] < angular_difference_threshold_deg)):
             (c1, c2) = key
             if (c1 not in vertex_handle):
                 vertex_handle[c1] = g.add_vertex(label=c1)
             if (c2 not in vertex_handle):
                 vertex_handle[c2] = g.add_vertex(label=c2)
             g.add_edge(vertex1=vertex_handle[c1],
                        vertex2=vertex_handle[c2])
     # Do connected component analysis and compose final tNCS pairs object
     components = connected_component_algorithm.connected_components(g)
     import itertools
     self.ncs_pairs = []
     self.tncsresults = [0, "", [], 0.0]
     for (i, group) in enumerate(components):
         chains = [g.vertex_label(vertex=v) for v in group]
         fracscats = []
         radii = []
         for pair in itertools.combinations(chains, 2):
             sup = result[frozenset(pair)][1]
             fracscats.append(sup[-1])
             radii.append(sup[-2])
         fs = sum(fracscats) / len(fracscats)
         self.tncsresults[3] = fs  # store fracscat in array
         rad = sum(radii) / len(radii)
         #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
         maxorder = 1
         vectors = []
         previous_id = next(itertools.combinations(chains, 2))[0].id
         for pair in itertools.combinations(chains, 2):
             sup = result[frozenset(pair)][1]
             ncs_pair = ext.pair(
                 r=sup[0],
                 t=sup[1],
                 radius=rad,
                 radius_estimate=rad,
                 fracscat=fs,
                 rho_mn=flex.double(
                 ),  # rho_mn undefined, needs to be set later
                 id=i)
             self.ncs_pairs.append(ncs_pair)
             # show tNCS pairs in group
             fmt = "group %d chains %s <> %s angle: %4.2f trans.vect.: (%s) fracscat: %5.3f"
             t = ",".join([("%6.3f" % t_).strip() for t_ in sup[1]]).strip()
             if not quiet:
                 print(fmt % (i, pair[0].id, pair[1].id, sup[2], t, fs))
             if pair[0].id == previous_id:
                 maxorder += 1
                 orthoxyz = unit_cell.orthogonalize(sup[1])
                 vectors.append((sup[1], orthoxyz, sup[2]))
             else:
                 previous_id = pair[0].id
                 maxorder = 1
                 vectors = []
             if maxorder > self.tncsresults[0]:
                 self.tncsresults[0] = maxorder
                 self.tncsresults[1] = previous_id
                 self.tncsresults[2] = vectors
     if not quiet:
         print("Largest TNCS order, peptide chain, fracvector, orthvector, angle, fracscat = ", \
          str(self.tncsresults))
示例#31
0
def _InteractionGraphAABB(movers, extraAtomInfoMap, probeRadius=0.25):
    """Uses the overlap of the axis-aligned bounding boxes (AABBs) of all possible
  positions of all movable atoms in the set of movers passed in to construct the
  graph of which might overlap across all possible orientations of each.  The use
  of bounding boxes makes this an overestimate but its time complexity is linear
  in the product of the number of movers times the number of atoms times the number
  of possible positions for each and quadratic in the number of Movers.

  :param movers: flex array of movers to add to the graph.  Note that this list must
  not be modified after the graph has been constructed because that will change the
  index of its elements, making the graph point to the wrong elements (or to elements
  that no longer exist).
  :param extraAtomInfoMap: probe.ExtraAtomInfoMap that can be used to look
  up the information for atoms whose values need to be changed.  Can be
  obtained by calling mmtbx.probe.Helpers.getExtraAtomInfo().
  :param probeRadius: Radius of the probe to use to determine neighbor contact.
  If it is not set, the default value of 0.25 will be used.
  :returns An undirected Boost graph whose nodes are indices into the movers list
  and whose edges indicate which Movers might overlap in any of their states.  Note that
  the mover list must not be modified after the graph has been constructed because
  that will change the index of its elements, making the graph point to the wrong
  elements (or to elements that no longer exist).
  """

    pr = probeRadius

    # Add all of the Movers as nodes in the graph
    # Compute the axis-aligned bounding box for each Mover
    ret = graph.adjacency_list(
        vertex_type=
        "list",  # List so that deletions do not invalidate iterators and descriptors
    )
    AABBs = []
    verts = []
    for m in movers:
        verts.append(ret.add_vertex(m))

        # Find all possible positions, coarse and fine.
        coarses = m.CoarsePositions()
        atoms = coarses.atoms
        coarsePositions = coarses.positions
        total = coarsePositions[:]
        for c in range(len(coarsePositions)):
            total.extend(m.FinePositions(c).positions)

        # Find the range of positions of all atoms in X, Y, and Z
        xRange = [1e10, -1e10]
        yRange = [1e10, -1e10]
        zRange = [1e10, -1e10]
        for pos in total:
            for i, atomLoc in enumerate(pos):
                # Find the radius of the atom, which is used to extend it in all directions
                # so that we catch all potential overlaps.
                r = extraAtomInfoMap.getMappingFor(atoms[i]).vdwRadius

                x = atomLoc[0]
                xRange[0] = min(xRange[0], x - r)
                xRange[1] = max(xRange[1], x + r)

                y = atomLoc[1]
                yRange[0] = min(yRange[0], y - r)
                yRange[1] = max(yRange[1], y + r)

                z = atomLoc[2]
                zRange[0] = min(zRange[0], z - r)
                zRange[1] = max(zRange[1], z + r)

        # Dilate the bounding box by the radius of the probe.
        # Because we're dilating each box by this radius, we're properly
        # checking to twice the probe radius between two Movers.
        xRange = [xRange[0] - pr, xRange[1] + pr]
        yRange = [yRange[0] - pr, yRange[1] + pr]
        zRange = [zRange[0] - pr, zRange[1] + pr]

        # Store the bounding boxes for this Mover
        AABBs.append([xRange, yRange, zRange])

    # For each pair of Movers whose bounding boxes overlap, add an
    # edge to the graph.  We add them based on their indices.
    for i in range(len(movers) - 1):
        for j in range(i + 1, len(movers)):
            if _AABBOverlap(AABBs[i], AABBs[j]):
                ret.add_edge(vertex1=verts[i], vertex2=verts[j])

    return ret
示例#32
0
 def __init__(self,
              pdb_hierarchy,
              crystal_symmetry,
              angular_difference_threshold_deg=5.,
              sequence_identity_threshold=90.):
   h = pdb_hierarchy
   superposition_threshold = 2*sequence_identity_threshold - 100.
   n_atoms_all = h.atoms_size()
   s_str = "altloc ' ' and (protein or nucleotide)"
   h = h.select(h.atom_selection_cache().selection(s_str))
   h1 = iotbx.pdb.hierarchy.root()
   h1.append_model(h.models()[0].detached_copy())
   unit_cell = crystal_symmetry.unit_cell()
   result = {}
   print "Find groups of chains related by translational NCS"
   # double loop over chains to find matching pairs related by pure translation
   for c1 in h1.chains():
     c1.parent().remove_chain(c1)
     nchains = len(h1.models()[0].chains())
     if([c1.is_protein(), c1.is_na()].count(True)==0): continue
     r1 = list(c1.residues())
     c1_seq = "".join(c1.as_sequence())
     sc_1_tmp = c1.atoms().extract_xyz()
     h1_p1 = h1.expand_to_p1(crystal_symmetry=crystal_symmetry)
     for (ii,c2) in enumerate(h1_p1.chains()):
       orig_c2 = h1.models()[0].chains()[ii%nchains]
       r2 = list(c2.residues())
       c2_seq = "".join(c2.as_sequence())
       sites_cart_1, sites_cart_2 = None,None
       sc_2_tmp = c2.atoms().extract_xyz()
       # chains are identical
       if(c1_seq==c2_seq and sc_1_tmp.size()==sc_2_tmp.size()):
         sites_cart_1 = sc_1_tmp
         sites_cart_2 = sc_2_tmp
         p_identity = 100.
       # chains are not identical, do alignment
       else:
         align_obj = mmtbx.alignment.align(seq_a = c1_seq, seq_b = c2_seq)
         alignment = align_obj.extract_alignment()
         matches = alignment.matches()
         equal = matches.count("|")
         total = len(alignment.a) - alignment.a.count("-")
         p_identity = 100.*equal/max(1,total)
         if(p_identity>superposition_threshold):
           sites_cart_1 = flex.vec3_double()
           sites_cart_2 = flex.vec3_double()
           for i1, i2, match in zip(alignment.i_seqs_a, alignment.i_seqs_b,
                                    matches):
             if(i1 is not None and i2 is not None and match=="|"):
               r1i, r2i = r1[i1], r2[i2]
               assert r1i.resname==r2i.resname, [r1i.resname,r2i.resname,i1,i2]
               for a1 in r1i.atoms():
                 for a2 in r2i.atoms():
                   if(a1.name == a2.name):
                     sites_cart_1.append(a1.xyz)
                     sites_cart_2.append(a2.xyz)
                     break
       # superpose two sequence-aligned chains
       if([sites_cart_1,sites_cart_2].count(None)==0):
         lsq_fit_obj = superpose.least_squares_fit(
           reference_sites = sites_cart_1,
           other_sites     = sites_cart_2)
         angle = lsq_fit_obj.r.rotation_angle()
         t_frac = unit_cell.fractionalize((sites_cart_1-sites_cart_2).mean())
         t_frac = [math.modf(t)[0] for t in t_frac] # put into [-1,1]
         radius = flex.sum(flex.sqrt((sites_cart_1-
           sites_cart_1.mean()).dot()))/sites_cart_1.size()*4./3.
         fracscat = min(c1.atoms_size(),c2.atoms_size())/n_atoms_all
         result.setdefault( frozenset([c1,orig_c2]), [] ).append( [p_identity,[lsq_fit_obj.r, t_frac, angle, radius, fracscat]] )
       else:
         result.setdefault( frozenset([c1,orig_c2]), [] ).append( [p_identity,None] )
   # Build graph
   g = graph.adjacency_list()
   vertex_handle = {}
   for key in result:
     seqid = result[key][0][0]
     sup = min( result[key],key=lambda s:0 if s[1] is None else s[1][2])[1]
     result[key] = [seqid,sup]
     if ((seqid > sequence_identity_threshold) and (sup[2] < angular_difference_threshold_deg)):
       (c1,c2) = key
       if (c1 not in vertex_handle):
         vertex_handle[c1] = g.add_vertex(label=c1)
       if (c2 not in vertex_handle):
         vertex_handle[c2] = g.add_vertex(label=c2)
       g.add_edge(vertex1=vertex_handle[c1],vertex2=vertex_handle[c2])
   # Do connected component analysis and compose final tNCS pairs object
   components = connected_component_algorithm.connected_components(g)
   import itertools
   self.ncs_pairs = []
   for (i,group) in enumerate(components):
     chains = [g.vertex_label(vertex=v) for v in group]
     fracscats = []
     radii = []
     for pair in itertools.combinations(chains,2):
       sup = result[frozenset(pair)][1]
       fracscats.append(sup[-1])
       radii.append(sup[-2])
     fs = sum(fracscats)/len(fracscats)
     rad = sum(radii)/len(radii)
     for pair in itertools.combinations(chains,2):
       sup = result[frozenset(pair)][1]
       ncs_pair = ext.pair(
         r = sup[0],
         t = sup[1],
         radius = rad,
         radius_estimate = rad,
         fracscat = fs,
         rho_mn = flex.double(), # rho_mn undefined, needs to be set later
         id = i)
       self.ncs_pairs.append(ncs_pair)
       # show tNCS pairs in group
       fmt="group %d chains %s <> %s angle: %4.2f trans.vect.: (%s) fracscat: %5.3f"
       t = ",".join([("%6.3f"%t_).strip() for t_ in sup[1]]).strip()
       print fmt%(i, pair[0].id, pair[1].id, sup[2], t, fs)