Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Box from coords #321

Merged
merged 17 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions polyply/src/gen_coords.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,22 @@ def gen_coords(toppath,
LOGGER.info("loading grid", type="step")
grid = np.loadtxt(grid)

# where to get the box size from
if box is not None and not np.array_equal(topology.box, box):
msg = ("A box is provided via the -box command line "
"and the starting coordinates. We consider the "
"the box of starting coordinates as correct. ")
LOGGER.warning(msg, type="warning")
box = topology.box
pckroon marked this conversation as resolved.
Show resolved Hide resolved
elif topology.box is not None:
box = topology.box
if density is not None:
msg = ("A density is provided via the command line, "
"but the starting coordinates define a box."
"Will try to pack all molecules in the box "
"provided with starting coordinates.")
LOGGER.warning(msg, type="warning")

# do a sanity check
LOGGER.info("checking residue integrity", type="step")
check_residue_equivalence(topology)
Expand Down
9 changes: 7 additions & 2 deletions polyply/src/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ def _coord_parser(path, extension):
molecule.merge_molecule(new_mol)
else:
molecule = molecules

box = molecule.box
positions = np.array(list(nx.get_node_attributes(molecule, "position").values()))
return positions
return positions, box


def replace_defined_interaction(interaction, defines):
Expand Down Expand Up @@ -213,6 +215,8 @@ class Topology(System):
A dictionary of all typed parameter
defines: list
A list of everything that is defined
box: np.array(3,1)
Box vectors as a, b, c in nanometers
"""

def __init__(self, force_field, name=None):
Expand All @@ -228,6 +232,7 @@ def __init__(self, force_field, name=None):
self.persistences = []
self.distance_restraints = defaultdict(dict)
self.volumes = {}
self.box = None

def preprocess(self):
"""
Expand Down Expand Up @@ -425,7 +430,7 @@ def add_positions_from_file(self, path, skip_res=[], resolution='mol'):
"""
path = Path(path)
extension = path.suffix.casefold()[1:]
positions = _coord_parser(path, extension)
positions, self.box = _coord_parser(path, extension)
max_coords = len(positions)
total = 0
for meta_mol in self.molecules:
Expand Down
2 changes: 1 addition & 1 deletion polyply/tests/test_data/topology_test/meta.gro
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ PMMA test file
2
1PMMA C1 1 -0.024 -0.125 0.104
1PMMA C2 2 -0.089 -0.100 -0.028
10.00000 10.00000 10.00000
10.00000 11.00000 12.00000
2 changes: 1 addition & 1 deletion polyply/tests/test_data/topology_test/test.gro
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ PMMA test file
2PMMA O1 12 4.482 6.483 9.965
2PMMA O2 13 4.579 6.512 9.772
2PMMA C5 14 4.632 6.624 9.842
10.00000 10.00000 10.00000
10.00000 11.00000 12.00000
1 change: 1 addition & 0 deletions polyply/tests/test_data/topology_test/test.pdb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
CRYST1 118.249 120.688 110.944 90.00 90.00 90.00 P 1 1
ATOM 1 BB MET A 1 17.193 61.796 62.315 1.00 0.00
ATOM 2 SC1 MET A 1 20.670 62.642 62.148 1.00 0.00
ATOM 3 BB TYR A 2 16.691 62.571 65.956 1.00 0.00
Expand Down
47 changes: 47 additions & 0 deletions polyply/tests/test_gen_coords_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,53 @@ def test_no_positions_generated(tmp_path, monkeypatch):
assert np.all(molecule_out.nodes[node]['position'] ==
molecule_in.nodes[node]['position'])

@pytest.mark.parametrize('box_input, box_ref, density, warning', [
# box from input coordinates
(None, np.array([11.0, 11.0, 11.0]), None, None),
# box from input coordinates overwrites
(np.array([5.0, 5.0, 5.0]), np.array([11.0, 11.0, 11.0]), None, "warn1"),
# box from input coordinates and density from CLI
(None, np.array([11.0, 11.0, 11.0]), 1000, "warn2"),
])
def test_box_input(tmp_path, caplog, box_input, box_ref, density, warning):
"""
Here we test that the correct box is chosen, in case there
are conflicting inputs.
"""
warnings = {"warn1": ("A box is provided via the -box command line "
"and the starting coordinates. We consider the "
"the box of starting coordinates as correct. "),
"warn2": ("A density is provided via the command line, "
"but the starting coordinates define a box."
"Will try to pack all molecules in the box "
"provided with starting coordinates."),}

top_file = TEST_DATA + "/topology_test/system.top"
pos_file = TEST_DATA + "/topology_test/complete.gro"
out_file = tmp_path / "out.gro"

with caplog.at_level(logging.WARNING):
gen_coords(toppath=top_file,
coordpath=pos_file,
outpath=out_file,
name="test",
box=box_input,
density=density,)

molecule_out = read_gro(out_file, exclude=())
assert np.array_equal(molecule_out.box, box_ref)
if warning:
for record in caplog.records:
if record.levelname == "WARNING":
assert str(record.msg) == warnings[warning]
break
else:
assert False
else:
for record in caplog.records:
if record.levelname == "WARNING":
assert False

def test_backmap_only(tmp_path, monkeypatch):
"""
Only meta_mol positions are defined so others have to be backmapped.
Expand Down
11 changes: 11 additions & 0 deletions polyply/tests/test_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def test_add_positions_from_gro():
"""
top = Topology.from_gmx_topfile(TEST_DATA + "/topology_test/system.top", "test")
top.add_positions_from_file(TEST_DATA + "/topology_test/test.gro")

# check that the box is correctly read
assert np.allclose(top.box, np.array([10.0, 11.0, 12.0]))

for node in top.molecules[0].molecule.nodes:
if node < 14:
assert "position" in top.molecules[0].molecule.nodes[node].keys()
Expand All @@ -70,6 +74,10 @@ def test_add_meta_positions_from_gro():
"""
top = Topology.from_gmx_topfile(TEST_DATA + "/topology_test/system.top", "test")
top.add_positions_from_file(TEST_DATA + "/topology_test/meta.gro", resolution="meta_mol")

# check that the box is correctly read
assert np.allclose(top.box, np.array([10.0, 11.0, 12.0]))

for node in top.molecules[0].nodes:
if node != 2:
assert "position" in top.molecules[0].nodes[node].keys()
Expand All @@ -90,6 +98,9 @@ def test_add_positions_from_pdb():
top = Topology.from_gmx_topfile(TEST_DATA + "/topology_test/pdb.top", "test")
top.add_positions_from_file(TEST_DATA + "/topology_test/test.pdb")

# check that the box is correctly read
assert np.allclose(top.box, np.array([11.8249, 12.0688, 11.0944]))

pdb_mols = read_pdb(TEST_DATA + "/topology_test/test.pdb")
for idx, meta_mol in enumerate(top.molecules):
for node in meta_mol.molecule.nodes:
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ install-requires = # ?? requires-dist?
numpy
decorator == 4.4.2
networkx ~= 2.0
vermouth >= 0.9.1
vermouth >= 0.9.6
scipy >= 1.6.0
tqdm
zip-safe = False
Expand Down
Loading