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

Added new to_hoomd method #212

Merged
merged 12 commits into from
Feb 20, 2024
1 change: 1 addition & 0 deletions ChangeLog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Added
- ``simplices``, ``equations``, and ``face_centroids`` properties for the
ConvexPolyhedron class.
- Additional pytests for surface area, volume, centroid, moment of inertia, and equations properties.
- Added ``to_hoomd`` export method for use with simulation tools

Changed
~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions Credits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Jen Bradley
* Added ``simplices``, ``equations``, and ``face_centroids`` properties to the
ConvexPolyhedron class.
* Optimized pytest configurations for more efficient use of local and remote resources.
* Added ``to_hoomd`` export method for use with simulation tools.
DomFijan marked this conversation as resolved.
Show resolved Hide resolved

Domagoj Fijan

Expand Down
39 changes: 39 additions & 0 deletions coxeter/shapes/convex_spheropolygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,42 @@ def _plato_primitive(self, backend):
vertices=verts[:, :2],
radius=self.radius,
)

def to_hoomd(self):
"""Get a json-serializable subset of ConvexSpheropolygon properties.
janbridley marked this conversation as resolved.
Show resolved Hide resolved

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
janbridley marked this conversation as resolved.
Show resolved Hide resolved
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For a ConvexSpheropolygon, the following properties are stored:

* vertices (list(list)):
The vertices of the shape.
janbridley marked this conversation as resolved.
Show resolved Hide resolved
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
* sweep_radius (float):
The rounding radius of the shape.
* area (float)
The area of the shape.
* moment_inertia (list(list))
The shape's inertia tensor.

Returns
-------
dict
Dict containing a subset of shape properties.
janbridley marked this conversation as resolved.
Show resolved Hide resolved
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
janbridley marked this conversation as resolved.
Show resolved Hide resolved
hoomd_dict = {
"vertices": self.vertices.tolist(),
"centroid": self.centroid.tolist(),
"sweep_radius": self.radius,
"area": self.area,
"moment_inertia": self.inertia_tensor.tolist(),
}
self.centroid = old_centroid
return hoomd_dict
36 changes: 36 additions & 0 deletions coxeter/shapes/convex_spheropolyhedron.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,39 @@ def _plato_primitive(self, backend):
vertices=self.vertices,
radius=self.radius,
)

def to_hoomd(self):
"""Get a json-serializable subset of ConvexSpheropolyhedron properties.

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For a ConvexSpheropolyhedron, the following properties are stored:

* vertices (list(list)):
The vertices of the shape.
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
DomFijan marked this conversation as resolved.
Show resolved Hide resolved
* sweep_radius (float):
The rounding radius of the shape.
* volume (float)
The volume of the shape.

Returns
-------
dict
Dict containing a subset of shape properties.
"""
old_centroid = self._polyhedron.centroid
self._polyhedron.centroid = np.array([0, 0, 0])
hoomd_dict = {
"vertices": self.vertices.tolist(),
"centroid": self._polyhedron.centroid.tolist(),
"sweep_radius": self.radius,
"volume": self.volume,
}
self._polyhedron.centroid = old_centroid
return hoomd_dict
42 changes: 42 additions & 0 deletions coxeter/shapes/ellipsoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,45 @@ def __repr__(self):
f"coxeter.shapes.Ellipsoid(a={self.a}, b={self.b}, c={self.c}, "
f"center={self.centroid.tolist()})"
)

def to_hoomd(self):
"""Get a json-serializable subset of Ellipsoid properties.

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For an Ellipsoid, the following properties are stored:

* a (float):
half axis of ellipsoid in the x direction
* b (float):
half axis of ellipsoid in the y direction
* c (float):
half axis of ellipsoid in the z direction
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
* volume (float)
The volume of the shape.
* moment_inertia (list(list))
The shape's inertia tensor.

