Esempio n. 1
0
    def test_init(self):
        sub = Substituent("COCH3")
        self.is_COCH3(sub)

        sub = Substituent("COCH3", targets=["C", "O", "H"])
        self.is_COCH3(sub)
        return
Esempio n. 2
0
    def test_substitute(self):
        ref = Geometry(TestGeometry.benz_NO2_Cl)
        mol = Geometry(TestGeometry.benzene)

        mol.substitute(Substituent("NO2"), "12")
        mol.substitute(Substituent("Cl"), "11")

        self.assertTrue(validate(mol, ref))
Esempio n. 3
0
    def test_substitute(self):
        ref = Geometry(TestGeometry.benz_NO2_Cl)
        mol = Geometry(TestGeometry.benzene)

        mol.substitute(Substituent("NO2"), "12")
        mol.substitute(Substituent("Cl"), "11")

        rmsd = mol.RMSD(ref, align=True)
        self.assertTrue(rmsd < rmsd_tol(ref))
Esempio n. 4
0
    def test_detect_sub(self):
        mol = TestSubstituent.benz_NO2_Cl

        NO2 = mol.get_fragment("N", "C", as_object=True)
        sub = Substituent(NO2)
        self.is_NO2(sub)

        NO2 = mol.get_fragment("N", "C", copy=True)
        sub = Substituent(NO2)
        self.is_NO2(sub)
Esempio n. 5
0
    def test_align_to_bond(self):
        mol = TestSubstituent.benz_NO2_Cl
        bond = mol.bond("1", "12")

        sub = Substituent("NO2")
        sub.align_to_bond(bond)

        bond /= np.linalg.norm(bond)
        test_bond = sub.find("N")[0].coords - np.array([0.0, 0.0, 0.0])
        test_bond /= np.linalg.norm(test_bond)
        self.assertTrue(np.linalg.norm(bond - test_bond) < 10**-8)
Esempio n. 6
0
    def test_minimize_torsion(self):
        geom = TestComponent.benz.copy()
        ref = Component("ref_files/minimize_torsion.xyz")

        geom.substitute(Substituent("tBu"), "12")
        geom.substitute(Substituent("Ph"), "10")
        geom.substitute(Substituent("OH"), "7")

        geom.minimize_sub_torsion()
        rmsd = geom.RMSD(ref, align=True)
        self.assertTrue(rmsd < 1)
Esempio n. 7
0
    def test_minimize_torsion(self):
        ref = Component(
            os.path.join(prefix, "ref_files", "minimize_torsion.xyz")
        )

        geom = TestComponent.benz.copy()
        geom.substitute(Substituent("tBu"), "12")
        geom.substitute(Substituent("Ph"), "10")
        geom.substitute(Substituent("OH"), "7")
        geom.minimize_sub_torsion()
        self.assertTrue(validate(geom, ref, heavy_only=True))
Esempio n. 8
0
    def register_selector_menus(session):
        from PyQt5.QtWidgets import QAction

        from AaronTools.const import ELEMENTS
        from AaronTools.substituent import Substituent

        add_submenu = session.ui.main_window.add_select_submenu
        add_selector = session.ui.main_window.add_menu_selector
        substituent_menu = add_submenu(['Che&mistry'], 'Substituents')
        for sub in Substituent.list():
            if sub in ELEMENTS:
                # print(sub, "in ELEMENTS")
                continue
            if not sub[0].isalpha():
                # print(sub, "startswith non-alpha")
                continue
            if len(sub) > 1 and any(not (c.isalnum() or c in "+-")
                                    for c in sub[1:]):
                # print(sub, "contains non-alphanumeric character")
                continue
            add_selector(substituent_menu, sub, sub)

        mw = session.ui.main_window
        structure_menu = add_submenu([], '&Structure')
        structure_menu.addAction(QAction("Connected", mw))
Esempio n. 9
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)
Esempio n. 10
0
    def substitute(self, sub, target, attached_to=None, minimize=True):
        if not isinstance(sub, Substituent):
            sub = Substituent(sub)
        for key, val in self.components.items():
            for comp in val:
                try:
                    target = comp.find_exact(target)
                except LookupError:
                    # keep looking
                    continue

                # found! do substitution and return
                comp.substitute(sub, target, attached_to)
                # update tags
                for a in comp.atoms:
                    a.add_tag(key)
                # remove old from conf_spec
                for t in target:
                    if t in self.conf_spec:
                        del self.conf_spec[t]
                # add new to conf_spec
                if sub.conf_num is not None and sub.conf_num > 1:
                    self.conf_spec[sub.atoms[0]] = [1, []]
                self.rebuild()
                self.detect_components()
                if minimize:
                    self.minimize()
                return
Esempio n. 11
0
 def _decode_substituent(self, obj):
     kwargs = {}
     for key in ["name", "end", "conf_num", "conf_angle"]:
         kwargs[key] = obj[key]
     ranks = [a._rank for a in obj["atoms"]]
     obj = self._decode_geometry(obj)
     for a, r in zip(obj.atoms, ranks):
         a._rank = r
     return Substituent(obj, **kwargs)
