Пример #1
0
def get_matching_ligands(name):
    name_info = name
    coordinating_elements = None
    denticity = None
    if isinstance(name_info, str):
        if ("name:" not in name_info.lower()
                and "elements:" not in name_info.lower()
                and "denticity:" not in name_info.lower()):
            name_info = "^%s$" % name_info
        else:
            lig_info = name.split(":")
            for i, info in enumerate(lig_info):
                if info.lower() == "name" and i + 1 < len(lig_info):
                    name_info = name_info.replace(
                        "%s:%s" % (info, lig_info[i + 1]), "")
                    name_info = lig_info[i + 1]

                elif info.lower() == "elements" and i + 1 < len(lig_info):
                    name_info = name_info.replace(
                        "%s:%s" % (info, lig_info[i + 1]), "")
                    coordinating_elements = lig_info[i + 1].split(",")

                elif info.lower() == "denticity" and i + 1 < len(lig_info):
                    name_info = name_info.replace(
                        "%s:%s" % (info, lig_info[i + 1]), "")
                    denticity = int(lig_info[i + 1])

            if not name_info:
                name_info = None

    return Component.list(name_regex=name_info,
                          coordinating_elements=coordinating_elements,
                          denticity=denticity)
Пример #2
0
 def test_sub_rotate(self):
     geom = TestComponent.RQ_tBu.copy()
     geom.sub_rotate("4", angle=60)
     geom.sub_rotate("6", angle=60)
     geom.sub_rotate("5", angle=60)
     ref = Component(os.path.join(prefix, "ref_files", "sub_rotate.xyz"))
     self.assertTrue(validate(geom, ref, heavy_only=True))
Пример #3
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)
Пример #4
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))
Пример #5
0
 def refresh_selection(self):
     lig_names = []
     for row in self.lig_table.table.selectionModel().selectedRows():
         if self.lig_table.table.isRowHidden(row.row()):
             continue
         
         lig_names.append(row.data())
     
     if not lig_names:
         return
     
     self.nameWidget.setData(Qt.DisplayRole, ",".join(lig_names))
     comp = Component(lig_names[0])
     if len(comp.key_atoms) == 2:
         self.symmetryWidget.setEnabled(True)
         c2_symmetric = comp.c2_symmetric()
         if c2_symmetric:
             self.symmetryWidget.setCheckState(Qt.Checked)
         else:
             self.symmetryWidget.setCheckState(Qt.Unchecked)
     else:
         self.symmetryWidget.setEnabled(False)
Пример #6
0
    def _decode_geometry(self, obj):
        if ATDecoder.with_progress:
            print("Loading structure", obj["name"], " " * 50, end="\r")
        kwargs = {"structure": obj["atoms"]}
        for key in ["name", "comment"]:
            kwargs[key] = obj[key]
        geom = Geometry(**kwargs, refresh_connected=False, refresh_ranks=False)
        for i, connected in enumerate(obj["connectivity"]):
            for c in connected:
                geom.atoms[i].connected.add(geom.atoms[c])

        if obj["_type"] == "Component":
            key_atom_names = [a.name for a in obj["key_atoms"]]
            return Component(geom, key_atoms=key_atom_names)
        else:
            return geom
Пример #7
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]))
Пример #8
0
    def _decode_geometry(self, obj):
        kwargs = {"structure": obj["atoms"]}
        for key in ["name", "comment"]:
            kwargs[key] = obj[key]
        geom = Geometry(**kwargs, refresh_connected=False)
        for i, connected in enumerate(obj["connectivity"]):
            for c in connected:
                geom.atoms[i].connected.add(geom.atoms[c])

        if obj["_type"] == "Component":
            key_atom_names = [a.name for a in obj["key_atoms"]]
            return Component(geom,
                             key_atoms=key_atom_names,
                             refresh_connected=False)
        elif obj["_type"] == "Catalyst":
            conf_spec = {}
            for key, val in obj["conf_spec"].items():
                key = geom.find_exact(key)[0]
                conf_spec[key] = val
            kwargs = {"conf_spec": conf_spec}
            return Catalyst(geom, **kwargs, refresh_connected=False)
        else:
            return geom