Returns
-------
dict
Dict containing a subset of shape properties.
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
hoomd_dict = {
"a": self.a,
"b": self.b,
"c": self.c,
"centroid": self.centroid.tolist(),
"volume": self.volume,
"moment_inertia": self.inertia_tensor.tolist(),
}
self.centroid = old_centroid
return hoomd_dict
39 changes: 39 additions & 0 deletions coxeter/shapes/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,3 +761,42 @@ def _plato_primitive(self, backend):
colors=np.array([[0.5, 0.5, 0.5, 1]]),
vertices=verts[:, :2],
)

def to_hoomd(self):
"""Get a json-serializable subset of Polygon properties.

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For a Polygon or ConvexPolygon, the following properties are stored:

* vertices (list(list)):
The vertices of the shape.
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
* sweep_radius (float):
The rounding radius of the shape (0.0).
* area (float)
The area of the shape.
* moment_inertia (list(list))
The shape's inertia tensor.

Returns
-------
dict
Dict containing a subset of shape properties.
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
hoomd_dict = {
"vertices": self.vertices.tolist(),
"centroid": self.centroid.tolist(),
"sweep_radius": 0.0,
"area": self.area,
"moment_inertia": self.inertia_tensor.tolist(),
}
self.centroid = old_centroid
return hoomd_dict
42 changes: 42 additions & 0 deletions coxeter/shapes/polyhedron.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,3 +973,45 @@ def _plato_primitive(self, backend):
indices=self.faces,
shape_colors=np.array([[0.5, 0.5, 0.5, 1]]),
)

def to_hoomd(self):
"""Get a json-serializable subset of Polyhedron properties.

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For a Polyhedron or ConvexPolyhedron, the following properties are stored:

* vertices (list(list)):
The vertices of the shape.
* faces (list(list)):
The faces of the shape.
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
* sweep_radius (float):
The rounding radius of the shape (0.0).
* volume (float)
The volume of the shape.
* moment_inertia (list(list))
The shape's inertia tensor.

Returns
-------
dict
Dict containing a subset of shape properties.
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
hoomd_dict = {
"vertices": self.vertices.tolist(),
"faces": [face.tolist() for face in self.faces],
"centroid": self.centroid.tolist(),
"sweep_radius": 0.0,
"volume": self.volume,
"moment_inertia": self.inertia_tensor.tolist(),
}
self.centroid = old_centroid
return hoomd_dict
36 changes: 36 additions & 0 deletions coxeter/shapes/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,39 @@ def _plato_primitive(self, backend):
colors=np.array([[0.5, 0.5, 0.5, 1]]),
radii=[self.radius],
)

def to_hoomd(self):
"""Get a dict of json-serializable subset of Sphere properties.

The json-serializable output of the to_hoomd method can be directly imported
into data management tools like Signac. This data can then be queried for use in
HOOMD simulations. Key naming matches HOOMD integrators: for example, the
moment_inertia key links to data from coxeter's inertia_tensor.

For a Sphere, the following properties are stored:

* diameter (float):
The diameter of the sphere, equal to twice the radius.
* centroid (list(float))
The centroid of the shape.
This is set to [0,0,0] to improve HOOMD performance.
* volume (float)
The volume of the shape.
* moment_inertia (list(list))
The shape's inertia tensor.

Returns
-------
dict
Dict containing a subset of shape properties.
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
hoomd_dict = {
"diameter": self.radius * 2,
"centroid": self.centroid.tolist(),
"volume": self.volume,
"moment_inertia": self.inertia_tensor.tolist(),
}
self.centroid = old_centroid
return hoomd_dict
17 changes: 17 additions & 0 deletions tests/test_ellipsoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,20 @@ def test_get_set_minimal_centered_bounding_circle_radius(a, b, c, center):
def test_repr():
ellipsoid = Ellipsoid(1, 2, 3, [1, 2, 3])
assert str(ellipsoid), str(eval(repr(ellipsoid)))


@given(floats(0.1, 1000), floats(0.1, 1000), floats(0.1, 1000))
def test_to_hoomd(a, b, c):
ellipsoid = Ellipsoid(a, b, c)
dict_keys = ["a", "b", "c", "centroid", "volume", "moment_inertia"]
dict_vals = [
ellipsoid.a,
ellipsoid.b,
ellipsoid.c,
[0, 0, 0],
ellipsoid.volume,
ellipsoid.inertia_tensor,
]
hoomd_dict = ellipsoid.to_hoomd()
for key, val in zip(dict_keys, dict_vals):
assert np.allclose(hoomd_dict[key], val), f"{key}"
18 changes: 18 additions & 0 deletions tests/test_polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,3 +595,21 @@ def test_repr_nonconvex(square):

def test_repr_convex(convex_square):
assert str(convex_square), str(eval(repr(convex_square)))


@given(EllipseSurfaceStrategy)
def test_to_hoomd(points):
hull = ConvexHull(points)
poly = polygon_from_hull(points[hull.vertices])
poly.centroid = [0, 0, 0]
dict_keys = ["vertices", "centroid", "sweep_radius", "area", "moment_inertia"]
dict_vals = [
poly.vertices,
[0, 0, 0],
0,
poly.area,
poly.inertia_tensor,
]
hoomd_dict = poly.to_hoomd()
for key, val in zip(dict_keys, dict_vals):
assert np.allclose(hoomd_dict[key], val), f"{key}"
19 changes: 19 additions & 0 deletions tests/test_polyhedron.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,22 @@ def test_find_equations_and_normals(poly):
ppoly._find_equations()
assert np.allclose(poly.equations, ppoly._equations)
assert np.allclose(poly.normals, ppoly.normals)


@named_solids_mark
def test_to_hoomd(poly):
poly.centroid = [0, 0, 0]
dict_keys = ["vertices", "centroid", "sweep_radius", "volume", "moment_inertia"]
dict_vals = [
poly.vertices,
[0, 0, 0],
0,
poly.volume,
poly.inertia_tensor,
]
hoomd_dict = poly.to_hoomd()
for key, val in zip(dict_keys, dict_vals):
assert np.allclose(hoomd_dict[key], val), f"{key}"

for i, face in enumerate(poly.faces):
assert np.allclose(face, hoomd_dict["faces"][i])
15 changes: 15 additions & 0 deletions tests/test_sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,18 @@ def test_get_set_minimal_centered_bounding_circle_radius(r, center):
def test_repr():
sphere = Sphere(1, [1, 2, 3])
assert str(sphere), str(eval(repr(sphere)))


@given(floats(0.1, 1000))
def test_to_hoomd(r):
sphere = Sphere(r)
dict_keys = ["diameter", "centroid", "volume", "moment_inertia"]
dict_vals = [
sphere.radius * 2,
[0, 0, 0],
sphere.volume,
sphere.inertia_tensor,
]
hoomd_dict = sphere.to_hoomd()
for key, val in zip(dict_keys, dict_vals):
assert np.allclose(hoomd_dict[key], val), f"{key}"
20 changes: 19 additions & 1 deletion tests/test_spheropolyhedron.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from hypothesis.strategies import floats
from pytest import approx

from conftest import make_sphero_cube
from conftest import make_sphero_cube, named_catalan_mark
from coxeter.shapes import ConvexSpheropolyhedron


@given(radius=floats(0.1, 1))
Expand Down Expand Up @@ -120,3 +121,20 @@ def test_inside_boundaries():
def test_repr():
sphero_cube = make_sphero_cube(radius=1)
assert str(sphero_cube), str(eval(repr(sphero_cube)))


@given(r=floats(0.01, 1))
@named_catalan_mark
def test_to_hoomd(poly, r):
poly.centroid = [0, 0, 0]
poly = ConvexSpheropolyhedron(poly.vertices, r)
dict_keys = ["vertices", "centroid", "sweep_radius", "volume"]
dict_vals = [
poly.vertices,
[0, 0, 0],
poly.radius,
poly.volume,
]
hoomd_dict = poly.to_hoomd()
for key, val in zip(dict_keys, dict_vals):
assert np.allclose(hoomd_dict[key], val), f"{key}"