Esempio n. 12
0
    def initialize(session, bundle_info):
        from SEQCROW import settings as seqcrow_settings
        seqcrow_settings.settings = settings._SEQCROWSettings(
            session, "SEQCROW")
        if session.ui.is_gui:
            from .presets import seqcrow_bse, seqcrow_s, seqcrow_vdw, indexLabel

            session.presets.add_presets(
                "SEQCROW",
                {"ball-stick-endcap": lambda p=seqcrow_bse: p(session)})
            session.presets.add_presets(
                "SEQCROW", {"sticks": lambda p=seqcrow_s: p(session)})
            session.presets.add_presets(
                "SEQCROW", {"VDW": lambda p=seqcrow_vdw: p(session)})
            session.presets.add_presets(
                "SEQCROW", {"index labels": lambda p=indexLabel: p(session)})

            session.ui.triggers.add_handler('ready',
                                            lambda *args, ses=session: settings
                                            .register_settings_options(ses))

            session.ui.triggers.add_handler(
                'ready',
                lambda *args, ses=session: _SEQCROW_API.
                register_selector_menus(ses))

        #apply AARONLIB setting
        if seqcrow_settings.settings.AARONLIB is not None:
            os.environ['AARONLIB'] = seqcrow_settings.settings.AARONLIB

        session.seqcrow_settings = seqcrow_settings

        from AaronTools.const import ELEMENTS
        from AaronTools.substituent import Substituent

        #register selectors from the user's personal library
        for sub in Substituent.list():
            if sub in ELEMENTS:
                # print(sub, "in ELEMENTS")
                continue
            if not sub[0].isalpha():
                # print(sub, "startswith non-alpha")
                continue
            if len(sub) > 1 and any(not (c.isalnum() or c in "+-")
                                    for c in sub[1:]):
                # print(sub, "contains non-alphanumeric character")
                continue
            if not any(
                [selector.name == sub for selector in bundle_info.selectors]):
                si = SelectorInfo(sub,
                                  atomic=True,
                                  synopsis="%s substituent" % sub)
                bundle_info.selectors.append(si)

        #need to reregister selectors b/c ^ that bypassed the bundle_info.xml or something
        bundle_info._register_selectors(session.logger)
Esempio n. 13
0
    def test_substituent(self):
        try:
            import rdkit

            sub = Substituent.from_string(
                "acetyl", form="iupac", strict_use_rdkit=True
            )
            self.is_COCH3(sub)

            with self.assertLogs(Substituent.LOG, level="WARNING"):
                sub = Substituent.from_string(
                    "nitro", form="iupac", strict_use_rdkit=True
                )
                self.is_NO2(sub)

            sub = Substituent.from_string(
                "O=[N.]=O", form="smiles", strict_use_rdkit=True
            )
            self.is_NO2(sub)

            sub = Substituent.from_string(
                "O=[N]=O", form="smiles", strict_use_rdkit=True
            )
            self.is_NO2(sub)

        except (ImportError, ModuleNotFoundError):
            # I still want to test CACTVS things because sometimes they change stuff
            # that breaks our stuff
            if any(
                user == os.getenv("USER", os.getenv("USERNAME", False))
                for user in ["ajs99778", "normn"]
            ):
                sub = Substituent.from_string("acetyl", form="iupac")
                print(sub.write(outfile=False))
                self.is_COCH3(sub, thresh=0.3)

                sub = Substituent.from_string("nitro", form="iupac")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

                sub = Substituent.from_string("O=[N.]=O", form="smiles")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

                sub = Substituent.from_string("O=[N]=O", form="smiles")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

            else:
                self.skipTest("RDKit not installed, CACTVS is not tested")
Esempio n. 14
0
    def test_substitute(self):
        mol = TestComponent.benz.copy()
        benz_Cl = TestComponent.benz_Cl.copy()
        benz_NO2_Cl = TestComponent.benz_NO2_Cl.copy()
        benz_OH_Cl = TestComponent.benz_OH_Cl.copy()
        benz_Ph_Cl = TestComponent.benz_Ph_Cl.copy()

        mol.substitute(Substituent("Cl"), "11")
        res = validate(mol, benz_Cl)
        self.assertTrue(res)

        mol.substitute(Substituent("NO2"), "12", "1")
        res = validate(mol, benz_NO2_Cl, sort=True)
        self.assertTrue(res)

        mol.substitute(Substituent("OH"), "NO2")
        res = validate(mol, benz_OH_Cl, sort=True)
        self.assertTrue(res)

        mol.substitute(Substituent("Ph"), ["12", "12.*"])
        res = validate(mol, benz_Ph_Cl, sort=True, thresh="loose")
        self.assertTrue(res)
