Skip to content

Make thread-safe #10

Description

@mattwthompson

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:

  • Trying to load an output file from a different packing (appropriately!) triggers a WrongShapeError
  • Sometimes, the output file packmol_output.pdb does not exist when it's trying to be loaded
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()

Out:

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)

Footnotes

  1. Or each call ends up in the same temporary directory, which I think is unlikely

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions