diff --git a/prody/proteins/interactions.py b/prody/proteins/interactions.py index dfca7a1d3..8fd925879 100644 --- a/prody/proteins/interactions.py +++ b/prody/proteins/interactions.py @@ -1425,7 +1425,7 @@ def calcHydrophobic(atoms, **kwargs): Additional selection can be added as shown below (with selection that includes only hydrophobic part): >>> calcHydrophobic(atoms, non_standard_Hph={'XLE'='noh and not backbone', - 'XLI'='noh and not backbone'}) + 'XLI'='noh and not backbone'}) Predictions for proteins only. To compute protein-ligand interactions use calcLigandInteractions(). Results can be displayed in VMD by using showVMDinteraction() @@ -1702,6 +1702,24 @@ def calcMetalInteractions(atoms, distA=3.0, extraIons=['FE'], excluded_ions=['SO raise TypeError('An object should contain ions') +def _analyseFrameTrajectory(j0, frame0, interactions_all, atoms_copy, interaction_type, interactions_dic, kwargs): + """Helper function for calcInteractionsMultipleFrames to handle trajectory frames in parallel.""" + LOGGER.info('Frame: {0}'.format(j0)) + atoms_copy.setCoords(frame0.getCoords()) + protein = atoms_copy.select('protein') + interactions = interactions_dic[interaction_type](protein, **kwargs) + interactions_all[j0] = interactions + + +def _analyseFrameCoordsets(i, interactions_all, atoms, interaction_type, interactions_dic, start_frame, kwargs): + """Helper function for calcInteractionsMultipleFrames to handle multi-model PDB models in parallel.""" + LOGGER.info('Model: {0}'.format(i+start_frame)) + atoms.setACSIndex(i+start_frame) + protein = atoms.select('protein') + interactions = interactions_dic[interaction_type](protein, **kwargs) + interactions_all[i] = interactions + + def calcInteractionsMultipleFrames(atoms, interaction_type, trajectory, **kwargs): """Compute selected type interactions for DCD trajectory or multi-model PDB using default parameters or those from kwargs. @@ -1750,20 +1768,15 @@ def calcInteractionsMultipleFrames(atoms, interaction_type, trajectory, **kwargs traj = trajectory[start_frame:stop_frame+1] atoms_copy = atoms.copy() - def analyseFrame(j0, frame0, interactions_all): - LOGGER.info('Frame: {0}'.format(j0)) - atoms_copy.setCoords(frame0.getCoords()) - protein = atoms_copy.select('protein') - interactions = interactions_dic[interaction_type](protein, **kwargs) - interactions_all.append(interactions) if max_proc == 1: - interactions_all = [] + interactions_all = list([None] * traj.numConfs()) # pre-allocate for j0, frame0 in enumerate(traj, start=start_frame): - analyseFrame(j0, frame0, interactions_all) + _analyseFrameTrajectory(j0, frame0, interactions_all, atoms_copy, + interaction_type, interactions_dic, kwargs) else: with mp.Manager() as manager: - interactions_all = manager.list() + interactions_all = manager.list([None] * traj.numConfs()) # pre-allocate j0 = start_frame while j0 < traj.numConfs()+start_frame: @@ -1772,8 +1785,9 @@ def analyseFrame(j0, frame0, interactions_all): for _ in range(max_proc): frame0 = traj[j0-start_frame] - p = mp.Process(target=analyseFrame, args=(j0, frame0, - interactions_all)) + p = mp.Process(target=_analyseFrameTrajectory, + args=(j0, frame0, interactions_all, atoms_copy, + interaction_type, interactions_dic, kwargs)) p.start() processes.append(p) @@ -1791,29 +1805,25 @@ def analyseFrame(j0, frame0, interactions_all): else: if atoms.numCoordsets() > 1: - def analyseFrame(i, interactions_all): - LOGGER.info('Model: {0}'.format(i+start_frame)) - atoms.setACSIndex(i+start_frame) - protein = atoms.select('protein') - interactions = interactions_dic[interaction_type](protein, **kwargs) - interactions_all.append(interactions) - if stop_frame == -1: stop_frame = atoms.numCoordsets() if max_proc == 1: - interactions_all = [] + interactions_all = list([None] * len(atoms.getCoordsets()[start_frame:stop_frame+1])) # pre-allocate for i in range(len(atoms.getCoordsets()[start_frame:stop_frame+1])): - analyseFrame(i, interactions_all) + _analyseFrameCoordsets(i, interactions_all, atoms, interaction_type, + interactions_dic, start_frame, kwargs) else: with mp.Manager() as manager: - interactions_all = manager.list() + interactions_all = manager.list([None] * len(atoms.getCoordsets()[start_frame:stop_frame+1])) # pre-allocate i = start_frame while i < len(atoms.getCoordsets()[start_frame:stop_frame+1]): processes = [] for _ in range(max_proc): - p = mp.Process(target=analyseFrame, args=(i, interactions_all)) + p = mp.Process(target=_analyseFrameCoordsets, + args=(i, interactions_all, atoms, interaction_type, + interactions_dic, start_frame, kwargs)) p.start() processes.append(p) @@ -5304,7 +5314,7 @@ def calcProteinInteractionsTrajectory(self, atoms, trajectory=None, filename=Non trajectory = atoms else: LOGGER.info('Include trajectory or use multi-model PDB file.') - return interactions_nb_traj + return None if isinstance(trajectory, Atomic): trajectory = Ensemble(trajectory) @@ -5335,78 +5345,28 @@ def calcProteinInteractionsTrajectory(self, atoms, trajectory=None, filename=Non HPh_nb = [[] for _ in traj] DiBs_nb = [[] for _ in traj] + interactions_dic = { + "HBs": calcHydrogenBonds, + "SBs": calcSaltBridges, + "RIB": calcRepulsiveIonicBonding, + "PiStack": calcPiStacking, + "PiCat": calcPiCation, + "HPh": calcHydrophobic, + "DiB": calcDisulfideBonds + } + interactions_traj = [HBs_all, SBs_all, RIB_all, PiStack_all, PiCat_all, HPh_all, DiBs_all] interactions_nb_traj = [HBs_nb, SBs_nb, RIB_nb, PiStack_nb, PiCat_nb, HPh_nb, DiBs_nb] atoms_copy = atoms.copy() - protein = atoms_copy.protein - - def analyseFrame(j0, frame0, interactions_all, interactions_nb): - LOGGER.info('Frame: {0}'.format(j0)) - atoms_copy.setCoords(frame0.getCoords()) - - ind = j0 - start_frame - - hydrogen_bonds = calcHydrogenBonds(protein, **kwargs) - salt_bridges = calcSaltBridges(protein, **kwargs) - RepulsiveIonicBonding = calcRepulsiveIonicBonding(protein, **kwargs) - Pi_stacking = calcPiStacking(protein, **kwargs) - Pi_cation = calcPiCation(protein, **kwargs) - hydrophobic = calcHydrophobic(protein, **kwargs) - Disulfide_Bonds = calcDisulfideBonds(protein, **kwargs) - - interactions_all[0][ind].extend(hydrogen_bonds) - interactions_all[1][ind].extend(salt_bridges) - interactions_all[2][ind].extend(RepulsiveIonicBonding) - interactions_all[3][ind].extend(Pi_stacking) - interactions_all[4][ind].extend(Pi_cation) - interactions_all[5][ind].extend(hydrophobic) - interactions_all[6][ind].extend(Disulfide_Bonds) - - interactions_nb[0][ind].append(len(hydrogen_bonds)) - interactions_nb[1][ind].append(len(salt_bridges)) - interactions_nb[2][ind].append(len(RepulsiveIonicBonding)) - interactions_nb[3][ind].append(len(Pi_stacking)) - interactions_nb[4][ind].append(len(Pi_cation)) - interactions_nb[5][ind].append(len(hydrophobic)) - interactions_nb[6][ind].append(len(Disulfide_Bonds)) - - if max_proc == 1: - interactions_all = interactions_traj - interactions_nb = interactions_nb_traj - for j0, frame0 in enumerate(traj, start=start_frame): - analyseFrame(j0, frame0, interactions_all, interactions_nb) - interactions_nb = [[item[0] for item in row] for row in interactions_nb] - else: - with mp.Manager() as manager: - interactions_all = manager.list() - interactions_nb = manager.list() - for row in interactions_traj: - interactions_all.append([manager.list() for _ in row]) - interactions_nb.append([manager.list() for _ in row]) - - j0 = start_frame - while j0 < traj.numConfs()+start_frame: - - processes = [] - for _ in range(max_proc): - frame0 = traj[j0-start_frame] - - p = mp.Process(target=analyseFrame, args=(j0, frame0, - interactions_all, - interactions_nb)) - p.start() - processes.append(p) - - j0 += 1 - if j0 >= traj.numConfs()+start_frame: - break - - for p in processes: - p.join() - - interactions_all = [[item[:] for item in row] for row in interactions_all] - interactions_nb = [[item[0] for item in row] for row in interactions_nb] + interaction_types = ['HBs', 'SBs', 'RIB', 'PiStack', 'PiCat', 'HPh', 'DiB'] + interactions_all = [calcInteractionsMultipleFrames(atoms, t, trajectory, + start_frame=start_frame, + stop_frame=stop_frame, + max_proc=max_proc, + **kwargs) + for t in interaction_types] + interactions_nb = [[len(frame) for frame in itype] for itype in interactions_all] self._atoms = atoms self._traj = trajectory