Skip to content
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.
Comment thread
DomFijan marked this conversation as resolved.
Outdated

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.
Comment thread
janbridley marked this conversation as resolved.
Outdated

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
Comment thread
janbridley marked this conversation as resolved.
Outdated
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.
Comment thread
janbridley marked this conversation as 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.
Comment thread
janbridley marked this conversation as resolved.
Outdated
"""
old_centroid = self.centroid
self.centroid = np.array([0, 0, 0])
Comment thread
janbridley marked this conversation as resolved.
Outdated
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.
Comment thread
DomFijan marked this conversation as resolved.
Outdated
* 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
Comment thread
DomFijan marked this conversation as resolved.
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}"