def reprepare(self): """Repeat the system preparation, after the user edited the .data table. You should only modify the value of the .data.forced_protonation column on the basis of the values in the .data.resid, .data.insertion, .data.chain attributes. Any other change will be ignored. Returns ------- mol_out : Molecule the molecule titrated and optimized. The molecule object contains an additional attribute, resData : ResidueData a table of residues with the corresponding protonation states, pKas, and other information Examples -------- mol, prepData = proteinPrepare(Molecule("3PTB"), returnDetails=True) d = prepData.data d.loc[d.resid == 40, 'forced_protonation'] = 'HIP' mHIP40, pHIP40 = prepData.reprepare() """ from pdb2pqr.src.hydrogens import hydrogenRoutines from pdb2pqr.src.forcefield import Forcefield from pdb2pqr.src.definitions import Definition from htmd.builder.preparation import _buildResAndMol d = self.data routines = self.pdb2pqr_routines p = routines.protein keep_pka_columns = ('forced_protonation', 'buried', 'z', 'membraneExposed', 'pKa', 'pka_group_id', 'pka_residue_type', 'pka_type', 'pka_charge', 'pka_atom_name', 'pka_atom_sybyl_type') copy_of_resname = d['resname'] copy_of_protonation = d['protonation'] copy_of_default_protonation = d['default_protonation'] list_of_forced_protonations = ~ pd.isnull(d['forced_protonation']) neutraln = neutralc = False assign_only = clean = False debump = opt = True # Some water molecules seem to have fixed=1 at this point. This makes initializeFullOptimization() skip them # when it builds the resmap dict, which in turns breaks later stages. So, let's reset it. for res in p.getResidues(): try: if res.fixed == 1: logger.debug("Resetting fixed flag on {:s}".format(str(res))) res.fixed = 0 except: logger.debug("Residue {:s} has no fixed attribute".format(str(res))) pass # Code lifted from resinter.py routines.removeHydrogens() for index, oldResidue in enumerate(p.getResidues()): chain = p.chainmap[oldResidue.chainID] chainIndex = chain.residues.index(oldResidue) d_idx = d.pdb2pqr_idx == index if sum(d_idx) != 1: logger.warning("Residue {:s} appears {:d} times in data table".format(str(oldResidue), sum(d_idx))) continue newResidueName = d.forced_protonation[d_idx].iloc[0] if pd.isnull(newResidueName): # newResidueName = d.protonation[d_idx].iloc[0] continue logger.debug("Replacing {} with {}".format(oldResidue, newResidueName)) # Create the replacement residue residueAtoms = oldResidue.atoms newResidue = routines.protein.createResidue(residueAtoms, newResidueName) # Make sure our names are cleaned up for output. newResidue.renameResidue(newResidueName) # Drop it in p.residues[index] = newResidue chain.residues[chainIndex] = newResidue # Run the meaty bits of PDB2PQR routines.setTermini(neutraln, neutralc) routines.updateBonds() if not clean and not assign_only: routines.updateSSbridges() if debump: routines.debumpProtein() routines.addHydrogens() hydRoutines = hydrogenRoutines(routines) if debump: routines.debumpProtein() if opt: hydRoutines.setOptimizeableHydrogens() hydRoutines.initializeFullOptimization() hydRoutines.optimizeHydrogens() else: hydRoutines.initializeWaterOptimization() hydRoutines.optimizeHydrogens() # Special for GLH/ASH, since both conformations were added hydRoutines.cleanup() ff = "parse" ffout = "amber" usernames = userff = None routines.setStates() # ? mydef = Definition() # ? myForcefield = Forcefield(ff, mydef, userff, usernames) hitlist, misslist = routines.applyForcefield(myForcefield) # reslist, charge = routines.getCharge() # <--- ? # Copied from runPDB2PQR = ? if not ffout is None: if ffout != ff: myNameScheme = Forcefield(ffout, mydef, userff) else: myNameScheme = myForcefield routines.applyNameScheme(myNameScheme) p.reSerialize() newMol, newResData = _buildResAndMol(p) # Assume that the number and order of residues does not change # Carry over old pka and other useful info newResData.data['resname'] = copy_of_resname newResData.data['protonation'] = copy_of_protonation newResData.data['default_protonation'] = copy_of_default_protonation newResData.data.loc[list_of_forced_protonations, 'protonation'] = \ d.loc[list_of_forced_protonations, 'forced_protonation'] for cn in keep_pka_columns: newResData.data[cn] = d[cn] newResData.pdb2pqr_routines = routines newResData.pdb2pqr_protein = routines.protein newResData.missedLigands = self.missedLigands return newMol, newResData