示例#1
0
def exercise_zeolite_atlas(distance_cutoff=3.5):
    atlas_file = libtbx.env.find_in_repositories(
        relative_path="phenix_regression/misc/strudat_zeolite_atlas",
        test=os.path.isfile)
    if (atlas_file is None):
        print("Skipping exercise_zeolite_atlas(): input file not available")
        return
    with open(atlas_file) as f:
        all_entries = strudat.read_all_entries(f)
    for i, entry in enumerate(all_entries.entries):
        structure = entry.as_xray_structure()
        if ("--full" in sys.argv[1:] or i % 20 == 0):
            tst_direct_space_asu.exercise_neighbors_pair_generators(
                structure=structure, verbose="--Verbose" in sys.argv[1:])
        asu_mappings = structure.asu_mappings(buffer_thickness=distance_cutoff)
        pair_generator = crystal.neighbors_fast_pair_generator(
            asu_mappings=asu_mappings, distance_cutoff=distance_cutoff)
        bond_counts = flex.size_t(structure.scatterers().size(), 0)
        for pair in pair_generator:
            bond_counts[pair.i_seq] += 1
            if (pair.j_sym == 0):
                bond_counts[pair.j_seq] += 1
        for atom, bond_count in zip(entry.atoms, bond_counts):
            assert atom.connectivity is not None
            assert atom.connectivity == bond_count
def check_distances(sites_cart, point_distance, verbose):
  asu_mappings = non_crystallographic_asu_mappings(sites_cart=sites_cart)
  distance_cutoff = point_distance * math.sqrt(2) * 0.99
  simple_pair_generator = crystal.neighbors_simple_pair_generator(
    asu_mappings=asu_mappings,
    distance_cutoff=distance_cutoff)
  pair_generator = crystal.neighbors_fast_pair_generator(
    asu_mappings=asu_mappings,
    distance_cutoff=distance_cutoff)
  assert simple_pair_generator.count_pairs() == pair_generator.count_pairs()
  pair_generator.restart()
  neighbors = {}
  for pair in pair_generator:
    assert pair.j_seq != pair.i_seq
    assert pair.j_sym == 0
    assert approx_equal(pair.dist_sq, point_distance**2)
    neighbors[pair.i_seq] = neighbors.get(pair.i_seq, 0) + 1
    neighbors[pair.j_seq] = neighbors.get(pair.j_seq, 0) + 1
  n_dict = {}
  for n in neighbors.values():
    n_dict[n] = n_dict.get(n, 0) + 1
  if (verbose):
    print n_dict
  if (len(neighbors) > 0):
    assert max(neighbors.values()) <= 12
示例#3
0
def get_crystal_contact_operators(hierarchy, crystal_symmetry,
                                  distance_cutoff):
    """Use an alternate method to identify the symmetry operations required to generate crystal contacts"""

    # Extract the xray structure from the reference hierarchy
    struc = hierarchy.extract_xray_structure(crystal_symmetry=crystal_symmetry)
    atoms = hierarchy.atoms()

    # Extract the mappings that will tell us the adjacent symmetry copies
    asu_mappings = struc.asu_mappings(buffer_thickness=distance_cutoff)
    uc = asu_mappings.unit_cell()
    # Symmetry operations for each atom
    mappings = asu_mappings.mappings()

    # There should be one mappings list per atom
    assert len(struc.scatterers()) == len(mappings)

    # Get all atom pairs within distance_cutoff distance
    pair_generator = crystal.neighbors_fast_pair_generator(
        asu_mappings, distance_cutoff=distance_cutoff)
    sym_operations = []
    for pair in pair_generator:
        # obtain rt_mx_ji - symmetry operator that should be applied to j-th atom
        # to transfer it to i-th atom
        rt_mx_i = asu_mappings.get_rt_mx_i(pair)
        rt_mx_j = asu_mappings.get_rt_mx_j(pair)
        rt_mx_ji = rt_mx_i.inverse().multiply(rt_mx_j)
        # if it is not a unit matrix, that is symmetry related pair of atoms
        if not rt_mx_ji.is_unit_mx():
            if rt_mx_ji not in sym_operations:
                sym_operations.append(rt_mx_ji)

    return sym_operations
示例#4
0
def exercise_zeolite_atlas(distance_cutoff=3.5):
  atlas_file = libtbx.env.find_in_repositories(
    relative_path="phenix_regression/misc/strudat_zeolite_atlas",
    test=os.path.isfile)
  if (atlas_file is None):
    print "Skipping exercise_zeolite_atlas(): input file not available"
    return
  all_entries = strudat.read_all_entries(open(atlas_file))
  for i,entry in enumerate(all_entries.entries):
    structure = entry.as_xray_structure()
    if ("--full" in sys.argv[1:] or i % 20 == 0):
      tst_direct_space_asu.exercise_neighbors_pair_generators(
        structure=structure,
        verbose="--Verbose" in sys.argv[1:])
    asu_mappings = structure.asu_mappings(buffer_thickness=distance_cutoff)
    pair_generator = crystal.neighbors_fast_pair_generator(
      asu_mappings=asu_mappings,
      distance_cutoff=distance_cutoff)
    bond_counts = flex.size_t(structure.scatterers().size(), 0)
    for pair in pair_generator:
      bond_counts[pair.i_seq] += 1
      if (pair.j_sym == 0):
        bond_counts[pair.j_seq] += 1
    for atom,bond_count in zip(entry.atoms, bond_counts):
      assert atom.connectivity is not None
      assert atom.connectivity == bond_count
 def sel_within(self, radius, primary_selection):
     assert radius > 0
     assert self.special_position_settings is not None
     return crystal.neighbors_fast_pair_generator(
         asu_mappings=self.special_position_settings.asu_mappings(
             buffer_thickness=radius,
             sites_cart=self.root.atoms().extract_xyz()),
         distance_cutoff=radius).neighbors_of(
             primary_selection=primary_selection)
