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