Esempio n. 15
0
    def test_substitute(self):
        mol = TestComponent.benz.copy()
        benz_Cl = TestComponent.benz_Cl.copy()
        benz_NO2_Cl = TestComponent.benz_NO2_Cl.copy()
        benz_OH_Cl = TestComponent.benz_OH_Cl.copy()
        benz_Ph_Cl = TestComponent.benz_Ph_Cl.copy()

        mol.substitute(Substituent("Cl"), "11")
        rmsd = mol.RMSD(benz_Cl, sort=True)
        self.assertTrue(rmsd < rmsd_tol(benz_Cl))

        mol.substitute(Substituent("NO2"), "12", "1")
        rmsd = mol.RMSD(benz_NO2_Cl, sort=True)
        self.assertTrue(rmsd < rmsd_tol(benz_NO2_Cl))

        mol.substitute(Substituent("OH"), "NO2")
        rmsd = mol.RMSD(benz_OH_Cl, sort=True)
        self.assertTrue(rmsd < rmsd_tol(benz_OH_Cl))

        mol.substitute(Substituent("Ph"), "12.*")
        rmsd = mol.RMSD(benz_Ph_Cl)
        self.assertTrue(rmsd < rmsd_tol(benz_Ph_Cl))
Esempio n. 16
0
def register_selectors(logger, name):
    if name == "tm":
        register_selector("tm", tm_selector, logger, desc="transition metals")

    elif any(name == sub for sub in Substituent.list()):
        register_selector(
            name,
            lambda sess, models, results, sub_name=name: substituent_selection(
                sess, sub_name, models, results),
            logger,
            desc="substituent %s" % name)

    elif name == "connected":
        register_selector("connected",
                          all_connected_selector,
                          logger,
                          desc="fragment connected to selected atoms")
Esempio n. 17
0
    def __init__(
        self,
        structure,
        name="",
        comment=None,
        tag=None,
        to_center=None,
        key_atoms=None,
        detect_backbone=True,
    ):
        """
        comp is either a file, a geometry, or an atom list
        """
        super().__init__()
        self.name = name
        self.comment = comment
        self.other = {}
        self.substituents = []
        self.backbone = None
        self.key_atoms = []

        if isinstance(structure, str) and not os.access(structure, os.R_OK):
            for ext in read_types:
                if structure.endswith(".%s" % ext):
                    structure = structure[: -(1 + len(ext))]

            for lib in [Component.AARON_LIBS, Component.BUILTIN]:
                if not os.path.exists(lib):
                    continue
                flig = None
                for f in os.listdir(lib):
                    name, ext = os.path.splitext(f)
                    if not any(".%s" % x == ext for x in read_types):
                        continue

                    match = structure == name
                    if match:
                        flig = os.path.join(lib, f)
                        break

                if flig:
                    break
            else:
                try:
                    structure = Substituent(structure)
                    Component.FROM_SUBSTITUENTS.add(structure.name)
                    self.__init__(structure, comment="K:1")
                    return
                except Exception:
                    raise FileNotFoundError(
                        "Cannot find ligand in library:", structure
                    )
            structure = flig
        super().__init__(structure, name, comment)

        if tag is not None:
            for a in self.atoms:
                a.add_tag(tag)

        self.other = self.parse_comment()
        try:
            self.key_atoms = self.find("key")
        except LookupError:
            if "key_atoms" in self.other:
                self.key_atoms = [
                    self.atoms[i] for i in self.other["key_atoms"]
                ]
        if key_atoms is not None:
            self.key_atoms = self.find(key_atoms)
        for a in self.key_atoms:
            a.tags.add("key")
        if detect_backbone:
            self.detect_backbone(to_center)
        self.rebuild()