示例#6
0
 def sel_within(self, radius, primary_selection):
   assert radius > 0
   assert self.special_position_settings is not None
   return crystal.neighbors_fast_pair_generator(
     asu_mappings=self.special_position_settings.asu_mappings(
       buffer_thickness=radius,
       sites_cart=self.root.atoms().extract_xyz()),
     distance_cutoff=radius).neighbors_of(
       primary_selection=primary_selection)
示例#7
0
def get_pair_generator(crystal_symmetry, buffer_thickness, sites_cart):
    sst = crystal_symmetry.special_position_settings().site_symmetry_table(
        sites_cart=sites_cart)
    from cctbx import crystal
    conn_asu_mappings = crystal_symmetry.special_position_settings().\
      asu_mappings(buffer_thickness = buffer_thickness)
    conn_asu_mappings.process_sites_cart(original_sites=sites_cart,
                                         site_symmetry_table=sst)
    conn_pair_asu_table = crystal.pair_asu_table(
        asu_mappings=conn_asu_mappings)
    conn_pair_asu_table.add_all_pairs(distance_cutoff=buffer_thickness)
    pair_generator = crystal.neighbors_fast_pair_generator(
        conn_asu_mappings, distance_cutoff=buffer_thickness)
    return group_args(pair_generator=pair_generator,
                      conn_asu_mappings=conn_asu_mappings)
示例#8
0
def exercise_icosahedron(max_level=2, verbose=0):
    for level in range(0, max_level + 1):
        if (0 or verbose):
            print("level:", level)
        icosahedron = scitbx.math.icosahedron(level=level)
        try:
            distance_cutoff = icosahedron.next_neighbors_distance() * (1 +
                                                                       1.e-3)
            estimated_distance_cutoff = False
        except RuntimeError as e:
            assert str(e) == "next_neighbors_distance not known."
            distance_cutoff = 0.4 / (2**(level - 1))
            estimated_distance_cutoff = True
        asu_mappings = crystal.direct_space_asu.non_crystallographic_asu_mappings(
            sites_cart=icosahedron.sites)
        pair_asu_table = crystal.pair_asu_table(asu_mappings=asu_mappings)
        pair_asu_table.add_all_pairs(distance_cutoff=distance_cutoff)
        if (0 or verbose):
            ps = pair_asu_table.show_distances(sites_cart=icosahedron.sites) \
              .distances_info
            print("level", level, "min", flex.min(ps.distances))
            print("     ", " ", "max", flex.max(ps.distances))
            assert ps.pair_counts.all_eq(pair_asu_table.pair_counts())
            if (level == 0):
                for d in ps.distances:
                    assert approx_equal(d, 1.0514622242382672)
        elif (level < 2):
            s = StringIO()
            ps = pair_asu_table.show_distances(sites_cart=icosahedron.sites, out=s) \
              .distances_info
            assert ps.pair_counts.all_eq(pair_asu_table.pair_counts())
            assert len(s.getvalue().splitlines()) == [72, 320][level]
            del s
        if (level == 0):
            assert pair_asu_table.pair_counts().all_eq(5)
        else:
            assert pair_asu_table.pair_counts().all_eq(3)
        del pair_asu_table
        max_distance = crystal.neighbors_fast_pair_generator(
            asu_mappings=asu_mappings,
            distance_cutoff=distance_cutoff).max_distance_sq()**.5
        if (0 or verbose):
            print("max_distance:", max_distance)
        if (not estimated_distance_cutoff):
            assert approx_equal(max_distance,
                                icosahedron.next_neighbors_distance())
            assert approx_equal(
                max_distance / icosahedron.next_neighbors_distance(), 1)
def exercise_icosahedron(max_level=2, verbose=0):
  for level in xrange(0,max_level+1):
    if (0 or verbose):
      print "level:", level
    icosahedron = scitbx.math.icosahedron(level=level)
    try:
      distance_cutoff = icosahedron.next_neighbors_distance()*(1+1.e-3)
      estimated_distance_cutoff = False
    except RuntimeError, e:
      assert str(e) == "next_neighbors_distance not known."
      distance_cutoff = 0.4/(2**(level-1))
      estimated_distance_cutoff = True
    asu_mappings = crystal.direct_space_asu.non_crystallographic_asu_mappings(
      sites_cart=icosahedron.sites)
    pair_asu_table = crystal.pair_asu_table(asu_mappings=asu_mappings)
    pair_asu_table.add_all_pairs(distance_cutoff=distance_cutoff)
    if (0 or verbose):
      ps = pair_asu_table.show_distances(sites_cart=icosahedron.sites) \
        .distances_info
      print "level", level, "min", flex.min(ps.distances)
      print "     ", " ",   "max", flex.max(ps.distances)
      assert ps.pair_counts.all_eq(pair_asu_table.pair_counts())
      if (level == 0):
        for d in ps.distances:
          assert approx_equal(d, 1.0514622242382672)
    elif (level < 2):
      s = StringIO()
      ps = pair_asu_table.show_distances(sites_cart=icosahedron.sites, out=s) \
        .distances_info
      assert ps.pair_counts.all_eq(pair_asu_table.pair_counts())
      assert len(s.getvalue().splitlines()) == [72,320][level]
      del s
    if (level == 0):
      assert pair_asu_table.pair_counts().all_eq(5)
    else:
      assert pair_asu_table.pair_counts().all_eq(3)
    del pair_asu_table
    max_distance = crystal.neighbors_fast_pair_generator(
      asu_mappings=asu_mappings,
      distance_cutoff=distance_cutoff).max_distance_sq()**.5
    if (0 or verbose):
      print "max_distance:", max_distance
    if (not estimated_distance_cutoff):
      assert approx_equal(max_distance, icosahedron.next_neighbors_distance())
      assert approx_equal(max_distance/icosahedron.next_neighbors_distance(),1)
