def library_construct_element_desc(symbol): """Constructs the ElementDesc object for the given element symbol. """ cif_data = ELEMENT_CIF_FILE.get_data(symbol) if cif_data is None: ConsoleOutput.warning("element description not found for %s" % (symbol)) return None ## create element description element_desc = ElementDesc() element_desc.cif_data = cif_data element = cif_data.get_table("element") element_desc.name = element["name"] element_desc.symbol = element["symbol"] element_desc.number = int(element["number"]) element_desc.atomic_weight = float(element["atomic_weight"]) element_desc.vdw_radius = float(element["van_der_walls_radius"]) element_desc.covalent_radius = float(element.get("covalent_radius", 0.0)) rgb8 = element["color_rgb"] element_desc.color_rgbf = (int(rgb8[1:3], 16) / 255.0, int(rgb8[3:5], 16) / 255.0, int(rgb8[5:7], 16) / 255.0) return element_desc
def load_atom(self, atm_map): """Called repeatedly by the implementation of read_atoms to load all the data for a single atom. The data is contained in the atm_map argument, and is not well documented at this point. Look at this function and you'll figure it out. """ ## create atom object atm = Structure.Atom(**atm_map) ## survey the atom and structure and determine if the atom requires ## being passed to the naming service, absence of required fields if not atm.fragment_id or not atm.chain_id: self.name_service_list.append(atm) return atm try: self.struct.add_atom(atm, True) except Structure.FragmentOverwrite: ConsoleOutput.warning("FragmentOverwrite: %s" % (atm)) self.name_service_list.append(atm) except Structure.AtomOverwrite, err: ConsoleOutput.warning("AtomOverwrite: %s" % (err)) self.name_service_list.append(atm)
def library_open_monomer_lib_zipfile(monomer_name): """Returns the open file object for the mmCIF monomer library file if it is found in the monomer library zipfile. """ if library_use_monomer_zipfile(): ## read data from zip file try: blob = RCSB_ZIP.read(monomer_name.upper()) except KeyError: ConsoleOutput.warning("monomer description not found in zipfile for '%s'" % (monomer_name)) else: from cStringIO import StringIO return StringIO(blob) return None
def library_get_element_desc(symbol): """Loads/caches/returns an instance of the ElementDesc class for the given element symbol. The source of the element data is the mmLib/Data/elements.cif file. """ assert isinstance(symbol, str) try: return ELEMENT_CACHE[symbol] except KeyError: pass element_desc = library_construct_element_desc(symbol) if element_desc is None: ConsoleOutput.warning("element description not found for %s" % (symbol)) return None ELEMENT_CACHE[symbol] = element_desc return element_desc
def load_bonds(self, bond_map): """Call by the implementation of load_metadata to load bond information on the structure. The keys of the bond map are a 2-tuple of the bonded Atom instances, and the value is a dictionary containing information on the type of bond, which may also be a symmetry operator. [bond_map] keys: (atm1, atm2) values: bond_data_map(s) [bond_data_map] bond_type -> text description of bond type: covalent, salt bridge, hydrogen, cispeptide atm1_symop -> symmetry operation (if any) to be applied to atm1 atm2_symop -> same as above, for atom 2 The symmetry operations themselves are a 3x4 array of floating point values composed of the 3x3 rotation matrix and the 3x1 translation. """ ### TODO: Fix this to build bonds in all models! 2010-09-22 for ((atm1, atm2), bd_map) in bond_map.iteritems(): ## check for files which, for some reason, define have a bond ## entry bonding the atom to itself if atm1 == atm2: ConsoleOutput.warning("silly file defines self bonded atom") continue atm1.create_bonds( atom = atm2, bond_type = bd_map.get("bond_type"), atom1_symop = bd_map.get("atm1_symop"), atom2_symop = bd_map.get("atm2_symop"), standard_res_bond = False)
def glr_render_end(self): """Write out the input file for the render program. """ ## open r3d file, write header pobj = None if self.render_stdin is not None: stdin = self.render_stdin else: cmdlist = [ self.render_program_path, "-png", self.render_png_path, "-gamma", "1.5" ] try: pobj = subprocess.Popen(cmdlist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, bufsize=32768) except OSError: ConsoleOutput.warning( "the render program failed to execute from path: %s" % (self.render_program_path)) return stdin = pobj.stdin ## XXX: debug ##r3dfil = open("/tmp/raytrace.r3d","w") ##stdin = TeeWrite(stdin) ## add required hader for the render program self.glr_construct_header() try: stdin.write("\n".join(self.header_list)) stdin.write("\n") self.glr_write_objects(stdin) except IOError, err: ConsoleOutput.warning("IOError while executing %s" % (self.render_program_path)) ConsoleOutput.warning(str(err)) return
def glr_render_end(self): """Write out the input file for the render program. """ ## open r3d file, write header pobj = None if self.render_stdin is not None: stdin = self.render_stdin else: cmdlist = [self.render_program_path, "-png", self.render_png_path, "-gamma", "1.5"] try: pobj = subprocess.Popen( cmdlist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, bufsize=32768, ) except OSError: ConsoleOutput.warning("the render program failed to execute from path: %s" % (self.render_program_path)) return stdin = pobj.stdin ## XXX: debug ##r3dfil = open("/tmp/raytrace.r3d","w") ##stdin = TeeWrite(stdin) ## add required hader for the render program self.glr_construct_header() try: stdin.write("\n".join(self.header_list)) stdin.write("\n") self.glr_write_objects(stdin) except IOError, err: ConsoleOutput.warning("IOError while executing %s" % (self.render_program_path)) ConsoleOutput.warning(str(err)) return
except ImportError: import NumericCompat as numpy from NumericCompat import linalg from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * import ConsoleOutput import Gaussian import AtomMath try: import glaccel except ImportError: ConsoleOutput.warning("cannot load OpenGL acceloration module glaccel") GLACCEL_EXISTS = False else: GLACCEL_EXISTS = True class OpenGLDriver(object): """OpenGL render driver for Viewer.py """ def __init__(self): object.__init__(self) ## some objects have a accelorated C version built in ## src/glaccel.c; if they exist, then use them ## this should really be done by a factory function... if GLACCEL_EXISTS:
def pdb_error(self, rec_name, text): ConsoleOutput.warning("PDB::%s %s" % (rec_name, text))
def library_guess_element_from_name(name0, res_name): """Try everything we can possibly think of to extract the element symbol from the atom name. If available, use the monomer dictionary to help narrow down the search. """ ## strip any space from the name, and return now if there ## is nothing left to work with name = name0.strip() if name == "": return None if name0 != res_name: ## try the easy way out -- look up the atom in the monomer dictionary mdesc = library_get_monomer_desc(res_name) if mdesc is not None: if mdesc.atom_dict.has_key(name): symbol = mdesc.atom_dict[name] if symbol is not None: return symbol if mdesc.is_amino_acid() and name == "OXT": return "O" if mdesc.is_amino_acid(): msg = "invalid amino acid atom name '%s' in residue '%s'" % ( name, res_name) ConsoleOutput.warning(msg) ## okay, that didn't work... ## set the space_flag to true if the name starts with a space, which can ## indicate the name of the atom is only 1 character long. if name0.startswith(" "): space_flag = True else: space_flag = False ## remove all non-alpha chars from the name alpha_name = "" for c in name: if c.isalpha() == True: alpha_name += c ## look up two possible element symbols in the library: ## e1 is the possible one-character symbol ## e2 is the possible two-character symbol if len(alpha_name) == 0: return None e1_symbol = alpha_name[0] e1_valid = ELEMENT_SYMBOL_DICT.has_key(e1_symbol) if len(alpha_name) > 1: e2_symbol = alpha_name[:2] e2_valid = ELEMENT_SYMBOL_DICT.has_key(e2_symbol) else: e2_symbol = None e2_valid = False ## e1 or e2 must return something for us to proceed, otherwise, ## there's just no possible element symbol contained in the atom ## name if e1_valid == False and e2_valid == False: return None elif e1_valid == True and e2_valid == False: return e1_symbol elif e1_valid == False and e2_valid == True: return e2_symbol ## if we get here, then e1 and e2 are both valid elements ## we're out of choices, go by the space_flag: if there is a space ## before the atom name, then use the 1-char element symbol; ## if there is no space, then use the 2-char element symbol if space_flag == True: return e1_symbol return e2_symbol
def library_construct_monomer_desc(res_name): """Constructs the MonomerDesc object for the given residue name. """ ## return None when the res_name is an empty string if len(res_name) < 1: return None if ALT_RES_NAME_DICT.has_key(res_name): lookup_name = ALT_RES_NAME_DICT[res_name] else: lookup_name = res_name.upper() libfil = library_open_monomer_lib_file(lookup_name) if libfil is None: ConsoleOutput.warning("monomer description not found for '%s'" % (res_name)) return None ## generate monomer description mon_desc = MonomerDesc() ## data from RCSB library rcsb_cif_file = mmCIF.mmCIFFile() rcsb_cif_file.load_file(libfil) rcsb_cif_data = rcsb_cif_file[0] libfil.close() chem_comp = rcsb_cif_data.get_table("chem_comp")[0] mon_desc.res_name = chem_comp.get_lower("res_name") mon_desc.full_name = chem_comp.get_lower("name") mon_desc.type = chem_comp.get_lower("type") mon_desc.pdbx_type = chem_comp.get_lower("pdbx_type") mon_desc.formula = chem_comp.get_lower("formula") mon_desc.rcsb_class_1 = chem_comp.get_lower("rcsb_class_1") chem_comp_atom = rcsb_cif_data.get_table("chem_comp_atom") if chem_comp_atom is not None: for cif_row in chem_comp_atom: name = cif_row.getitem_lower("atom_id") try: symbol = cif_row.getitem_lower("type_symbol") except KeyError: ## this should occur when an atom name does not match the ones ## found in a monomer file symbol = name msg = "unrecognized atom name: '%s' in residue '%s'" % ( symbol, res_name) ConsoleOutput.warning(msg) mon_desc.atom_list.append({"name": name, "symbol": symbol}) mon_desc.atom_dict[name] = symbol try: alt_name = cif_row.getitem_lower("alt_atom_id") except KeyError: pass else: mon_desc.alt_atom_dict[name] = alt_name chem_comp_bond = rcsb_cif_data.get_table("chem_comp_bond") if chem_comp_bond is not None: for cif_row in chem_comp_bond: atom1 = cif_row.getitem_lower("atom_id_1") atom2 = cif_row.getitem_lower("atom_id_2") mon_desc.bond_list.append({"atom1": atom1, "atom2": atom2}) ## data from mmLib supplemental library in mmLib/Data/monomers.cif mmlib_cif_data = MMLIB_MONOMERS_CIF.get_data(res_name) if mmlib_cif_data is not None: ## get additional chemical information on amino acids chem_comp = mmlib_cif_data.get_table("chem_comp") if chem_comp is not None: mon_desc.one_letter_code = chem_comp["one_letter_code"] mon_desc.chem_type = chem_comp["chem_type"] ## get torsion angle definitions torsion_angles = mmlib_cif_data.get_table("torsion_angles") if torsion_angles is not None: for cif_row in torsion_angles: mon_desc.torsion_angle_dict[cif_row["name"]] = ( cif_row["atom1"], cif_row["atom2"], cif_row["atom3"], cif_row["atom4"]) ## set some derived flags on the monomer description mon_type = mon_desc.type.upper() if mon_type == "L-PEPTIDE LINKING": mon_desc.amino_acid = True elif mon_type == "DNA LINKING" or mon_type == "RNA LINKING": mon_desc.nucleic_acid = True elif mon_type == "HOH" or mon_type == "WAT": mon_desc.water = True return mon_desc
def name_service(self): """Runs the name service on all atoms needing to be named. This is a complicated function which corrects most commonly found errors and omissions from PDB files. """ if len(self.name_service_list) == 0: return ## returns the next available chain_id in self.struct ## XXX: it's possible to run out of chain IDs! def next_chain_id(suggest_chain_id): if suggest_chain_id != "": chain = self.struct.get_chain(suggest_chain_id) if not chain: return suggest_chain_id ## TODO: Add the following alphanumeric string to Constants.py, 2010-09-21 for chain_id in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789": chain = self.struct.get_chain(chain_id) if not chain: return chain_id raise StructureBuilderError("name_service exhausted new chain_ids") ## NAME SERVICE FOR POLYMER ATOMS ## What if we are given a list of atoms with res_name, frag_id, and ## model_id where the frag_id are sequential? They can be sequential ## several ways using insertion codes, but large breaks often denote ## chain breaks. ## We need to handle the special case of a list of polymer residues ## which do not have chain_ids. This requires a first pass over the ## atom list using different rules than what we use for sorting out ## non-polymers. current_polymer_type = None current_polymer_model_id = None current_polymer_chain_id = None current_polymer_frag_id = None current_polymer_res_name = None current_polymer_name_dict = None polymer_model_dict = {} current_frag = None current_frag_list = None for atm in self.name_service_list[:]: ## determine the polymer type of the atom if Library.library_is_amino_acid(atm.res_name): polymer_type = "protein" elif Library.library_is_nucleic_acid(atm.res_name): polymer_type = "dna" else: ## if the atom is not a polymer, we definitely have a break ## in this chain current_polymer_type = None current_polymer_model_id = None current_polymer_chain_id = None current_polymer_frag_id = None current_polymer_res_name = None current_polymer_name_dict = None current_frag = None current_frag_list = None continue fragment_id = Structure.FragmentID(atm.fragment_id) ## now we deal with conditions which can terminate the current ## polymer chain if polymer_type!=current_polymer_type or \ atm.model_id!=current_polymer_model_id or \ atm.chain_id!=current_polymer_chain_id or \ fragment_id<current_polymer_frag_id: current_polymer_type = polymer_type current_polymer_model_id = atm.model_id current_polymer_chain_id = atm.chain_id current_polymer_frag_id = Structure.FragmentID(atm.fragment_id) current_polymer_res_name = atm.res_name current_polymer_name_dict = {atm.name: True} ## create new fragment current_frag = [atm] current_frag_list = [current_frag] ## create new fragment list (chain) try: model = polymer_model_dict[atm.model_id] except KeyError: model = [current_frag_list] polymer_model_dict[atm.model_id] = model else: model.append(current_frag_list) ## we have now dealt with the atom, so it can be removed from ## the name service list self.name_service_list.remove(atm) continue ## if we get here, then we know this atom is destine for the ## current chain, and the algorithm needs to place the atom ## in the current fragment, or create a new fragment for it ## to go into; the conditions for it going into the current ## fragment are: it has it have the same res_name, and its ## atom name cannot conflict with the names of atoms already in ## in the fragment if atm.res_name != current_polymer_res_name or current_polymer_name_dict.has_key(atm.name): current_polymer_res_name = atm.res_name current_polymer_name_dict = {atm.name: True} ## create new fragment and add it to the current fragment list current_frag = [atm] current_frag_list.append(current_frag) ## we have now dealt with the atom, so it can be removed ## from the name service list self.name_service_list.remove(atm) continue ## okay, put it in the current fragment current_frag.append(atm) self.name_service_list.remove(atm) ## now assign chain_ids and add the atoms to the structure model_ids = polymer_model_dict.keys() model_ids.sort() model_list = [polymer_model_dict[model_id] for model_id in model_ids] num_chains = 0 for frag_list in polymer_model_dict.itervalues(): num_chains = max(num_chains, len(frag_list)) for chain_index in xrange(num_chains): ## get next available chain_id chain_id = next_chain_id("") ## assign the chain_id to all the atoms in the chain ## TODO: check fragment_id too, 2010-09-22 for model in model_list: frag_list = model[chain_index] for frag in frag_list: for atm in frag: atm.chain_id = chain_id self.struct.add_atom(atm, True) ## free the memory used by the polymer naming service del polymer_model_dict del model_list ## NAME SERVICE FOR NON-POLYMER ATOMS ## cr = (chain_id, res_name) ## ## cr_dict[cr_key] = model_dict ## ## model_dict[model] = frag_list ## ## frag_list = [ frag1, frag2, frag3, ...] ## ## frag = [atm1, atm2, atm3, ...] cr_dict = {} cr_key_list = [] frag_id = None frag = None name_dict = {} ## split atoms into fragments for atm in self.name_service_list: atm_id = (atm.name, atm.alt_loc) atm_frag_id = (atm.model_id, atm.chain_id, atm.fragment_id, atm.res_name) ## if the atom fragment id matches the current fragment id ## and doesn't conflict with any other atom name in the fragment ## then add it to the fragment if atm_frag_id==frag_id and not name_dict.has_key(atm_id): frag.append(atm) name_dict[atm_id] = True else: cr_key = (atm.chain_id, atm.res_name) ### debug if frag: msg = "name_service: fragment detected in cr=%s" % ( str(cr_key)) ConsoleOutput.debug(msg) for a in frag: ConsoleOutput.debug(" " + str(a)) ### /debug try: model_dict = cr_dict[cr_key] except KeyError: model_dict = cr_dict[cr_key] = {} cr_key_list.append(cr_key) try: frag_list = model_dict[atm.model_id] except KeyError: frag_list = model_dict[atm.model_id] = [] name_dict = {atm_id: True} frag_id = atm_frag_id frag = [atm] frag_list.append(frag) ## free self.name_service_list and other vars to save some memory del self.name_service_list new_chain_id = None fragment_id_num = None for cr_key in cr_key_list: ### debug msg = "name_service: chain_id / res_name keys\n" msg += " cr_key: chain_id='%s' res_name='%s'" % ( cr_key[0], cr_key[1]) ConsoleOutput.debug(msg) ### /debug ## get the next chain ID, use the cfr group's ## loaded chain_id if possible chain_id = next_chain_id(cr_key[0]) ## if we are not out of chain IDs, use the new chain ID and ## reset the fragment_id if chain_id != None: new_chain_id = chain_id fragment_id_num = 0 elif new_chain_id == None or fragment_id_num == None: ConsoleOutput.fatal("name_service: unable to assign any chain ids") ## get model dictionary model_dict = cr_dict[cr_key] ## inspect the model dictionary to determine the number of ## fragments in each model -- they should be the same ## and have a 1:1 correspondence; if not, match up the ## fragments as much as possible max_frags = -1 for (model, frag_list) in model_dict.iteritems(): frag_list_len = len(frag_list) if max_frags == -1: max_frags = frag_list_len continue if max_frags != frag_list_len: strx = "name_service: model fragments not identical" ConsoleOutput.debug(strx) ConsoleOutput.warning(strx) max_frags = max(max_frags, frag_list_len) ## now iterate through the fragment lists in parallel and assign ## the new chain_id and fragment_id for i in xrange(max_frags): fragment_id_num += 1 for frag_list in model_dict.itervalues(): try: frag = frag_list[i] except IndexError: continue ## assign new chain_id and fragment_id, than place the ## atom in the structure for atm in frag: atm.chain_id = new_chain_id atm.fragment_id = str(fragment_id_num) self.struct.add_atom(atm, True) ## logging ConsoleOutput.warning("name_service(): added chain_id=%s, res_name=%s, num_residues=%d" % ( new_chain_id, cr_key[1], fragment_id_num))
def read_atoms(self): try: atom_site_table = self.cif_data["atom_site"] except KeyError: ConsoleOutput.warning("read_atoms: atom_site table not found") return try: aniso_table = self.cif_data["atom_site_anisotrop"] except KeyError: aniso_table = None else: aniso_dict = aniso_table.row_index_dict("id") for atom_site in atom_site_table: try: atom_site_id = atom_site["id"] except KeyError: ConsoleOutput.warning("unable to find id for atom_site row") continue atm_map = {} setmaps_cif(atom_site, self.atom_id, atm_map, "name") setmaps_cif(atom_site, self.alt_id, atm_map, "alt_loc") setmaps_cif(atom_site, self.comp_id, atm_map, "res_name") setmaps_cif(atom_site, self.seq_id, atm_map, "fragment_id") setmaps_cif(atom_site, self.asym_id, atm_map, "chain_id") setmaps_cif(atom_site, "label_entity_id", atm_map, "label_entity_id") setmaps_cif(atom_site, "label_asym_id", atm_map, "label_asym_id") setmaps_cif(atom_site, "label_seq_id", atm_map, "label_seq_id") setmaps_cif(atom_site, "type_symbol", atm_map, "element") setmapf_cif(atom_site, "cartn_x", atm_map, "x") setmapf_cif(atom_site, "cartn_y", atm_map, "y") setmapf_cif(atom_site, "cartn_z", atm_map, "z") setmapf_cif(atom_site, "occupancy", atm_map, "occupancy") setmapf_cif(atom_site, "b_iso_or_equiv", atm_map, "temp_factor") setmapf_cif(atom_site, "cartn_x_esd", atm_map, "sig_x") setmapf_cif(atom_site, "cartn_y_esd", atm_map, "sig_y") setmapf_cif(atom_site, "cartn_z_esd", atm_map, "sig_z") setmapf_cif(atom_site, "occupancy_esd", atm_map, "sig_occupancy") setmapf_cif(atom_site, "b_iso_or_equiv_esd", atm_map, "sig_temp_factor") setmapi_cif(atom_site, "pdbx_pdb_model_num", atm_map, "model_id") if aniso_table is not None: try: aniso = aniso_dict[atom_site_id] except KeyError: ConsoleOutput.warning("unable to find aniso row for atom") else: setmapf_cif(aniso, "u[1][1]", atm_map, "u11") setmapf_cif(aniso, "u[2][2]", atm_map, "u22") setmapf_cif(aniso, "u[3][3]", atm_map, "u33") setmapf_cif(aniso, "u[1][2]", atm_map, "u12") setmapf_cif(aniso, "u[1][3]", atm_map, "u13") setmapf_cif(aniso, "u[2][3]", atm_map, "u23") setmapf_cif(aniso, "u[1][1]_esd", atm_map, "sig_u12") setmapf_cif(aniso, "u[2][2]_esd", atm_map, "sig_u22") setmapf_cif(aniso, "u[3][3]_esd", atm_map, "sig_u33") setmapf_cif(aniso, "u[1][2]_esd", atm_map, "sig_u12") setmapf_cif(aniso, "u[1][3]_esd", atm_map, "sig_u13") setmapf_cif(aniso, "u[2][3]_esd", atm_map, "sig_u23") atm = self.load_atom(atm_map) self.atom_site_id_map[atom_site_id] = atm
def read_struct_conn(self): """Read bond information form the struct_conn and struct_conn_type sections. """ ## only read these types of bonds for now bond_type_list = [ "covale", # covalent bond "metalc", # metal coordination "disulf", # disulfide bridge "saltbr", # ionic interaction "covale_base", # covalent modification of a nucleotide base "covale_sugar", # covalent modification of a nucleotide sugar "covale_phosphate", # covalent modification of a nucleotide phosphate ] try: atom_site = self.cif_data["atom_site"] except KeyError: ConsoleOutput.warning("read_struct_conn: atom_site table not found") return try: struct_conn_table = self.cif_data["struct_conn"] except KeyError: ConsoleOutput.warning("read_struct_conn: struct_conn table not found") return bond_map = {} for row in struct_conn_table: conn_type = row.get("conn_type_id") if conn_type not in bond_type_list: continue # Always use label_ values since they are mandatory asym_id1 = row.get("ptnr1_label_asym_id") seq_id1 = row.get("ptnr1_label_seq_id") comp_id1 = row.get("ptnr1_label_comp_id") atom_id1 = row.get("ptnr1_label_atom_id") auth_asym_id1 = row.get("ptnr1_auth_asym_id") auth_seq_id1 = row.get("ptnr1_auth_seq_id") auth_comp_id1 = row.get("ptnr1_auth_comp_id") symm1 = row.get("ptnr1_symmetry") asym_id2 = row.get("ptnr2_label_asym_id") seq_id2 = row.get("ptnr2_label_seq_id") comp_id2 = row.get("ptnr2_label_comp_id") atom_id2 = row.get("ptnr2_label_atom_id") auth_asym_id2 = row.get("ptnr2_auth_asym_id") auth_seq_id2 = row.get("ptnr2_auth_seq_id") auth_comp_id2 = row.get("ptnr2_auth_comp_id") symm2 = row.get("ptnr2_symmetry") ## check for these special mmCIF tokens if conn_type == "disulf": atom_id1 = atom_id2 = "SG" as1 = atom_site.get_row( ("label_asym_id", asym_id1), ("label_seq_id", seq_id1), ("label_comp_id", comp_id1), ("auth_asym_id", auth_asym_id1), ("auth_seq_id", auth_seq_id1), ("auth_comp_id", auth_comp_id1), ("label_atom_id", atom_id1)) as2 = atom_site.get_row( ("label_asym_id", asym_id2), ("label_seq_id", seq_id2), ("label_comp_id", comp_id2), ("auth_asym_id", auth_asym_id2), ("auth_seq_id", auth_seq_id2), ("auth_comp_id", auth_comp_id2), ("label_atom_id", atom_id2)) if not as1 or not as2: ConsoleOutput.warning("read_struct_conn: atom not found id: " + \ row.get("id","[No ID]")) ConsoleOutput.warning("atm1: asym=%s seq=%s comp=%s atom=%s symm=%s" % ( asym_id1, seq_id1, comp_id1, atom_id1, symm1)) ConsoleOutput.warning("atm2: asym=%s seq=%s comp=%s atom=%s symm=%s" % ( asym_id2, seq_id2, comp_id2, atom_id2, symm2)) continue try: atm1 = self.atom_site_id_map[as1["id"]] atm2 = self.atom_site_id_map[as2["id"]] except KeyError: ConsoleOutput.warning("read_struct_conn: atom_site_id_map incorrect id: " + \ row.get("id", "[No ID]")) ConsoleOutput.warning("atm1: asym=%s seq=%s comp=%s atom=%s symm=%s" % ( asym_id1, seq_id1, comp_id1, atom_id1, symm1)) ConsoleOutput.warning("atm2: asym=%s seq=%s comp=%s atom=%s symm=%s" % ( asym_id2, seq_id2, comp_id2, atom_id2, symm2)) continue if id(atm1) < id(atm2): bnd = (atm1, atm2) else: bnd = (atm2, atm1) try: bond_map[bnd]["bond_type"] = conn_type except KeyError: bond_map[bnd] = {"bond_type": conn_type} if symm1: bond_map[bnd]["symop1"] = symm1 if symm2: bond_map[bnd]["symop2"] = symm2 ## load the bonds self.load_bonds(bond_map)