Esempio n. 18
0
    def _build_ui(self):
        layout = QGridLayout()
        
        self.alchemy_tabs = QTabWidget()
        
        #substitute
        substitute_tab = QWidget()
        substitute_layout = QGridLayout(substitute_tab) 

        sublabel = QLabel("substituent name:")
        substitute_layout.addWidget(sublabel, 0, 0, Qt.AlignVCenter)
        
        self.subname = QLineEdit()
        # self.subname.setText("Et")
        sub_completer = NameCompleter(Substituent.list(), self.subname)
        self.subname.setCompleter(sub_completer)
        self.subname.setToolTip("name of substituent in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        substitute_layout.addWidget(self.subname, 0, 1, Qt.AlignVCenter)
        
        open_sub_lib = QPushButton("from library...")
        open_sub_lib.clicked.connect(self.open_sub_selector)
        substitute_layout.addWidget(open_sub_lib, 0, 2, Qt.AlignTop)        
        
        substitute_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter)
        
        self.close_previous_sub = QCheckBox()
        self.close_previous_sub.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_sub.setChecked(self.settings.modify)
        self.close_previous_sub.stateChanged.connect(self.close_previous_change)
        substitute_layout.addWidget(self.close_previous_sub, 1, 1, 1, 2, Qt.AlignTop)    
        
        substitute_layout.addWidget(QLabel("relax substituent:"), 2, 0, 1, 1, Qt.AlignVCenter)
        
        self.minimize = QCheckBox()
        self.minimize.setToolTip("spin the added substituents to try to minimize the LJ potential energy")
        self.minimize.setChecked(self.settings.minimize)
        substitute_layout.addWidget(self.minimize, 2, 1, 1, 1, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("guess previous substituent:"), 3, 0, 1, 1, Qt.AlignVCenter)
        
        self.guess_old = QCheckBox()
        self.guess_old.setToolTip("checked: leave the longest connected fragment in the residue\nunchecked: previous substituent must be selected")
        self.guess_old.setChecked(self.settings.guess)
        self.guess_old.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("guess", True if state == Qt.Checked else False))
        substitute_layout.addWidget(self.guess_old, 3, 1, 1, 2, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("new residue:"), 5, 0, 1, 1, Qt.AlignVCenter)

        self.new_residue = QCheckBox()
        self.new_residue.setToolTip("put the new substituent in its own residue instead\nof adding it to the residue of the old substituent")
        self.new_residue.setChecked(self.settings.new_residue)
        self.new_residue.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("new_residue", True if state == Qt.Checked else False))
        substitute_layout.addWidget(self.new_residue, 5, 1, 1, 2, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("use distance names:"), 4, 0, 1, 1, Qt.AlignVCenter)
        
        self.use_greek = QCheckBox()
        self.use_greek.setChecked(self.settings.use_greek)
        self.use_greek.setToolTip("indicate distance from point of attachment with atom name")
        substitute_layout.addWidget(self.use_greek, 4, 1, 1, 1, Qt.AlignTop)

        substitute_layout.addWidget(QLabel("change residue name:"), 6, 0, 1, 1, Qt.AlignVCenter)
        
        self.new_sub_name = QLineEdit()
        self.new_sub_name.setToolTip("change name of modified residues")
        self.new_sub_name.setPlaceholderText("leave blank to keep current")
        substitute_layout.addWidget(self.new_sub_name, 6, 1, 1, 2, Qt.AlignTop)

        substitute_button = QPushButton("substitute current selection")
        substitute_button.clicked.connect(self.do_substitute)
        substitute_layout.addWidget(substitute_button, 7, 0, 1, 3, Qt.AlignTop)
        self.substitute_button = substitute_button
        
        substitute_layout.setRowStretch(0, 0)
        substitute_layout.setRowStretch(1, 0)
        substitute_layout.setRowStretch(2, 0)
        substitute_layout.setRowStretch(3, 0)
        substitute_layout.setRowStretch(4, 0)
        substitute_layout.setRowStretch(5, 0)
        substitute_layout.setRowStretch(6, 0)
        substitute_layout.setRowStretch(7, 1)
        
        
        #map ligand
        maplig_tab = QWidget()
        maplig_layout = QGridLayout(maplig_tab)
        
        liglabel = QLabel("ligand name:")
        maplig_layout.addWidget(liglabel, 0, 0, Qt.AlignVCenter)
        
        self.ligname = QLineEdit()
        lig_completer = NameCompleter(Component.list(), self.ligname)
        self.ligname.setCompleter(lig_completer)
        self.ligname.setToolTip("name of ligand in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        maplig_layout.addWidget(self.ligname, 0, 1, Qt.AlignVCenter)
        
        open_lig_lib = QPushButton("from library...")
        open_lig_lib.clicked.connect(self.open_lig_selector)
        maplig_layout.addWidget(open_lig_lib, 0, 2, Qt.AlignTop)        
        
        maplig_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter)
        
        self.close_previous_lig = QCheckBox()
        self.close_previous_lig.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_lig.setChecked(self.settings.modify)
        self.close_previous_lig.stateChanged.connect(self.close_previous_change)
        maplig_layout.addWidget(self.close_previous_lig, 1, 1, 1, 2, Qt.AlignTop)

        maplig_button = QPushButton("swap ligand with selected coordinating atoms")
        maplig_button.clicked.connect(self.do_maplig)
        maplig_layout.addWidget(maplig_button, 2, 0, 1, 3, Qt.AlignTop)
        self.maplig_button = maplig_button

        start_structure_button = QPushButton("place in:")
        self.lig_model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_lig)
        maplig_layout.addWidget(start_structure_button, 3, 0, 1, 1, Qt.AlignTop)
        maplig_layout.addWidget(self.lig_model_selector, 3, 1, 1, 2, Qt.AlignTop)

        maplig_layout.setRowStretch(0, 0)
        maplig_layout.setRowStretch(1, 0)
        maplig_layout.setRowStretch(2, 0)
        maplig_layout.setRowStretch(3, 1)
        
        
        #close ring
        closering_tab = QWidget()
        closering_layout = QGridLayout(closering_tab)
        
        ringlabel = QLabel("ring name:")
        closering_layout.addWidget(ringlabel, 0, 0, Qt.AlignVCenter)
        
        self.ringname = QLineEdit()
        ring_completer = NameCompleter(Ring.list(), self.ringname)
        self.ringname.setCompleter(ring_completer)
        self.ringname.setToolTip("name of ring in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        closering_layout.addWidget(self.ringname, 0, 1, Qt.AlignVCenter)
        
        open_ring_lib = QPushButton("from library...")
        open_ring_lib.clicked.connect(self.open_ring_selector)
        closering_layout.addWidget(open_ring_lib, 0, 2, Qt.AlignTop)        
        
        closering_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter) 
        
        self.close_previous_ring = QCheckBox()
        self.close_previous_ring.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_ring.setChecked(self.settings.modify)
        self.close_previous_ring.stateChanged.connect(self.close_previous_change)
        closering_layout.addWidget(self.close_previous_ring, 1, 1, 1, 2, Qt.AlignTop)

        closering_layout.addWidget(QLabel("try multiple:"), 2, 0, 1, 1, Qt.AlignVCenter)

        self.minimize_ring = QCheckBox()
        self.minimize_ring.setToolTip("try to use other versions of this ring in the library to find the one that fits best")
        self.minimize_ring.setChecked(self.settings.minimize_ring)
        closering_layout.addWidget(self.minimize_ring, 2, 1, 1, 2, Qt.AlignTop)

        closering_layout.addWidget(QLabel("new residue name:"), 3, 0, 1, 1, Qt.AlignVCenter)
        
        self.new_ring_name = QLineEdit()
        self.new_ring_name.setToolTip("change name of modified residues")
        self.new_ring_name.setPlaceholderText("leave blank to keep current")
        closering_layout.addWidget(self.new_ring_name, 3, 1, 1, 2, Qt.AlignTop)

        closering_button = QPushButton("put a ring on current selection")
        closering_button.clicked.connect(self.do_fusering)

        closering_layout.addWidget(closering_button, 4, 0, 1, 3, Qt.AlignTop)
        self.closering_button = closering_button

        start_structure_button = QPushButton("place in:")
        self.ring_model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_ring)
        closering_layout.addWidget(start_structure_button, 5, 0, 1, 1, Qt.AlignTop)
        closering_layout.addWidget(self.ring_model_selector, 5, 1, 1, 2, Qt.AlignTop)

        closering_layout.setRowStretch(0, 0)
        closering_layout.setRowStretch(1, 0)
        closering_layout.setRowStretch(2, 0)
        closering_layout.setRowStretch(3, 0)
        closering_layout.setRowStretch(4, 0)
        closering_layout.setRowStretch(5, 1)


        #change element
        changeelement_tab = QWidget()
        changeelement_layout = QFormLayout(changeelement_tab)
        
        self.element = ElementButton("C", single_state=True)
        self.element.clicked.connect(self.open_ptable)
        changeelement_layout.addRow("element:", self.element)
        
        self.vsepr = QComboBox()
        self.vsepr.addItems([
            "do not change",                  # 0
            
            "linear (1 bond)",                # 1
            
            "linear (2 bonds)",               # 2 
            "trigonal planar (2 bonds)",      # 3
            "tetrahedral (2 bonds)",          # 4 
            
            "trigonal planar",                # 5
            "tetrahedral (3 bonds)",          # 6
            "T-shaped",                       # 7
            
            "trigonal pyramidal",             # 8
            "tetrahedral",                    # 9
            "sawhorse",                       #10
            "seesaw",                         #11
            "square planar",                  #12
            
            "trigonal bipyramidal",           #13
            "square pyramidal",               #14
            "pentagonal",                     #15
            
            "octahedral",                     #16
            "hexagonal",                      #17
            "trigonal prismatic",             #18
            "pentagonal pyramidal",           #19
            
            "capped octahedral",              #20
            "capped trigonal prismatic",      #21
            "heptagonal",                     #22
            "hexagonal pyramidal",            #23
            "pentagonal bipyramidal",         #24
            
            "biaugmented trigonal prismatic", #25
            "cubic",                          #26
            "elongated trigonal bipyramidal", #27
            "hexagonal bipyramidal",          #28
            "heptagonal pyramidal",           #29
            "octagonal",                      #30
            "square antiprismatic",           #31
            "trigonal dodecahedral",          #32
            
            "capped cube",                    #33
            "capped square antiprismatic",    #34
            "enneagonal",                     #35
            "heptagonal bipyramidal",         #36
            "hula-hoop",                      #37
            "triangular cupola",              #38
            "tridiminished icosahedral",      #39
            "muffin",                         #40
            "octagonal pyramidal",            #41
            "tricapped trigonal prismatic",   #42
        ])
        
        self.vsepr.setCurrentIndex(9)
        
        self.vsepr.insertSeparator(33)
        self.vsepr.insertSeparator(25)
        self.vsepr.insertSeparator(20)
        self.vsepr.insertSeparator(16)
        self.vsepr.insertSeparator(13)
        self.vsepr.insertSeparator(8)
        self.vsepr.insertSeparator(5)
        self.vsepr.insertSeparator(2)
        self.vsepr.insertSeparator(1)
        self.vsepr.insertSeparator(0)
        changeelement_layout.addRow("geometry:", self.vsepr)
        
        self.change_bonds = QCheckBox()
        self.change_bonds.setChecked(self.settings.change_bonds)
        changeelement_layout.addRow("adjust bond lengths:", self.change_bonds)
        
        change_element_button = QPushButton("change selected elements")
        change_element_button.clicked.connect(self.do_change_element)
        changeelement_layout.addRow(change_element_button)
        self.change_element_button = change_element_button

        start_structure_button = QPushButton("place in:")
        self.model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_atom)
        changeelement_layout.addRow(start_structure_button, self.model_selector)
        
        delete_atoms_button = QPushButton("delete selected atoms")
        delete_atoms_button.clicked.connect(self.delete_atoms)
        changeelement_layout.addRow(delete_atoms_button)

        self.alchemy_tabs.addTab(substitute_tab, "substitute")
        self.alchemy_tabs.addTab(maplig_tab, "swap ligand")
        self.alchemy_tabs.addTab(closering_tab, "fuse ring")
        self.alchemy_tabs.addTab(changeelement_tab, "change element")

        layout.addWidget(self.alchemy_tabs)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Esempio n. 19
