示例#1
0
    def metarun(self):

        results = adfaccurateembeddingresults()

        # run supermolecular calculation
        self.settings.set_lmo(True)
        self.settings.set_save_tapes([21, 10])
        self.settings.set_exactdensity(True)

        results.super = adfsinglepointjob(self.supermol, self.basis, settings=self.settings).run()

        # orbital localization is turned off for the other calculations
        self.settings.set_lmo(False)

        # fragment density is obtained from frag1 and frag2
        results.frag1 = adfsinglepointjob(self.frag1, self.basis, settings=self.settings).run()
        results.frag2 = adfsinglepointjob(self.frag2, self.basis, settings=self.settings).run()

        # get localized orbital densities for subsystems 1 and 2

        self.assign_locorbs_to_fragments(results)

        adfGrid = adfgrid(results.super)

        sys1_dens = results.super.get_locorb_density(grid=adfGrid, orbs=results.locorb_set1)
        sys1_dens.prop = 'density scf'

        # results.sys2_dens = results.super.get_locorb_density(grid=adfGrid, orbs=results.locorb_set2)
        # results.sys2_dens.prop = 'density scf'

        print 'reference calculations finished'

        #  Now comes the potential reconstruction:

        self.settings.set_ncycles(self.cyc)

        job = adffragmentsjob([fragment(results.frag1, [self.frag1])], self.basis, settings=self.settings)
        potjob = adfpotentialjob(job, sys1_dens, potoptions=self.potoptions)

        print 'Running potential reconstruction job ... '
        results.pot = potjob.run()

        # Calculate the error in the density

        # the reconstructed density
        rec_dens = results.pot.get_density(grid=adfGrid)

        # the difference density
        diff_dens = sys1_dens - rec_dens

        # calculate integral over the difference density
        results.dens_error = diff_dens.integral(func=lambda x: abs(x))

        return results
示例#2
0
    def prepare_frags(self):
        """
        Prepare fragments (make single point runs for molecules).

        @note:
            we cannot use symmetry in the fragments if we are interested in the
            difference density -> otherwise they will be rotated

        @returns: The results of single point runs for a list of molecules
        @rtype: tuple of list of adfsinglepointresults and fragments
        """

        r_frags = []
        frags = []
        self.adfsettings.set_occupations(None)
        for mol in self.molecules:
            mol.set_symmetry('NOSYM')
            r = adfsinglepointjob(mol=mol,
                                  basis=self.basis,
                                  core=self.core,
                                  settings=self.adfsettings,
                                  options=['NOSYMFIT']).run()
            r_frags.append(r)
            if self.settings.usebasis == 'True':
                frags.append(
                    fragment(r,
                             mol,
                             fdeoptions={
                                 "USEBASIS": "",
                                 "RELAX": "",
                                 "XC": " GGA PBE"
                             }))
            else:
                frags.append(fragment(r, mol, fdeoptions={"XC": "GGA PBE"}))

        return frags, r_frags
