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 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 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 do_maplig(self): lignames = self.ligname.text() selection = selected_atoms(self.session) if len(selection) < 1: raise RuntimeWarning("nothing selected") models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [AtomSpec(atom.atomspec)] else: models[atom.structure].append(AtomSpec(atom.atomspec)) first_pass = True new_structures = [] for ligname in lignames.split(','): ligname = ligname.strip() lig = Component(ligname) for model in models: if self.close_previous_bool and first_pass: rescol = ResidueCollection(model) elif self.close_previous_bool and not first_pass: raise RuntimeError("only the first model can be replaced") else: model_copy = model.copy() rescol = ResidueCollection(model_copy) for i, atom in enumerate(model.atoms): rescol.atoms[i].atomspec = atom.atomspec rescol.atoms[i].add_tag(atom.atomspec) rescol.atoms[i].chix_atom = atom target = rescol.find(models[model]) if len(target) % len(lig.key_atoms) == 0: k = 0 ligands = [] while k != len(target): res_lig = ResidueCollection(lig.copy(), comment=lig.comment) res_lig.parse_comment() res_lig = Component(res_lig, key_atoms = ",".join([str(k + 1) for k in res_lig.other["key_atoms"]])) ligands.append(res_lig) k += len(lig.key_atoms) else: raise RuntimeError("number of key atoms no not match: %i now, new ligand has %i" % (len(target), len(lig.key_atoms))) rescol.map_ligand(ligands, target) for center_atom in rescol.center: center_atom.connected = set([]) for atom in rescol.atoms: if atom not in rescol.center: if center_atom.is_connected(atom): atom.connected.add(center_atom) center_atom.connected.add(atom) if self.close_previous_bool: rescol.update_chix(model) else: struc = rescol.get_chimera(self.session) new_structures.append(struc) first_pass = False if not self.close_previous_bool: self.session.models.add(new_structures)