示例#10
0
    def contacts_to_all(self, pdb_hier, symmetry, cutoff=6.0):
        #finds all contacts within cutoff in an entire pdb_hier
        xrs = pdb_hier.extract_xray_structure(crystal_symmetry=symmetry)
        asu_mappings = xrs.asu_mappings(buffer_thickness=cutoff + 1.0)
        pair_generator = crystal.neighbors_fast_pair_generator(
            asu_mappings, distance_cutoff=cutoff)
        natoms = pdb_hier.atoms().size()
        #distance matrix impractical as we may have multiple contacts to the same atom by symmetry
        #all of which need to be preserved
        all_cont = {}
        for i in range(natoms):
            all_cont[i] = []
        for pair in pair_generator:
            pi = pair.i_seq
            pj = pair.j_seq
            ps = pair.j_sym
            pd = int(np.sqrt(pair.dist_sq) *
                     1000) / 1000.0  #avoid base2 float issues for uniquifying
            all_cont[pi].append(
                (pj, pd, ps))  #need both from and to (across asu)
            all_cont[pj].append((pi, pd, ps))
        ncont = 0

        awl_db = {}  # refs to awl objects to pass
        for awl in pdb_hier.atoms_with_labels():
            awl_db[awl.i_seq] = awl

        all_cont_db = {}

        for iseq, clist in all_cont.iteritems():
            #print "PROTO",iseq,clist
            ncont = ncont + len(clist)
            source_at = iseq
            source_awl = awl_db[source_at]
            uni_c = set(clist)
            # for each source awl, generate list of unique tuples (cont awl,distance,sym)
            cpairs = list(
                (awl_db[c_at[0]], c_at[1], c_at[2]) for c_at in uni_c)
            contacts, s_unique_id = self.get_contacts(source_awl,
                                                      cpairs,
                                                      cutoff=cutoff)
            all_cont_db[s_unique_id] = contacts
        print "      Found %d contact pairs" % ncont
        return all_cont_db
示例#11
0
def check_distances(sites_cart, point_distance, verbose):
    asu_mappings = non_crystallographic_asu_mappings(sites_cart=sites_cart)
    distance_cutoff = point_distance * math.sqrt(2) * 0.99
    simple_pair_generator = crystal.neighbors_simple_pair_generator(
        asu_mappings=asu_mappings, distance_cutoff=distance_cutoff)
    pair_generator = crystal.neighbors_fast_pair_generator(
        asu_mappings=asu_mappings, distance_cutoff=distance_cutoff)
    assert simple_pair_generator.count_pairs() == pair_generator.count_pairs()
    pair_generator.restart()
    neighbors = {}
    for pair in pair_generator:
        assert pair.j_seq != pair.i_seq
        assert pair.j_sym == 0
        assert approx_equal(pair.dist_sq, point_distance**2)
        neighbors[pair.i_seq] = neighbors.get(pair.i_seq, 0) + 1
        neighbors[pair.j_seq] = neighbors.get(pair.j_seq, 0) + 1
    n_dict = {}
    for n in neighbors.values():
        n_dict[n] = n_dict.get(n, 0) + 1
    if (verbose):
        print(n_dict)
    if (len(neighbors) > 0):
        assert max(neighbors.values()) <= 12