示例#3
0
    def metarun(self):

        import copy

        print "-" * 50
        print "Beginning WFT-in-DFT embedding calculation "
        print
        print "Performing %i RELAX-cycles" % self._cycles
        print

        # first we do a normal DFT-in-DFT run
        initial_frags = copy.deepcopy(self._frags)
        for f in initial_frags:
            # rename RELAX option to RELAXsave so that we can handle it, instead of ADF
            if f.has_fdeoption("RELAX"):
                f.delete_fdeoption("RELAX")
                f.add_fdeoption("RELAXsave", "")

        # pylint: disable-msg=W0142
        dftindft_res = adffragmentsjob(initial_frags, **self._adfoptions).run()

        # now construct a new list of fragments
        frags = copy.deepcopy(fragmentlist(initial_frags.get_frozen_frags()))
        for f in frags:
            if f.has_fdeoption("RELAXsave"):
                f.isfrozen = False
        dirac_frag = fragment(dftindft_res, dftindft_res.get_nonfrozen_molecule(), subfrag="active", isfrozen=True)
        dirac_mol = dirac_frag.get_total_molecule()
        frags.append(dirac_frag)

        # now run a DFT-in-DFT calculation with the Dirac-fragment frozen,
        # and all DFT-relax fragments nonfrozen in order to get a grid that
        # can be used for all of them
        # (the Dirac step is expensive, so we want to do it only for one common grid)
        #
        # FIXME: Alternatively, Dirac could use several grids for exporting
        #
        # FIXME: we do the full DFT-in-DFT calculation, but only extracting
        #        the grid would be enough; maybe use some STOPAFTER option?

        # pylint: disable-msg=W0142
        outgrid_res = adffragmentsjob(frags, **self._adfoptions).run()

        for i in range(self._cycles):

            print "-" * 50
            print "Performing cycle ", i + 1
            print

            # do the Dirac calculation
            # pylint: disable-msg=W0142
            dirac_res = diracsinglepointjob(dirac_mol, fdein=dftindft_res, fdeout=outgrid_res, **self._diracoptions).run()

            # construct new list of fragments, update the Dirac fragment,
            frags = fragmentlist(initial_frags.get_frozen_frags())
            dirac_frag = diracfragment(dirac_res, dirac_mol, isfrozen=True)
            frags.append(dirac_frag)

            # loop over all DFT-relax fragments and update them
            for f in frags:
                if f.has_fdeoption("RELAXsave"):
                    f.isfrozen = False
                    # pylint: disable-msg=W0142
                    f.results = adffragmentsjob(frags, **self._adfoptions).run()
                    f.isfrozen = True

            frozenfrags = frags.get_frozen_frags()
            frozenfrags = [f for f in frozenfrags if not isinstance(f, diracfragment)]
            initial_frags = copy.deepcopy(fragmentlist(frozenfrags))
            dirac_frag = fragment(dftindft_res, dirac_mol, subfrag="active", isfrozen=False)
            initial_frags.append(dirac_frag)

            # run ADF DFT-in-DFT again to get a new embedding potential
            #
            # FIXME: rho1 is calculated by ADF in this step again.
            #        Instead, the rho1 calculated by Dirac should be used
            dftindft_res = adffragmentsjob(initial_frags, **self._adfoptions).run()

        print "-" * 50
        print "Performing final DIRAC calculation "
        print

        dirac_res = diracsinglepointjob(dirac_mol, fdein=dftindft_res, fdeout=outgrid_res, **self._diracoptions).run()

        return dirac_res