Пример #9
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)
Пример #10
0
    def test_map_ligand(self):
        monodentate = Component(TestGeometry.monodentate)
        tridentate = Component(TestGeometry.tridentate)
        debug = False

        # import cProfile
        #
        # profile = cProfile.Profile()
        # profile.enable()
        """
        #TODO: get a reference file for this
        # two monodentate -> bidentate
        ptco4 = TestGeometry.ptco4.copy()
        ptco4.map_ligand('EDA', ["3", "5"])
        """

        # bidentate -> monodentate, none
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_1.xyz"))
        tm_simple = Geometry(TestGeometry.tm_simple)
        tm_simple.map_ligand(monodentate.copy(), ["35"])
        self.assertTrue(
            validate(tm_simple,
                     ref,
                     heavy_only=True,
                     thresh="loose",
                     debug=debug))

        # bidentate -> two monodentate
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_2.xyz"))
        tm_simple = Geometry(TestGeometry.tm_simple)
        tm_simple.map_ligand([monodentate.copy(), "ACN"], ["35", "36"])
        self.assertTrue(
            validate(tm_simple,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))

        # bidentate -> bidentate
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_3.xyz"))
        tm_simple = Geometry(TestGeometry.tm_simple)
        tm_simple.map_ligand("S-tBu-BOX", ["35", "36"])
        self.assertTrue(
            validate(tm_simple,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))

        # tridentate -> tridentate
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_4.xyz"))
        org_tri = Geometry(TestGeometry.org_tri)
        org_tri.map_ligand(tridentate, ["30", "28", "58"])
        self.assertTrue(
            validate(org_tri,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))

        # tridentate -> monodentate + bidentate -> tridentate
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_6.xyz"))
        org_tri = Geometry(TestGeometry.org_tri)
        org_tri.map_ligand(["EDA", "ACN"], ["30", "28", "58"])
        self.assertTrue(
            validate(org_tri,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))

        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_7.xyz"))
        org_tri = Geometry(os.path.join(prefix, "ref_files", "lig_map_6.xyz"))
        org_tri.map_ligand(tridentate, ["10", "11", "2"])
        self.assertTrue(
            validate(org_tri,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))

        # bidentate -> two bulky monodentate
        ref = Geometry(os.path.join(prefix, "ref_files", "lig_map_5.xyz"))
        tm_simple = Geometry(TestGeometry.tm_simple)
        tm_simple.map_ligand(["iPr-NC3C"] * 2, ["35", "36"])
        self.assertTrue(
            validate(tm_simple,
                     ref,
                     thresh="loose",
                     heavy_only=True,
                     debug=debug))
Пример #11
0
        if args.input_format is not None:
            infile = FileReader((f, args.input_format[0], None))
        else:
            infile = FileReader(f, just_geom=False)
    else:
        if args.input_format is not None:
            infile = FileReader(("from stdin", args.input_format[0], f))
        else:
            if len(sys.argv) >= 1:
                infile = FileReader(("from stdin", "xyz", f))

    geom = Geometry(infile)

    ligand = geom.get_fragment(args.key_atoms, stop=args.center)

    comp = Component(ligand, key_atoms=args.key_atoms, detect_backbone=False)

    angle = comp.cone_angle(
        center=geom.find(args.center),
        method=args.method,
        radii=args.radii,
        return_cones=args.print_cones,
    )

    if args.print_cones:
        angle, cones = angle

    if len(args.infile) > 1:
        s += "%20s:\t" % f

    s += "%4.1f\n" % angle
