def create_complexes(self): c2_symmetric = [] ligands = [] minimize = self.minimize.checkState() == Qt.Checked for i in range(0, self.ligand_table.rowCount() - 1): ligand_name = self.ligand_table.item(i, 0).text() ligands.append(ligand_name) checkbox = self.ligand_table.cellWidget(i, 1).layout().itemAt(0).widget() c2 = checkbox.checkState() == Qt.Checked c2_symmetric.append(c2) rescols, formula = ResidueCollection.get_coordination_complexes( self.element.text(), ligands, self.vsepr.currentText(), c2_symmetric=c2_symmetric, minimize=minimize, session=self.session, ) self.session.logger.info("generic formula is %s" % formula) models = [rescol.get_chimera(self.session) for rescol in rescols] self.session.models.add(models) for model in models: apply_seqcrow_preset(model, fallback="Ball-Stick-Endcap")
def open_substituents(self): for row in self.sub_table.table.selectionModel().selectedRows(): if self.sub_table.table.isRowHidden(row.row()): continue sub_name = row.data() substituent = Substituent(sub_name, name=sub_name) chimera_substituent = ResidueCollection(substituent).get_chimera( self.session) self.session.models.add([chimera_substituent]) apply_seqcrow_preset(chimera_substituent, fallback="Ball-Stick-Endcap") if self.showSubGhostBool: color = self.sub_color.get_color() color = [c / 255. for c in color] self.settings.ghost_connection_color = tuple(color) bild_obj = ghost_connection_highlight(substituent, color, self.session) self.session.models.add(bild_obj, parent=chimera_substituent)
def new_atom(self): element = ChangeElementMouseMode.element adjust_bonds = True vsepr = ChangeElementMouseMode.vsepr if vsepr == "do not change": vsepr = False elif vsepr == "linear (1 bond)": vsepr = "linear 1" elif vsepr == "linear (2 bonds)": vsepr = "linear 2" elif vsepr == "trigonal planar (2 bonds)": vsepr = "bent 2 planar" elif vsepr == "tetrahedral (2 bonds)": vsepr = "bent 2 tetrahedral" elif vsepr == "tetrahedral (3 bonds)": vsepr = "bent 3 tetrahedral" if vsepr: atoms = Atom.get_shape(vsepr) atoms[0].element = element for atom in atoms[1:]: atom.element = "H" if adjust_bonds: # this works b/c all atoms are 1 angstrom from the center # just multiply by the distance we want expected_dist = RADII[element] + RADII["H"] for atom in atoms[1:]: atom.coords *= expected_dist for atom in atoms[1:]: atoms[0].connected.add(atom) atom.connected.add(atoms[0]) else: atoms = [Atom(element=element, coords=np.zeros(3))] rescol = ResidueCollection(atoms, name="new", refresh_connected=False) rescol.coord_shift(self._coords) model = self.model_selector.currentData() if model is None: chix = rescol.get_chimera(self.session) self.session.models.add([chix]) apply_seqcrow_preset(chix, fallback="Ball-Stick-Endcap") else: res = model.new_residue("new", "a", len(model.residues) + 1) rescol.residues[0].update_chix(res) run( self.session, "select add %s" % " ".join([atom.atomspec for atom in res.atoms])) self.delete()
def do_new_lig(self): ligands = self.ligname.text() for lig in ligands.split(","): lig = lig.strip() rescol = ResidueCollection(Component(lig)) model = self.lig_model_selector.currentData() if model is None: chix = rescol.get_chimera(self.session) self.session.models.add([chix]) apply_seqcrow_preset(chix, fallback="Ball-Stick-Endcap") self.lig_model_selector.setCurrentIndex(self.lig_model_selector.count()-1) else: res = model.new_residue("new", "a", len(model.residues)+1) rescol.residues[0].update_chix(res) run(self.session, "select add %s" % " ".join([atom.atomspec for atom in res.atoms]))
def open_ligands(self): for row in self.lig_table.table.selectionModel().selectedRows(): if self.lig_table.table.isRowHidden(row.row()): continue lig_name = row.data() ligand = Component(lig_name) chimera_ligand = ResidueCollection( ligand, name=lig_name).get_chimera(self.session) self.session.models.add([chimera_ligand]) apply_seqcrow_preset(chimera_ligand, fallback="Ball-Stick-Endcap") if self.showLigKeyBool: color = self.lig_color.get_color() color = [c / 255. for c in color] self.settings.key_atom_color = tuple(color) bild_obj = key_atom_highlight(ligand, color, self.session) self.session.models.add(bild_obj, parent=chimera_ligand)
def open_rings(self): for row in self.ring_table.table.selectionModel().selectedRows(): if self.ring_table.table.isRowHidden(row.row()): continue ring_name = row.data() ring = Ring(ring_name, name=ring_name) chimera_ring = ResidueCollection(ring.copy()).get_chimera( self.session) self.session.models.add([chimera_ring]) apply_seqcrow_preset(chimera_ring, fallback="Ball-Stick-Endcap") if self.showRingWalkBool: color = self.ring_color.get_color() color = [c / 255. for c in color] self.ring_walk_color = tuple(color) bild_obj = show_walk_highlight(ring, chimera_ring, color, self.session) self.session.models.add(bild_obj, parent=chimera_ring)
def handle_scheme(self, url): query = urllib.parse.parse_qs(url.query()) # tool has URL's to acknowledge how we get the structure # clicking those opens these links if "link" in query: link = query["link"][0] if link == "AmberTools": run(self.session, "open \"https://ambermd.org/AmberTools.php\"") elif link == "NCI/CADD": run(self.session, "open \"https://cactus.nci.nih.gov/\"") return # this is the 2D mol file that we will convert to a 3D structure # as some point in the HTML file, spaces are turned into sPaCe so they don't get nuked molfile = query["molfile"][0].replace("sPaCe", " ").replace("\\n", "\n") # copy-paste from AaronTools.from_string # instead of smiles, we have a file url = "https://cactus.nci.nih.gov/cgi-bin/translate.tcl?smiles=&format=sdf&astyle=kekule&dim=3D&file=%s" % urllib.parse.quote_plus( molfile) s_sd_get = urlopen(url, context=ssl.SSLContext()) msg, status = s_sd_get.msg, s_sd_get.status if msg != "OK": self.session.logger.error( "Issue contacting %s for MOL lookup (status: %s)", CACTUS_HOST, status, ) raise IOError s_sd_get = s_sd_get.read().decode("utf8") try: tmp_url = re.search( 'User-defined exchange format file: <a href="(.*)"', s_sd_get, ).group(1) except AttributeError as err: if re.search("You entered an invalid MOL file", s_sd_get): self.session.logger.error( "Invalid format encountered: %s (consult %s for syntax help)", molfile, "https://cactus.nci.nih.gov/translate/smiles.html", ) raise IOError(err) new_url = "{}{}".format(CACTUS_HOST, tmp_url) s_sd = (urlopen(new_url, context=ssl.SSLContext()).read().decode("utf8")) name = query["name"][0] fr = FileReader((name, "sd", s_sd)) rescol = ResidueCollection(fr) # if not optimization was requested, open the new molecule if query["method"][0] == "no": struc = rescol.get_chimera(self.session, filereader=fr) self.session.models.add([struc]) apply_seqcrow_preset( struc, fallback="Ball-Stick-Endcap", ) return # if optimization was requested, run the SQM job with auto_open=True theory = Theory( method=query["method"][0], charge=fr.other["charge"], job_type=OptimizationJob(), ) job = SQMJob( name, self.session, theory, rescol, auto_open=True, ) self.session.logger.info( "structure will appear when optimization completes") self.session.logger.status( "structure will appear when optimization completes") self.session.seqcrow_job_manager.add_job(job)
def update_chix(self, chix_residue, refresh_connected=True): """changes chimerax residue to match self""" elements = {} known_atoms = [] new_atoms = [] #print("updating residue", self.name, chix_residue.name) chix_residue.name = self.name #print("updating residue:") #print(self.write(outfile=False)) for atom in self.atoms: #print(atom, hasattr(atom, "chix_atom")) if not hasattr(atom, "chix_atom") or \ atom.chix_atom is None or \ atom.chix_atom.deleted or atom.chix_atom not in chix_residue.atoms: #if not hasattr(atom, "chix_atom"): # print("no chix atom", atom) #elif atom.chix_atom is None: # print("no chix atom yet", atom) #elif atom.chix_atom.deleted: # print("chix_atom deleted", atom) #else: # print("atoms do not match", atom.chix_atom) #print("new chix atom for", atom) if hasattr(atom, "chix_name"): atom_name = atom.chix_name # print("atom has chix name:", atom_name) else: atom_name = atom.name # print("atom does not have chix name:", atom_name) if "." in atom_name or len(atom_name) > 4: # print("previous atom name was illegal, using", atom.element) atom_name = atom.element new_atom = chix_residue.structure.new_atom( atom_name, atom.element) new_atom.coord = atom.coords chix_residue.add_atom(new_atom) atom.chix_atom = new_atom known_atoms.append(new_atom) new_atoms.append(new_atom) else: if atom.chix_atom.element.name != atom.element: atom.chix_atom.element = Element.get_element(atom.element) new_atoms.append(atom.chix_atom) atom.chix_atom.coord = atom.coords known_atoms.append(atom.chix_atom) for atom in chix_residue.atoms: if atom not in known_atoms: #print("deleting %s" % atom.atomspec) atom.delete() for atom in new_atoms: # print("starting name:", atom.name) if ([a.name for a in known_atoms].count(atom.name) == 1 and atom.name.startswith(atom.element.name) and atom.name != atom.element.name and "." not in atom.name): # print("skipping", atom.name, atom.serial_number, atom.atomspec) continue if not atom.name.startswith(atom.element.name): atom.name = atom.element.name atom_name = "%s1" % atom.name k = 1 while k == 1 or any( [chix_atom.name == atom_name for chix_atom in known_atoms]): atom_name = "%s%i" % (atom.name, k) k += 1 if len(atom_name) > 4: if atom.name == atom.element.name: # print("breaking:", k, atom.name) break atom.name = atom.element.name k = 1 # print("name:", atom_name) if len(atom_name) <= 4: atom.name = atom_name else: atom.name = atom.element.name # print("final name:", atom.name) if refresh_connected: self.refresh_chix_connected(chix_residue) for atom in chix_residue.atoms: if atom.serial_number == -1: atom.serial_number = atom.structure.atoms.index(atom) + 1 apply_seqcrow_preset(chix_residue.structure, atoms=new_atoms)