def run_tm_bond(self, *args): color = self.tm_bond_color.get_color() self.settings.tm_bond_color = tuple([c / 255. for c in color]) radius = self.tm_bond_radius.value() self.settings.tm_bond_radius = radius dashes = self.tm_bond_dashes.value() self.settings.tm_bond_dashes = dashes models = self.session.models.list(type=AtomicStructure) for model in models: rescol = ResidueCollection(model, bonds_matter=False) try: tm_list = rescol.find([ AnyTransitionMetal(), "Na", "K", "Rb", "Cs", "Fr", "Mg", "Ca", "Sr", "Ba", "Ra" ]) for tm in tm_list: for atom in rescol.atoms: if atom is tm: continue if atom.is_connected(tm): pbg = model.pseudobond_group( model.PBG_METAL_COORDINATION, create_type="normal") pbg.new_pseudobond(tm.chix_atom, atom.chix_atom) pbg.dashes = dashes pbg.color = color pbg.radius = radius except LookupError: pass
def restore_selected(self): items = [item for item in self.tree.selectedItems()] model_dict = self.session.filereader_manager.filereader_dict models = list(model_dict.keys()) for item in items: parent = item.parent() mdl = models[self.tree.indexOfTopLevelItem(parent)] if parent is None: fr = model_dict[mdl][-1] else: fr = model_dict[mdl][parent.indexOfChild(item)] fr_rescol = ResidueCollection(fr) fr_rescol.update_chix(mdl) if fr.all_geom is not None and len(fr.all_geom) > 1: coordsets = fr_rescol.all_geom_coordsets(fr) mdl.remove_coordsets() mdl.add_coordsets(coordsets) for i, coordset in enumerate(coordsets): mdl.active_coordset_id = i + 1 for atom, coord in zip(mdl.atoms, coordset): atom.coord = coord mdl.active_coordset_id = 1
def test_fuseRing_modify(self): ref = ResidueCollection(self.naphthalene) run(self.session, "open %s" % self.benzene) run(self.session, "fuseRing #1/a:1@H1 #1/a:1@H2 ring benzene") mdl = self.session.models.list()[0] rescol = ResidueCollection(mdl) self.assertTrue(validate(ref, rescol, thresh="loose"))
def test_substitute_modify(self): ref = ResidueCollection(self.chlorobiphenyl) run(self.session, "open %s" % self.benzene) run(self.session, "substitute #1/a:1@H5 substituent Cl minimize false") run(self.session, "substitute #1/a:1@H6 substituent Ph minimize false") mdl = self.session.models.list()[0] rescol = ResidueCollection(mdl) self.assertTrue(validate(ref, rescol))
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 test_fuseRing_copy(self): ref1 = ResidueCollection(self.naphthalene) ref2 = ResidueCollection(self.tetrahydronaphthalene) run(self.session, "open %s" % self.benzene) run(self.session, "fuseRing #1/a:1@H1 #1/a:1@H2 ring benzene modify false") run(self.session, "fuseRing #1/a:1@H1 #1/a:1@H2 ring cyclohexane modify false") mdl1 = self.session.models.list()[1] rescol1 = ResidueCollection(mdl1) mdl2 = self.session.models.list()[2] rescol2 = ResidueCollection(mdl2) self.assertTrue(validate(ref1, rescol1, thresh="loose")) self.assertTrue(validate(ref2, rescol2, thresh="loose"))
def test_substitute_copy(self): ref1 = ResidueCollection(self.chlorobenzene) ref2 = ResidueCollection(self.chlorobiphenyl) run(self.session, "open %s" % self.benzene) run(self.session, "substitute #1/a:1@H5 substituent Cl minimize false modify false") run(self.session, "substitute #2/a:1@H6 substituent Ph minimize false modify false") mdl1 = self.session.models.list()[1] rescol1 = ResidueCollection(mdl1) mdl2 = self.session.models.list()[2] rescol2 = ResidueCollection(mdl2) self.assertTrue(validate(ref1, rescol1)) self.assertTrue(validate(ref2, rescol2))
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 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 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 rmsdAlign(session, models, reference, align=True, sort=False, heavyOnly=False): ref = ResidueCollection(reference) order1 = None for model in models: if not isinstance(model, AtomicStructure): continue rescol = ResidueCollection(model) if align: rmsd = rescol.RMSD(ref, sort=sort, align=True, heavy_only=heavyOnly) session.logger.info("rmsd between %s and %s: %.4f" % (ref.atomspec, model.atomspec, rmsd)) for atom in rescol.atoms: #update coordinates (without rescol.update_chix - that's slower b/c it checks bonds) atom.chix_atom.coord = atom.coords else: #get ordering of atoms #XXX: RMSD returns early (without giving ordered atoms) if align=False (which is the default) if order1 is None: if sort: order1, _ = ref.reorder() else: order1 = ref.atoms if sort: order2, _ = rescol.reorder() else: order2 = rescol.atoms #recompute rmsd using untranslated coordinates (from original AtomicStructures) rmsd = 0 atoms = 0 for a1, a2 in zip(order1, order2): atom1 = a1.chix_atom atom2 = a2.chix_atom v = atom1.coord - atom2.coord if heavyOnly and (atom1.element.name == "H" or atom2.element.name == "H"): continue rmsd += np.dot(v, v) atoms += 1 rmsd = np.sqrt(rmsd / atoms) session.logger.info("rmsd between %s and %s: %.4f" % (ref.atomspec, model.atomspec, rmsd))
def libadd_ring(self): """add ring to library or open it in a new model""" selection = self.session.seqcrow_ordered_selection_manager.selection if not selection.single_structure: raise RuntimeError("selected atoms must be on the same model") rescol = ResidueCollection(selection[0].structure) walk_atoms = rescol.find( [AtomSpec(atom.atomspec) for atom in selection]) if len(walk_atoms) < 1: raise RuntimeError("no walk direction could be determined") ring_name = self.ring_name.text() ring = Ring(rescol, name=ring_name, end=walk_atoms) ring.comment = "E:%s" % ",".join( [str(rescol.atoms.index(atom) + 1) for atom in walk_atoms]) if len(ring_name) == 0: chimerax_ring = ResidueCollection(ring).get_chimera(self.session) chimerax_ring.name = "ring preview" self.session.models.add([chimerax_ring]) bild_obj = show_walk_highlight(ring, chimerax_ring, [0.9, 0.4, 0.3, 0.9], self.session) self.session.models.add(bild_obj, parent=chimerax_ring) else: check_aaronlib_dir() filename = os.path.join(AARONLIB, "Rings", ring_name + ".xyz") if os.path.exists(filename): exists_warning = QMessageBox() exists_warning.setIcon(QMessageBox.Warning) exists_warning.setText( "%s already exists.\nWould you like to overwrite?" % filename) exists_warning.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rv = exists_warning.exec_() if rv == QMessageBox.Yes: ring.write(outfile=filename) self.tool_window.status("%s added to ring library" % ring_name) else: self.tool_window.status( "%s has not been added to ring library" % ring_name) else: ring.write(outfile=filename) self.tool_window.status("%s added to ring library" % ring_name)
def save_aarontools(session, path, format_name, **kwargs): """ save XYZ file using AaronTools kwargs may be: comment - str """ from SEQCROW.residue_collection import ResidueCollection from AaronTools.geometry import Geometry from chimerax.atomic import AtomicStructure accepted_kwargs = ['comment', 'models'] unknown_kwargs = [kw for kw in kwargs if kw not in accepted_kwargs] if len(unknown_kwargs) > 0: raise RuntimeWarning("unrecognized keyword%s %s?" % ("s" if len(unknown_kwargs) > 1 else "", ", ".join(unknown_kwargs))) if 'models' in kwargs: models = kwargs['models'] else: models = None if models is None: models = session.models.list(type=AtomicStructure) models = [m for m in models if isinstance(m, AtomicStructure)] if len(models) < 1: raise RuntimeError('nothing to save') res_cols = [ResidueCollection(model) for model in models] atoms = [] for res in res_cols: atoms.extend(res.atoms) geom = Geometry(atoms) if 'comment' in kwargs: geom.comment = kwargs[comment] geom.write(outfile=path)
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 libadd_ligand(self): """add ligand to library or open it in a new model""" selection = selected_atoms(self.session) if not selection.single_structure: raise RuntimeError("selected atoms must be on the same model") rescol = ResidueCollection(selection[0].structure) ligand_atoms = [ atom for atom in rescol.atoms if atom.chix_atom in selection ] key_chix_atoms = [ atom for atom in self.key_atomspec if not atom.deleted ] if len(key_chix_atoms) < 1: key_atoms = set([]) for atom in ligand_atoms: for atom2 in atom.connected: if atom2 not in ligand_atoms: key_atoms.add(atom) else: key_atoms = rescol.find( [AtomSpec(atom.atomspec) for atom in key_chix_atoms]) if len(key_atoms) < 1: raise RuntimeError("no key atoms could be determined") lig_name = self.ligand_name.text() ligand = Component(ligand_atoms, name=lig_name, key_atoms=key_atoms) ligand.comment = "K:%s" % ",".join( [str(ligand.atoms.index(atom) + 1) for atom in key_atoms]) if len(lig_name) == 0: chimerax_ligand = ResidueCollection(ligand).get_chimera( self.session) chimerax_ligand.name = "ligand preview" self.session.models.add([chimerax_ligand]) bild_obj = key_atom_highlight(ligand, [0.2, 0.5, 0.8, 0.5], self.session) self.session.models.add(bild_obj, parent=chimerax_ligand) else: check_aaronlib_dir() filename = os.path.join(AARONLIB, "Ligands", lig_name + ".xyz") if os.path.exists(filename): exists_warning = QMessageBox() exists_warning.setIcon(QMessageBox.Warning) exists_warning.setText( "%s already exists.\nWould you like to overwrite?" % filename) exists_warning.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rv = exists_warning.exec_() if rv == QMessageBox.Yes: ligand.write(outfile=filename) self.tool_window.status("%s added to ligand library" % lig_name) else: self.tool_window.status( "%s has not been added to ligand library" % lig_name) else: ligand.write(outfile=filename) self.tool_window.status("%s added to ligand library" % lig_name)
def mouse_up(self, event): if event.shift_down(): _ElementPicker(self.session, "pick element") return if not self.element: self.session.logger.warning( "no element selected; shift-click to set element") self.session.logger.status( "no element selected; shift-click to set element") _ElementPicker(self.session, "pick element") return x, y = event.position() pick = self.view.picked_object(x, y) if not pick: x1, x2 = self.session.main_view.clip_plane_points(x, y) coords = (x1 + x2) / 2 new_fragment = _ModelSelector(self.session, "place atom in model", coords) if new_fragment.model_selector.count() == 1: new_fragment.new_atom() return # import cProfile # # profile = cProfile.Profile() # profile.enable() vsepr = self.vsepr if vsepr == "do not change": vsepr = False elif vsepr == "linear (1 bond)": vsepr = "linear 1" goal = 1 elif vsepr == "linear (2 bonds)": vsepr = "linear 2" goal = 2 elif vsepr == "trigonal planar (2 bonds)": vsepr = "bent 2 planar" goal = 2 elif vsepr == "tetrahedral (2 bonds)": vsepr = "bent 2 tetrahedral" goal = 2 elif vsepr == "trigonal planar": goal = 3 elif vsepr == "tetrahedral (3 bonds)": vsepr = "bent 3 tetrahedral" goal = 3 elif vsepr == "tetrahedral": goal = 4 else: goal = len(Atom.get_shape(vsepr)) - 1 if not isinstance(pick, PickedAtom): return atom = pick.atom # # use built-in ChimeraX command for some of the more common things # # because it's faster for proteins # if False: # run( # self.session, # "build modify %s %s %i geometry %s" % ( # atom.atomspec, # self.element, # goal, # vsepr, # ) # ) # frags = [] for neighbor in atom.neighbors: frags.append( get_fragment(neighbor, stop=atom, max_len=atom.structure.num_atoms)) residues = [atom.residue] hold_steady = None for i, frag in enumerate(sorted(frags, key=len)): if i == len(frags) - 1: hold_steady = AtomSpec(frag[0].atomspec) residues.append(frag[0].residue) continue residues.extend(frag.residues) rescol = ResidueCollection(atom.structure, convert_residues=set(residues), refresh_ranks=False) res = [ residue for residue in rescol.residues if residue.chix_residue is atom.residue ][0] target = res.find_exact(AtomSpec(atom.atomspec))[0] adjust_hydrogens = vsepr if vsepr is not False: cur_bonds = len(target.connected) change_Hs = goal - cur_bonds adjust_hydrogens = (change_Hs, vsepr) rescol.change_element( target, self.element, adjust_bonds=True, adjust_hydrogens=adjust_hydrogens, hold_steady=hold_steady, ) res.update_chix(res.chix_residue, apply_preset=True, refresh_connected=True) rescol.update_chix(atom.structure, apply_preset=False, refresh_connected=False)
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 libadd_substituent(self): """add ligand to library or open it in a new model""" selection = selected_atoms(self.session) if not selection.single_structure: raise RuntimeError("selected atoms must be on the same model") residues = [] for atom in selection: if atom.residue not in residues: residues.append(atom.residue) rescol = ResidueCollection(selection[0].structure, convert_residues=residues) substituent_atoms = [ atom for atom in rescol.atoms if atom.chix_atom in selection ] start = None avoid = None for atom in substituent_atoms: for atom2 in atom.connected: if atom2 not in substituent_atoms: if start is None: start = atom avoid = atom2 else: raise RuntimeError( "substituent must only have one connection to the molecule" ) if start is None: raise RuntimeError( "substituent is not connected to a larger molecule") substituent_atoms.remove(start) substituent_atoms.insert(0, start) sub_name = self.sub_name.text() confs = self.sub_confs.value() angle = self.sub_angle.value() comment = "CF:%i,%i" % (confs, angle) if len(sub_name) == 0: sub = Substituent(substituent_atoms, name="test", conf_num=confs, conf_angle=angle) else: sub = Substituent(substituent_atoms, name=sub_name, conf_num=confs, conf_angle=angle) sub.comment = comment #align substituent bond to x axis sub.coord_shift(-avoid.coords) x_axis = np.array([1., 0., 0.]) n = np.linalg.norm(start.coords) vb = start.coords / n d = np.linalg.norm(vb - x_axis) theta = np.arccos((d**2 - 2) / -2) vx = np.cross(vb, x_axis) sub.rotate(vx, theta) add = False if len(sub_name) == 0: chimerax_sub = ResidueCollection(sub).get_chimera(self.session) chimerax_sub.name = "substituent preview" self.session.models.add([chimerax_sub]) bild_obj = ghost_connection_highlight( sub, [0.60784, 0.145098, 0.70196, 0.5], self.session) self.session.models.add(bild_obj, parent=chimerax_sub) else: check_aaronlib_dir() filename = os.path.join(AARONLIB, "Subs", sub_name + ".xyz") if os.path.exists(filename): exists_warning = QMessageBox() exists_warning.setIcon(QMessageBox.Warning) exists_warning.setText( "%s already exists.\nWould you like to overwrite?" % filename) exists_warning.setStandardButtons(QMessageBox.Yes | QMessageBox.No) rv = exists_warning.exec_() if rv == QMessageBox.Yes: add = True else: self.tool_window.status( "%s has not been added to substituent library" % sub_name) else: add = True if add: sub.write(outfile=filename) self.tool_window.status("%s added to substituent library" % sub_name) register_selectors(self.session.logger, sub_name) if self.session.ui.is_gui: if (sub_name not in ELEMENTS and sub_name[0].isalpha() and (len(sub_name) > 1 and not any(not (c.isalnum() or c in "+-") for c in sub_name[1:]))): add_submenu = self.session.ui.main_window.add_select_submenu add_selector = self.session.ui.main_window.add_menu_selector substituent_menu = add_submenu(['Che&mistry'], 'Substituents') add_selector(substituent_menu, sub_name, sub_name)
def pointGroup( session, selection, printElements=False, displayElements=True, tolerance=0.1, axisTolerance=0.5, maxRotation=6, ): for model in selection: rescol = ResidueCollection(model, refresh_ranks=False) pg = PointGroup( rescol, tolerance=tolerance, rotation_tolerance=np.deg2rad(axisTolerance), max_rotation=maxRotation, ) session.logger.info("%s: %s" % (model.name, pg.name)) if printElements: for ele in sorted(pg.elements, reverse=True): session.logger.info(repr(ele)) if displayElements: for ele in sorted(pg.elements, reverse=True): if isinstance(ele, InversionCenter): inv = ".note %s\n" % repr(ele) inv += ".sphere %.5f %.5f %.5f 0.1\n" % tuple( pg.center) stream = BytesIO(bytes(inv, "utf-8")) bild_obj, status = read_bild(session, stream, repr(ele)) session.models.add(bild_obj, parent=model) elif isinstance(ele, ProperRotation): prots = ".note %s\n" % repr(ele) prots += ".color red\n" prots += ".arrow %.5f %.5f %.5f " % tuple(pg.center) end = pg.center + ele.n * np.sqrt(ele.exp) * ele.axis prots += "%.5f %.5f %.5f 0.05\n" % tuple(end) stream = BytesIO(bytes(prots, "utf-8")) bild_obj, status = read_bild(session, stream, repr(ele)) session.models.add(bild_obj, parent=model) elif isinstance(ele, ImproperRotation): irots = ".note %s\n" % repr(ele) irots += ".color blue\n" irots += ".arrow %.5f %.5f %.5f " % tuple(pg.center) end = pg.center + np.sqrt(ele.n) * np.sqrt( ele.exp) * ele.axis irots += "%.5f %.5f %.5f 0.05\n" % tuple(end) irots += ".transparency 25\n" z = ele.axis x = perp_vector(z) y = np.cross(x, z) for angle in np.linspace(0, 2 * np.pi, num=250): pt2 = ele.n**0.9 * x * np.cos(angle) pt2 += ele.n**0.9 * y * np.sin(angle) pt2 += pg.center if angle > 0: irots += ".polygon %6.3f %6.3f %6.3f" % tuple( pt1) irots += " %6.3f %6.3f %6.3f" % tuple( pg.center) irots += " %6.3f %6.3f %6.3f" % tuple(pt2) irots += "\n" pt1 = pt2 stream = BytesIO(bytes(irots, "utf-8")) bild_obj, status = read_bild(session, stream, repr(ele)) session.models.add(bild_obj, parent=model) elif isinstance(ele, MirrorPlane): mirror = ".note %s\n" % repr(ele) mirror += ".color purple\n" mirror += ".transparency 25\n" z = ele.axis x = perp_vector(z) y = np.cross(x, z) for angle in np.linspace(0, 2 * np.pi, num=250): pt2 = 5 * x * np.cos(angle) pt2 += 5 * y * np.sin(angle) pt2 += pg.center if angle > 0: mirror += ".polygon %6.3f %6.3f %6.3f" % tuple( pt1) mirror += " %6.3f %6.3f %6.3f" % tuple( pg.center) mirror += " %6.3f %6.3f %6.3f" % tuple(pt2) mirror += "\n" pt1 = pt2 stream = BytesIO(bytes(mirror, "utf-8")) bild_obj, status = read_bild(session, stream, repr(ele)) session.models.add(bild_obj, parent=model)
def percent_vbur( session, selection, radii="UMN", radius=3.5, scale=1.17, method="Lebedev", radialPoints=20, angularPoints=1454, minimumIterations=25, onlyAtoms=None, center=None, useCentroid=True, displaySphere=None, pointSpacing=0.075, intersectionScale=2, palette="rainbow", return_values=False, steric_map=False, use_scene=False, num_pts=100, shape="circle", ): out = [] models = { model: [ atom for atom in model.atoms if onlyAtoms is not None and atom in onlyAtoms ] for model in selection if isinstance(model, AtomicStructure) } s = "<pre>model\tcenter\t%Vbur\n" for model in models: if len(models[model]) == 0: targets = None else: targets = [AtomSpec(atom.atomspec) for atom in models[model]] if center is not None: if isinstance(center, tuple): mdl_center = np.array(center) else: mdl_center = [ AtomSpec(atom.atomspec) for atom in model.atoms if atom in center ] else: mdl_center = [] rescol = ResidueCollection(model) if use_scene: oop_vector = session.view.camera.get_position().axes()[2] ip_vector = session.view.camera.get_position().axes()[1] else: oop_vector = None ip_vector = None if len(mdl_center) == 0: rescol.detect_components() mdl_center = rescol.center elif not isinstance(center, np.ndarray): mdl_center = rescol.find([AtomSpec(c.atomspec) for c in center]) if not useCentroid and not isinstance(center, np.ndarray): for c in mdl_center: if steric_map: if targets is not None: key_atoms = [] targets = rescol.find(targets) for atom in targets: if c in atom.connected or atom in c.connected: key_atoms.append(atom) else: key_atoms = None x, y, z, min_alt, max_alt, basis, targets = rescol.steric_map( center=c, key_atoms=key_atoms, radii=radii, oop_vector=oop_vector, ip_vector=ip_vector, radius=radius, return_basis=True, num_pts=num_pts, shape=shape, ) vbur = rescol.percent_buried_volume( targets=targets, basis=basis, center=c, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) out.append((model.name, c.atomspec, vbur, (x, y, z, min_alt, max_alt))) else: vbur = rescol.percent_buried_volume( targets=targets, center=c, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) s += "%s\t%s\t%4.1f%%\n" % (model.name, c.atomspec, vbur) out.append((model.name, c.atomspec, vbur)) if displaySphere is not None: mdl = vbur_vis( session, rescol, targets, radii, scale, radius, c, pointSpacing, intersectionScale, displaySphere, ) model.add([mdl]) atomspec = mdl.atomspec center_coords = rescol.COM(c) #XXX: the center will be wrong if the models are tiled args = [ "color", "radial", atomspec, "center", ",".join(["%.4f" % x for x in center_coords]), "palette", palette, ";", "transparency", atomspec, "30", ] run(session, " ".join(args)) else: if steric_map: if targets is not None: key_atoms = [] targets = rescol.find(targets) for atom in targets: if any(c in atom.connected for c in mdl_center): key_atoms.append(atom) else: key_atoms = None x, y, z, min_alt, max_alt, basis, targets = rescol.steric_map( center=mdl_center, key_atoms=key_atoms, radius=radius, radii=radii, oop_vector=oop_vector, ip_vector=ip_vector, return_basis=True, num_pts=num_pts, shape=shape, ) vbur = rescol.percent_buried_volume( targets=targets, basis=basis, center=mdl_center, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) if not isinstance(mdl_center, np.ndarray): out.append( (model.name, ",".join([c.atomspec for c in mdl_center]), vbur, (x, y, z, min_alt, max_alt))) else: out.append( (model.name, ",".join(["%.3f" % c for c in mdl_center]), vbur, (x, y, z, min_alt, max_alt))) else: vbur = rescol.percent_buried_volume( targets=targets, center=mdl_center, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) if not isinstance(mdl_center, np.ndarray): s += "%s\t%s\t%4.1f%%\n" % (model.name, ", ".join( [c.atomspec for c in mdl_center]), vbur) out.append( (model.name, ", ".join([c.atomspec for c in mdl_center]), vbur)) else: s += "%s\t%s\t%4.1f%%\n" % (model.name, ",".join( ["%.3f" % c for c in mdl_center]), vbur) out.append( (model.name, ",".join(["%.3f" % c for c in mdl_center]), vbur)) if displaySphere is not None: mdl = vbur_vis( session, rescol, targets, radii, scale, radius, mdl_center, pointSpacing, intersectionScale, displaySphere, ) model.add([mdl]) atomspec = mdl.atomspec if not isinstance(mdl_center, np.ndarray): center_coords = rescol.COM(mdl_center) else: center_coords = mdl_center #XXX: the center will be wrong if the models are tiled args = [ "color", "radial", atomspec, "center", ",".join(["%.4f" % x for x in center_coords]), "palette", palette, ";", "transparency", atomspec, "30", ] run(session, " ".join(args)) s = s.strip() s += "</pre>" if not return_values: session.logger.info(s, is_html=True) else: return out
def substitute( session, selection=None, substituents=None, newName=None, guessAttachment=True, modify=True, minimize=False, useRemoteness=False, available=False, newResidue=False, ): if available: substitute_list(session) return if not selection: selection = selected_atoms(session) if not substituents: session.logger.error("missing required \"substituents\" argument") return attached = {} if newName is None: newName = [None for s in substituents] elif any(len(name.strip()) > 4 for name in newName): raise RuntimeError("residue names must be 4 characters or less") elif not all(name.isalnum() for name in newName): raise RuntimeError("invalid residue name: %s" % " ".join(newName)) elif len(substituents) != len(newName): raise RuntimeError( "number of substituents is not the same as the number of new names" ) if not guessAttachment: models, attached = avoidTargets(selection) else: models, attached = guessAttachmentTargets(selection, session) first_pass = True new_structures = [] for ndx, subname in enumerate(substituents): subname = subname.strip() sub = Substituent(subname) # when minimizing, we only want to deal with residues that are close to the substituent # determine the size of the new substituent to limit this if minimize: size = 5 for atom in sub.atoms: d = np.linalg.norm(atom.coords) if d > size: size = d for model in models: if modify and first_pass: conv_res = [] for res in models[model]: if res not in conv_res: conv_res.append(res) if minimize: for chix_res in model.residues: if chix_res in conv_res: continue added_res = False for atom in chix_res.atoms: for target in models[model][res]: d = np.linalg.norm(atom.coord - target.coord) if d < (size + 3): conv_res.append(chix_res) added_res = True break if added_res: break rescol = ResidueCollection(model, convert_residues=conv_res) for res in models[model]: for target in models[model][res]: if attached is not None: end = AtomSpec(attached[target].atomspec) else: end = None # call substitute on the ResidueCollection b/c we need to see # the other residues if minimize=True rescol.substitute( sub.copy(), AtomSpec(target.atomspec), attached_to=end, minimize=minimize, use_greek=useRemoteness, new_residue=newResidue, new_name=newName[ndx], ) rescol.update_chix(model) elif modify and not first_pass: raise RuntimeError("only the first model can be replaced") else: model_copy = model.copy() conv_res = [ model_copy.residues[i] for i in [model.residues.index(res) for res in models[model]] ] # modifying_residues = [model_copy.residues[i] for i in [model.residues.index(res) for res in models[model]]] modifying_residues = [r for r in conv_res] if minimize: for chix_res in model_copy.residues: if chix_res in conv_res: continue added_res = False for res in models[model]: for target in models[model][res]: for atom in chix_res.atoms: d = np.linalg.norm(atom.coord - target.coord) if d < (size + 3): conv_res.append(chix_res) added_res = True break if added_res: break if added_res: break rescol = ResidueCollection(model_copy, convert_residues=conv_res) for residue, res in zip(modifying_residues, models[model]): for target in models[model][res]: if attached is not None: end = AtomSpec(model_copy.atoms[model.atoms.index( attached[target])].atomspec) else: end = None rescol.substitute( sub.copy(), AtomSpec(model_copy.atoms[model.atoms.index( target)].atomspec), attached_to=end, minimize=minimize, use_greek=useRemoteness, new_residue=newResidue, new_name=newName[ndx], ) rescol.update_chix(model_copy) new_structures.append(model_copy) first_pass = False if not modify: session.models.add(new_structures)
def sterimol( session, selection, radii="UMN", showVectors=True, showRadii=True, LCorrection="FORTRAN", return_values=False ): models, attached = avoidTargets(session.logger, selection) radii = radii.lower() old_L = False if LCorrection.upper() == "FORTRAN": old_L = True model_names = [] targets = [] datas = [] info = "<pre>model\tsubstituent atom\tB1\tB2\tB3\tB4\tB5\tL\n" # if return_values: # if len(models.keys()) > 1: # raise RuntimeError("only one substituent may be selected") # if any(len(models[key]) > 1 for key in models.keys()): # raise RuntimeError("only one substituent may be selected") for model in models: rescol = ResidueCollection(model, refresh_ranks=False) for res in models[model]: for target in models[model][res]: end_atomspec = AtomSpec(attached[target].atomspec) start_atomspec = AtomSpec(target.atomspec) sub_atoms = rescol.get_fragment(start_atomspec, end_atomspec) sub = Substituent( sub_atoms, end=rescol.find_exact(end_atomspec)[0], detect=False, ) data = sub.sterimol( return_vector=True, radii=radii, old_L=old_L, ) l = np.linalg.norm(data["L"][1] - data["L"][0]) b1 = np.linalg.norm(data["B1"][1] - data["B1"][0]) b2 = np.linalg.norm(data["B2"][1] - data["B2"][0]) b3 = np.linalg.norm(data["B3"][1] - data["B3"][0]) b4 = np.linalg.norm(data["B4"][1] - data["B4"][0]) b5 = np.linalg.norm(data["B5"][1] - data["B5"][0]) if showVectors: for key, color in zip( ["B1", "B2", "B3", "B4", "B5", "L"], ["black", "green", "purple", "orange", "red", "blue"] ): start, end = data[key] s = ".color %s\n" % color s += ".note Sterimol %s\n" % key s += ".arrow %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n" % (*start, *end) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(session, stream, "Sterimol %s" % key) session.models.add(bild_obj, parent=model) if showRadii: s = ".note radii\n" s += ".transparency 75\n" color = None for atom in sub.atoms: chix_atom = atom.chix_atom if radii == "umn": r = VDW_RADII[chix_atom.element.name] elif radii == "bondi": r = BONDI_RADII[chix_atom.element.name] if color is None or chix_atom.color != color: color = chix_atom.color rgb = [x/255. for x in chix_atom.color] rgb.pop(-1) s += ".color %f %f %f\n" % tuple(rgb) s += ".sphere %f %f %f %f\n" % (*chix_atom.coord, r) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(session, stream, "Sterimol radii") session.models.add(bild_obj, parent=model) model_name = get_filename(model.name, include_parent_dir=False) info += "%-16s\t%-11s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n" % ( model_name, target.atomspec, b1, b2, b3, b4, b5, l ) model_names.append(model_name) targets.append(target.atomspec) datas.append(data) info = info.strip() info += "</pre>" if not return_values: session.logger.info(info, is_html=True) if return_values: return model_names, targets, datas
def job_finished(self, trigger_name, job): """when a job is finished, open or update the structure as requested""" if self.session.seqcrow_settings.settings.JOB_FINISHED_NOTIFICATION == \ 'log and popup notifications' and self.session.ui.is_gui: #it's just an error message for now #TODO: make my own logger self.session.logger.error("%s: %s" % (trigger_name, job)) else: job.session.logger.info("%s: %s" % (trigger_name, job)) if isinstance(job, LocalJob): self._thread = None if not hasattr(job, "output_name") or \ not os.path.exists(job.output_name): job.error = True else: fr = FileReader(job.output_name, just_geom=False) #XXX: finished is not added to the FileReader for ORCA and Psi4 when finished = False if 'finished' not in fr.other or not fr.other['finished']: job.error = True if job.auto_update and ( job.theory.geometry.chix_atomicstructure is not None and not job.theory.geometry.chix_atomicstructure.deleted): if os.path.exists(job.output_name): finfo = job.output_name try: finfo = (job.output_name, job.format_name, None) fr = FileReader(finfo, get_all=True, just_geom=False) if len(fr.atoms) > 0: job.session.filereader_manager.triggers.activate_trigger( ADD_FILEREADER, ([job.theory.geometry.chix_atomicstructure], [fr])) rescol = ResidueCollection(fr) rescol.update_chix( job.theory.geometry.chix_atomicstructure) except: job.update_structure() if fr.all_geom is not None and len(fr.all_geom) > 1: coordsets = rescol.all_geom_coordsets(fr) job.theory.geometry.chix_atomicstructure.remove_coordsets() job.theory.geometry.chix_atomicstructure.add_coordsets( coordsets) for i, coordset in enumerate(coordsets): job.theory.geometry.chix_atomicstructure.active_coordset_id = i + 1 for atom, coord in zip( job.theory.geometry.chix_atomicstructure.atoms, coordset): atom.coord = coord job.theory.geometry.chix_atomicstructure.active_coordset_id = job.theory.geometry.chix_atomicstructure.num_coordsets elif job.auto_open or job.auto_update: if hasattr(job, "output_name") and os.path.exists(job.output_name): if job.format_name: run( job.session, "open \"%s\" coordsets true format %s" % (job.output_name, job.format_name)) else: run(job.session, "open \"%s\" coordsets true" % job.output_name) else: self.session.logger.error("could not open output of %s" % repr(job)) self.triggers.activate_trigger(JOB_QUEUED, trigger_name) pass
def ligandSterimol(session, selection, radii="UMN", showVectors=True, showRadii=True, at_L=None, bisect_L=False, return_values=False): models, center, key_atoms = avoidTargets(session.logger, selection) radii = radii.lower() targets = [] coord_atoms = [] datas = [] info = "<pre>model\tcoord. atoms\tB1\tB2\tB3\tB4\tB5\tL\n" # if return_values: # if len(models.keys()) > 1: # raise RuntimeError("only one substituent may be selected") # if any(len(models[key]) > 1 for key in models.keys()): # raise RuntimeError("only one substituent may be selected") for model in models: rescol = ResidueCollection(model) comp_atoms = [AtomSpec(at.atomspec) for at in models[model]] key_atomspec = [AtomSpec(at.atomspec) for at in key_atoms[model]] center_atomspec = [AtomSpec(at.atomspec) for at in center[model]] if len(center_atomspec) != 1: session.logger.error( "ligand sterimol requires one central atom to which " + \ "the ligand is coordinated\n" + \ "%i were found on model %s:\n" % (len(center_atomspec), model.atomspec) + \ "\n".join([at.atomspec for at in center[model]]) ) continue comp = Component( rescol.find(comp_atoms), to_center=rescol.find(center_atomspec), key_atoms=rescol.find(key_atomspec), ) data = comp.sterimol( return_vector=True, radii=radii, at_L=at_L, to_center=rescol.find(center_atomspec), bisect_L=bisect_L, ) l = np.linalg.norm(data["L"][1] - data["L"][0]) b1 = np.linalg.norm(data["B1"][1] - data["B1"][0]) b2 = np.linalg.norm(data["B2"][1] - data["B2"][0]) b3 = np.linalg.norm(data["B3"][1] - data["B3"][0]) b4 = np.linalg.norm(data["B4"][1] - data["B4"][0]) b5 = np.linalg.norm(data["B5"][1] - data["B5"][0]) if showVectors: for key, color in zip( ["B1", "B2", "B3", "B4", "B5", "L"], ["black", "green", "purple", "orange", "red", "blue"]): start, end = data[key] s = ".color %s\n" % color s += ".note Sterimol %s\n" % key s += ".arrow %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n" % ( *start, *end) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(session, stream, "Sterimol %s" % key) session.models.add(bild_obj, parent=model) if showRadii: s = ".note radii\n" s += ".transparency 75\n" color = None for atom in comp.atoms: chix_atom = atom.chix_atom if radii == "umn": r = VDW_RADII[chix_atom.element.name] elif radii == "bondi": r = BONDI_RADII[chix_atom.element.name] if color is None or chix_atom.color != color: color = chix_atom.color rgb = [x / 255. for x in chix_atom.color] rgb.pop(-1) s += ".color %f %f %f\n" % tuple(rgb) s += ".sphere %f %f %f %f\n" % (*chix_atom.coord, r) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(session, stream, "Sterimol radii") session.models.add(bild_obj, parent=model) name = get_filename(model.name, include_parent_dir=False) info += "%-16s\t%-11s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n" % ( name, ", ".join(at.atomspec for at in key_atoms[model]), b1, b2, b3, b4, b5, l) targets.append(name) coord_atoms.append([at.atomspec for at in key_atoms[model]]) datas.append(data) info = info.strip() info += "</pre>" if not return_values: session.logger.info(info, is_html=True) if return_values: return targets, coord_atoms, datas
def substituent_selection(session, sub_name, models, results): #TODO: optimize - or cheat and use cython or something #TODO: make it so it doesn't select things with just an H bonded to them # e.g. sel OH should not select water molecules # probably do a get_all_connected for each fragment and # check if all_connected.subtract(Atoms[atom]).subtract(frag) leave just an H atoms = Atoms() sub = Substituent(sub_name) chix_sub = ResidueCollection(sub).get_chimera(session) sub_elements = sorted(chix_sub.atoms.elements.names) sub_ranks = canonical_rank(Atoms(chix_sub.atoms)) sorted_sub_atoms = [ x for _, x in sorted(zip(sub_ranks, chix_sub.atoms), key=lambda pair: pair[0]) ] length = len(sub.atoms) #rank_time = 0 #frag_time = 0 for model in models: if isinstance(model, AtomicStructure): for atom in model.atoms: #session.logger.info("checking groups on %s" % atom.atomspec) for bonded_atom in atom.neighbors: if bonded_atom.element.name != sub.atoms[0].element: continue #session.logger.info("fragment for %s" % bonded_atom.atomspec) #frag_start = perf_counter() frag = get_fragment(bonded_atom, atom, length) #frag_stop = perf_counter() #frag_time += frag_stop - frag_start if frag.intersects(atoms): continue frag = frag.subtract(Atoms([atom])) if len(frag) != length: continue elements = sorted(frag.elements.names) if sub_elements != elements: #session.logger.info("wrong elements") continue #rank_start = perf_counter() frag_ranks = canonical_rank(frag) #rank_stop = perf_counter() #rank_time += rank_stop - rank_start #session.logger.warning(", ".join(sub_elements)) #session.logger.warning("%s;\n%s" % (", ".join(str(x) for x in sorted(frag_ranks)), ", ".join(str(x) for x in sorted(sub_ranks)))) sorted_frag_atoms = [ x for _, x in sorted(zip(frag_ranks, frag.instances()), key=lambda pair: pair[0]) ] #session.logger.warning("%s;\n%s" % (", ".join(x.atomspec for x in sorted_frag_atoms), ", ".join(x.name for x in sorted_sub_atoms))) for a, b in zip(sorted_frag_atoms, sorted_sub_atoms): #session.logger.info("%s %s" % (a.atomspec, b.name)) if a.element.name != b.element.name: #session.logger.info("different elements") break #session.logger.info("bonded: %s; other: %s" % (bonded_atom.atomspec, atom.atomspec)) if a is not bonded_atom and len(a.neighbors) != len( b.neighbors): #session.logger.info("different num neighbors") #session.logger.info("%s and %s" % (a.atomspec, b.name)) #session.logger.info("%i vs %i" % (len(a.neighbors), len(b.neighbors))) break elif a is bonded_atom and (len(a.neighbors) - 1) != len(b.neighbors): #session.logger.info("first atom, different num neighbors") #session.logger.info("%s and %s" % (a.atomspec, b.name)) #session.logger.info("%i vs %i" % (len(a.neighbors) - 1, len(b.neighbors))) break failed = False for i, j, k in zip( sorted([ aa.element.name for aa in a.neighbors if ((aa is not atom and a is bonded_atom) or a is not bonded_atom) ]), sorted([bb.element.name for bb in b.neighbors]), sorted([ aa for aa in a.neighbors if ((aa is not atom and a is bonded_atom) or a is not bonded_atom) ]), ): if i != j: #session.logger.info("failed %s %s, %s" % (i, j, k.atomspec)) failed = True break if failed: break else: atoms = atoms.merge(frag) #session.logger.info("spent %f time fragmenting" % frag_time) #session.logger.info("spent %f time ranking atoms" % rank_time) results.add_atoms(atoms)
def fuseRing(session, selection=None, rings=None, newName=None, modify=True, minimize=False, available=False): if available: fuseRing_list(session) return if not selection: selection = selected_atoms(session) if not rings: session.logger.error("missing required \"rings\" argument") return if newName is None: pass elif any(len(name.strip()) > 4 for name in newName): raise RuntimeError("residue names must be 4 characters or less") elif not all(name.isalnum() for name in newName): raise RuntimeError("invalid residue name: %s" % newName) elif len(rings) != len(newName): raise RuntimeError( "number of substituents is not the same as the number of new names" ) if len(selection) < 2: raise RuntimeWarning("two atoms must be selected per molecule") models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [atom] else: models[atom.structure].append(atom) if len(models[atom.structure]) > 2: raise RuntimeError("only two atoms can be selected on any model") first_pass = True new_structures = [] for i, ringname in enumerate(rings): ringname = ringname.strip() for model in models: atom1 = models[model][0] atom2 = models[model][1] if modify and first_pass: convert = minimal_ring_convert(model, *models[model]) if newName is not None: for res in convert: res.name = newName[i] rescol = ResidueCollection(model, convert_residues=convert) target = rescol.find( [AtomSpec(atom1.atomspec), AtomSpec(atom2.atomspec)]) elif modify and not first_pass: raise RuntimeError("only the first model can be replaced") else: model_copy = model.copy() a1 = model_copy.atoms[model.atoms.index(models[model][0])] a2 = model_copy.atoms[model.atoms.index(models[model][1])] convert = minimal_ring_convert(model_copy, a1, a2) if newName is not None: for res in convert: res.name = newName[i] rescol = ResidueCollection(model_copy, convert_residues=convert) target = rescol.find( [AtomSpec(a1.atomspec), AtomSpec(a2.atomspec)]) rescol.ring_substitute(target, ringname, minimize=minimize) if modify: rescol.update_chix(model) else: rescol.update_chix(model_copy) new_structures.append(model_copy) first_pass = False if not modify: session.models.add(new_structures)
def open_aarontools(session, stream, file_name, format_name=None, coordsets=False): from AaronTools.fileIO import FileReader from AaronTools.geometry import Geometry from SEQCROW.residue_collection import ResidueCollection from SEQCROW.managers import ADD_FILEREADER from os.path import split as path_split from warnings import warn if format_name == "Gaussian input file": fmt = "com" elif format_name == "Gaussian output file": fmt = "log" elif format_name == "ORCA output file": fmt = "out" elif format_name == "Psi4 output file": fmt = "dat" elif format_name == "XYZ file": fmt = "xyz" elif format_name == "FCHK file": fmt = "fchk" fr = FileReader((file_name, fmt, stream), just_geom=False, get_all=True) if hasattr(stream, "close") and callable(stream.close): stream.close() if fr.file_type == "dat": format_name = "Psi4 output file" elif fr.file_type == "out": format_name = "ORCA output file" try: geom = ResidueCollection(fr) except Exception as e: s = "could not open %s" % file_name if "error" in fr.other and fr.other["error"]: s += "\n%s contains an error (%s):\n%s" % ( format_name, fr.other["error"], fr.other["error_msg"]) session.logger.error(s) session.logger.error(repr(e)) return [], "SEQCROW failed to open %s" % file_name structure = geom.get_chimera(session, coordsets=(fr.all_geom is not None and len(fr.all_geom) > 1), filereader=fr) #associate the AaronTools FileReader with each structure session.filereader_manager.triggers.activate_trigger( ADD_FILEREADER, ([structure], [fr])) if coordsets: from chimerax.std_commands.coordset_gui import CoordinateSetSlider from SEQCROW.tools import EnergyPlot slider = CoordinateSetSlider(session, structure) if "energy" in fr.other: nrg_plot = EnergyPlot(session, structure, fr) if not nrg_plot.opened: warn("energy plot could not be opened\n" + \ "there might be a mismatch between energy entries and structure entries in %s" % file_name) nrg_plot.delete() if fr.all_geom is not None and len(fr.all_geom) > 1: structure.active_coordset_id = len(fr.all_geom) if coordsets: slider.set_slider(len(fr.all_geom)) if format_name == "Gaussian input file": a_or_an = "a" elif format_name == "Gaussian output file": a_or_an = "a" elif format_name == "ORCA output file": a_or_an = "an" elif format_name == "Psi4 output file": a_or_an = "a" elif format_name == "XYZ file": a_or_an = "an" elif format_name == "FCHK file": a_or_an = "an" status = "Opened %s as %s %s %s" % (file_name, a_or_an, format_name, "movie" if coordsets else "") structure.filename = file_name return [structure], status
def calc_cone(self, *args): self.settings.cone_option = self.cone_option.currentText() self.settings.radii = self.radii_option.currentText() self.settings.display_radii = self.display_radii.checkState( ) == Qt.Checked self.settings.display_cone = self.display_cone.checkState( ) == Qt.Checked if self.cone_option.currentText() == "Tolman (Unsymmetrical)": method = "tolman" else: method = self.cone_option.currentText() radii = self.radii_option.currentText() return_cones = self.display_cone.checkState() == Qt.Checked display_radii = self.display_radii.checkState() == Qt.Checked # self.table.setRowCount(0) for center_atom in selected_atoms(self.session): rescol = ResidueCollection(center_atom.structure) at_center = rescol.find_exact(AtomSpec(center_atom.atomspec))[0] if center_atom.structure in self.ligands: comp = Component( rescol.find([ AtomSpec(atom.atomspec) for atom in self.ligands[center_atom.structure] ]), to_center=rescol.find_exact(AtomSpec( center_atom.atomspec)), key_atoms=rescol.find(BondedTo(at_center)), ) else: comp = Component( rescol.find(NotAny(at_center)), to_center=rescol.find_exact(AtomSpec( center_atom.atomspec)), key_atoms=rescol.find(BondedTo(at_center)), ) cone_angle = comp.cone_angle( center=rescol.find(AtomSpec(center_atom.atomspec)), method=method, radii=radii, return_cones=return_cones, ) if return_cones: cone_angle, cones = cone_angle s = ".transparency 0.5\n" for cone in cones: apex, base, radius = cone s += ".cone %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %.3f open\n" % ( *apex, *base, radius) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(self.session, stream, "Cone angle %s" % center_atom) self.session.models.add(bild_obj, parent=center_atom.structure) if display_radii: s = ".note radii\n" s += ".transparency 75\n" color = None for atom in comp.atoms: chix_atom = atom.chix_atom if radii.lower() == "umn": r = VDW_RADII[chix_atom.element.name] elif radii.lower() == "bondi": r = BONDI_RADII[chix_atom.element.name] if color is None or chix_atom.color != color: color = chix_atom.color rgb = [x / 255. for x in chix_atom.color] rgb.pop(-1) s += ".color %f %f %f\n" % tuple(rgb) s += ".sphere %f %f %f %f\n" % (*chix_atom.coord, r) stream = BytesIO(bytes(s, "utf-8")) bild_obj, status = read_bild(self.session, stream, "Cone angle radii") self.session.models.add(bild_obj, parent=center_atom.structure) row = self.table.rowCount() self.table.insertRow(row) name = QTableWidgetItem() name.setData(Qt.DisplayRole, center_atom.structure.name) self.table.setItem(row, 0, name) center = QTableWidgetItem() center.setData(Qt.DisplayRole, center_atom.atomspec) self.table.setItem(row, 1, center) ca = QTableWidgetItem() ca.setData(Qt.DisplayRole, "%.2f" % cone_angle) self.table.setItem(row, 2, ca) self.table.resizeColumnToContents(0) self.table.resizeColumnToContents(1) self.table.resizeColumnToContents(2)
def percent_vbur( session, selection, radii="UMN", radius=3.5, scale=1.17, method="Lebedev", radialPoints=20, angularPoints=1454, minimumIterations=25, onlyAtoms=None, center=None, useCentroid=True, displaySphere=None, pointSpacing=0.1, intersectionScale=6, palette="rainbow", return_values=False, steric_map=False, useScene=False, num_pts=100, shape="circle", labels="none", reportComponent="total", ): out = [] models = { model: [ atom for atom in model.atoms if onlyAtoms is not None and atom in onlyAtoms ] for model in selection if isinstance(model, AtomicStructure) } s = "<pre>model\tcenter\t%Vbur\n" for model in models: if len(models[model]) == 0: targets = None else: targets = [AtomSpec(atom.atomspec) for atom in models[model]] if center is not None: if isinstance(center, tuple): mdl_center = np.array(center) else: mdl_center = [ AtomSpec(atom.atomspec) for atom in model.atoms if atom in center ] else: mdl_center = [] rescol = ResidueCollection(model) if useScene: oop_vector = session.view.camera.get_position().axes()[2] ip_vector = session.view.camera.get_position().axes()[1] x_vec = session.view.camera.get_position().axes()[0] basis = np.array([x_vec, ip_vector, oop_vector]).T else: oop_vector = None ip_vector = None basis = None if len(mdl_center) == 0: rescol.detect_components() mdl_center = rescol.center elif not isinstance(center, np.ndarray): mdl_center = rescol.find([AtomSpec(c.atomspec) for c in center]) key_atoms = None if not useCentroid and not isinstance(center, np.ndarray): for c in mdl_center: if targets is not None: key_atoms = [] targets = rescol.find(targets) for atom in targets: if c in atom.connected or atom in c.connected: key_atoms.append(atom) else: key_atoms = None if (labels != "none" or reportComponent != "total") and not useScene: if not key_atoms: session.logger.warning( "bonds between center and coordinating atoms is required to" " properly orient octants") oop_vector = np.zeros(3) for atom in key_atoms: oop_vector += c.coords - atom.coords if len(key_atoms) == 1: ip_vector = perp_vector(oop_vector) x_vec = np.cross(ip_vector, oop_vector) else: coords = [atom.coords for atom in key_atoms] coords.append(c.coords) coords = np.array(coords) ip_vector = perp_vector(coords) x_vec = np.cross(ip_vector, oop_vector) x_vec /= np.linalg.norm(x_vec) ip_vector = -np.cross(x_vec, oop_vector) ip_vector /= np.linalg.norm(ip_vector) basis = np.array([x_vec, ip_vector, oop_vector]).T if steric_map: x, y, z, min_alt, max_alt, basis, _ = rescol.steric_map( center=c, key_atoms=key_atoms, radii=radii, oop_vector=oop_vector, ip_vector=ip_vector, radius=radius, return_basis=True, num_pts=num_pts, shape=shape, ) vbur = rescol.percent_buried_volume( targets=targets, basis=basis, center=c, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) if steric_map: out.append( (model, c.atomspec, vbur, (x, y, z, min_alt, max_alt))) else: out.append((model, c.atomspec, vbur)) s += "%s\t%s\t" % (model.name, c.atomspec) if hasattr(vbur, "__iter__"): if reportComponent == "octants": s += "%s\n" % ",".join(["%.1f%%" % v for v in vbur]) elif reportComponent == "quadrants": s += "%s\n" % ",".join([ "%.1f%%" % v for v in [ vbur[0] + vbur[7], vbur[1] + vbur[6], vbur[2] + vbur[5], vbur[3] + vbur[4], ] ]) else: s += "%.1f%%\n" % sum(vbur) else: s += "%.1f%%\n" % vbur if displaySphere is not None: mdl = vbur_vis( session, rescol, targets, radii, scale, radius, c, pointSpacing, intersectionScale, displaySphere, vbur, labels, basis=basis, ) model.add(mdl) atomspec = mdl[0].atomspec center_coords = rescol.COM(c) args = [ "color", "radial", atomspec, "center", ",".join(["%.4f" % x for x in center_coords]), "palette", palette, "range", "0,%.2f" % radius, "coordinateSystem", model.atomspec, ";", "transparency", atomspec, "30", ] run(session, " ".join(args)) else: if targets is not None: key_atoms = [] targets = rescol.find(targets) for atom in targets: if any(c in atom.connected for c in mdl_center): key_atoms.append(atom) else: key_atoms = None if (labels != "none" or reportComponent != "total") and not useScene: if not key_atoms: session.logger.warning( "bonds between center and coordinating atoms is required to" " properly orient octants") oop_vector = np.zeros(3) for atom in key_atoms: if isinstance(mdl_center, np.ndarray): oop_vector += mdl_center - atom.coords else: for c in mdl_center: oop_vector += c.coords - atom.coords if len(key_atoms) == 1: ip_vector = perp_vector(oop_vector) x_vec = np.cross(ip_vector, oop_vector) else: coords = [atom.coords for atom in key_atoms] if isinstance(mdl_center, np.ndarray): coords.append(mdl_center) else: coords.extend([c.coords for c in mdl_center]) coords = np.array(coords) ip_vector = perp_vector(coords) x_vec = np.cross(ip_vector, oop_vector) x_vec /= np.linalg.norm(x_vec) ip_vector = -np.cross(x_vec, oop_vector) ip_vector /= np.linalg.norm(ip_vector) basis = np.array([x_vec, ip_vector, oop_vector]).T if steric_map: x, y, z, min_alt, max_alt, basis, _ = rescol.steric_map( center=mdl_center, key_atoms=key_atoms, radius=radius, radii=radii, oop_vector=oop_vector, ip_vector=ip_vector, return_basis=True, num_pts=num_pts, shape=shape, ) vbur = rescol.percent_buried_volume( targets=targets, basis=basis, center=mdl_center, radius=radius, radii=radii, scale=scale, method=method, rpoints=int(radialPoints), apoints=int(angularPoints), min_iter=minimumIterations, ) if steric_map: if not isinstance(mdl_center, np.ndarray): out.append( (model, ",".join([c.atomspec for c in mdl_center]), vbur, (x, y, z, min_alt, max_alt))) else: out.append( (model, ",".join(["%.3f" % c for c in mdl_center]), vbur, (x, y, z, min_alt, max_alt))) else: if not isinstance(mdl_center, np.ndarray): s += "%s\t%s\t" % (model.name, ", ".join( [c.atomspec for c in mdl_center])) out.append( (model, ", ".join([c.atomspec for c in mdl_center]), vbur)) else: s += "%s\t%s\t" % (model.name, ",".join( ["%.3f" % c for c in mdl_center])) out.append( (model, ",".join(["%.3f" % c for c in mdl_center]), vbur)) if hasattr(vbur, "__iter__"): if reportComponent == "octants": s += "%s\n" % ",".join(["%.1f%%" % v for v in vbur]) elif reportComponent == "quadrants": s += "%s\n" % ",".join([ "%.1f%%" % v for v in [ vbur[0] + vbur[7], vbur[1] + vbur[6], vbur[2] + vbur[5], vbur[3] + vbur[4], ] ]) else: s += "%.1f%%\n" % sum(vbur) else: s += "%.1f%%\n" % vbur if displaySphere is not None: mdl = vbur_vis( session, rescol, targets, radii, scale, radius, mdl_center, pointSpacing, intersectionScale, displaySphere, vbur, labels, basis=basis, ) model.add(mdl) atomspec = mdl[0].atomspec if not isinstance(mdl_center, np.ndarray): center_coords = rescol.COM(mdl_center) else: center_coords = mdl_center #XXX: the center will be wrong if the models are tiled args = [ "color", "radial", atomspec, "center", ",".join(["%.4f" % x for x in center_coords]), "palette", palette, "range", "0,%.2f" % radius, "coordinateSystem", model.atomspec, ";", "transparency", atomspec, "30", ] run(session, " ".join(args)) s = s.strip() s += "</pre>" if not return_values: session.logger.info(s, is_html=True) else: return out