示例#4
0
    def partition_protein(self,
                          mol,
                          special_reslists=None,
                          fragsize=None,
                          caps=None):
        """
        Partition a protein into the individual amino acids and caps.

        @param mol: the protein
        @type mol:  L{molecule}

        @param special_reslists:
            lists of residue numbers that should be treated within one 3-FDE fragment
        @type special_reslists: list of lists of integers

        @param fragsize:
            number of residues in one 3-FDE fragment (not for residues in special_reslist)
        @type fragsize: int

        @param caps:
            type of cap molecule, standard is mfcc caps, option is hydrogen caps
        @type caps: str
        """

        # generate fragment list

        res_of_atoms = mol.get_residx_of_atoms()

        capped_bonds = []
        # list of bonds between residues within fragment
        non_capped_res = []
        # to which fragment belongs the residue
        frag_indices = []

        # clear the fragment list
        self._frags = []
        self._caps = []

        if fragsize is None:
            fragsize = 1
        if special_reslists is None:
            special_reslists = {}

        # ----------------------------------------------------------------------------------
        # simplest fragmentation: each residue is one fragment

        if special_reslists == {} and fragsize == 1:

            # get the individual residues
            for res in mol.get_residues():
                self.append(cappedfragment(None, res))
                frag_indices.append(len(self._frags) - 1)
        # ----------------------------------------------------------------------------------
        # more complicated fragmentation

        else:
            # careful with residue numbers (internal openbabel index idx starts at 0)

            fragmentation_list = []
            residuelist = mol.get_residues()
            frag_indices = [-1] * len(residuelist)

            # get list of residues connected by covalent bonds (tuples)
            connected_residues = []
            for b in mol.get_all_bonds():
                if not (res_of_atoms[b[0] - 1] == res_of_atoms[b[1] - 1]):
                    # -1 is not totally clear to me, but works
                    connected_residues.append(
                        {res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]})

            # ------------------------------------------------------------------------------
            # first get fragmentation list: which residues belong to which fragment
            # something like [ [3,4,5], [11,12,14], [1, 2], [6, 7], [8, 9], [10], [13]]

            # ugly
            # dictionary that connects pdb resnums with internal idx
            # problem: resnum as key is not unique, use combination of residue name and chain as key
            res_idx = {}

            for reschain, resname, resnum in mol.residue_iter():
                reskey = 'c' + str(reschain) + str(resnum)
                res_idx[reskey] = mol.get_residx_from_resinfo(
                    reschain, resname, resnum)

            # convert residue numbers in special_reslists to internal numbers
            for i in range(len(special_reslists)):
                for j in range(len(special_reslists[i])):
                    special_reslists[i][j] = res_idx[special_reslists[i][j]]

            # flatten list of lists so that you can check whether a residue is a special residue
            specialresidxs = []
            for slist in special_reslists:
                specialresidxs.extend(slist)

            # first add special residues to fragmentation list
            for slist in special_reslists:
                fragmentation_list.append(slist)

            fragl = []  # templist for fragments
            # add all other residues
            # use res.GetIdx() instead of enumerate
            for res, (reschain, resname,
                      resnum) in zip(residuelist, mol.residue_iter()):
                residx = mol.get_residx_from_resinfo(reschain, resname, resnum)
                if residx not in specialresidxs:
                    # take care of fragsize
                    if fragsize == 1:
                        fragmentation_list.append([residx])
                    else:
                        # check whether there has to be a new fragment
                        if len(fragl) != 0:
                            if not {residx, fragl[-1]} in connected_residues or \
                                    len(fragl) == fragsize:
                                # no covalent connection? new fragment! fragsize reached?
                                fragmentation_list.append(fragl)
                                fragl = []
                        # new fragment
                        if len(fragl) == 0:
                            fragl.append(residx)
                        # add to fragment
                        else:
                            fragl.append(residx)
            # last fragment
            if len(fragl) != 0:
                fragmentation_list.append(fragl)

            # ------------------------------------------------------------------------------
            # now add fragments to _frags using fragmentation list
            # take care of uncapped bonds and fragindices etc.

            frag_reslist = []

            for rlist in fragmentation_list:
                for rnum in range(len(rlist)):
                    res = mol.get_residues(idx=rlist[rnum])[0]
                    frag_reslist.append(res)

                    # if residue is added to an existing fragment: add tuple of residues to
                    # list of connected (non-capped) residues (only if they are connected)

                    # take also care of disulfide bonds within one fragment
                    # check whether new residue is connected to another residue within this fragment
                    if len(frag_reslist) > 1:
                        for rd in range(len(frag_reslist)):
                            if {rlist[rnum], rlist[rd]} in connected_residues:
                                non_capped_res.append({rlist[rnum], rlist[rd]})

                    # take care of residue information here
                    frag_indices[rlist[rnum]] = len(self._frags)

                res_frag = fragment(None, mols=frag_reslist)

                self.append(cappedfragment(None,
                                           res_frag.get_total_molecule()))
                # clear frag_reslist for next fragment
                frag_reslist = []

        # ------------------------------------------------------------------------------

        # find all peptide bonds and create caps

        if caps is None:
            caps = 'mfcc'

        if caps == 'mfcc':
            sp = '[C;X4;H1,H2][CX3](=O)[NX3][C;X4;H1,H2][CX3](=O)'
            # this SMARTS pattern matches all peptide bonds
            #
            # (in this comment: atom numbering starts at 1;
            #  in the code below the numbering of the list starts at 0)
            # the peptide bond is between atoms 2 and 4
            # atoms 1-5 (+ connected hydrogens) form the cap fragment
            # part 1 (o-part): atoms 1-3
            # part 2 (n-part): atoms 4-5

        elif caps == 'hydrogen':
            sp = '[C;X4;H1,H2][CX3](=O)[NX3]([*])[C;X4;H1,H2][CX3](=O)'
            # same as above, but also matches any atom bound to the nitrogen
            # the * might not be a good idea, but [C,H] was not working...
            # (this is needed for the proper calculation of the hydrogen coordinates)

        else:
            raise PyAdfError(
                'unsupported cap type, please specify one of the following: mfcc, hydrogen'
            )

        maplist = mol.get_smarts_matches(sp)

        for mp in maplist:

            if {res_of_atoms[mp[3] - 1],
                    res_of_atoms[mp[1] - 1]} not in non_capped_res:

                capped_bonds.append({mp[1], mp[3]})

                if caps == 'mfcc':
                    cap_o = mp[0:3] + mol.find_adjacent_hydrogens(mp[0:3])
                    cap_n = mp[3:5] + mol.find_adjacent_hydrogens(mp[3:5])
                    m_cap = mol.get_fragment(cap_o + cap_n)
                    m_cap.set_spin(0)
                    m_cap.set_residue('CAP', 1, atoms=range(1, len(cap_o) + 1))
                    m_cap.set_residue('CAP',
                                      2,
                                      atoms=range(
                                          len(cap_o) + 1,
                                          len(cap_o + cap_n) + 1))

                    m_cap.add_hydrogens_to_sp3_c(1)
                    m_cap.add_hydrogens_to_sp2_n(len(cap_o) + 1)
                    m_cap.add_hydrogens_to_sp3_c(len(cap_o) + 2)

                elif caps == 'hydrogen':
                    ccap = mol.get_fragment([mp[1], mp[2], mp[0]])
                    ccap.add_hydrogens_to_sp2_c(1)
                    ncap = mol.get_fragment([mp[3], mp[4], mp[5]])
                    ncap.add_hydrogens_to_sp3_n(1)

                    m_cap = capmolecule()
                    m_cap.add_atoms(['H'], ncap.get_coordinates([4]))
                    m_cap.add_atoms(['H'],
                                    ccap.get_coordinates([4]),
                                    bond_to=1)

                    m_cap.set_spin(0)
                    m_cap.set_residue('CAP', 1, atoms=[1])
                    m_cap.set_residue('CAP', 2, atoms=[2])

                    m_cap.set_symmetry('NOSYM')

                # find the capped fragments
                #   frag1: fragment that contains the N atom (mp[3])
                #   frag2: fragment that contains the C=O atom (mp[1])

                fi1 = frag_indices[res_of_atoms[mp[3] - 1]]
                fi2 = frag_indices[res_of_atoms[mp[1] - 1]]

                frag1 = self._frags[fi1]
                frag2 = self._frags[fi2]
                self.append_cap(cappedfragment(None, capmolecule(m_cap)),
                                frag1, frag2)

        # ------------------------------------------------------------------------------
        # check here for disulfide bonds and create disulfide bond caps

        maplist_sulfide = mol.get_smarts_matches('[C;X4;H1,H2]SS[C;X4;H1,H2]')
        # SMARTS pattern for disulfde bonds

        for mps in maplist_sulfide:

            if {res_of_atoms[mps[2] - 1],
                    res_of_atoms[mps[1] - 1]} not in non_capped_res:

                capped_bonds.append({mps[1], mps[2]})

                if caps == 'mfcc':
                    cap_s1 = mps[0:2] + mol.find_adjacent_hydrogens(mps[0:2])
                    cap_s2 = mps[2:] + mol.find_adjacent_hydrogens(mps[2:])
                    m_cap_s = mol.get_fragment(cap_s1 + cap_s2)
                    m_cap_s.set_spin(0)
                    m_cap_s.set_residue('SCP',
                                        1,
                                        atoms=range(1,
                                                    len(cap_s1) + 1))
                    m_cap_s.set_residue('SCP',
                                        2,
                                        atoms=range(
                                            len(cap_s1) + 1,
                                            len(cap_s1 + cap_s2) + 1))

                    m_cap_s.add_hydrogens_to_sp3_c(1)
                    m_cap_s.add_hydrogens_to_sp3_c(len(cap_s1) + 2)

                elif caps == 'hydrogen':

                    import numpy
                    import math

                    s1_coord = numpy.array(mol.get_coordinates([mps[1]]))
                    s2_coord = numpy.array(mol.get_coordinates([mps[2]]))

                    h1_coord = s1_coord + 1.34 * (
                        (s2_coord - s1_coord) /
                        numpy.linalg.norm(s2_coord - s1_coord))
                    h2_coord = s2_coord + 1.34 * (
                        (s1_coord - s2_coord) /
                        numpy.linalg.norm(s1_coord - s2_coord))

                    m_cap_s = capmolecule()
                    m_cap_s.add_atoms(['H'], h2_coord)
                    m_cap_s.add_atoms(['H'], h1_coord, bond_to=1)

                    m_cap_s.set_spin(0)
                    m_cap_s.set_residue('SCP', 1, atoms=[1])
                    m_cap_s.set_residue('SCP', 2, atoms=[2])

                    m_cap_s.set_symmetry('NOSYM')

                fi1 = frag_indices[res_of_atoms[mps[2] - 1]]
                fi2 = frag_indices[res_of_atoms[mps[1] - 1]]

                frag_s1 = self._frags[fi1]
                frag_s2 = self._frags[fi2]
                self.append_scap(cappedfragment(None, capmolecule(m_cap_s)),
                                 frag_s1, frag_s2)

        # ------------------------------------------------------------------------------

        # find bonds between different residues and check if they have been capped

        num_uncapped_bonds = 0
        for b in mol.get_all_bonds():

            if not (res_of_atoms[b[0] - 1] == res_of_atoms[b[1] - 1]):

                if not {b[0], b[1]} in capped_bonds \
                        and not {res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]} in non_capped_res \
                        and not {res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]}.issubset(special_reslists):
                    num_uncapped_bonds += 1
                    print "Bond between atoms ", b[0], " and ", b[
                        1], "not capped."
                    print "Bond between res ", res_of_atoms[
                        b[0] - 1], " and ", res_of_atoms[b[1] -
                                                         1], "not capped."

        if num_uncapped_bonds > 0:
            print num_uncapped_bonds, " bonds not capped. "
            raise PyAdfError('Not all bonds capped in partition_protein')