示例#12
0
def create_super_sphere(pdb_hierarchy,
                        crystal_symmetry,
                        select_within_radius,
                        link_min=1.0,
                        link_max=2.0,
                        r=None):
    if (r is None):
        # This is equivalent to (but much faster):
        #
        #r = grm.geometry.pair_proxies().nonbonded_proxies.\
        #  get_symmetry_interacting_indices_unique(
        #    sites_cart = pdb_hierarchy.atoms().extract_xyz())
        #
        sites_cart = pdb_hierarchy.atoms().extract_xyz()
        sst = crystal_symmetry.special_position_settings().site_symmetry_table(
            sites_cart=sites_cart)
        r = {}
        from cctbx import crystal
        cutoff = select_within_radius + 1  # +1 is nonbonded buffer
        conn_asu_mappings = crystal_symmetry.special_position_settings().\
          asu_mappings(buffer_thickness=cutoff)
        conn_asu_mappings.process_sites_cart(original_sites=sites_cart,
                                             site_symmetry_table=sst)
        conn_pair_asu_table = crystal.pair_asu_table(
            asu_mappings=conn_asu_mappings)
        conn_pair_asu_table.add_all_pairs(distance_cutoff=cutoff)
        pair_generator = crystal.neighbors_fast_pair_generator(
            conn_asu_mappings, distance_cutoff=cutoff)
        for pair in pair_generator:
            rt_mx_i = conn_asu_mappings.get_rt_mx_i(pair)
            rt_mx_j = conn_asu_mappings.get_rt_mx_j(pair)
            rt_mx_ji = rt_mx_i.inverse().multiply(rt_mx_j)
            if str(rt_mx_ji) == "x,y,z": continue
            r.setdefault(pair.j_seq, []).append(rt_mx_ji)
        for k, v in zip(r.keys(), r.values()):  # remove duplicates!
            r[k] = list(set(v))
    c = iotbx.pdb.hierarchy.chain(
        id="SS")  # all symmetry related full residues
    fm = crystal_symmetry.unit_cell().fractionalization_matrix()
    om = crystal_symmetry.unit_cell().orthogonalization_matrix()
    selection = r.keys()
    for rg in pdb_hierarchy.residue_groups():
        keep = False
        for i in rg.atoms().extract_i_seq():
            if (i in selection):
                keep = True
                break
        if (keep):
            ops = r[i]
            for op in ops:
                rg_ = rg.detached_copy()
                xyz = rg_.atoms().extract_xyz()
                new_xyz = flex.vec3_double()
                for xyz_ in xyz:
                    t1 = fm * flex.vec3_double([xyz_])
                    t2 = op * t1[0]
                    t3 = om * flex.vec3_double([t2])
                    new_xyz.append(t3[0])
                rg_.atoms().set_xyz(new_xyz)
                rg_.link_to_previous = True
                c.append_residue_group(rg_)
    resseq = 0
    for rg in c.residue_groups():
        rg.resseq = "%4d" % resseq
        resseq += 1
    # Now we need to re-order residues and group by chains so that they can be
    # linked by pdb interpretation.
    super_sphere_hierarchy = pdb_hierarchy.deep_copy()
    #
    all_chains = iotbx.pdb.utils.all_chain_ids()
    all_chains = [chid.strip() for chid in all_chains]
    for cid in list(set([i.id for i in pdb_hierarchy.chains()])):
        all_chains.remove(cid)
    all_chains = iter(all_chains)

    #
    def get_atom(atoms, name):
        for a in atoms:
            if (a.name.strip().lower() == name.strip().lower()):
                return a.xyz

    residue_groups_i = list(c.residue_groups())
    residue_groups_j = list(c.residue_groups())
    residue_groups_k = list()  # standard aa residues only

    #
    def dist(r1, r2):
        return math.sqrt((r1[0] - r2[0])**2 + (r1[1] - r2[1])**2 +
                         (r1[2] - r2[2])**2)

    #
    def grow_chain(residue_groups_j, chunk, ci):
        n_linked = 0
        for rgj in residue_groups_j:
            nj = get_atom(atoms=rgj.atoms(), name="N")
            if (nj is None): continue
            d_ci_nj = dist(ci, nj)
            if (d_ci_nj < link_max and d_ci_nj > link_min):
                n_linked += 1
                chunk.append(rgj)
                residue_groups_j.remove(rgj)
                break
        return n_linked, rgj

    # Find all isolated single residues, and also save starters
    starters = []
    for rgi in residue_groups_i:
        ci = get_atom(atoms=rgi.atoms(), name="C")
        ni = get_atom(atoms=rgi.atoms(), name="N")
        if (ci is None or ni is None):  # collect non-proteins
            c = iotbx.pdb.hierarchy.chain(id=all_chains.next())
            c.append_residue_group(rgi)
            super_sphere_hierarchy.models()[0].append_chain(c)
            continue
        residue_groups_k.append(rgi)
        c_linked = 0
        n_linked = 0
        for rgj in residue_groups_j:
            cj = get_atom(atoms=rgj.atoms(), name="C")
            nj = get_atom(atoms=rgj.atoms(), name="N")
            if (cj is None or nj is None): continue
            d_ci_nj = dist(ci, nj)
            d_ni_cj = dist(ni, cj)
            if (d_ci_nj < link_max and d_ci_nj > link_min):
                n_linked += 1
            if (d_ni_cj < link_max and d_ni_cj > link_min):
                c_linked += 1
        assert c_linked in [1, 0], c_linked  # Either linked or not!
        assert n_linked in [1, 0], n_linked  # Either linked or not!
        if (c_linked == 0 and n_linked == 0):  # isolated single residue
            c = iotbx.pdb.hierarchy.chain(id=all_chains.next())
            rgi.link_to_previous = True
            c.append_residue_group(rgi)
            super_sphere_hierarchy.models()[0].append_chain(c)
        elif (c_linked == 0):  # collect c-terminal residues
            starters.append(rgi)
    # Grow continuous chains from remaining residues starting from c-terminals
    for rgi in starters:
        ci = get_atom(atoms=rgi.atoms(), name="C")
        chunk = [rgi]
        n_linked = 1
        while n_linked == 1:
            n_linked, rgj = grow_chain(residue_groups_k, chunk, ci)
            if (n_linked == 1):
                ci = get_atom(atoms=rgj.atoms(), name="C")
        c = iotbx.pdb.hierarchy.chain(id=all_chains.next())
        for i, rg in enumerate(chunk):
            rg.resseq = "%4d" % i
            c.append_residue_group(rg)
        super_sphere_hierarchy.models()[0].append_chain(c)
    #
    box = uctbx.non_crystallographic_unit_cell_with_the_sites_in_its_center(
        sites_cart=super_sphere_hierarchy.atoms().extract_xyz(),
        buffer_layer=10)
    cs_super_sphere = box.crystal_symmetry()
    return group_args(hierarchy=super_sphere_hierarchy,
                      crystal_symmetry=cs_super_sphere,
                      selection_r=r)
