示例#1
0
    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
示例#2
0
    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
示例#3
0
 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"))
示例#4
0
    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))
示例#5
0
    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()
示例#6
0
 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"))
示例#7
0
    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))
示例#8
0
    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)
示例#9
0
    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")
示例#10
0
 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]))
示例#11
0
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))
示例#12
0
文件: libadd.py 项目: QChASM/SEQCROW
    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)
示例#13
0
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)
示例#14
0
    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)
示例#15
0
    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)
示例#16
0
文件: libadd.py 项目: QChASM/SEQCROW
    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)
示例#17
0
    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)
示例#18
0
    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)
示例#19
0
文件: libadd.py 项目: QChASM/SEQCROW
    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)
示例#20
0
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)
示例#21
0
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
示例#22
0
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)
示例#23
0
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
示例#24
0
    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
示例#25
0
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
示例#26
0
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)
示例#27
0
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)
示例#28
0
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
示例#29
0
    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)
示例#30
0
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