예제 #1
0
 def test_copy(self):
     sub = Substituent("COCH3")
     sub = sub.copy(name="COCH3")
     self.is_COCH3(sub)
     return
예제 #2
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)