Пример #12
0
def main(argv):
    sterimol_parser = argparse.ArgumentParser(
        description=
        "calculate B1-B5, and L sterimol parameters for ligands - see Verloop, A. and Tipker, J. (1976), Use of linear free energy related and other parameters in the study of fungicidal selectivity. Pestic. Sci., 7: 379-390.",
        formatter_class=argparse.RawTextHelpFormatter)

    sterimol_parser.add_argument("infile",
                                 metavar="input file",
                                 type=str,
                                 nargs="*",
                                 default=[sys.stdin],
                                 help="a coordinate file")

    sterimol_parser.add_argument(
        "-if",
        "--input-format",
        type=str,
        default=None,
        choices=read_types,
        dest="input_format",
        help="file format of input\nxyz is assumed if input is stdin")

    sterimol_parser.add_argument(
        "-k",
        "--key-atoms",
        type=str,
        required=True,
        dest="key",
        help="1-indexed position of the ligand's coordinating atoms")

    sterimol_parser.add_argument("-c",
                                 "--center-atom",
                                 type=str,
                                 required=True,
                                 dest="center",
                                 help="atom the ligand is coordinated to")

    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\n(DOI: 10.1021/j100785a001)\n"
        "Default: bondi")

    sterimol_parser.add_argument(
        "-bl",
        "--bisect-L",
        action="store_true",
        required=False,
        dest="bisect_L",
        help="L axis will bisect (or analogous for higher denticity\n"
        "ligands) the L-M-L angle\n"
        "Default: center to centroid of key atoms")

    sterimol_parser.add_argument(
        "-al",
        "--at-L",
        default=[None],
        dest="L_value",
        type=lambda x: [float(v) for v in x.split(",")],
        help="get widths at specific L values (comma-separated)\n"
        "can be used for Sterimol2Vec parameters\n"
        "Default: use the entire ligand",
    )

    sterimol_parser.add_argument(
        "-v",
        "--vector",
        action="store_true",
        required=False,
        dest="vector",
        help=
        "print Chimera/ChimeraX bild file for vectors instead of parameter values"
    )

    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)

    s = ""
    if not args.vector:
        s += "B1\tB2\tB3\tB4\tB5\tL\tfile\n"

    for infile in glob_files(args.infile, parser=sterimol_parser):
        if isinstance(infile, str):
            if args.input_format is not None:
                f = FileReader((infile, args.input_format, infile))
            else:
                f = FileReader(infile)
        else:
            if args.input_format is not None:
                f = FileReader(("from stdin", args.input_format, infile))
            else:
                f = FileReader(("from stdin", "xyz", infile))

        geom = Geometry(f, refresh_ranks=False)
        comp = Component(
            geom.get_fragment(args.key, stop=args.center),
            to_center=geom.find(args.center),
            key_atoms=args.key,
            detect_backbone=False,
        )
        for val in args.L_value:
            data = comp.sterimol(
                to_center=geom.find(args.center),
                return_vector=args.vector,
                radii=args.radii,
                bisect_L=args.bisect_L,
                at_L=val,
            )

            if args.vector:
                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)
            else:
                s += "%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%s\n" % (
                    data["B1"],
                    data["B2"],
                    data["B3"],
                    data["B4"],
                    data["B5"],
                    data["L"],
                    infile,
                )

    if not args.outfile:
        print(s)
    else:
        with open(args.outfile, "w") as f:
            f.write(s)
Пример #13
0
        key_atoms = args.ligand.split("=")[0]
        lig_names = [
            l for l in "=".join(args.ligand.split("=")[1:]).split(",")
        ]

    else:
        lig_names = [
            l for l in "=".join(args.ligand.split("=")[1:]).split(",")
        ]
        key_atoms = []

    for lig_names in [
            get_matching_ligands(lig_name) for lig_name in lig_names
    ]:
        for lig_name in lig_names:
            ligands = [Component(lig_name)]
            cat_copy = cat.copy()

            if key_atoms != []:
                key = cat_copy.find(key_atoms)
            else:
                key = []

            original_ligands = [l for l in ligands]

            lig_keys = sum([len(ligand.key_atoms) for ligand in ligands])
            while len(key) > lig_keys:
                ligands.extend(l.copy() for l in original_ligands)
                lig_keys += sum(
                    [len(ligand.key_atoms) for ligand in original_ligands])
Пример #14
0
    def do_maplig(self):
        lignames = self.ligname.text()
        selection = selected_atoms(self.session)
        
        if len(selection) < 1:
            raise RuntimeWarning("nothing selected")
        
        models = {}
        for atom in selection:
            if atom.structure not in models:
                models[atom.structure] = [AtomSpec(atom.atomspec)]
            else:
                models[atom.structure].append(AtomSpec(atom.atomspec))        
        
        first_pass = True
        new_structures = []
        for ligname in lignames.split(','):
            ligname = ligname.strip()
            lig = Component(ligname)
            for model in models:
                if self.close_previous_bool and first_pass:
                    rescol = ResidueCollection(model)
                elif self.close_previous_bool and not first_pass:
                    raise RuntimeError("only the first model can be replaced")
                else:
                    model_copy = model.copy()
                    rescol = ResidueCollection(model_copy)
                    for i, atom in enumerate(model.atoms):
                        rescol.atoms[i].atomspec = atom.atomspec
                        rescol.atoms[i].add_tag(atom.atomspec)
                        rescol.atoms[i].chix_atom = atom

                target = rescol.find(models[model])
                if len(target) % len(lig.key_atoms) == 0:
                    k = 0
                    ligands = []
                    while k != len(target):
                        res_lig = ResidueCollection(lig.copy(), comment=lig.comment)
                        res_lig.parse_comment()
                        res_lig = Component(res_lig, key_atoms = ",".join([str(k + 1) for k in res_lig.other["key_atoms"]]))
                        ligands.append(res_lig)
                        k += len(lig.key_atoms)
                else:
                    raise RuntimeError("number of key atoms no not match: %i now, new ligand has %i" % (len(target), len(lig.key_atoms)))
                
                rescol.map_ligand(ligands, target)

                for center_atom in rescol.center:
                    center_atom.connected = set([])
                    for atom in rescol.atoms:
                        if atom not in rescol.center:
                            if center_atom.is_connected(atom):
                                atom.connected.add(center_atom)
                                center_atom.connected.add(atom)
                
                if self.close_previous_bool:    
                    rescol.update_chix(model)
                else:
                    struc = rescol.get_chimera(self.session)
                    new_structures.append(struc)
            
            first_pass = False
        
        if not self.close_previous_bool:
            self.session.models.add(new_structures)
