Most of the setup happens in temporary directories, but something about parsing the output does not1. As a result, multiple calls on separate threads can easily choke. This example shows two ways:
from openff.packmol import pack_box
from openff.toolkit import Molecule, Quantity
import threading
water = Molecule.from_smiles("O")
threads = []
for i in range(3):
t = threading.Thread(
target=pack_box,
args=(
[water],
[100 + i],
None,
Quantity(0.2, "nanometer"),
None,
Quantity(0.5, "g/mL"),
),
)
threads.append(t)
t.start()
for t in threads:
t.join()
Exception in thread Thread-1 (pack_box):
Exception in thread Thread-3 (pack_box):
Traceback (most recent call last):
Traceback (most recent call last):
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1075, in _bootstrap_inner
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1075, in _bootstrap_inner
Exception in thread Thread-2 (pack_box):
Traceback (most recent call last):
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/packmol/_packmol.py", line 853, in _load_positions
for line in open(output_file_path).readlines()
^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'packmol_output.pdb'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1075, in _bootstrap_inner
self.run()
self.run()
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1012, in run
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1012, in run
self.run()
self._target(*self._args, **self._kwargs)
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/threading.py", line 1012, in run
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/utilities/utilities.py", line 79, in wrapper
self._target(*self._args, **self._kwargs)
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/utilities/utilities.py", line 79, in wrapper
self._target(*self._args, **self._kwargs)
return function(*args, **kwargs)
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/utilities/utilities.py", line 79, in wrapper
^^^^^^^^^^^^^^^^^^^^^^^^^
return function(*args, **kwargs)
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/packmol/_packmol.py", line 810, in pack_box
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/packmol/_packmol.py", line 810, in pack_box
topology.set_positions(Quantity(positions[n_solute_atoms:], "angstrom"))
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/toolkit/topology/topology.py", line 2109, in set_positions
topology.set_positions(Quantity(positions[n_solute_atoms:], "angstrom"))
return function(*args, **kwargs)
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/toolkit/topology/topology.py", line 2109, in set_positions
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/packmol/_packmol.py", line 795, in pack_box
positions = _load_positions(output_file_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mattthompson/software/dimsim/.pixi/envs/dev/lib/python3.12/site-packages/openff/packmol/_packmol.py", line 859, in _load_positions
raise PACKMOLRuntimeError(
openff.packmol.exceptions.PACKMOLRuntimeError: PACKMOL output could not be parsed by a native coordinate parser, please raise an issue with code reproducing this error.
raise WrongShapeError(f"Array has shape {array.shape} but should have shape {self.n_atoms, 3}")
raise WrongShapeError(f"Array has shape {array.shape} but should have shape {self.n_atoms, 3}")
openff.toolkit.utils.exceptions.WrongShapeError: Array has shape (102, 3) but should have shape (300, 3)
openff.toolkit.utils.exceptions.WrongShapeError: Array has shape (102, 3) but should have shape (306, 3)
Most of the setup happens in temporary directories, but something about parsing the output does not1. As a result, multiple calls on separate threads can easily choke. This example shows two ways:
WrongShapeErrorpackmol_output.pdbdoes not exist when it's trying to be loadedOut:
Footnotes
Or each call ends up in the same temporary directory, which I think is unlikely ↩