0
class TestFromString(TestWithTimer):
    """
    these only get run if RDKit is installed
    molecules can be fetched from CATCVS, but there can be
    discrepencies that make these tests "fail"
    """

    COCH3 = Substituent("COCH3")
    NO2 = Substituent("NO2")
    benzene = Ring("benzene")
    chiral_geom = Geometry(
        os.path.join(prefix, "test_files", "chiral_ring.xyz")
    )

    def is_COCH3(self, sub, thresh=0.03):
        ref = TestFromString.COCH3
        ref.refresh_connected()
        sub.refresh_connected()
        ref.refresh_ranks()
        ref.refresh_ranks()
        ref.atoms = ref.reorder(start=ref.atoms[0])[0]
        sub.atoms = sub.reorder(start=sub.atoms[0])[0]
        self.assertTrue(
            validate(
                sub,
                ref,
                thresh=thresh,
                heavy_only=True,
                sort=False,
                debug=False,
            )
        )

    def is_NO2(self, sub):
        ref = TestFromString.NO2
        self.assertTrue(validate(sub, ref, thresh=2e-1))

    def test_substituent(self):
        try:
            import rdkit

            sub = Substituent.from_string(
                "acetyl", form="iupac", strict_use_rdkit=True
            )
            self.is_COCH3(sub)

            with self.assertLogs(Substituent.LOG, level="WARNING"):
                sub = Substituent.from_string(
                    "nitro", form="iupac", strict_use_rdkit=True
                )
                self.is_NO2(sub)

            sub = Substituent.from_string(
                "O=[N.]=O", form="smiles", strict_use_rdkit=True
            )
            self.is_NO2(sub)

            sub = Substituent.from_string(
                "O=[N]=O", form="smiles", strict_use_rdkit=True
            )
            self.is_NO2(sub)

        except (ImportError, ModuleNotFoundError):
            # I still want to test CACTVS things because sometimes they change stuff
            # that breaks our stuff
            if any(
                user == os.getenv("USER", os.getenv("USERNAME", False))
                for user in ["ajs99778", "normn"]
            ):
                sub = Substituent.from_string("acetyl", form="iupac")
                print(sub.write(outfile=False))
                self.is_COCH3(sub, thresh=0.3)

                sub = Substituent.from_string("nitro", form="iupac")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

                sub = Substituent.from_string("O=[N.]=O", form="smiles")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

                sub = Substituent.from_string("O=[N]=O", form="smiles")
                print(sub.write(outfile=False))
                self.is_NO2(sub)

            else:
                self.skipTest("RDKit not installed, CACTVS is not tested")

    def test_geometry(self):
        try:
            import rdkit

            geom = Geometry.from_string(
                "(1R,2R)-1-Chloro-2-methylcyclohexane", form="iupac"
            )
            ref = TestFromString.chiral_geom
            # really loose threshhold b/c rdkit can give a boat cyclohexane...
            self.assertTrue(validate(geom, ref, thresh=0.35, heavy_only=True))

        except (ImportError, ModuleNotFoundError):
            if any(
                user == os.getenv("USER", os.getenv("USERNAME", False))
                for user in ["ajs99778", "normn"]
            ):
                geom = Geometry.from_string(
                    "(1R,2R)-1-Chloro-2-methylcyclohexane", form="iupac"
                )
                ref = TestFromString.chiral_geom
                # really loose threshhold b/c rdkit can give a boat cyclohexane...
                self.assertTrue(
                    validate(geom, ref, thresh=0.35, heavy_only=True)
                )
            else:
                self.skipTest("RDKit not installed, CACTVS is not tested")

    def test_ring(self):
        try:
            import rdkit

            ring = Ring.from_string(
                "benzene", end_length=1, end_atom="C", form="iupac"
            )
            ref = self.benzene
            self.assertTrue(validate(ring, ref, thresh="loose"))

        except ImportError:
            if any(
                user == os.getenv("USER", os.getenv("USERNAME", False))
                for user in ["ajs99778", "normn"]
            ):
                ring = Ring.from_string(
                    "benzene", end_length=1, end_atom="C", form="iupac"
                )
                print(ring.comment)
                ref = self.benzene
                self.assertTrue(
                    validate(ring, ref, thresh="loose", debug=True)
                )

            else:
                self.skipTest("RDKit not installed, CACTVS is not tested")