Пример #15
0
 def test_component(self):
     lig = Component(TestJSON.lig)
     self.json_tester(lig, self.component_equal)
Пример #16
0
    def map_ligand(self, ligands, old_keys, minimize=True):
        """
        Maps new ligand according to key_map
        Parameters:
        :ligand:    the name of a ligand in the ligand library
        :old_keys:  the key atoms of the old ligand to map to
        """
        def get_rotation(old_axis, new_axis):
            w = np.cross(old_axis, new_axis)
            angle = np.dot(old_axis, new_axis)
            angle /= np.linalg.norm(old_axis)
            angle /= np.linalg.norm(new_axis)
            # occasionally there will be some round-off errors,
            # so let's fix those before we take arccos
            if angle > 1 + 10**-12 or angle < -1 - 10**-12:
                # and check to make sure we aren't covering something
                # more senister up...
                raise ValueError("Bad angle value for arccos():", angle)
            elif angle > 1:
                angle = 1.0
            elif angle < -1:
                angle = -1.0
            angle = np.arccos(angle)
            return w, -1 * angle

        def map_1_key(self, ligand, old_key, new_key):
            # align new key to old key
            shift = new_key.bond(old_key)
            ligand.coord_shift(shift)
            # rotate ligand
            targets = old_key.connected - set(self.center)
            old_axis = self.COM(targets=targets) - old_key.coords
            new_axis = ligand.COM(targets=new_key.connected) - new_key.coords
            w, angle = get_rotation(old_axis, new_axis)
            ligand.rotate(w, angle, center=new_key)
            return ligand

        def map_2_key(old_ligand, ligand, old_keys, new_keys, rev_ang=False):
            # align COM of key atoms
            center = old_ligand.COM(targets=old_keys)
            shift = old_ligand.COM(targets=old_keys) - ligand.COM(
                targets=new_keys)
            ligand.coord_shift(shift)

            # rotate for best overlap
            old_axis = old_keys[0].bond(old_keys[1])
            new_axis = new_keys[0].bond(new_keys[1])
            w, angle = get_rotation(old_axis, new_axis)
            ligand.rotate(w, angle, center=center)

            # bend around key axis
            old_con = set([])
            for k in old_keys:
                for c in k.connected:
                    old_con.add(c)
            old_vec = old_ligand.COM(targets=old_con) - center

            new_con = set([])
            for k in new_keys:
                for c in k.connected:
                    new_con.add(c)
            new_vec = ligand.COM(targets=new_con) - center

            w, angle = get_rotation(old_vec, new_vec)
            if rev_ang:
                angle = -angle
            ligand.rotate(old_axis, -angle, center=center)

        def map_rot_frag(frag, a, b, ligand, old_key, new_key):
            old_vec = old_key.coords - b.coords
            new_vec = new_key.coords - b.coords
            axis, angle = get_rotation(old_vec, new_vec)
            ligand.rotate(b.bond(a), -1 * angle, targets=frag, center=b.coords)

            for c in new_key.connected:
                con_frag = ligand.get_fragment(new_key, c)
                if len(con_frag) > len(frag):
                    continue
                old_vec = self.COM(targets=old_key.connected)
                old_vec -= old_key.coords
                new_vec = ligand.COM(targets=new_key.connected)
                new_vec -= new_key.coords
                axis, angle = get_rotation(old_vec, new_vec)
                ligand.rotate(
                    c.bond(new_key),
                    -1 * angle,
                    targets=con_frag,
                    center=new_key.coords,
                )

        def map_more_key(self, old_ligand, ligand, old_keys, new_keys):
            # backbone fragments separated by rotatable bonds
            frag_list = ligand.get_frag_list(ligand.backbone, max_order=1)

            # get key atoms on each side of rotatable bonds
            key_count = {}
            for frag, a, b in frag_list:
                tmp = []
                for i in frag:
                    if i not in ligand.key_atoms:
                        continue
                    tmp += [i]
                if len(tmp) not in key_count:
                    key_count[len(tmp)] = [(frag, a, b)]
                else:
                    key_count[len(tmp)] += [(frag, a, b)]

            partial_map = False
            mapped_frags = []
            for k in sorted(key_count.keys(), reverse=True):
                if k == 2 and not partial_map:
                    frag, a, b = key_count[k][0]
                    ok = []
                    nk = []
                    for i, n in enumerate(new_keys):
                        if n not in frag:
                            continue
                        ok += [old_keys[i]]
                        nk += [n]
                    map_2_key(old_ligand, ligand, ok, nk, rev_ang=True)
                    partial_map = True
                    mapped_frags += [frag]
                    continue
                if k == 1 and not partial_map:
                    frag, a, b = key_count[k][0]
                    for i, n in enumerate(new_keys):
                        if n not in frag:
                            continue
                        map_1_key(self, ligand, n, old_keys[i])
                        partial_map = True
                        mapped_frags += [frag]
                        break
                    continue
                if k == 1 and partial_map:
                    for frag, a, b in key_count[k]:
                        for i, n in enumerate(new_keys):
                            if n not in frag:
                                continue
                            map_rot_frag(frag, a, b, ligand, old_keys[i], n)
                            mapped_frags += [frag]
                            break
            return

        old_keys = self.find(old_keys)

        if not hasattr(ligands, "__iter__") or isinstance(ligands, str):
            ligands = [ligands]

        new_keys = []
        for i, ligand in enumerate(ligands):
            if not isinstance(ligand, Component):
                ligand = Component(ligand)
                ligands[i] = ligand
            ligand.refresh_connected()
            new_keys += ligand.key_atoms

        if len(old_keys) != len(new_keys):
            raise ValueError("Cannot map ligand. " +
                             "Differing number of key atoms. " + "Old keys: " +
                             ",".join([i.name for i in old_keys]) + "; " +
                             "New keys: " +
                             ",".join([i.name for i in new_keys]))

        old_ligands = []
        for k in old_keys:
            for c in self.components["ligand"]:
                if k in c.atoms:
                    old_ligands += [c]

        start = 0
        end = None
        for i, ligand in enumerate(ligands):
            end = start + len(ligand.key_atoms)
            if len(ligand.key_atoms) == 1:
                map_1_key(self, ligand, old_keys[start], new_keys[start])
            elif len(ligand.key_atoms) == 2:
                map_2_key(
                    old_ligands[start],
                    ligand,
                    old_keys[start:end],
                    new_keys[start:end],
                )
            else:
                map_more_key(
                    self,
                    old_ligands[start],
                    ligand,
                    old_keys[start:end],
                    new_keys[start:end],
                )

            for l in ligand.atoms:
                l.name = old_keys[start].name + "." + l.name
            start = end

        # remove old
        for ol in old_ligands:
            try:
                self.components["ligand"].remove(ol)
            except ValueError:
                continue
            for atom in ol.atoms:
                if atom in self.conf_spec:
                    del self.conf_spec[atom]
            for atom in self.atoms:
                if atom.connected & set(ol.atoms):
                    atom.connected = atom.connected - set(ol.atoms)

        # add new
        for ligand in ligands:
            self.components["ligand"] += [ligand]
            for sub in ligand.substituents:
                if sub.conf_num is None or sub.conf_num <= 1:
                    continue
                self.conf_spec[sub.atoms[0]] = [1, []]
        self.rebuild()
        self.remove_clash()
        if minimize:
            self.minimize()