示例#13
0
def compare_ions(hierarchy,
                 reference_hierarchy,
                 reference_xrs,
                 distance_cutoff=2.0,
                 log=None,
                 ignore_elements=(),
                 only_elements=(),
                 sel_str_base="segid ION"):
    """
  Compares two pdb structures to determine the number of ions that appear in the
  reference structure and are either matched or missing in the other structure.

  Parameters
  ----------
  hierarchy : iotbx.pdb.hierarchy.root
  reference_hierarchy : iotbx.pdb.hierarchy.root
  reference_xrs : ...
  distance_cutoff : float, optional
  log : file, optional
  ignore_element : iterable, optional
  only_elements : iterable, optional
  sel_str_base : str, optional

  Returns
  -------
  int
      Number of ions in reference_hierarchy that were also found in hierarchy.
  int
      Number of ions in reference_hierarchy that were not found in hierarchy.
  """
    if log is None:
        log = null_out()
    sel_cache = hierarchy.atom_selection_cache()
    sel_str = sel_str_base
    if len(only_elements) > 0:
        sel_str += " and (%s)" % " or ".join(
            ["element %s" % e for e in only_elements])
    elif len(ignore_elements) > 0:
        sel_str += " and not (%s)" % " or ".join(
            ["element %s" % e for e in ignore_elements])
    ion_isel = sel_cache.selection(sel_str).iselection()
    if len(ion_isel) == 0:
        return [], []
    pdb_atoms = hierarchy.atoms()
    pdb_atoms.reset_i_seq()
    ions = pdb_atoms.select(ion_isel)
    asu_mappings = reference_xrs.asu_mappings(
        buffer_thickness=distance_cutoff + 0.1)
    unit_cell = reference_xrs.unit_cell()
    sites_cart = ions.extract_xyz()
    sites_frac = unit_cell.fractionalize(sites_cart=sites_cart)
    asu_mappings.process_sites_frac(
        sites_frac,
        min_distance_sym_equiv=reference_xrs.min_distance_sym_equiv())
    pair_generator = crystal.neighbors_fast_pair_generator(
        asu_mappings=asu_mappings, distance_cutoff=distance_cutoff)
    reference_atoms = reference_hierarchy.atoms()
    n_xray = reference_xrs.scatterers().size()
    ion_ref_i_seqs = []
    for k in range(len(ions)):
        ion_ref_i_seqs.append([])
    for pair in pair_generator:
        if ((pair.i_seq < n_xray and pair.j_seq < n_xray)
                or (pair.i_seq >= n_xray and pair.j_seq >= n_xray)):
            continue
        if pair.i_seq < n_xray:
            ion_seq, ref_seq = pair.j_seq, pair.i_seq
        else:
            ion_seq, ref_seq = pair.i_seq, pair.j_seq
        site_frac = sites_frac[ion_seq - n_xray]
        dxyz = sqrt(pair.dist_sq)
        j_seq = ion_seq - n_xray
        ion_ref_i_seqs[j_seq].append(ref_seq)
    # FIXME better filtering needed - right now we risk double-counting ions in
    # the reference model, although I haven't found a case of this yet
    matched = []
    missing = []
    for i_seq, ref_i_seqs in enumerate(ion_ref_i_seqs):
        ion = ions[i_seq]
        if len(ref_i_seqs) == 0:
            print("No match for %s" % ion.id_str(), file=log)
            missing.append(ion.id_str())
        else:
            ref_ions = []
            for i_seq in ref_i_seqs:
                ref_atom = reference_atoms[i_seq]
                if ion.element.upper() == ref_atom.element.upper():
                    ref_ions.append(ref_atom.id_str())
            if len(ref_ions) >= 1:
                matched.append(ion.id_str())
                if len(ref_ions) > 1:
                    print("Multiple matches for %s:" % ion.id_str(), file=log)
                    for ref_ion in ref_ions:
                        print("  %s" % ref_ion, file=log)
                else:
                    print("Ion %s matches %s" % (ion.id_str(), ref_ions[0]),
                          file=log)
            else:
                print("No match for %s" % ion.id_str(), file=log)
                missing.append(ion.id_str())
    return matched, missing