Esempio n. 20
0
    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)
Esempio n. 21
0
    "--output",
    type=str,
    default=False,
    required=False,
    metavar="output destination",
    dest="outfile",
    help="output destination\n" +
    "$INFILE will be replaced with the name of the input file\n" +
    "Default: stdout"
)

args = substitute_parser.parse_args()

if args.list_avail:
    s = ""
    for i, name in enumerate(sorted(Substituent.list())):
        s += "%-20s" % name
        # if (i + 1) % 3 == 0:
        if (i + 1) % 1 == 0:
            s += "\n"

    print(s.strip())
    sys.exit(0)

for infile in glob_files(args.infile, parser=substitute_parser):
    if isinstance(infile, str):
        if args.input_format is not None:
            f = FileReader((infile, args.input_format, infile))
        else:
            f = FileReader(infile)
    else:
Esempio n. 22
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
Esempio n. 23
0
def substitute_list(session):
    s = ""
    for subname in Substituent.list():
        s += "%s\n" % subname

    session.logger.info(s.strip())
Esempio n. 24
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)
Esempio n. 25
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)
Esempio n. 26
0
 def test_copy(self):
     sub = Substituent("COCH3")
     sub = sub.copy(name="COCH3")
     self.is_COCH3(sub)
     return
Esempio n. 27
0
def main(argv):
    sterimol_parser = argparse.ArgumentParser(
        description=
        "calculate Boltzmann-weighted Sterimol parameters - see doi 10.1021/acscatal.8b04043",
        formatter_class=argparse.RawTextHelpFormatter)

    sterimol_parser.add_argument("infiles",
                                 metavar="input files",
                                 type=str,
                                 nargs="+",
                                 help="file containing coordinates and energy")

    sterimol_parser.add_argument("-if",
                                 "--input-format",
                                 type=str,
                                 default=None,
                                 choices=["log", "out", "dat"],
                                 dest="input_format",
                                 help="file format of input")

    sterimol_parser.add_argument(
        "-s",
        "--substituent-atom",
        type=str,
        required=True,
        dest="targets",
        help="substituent atom\n" +
        "1-indexed position of the starting position of the\n" +
        "substituent of which you are calculating sterimol\nparameters")

    sterimol_parser.add_argument(
        "-a",
        "--attached-to",
        type=str,
        required=True,
        dest="avoid",
        help="non-substituent atom\n" +
        "1-indexed position of the starting position of the atom\n" +
        "connected to the substituent of which you are calculating\n" +
        "sterimol parameters")

    sterimol_parser.add_argument(
        "-r",
        "--radii",
        type=str,
        default="bondi",
        choices=["bondi", "umn"],
        dest="radii",
        help="VDW radii to use in calculation\n" +
        "umn: main group vdw radii from J. Phys. Chem. A 2009, 113, 19, 5806–5812\n"
        + "    (DOI: 10.1021/jp8111556)\n" +
        "    transition metals are crystal radii from Batsanov, S.S. Van der Waals\n"
        + "    Radii of Elements. Inorganic Materials 37, 871–885 (2001).\n" +
        "    (DOI: 10.1023/A:1011625728803)\n" +
        "bondi: radii from J. Phys. Chem. 1964, 68, 3, 441–451 (DOI: 10.1021/j100785a001)\n"
        + "Default: bondi")

    sterimol_parser.add_argument(
        "-l",
        "--old-l",
        action="store_true",
        required=False,
        dest="old_L",
        help="approximate FORTRAN Sterimol method for determining L\n"
        "This is 0.4 + the ideal bond length for a target-H bond\n"
        "to outer VDW radii of atoms projected onto L-axis\n"
        "Default: L value is from VDW radii of target atom to outer\n"
        "VDW radii of atoms projected onto L-axis")

    sterimol_parser.add_argument("-t",
                                 "--temperature",
                                 type=float,
                                 default=298.15,
                                 required=False,
                                 dest="temperature",
                                 help="temperature in K\nDefault: 298.15")

    sterimol_parser.add_argument(
        "-f",
        "--frequency",
        action="store_true",
        default=False,
        required=False,
        dest="frequency",
        help="input files are frequency job output files\n"
        "additional average values will be calculated for ZPE, H, G, etc.")

    sterimol_parser.add_argument(
        "-w0",
        "--frequency-cutoff",
        type=float,
        default=100.0,
        required=False,
        dest="w0",
        help="cutoff frequency for quasi free energy corrections (1/cm)\n" +
        "Default: 100 cm^-1")

    sterimol_parser.add_argument("-v",
                                 "--verbose",
                                 action="store_true",
                                 default=False,
                                 required=False,
                                 dest="verbose",
                                 help="also print population")

    sterimol_parser.add_argument("-o",
                                 "--output",
                                 type=str,
                                 default=False,
                                 required=False,
                                 metavar="output destination",
                                 dest="outfile",
                                 help="output destination\n" +
                                 "Default: stdout")

    args = sterimol_parser.parse_args(args=argv)

    subs = []
    energies = {"E": []}
    if args.frequency:
        energies["E+ZPE"] = []
        energies["H(RRHO)"] = []
        energies["G(RRHO)"] = []
        energies["G(Quasi-RRHO)"] = []
        energies["G(Quasi-Harmonic)"] = []

    for infile in glob_files(args.infiles, parser=sterimol_parser):
        if args.input_format is not None:
            fr = FileReader((infile, args.input_format, infile),
                            just_geom=False)
        else:
            fr = FileReader(infile, just_geom=False)

        geom = Geometry(fr)
        target = args.targets
        avoid = args.avoid
        end = geom.find(avoid)[0]
        frag = geom.get_fragment(target, stop=end)
        sub = Substituent(frag, end=end, detect=False)
        subs.append(sub)

        nrg = fr.other["energy"]
        energies["E"].append(nrg)
        if args.frequency:
            co = CompOutput(fr)
            dE, dH, entropy = co.therm_corr(temperature=args.temperature)
            rrho_dG = co.calc_G_corr(v0=0,
                                     temperature=args.temperature,
                                     method="RRHO")
            qrrho_dG = co.calc_G_corr(v0=args.w0,
                                      temperature=args.temperature,
                                      method="QRRHO")
            qharm_dG = co.calc_G_corr(v0=args.w0,
                                      temperature=args.temperature,
                                      method="QHARM")
            energies["E+ZPE"].append(nrg + co.ZPVE)
            energies["H(RRHO)"].append(nrg + dH)
            energies["G(RRHO)"].append(nrg + rrho_dG)
            energies["G(Quasi-RRHO)"].append(nrg + qrrho_dG)
            energies["G(Quasi-Harmonic)"].append(nrg + qharm_dG)

    s = ""
    for nrg_type in energies:
        energies_arr = np.array(energies[nrg_type])
        energies_arr *= UNIT.HART_TO_KCAL

        if args.verbose and nrg_type == "E":
            s += "\t".join(["B1", "B2", "B3", "B4", "B5", "L", "file"])
            s += "\n"
            for f, sub in zip(args.infiles, subs):
                data = sub.sterimol(
                    radii=args.radii,
                    old_L=args.old_L,
                )
                s += "\t".join([
                    "%.2f" % data[x]
                    for x in ["B1", "B2", "B3", "B4", "B5", "L"]
                ])
                s += "\t%s\n" % f
        s += "weighted using %s:\n" % nrg_type
        data = Substituent.weighted_sterimol(
            subs,
            energies_arr,
            args.temperature,
            radii=args.radii,
            old_L=args.old_L,
        )
        if args.verbose:
            coeff = boltzmann_coefficients(energies_arr, args.temperature)
            coeff /= sum(coeff)
            coeff *= 100
            for f, c, e in zip(args.infiles, coeff, energies_arr):
                s += "%s  %.1f%% (%.1f kcal/mol)\n" % (f, c,
                                                       e - min(energies_arr))

        s += "\t".join(["B1", "B2", "B3", "B4", "B5", "L"])
        s += "\n"
        s += "\t".join(
            ["%.2f" % data[x] for x in ["B1", "B2", "B3", "B4", "B5", "L"]])
        s += "\n"
        s += "\n"

    if not args.outfile:
        print(s)
    else:
        with open(args.outfile, "w") as f:
            f.write(s)
