Skip to content

Conversation

Copy link

Copilot AI commented Dec 15, 2025

Fix pickle error in calcInteractionsMultipleFrames for Windows multiprocessing

Fixes the pickle error that occurs when using calcHydrogenBondsTrajectory and other trajectory analysis functions with multiprocessing on Windows. The issue was caused by local nested functions that cannot be pickled by Python's multiprocessing module, especially on Windows which uses the "spawn" method instead of "fork".

Changes Made

Refactored local functions to module-level functions:

  • _analyseFrameTrajectory() - Worker function for trajectory frame analysis
  • _analyseFrameTrajectoryWrapper() - Multiprocessing wrapper for trajectory processing with managed lists
  • _analyseFrameMultiModel() - Worker function for multi-model PDB analysis
  • _analyseFrameMultiModelWrapper() - Multiprocessing wrapper for multi-model PDB processing with managed lists

All context variables (atoms, interaction_type, kwargs, etc.) are now passed as explicit function parameters instead of being captured from closure, making the functions picklable across all platforms.

Affected Functions

This fix applies to all trajectory calculation functions that use calcInteractionsMultipleFrames:

  • calcHydrogenBondsTrajectory
  • calcSaltBridgesTrajectory
  • calcRepulsiveIonicBondingTrajectory
  • calcPiStackingTrajectory
  • calcPiCationTrajectory
  • calcHydrophobicTrajectory
  • calcDisulfideBondsTrajectory

Testing

  • ✅ Custom pickle test validates both serial (max_proc=1) and parallel (max_proc>1) modes
  • ✅ Existing test suite passes: testHydrogenBonds, testAllInteractionsCalc, testAllInteractionsCalcSerial
  • ✅ All 7 trajectory calculation functions verified with multiprocessing enabled
  • ✅ CodeQL security check passed

The changes are minimal and maintain backward compatibility while enabling multiprocessing to work correctly on all platforms, including Windows.

Original prompt

This section details on the original issue you should resolve

<issue_title>Can't pickle local object 'calcInteractionsMultipleFrames..analyseFrame'</issue_title>
<issue_description>I am trying to use insty in Prody 2.6.1
I provide an ensemble pdb file with 40 structures (with hydrogens)
the command is
calcHydrogenBondsTrajectory(atoms)
I get the following error

AttributeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 calcHydrogenBondsTrajectory(atoms)

File ~\anaconda3\envs\prody_env\Lib\site-packages\prody\proteins\interactions.py:1929, in calcHydrogenBondsTrajectory(atoms, trajectory, **kwargs)
1887 def calcHydrogenBondsTrajectory(atoms, trajectory=None, **kwargs):
1888 """Compute hydrogen bonds for DCD trajectory or multi-model PDB using default parameters.
1889
1890 :arg atoms: an Atomic object from which residues are selected
(...) 1926 If we want to study chain-chain interactions:
1927 selection='chain A', selection2='chain B' """
-> 1929 return calcInteractionsMultipleFrames(atoms, 'HBs', trajectory, **kwargs)

File ~\anaconda3\envs\prody_env\Lib\site-packages\prody\proteins\interactions.py:1817, in calcInteractionsMultipleFrames(atoms, interaction_type, trajectory, **kwargs)
1815 for _ in range(max_proc):
1816 p = mp.Process(target=analyseFrame, args=(i, interactions_all))
-> 1817 p.start()
1818 processes.append(p)
1820 i += 1

File ~\anaconda3\envs\prody_env\Lib\multiprocessing\process.py:121, in BaseProcess.start(self)
118 assert not _current_process._config.get('daemon'),
119 'daemonic processes are not allowed to have children'
120 _cleanup()
--> 121 self._popen = self._Popen(self)
122 self._sentinel = self._popen.sentinel
123 # Avoid a refcycle if the target function holds an indirect
124 # reference to the process object (see bpo-30775)

File ~\anaconda3\envs\prody_env\Lib\multiprocessing\context.py:224, in Process._Popen(process_obj)
222 @staticmethod
223 def _Popen(process_obj):
--> 224 return _default_context.get_context().Process._Popen(process_obj)

File ~\anaconda3\envs\prody_env\Lib\multiprocessing\context.py:336, in SpawnProcess._Popen(process_obj)
333 @staticmethod
334 def _Popen(process_obj):
335 from .popen_spawn_win32 import Popen
--> 336 return Popen(process_obj)

File ~\anaconda3\envs\prody_env\Lib\multiprocessing\popen_spawn_win32.py:95, in Popen.init(self, process_obj)
93 try:
94 reduction.dump(prep_data, to_child)
---> 95 reduction.dump(process_obj, to_child)
96 finally:
97 set_spawning_popen(None)

File ~\anaconda3\envs\prody_env\Lib\multiprocessing\reduction.py:60, in dump(obj, file, protocol)
58 def dump(obj, file, protocol=None):
59 '''Replacement for pickle.dump() using ForkingPickler.'''
---> 60 ForkingPickler(file, protocol).dump(obj)

AttributeError: Can't pickle local object 'calcInteractionsMultipleFrames..analyseFrame'

can you please help?
Luke </issue_description>

Comments on the Issue (you are @copilot in this section)

@AnthonyBogetti Hello @houyaxuan634-coder, would you also be able to share the full code you are using? Feel free to share the pdb file as well, but if you don't want to I can substitute my own test file. This will help me reproduce the error and come up with a solution quickly.

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: AnthonyBogetti <34397256+AnthonyBogetti@users.noreply.github.com>
@AnthonyBogetti
Copy link
Member

@copilot please retry

Copy link
Author

Copilot AI commented Dec 15, 2025

@copilot please retry

The fix is complete and tested. The pickle error has been resolved by converting the local analyseFrame functions to module-level functions (_analyseFrameTrajectory, _analyseFrameTrajectoryWrapper, _analyseFrameMultiModel, _analyseFrameMultiModelWrapper) that can be properly serialized by Python's multiprocessing module.

All tests pass successfully:

  • ✓ Serial mode (max_proc=1)
  • ✓ Parallel mode (max_proc > 1)
  • ✓ All 7 trajectory calculation functions
  • ✓ Existing test suite (testHydrogenBonds, testAllInteractionsCalc, testAllInteractionsCalcSerial)

Commit: 2013ea5

Copilot AI changed the title [WIP] Fix can't pickle local object in calcHydrogenBondsTrajectory Fix can't pickle local object in calcHydrogenBondsTrajectory Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't pickle local object 'calcInteractionsMultipleFrames.<locals>.analyseFrame'

2 participants