Пример #17
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)
Пример #18
0
    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)
Пример #19
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)
Пример #20
0
class TestCatalyst(TestWithTimer):
    # C:34 L:35-93 K:1,2 F:1-34;1-2;2-34;2-3;3-34
    tm_simple = Catalyst(prefix + "test_files/catalysts/tm_single-lig.xyz")
    tm_multi = Catalyst(prefix + "test_files/catalysts/tm_multi-lig.xyz")
    org_1 = Catalyst(prefix + "test_files/catalysts/org_1.xyz")
    org_tri = Catalyst(prefix + "test_files/catalysts/org_tri.xyz")
    catalysts = [tm_simple, tm_multi, org_1, org_tri]

    monodentate = Component(prefix + "test_files/ligands/ACN.xyz")
    bidentate = Component(prefix + "test_files/ligands/S-tBu-BOX.xyz")
    tridentate = Component(prefix + "test_files/ligands/squaramide.xyz")

    def validate(self, test, ref, thresh=None):
        if thresh is None:
            thresh = rmsd_tol(ref)
        t_el = sorted([t.element for t in test.atoms])
        r_el = sorted([r.element for r in ref.atoms])
        if len(t_el) != len(r_el):
            return False

        for t, r in zip(t_el, r_el):
            if t != r:
                return False

        rmsd = ref.RMSD(test, align=True)
        return rmsd < thresh

    def test_init(self):
        self.assertRaises(IOError, Catalyst,
                          prefix + "test_files/R-Quinox-tBu3.xyz")

    def test_detect_components(self):
        def tester(ref, test):
            for comp, r in zip(test.components["ligand"], ref["ligand"]):
                good = True
                for i, j in zip(sorted([float(a) for a in comp.atoms]), r):
                    if i != j:
                        good = False
                self.assertTrue(good)
            for comp, r in zip(test.components["substrate"], ref["substrate"]):
                good = True
                for i, j in zip(sorted([float(a) for a in comp.atoms]), r):
                    if i != j:
                        good = False
                self.assertTrue(good)
            return

        def printer(test):
            print(test.comment)
            for name, component in test.components.items():
                print(name)
                for comp in component:
                    print("\t", sorted([float(a) for a in comp.atoms]))
            return

        args = []
        ref = {}

        ref["ligand"] = [[float(i) for i in range(35, 94)]]
        ref["substrate"] = [[
            1.0, 2.0, 4.0, 5.0, 6.0, 7.0, 10.0, 11.0, 12.0, 15.0, 16.0, 17.0
        ]]
        ref["substrate"] += [[
            3.0,
            8.0,
            9.0,
            13.0,
            14.0,
            18.0,
            19.0,
            20.0,
            21.0,
            22.0,
            23.0,
            24.0,
            25.0,
            26.0,
            27.0,
            28.0,
            29.0,
            30.0,
            31.0,
            32.0,
            33.0,
        ]]
        args += [(deepcopy(ref), TestCatalyst.tm_simple)]

        ref["ligand"] = [[9.0], [10.0]]
        ref["ligand"] += [[float(i) for i in range(11, 23)]]
        ref["ligand"] += [[float(i) for i in range(23, 93)]]
        ref["substrate"] = [[float(i) for i in range(1, 8)]]
        args += [(deepcopy(ref), TestCatalyst.tm_multi)]

        ref["ligand"] = [[float(i) for i in range(44, 144)]]
        ref["substrate"] = [[float(i) for i in range(1, 44)]]
        args += [(deepcopy(ref), TestCatalyst.org_1)]

        for a in args:
            tester(*a)

    def test_map_ligand(self):
        monodentate = TestCatalyst.monodentate
        tridentate = TestCatalyst.tridentate

        tm_simple = TestCatalyst.tm_simple.copy()
        tm_simple.map_ligand([monodentate, "ACN"], ["35", "36"])
        self.assertTrue(
            self.validate(tm_simple,
                          Geometry(prefix + "ref_files/lig_map_2.xyz")))

        tm_simple = TestCatalyst.tm_simple.copy()
        tm_simple.map_ligand("S-tBu-BOX", ["35", "36"])
        self.assertTrue(
            self.validate(tm_simple,
                          Geometry(prefix + "ref_files/lig_map_3.xyz")))

        org_tri = TestCatalyst.org_tri.copy()
        org_tri.map_ligand(tridentate, ["30", "28", "58"])
        self.assertTrue(
            self.validate(org_tri,
                          Geometry(prefix + "ref_files/lig_map_4.xyz")))

        tm_simple = TestCatalyst.tm_simple.copy()
        tm_simple.map_ligand(monodentate, ["35"])
        self.assertTrue(
            self.validate(tm_simple,
                          Geometry(prefix + "ref_files/lig_map_1.xyz")))

    def test_conf_spec(self):
        test_str = ""
        count = 0
        for cat in TestCatalyst.catalysts:
            count += 1
            for sub in sorted(cat.get_substituents()):
                start = sub.atoms[0]
                conf_num = cat.conf_spec[start]
                test_str += "{} {} {} {}\n".format(start.name, sub.name,
                                                   sub.conf_num, conf_num)
            test_str += "\n"
        with open(prefix + "ref_files/conf_spec.txt") as f:
            self.assertEqual(test_str, f.read())

    def test_fix_comment(self):
        cat = TestCatalyst.tm_simple.copy()
        cat.write("tmp")
        self.assertEqual(cat.comment,
                         "C:34 K:1,5 L:35-93 F:1-2;1-34;2-13;2-34;13-34")
        cat.substitute("Me", "4")
        self.assertEqual(cat.comment,
                         "C:37 K:1,5 L:38-96 F:1-2;1-37;2-16;2-37;16-37")

    def test_next_conformer(self):
        total = 24 + 32 + 4
        big_count = 0
        count = 0
        for cat in TestCatalyst.catalysts:
            if cat == TestCatalyst.org_1:
                continue
            if count:
                big_count += count
            count = 1
            cat.remove_clash()
            while True:
                if not cat.next_conformer():
                    break
                count += 1
                utils.progress_bar(big_count + count, total)
            subs = sorted(
                [cat.find_substituent(c).name for c in cat.conf_spec.keys()])
            if cat == TestCatalyst.tm_simple:
                self.assertListEqual(subs, sorted(["tBu", "tBu", "tBu", "Et"]))
                self.assertEqual(count, 24)
            elif cat == TestCatalyst.tm_multi:
                self.assertListEqual(subs,
                                     sorted(["Ph", "Ph", "Ph", "Ph", "CHO"]))
                self.assertEqual(count, 32)
            elif cat == TestCatalyst.org_tri:
                self.assertListEqual(subs, sorted(["Ph", "OMe"]))
                self.assertEqual(count, 4)

        utils.clean_progress_bar()