示例#5
0
    def partition_protein(self, mol, special_reslists=None, fragsize=None):
        """
        Partition a protein into the individual amino acids and caps.

        @param mol: the protein
        @type mol:  L{molecule}

        @param special_reslists:
            lists of residue numbers that should be treated within one 3-FDE fragment
        @type special_reslists: list of lists of integers

        @param fragsize:
            number of residues in one 3-FDE fragment (not for residues in special_reslist)
        @type fragsize: int
        """

        import openbabel

        # generate fragment list

        res_of_atoms = mol.get_residue_numbers_of_atoms()

        capped_bonds = []
        # list of bonds between residues within fragment
        non_capped_res = []
        # to which fragment belongs the residue
        frag_indices = []

        # clear the fragment list
        self._frags = []
        self._caps = []

        if fragsize == None:
            fragsize = 1
        if special_reslists == None:
            special_reslists = {}

        #----------------------------------------------------------------------------------
        # simplest fragmentation: each residue is one fragment

        if special_reslists == {} and fragsize == 1:

            # get the individual residues
            for res in mol.get_residues():
                self.append(cappedfragment(None, res))
                frag_indices.append(len(self._frags) - 1)
        #----------------------------------------------------------------------------------
        # more complicated fragmentation

        else:
            # careful with residue numbers (internal openbabel index idx starts at 0)

            fragmentation_list = []
            residuelist = mol.get_residues()
            frag_indices = [-1 for i in range(len(residuelist))]

            # get list of residues connected by covalent bonds (tuples)
            connected_residues = []
            for b in mol.get_all_bonds():
                if not (res_of_atoms[b[0] - 1] == res_of_atoms[b[1] - 1]):
                    # -1 is not totally clear to me, but works
                    connected_residues.append(
                        set([res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]]))

            #------------------------------------------------------------------------------
            # first get fragmentation list: which residues belong to which fragment
            # something like [ [3,4,5], [11,12,14], [1, 2], [6, 7], [8, 9], [10], [13]]

            # ugly
            # dictionary that connects pdb resnums with internal idx
            # problem: resnum as key is not unique, use combination of residue name and chain as key
            res_idx = {}
            for res in residuelist:
                resnum = res.mol.GetResidue(0).GetNum()
                reschain = res.mol.GetResidue(0).GetChain()
                reskey = 'c' + str(reschain) + str(resnum)
                intresnum = res.mol.GetResidue(0).GetIdx()
                res_idx[reskey] = intresnum

            # convert residue numbers in special_reslists to internal numbers
            for i in range(len(special_reslists)):
                for j in range(len(special_reslists[i])):
                    special_reslists[i][j] = res_idx[special_reslists[i][j]]

            # flatten list of lists so that you can check whether a residue is a special residue
            specialresnums = []
            for slist in special_reslists:
                if isinstance(slist, (list, tuple)):
                    specialresnums.extend(slist)
                # else should not occur, but maybe it is needed later
                else:
                    specialresnums.append(slist)

            # first add special residues to fragmentation list
            for slist in special_reslists:
                fragmentation_list.append(slist)

            fragl = []  # templist for fragments
            # add all other residues
            # use res.GetIdx() instead of enumerate
            for res in residuelist:
                resnum = res.mol.GetResidue(0).GetIdx()
                if resnum not in specialresnums:
                    # take care of fragsize
                    if fragsize == 1:
                        fragmentation_list.append([resnum])
                    else:
                        # check whether there has to be a new fragment
                        if len(fragl) != 0:
                            if not set([resnum, fragl[-1]]) in connected_residues or \
                                    len(fragl) == fragsize:
                                # no covalent connection? new fragment! fragsize reached?
                                fragmentation_list.append(fragl)
                                fragl = []
                        # new fragment
                        if len(fragl) == 0:
                            fragl.append(resnum)
                        # add to fragment
                        else:
                            fragl.append(resnum)
            # last fragment
            if len(fragl) != 0:
                fragmentation_list.append(fragl)

            #------------------------------------------------------------------------------
            # now add fragments to _frags using fragmentation list
            # take care of uncapped bonds and fragindices etc.

            frag_reslist = []

            for rlist in fragmentation_list:
                for rnum in range(len(rlist)):
                    res = mol.get_residues(idx=rlist[rnum])[0]
                    frag_reslist.append(res)

                    # if residue is added to an existing fragment: add tuple of residues to
                    # list of connected (non-capped) residues (only if they are connected)

                    # take also care of disulfide bonds within one fragment
                    # check whether new residue is connected to another residue within this fragment
                    if len(frag_reslist) > 1:
                        for rd in range(len(frag_reslist)):
                            if set([rlist[rnum],
                                    rlist[rd]]) in connected_residues:
                                non_capped_res.append(
                                    set([rlist[rnum], rlist[rd]]))

                    # take care of residue information here
                    frag_indices[rlist[rnum]] = len(self._frags)

                res_frag = fragment(None, mols=frag_reslist)

                self.append(cappedfragment(None,
                                           res_frag.get_total_molecule()))
                # clear frag_reslist for next fragment
                frag_reslist = []

        #------------------------------------------------------------------------------

        # find all peptide bonds and create caps

        sp = openbabel.OBSmartsPattern()
        sp.Init('[C;X4;H1,H2][CX3](=O)[NX3][C;X4;H1,H2][CX3](=O)')
        # this SMARTS pattern matches all peptide bonds
        #
        # (in this comment: atom numbering starts at 1;
        #  in the code below the numbering of the list starts at 0)
        # the peptide bond is between atoms 2 and 4
        # atoms 1-5 (+ connected hydrogens) form the cap fragment
        # part 1 (o-part): atoms 1-3
        # part 2 (n-part): atoms 4-5

        sp.Match(mol.mol)
        maplist = sp.GetUMapList()
        for mp in maplist:
            mp = list(mp)

            if set([res_of_atoms[mp[3] - 1],
                    res_of_atoms[mp[1] - 1]]) not in non_capped_res:

                capped_bonds.append(set([mp[1], mp[3]]))
                cap_o = mp[0:3] + mol.find_adjacent_hydrogens(mp[0:3])
                cap_n = mp[3:5] + mol.find_adjacent_hydrogens(mp[3:5])
                m_cap = mol.get_fragment(cap_o + cap_n)
                m_cap.set_spin(0)
                m_cap.set_residue('CAP', 1, atoms=range(1, len(cap_o) + 1))
                m_cap.set_residue('CAP',
                                  2,
                                  atoms=range(
                                      len(cap_o) + 1,
                                      len(cap_o + cap_n) + 1))
                m_cap.add_hydrogens()

                # find the capped fragments
                #   frag1: fragment that contains the N atom (mp[3])
                #   frag2: fragment that contains the C=O atom (mp[1])
                # why minus 1???

                fi1 = frag_indices[res_of_atoms[mp[3] - 1]]
                fi2 = frag_indices[res_of_atoms[mp[1] - 1]]

                frag1 = self._frags[fi1]
                frag2 = self._frags[fi2]
                self.append_cap(cappedfragment(None, capmolecule(m_cap)),
                                frag1, frag2)

        #------------------------------------------------------------------------------

        # check here for disulfide bonds and create disulfide bond caps

        sp_sulfide = openbabel.OBSmartsPattern()
        sp_sulfide.Init('[C;X4;H1,H2]SS[C;X4;H1,H2]')
        # SMARTS pattern for disulfde bonds

        sp_sulfide.Match(mol.mol)
        maplist_sulfide = sp_sulfide.GetUMapList()
        for mps in maplist_sulfide:
            mps = list(mps)

            if set([res_of_atoms[mps[2] - 1],
                    res_of_atoms[mps[1] - 1]]) not in non_capped_res:

                capped_bonds.append(set([mps[1], mps[2]]))
                cap_s1 = mps[0:2] + mol.find_adjacent_hydrogens(mps[0:2])
                cap_s2 = mps[2:] + mol.find_adjacent_hydrogens(mps[2:])
                m_cap_s = mol.get_fragment(cap_s1 + cap_s2)
                m_cap_s.set_spin(0)
                m_cap_s.set_residue('SCP', 1, atoms=range(1, len(cap_s1) + 1))
                m_cap_s.set_residue('SCP',
                                    2,
                                    atoms=range(
                                        len(cap_s1) + 1,
                                        len(cap_s1 + cap_s2) + 1))
                m_cap_s.add_hydrogens()

                fi1 = frag_indices[res_of_atoms[mps[2] - 1]]
                fi2 = frag_indices[res_of_atoms[mps[1] - 1]]

                frag_s1 = self._frags[fi1]
                frag_s2 = self._frags[fi2]
                self.append_scap(cappedfragment(None, capmolecule(m_cap_s)),
                                 frag_s1, frag_s2)

        #------------------------------------------------------------------------------

        # find bonds between different residues and check if they have been capped

        num_uncapped_bonds = 0
        for b in mol.get_all_bonds():

            if not (res_of_atoms[b[0] - 1] == res_of_atoms[b[1] - 1]):

                if not set([b[0], b[1]]) in capped_bonds \
                        and not set([res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]]) in non_capped_res \
                        and not set([res_of_atoms[b[0] - 1], res_of_atoms[b[1] - 1]]).issubset(special_reslists):

                    num_uncapped_bonds += 1
                    print "Bond between atoms ", b[0], " and ", b[
                        1], "not capped."
                    print "Bond between res ", res_of_atoms[
                        b[0] - 1], " and ", res_of_atoms[b[1] -
                                                         1], "not capped."

        if num_uncapped_bonds > 0:
            print num_uncapped_bonds, " bonds not capped. "
            raise PyAdfError('Not all bonds capped in partition_protein')