def exercise_with_zeolite(verbose):
    if (not libtbx.env.has_module("iotbx")):
        print("Skipping exercise_with_zeolite(): iotbx not available")
        return
    from iotbx.kriber import strudat
    atlas_file = libtbx.env.find_in_repositories(
        relative_path="phenix_regression/misc/strudat_zeolite_atlas",
        test=os.path.isfile)
    if (atlas_file is None):
        print("Skipping exercise_with_zeolite(): input file not available")
        return
    strudat_contents = strudat.read_all_entries(open(atlas_file))
    strudat_entry = strudat_contents.get("YUG")
    si_structure = strudat_entry.as_xray_structure()
    if (verbose):
        out = sys.stdout
    else:
        out = StringIO()
    drls = distance_and_repulsion_least_squares(
        si_structure=si_structure,
        distance_cutoff=3.5,
        nonbonded_repulsion_function_type="prolsq",
        n_macro_cycles=2,
        out=out)
    #
    nbp = drls.geometry_restraints_manager.pair_proxies().nonbonded_proxies
    assert nbp.n_total() > 50
    # expected is 60, but the exact number depends on the minimizer
    #
    site_labels = drls.minimized_structure.scatterers().extract_labels()
    sites_cart = drls.start_structure.sites_cart()
    pair_proxies = drls.geometry_restraints_manager.pair_proxies()
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          site_labels=site_labels,
                                          f=out)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert len(out.getvalue().splitlines()) == 48 * 4 + 2
    assert out.getvalue().splitlines()[-1].find("remaining") < 0
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          site_labels=site_labels,
                                          f=out,
                                          prefix="0^",
                                          max_items=28)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue().replace("e-00", "e-0"),
                         """\
0^Bond restraints: 48
0^Sorted by residual:
0^bond O3
0^     O4
0^  ideal  model  delta    sigma   weight residual
0^  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
0^bond SI1
0^     SI1
0^  ideal  model  delta    sigma   weight residual sym.op.
0^  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
0^... (remaining 20 not shown)
""",
                         selections=[range(6), range(-5, 0)])
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="delta",
                                          sites_cart=sites_cart,
                                          site_labels=site_labels,
                                          f=out,
                                          prefix="0^",
                                          max_items=28)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue().replace("e-00", "e-0"),
                         """\
0^Bond restraints: 48
0^Sorted by delta:
0^bond O3
0^     O4
0^  ideal  model  delta    sigma   weight residual
0^  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
0^... (remaining 20 not shown)
""",
                         selections=[range(6), [-1]])
    site_labels_long = ["abc" + label + "def" for label in site_labels]
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          site_labels=site_labels_long,
                                          f=out,
                                          prefix="^0",
                                          max_items=28)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue().replace("e-00", "e-0"),
                         """\
^0Bond restraints: 48
^0Sorted by residual:
^0bond abcO3def
^0     abcO4def
^0  ideal  model  delta    sigma   weight residual
^0  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
^0bond abcSI1def
^0     abcSI1def
^0  ideal  model  delta    sigma   weight residual sym.op.
^0  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
^0... (remaining 20 not shown)
""",
                         selections=[range(6), range(-5, 0)])
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          f=out,
                                          prefix=".=",
                                          max_items=28)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue().replace("e-00", "e-0"),
                         """\
.=Bond restraints: 48
.=Sorted by residual:
.=bond 4
.=     5
.=  ideal  model  delta    sigma   weight residual
.=  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
.=bond 0
.=     0
.=  ideal  model  delta    sigma   weight residual sym.op.
.=  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
.=... (remaining 20 not shown)
""",
                         selections=[range(6), range(-5, 0)])
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          f=out,
                                          prefix="-+",
                                          max_items=1)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(
        out.getvalue().replace("e-00", "e-0"), """\
-+Bond restraints: 48
-+Sorted by residual:
-+bond 4
-+     5
-+  ideal  model  delta    sigma   weight residual
-+  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
-+... (remaining 47 not shown)
""")
    out = StringIO()
    pair_proxies.bond_proxies.show_sorted(by_value="residual",
                                          sites_cart=sites_cart,
                                          f=out,
                                          prefix="=+",
                                          max_items=0)
    if (verbose):
        sys.stdout.write(out.getvalue())
    assert not show_diff(
        out.getvalue(), """\
=+Bond restraints: 48
=+Sorted by residual:
=+... (remaining 48 not shown)
""")
    #
    sites_cart = si_structure.sites_cart()
    site_labels = [sc.label for sc in si_structure.scatterers()]
    asu_mappings = si_structure.asu_mappings(buffer_thickness=3.5)
    for min_cubicle_edge in [0, 5]:
        pair_generator = crystal.neighbors_fast_pair_generator(
            asu_mappings=asu_mappings,
            distance_cutoff=asu_mappings.buffer_thickness(),
            minimal=False,
            min_cubicle_edge=min_cubicle_edge)
        sorted_asu_proxies = geometry_restraints.nonbonded_sorted_asu_proxies(
            asu_mappings=asu_mappings)
        while (not pair_generator.at_end()):
            p = geometry_restraints.nonbonded_asu_proxy(
                pair=next(pair_generator), vdw_distance=3)
            sorted_asu_proxies.process(p)
        out = StringIO()
        sorted_asu_proxies.show_sorted(by_value="delta",
                                       sites_cart=sites_cart,
                                       site_labels=site_labels,
                                       f=out,
                                       prefix="d%")
        if (verbose):
            sys.stdout.write(out.getvalue())
        assert not show_diff(
            out.getvalue(),
            """\
d%Nonbonded interactions: 7
d%Sorted by model distance:
...
d%nonbonded SI2
d%          SI2
d%   model   vdw sym.op.
d%   3.092 3.000 -x+1,y,-z
...
d%nonbonded SI1
d%          SI1
d%   model   vdw sym.op.
d%   3.216 3.000 -x+1/2,-y+1/2,-z+1
""",
            selections=[range(2), range(10, 14),
                        range(26, 30)])
        out = StringIO()
        sorted_asu_proxies.show_sorted(by_value="delta",
                                       sites_cart=sites_cart,
                                       f=out,
                                       prefix="*j",
                                       max_items=5)
        if (verbose):
            sys.stdout.write(out.getvalue())
        assert not show_diff(out.getvalue(),
                             """\
*jNonbonded interactions: 7
*jSorted by model distance:
...
*jnonbonded 0
*j          1
*j   model   vdw
*j   3.107 3.000
*jnonbonded 0
*j          0
*j   model   vdw sym.op.
*j   3.130 3.000 -x+1,y,-z+1
*j... (remaining 2 not shown)
""",
                             selections=[range(2), range(-9, 0)])
        out = StringIO()
        sorted_asu_proxies.show_sorted(by_value="delta",
                                       sites_cart=sites_cart,
                                       f=out,
                                       prefix="@r",
                                       max_items=0)
        if (verbose):
            sys.stdout.write(out.getvalue())
        assert not show_diff(out.getvalue(), """\
@rNonbonded interactions: 7
""")
示例#15
0
    def contacts_to_coord(self, coord, pdb_hier, symmetry, cutoff=6.0):
        """
        Used to use extract map_model, but that caused problems
        This function takes cartesian coordinate, pdb_hier, and symmetry and returns
        sorted list of dictionaries, each a particular contact

        very hacked together, jams pdb strings together
        create a dummy pdb, put water at the peak site in the original coordinate system
        then use fast pair generater to get all contacts to our peak atom
        """
        dummy_atom = self.pput.write_atom(1, "O", "", "HOH", "ZZ", 9999, "",
                                          coord[0], coord[1], coord[2], 1.0,
                                          35.0, "O", "")
        #hack to add an atom to a pdb
        orig_str = pdb_hier.as_pdb_string(write_scale_records=False,
                                          append_end=False,
                                          interleaved_conf=0,
                                          atoms_reset_serial_first_value=1,
                                          atom_hetatm=True,
                                          sigatm=False,
                                          anisou=False,
                                          siguij=False,
                                          output_break_records=False)
        nmodels = len(pdb_hier.models())
        if nmodels == 1:
            comb = orig_str + dummy_atom
        else:
            newmodel = nmodels + 1
            comb = orig_str + "MODEL %s\n" % newmodel
            comb = comb + dummy_atom
            comb = comb + "ENDMDL\n"
        dummy_pdb = iotbx.pdb.input(source_info=None,
                                    lines=flex.split_lines(comb))
        dummy_hier = dummy_pdb.construct_hierarchy()
        atsel = "chain ZZ and resid 9999"
        dummy_select = dummy_hier.atom_selection_cache().selection(
            string=atsel)
        atsel_index = np.argwhere(dummy_select.as_numpy_array())
        dummy_xrs = dummy_pdb.xray_structure_simple(crystal_symmetry=symmetry)
        #find neighbors with symmetry -- use pair_finding with asu_mappings
        #doing this for each peak may be a bad idea, use all_contacts version instead if possible
        asu_mappings = dummy_xrs.asu_mappings(buffer_thickness=cutoff)
        pair_generator = crystal.neighbors_fast_pair_generator(
            asu_mappings, distance_cutoff=cutoff)

        peak_vector_list = []
        #neighbor_mask = pair_generator.neighbors_of(atsel_arr)
        #neighbors = pair_generator.select(neighbor_mask)
        for pair in pair_generator:
            if pair.i_seq == atsel_index:
                #our peak is first atom, but we want pairs in both directions
                #to provide exhaustive list of contacts
                #store index number and difference vector and sym to make unique
                #we don't care which symop, just how far away
                rdist = int(
                    np.sqrt(pair.dist_sq) * 1000) / 1000.0  #avoid float error
                peak_vector_list.append((pair.j_seq, rdist, pair.j_sym))
            if pair.j_seq == atsel_index:
                rdist = int(np.sqrt(pair.dist_sq) * 1000) / 1000.0
                peak_vector_list.append((pair.i_seq, rdist, pair.j_sym))

        unique = set(peak_vector_list)
        dummy_atoms = dummy_hier.atoms()

        #selection is boolean flex array, sizeof no atoms, can be indexed directly
        #get awl for our dummy atom
        s_awl = dummy_atoms.select(dummy_select)[0].fetch_labels()
        #list((awl_db[c_at[0]],c_at[1],c_at[2]) for c_at in uni_c )
        #next, get list of contacts (awl,dist)
        selection = dummy_hier.atom_selection_cache().selection("not all")
        if len(unique) == 0:
            return []
        cont_list = []
        for conti in unique:
            selection[conti[0]] = True
            sel_awl = dummy_atoms.select(selection)[0].fetch_labels()
            cont_list.append(
                (sel_awl, conti[1],
                 conti[2]))  #pass source awl, index for target, distance
            selection[conti[0]] = False  #unselect
        contacts, s_unal = self.get_contacts(s_awl, cont_list, cutoff=cutoff)
        return contacts