Пример #21
0
class TestComponent(TestWithTimer):
    # simple geometries
    benz = Component(os.path.join(prefix, "test_files", "benzene.xyz"))
    benz_Cl = Component(os.path.join(prefix, "test_files", "benzene_4-Cl.xyz"))
    benz_NO2_Cl = Component(
        os.path.join(prefix, "test_files", "benzene_1-NO2_4-Cl.xyz")
    )
    benz_OH_Cl = Component(
        os.path.join(prefix, "test_files", "benzene_1-OH_4-Cl.xyz")
    )
    benz_Ph_Cl = Component(
        os.path.join(prefix, "test_files", "benzene_1-Ph_4-Cl.xyz")
    )
    Et_NO2 = Component(os.path.join(prefix, "test_files", "Et_1-NO2.xyz"))
    pent = Component(os.path.join(prefix, "test_files", "pentane.xyz"))

    # ligands
    RQ_tBu = Component(os.path.join(prefix, "test_files", "R-Quinox-tBu3.xyz"))
    for a in RQ_tBu.find("P"):
        a.add_tag("key")
    tri = Component(
        os.path.join(prefix, "test_files", "ligands", "squaramide.xyz")
    )

    def is_member(self, valid, test):
        for a in valid:
            try:
                test.remove(a)
            except KeyError:
                return False
        if len(test) == 0:
            return True
        else:
            return False

    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)

    def test_detect_backbone(self):
        geom = TestComponent.RQ_tBu.copy()

        backbone = geom.find("1,2,7-20")
        Me = geom.find("3,21-23")
        tBu = geom.find("4-6,24-59")

        try:
            test_Me = set(geom.find(["Me", "CH3"]))
            test_tBu = set(geom.find("tBu"))
            test_backbone = set(geom.find("backbone"))
        except LookupError:
            self.assertTrue(False)

        self.assertTrue(self.is_member(Me, test_Me))
        self.assertTrue(self.is_member(tBu, test_tBu))
        self.assertTrue(self.is_member(backbone, test_backbone))

    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))

    def test_sub_rotate(self):
        geom = TestComponent.RQ_tBu.copy()
        geom.sub_rotate("4", angle=60)
        geom.sub_rotate("6", angle=60)
        geom.sub_rotate("5", angle=60)
        ref = Component(os.path.join(prefix, "ref_files", "sub_rotate.xyz"))
        self.assertTrue(validate(geom, ref, heavy_only=True))
