From 4113f24a9407b5dc2e329309342d1222bb34cc8b Mon Sep 17 00:00:00 2001 From: Co Quach Date: Sun, 4 Jun 2023 22:10:07 -0500 Subject: [PATCH 1/8] add shift_coord option --- gmso/formats/gro.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gmso/formats/gro.py b/gmso/formats/gro.py index a702f68d6..d1bcc9937 100644 --- a/gmso/formats/gro.py +++ b/gmso/formats/gro.py @@ -103,7 +103,7 @@ def read_gro(filename): @saves_as(".gro") -def write_gro(top, filename, precision=3): +def write_gro(top, filename, precision=3, shift_coord=False): """Write a topology to a gro file. The Gromos87 (gro) format is a common plain text structure file used @@ -121,6 +121,9 @@ def write_gro(top, filename, precision=3): The location and name of file to save to disk. precision : int, optional, default=3 The number of sig fig to write out the position in. + shift_coord : bool, optional, default=False + If True, shift the coordinate to be all sites to ensure + all coordinates are non-negative. Notes ----- @@ -131,7 +134,8 @@ def write_gro(top, filename, precision=3): """ pos_array = np.ndarray.copy(top.positions) - pos_array = _validate_positions(pos_array) + if shift_coord: + pos_array = _validate_positions(pos_array) with open(filename, "w") as out_file: out_file.write( From b12af25034e0685cd25ea5110d9caca6d31b9b11 Mon Sep 17 00:00:00 2001 From: Co Quach Date: Fri, 7 Jul 2023 14:25:46 -0500 Subject: [PATCH 2/8] add simple test to improve coverage --- gmso/tests/test_gro.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gmso/tests/test_gro.py b/gmso/tests/test_gro.py index 75534fc13..b3f6f38d6 100644 --- a/gmso/tests/test_gro.py +++ b/gmso/tests/test_gro.py @@ -48,6 +48,10 @@ def test_write_gro(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.save("out.gro") + def test_write_gro_with_shift_coord(self): + top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) + top.save("out.gro", shift_coord=True) + def test_write_gro_non_orthogonal(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.box.angles = u.degree * [90, 90, 120] From 8454dab87aca907b36a7a51e4f34298a1677bb11 Mon Sep 17 00:00:00 2001 From: Co Quach <43968221+daico007@users.noreply.github.com> Date: Mon, 28 Aug 2023 02:01:20 -0500 Subject: [PATCH 3/8] Update gmso/formats/gro.py Co-authored-by: CalCraven <54594941+CalCraven@users.noreply.github.com> --- gmso/formats/gro.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gmso/formats/gro.py b/gmso/formats/gro.py index a1bb34327..e85d6c5d9 100644 --- a/gmso/formats/gro.py +++ b/gmso/formats/gro.py @@ -122,8 +122,9 @@ def write_gro(top, filename, precision=3, shift_coord=False): precision : int, optional, default=3 The number of sig fig to write out the position in. shift_coord : bool, optional, default=False - If True, shift the coordinate to be all sites to ensure - all coordinates are non-negative. + If True, shift the coordinates of all sites by the minimum position + to ensure all sites have non-negative positions. This is not a requirement + for GRO files, but can be useful for visualizing. Notes ----- From 2ef6eecbdd3bc596fccf0e52724904bc5d7aa8f0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 07:01:31 +0000 Subject: [PATCH 4/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- gmso/formats/gro.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gmso/formats/gro.py b/gmso/formats/gro.py index e85d6c5d9..1649547b4 100644 --- a/gmso/formats/gro.py +++ b/gmso/formats/gro.py @@ -122,7 +122,7 @@ def write_gro(top, filename, precision=3, shift_coord=False): precision : int, optional, default=3 The number of sig fig to write out the position in. shift_coord : bool, optional, default=False - If True, shift the coordinates of all sites by the minimum position + If True, shift the coordinates of all sites by the minimum position to ensure all sites have non-negative positions. This is not a requirement for GRO files, but can be useful for visualizing. From 344d57343a44d8c3186bf16c071c4c01fd5e2b9d Mon Sep 17 00:00:00 2001 From: Co Quach Date: Mon, 28 Aug 2023 02:03:29 -0500 Subject: [PATCH 5/8] add additional check for test_write_gro_with_shift_coord --- gmso/tests/test_gro.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gmso/tests/test_gro.py b/gmso/tests/test_gro.py index b3f6f38d6..b66011d24 100644 --- a/gmso/tests/test_gro.py +++ b/gmso/tests/test_gro.py @@ -48,6 +48,9 @@ def test_write_gro(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.save("out.gro") + read_top = Topology("out.gro") + assert np.all(list(map(lambda x: x.positions >= 0, read_top.sites))) + def test_write_gro_with_shift_coord(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.save("out.gro", shift_coord=True) From 24be7e16a3f68e90e190dba82d9711c40baaea99 Mon Sep 17 00:00:00 2001 From: Co Quach Date: Mon, 28 Aug 2023 02:09:19 -0500 Subject: [PATCH 6/8] change precision to n_decimals --- gmso/formats/gro.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gmso/formats/gro.py b/gmso/formats/gro.py index 1649547b4..e4c6c2b02 100644 --- a/gmso/formats/gro.py +++ b/gmso/formats/gro.py @@ -103,7 +103,7 @@ def read_gro(filename): @saves_as(".gro") -def write_gro(top, filename, precision=3, shift_coord=False): +def write_gro(top, filename, n_decimals=3, shift_coord=False): """Write a topology to a gro file. The Gromos87 (gro) format is a common plain text structure file used @@ -119,7 +119,7 @@ def write_gro(top, filename, precision=3, shift_coord=False): The `topology` to write out to the gro file. filename : str or file object The location and name of file to save to disk. - precision : int, optional, default=3 + n_decimals : int, optional, default=3 The number of sig fig to write out the position in. shift_coord : bool, optional, default=False If True, shift the coordinates of all sites by the minimum position @@ -147,7 +147,7 @@ def write_gro(top, filename, precision=3, shift_coord=False): ) ) out_file.write("{:d}\n".format(top.n_sites)) - out_file.write(_prepare_atoms(top, pos_array, precision)) + out_file.write(_prepare_atoms(top, pos_array, n_decimals)) out_file.write(_prepare_box(top)) @@ -166,7 +166,7 @@ def _validate_positions(pos_array): return pos_array -def _prepare_atoms(top, updated_positions, precision): +def _prepare_atoms(top, updated_positions, n_decimals): out_str = str() warnings.warn( "Residue information is parsed from site.molecule," @@ -226,8 +226,8 @@ def _prepare_atoms(top, updated_positions, precision): atom_id = atom_id % max_val res_id = res_id % max_val - varwidth = 5 + precision - crdfmt = f"{{:{varwidth}.{precision}f}}" + varwidth = 5 + n_decimals + crdfmt = f"{{:{varwidth}.{n_decimals}f}}" # preformat pos str crt_x = crdfmt.format(pos[0].in_units(u.nm).value)[:varwidth] From cd7de1fa9c5c8110b51b3757bd021ac03f8eda21 Mon Sep 17 00:00:00 2001 From: Co Quach Date: Wed, 6 Sep 2023 17:51:11 -0500 Subject: [PATCH 7/8] vectorize shift_coord --- gmso/formats/gro.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gmso/formats/gro.py b/gmso/formats/gro.py index e4c6c2b02..f9315648f 100644 --- a/gmso/formats/gro.py +++ b/gmso/formats/gro.py @@ -159,10 +159,10 @@ def _validate_positions(pos_array): "in order to ensure all coordinates are non-negative." ) min_xyz = np.min(pos_array, axis=0) - for i, minimum in enumerate(min_xyz): - if minimum < 0.0: - for loc in pos_array: - loc[i] = loc[i] - minimum + min_xyz0 = np.where(min_xyz < 0, min_xyz, 0) * min_xyz.units + + pos_array -= min_xyz0 + return pos_array From 552535020c773764c66f3889adb52328ef2e38cb Mon Sep 17 00:00:00 2001 From: Co Quach Date: Wed, 6 Sep 2023 21:53:55 -0500 Subject: [PATCH 8/8] address remaining comment --- gmso/tests/test_gro.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gmso/tests/test_gro.py b/gmso/tests/test_gro.py index b66011d24..946d9f5dc 100644 --- a/gmso/tests/test_gro.py +++ b/gmso/tests/test_gro.py @@ -48,13 +48,13 @@ def test_write_gro(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.save("out.gro") - read_top = Topology("out.gro") - assert np.all(list(map(lambda x: x.positions >= 0, read_top.sites))) - def test_write_gro_with_shift_coord(self): - top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) + top = from_parmed(pmd.load_file(get_fn("ethane.mol2"), structure=True)) top.save("out.gro", shift_coord=True) + read_top = Topology.load("out.gro") + assert np.all(list(map(lambda x: x.position >= 0, read_top.sites))) + def test_write_gro_non_orthogonal(self): top = from_parmed(pmd.load_file(get_fn("ethane.gro"), structure=True)) top.box.angles = u.degree * [90, 90, 120]