def exercise_with_zeolite(verbose):
  if (not libtbx.env.has_module("iotbx")):
    print "Skipping exercise_with_zeolite(): iotbx not available"
    return
  from iotbx.kriber import strudat
  atlas_file = libtbx.env.find_in_repositories(
    relative_path="phenix_regression/misc/strudat_zeolite_atlas",
    test=os.path.isfile)
  if (atlas_file is None):
    print "Skipping exercise_with_zeolite(): input file not available"
    return
  strudat_contents = strudat.read_all_entries(open(atlas_file))
  strudat_entry = strudat_contents.get("YUG")
  si_structure = strudat_entry.as_xray_structure()
  if (verbose):
    out = sys.stdout
  else:
    out = StringIO()
  drls = distance_and_repulsion_least_squares(
    si_structure=si_structure,
    distance_cutoff=3.5,
    nonbonded_repulsion_function_type="prolsq",
    n_macro_cycles=2,
    out=out)
  #
  nbp = drls.geometry_restraints_manager.pair_proxies().nonbonded_proxies
  assert nbp.n_total() > 50
    # expected is 60, but the exact number depends on the minimizer
  #
  site_labels = drls.minimized_structure.scatterers().extract_labels()
  sites_cart = drls.start_structure.sites_cart()
  pair_proxies = drls.geometry_restraints_manager.pair_proxies()
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    site_labels=site_labels,
    f=out)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert len(out.getvalue().splitlines()) == 48*4+2
  assert out.getvalue().splitlines()[-1].find("remaining") < 0
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    site_labels=site_labels,
    f=out,
    prefix="0^",
    max_items=28)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue().replace("e-00", "e-0"), """\
0^Bond restraints: 48
0^Sorted by residual:
0^bond O3
0^     O4
0^  ideal  model  delta    sigma   weight residual
0^  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
0^bond SI1
0^     SI1
0^  ideal  model  delta    sigma   weight residual sym.op.
0^  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
0^... (remaining 20 not shown)
""",
    selections=[range(6), range(-5,0)])
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="delta",
    sites_cart=sites_cart,
    site_labels=site_labels,
    f=out,
    prefix="0^",
    max_items=28)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue().replace("e-00", "e-0"), """\
0^Bond restraints: 48
0^Sorted by delta:
0^bond O3
0^     O4
0^  ideal  model  delta    sigma   weight residual
0^  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
0^... (remaining 20 not shown)
""",
    selections=[range(6), [-1]])
  site_labels_long = ["abc"+label+"def" for label in site_labels]
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    site_labels=site_labels_long,
    f=out,
    prefix="^0",
    max_items=28)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue().replace("e-00", "e-0"), """\
^0Bond restraints: 48
^0Sorted by residual:
^0bond abcO3def
^0     abcO4def
^0  ideal  model  delta    sigma   weight residual
^0  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
^0bond abcSI1def
^0     abcSI1def
^0  ideal  model  delta    sigma   weight residual sym.op.
^0  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
^0... (remaining 20 not shown)
""",
    selections=[range(6), range(-5,0)])
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    f=out,
    prefix=".=",
    max_items=28)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue().replace("e-00", "e-0"), """\
.=Bond restraints: 48
.=Sorted by residual:
.=bond 4
.=     5
.=  ideal  model  delta    sigma   weight residual
.=  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
...
.=bond 0
.=     0
.=  ideal  model  delta    sigma   weight residual sym.op.
.=  3.071  3.216 -0.145 2.08e+00 2.31e-01 4.83e-03 -x+1/2,-y+1/2,-z+1
.=... (remaining 20 not shown)
""",
    selections=[range(6), range(-5,0)])
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    f=out,
    prefix="-+",
    max_items=1)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue().replace("e-00", "e-0"), """\
-+Bond restraints: 48
-+Sorted by residual:
-+bond 4
-+     5
-+  ideal  model  delta    sigma   weight residual
-+  2.629  2.120  0.509 1.56e+00 4.10e-01 1.06e-01
-+... (remaining 47 not shown)
""")
  out = StringIO()
  pair_proxies.bond_proxies.show_sorted(
    by_value="residual",
    sites_cart=sites_cart,
    f=out,
    prefix="=+",
    max_items=0)
  if (verbose):
    sys.stdout.write(out.getvalue())
  assert not show_diff(out.getvalue(), """\
=+Bond restraints: 48
=+Sorted by residual:
=+... (remaining 48 not shown)
""")
  #
  sites_cart = si_structure.sites_cart()
  site_labels = [sc.label for sc in si_structure.scatterers()]
  asu_mappings = si_structure.asu_mappings(buffer_thickness=3.5)
  for min_cubicle_edge in [0, 5]:
    pair_generator = crystal.neighbors_fast_pair_generator(
      asu_mappings=asu_mappings,
      distance_cutoff=asu_mappings.buffer_thickness(),
      minimal=False,
      min_cubicle_edge=min_cubicle_edge)
    sorted_asu_proxies = geometry_restraints.nonbonded_sorted_asu_proxies(
      asu_mappings=asu_mappings)
    while (not pair_generator.at_end()):
      p = geometry_restraints.nonbonded_asu_proxy(
        pair=pair_generator.next(),
        vdw_distance=3)
      sorted_asu_proxies.process(p)
    out = StringIO()
    sorted_asu_proxies.show_sorted(
      by_value="delta",
      sites_cart=sites_cart,
      site_labels=site_labels,
      f=out,
      prefix="d%")
    if (verbose):
      sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue(), """\
d%Nonbonded interactions: 7
d%Sorted by model distance:
...
d%nonbonded SI2
d%          SI2
d%   model   vdw sym.op.
d%   3.092 3.000 -x+1,y,-z
...
d%nonbonded SI1
d%          SI1
d%   model   vdw sym.op.
d%   3.216 3.000 -x+1/2,-y+1/2,-z+1
""",
      selections=[range(2), range(10,14), range(26,30)])
    out = StringIO()
    sorted_asu_proxies.show_sorted(
      by_value="delta",
      sites_cart=sites_cart,
      f=out,
      prefix="*j",
      max_items=5)
    if (verbose):
      sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue(), """\
*jNonbonded interactions: 7
*jSorted by model distance:
...
*jnonbonded 0
*j          1
*j   model   vdw
*j   3.107 3.000
*jnonbonded 0
*j          0
*j   model   vdw sym.op.
*j   3.130 3.000 -x+1,y,-z+1
*j... (remaining 2 not shown)
""",
      selections=[range(2), range(-9,0)])
    out = StringIO()
    sorted_asu_proxies.show_sorted(
      by_value="delta",
      sites_cart=sites_cart,
      f=out,
      prefix="@r",
      max_items=0)
    if (verbose):
      sys.stdout.write(out.getvalue())
    assert not show_diff(out.getvalue(), """\
@rNonbonded interactions: 7
""")
示例#17
0
def compare_ions(
    hierarchy,
    reference_hierarchy,
    reference_xrs,
    distance_cutoff=2.0,
    log=None,
    ignore_elements=(),
    only_elements=(),
    sel_str_base="segid ION",
):
    """
  Compares two pdb structures to determine the number of ions that appear in the
  reference structure and are either matched or missing in the other structure.

  Parameters
  ----------
  hierarchy : iotbx.pdb.hierarchy.root
  reference_hierarchy : iotbx.pdb.hierarchy.root
  reference_xrs : ...
  distance_cutoff : float, optional
  log : file, optional
  ignore_element : iterable, optional
  only_elements : iterable, optional
  sel_str_base : str, optional

  Returns
  -------
  int
      Number of ions in reference_hierarchy that were also found in hierarchy.
  int
      Number of ions in reference_hierarchy that were not found in hierarchy.
  """
    if log is None:
        log = null_out()
    sel_cache = hierarchy.atom_selection_cache()
    sel_str = sel_str_base
    if len(only_elements) > 0:
        sel_str += " and (%s)" % " or ".join(["element %s" % e for e in only_elements])
    elif len(ignore_elements) > 0:
        sel_str += " and not (%s)" % " or ".join(["element %s" % e for e in ignore_elements])
    ion_isel = sel_cache.selection(sel_str).iselection()
    if len(ion_isel) == 0:
        return [], []
    pdb_atoms = hierarchy.atoms()
    pdb_atoms.reset_i_seq()
    ions = pdb_atoms.select(ion_isel)
    asu_mappings = reference_xrs.asu_mappings(buffer_thickness=distance_cutoff + 0.1)
    unit_cell = reference_xrs.unit_cell()
    sites_cart = ions.extract_xyz()
    sites_frac = unit_cell.fractionalize(sites_cart=sites_cart)
    asu_mappings.process_sites_frac(sites_frac, min_distance_sym_equiv=reference_xrs.min_distance_sym_equiv())
    pair_generator = crystal.neighbors_fast_pair_generator(asu_mappings=asu_mappings, distance_cutoff=distance_cutoff)
    reference_atoms = reference_hierarchy.atoms()
    n_xray = reference_xrs.scatterers().size()
    ion_ref_i_seqs = []
    for k in range(len(ions)):
        ion_ref_i_seqs.append([])
    for pair in pair_generator:
        if (pair.i_seq < n_xray and pair.j_seq < n_xray) or (pair.i_seq >= n_xray and pair.j_seq >= n_xray):
            continue
        if pair.i_seq < n_xray:
            ion_seq, ref_seq = pair.j_seq, pair.i_seq
        else:
            ion_seq, ref_seq = pair.i_seq, pair.j_seq
        site_frac = sites_frac[ion_seq - n_xray]
        dxyz = sqrt(pair.dist_sq)
        j_seq = ion_seq - n_xray
        ion_ref_i_seqs[j_seq].append(ref_seq)
    # FIXME better filtering needed - right now we risk double-counting ions in
    # the reference model, although I haven't found a case of this yet
    matched = []
    missing = []
    for i_seq, ref_i_seqs in enumerate(ion_ref_i_seqs):
        ion = ions[i_seq]
        if len(ref_i_seqs) == 0:
            print >> log, "No match for %s" % ion.id_str()
            missing.append(ion.id_str())
        else:
            ref_ions = []
            for i_seq in ref_i_seqs:
                ref_atom = reference_atoms[i_seq]
                if ion.element.upper() == ref_atom.element.upper():
                    ref_ions.append(ref_atom.id_str())
            if len(ref_ions) >= 1:
                matched.append(ion.id_str())
                if len(ref_ions) > 1:
                    print >> log, "Multiple matches for %s:" % ion.id_str()
                    for ref_ion in ref_ions:
                        print >> log, "  %s" % ref_ion
                else:
                    print >> log, "Ion %s matches %s" % (ion.id_str(), ref_ions[0])
            else:
                print >> log, "No match for %s" % ion.id_str()
                missing.append(ion.id_str())
    return matched, missing