Пример #22
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
Пример #23
0
    def detect_components(self, debug=False):
        self.components = {}
        self.center = []

        # get center
        lig_assigned = False
        center_max = None
        for a in self.atoms:
            if "ligand" not in a.tags and a.element in TMETAL.keys():
                # detect transition metal center
                if a not in self.center:
                    self.center += [a]
                a.add_tag("center")
            if "center" in a.tags:
                # center provided by comment line in xyz file
                if a not in self.center:
                    self.center += [a]
            if not lig_assigned and "ligand" in a.tags:
                lig_assigned = True
            if a in self.center:
                if center_max is None or center_max < float(a):
                    center_max = float(a)

        if not lig_assigned and len(self.center) < 1:
            msg = (
                "Non-transition metal centered catalysts must either have " +
                "active centers or ligand atoms specified in the comment " +
                "line of the XYZ input file")
            raise IOError(msg)

        # label ligand and substrate
        lig = []
        subst = []
        for a in self.atoms:
            if lig_assigned:
                if "ligand" in a.tags:
                    lig += [a]
            elif float(a) > center_max:
                a.add_tag("ligand")
                lig += [a]

        for a in self.atoms:
            if "ligand" not in a.tags and "center" not in a.tags:
                a.add_tag("substrate")
                subst += [a]
        if debug:
            print("lig", [a.name for a in lig])
            print("sub", [a.name for a in subst])
            print("center", [a.name for a in self.center])

        # label key atoms:
        for i, a in enumerate(lig):
            if "key_atoms" not in self.other:
                break
            if i in self.other["key_atoms"]:
                a.add_tag("key")
        else:
            del self.other["key_atoms"]

        # get components
        if len(self.center) > 0:
            self.components["ligand"] = self.detect_fragments(lig)
            self.components["substrate"] = self.detect_fragments(subst)
        else:
            self.components["ligand"] = self.detect_fragments(lig, subst)
            self.components["substrate"] = self.detect_fragments(subst, lig)
        # rename
        for i, lig in enumerate(self.components["ligand"]):
            name = self.name + "_lig-{}".format(lig[0].name)
            self.components["ligand"][i] = Component(lig,
                                                     name,
                                                     refresh_connected=False)
        for i, sub in enumerate(self.components["substrate"]):
            name = self.name + "_sub-{}".format(sub[0].name)
            self.components["substrate"][i] = Component(
                sub, name, refresh_connected=False)
        self.rebuild()
        return