Esempio n. 28
0
                "when no input file is given, stdin is read and a format must be specified"
            )

    geom = Geometry(f)

    target_list = []
    for sub in args.substitutions:
        ndx_targets = sub.split('=')[0]
        target_list.append(geom.find(ndx_targets))

    for i, sub in enumerate(args.substitutions):
        ndx_target = target_list[i]
        sub_name = '='.join(sub.split('=')[1:])

        for target in ndx_target:
            if args.form[0] == 'from_library':
                sub = Substituent(sub_name)
            elif args.form[0] in ['iupac', 'smiles']:
                sub = Substituent.from_string(sub_name, args.form[0])

            #replace old substituent with new substituent
            geom.substitute(sub, target)

            geom.refresh_connected()

    if args.outfile:
        FileWriter.write_xyz(geom, append=False, outfile=args.outfile[0])
    else:
        s = FileWriter.write_xyz(geom, append=False, outfile=False)
        print(s)
Esempio n. 29
0
    type=str,
    default=None,
    required=False,
    metavar="output destination",
    dest="outfile",
    help="output destination\n" +
    "$i in the filename will be replaced with conformer number\n" +
    "if a directory is given, default is \"conformer-$i.xyz\" in that directory\n"
    + "$INFILE will be replaced with the name of the input file\n" +
    "Default: stdout")

args = makeconf_parser.parse_args()

if args.list_avail:
    s = ""
    for i, name in enumerate(sorted(Substituent.list())):
        sub = Substituent(name)
        if sub.conf_num > 1:
            s += "%-20s" % name
            # if (i + 1) % 3 == 0:
            if (i + 1) % 1 == 0:
                s += "\n"

    print(s.strip())
    sys.exit(0)

detect_subs = False

s = ""

skipped = 0
Esempio n. 30
0
 def test_substituent(self):
     sub = Substituent("COCH3")
     self.json_tester(sub, self.sub_equal)