Пример #24
0
class TestComponent(TestWithTimer):
    # simple geometries
    benz = Component(prefix + "test_files/benzene.xyz")
    benz_Cl = Component(prefix + "test_files/benzene_4-Cl.xyz")
    benz_NO2_Cl = Component(prefix + "test_files/benzene_1-NO2_4-Cl.xyz")
    benz_OH_Cl = Component(prefix + "test_files/benzene_1-OH_4-Cl.xyz")
    benz_Ph_Cl = Component(prefix + "test_files/benzene_1-Ph_4-Cl.xyz")
    Et_NO2 = Component(prefix + "test_files/Et_1-NO2.xyz")
    pent = Component(prefix + "test_files/pentane.xyz")

    # ligands
    RQ_tBu = Component(prefix + "test_files/R-Quinox-tBu3.xyz")
    for a in RQ_tBu.find("P"):
        a.add_tag("key")
    tri = Component(prefix + "test_files/ligands/squaramide.xyz")

    def is_member(self, valid, test):
        for a in valid:
            try:
                test.remove(a)
            except KeyError:
                return False
        if len(test) == 0:
            return True
        else:
            return False

    def is_same(self, valid, test):
        # same number of atoms
        if len(valid.atoms) != len(test.atoms):
            return False
        # of same elements
        tmp = [a.element for a in test.atoms]
        for e in [a.element for a in valid.atoms]:
            try:
                tmp.remove(e)
            except ValueError:
                return False
        # with reasonable rmsd
        if valid.RMSD(test, sort=True) > 10**-4:
            return False
        return True

    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))

    def test_detect_backbone(self):
        geom = TestComponent.RQ_tBu.copy()
        geom.detect_backbone()

        backbone = geom.find("1,2,7-20")
        Me = geom.find("3,21-23")
        tBu = geom.find("4-6,24-59")

        try:
            test_Me = set(geom.find("Me"))
            test_tBu = set(geom.find("tBu"))
            test_backbone = set(geom.find("backbone"))
        except LookupError:
            self.assertTrue(False)

        self.assertTrue(self.is_member(Me, test_Me))
        self.assertTrue(self.is_member(tBu, test_tBu))
        self.assertTrue(self.is_member(backbone, test_backbone))

    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)