Shapes Module#

Overview

Define shape classes.

This subpackage is the core of coxeter and defines various shapes in two and three dimensions. Shapes support standard calculations like volume and area, and they take care of various conveniences such as orienting polyhedron faces and automatically identifying convex hulls of points.

Classes:

Circle(radius[, center])

A circle with the given radius.

ConvexPolygon(vertices[, normal, ...])

A convex polygon.

ConvexPolyhedron(vertices)

A convex polyhedron.

ConvexSpheropolygon(vertices, radius[, normal])

A convex spheropolygon.

ConvexSpheropolyhedron(vertices, radius)

A convex spheropolyhedron.

Ellipse(a, b[, center])

An ellipse with principal axes a and b.

Ellipsoid(a, b, c[, center])

An ellipsoid with principal axes a, b, and c.

Polygon(vertices[, normal, ...])

A simple (non-self-overlapping) polygon.

Polyhedron(vertices, faces[, faces_are_convex])

A three-dimensional polytope.

Shape()

An abstract representation of a shape in N dimensions.

Shape2D()

An abstract representation of a shape in 2 dimensions.

Shape3D()

An abstract representation of a shape in 3 dimensions.

Sphere(radius[, center])

A sphere with the given radius.

class coxeter.shapes.Circle(radius, center=(0, 0, 0))#

Bases: Shape2D

A circle with the given radius.

Parameters:
  • radius (float) – Radius of the circle.

  • center (Sequence[float]) – The coordinates of the centroid of the circle (Default value: (0, 0, 0)).

Example

>>> circle = coxeter.shapes.circle.Circle(radius=1.0, center=(1, 1, 1))
>>> import numpy as np
>>> assert np.isclose(circle.area, np.pi)
>>> circle.centroid
array([1, 1, 1])
>>> assert np.isclose(circle.circumference, 2 * np.pi)
>>> circle.eccentricity
0
>>> circle.gsd_shape_spec
{'type': 'Sphere', 'diameter': 2.0}
>>> circle.iq
1
>>> assert np.isclose(circle.perimeter, 2 * np.pi)
>>> assert np.allclose(
...   circle.planar_moments_inertia,
...   (5. / 4. * np.pi, 5. / 4. * np.pi, np.pi))
>>> assert np.isclose(circle.polar_moment_inertia, 5. / 2. * np.pi)
>>> circle.radius
1.0

Attributes:

area

Get the area of the circle.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

circumference

Get the circumference, alias for Circle.perimeter.

eccentricity

Get the eccentricity of the circle.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_bounding_circle

Get the largest bounded circle.

maximal_centered_bounded_circle

Get the largest bounded concentric circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the smallest bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

perimeter

Get the perimeter of the circle.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

radius

Get the radius of the circle.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Determine whether a set of points are contained in this circle.

plot()

Plot the shape.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property area#

Get the area of the circle.

Type:

float

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

property circumference#

Get the circumference, alias for Circle.perimeter.

Type:

float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property eccentricity#

Get the eccentricity of the circle.

This is 0 by definition for circles.

Type:

float

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

For non-orientable 2D shapes, the inertia tensor can be trivially constructed from the polar moment of inertia. This calculation assumes that the shape lies in the \(xy\)-plane. Shapes that can be rotated relative to this plane must define their own methods.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

This is 1 by definition for circles.

Type:

float

is_inside(points)#

Determine whether a set of points are contained in this circle.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the circle.

Return type:

\((N, )\) numpy.ndarray

Example

>>> circle = coxeter.shapes.Circle(1.0)
>>> circle.is_inside([[0, 0, 0], [20, 20, 20]])
array([ True, False])
property maximal_bounded_circle#

Get the largest bounded circle.

The largest circle contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the incircle of a polygon), this property is named as an explicit analog to minimal_bounding_circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_bounding_circle#

Get the largest bounded circle.

Type:

Circle

property maximal_centered_bounded_circle#

Get the largest bounded concentric circle.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the smallest bounding circle.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

property perimeter#

Get the perimeter of the circle.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments and the product of inertia are defined by the formulas:

\[\begin{split}\begin{align} I_x &= {\int \int}_A y^2 dA = \frac{\pi}{4} r^4 = \frac{Ar^2}{4} \\ I_y &= {\int \int}_A x^2 dA = \frac{\pi}{4} r^4 = \frac{Ar^2}{4} \\ I_{xy} &= {\int \int}_A xy dA = 0 \\ \end{align}\end{split}\]

These formulas are given here. Note that the product moment is zero by symmetry.

Type:

list[float, float, float]

plot()#

Plot the shape.

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

property radius#

Get the radius of the circle.

Type:

float

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

class coxeter.shapes.ConvexPolygon(vertices, normal=None, planar_tolerance=1e-05)#

Bases: Polygon

A convex polygon.

The polygon is embedded in 3-dimensions, so the normal vector determines which way is “up”.

Parameters:
  • vertices (\((N, 3)\) or \((N, 2)\) numpy.ndarray) – The vertices of the polygon. They need not be sorted since the order will be determined by the hull.

  • normal (sequence of length 3 or None) – The normal vector to the polygon. If None, the normal is computed by taking the cross product of the vectors formed by the first three vertices np.cross(vertices[2, :] - vertices[1, :], vertices[0, :] - vertices[1, :]). This choice is made so that if the provided vertices are in the \(xy\) plane and are specified in counterclockwise order, the resulting normal is the \(z\) axis. Since this arbitrary choice may not preserve the orientation of the provided vertices, users may provide a normal instead (Default value: None).

  • planar_tolerance (float) – The tolerance to use to verify that the vertices are planar. Providing this argument may be necessary if you have a large number of vertices and are rotated significantly out of the plane.

Example

>>> square = coxeter.shapes.ConvexPolygon(
...   [[1, 1], [-1, -1], [1, -1], [-1, 1]])
>>> import numpy as np
>>> assert np.isclose(square.area, 4.0)
>>> assert np.isclose(
...   square.minimal_bounding_circle.radius,
...   np.sqrt(2.))
>>> square.center
array([0., 0., 0.])
>>> assert np.isclose(
...   square.circumcircle.radius,
...   np.sqrt(2.))
>>> square.gsd_shape_spec
{'type': 'Polygon', 'vertices': [[1.0, 1.0, 0.0], [-1.0, 1.0, 0.0],
[-1.0, -1.0, 0.0], [1.0, -1.0, 0.0]]}
>>> assert np.isclose(square.maximal_centered_bounded_circle.radius, 1.0)
>>> assert np.allclose(
...   square.inertia_tensor,
...   [[0., 0., 0.],
...    [0., 0., 0.],
...    [0., 0., 8. / 3.]])
>>> square.normal
array([0., 0., 1.])
>>> assert np.allclose(
...   square.planar_moments_inertia,
...   (4. / 3., 4. / 3., 0.))
>>> assert np.isclose(square.polar_moment_inertia, 8. / 3.)
>>> assert np.isclose(square.signed_area, 4.0)
>>> square.vertices
array([[ 1.,  1.,  0.],
       [-1.,  1.,  0.],
       [-1., -1.,  0.],
       [ 1., -1.,  0.]])

Attributes:

area

Get or set the polygon's area.

bounding_circle

Get the minimal bounding circle.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

circumcircle

Get the polygon's circumcircle.

circumcircle_radius

Get the radius of the polygon's circumcircle.

gsd_shape_spec

Get a complete GSD specification.

incircle

Get the polygon's incircle.

incircle_from_center

Get the largest concentric inscribed circle.

incircle_radius

Get the radius of the polygon's incircle.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_centered_bounded_circle

Get the largest bounded concentric circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the minimal bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

normal

Get the normal vector.

num_vertices

Get the number of vertices.

perimeter

Get the perimeter of the polygon.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

signed_area

Get the polygon's area.

vertices

Get the vertices of the polygon.

Methods:

compute_form_factor_amplitude(q[, density])

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Implement a simple point-in-polygon algorithm based on winding number.

plot([ax, center, plot_verts, label_verts])

Plot the polygon.

to_hoomd()

Get a JSON-serializable subset of Polygon properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property area#

Get or set the polygon’s area.

To get the area, we simply compute the signed area and take the absolute value.

Type:

float

property bounding_circle#

Get the minimal bounding circle.

Type:

Circle

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

The centroid of a polygon is calculated according to this formula.

Type:

\((3, )\) numpy.ndarray of float

property circumcircle#

Get the polygon’s circumcircle.

A circumcircle must touch all the points of the polygon. A circumcircle exists if and only if there is a point equidistant from all the vertices. The circumcircle is found by finding the least squares solution of the overdetermined system of linear equations defined by this constraint, and the circumcircle only exists if the resulting solution has no residual.

Raises:

RuntimeError – If no circumcircle exists for this polygon.:

Type:

Circle

property circumcircle_radius#

Get the radius of the polygon’s circumcircle.

Type:

float

compute_form_factor_amplitude(q, density=1.0)#

Calculate the form factor intensity.

The form factor amplitude of a polygon is computed according to the derivation provided in this dissertation: https://deepblue.lib.umich.edu/handle/2027.42/120906. The Kelvin-Stokes theorem allows reducing the surface integral to a line integral around the boundary.

For more generic information about form factors, see Shape.compute_form_factor_amplitude.

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property incircle#

Get the polygon’s incircle.

Note

The incircle of a polygon is defined as the circle contained within the polygon that is tangent to all its faces. This condition uniquely defines the circle, if it exists. The set of equations defined by this equation is solved using a least squares approach, with the magnitude of the residual used to determine whether or not the incircle exists.

Type:

Sphere

property incircle_from_center#

Get the largest concentric inscribed circle.

Type:

Circle

property incircle_radius#

Get the radius of the polygon’s incircle.

Type:

float

property inertia_tensor#

Get the inertia tensor.

The inertia tensor is computed for the polygon embedded in \(\mathbb{R}^3\). This computation proceeds by first computing the polar moment of inertia for the polygon in the \(xy\)-plane relative to its centroid. The tensor is then rotated back to the orientation of the polygon and shifted to the original centroid.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the area of a shape to the area of a circle with the same perimeter. Given a shape of area \(A\) and perimeter \(p\), the circle with the same perimeter has radius \(r_p = \frac{p}{2\pi}\) and therefore has an area \(A_{circle} = \pi r_p^2 = \frac{p^2}{4\pi}\). Therefore, we have that:

\[\begin{split}\begin{align} IQ &= \frac{A}{A_{circle}} \\ &= \frac{4\pi A}{p^2} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Implement a simple point-in-polygon algorithm based on winding number.

The code in this function is based on implementation in [Dic19] which is licensed under the BSD-3 license.

Given a closed, possibly non-simple polygon described as a list of vertices in \(\mathbb{R}^2\) and a point that doesn’t lie directly on the path of the polygon, we’d like to compute the winding number of the polygon around the point. To achieve this, we place the point at the origin. Divide the remainder of the plane (i.e., \(\mathbb{R}^2\) minus the origin) into two halves, \(L\) and \(R\), defined as follows:

\[ \begin{align}\begin{aligned}L = {(x, y) | x < 0 \lor x = 0 \land y < 0}\\R = {(x, y) | x > 0 \lor x = 0 \land y > 0}\end{aligned}\end{align} \]

That is, \(R\) contains all points with argument in the half-closed interval \(\left[-\frac{\pi}{2},\frac{\pi}{2}\right)\), and \(L\) contains all others. Note that with these definitions, \(L\) and \(R\) are both convex: a line segment between two points in \(R\) lies entirely in \(R\), and similarly for \(L\). In particular, a line segment between two points can only pass through the origin if one of those points is in \(L\) and the other in \(R\). Now, we follow the edges of the polygon, keeping track of how many times we move between \(L\) and \(R\). For each move from \(L\) to \(R\) (or vice versa), we also need to compute whether the edge passes above or below the origin, to compute its contribution to the total winding number. From the comment above, we can safely ignore all edges that lie entirely within either \(L\) or \(R\).

Note

Points on the boundary of the shape will return False.

Parameters:

points (\((N, 3)\) or \((N, 2)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the polyhedron.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_circle#

Get the largest bounded circle.

The largest circle contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the incircle of a polygon), this property is named as an explicit analog to minimal_bounding_circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_centered_bounded_circle#

Get the largest bounded concentric circle.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the minimal bounding circle.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

property normal#

Get the normal vector.

Type:

\((3, )\) numpy.ndarray of float

property num_vertices#

Get the number of vertices.

Type:

int

property perimeter#

Get the perimeter of the polygon.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments and the product of inertia are defined by the formulas:

\[\begin{split}\begin{align} I_x &= {\int \int}_A y^2 dA \\ I_y &= {\int \int}_A x^2 dA \\ I_{xy} &= {\int \int}_A xy dA \\ \end{align}\end{split}\]

To compute this for a polygon, we discretize the sum:

\[\begin{split}\begin{align} I_x &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (y_i^2 + y_i*y_{i+1} + y_{i+1}^2) \\ I_y &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (x_i^2 + x_i*x_{i+1} + x_{i+1}^2) \\ I_{xy} &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (x_i y_{i+1} + 2 x_i y_i + 2 x_{i+1} y_{i+1} + x_{i+1} y_i) \\ \end{align}\end{split}\]

These formulas can be derived as described here.

Note that the moments are always calculated about an axis perpendicular to the polygon, i.e. the normal vector is aligned with the \(z\) axis before the moments are calculated. This alignment should be considered when computing the moments for polygons embedded in three-dimensional space that are rotated out of the \(xy\) plane, since the planar moments are invariant to this orientation. The exact rotation used for this computation (i.e. changes in the \(x\) and \(y\) position) should not be relied upon.

Type:

list[float, float, float]

plot(ax=None, center=False, plot_verts=False, label_verts=False)#

Plot the polygon.

Note that the polygon is always rotated into the \(xy\) plane and plotted in two dimensions.

Parameters:
  • ax (matplotlib.axes.Axes) – The axes on which to draw the polygon. Axes will be created if this is None (Default value: None).

  • center (bool) – If True, the polygon vertices are plotted relative to its center (Default value: False).

  • plot_verts (bool) – If True, scatter points will be added at the vertices (Default value: False).

  • label_verts (bool) – If True, vertex indices will be added next to the vertices (Default value: False).

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

property signed_area#

Get the polygon’s area.

To support polygons embedded in 3 dimensional space, we employ a projection- and rescaling-based algorithm described here. Specifically, the polygon is projected onto the plane it is “most parallel” to, the area of the projected polygon is computed, then the area is rescaled by the component of the normal in the projected dimension.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • 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 containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the polygon.

Type:

\((N_{verts}, 3)\) numpy.ndarray of float

class coxeter.shapes.ConvexPolyhedron(vertices)#

Bases: Polyhedron

A convex polyhedron.

A convex polyhedron is defined as the convex hull of its vertices. The class is an extension of Polyhedron that builds the faces from the simplices of the convex hull. Simplices are stored and class methods are optimized to make use of the triangulation, as well as special properties of convex solids in three dimensions. This class also includes various additional properties that can be used to characterize geometric features of the polyhedron.

Parameters:

vertices (\((N, 3)\) numpy.ndarray) – The vertices of the polyhedron.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[-1, -1, -1], [-1, -1, 1], [-1, 1, -1], [-1, 1, 1],
...    [1, -1, -1], [1, -1, 1], [1, 1, -1], [1, 1, 1]])
>>> import numpy as np
>>> assert np.isclose(cube.asphericity, 1.5)
>>> bounding_sphere = cube.minimal_bounding_sphere
>>> assert np.isclose(bounding_sphere.radius, np.sqrt(3))
>>> cube.centroid
array([0., 0., 0.])
>>> circumsphere = cube.circumsphere
>>> assert np.isclose(circumsphere.radius, np.sqrt(3))
>>> cube.faces
[array([0, 2, 6, 4], dtype=int32), array([0, 4, 5, 1], dtype=int32),
array([4, 6, 7, 5], dtype=int32), array([0, 1, 3, 2], dtype=int32),
array([2, 3, 7, 6], dtype=int32), array([1, 5, 7, 3], dtype=int32)]
>>> cube.gsd_shape_spec
{'type': 'ConvexPolyhedron', 'vertices': [[-1.0, -1.0, -1.0], [-1.0, -1.0, 1.0],
[-1.0, 1.0, -1.0], [-1.0, 1.0, 1.0], [1.0, -1.0, -1.0], [1.0, -1.0, 1.0],
[1.0, 1.0, -1.0], [1.0, 1.0, 1.0]]}
>>> assert np.allclose(
...   cube.inertia_tensor,
...   np.diag([16. / 3., 16. / 3., 16. / 3.]))
>>> sphere = cube.maximal_centered_bounded_sphere
>>> sphere.radius
1.0
>>> assert np.isclose(cube.iq, np.pi / 6.)
>>> assert np.isclose(cube.mean_curvature, 1.5)
>>> cube.neighbors
[array([1, 2, 3, 4]), array([0, 2, 3, 5]), array([0, 1, 4, 5]),
array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([1, 2, 3, 4])]
>>> cube.normals
array([[-0., -0., -1.],
       [ 0., -1.,  0.],
       [ 1., -0., -0.],
       [-1., -0., -0.],
       [ 0.,  1., -0.],
       [-0., -0.,  1.]])
>>> cube.num_faces
6
>>> cube.num_vertices
8
>>> cube.surface_area
24.0
>>> assert np.isclose(cube.tau, 3. / 8. * np.pi)
>>> cube.vertices
array([[-1., -1., -1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1.,  1.,  1.],
       [ 1., -1., -1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1.,  1.,  1.]])
>>> assert np.isclose(cube.volume, 8.)

Attributes:

asphericity

Get the asphericity as defined in [IES+17].

bounding_sphere

Get the polyhedron's bounding sphere.

center

Alias for centroid.

centroid

Get or set the center of mass.

circumsphere

Get the polyhedron's circumsphere.

circumsphere_from_center

Get the smallest circumscribed sphere centered at the centroid.

circumsphere_radius

Get the radius of the polygon's circumsphere.

edge_lengths

Get the length of each edge of the polyhedron.

edge_vectors

Get the polyhedron's edges as vectors.

edges

Get the polyhedron's edges.

equations

Get plane equations for each face.

face_centroids

Calculate the centroid (center of mass) of each polygonal face.

faces

Get the polyhedron's faces.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

insphere

Get the polyhedron's insphere.

insphere_from_center

Get the largest concentric inscribed sphere.

insphere_radius

Get the radius of the polygon's insphere.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest bounded concentric sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

mean_curvature

The integrated, normalized mean curvature.

minimal_bounding_sphere

Get the polyhedron's bounding sphere.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get the smallest bounding concentric sphere.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

neighbors

Get neighboring pairs of faces.

normals

Get normal vectors for each face.

num_edges

Get the number of edges.

num_faces

Get the number of faces.

num_vertices

Get the number of vertices.

simplices

Output the vertex indices of simplices composing the polyhedron's surface.

surface_area

Get or set the surface area.

tau

Get the parameter \(\tau = \frac{4\pi R^2}{S}\).

vertices

Get the vertices of the polyhedron.

volume

Get or set the polyhedron's volume.

Methods:

compute_form_factor_amplitude(q[, density])

Calculate the form factor intensity.

diagonalize_inertia()

Orient the shape along its principal axes.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

get_dihedral(a, b)

Get the dihedral angle between a pair of faces.

get_face_area([face])

Get the total surface area of a set of faces.

is_inside(points)

Determine whether points are contained in this polyhedron.

merge_faces([atol, rtol])

Merge coplanar faces to a given tolerance.

plot([ax, plot_verts, label_verts])

Plot the polyhedron.

sort_faces()

Reorder faces counterclockwise relatative to the plane they lie on.

to_hoomd()

Get a JSON-serializable subset of Polyhedron properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property asphericity#

Get the asphericity as defined in [IES+17].

Type:

float

property bounding_sphere#

Get the polyhedron’s bounding sphere.

Type:

Sphere

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the center of mass.

The centroid is calculated using the curl theorem over the surface simplices.

Type:

\((3, )\) numpy.ndarray of float

property circumsphere#

Get the polyhedron’s circumsphere.

A circumsphere must touch all the points of the polyhedron. A circumsphere exists if and only if there is a point equidistant from all the vertices. The circumsphere is found by finding the least squares solution of the overdetermined system of linear equations defined by this constraint, and the circumsphere only exists if the resulting solution has no residual.

Raises:

RuntimeError – If no circumsphere exists for this polyhedron.:

Type:

Sphere

property circumsphere_from_center#

Get the smallest circumscribed sphere centered at the centroid.

The requirement that the sphere be centered at the centroid of the shape distinguishes this sphere from most typical circumsphere calculations.

Type:

Sphere

property circumsphere_radius#

Get the radius of the polygon’s circumsphere.

Type:

float

compute_form_factor_amplitude(q, density=1.0)#

Calculate the form factor intensity.

The form factor amplitude of a polyhedron is computed according to the derivation provided in this dissertation: https://deepblue.lib.umich.edu/handle/2027.42/120906. In brief, two applications of Stokes theorem (or to use the names more familiar from elementary vector calculus, the application of the divergence theorem followed by the classic Kelvin-Stokes theorem) are used to reduce the volume integral over a polyhedron into a series of line integrals around the boundaries of each polygonal face.

For more generic information about form factors, see Shape.compute_form_factor_amplitude.

diagonalize_inertia()#

Orient the shape along its principal axes.

The principal axes of a shape are defined by the eigenvectors of the inertia tensor. This method computes the inertia tensor of the shape, diagonalizes it, and then rotates the shape by the corresponding orthogonal transformation.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube.diagonalize_inertia()
>>> cube.vertices
array([[ 1.,  1.,  1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1., -1., -1.],
       [-1.,  1.,  1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1., -1., -1.]])
distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property edge_lengths#

Get the length of each edge of the polyhedron.

edge_lengths are returned in the same order as in edges.

Type:

numpy.ndarray

property edge_vectors#

Get the polyhedron’s edges as vectors.

edge_vectors are returned in the same order as in edges.

Type:

numpy.ndarray

property edges#

Get the polyhedron’s edges.

Results returned as vertex index pairs, with each edge of the polyhedron included exactly once. Edge (i,j) pairs are ordered by vertex index with i<j.

Type:

numpy.ndarray

property equations#

Get plane equations for each face.

Sign convention matches Scipy Convex Hull (ax + by + cz + d = 0).

Type:

\((N, 4)\) numpy.ndarray

property face_centroids#

Calculate the centroid (center of mass) of each polygonal face.

Returns:

Array of centroids for each face.

Return type:

\((N,3)\) numpy.ndarray

property faces#

Get the polyhedron’s faces.

Type:

list(numpy.ndarray)

get_dihedral(a, b)#

Get the dihedral angle between a pair of faces.

The dihedral is computed from the dot product of the face normals.

Parameters:
  • a (int) – The index of the first face.

  • b (int) – The index of the second face.

Returns:

float

Return type:

The dihedral angle in radians.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices, faces=cube.faces)
>>> import numpy as np
>>> assert np.isclose(cube.get_dihedral(1, 2), np.pi / 2.)
get_face_area(face=None)#

Get the total surface area of a set of faces.

Parameters:

faces (int, sequence, or None) – The index of a face or a set of face indices for which to find the area. If None, finds the area of all faces. (Default value: None).

Returns:

:class:`numpy.ndarray`

Return type:

The area of each face.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices,faces=cube.faces)
>>> import numpy as np
>>> assert np.allclose(
...   cube.get_face_area([1, 2, 3]),
...   [4., 4., 4.])
property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

The inertia tensor for convex shapes is computed using the algorithm described in [MT80].

Note

For improved stability, the inertia tensor is computed about the center of mass and then shifted rather than directly computed in the global frame.

Type:

\((3, 3)\) numpy.ndarray

property insphere#

Get the polyhedron’s insphere.

Note

The insphere of a polyhedron is defined as the sphere contained within the polyhedron that is tangent to all its faces. This condition uniquely defines the sphere, if it exists. The set of equations defined by this equation is solved using a least squares approach, with the magnitude of the residual used to determine whether or not the insphere exists.

Type:

Sphere

property insphere_from_center#

Get the largest concentric inscribed sphere.

Type:

Sphere

property insphere_radius#

Get the radius of the polygon’s insphere.

Type:

float

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the volume of a shape to the volume of a sphere with the same perimeter. Given a shape of volume \(A\) and surface \(S\), the sphere with the same surface has radius \(r_S = \sqrt{\frac{S}{4\pi}}\) and therefore has volume \(V_{sphere} = \frac{4}{3} \pi r_S^3 = \frac{S^{3/2}}{\sqrt{4\pi}}\). Taking the ratio of volumes gives:

\[\begin{equation} \frac{V}{V_{sphere}} = \frac{6\sqrt{\pi} V}{S^{3/2}} \end{equation}\]

To avoid inconvenient fractional exponents, the isoperimetric quotient is conventionally defined as the square of this quantity:

\[\begin{split}\begin{align} IQ &= \left(\frac{V}{V_{sphere}}\right)^2 \\ &= \frac{36\pi V^2}{S^3} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this polyhedron.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the polyhedron.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_sphere#

Get the largest bounded sphere.

The largest sphere contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the insphere of a polyhedron), this property is named as an explicit analog to minimal_bounding_sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest bounded concentric sphere.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

property mean_curvature#

The integrated, normalized mean curvature.

This quantity is calculated by the formula \(R = \sum_i (1/2) L_i (\pi - \phi_i) / (4 \pi)\) with edge lengths \(L_i\) and dihedral angles \(\phi_i\) (see [IES+17] for more information).

Type:

float

merge_faces(atol=1e-08, rtol=1e-05)#

Merge coplanar faces to a given tolerance.

Whether or not faces should be merged is determined using numpy.allclose() to compare the plane equations of neighboring faces. Connected components of mergeable faces are then merged into a single face. This method can be safely called many times with different tolerances, however, the operation is destructive in the sense that merged faces cannot be recovered. Users wishing to undo a merge to attempt a less expansive merge must build a new polyhedron.

Parameters:
property minimal_bounding_sphere#

Get the polyhedron’s bounding sphere.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get the smallest bounding concentric sphere.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

property neighbors#

Get neighboring pairs of faces.

The neighbors are provided as a list where the \(i^{\text{th}}\) element is an array of indices of faces that are neighbors of face \(i\).

Type:

list(numpy.ndarray)

property normals#

Get normal vectors for each face.

Type:

\((N, 3)\) numpy.ndarray

property num_edges#

Get the number of edges.

Type:

int

property num_faces#

Get the number of faces.

Type:

int

property num_vertices#

Get the number of vertices.

Type:

int

plot(ax=None, plot_verts=False, label_verts=False)#

Plot the polyhedron.

Note that the ax argument should be a 3D axes object; passing in a 2D axes object will result in wrong behavior.

Parameters:
  • ax (mpl_toolkits.mplot3d.axes3d.Axes3D) – The axes on which to draw the polyhedron. Axes will be created if this is None (Default value: None).

  • plot_verts (bool) – If True, scatter points will be added at the vertices (Default value: False).

  • label_verts (bool) – If True, vertex indices will be added next to the vertices (Default value: False).

property simplices#

Output the vertex indices of simplices composing the polyhedron’s surface.

Returns:

Array of vertex indices of simplices making up the polyhedron’s surface.

Return type:

\((N,3)\) numpy.ndarray

sort_faces()#

Reorder faces counterclockwise relatative to the plane they lie on.

This does NOT change the order of faces in the list.

property surface_area#

Get or set the surface area.

Type:

float

property tau#

Get the parameter \(\tau = \frac{4\pi R^2}{S}\).

This parameter is defined in [NL84] and is closely related to the Pitzer acentric factor. This quantity appears relevant to the third and fourth virial coefficient for hard polyhedron fluids.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • 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 containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the polyhedron.

Type:

\((N, 3)\) numpy.ndarray

property volume#

Get or set the polyhedron’s volume.

Type:

float

class coxeter.shapes.ConvexSpheropolygon(vertices, radius, normal=None)#

Bases: Shape2D

A convex spheropolygon.

Parameters:
  • vertices (\((N, 3)\) or \((N, 2)\) numpy.ndarray) – The vertices of the polygon.

  • radius (float) – The rounding radius of the spheropolygon.

  • normal (sequence of length 3 or None) – The normal vector to the polygon. If None, the normal is computed by taking the cross product of the vectors formed by the first three vertices np.cross(vertices[2, :] - vertices[1, :], vertices[0, :] - vertices[1, :]). Since this arbitrary choice may not preserve the orientation of the provided vertices, users may provide a normal instead (Default value: None).

Example

>>> rounded_tri = coxeter.shapes.ConvexSpheropolygon(
...   [[-1, 0], [0, 1], [1, 0]], radius=.1)
>>> rounded_tri.area
1.5142...
>>> rounded_tri.gsd_shape_spec
{'type': 'Polygon', 'vertices': [[-1.0, 0.0, 0.0],
[0.0, 1.0, 0.0], [1.0, 0.0, 0.0]], 'rounding_radius': 0.1}
>>> rounded_tri.radius
0.1
>>> rounded_tri.signed_area
1.5142...
>>> rounded_tri.vertices
array([[-1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 1.,  0.,  0.]])

Attributes:

area

Get or set the polygon's area.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_centered_bounded_circle

Get the largest concentric bounded circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the smallest bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

normal

Get the normal vector.

num_vertices

Get the number of vertices.

perimeter

Get the perimeter of the spheropolygon.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

polygon

The underlying polygon.

radius

Get or set the rounding radius.

signed_area

Get the signed area of the spheropolygon.

vertices

Get the vertices of the spheropolygon.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Distance to the surface of this shape.

is_inside(points)

Determine whether points are contained in this shape.

plot()

Plot the shape.

to_hoomd()

Get a JSON-serializable subset of ConvexSpheropolygon properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property area#

Get or set the polygon’s area.

To get the area, we simply compute the signed area and take the absolute value.

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Distance to the surface of this shape.

Since the centroid of a spheropolygon is difficult to compute in general, the distance is calculated relative to the centroid of the core polygon. For more general information about this calculation, see Shape.distance_to_surface.

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

For non-orientable 2D shapes, the inertia tensor can be trivially constructed from the polar moment of inertia. This calculation assumes that the shape lies in the \(xy\)-plane. Shapes that can be rotated relative to this plane must define their own methods.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the area of a shape to the area of a circle with the same perimeter. Given a shape of area \(A\) and perimeter \(p\), the circle with the same perimeter has radius \(r_p = \frac{p}{2\pi}\) and therefore has an area \(A_{circle} = \pi r_p^2 = \frac{p^2}{4\pi}\). Therefore, we have that:

\[\begin{split}\begin{align} IQ &= \frac{A}{A_{circle}} \\ &= \frac{4\pi A}{p^2} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this shape.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the shape.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_circle#

Get the largest bounded circle.

The largest circle contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the incircle of a polygon), this property is named as an explicit analog to minimal_bounding_circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_centered_bounded_circle#

Get the largest concentric bounded circle.

This property gives the largest circle that fits in the shape whose center also coincides with the center of the shape.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the smallest bounding circle.

A bounding circle in two dimensions is a circle containing all of the points. There are an infinite set of possible bounding circles for a shape (since any circle that entirely contains a bounding circle is also a bounding circle), so additional constraints must be imposed to define a unique circle. This property provides the smallest bounding circle of a shape.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

This property gives the smallest bounding circle whose center coincides with the center of the shape.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

property normal#

Get the normal vector.

Type:

\((3, )\) numpy.ndarray of float

property num_vertices#

Get the number of vertices.

Type:

int

property perimeter#

Get the perimeter of the spheropolygon.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments of inertia and the product of inertia define the in-plane area distribution.

Type:

list[float, float, float]

plot()#

Plot the shape.

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

property polygon#

The underlying polygon.

Type:

ConvexPolygon

property radius#

Get or set the rounding radius.

Type:

float

property signed_area#

Get the signed area of the spheropolygon.

The area is computed as the sum of the underlying polygon area and the area added by the rounding radius.

to_hoomd()#

Get a JSON-serializable subset of ConvexSpheropolygon 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. Stored values are based on the shape with its centroid at the origin.

For a ConvexSpheropolygon, 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] per HOOMD’s spec.

  • sweep_radius (float):

    The rounding radius of the shape.

  • area (float)

    The area of the shape.

Returns:

Dict containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the spheropolygon.

Type:

\((N_{verts}, 3)\) numpy.ndarray of float

class coxeter.shapes.ConvexSpheropolyhedron(vertices, radius)#

Bases: Shape3D

A convex spheropolyhedron.

A convex spheropolyhedron is defined as a convex polyhedron plus a rounding radius. All properties of the underlying polyhedron (the vertices, the faces and their neighbors, etc.) can be accessed directly through polyhedron.

Parameters:
  • vertices (\((N, 3)\) numpy.ndarray) – The vertices of the underlying polyhedron.

  • radius (float) – The rounding radius of the spheropolyhedron.

Example

>>> spherocube = coxeter.shapes.ConvexSpheropolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]],
...   radius=0.5)
>>> spherocube.gsd_shape_spec
{'type': 'ConvexPolyhedron', 'vertices': [[1.0, 1.0, 1.0], [1.0, -1.0, 1.0],
[1.0, 1.0, -1.0], [1.0, -1.0, -1.0], [-1.0, 1.0, 1.0], [-1.0, -1.0, 1.0],
[-1.0, 1.0, -1.0], [-1.0, -1.0, -1.0]], 'rounding_radius': 0.5}
>>> cube = spherocube.polyhedron
>>> cube.vertices
array([[ 1.,  1.,  1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1., -1., -1.],
       [-1.,  1.,  1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1., -1., -1.]])
>>> spherocube.radius
0.5
>>> spherocube.surface_area
45.991...
>>> spherocube.vertices
array([[ 1.,  1.,  1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1., -1., -1.],
       [-1.,  1.,  1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1., -1., -1.]])
>>> spherocube.volume
25.235...

Attributes:

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest concentric bounded sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

mean_curvature

Get the mean curvature.

minimal_bounding_sphere

Get a bounding sphere sharing the center of this shape.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get a bounding sphere sharing the center of this shape.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

polyhedron

The underlying polyhedron.

radius

The rounding radius.

surface_area

Get the surface area.

vertices

Get the vertices of the spheropolyhedron.

volume

The volume.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

inertia_tensor()

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

is_inside(points)

Determine whether points are contained in this spheropolyhedron.

plot()

Plot the shape.

to_hoomd()

Get a JSON-serializable subset of ConvexSpheropolyhedron properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

inertia_tensor()#

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the volume of a shape to the volume of a sphere with the same perimeter. Given a shape of volume \(A\) and surface \(S\), the sphere with the same surface has radius \(r_S = \sqrt{\frac{S}{4\pi}}\) and therefore has volume \(V_{sphere} = \frac{4}{3} \pi r_S^3 = \frac{S^{3/2}}{\sqrt{4\pi}}\). Taking the ratio of volumes gives:

\[\begin{equation} \frac{V}{V_{sphere}} = \frac{6\sqrt{\pi} V}{S^{3/2}} \end{equation}\]

To avoid inconvenient fractional exponents, the isoperimetric quotient is conventionally defined as the square of this quantity:

\[\begin{split}\begin{align} IQ &= \left(\frac{V}{V_{sphere}}\right)^2 \\ &= \frac{36\pi V^2}{S^3} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this spheropolyhedron.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the spheropolyhedron.

Return type:

\((N, )\) numpy.ndarray

Example

>>> sphero = coxeter.shapes.ConvexSpheropolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]],
...   radius=0.5)
>>> sphero.is_inside([[0, 0, 0], [10, 10, 10]])
array([ True, False])
property maximal_bounded_sphere#

Get the largest bounded sphere.

The largest sphere contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the insphere of a polyhedron), this property is named as an explicit analog to minimal_bounding_sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest concentric bounded sphere.

This property gives the largest sphere that fits in the shape whose center also coincides with the center of the shape.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

property mean_curvature#

Get the mean curvature.

Type:

float

property minimal_bounding_sphere#

Get a bounding sphere sharing the center of this shape.

A bounding sphere of a collection of points in dimensions is a sphere containing all of the points. There are an infinite set of possible bounding spheres for a shape (since any sphere that entirely contains a bounding sphere is also a bounding sphere), so additional constraints must be imposed to define a unique sphere. This property provides the smallest bounding sphere of a shape.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get a bounding sphere sharing the center of this shape.

A bounding sphere of a collection of points in is a sphere containing all of the points. There are an infinite set of possible bounding spheres for a shape (since any sphere that entirely contains a bounding sphere is also a bounding sphere), so additional constraints must be imposed to define a unique sphere. This property provides the smallest bounding sphere of a shape whose center coincides with the center of the shape.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

plot()#

Plot the shape.

property polyhedron#

The underlying polyhedron.

Type:

ConvexPolyhedron

property radius#

The rounding radius.

Type:

float

property surface_area#

Get the surface area.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • sweep_radius (float):

    The rounding radius of the shape.

  • volume (float)

    The volume of the shape.

Returns:

Dict containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the spheropolyhedron.

property volume#

The volume.

Type:

float

class coxeter.shapes.Ellipse(a, b, center=(0, 0, 0))#

Bases: Shape2D

An ellipse with principal axes a and b.

Parameters:
  • a (float) – Principal axis a of the ellipse (radius in the \(x\) direction).

  • b (float) – Principal axis b of the ellipse (radius in the \(y\) direction).

  • center (Sequence[float]) – The coordinates of the centroid of the ellipse (Default value: (0, 0, 0)).

Example

>>> ellipse = coxeter.shapes.Ellipse(1.0, 2.0)
>>> ellipse.a
1.0
>>> ellipse.b
2.0
>>> ellipse.area
6.28318...
>>> ellipse.centroid
array([0, 0, 0])
>>> ellipse.circumference
9.68844...
>>> ellipse.eccentricity
0.86602...
>>> ellipse.gsd_shape_spec
{'type': 'Ellipsoid', 'a': 1.0, 'b': 2.0}
>>> ellipse.iq
0.84116...
>>> ellipse.perimeter
9.68844...
>>> ellipse.polar_moment_inertia
7.85398...

Attributes:

a

Length of principal axis a (radius in the \(x\) direction).

area

Get or set the area.

b

Length of principal axis b (radius in the \(y\) direction).

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

circumference

Alias for Ellipse.perimeter.

eccentricity

The eccentricity.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_centered_bounded_circle

Get the largest bounded concentric circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the smallest bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

perimeter

The perimeter.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Determine whether a set of points are contained in this ellipse.

plot()

Plot the shape.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property a#

Length of principal axis a (radius in the \(x\) direction).

Type:

float

property area#

Get or set the area.

Type:

float

property b#

Length of principal axis b (radius in the \(y\) direction).

Type:

float

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

property circumference#

Alias for Ellipse.perimeter.

Type:

float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property eccentricity#

The eccentricity.

An ellipse’s eccentricity is defined as \(e = \sqrt{1 - \frac{b^2}{a^2}}\) where \(b\) is the length of the smaller semi-axis and \(a\) is the length of the larger semi-axis.

Type:

float

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

For non-orientable 2D shapes, the inertia tensor can be trivially constructed from the polar moment of inertia. This calculation assumes that the shape lies in the \(xy\)-plane. Shapes that can be rotated relative to this plane must define their own methods.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

Type:

float

is_inside(points)#

Determine whether a set of points are contained in this ellipse.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the ellipsoid.

Return type:

\((N, )\) numpy.ndarray

Example

>>> ellipse = coxeter.shapes.Ellipse(1.0, 2.0)
>>> ellipse.is_inside([[0, 0, 0], [100, 1, 1]])
array([ True, False])
property maximal_bounded_circle#

Get the largest bounded circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_centered_bounded_circle#

Get the largest bounded concentric circle.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the smallest bounding circle.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

property perimeter#

The perimeter.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments and the product of inertia are defined by the formulas:

\[\begin{split}\begin{align} I_x &= {\int \int}_A y^2 dA = \frac{\pi}{4} a b^3 = \frac{Ab^2}{4} \\ I_y &= {\int \int}_A x^2 dA = \frac{\pi}{4} a^3 b = \frac{Aa^2}{4} \\ I_{xy} &= {\int \int}_A xy dA = 0 \\ \end{align}\end{split}\]

These formulas are given here. Note that the product moment is zero by symmetry.

Type:

list[float, float, float]

plot()#

Plot the shape.

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

class coxeter.shapes.Ellipsoid(a, b, c, center=(0, 0, 0))#

Bases: Shape3D

An ellipsoid with principal axes a, b, and c.

Parameters:
  • a (float) – Length of the principal semi-axis of the ellipsoid in the \(x\) direction.

  • b (float) – Length of the principal semi-axis of the ellipsoid in the \(y\) direction.

  • c (float) – Length of the principal semi-axis of the ellipsoid in the \(z\) direction.

  • center (Sequence[float]) – The coordinates of the centroid of the ellipsoid (Default value: (0, 0, 0)).

Example

>>> ellipsoid = coxeter.shapes.Ellipsoid(1.0, 3.0, 2.0)
>>> ellipsoid.a
1.0
>>> ellipsoid.b
3.0
>>> ellipsoid.c
2.0
>>> ellipsoid.centroid
array([0, 0, 0])
>>> ellipsoid.gsd_shape_spec
{'type': 'Ellipsoid', 'a': 1.0, 'b': 3.0, 'c': 2.0}
>>> ellipsoid.inertia_tensor
array([[65.34512...,  0.        ,  0.        ],
       [ 0.        , 25.13274...,  0.        ],
       [ 0.        ,  0.        , 50.26548...]])
>>> ellipsoid.iq
0.61161...
>>> ellipsoid.surface_area
48.88214...
>>> ellipsoid.volume
25.13274...

Attributes:

a

Get or set the length of principal axis a (the \(x\) radius).

b

Get or set the length of principal axis b (the \(y\) radius).

c

Get or set the length of principal axis c (the \(z\) radius).

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest bounded concentric sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

minimal_bounding_sphere

Get the smallest bounding sphere.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get the smallest bounding concentric sphere.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

surface_area

Get the surface area.

volume

Get or set the volume.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Determine whether a set of points are contained in this ellipsoid.

plot()

Plot the shape.

to_hoomd()

Get a JSON-serializable subset of Ellipsoid properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property a#

Get or set the length of principal axis a (the \(x\) radius).

Type:

float

property b#

Get or set the length of principal axis b (the \(y\) radius).

Type:

float

property c#

Get or set the length of principal axis c (the \(z\) radius).

Type:

float

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

Assumes a constant density of 1.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the volume of a shape to the volume of a sphere with the same perimeter. Given a shape of volume \(A\) and surface \(S\), the sphere with the same surface has radius \(r_S = \sqrt{\frac{S}{4\pi}}\) and therefore has volume \(V_{sphere} = \frac{4}{3} \pi r_S^3 = \frac{S^{3/2}}{\sqrt{4\pi}}\). Taking the ratio of volumes gives:

\[\begin{equation} \frac{V}{V_{sphere}} = \frac{6\sqrt{\pi} V}{S^{3/2}} \end{equation}\]

To avoid inconvenient fractional exponents, the isoperimetric quotient is conventionally defined as the square of this quantity:

\[\begin{split}\begin{align} IQ &= \left(\frac{V}{V_{sphere}}\right)^2 \\ &= \frac{36\pi V^2}{S^3} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether a set of points are contained in this ellipsoid.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the ellipsoid.

Return type:

\((N, )\) numpy.ndarray

Example

>>> ellipsoid = coxeter.shapes.Ellipsoid(1.0, 2.0, 3.0)
>>> ellipsoid.is_inside([[0, 0, 0], [100, 1, 1]])
array([ True, False])
property maximal_bounded_sphere#

Get the largest bounded sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest bounded concentric sphere.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

property minimal_bounding_sphere#

Get the smallest bounding sphere.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get the smallest bounding concentric sphere.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

plot()#

Plot the shape.

property surface_area#

Get the surface area.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • volume (float)

    The volume of the shape.

  • moment_inertia (list(list))

    The shape’s inertia tensor.

Returns:

Dict containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property volume#

Get or set the volume.

Type:

float

class coxeter.shapes.Polygon(vertices, normal=None, planar_tolerance=1e-05, test_simple=True)#

Bases: Shape2D

A simple (non-self-overlapping) polygon.

The polygon is embedded in 3-dimensions, so the normal vector determines which way is “up”.

Note

This class is designed for polygons without self-intersections, so the internal sorting will automatically result in such intersections being removed.

Parameters:
  • vertices (\((N, 3)\) or \((N, 2)\) numpy.ndarray) – The vertices of the polygon.

  • normal (sequence of length 3 or None) – The normal vector to the polygon. If None, the normal is computed by taking the cross product of the vectors formed by the first three vertices np.cross(vertices[2, :] - vertices[1, :], vertices[0, :] - vertices[1, :]). This choice is made so that if the provided vertices are in the \(xy\) plane and are specified in counterclockwise order, the resulting normal is the \(z\) axis. Since this arbitrary choice may not preserve the orientation of the provided vertices, users may provide a normal instead (Default value: None).

  • planar_tolerance (float) – The tolerance to use to verify that the vertices are planar. Providing this argument may be necessary if you have a large number of vertices and are rotated significantly out of the plane.

  • test_simple (bool) – If True, perform a sanity check on construction that the provided vertices constitute a simple polygon. If this check is omitted, the class may produce invalid results if the user inputs incorrect coordinates, so this flag should be set to False with care.

Example

>>> triangle = coxeter.shapes.Polygon([[-1, 0], [0, 1], [1, 0]])
>>> import numpy as np
>>> assert np.isclose(triangle.area, 1.0)
>>> bounding_circle = triangle.minimal_bounding_circle
>>> assert np.isclose(bounding_circle.radius, 1.0)
>>> assert np.allclose(triangle.center, [0., 1. / 3., 0.])
>>> circumcircle = triangle.circumcircle
>>> assert np.isclose(circumcircle.radius, 1.0)
>>> triangle.gsd_shape_spec
{'type': 'Polygon', 'vertices': [[-1.0, 0.0, 0.0], [0.0, 1.0, 0.0],
[1.0, 0.0, 0.0]]}
>>> assert np.allclose(
...   triangle.inertia_tensor,
...   np.diag([1. / 9., 0., 1. / 3.]))
>>> triangle.normal
array([ 0., -0., -1.])
>>> assert np.allclose(
...   triangle.planar_moments_inertia,
...   (1. / 6., 1. / 6., 0.))
>>> assert np.isclose(triangle.polar_moment_inertia, 1. / 3.)
>>> assert np.isclose(triangle.signed_area, 1.0)

Attributes:

area

Get or set the polygon's area.

bounding_circle

Get the minimal bounding circle.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

circumcircle

Get the polygon's circumcircle.

circumcircle_radius

Get the radius of the polygon's circumcircle.

gsd_shape_spec

Get a complete GSD specification.

incircle

Get the polygon's incircle.

incircle_radius

Get the radius of the polygon's incircle.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_centered_bounded_circle

Get the largest concentric bounded circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the minimal bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

normal

Get the normal vector.

num_vertices

Get the number of vertices.

perimeter

Get the perimeter of the polygon.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

signed_area

Get the polygon's area.

vertices

Get the vertices of the polygon.

Methods:

compute_form_factor_amplitude(q[, density])

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Implement a simple point-in-polygon algorithm based on winding number.

plot([ax, center, plot_verts, label_verts])

Plot the polygon.

to_hoomd()

Get a JSON-serializable subset of Polygon properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property area#

Get or set the polygon’s area.

To get the area, we simply compute the signed area and take the absolute value.

Type:

float

property bounding_circle#

Get the minimal bounding circle.

Type:

Circle

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

The centroid of a polygon is calculated according to this formula.

Type:

\((3, )\) numpy.ndarray of float

property circumcircle#

Get the polygon’s circumcircle.

A circumcircle must touch all the points of the polygon. A circumcircle exists if and only if there is a point equidistant from all the vertices. The circumcircle is found by finding the least squares solution of the overdetermined system of linear equations defined by this constraint, and the circumcircle only exists if the resulting solution has no residual.

Raises:

RuntimeError – If no circumcircle exists for this polygon.:

Type:

Circle

property circumcircle_radius#

Get the radius of the polygon’s circumcircle.

Type:

float

compute_form_factor_amplitude(q, density=1.0)#

Calculate the form factor intensity.

The form factor amplitude of a polygon is computed according to the derivation provided in this dissertation: https://deepblue.lib.umich.edu/handle/2027.42/120906. The Kelvin-Stokes theorem allows reducing the surface integral to a line integral around the boundary.

For more generic information about form factors, see Shape.compute_form_factor_amplitude.

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property incircle#

Get the polygon’s incircle.

Note

The incircle of a polygon is defined as the circle contained within the polygon that is tangent to all its faces. This condition uniquely defines the circle, if it exists. The set of equations defined by this equation is solved using a least squares approach, with the magnitude of the residual used to determine whether or not the incircle exists.

Type:

Sphere

property incircle_radius#

Get the radius of the polygon’s incircle.

Type:

float

property inertia_tensor#

Get the inertia tensor.

The inertia tensor is computed for the polygon embedded in \(\mathbb{R}^3\). This computation proceeds by first computing the polar moment of inertia for the polygon in the \(xy\)-plane relative to its centroid. The tensor is then rotated back to the orientation of the polygon and shifted to the original centroid.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the area of a shape to the area of a circle with the same perimeter. Given a shape of area \(A\) and perimeter \(p\), the circle with the same perimeter has radius \(r_p = \frac{p}{2\pi}\) and therefore has an area \(A_{circle} = \pi r_p^2 = \frac{p^2}{4\pi}\). Therefore, we have that:

\[\begin{split}\begin{align} IQ &= \frac{A}{A_{circle}} \\ &= \frac{4\pi A}{p^2} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Implement a simple point-in-polygon algorithm based on winding number.

The code in this function is based on implementation in [Dic19] which is licensed under the BSD-3 license.

Given a closed, possibly non-simple polygon described as a list of vertices in \(\mathbb{R}^2\) and a point that doesn’t lie directly on the path of the polygon, we’d like to compute the winding number of the polygon around the point. To achieve this, we place the point at the origin. Divide the remainder of the plane (i.e., \(\mathbb{R}^2\) minus the origin) into two halves, \(L\) and \(R\), defined as follows:

\[ \begin{align}\begin{aligned}L = {(x, y) | x < 0 \lor x = 0 \land y < 0}\\R = {(x, y) | x > 0 \lor x = 0 \land y > 0}\end{aligned}\end{align} \]

That is, \(R\) contains all points with argument in the half-closed interval \(\left[-\frac{\pi}{2},\frac{\pi}{2}\right)\), and \(L\) contains all others. Note that with these definitions, \(L\) and \(R\) are both convex: a line segment between two points in \(R\) lies entirely in \(R\), and similarly for \(L\). In particular, a line segment between two points can only pass through the origin if one of those points is in \(L\) and the other in \(R\). Now, we follow the edges of the polygon, keeping track of how many times we move between \(L\) and \(R\). For each move from \(L\) to \(R\) (or vice versa), we also need to compute whether the edge passes above or below the origin, to compute its contribution to the total winding number. From the comment above, we can safely ignore all edges that lie entirely within either \(L\) or \(R\).

Note

Points on the boundary of the shape will return False.

Parameters:

points (\((N, 3)\) or \((N, 2)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the polyhedron.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_circle#

Get the largest bounded circle.

The largest circle contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the incircle of a polygon), this property is named as an explicit analog to minimal_bounding_circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_centered_bounded_circle#

Get the largest concentric bounded circle.

This property gives the largest circle that fits in the shape whose center also coincides with the center of the shape.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the minimal bounding circle.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

This property gives the smallest bounding circle whose center coincides with the center of the shape.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

property normal#

Get the normal vector.

Type:

\((3, )\) numpy.ndarray of float

property num_vertices#

Get the number of vertices.

Type:

int

property perimeter#

Get the perimeter of the polygon.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments and the product of inertia are defined by the formulas:

\[\begin{split}\begin{align} I_x &= {\int \int}_A y^2 dA \\ I_y &= {\int \int}_A x^2 dA \\ I_{xy} &= {\int \int}_A xy dA \\ \end{align}\end{split}\]

To compute this for a polygon, we discretize the sum:

\[\begin{split}\begin{align} I_x &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (y_i^2 + y_i*y_{i+1} + y_{i+1}^2) \\ I_y &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (x_i^2 + x_i*x_{i+1} + x_{i+1}^2) \\ I_{xy} &= \frac{1}{12} \sum_{i=1}^N (x_i y_{i+1} - x_{i+1} y_i) (x_i y_{i+1} + 2 x_i y_i + 2 x_{i+1} y_{i+1} + x_{i+1} y_i) \\ \end{align}\end{split}\]

These formulas can be derived as described here.

Note that the moments are always calculated about an axis perpendicular to the polygon, i.e. the normal vector is aligned with the \(z\) axis before the moments are calculated. This alignment should be considered when computing the moments for polygons embedded in three-dimensional space that are rotated out of the \(xy\) plane, since the planar moments are invariant to this orientation. The exact rotation used for this computation (i.e. changes in the \(x\) and \(y\) position) should not be relied upon.

Type:

list[float, float, float]

plot(ax=None, center=False, plot_verts=False, label_verts=False)#

Plot the polygon.

Note that the polygon is always rotated into the \(xy\) plane and plotted in two dimensions.

Parameters:
  • ax (matplotlib.axes.Axes) – The axes on which to draw the polygon. Axes will be created if this is None (Default value: None).

  • center (bool) – If True, the polygon vertices are plotted relative to its center (Default value: False).

  • plot_verts (bool) – If True, scatter points will be added at the vertices (Default value: False).

  • label_verts (bool) – If True, vertex indices will be added next to the vertices (Default value: False).

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

property signed_area#

Get the polygon’s area.

To support polygons embedded in 3 dimensional space, we employ a projection- and rescaling-based algorithm described here. Specifically, the polygon is projected onto the plane it is “most parallel” to, the area of the projected polygon is computed, then the area is rescaled by the component of the normal in the projected dimension.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • 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 containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the polygon.

Type:

\((N_{verts}, 3)\) numpy.ndarray of float

class coxeter.shapes.Polyhedron(vertices, faces, faces_are_convex=None)#

Bases: Shape3D

A three-dimensional polytope.

A polyhedron is defined by a set of vertices and a set of faces composed of the vertices. On construction, the faces are reordered counterclockwise with respect to an outward normal. The polyhedron provides various standard geometric calculations, such as volume and surface area. Most features of the polyhedron can be accessed via properties, including the plane equations defining the faces and the neighbors of each face.

Note

For the purposes of calculations like moments of inertia, the polyhedron is assumed to be of constant, unit density.

Parameters:
  • vertices (\((N, 3)\) numpy.ndarray) – The vertices of the polyhedron.

  • faces (list(list)) – The faces of the polyhedron.

  • faces_are_convex (bool, optional) – Whether or not the faces of the polyhedron are all convex. This is used to determine whether certain operations like coplanar face merging are allowed (Default value: False).

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[-1, -1, -1], [-1, -1, 1], [-1, 1, -1], [-1, 1, 1],
...    [1, -1, -1], [1, -1, 1], [1, 1, -1], [1, 1, 1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices, faces=cube.faces)
>>> bounding_sphere = cube.minimal_bounding_sphere
>>> import numpy as np
>>> assert np.isclose(bounding_sphere.radius, np.sqrt(3))
>>> cube.center
array([0., 0., 0.])
>>> cube.faces
[array([0, 2, 6, 4], dtype=int32), array([0, 4, 5, 1], dtype=int32),
array([4, 6, 7, 5], dtype=int32), array([0, 1, 3, 2], dtype=int32),
array([2, 3, 7, 6], dtype=int32), array([1, 5, 7, 3], dtype=int32)]
>>> cube.gsd_shape_spec
{'type': 'Mesh', 'vertices': [[-1.0, -1.0, -1.0], [-1.0, -1.0, 1.0],
[-1.0, 1.0, -1.0], [-1.0, 1.0, 1.0], [1.0, -1.0, -1.0], [1.0, -1.0, 1.0],
[1.0, 1.0, -1.0], [1.0, 1.0, 1.0]], 'indices':
[array([0, 2, 6, 4], dtype=int32), array([0, 4, 5, 1], dtype=int32),
array([4, 6, 7, 5], dtype=int32), array([0, 1, 3, 2], dtype=int32),
array([2, 3, 7, 6], dtype=int32), array([1, 5, 7, 3], dtype=int32)]}
>>> assert np.allclose(
...   cube.inertia_tensor,
...   np.diag([16. / 3., 16. / 3., 16. / 3.]))
>>> assert np.isclose(cube.iq, np.pi / 6.)
>>> cube.neighbors
[array([1, 2, 3, 4]), array([0, 2, 3, 5]), array([0, 1, 4, 5]),
array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([1, 2, 3, 4])]
>>> cube.normals
array([[ 0.,  0., -1.],
       [ 0., -1.,  0.],
       [ 1.,  0., -0.],
       [-1.,  0.,  0.],
       [-0.,  1.,  0.],
       [ 0., -0.,  1.]])
>>> cube.num_faces
6
>>> cube.num_vertices
8
>>> assert np.isclose(cube.surface_area, 24.0)
>>> cube.vertices
array([[-1., -1., -1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1.,  1.,  1.],
       [ 1., -1., -1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1.,  1.,  1.]])
>>> assert np.isclose(cube.volume, 8.0)

Attributes:

bounding_sphere

Get the polyhedron's bounding sphere.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

circumsphere

Get the polyhedron's circumsphere.

circumsphere_radius

Get the radius of the polygon's circumsphere.

edge_lengths

Get the length of each edge of the polyhedron.

edge_vectors

Get the polyhedron's edges as vectors.

edges

Get the polyhedron's edges.

faces

Get the polyhedron's faces.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

insphere

Get the polyhedron's insphere.

insphere_radius

Get the radius of the polygon's insphere.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest concentric bounded sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

minimal_bounding_sphere

Get the polyhedron's bounding sphere.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get a bounding sphere sharing the center of this shape.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

neighbors

Get neighboring pairs of faces.

normals

Get the face normals.

num_edges

Get the number of edges.

num_faces

Get the number of faces.

num_vertices

Get the number of vertices.

surface_area

Get the surface area.

vertices

Get the vertices of the polyhedron.

volume

Get or set the polyhedron's volume.

Methods:

compute_form_factor_amplitude(q[, density])

Calculate the form factor intensity.

diagonalize_inertia()

Orient the shape along its principal axes.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

get_dihedral(a, b)

Get the dihedral angle between a pair of faces.

get_face_area([faces])

Get the total surface area of a set of faces.

is_inside(points)

Determine whether points are contained in this polyhedron.

merge_faces([atol, rtol])

Merge coplanar faces to a given tolerance.

plot([ax, plot_verts, label_verts])

Plot the polyhedron.

sort_faces()

Sort faces of the polyhedron.

to_hoomd()

Get a JSON-serializable subset of Polyhedron properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property bounding_sphere#

Get the polyhedron’s bounding sphere.

Type:

Sphere

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

The centroid is computed using the algorithm described in [Ebe02].

Type:

\((3, )\) numpy.ndarray of float

property circumsphere#

Get the polyhedron’s circumsphere.

A circumsphere must touch all the points of the polyhedron. A circumsphere exists if and only if there is a point equidistant from all the vertices. The circumsphere is found by finding the least squares solution of the overdetermined system of linear equations defined by this constraint, and the circumsphere only exists if the resulting solution has no residual.

Raises:

RuntimeError – If no circumsphere exists for this polyhedron.:

Type:

Sphere

property circumsphere_radius#

Get the radius of the polygon’s circumsphere.

Type:

float

compute_form_factor_amplitude(q, density=1.0)#

Calculate the form factor intensity.

The form factor amplitude of a polyhedron is computed according to the derivation provided in this dissertation: https://deepblue.lib.umich.edu/handle/2027.42/120906. In brief, two applications of Stokes theorem (or to use the names more familiar from elementary vector calculus, the application of the divergence theorem followed by the classic Kelvin-Stokes theorem) are used to reduce the volume integral over a polyhedron into a series of line integrals around the boundaries of each polygonal face.

For more generic information about form factors, see Shape.compute_form_factor_amplitude.

diagonalize_inertia()#

Orient the shape along its principal axes.

The principal axes of a shape are defined by the eigenvectors of the inertia tensor. This method computes the inertia tensor of the shape, diagonalizes it, and then rotates the shape by the corresponding orthogonal transformation.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices, faces=cube.faces)
>>> cube.diagonalize_inertia()
>>> cube.vertices
array([[ 1.,  1.,  1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.],
       [ 1., -1., -1.],
       [-1.,  1.,  1.],
       [-1., -1.,  1.],
       [-1.,  1., -1.],
       [-1., -1., -1.]])
distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property edge_lengths#

Get the length of each edge of the polyhedron.

edge_lengths are returned in the same order as in edges.

Type:

numpy.ndarray

property edge_vectors#

Get the polyhedron’s edges as vectors.

edge_vectors are returned in the same order as in edges.

Type:

numpy.ndarray

property edges#

Get the polyhedron’s edges.

Results returned as vertex index pairs, with each edge of the polyhedron included exactly once. Edge (i,j) pairs are ordered by vertex index with i<j.

Type:

numpy.ndarray

property faces#

Get the polyhedron’s faces.

Results returned as vertex index lists.

Type:

list(numpy.ndarray)

get_dihedral(a, b)#

Get the dihedral angle between a pair of faces.

The dihedral is computed from the dot product of the face normals.

Parameters:
  • a (int) – The index of the first face.

  • b (int) – The index of the second face.

Returns:

float

Return type:

The dihedral angle in radians.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices, faces=cube.faces)
>>> import numpy as np
>>> assert np.isclose(cube.get_dihedral(1, 2), np.pi / 2.)
get_face_area(faces=None)#

Get the total surface area of a set of faces.

Parameters:

faces (int, sequence, or None) – The index of a face or a set of face indices for which to find the area. If None, finds the area of all faces (Default value: None).

Returns:

:class:`numpy.ndarray`

Return type:

The area of each face.

Example

>>> cube = coxeter.shapes.ConvexPolyhedron(
...   [[1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1],
...    [-1, 1, 1], [-1, -1, 1], [-1, 1, -1], [-1, -1, -1]])
>>> cube = coxeter.shapes.Polyhedron(
...   vertices=cube.vertices,faces=cube.faces)
>>> import numpy as np
>>> assert np.allclose(
...   cube.get_face_area([1, 2, 3]),
...   [4., 4., 4.])
property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

The inertia tensor is computed using the algorithm described in [Kal06].

Note

For improved stability, the inertia tensor is computed about the center of mass and then shifted rather than directly computed in the global frame.

Type:

\((3, 3)\) numpy.ndarray

property insphere#

Get the polyhedron’s insphere.

Note

The insphere of a polyhedron is defined as the sphere contained within the polyhedron that is tangent to all its faces. This condition uniquely defines the sphere, if it exists. The set of equations defined by this equation is solved using a least squares approach, with the magnitude of the residual used to determine whether or not the insphere exists.

Type:

Sphere

property insphere_radius#

Get the radius of the polygon’s insphere.

Type:

float

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the volume of a shape to the volume of a sphere with the same perimeter. Given a shape of volume \(A\) and surface \(S\), the sphere with the same surface has radius \(r_S = \sqrt{\frac{S}{4\pi}}\) and therefore has volume \(V_{sphere} = \frac{4}{3} \pi r_S^3 = \frac{S^{3/2}}{\sqrt{4\pi}}\). Taking the ratio of volumes gives:

\[\begin{equation} \frac{V}{V_{sphere}} = \frac{6\sqrt{\pi} V}{S^{3/2}} \end{equation}\]

To avoid inconvenient fractional exponents, the isoperimetric quotient is conventionally defined as the square of this quantity:

\[\begin{split}\begin{align} IQ &= \left(\frac{V}{V_{sphere}}\right)^2 \\ &= \frac{36\pi V^2}{S^3} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this polyhedron.

The code in this function is based on implementation in [Dic19] which is licensed under the BSD-3 license. The computation is based on calculation of winding number.

Note

Points on the boundary of the shape will return False.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the polyhedron.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_sphere#

Get the largest bounded sphere.

The largest sphere contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the insphere of a polyhedron), this property is named as an explicit analog to minimal_bounding_sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest concentric bounded sphere.

This property gives the largest sphere that fits in the shape whose center also coincides with the center of the shape.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

merge_faces(atol=1e-08, rtol=1e-05)#

Merge coplanar faces to a given tolerance.

Whether or not faces should be merged is determined using numpy.allclose() to compare the plane equations of neighboring faces. Connected components of mergeable faces are then merged into a single face. This method can be safely called many times with different tolerances, however, the operation is destructive in the sense that merged faces cannot be recovered. Users wishing to undo a merge to attempt a less expansive merge must build a new polyhedron.

Parameters:
property minimal_bounding_sphere#

Get the polyhedron’s bounding sphere.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get a bounding sphere sharing the center of this shape.

A bounding sphere of a collection of points in is a sphere containing all of the points. There are an infinite set of possible bounding spheres for a shape (since any sphere that entirely contains a bounding sphere is also a bounding sphere), so additional constraints must be imposed to define a unique sphere. This property provides the smallest bounding sphere of a shape whose center coincides with the center of the shape.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

property neighbors#

Get neighboring pairs of faces.

The neighbors are provided as a list where the \(i^{\text{th}}\) element is an array of indices of faces that are neighbors of face \(i\).

Type:

list(numpy.ndarray)

property normals#

Get the face normals.

Type:

\((N, 3)\) numpy.ndarray

property num_edges#

Get the number of edges.

Type:

int

property num_faces#

Get the number of faces.

Type:

int

property num_vertices#

Get the number of vertices.

Type:

int

plot(ax=None, plot_verts=False, label_verts=False)#

Plot the polyhedron.

Note that the ax argument should be a 3D axes object; passing in a 2D axes object will result in wrong behavior.

Parameters:
  • ax (mpl_toolkits.mplot3d.axes3d.Axes3D) – The axes on which to draw the polyhedron. Axes will be created if this is None (Default value: None).

  • plot_verts (bool) – If True, scatter points will be added at the vertices (Default value: False).

  • label_verts (bool) – If True, vertex indices will be added next to the vertices (Default value: False).

sort_faces()#

Sort faces of the polyhedron.

This method ensures that all faces are ordered such that the normals are counterclockwise and point outwards. This algorithm proceeds in four steps. First, it ensures that each face is ordered in either clockwise or counterclockwise order such that edges can be found from the sequence of the vertices in each face. Next, it calls the neighbor finding routine to establish with faces are neighbors. Then, it performs a breadth-first search, reorienting faces to match the orientation of the first face. Finally, it computes the signed volume to determine whether or not all the normals need to be flipped.

Note

This method can only be called for polyhedra whose faces are all convex (i.e. constructed with faces_are_convex=True).

property surface_area#

Get the surface area.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • 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 containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property vertices#

Get the vertices of the polyhedron.

Type:

\((N, 3)\) numpy.ndarray

property volume#

Get or set the polyhedron’s volume.

Type:

float

class coxeter.shapes.Shape#

Bases: ABC

An abstract representation of a shape in N dimensions.

Attributes:

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

inertia_tensor()

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

is_inside(points)

Determine whether points are contained in this shape.

plot()

Plot the shape.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

inertia_tensor()#

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

is_inside(points)#

Determine whether points are contained in this shape.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the shape.

Return type:

\((N, )\) numpy.ndarray

plot()#

Plot the shape.

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

class coxeter.shapes.Shape2D#

Bases: Shape

An abstract representation of a shape in 2 dimensions.

Attributes:

area

Get or set the area of the shape.

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_circle

Get the largest bounded circle.

maximal_bounded_circle_radius

Get or set the radius of the maximal bounded circle.

maximal_centered_bounded_circle

Get the largest concentric bounded circle.

maximal_centered_bounded_circle_radius

Get or set the radius of the maximal centered bounded circle.

minimal_bounding_circle

Get the smallest bounding circle.

minimal_bounding_circle_radius

Get or set the radius of the minimal bounding circle.

minimal_centered_bounding_circle

Get the smallest bounding concentric circle.

minimal_centered_bounding_circle_radius

Get or set the radius of the minimal centered bounding circle.

perimeter

Get the perimeter of the shape.

planar_moments_inertia

Get the planar and product moments of inertia.

polar_moment_inertia

Get the polar moment of inertia.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Determine whether points are contained in this shape.

plot()

Plot the shape.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

abstract property area#

Get or set the area of the shape.

Type:

float

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

For non-orientable 2D shapes, the inertia tensor can be trivially constructed from the polar moment of inertia. This calculation assumes that the shape lies in the \(xy\)-plane. Shapes that can be rotated relative to this plane must define their own methods.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the area of a shape to the area of a circle with the same perimeter. Given a shape of area \(A\) and perimeter \(p\), the circle with the same perimeter has radius \(r_p = \frac{p}{2\pi}\) and therefore has an area \(A_{circle} = \pi r_p^2 = \frac{p^2}{4\pi}\). Therefore, we have that:

\[\begin{split}\begin{align} IQ &= \frac{A}{A_{circle}} \\ &= \frac{4\pi A}{p^2} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this shape.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the shape.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_circle#

Get the largest bounded circle.

The largest circle contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the incircle of a polygon), this property is named as an explicit analog to minimal_bounding_circle.

Type:

Circle

property maximal_bounded_circle_radius#

Get or set the radius of the maximal bounded circle.

See maximal_bounded_circle() for more information.

Type:

float

property maximal_centered_bounded_circle#

Get the largest concentric bounded circle.

This property gives the largest circle that fits in the shape whose center also coincides with the center of the shape.

Type:

Circle

property maximal_centered_bounded_circle_radius#

Get or set the radius of the maximal centered bounded circle.

See maximal_centered_bounded_circle() for more information.

Type:

float

property minimal_bounding_circle#

Get the smallest bounding circle.

A bounding circle in two dimensions is a circle containing all of the points. There are an infinite set of possible bounding circles for a shape (since any circle that entirely contains a bounding circle is also a bounding circle), so additional constraints must be imposed to define a unique circle. This property provides the smallest bounding circle of a shape.

Type:

Circle

property minimal_bounding_circle_radius#

Get or set the radius of the minimal bounding circle.

See minimal_bounding_circle() for more information.

Type:

float

property minimal_centered_bounding_circle#

Get the smallest bounding concentric circle.

This property gives the smallest bounding circle whose center coincides with the center of the shape.

Type:

Circle

property minimal_centered_bounding_circle_radius#

Get or set the radius of the minimal centered bounding circle.

See minimal_centered_bounding_circle() for more information.

Type:

float

abstract property perimeter#

Get the perimeter of the shape.

Type:

float

property planar_moments_inertia#

Get the planar and product moments of inertia.

Moments are computed with respect to the \(x\) and \(y\) axes. In addition to the two planar moments, this property also provides the product of inertia.

The planar moments of inertia and the product of inertia define the in-plane area distribution.

Type:

list[float, float, float]

plot()#

Plot the shape.

property polar_moment_inertia#

Get the polar moment of inertia.

The polar moment of inertia is always calculated about an axis perpendicular to the shape (i.e. the normal vector).

The polar moment is computed as the sum of the two planar moments of inertia.

Type:

float

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

class coxeter.shapes.Shape3D#

Bases: Shape

An abstract representation of a shape in 3 dimensions.

Attributes:

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

gsd_shape_spec

Get a complete GSD specification.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest concentric bounded sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

minimal_bounding_sphere

Get a bounding sphere sharing the center of this shape.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get a bounding sphere sharing the center of this shape.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

surface_area

Get or set the surface area of the shape.

volume

Get or set the volume of the shape.

Methods:

compute_form_factor_amplitude(q)

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

inertia_tensor()

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

is_inside(points)

Determine whether points are contained in this shape.

plot()

Plot the shape.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

inertia_tensor()#

\((3, 3)\) numpy.ndarray: Get the inertia tensor.

property iq#

The isoperimetric quotient.

The isoperimetric quotient is the ratio of the volume of a shape to the volume of a sphere with the same perimeter. Given a shape of volume \(A\) and surface \(S\), the sphere with the same surface has radius \(r_S = \sqrt{\frac{S}{4\pi}}\) and therefore has volume \(V_{sphere} = \frac{4}{3} \pi r_S^3 = \frac{S^{3/2}}{\sqrt{4\pi}}\). Taking the ratio of volumes gives:

\[\begin{equation} \frac{V}{V_{sphere}} = \frac{6\sqrt{\pi} V}{S^{3/2}} \end{equation}\]

To avoid inconvenient fractional exponents, the isoperimetric quotient is conventionally defined as the square of this quantity:

\[\begin{split}\begin{align} IQ &= \left(\frac{V}{V_{sphere}}\right)^2 \\ &= \frac{36\pi V^2}{S^3} \end{align}\end{split}\]
Type:

float

is_inside(points)#

Determine whether points are contained in this shape.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the shape.

Return type:

\((N, )\) numpy.ndarray

property maximal_bounded_sphere#

Get the largest bounded sphere.

The largest sphere contained in a shape is referred to by a range of ambiguous names. To avoid conflicts with the most common naming choices of other properties in the literature (particularly the insphere of a polyhedron), this property is named as an explicit analog to minimal_bounding_sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest concentric bounded sphere.

This property gives the largest sphere that fits in the shape whose center also coincides with the center of the shape.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

property minimal_bounding_sphere#

Get a bounding sphere sharing the center of this shape.

A bounding sphere of a collection of points in dimensions is a sphere containing all of the points. There are an infinite set of possible bounding spheres for a shape (since any sphere that entirely contains a bounding sphere is also a bounding sphere), so additional constraints must be imposed to define a unique sphere. This property provides the smallest bounding sphere of a shape.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get a bounding sphere sharing the center of this shape.

A bounding sphere of a collection of points in is a sphere containing all of the points. There are an infinite set of possible bounding spheres for a shape (since any sphere that entirely contains a bounding sphere is also a bounding sphere), so additional constraints must be imposed to define a unique sphere. This property provides the smallest bounding sphere of a shape whose center coincides with the center of the shape.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

plot()#

Plot the shape.

abstract property surface_area#

Get or set the surface area of the shape.

Type:

float

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

abstract property volume#

Get or set the volume of the shape.

Type:

float

class coxeter.shapes.Sphere(radius, center=(0, 0, 0))#

Bases: Shape3D

A sphere with the given radius.

Parameters:
  • radius (float) – Radius of the sphere.

  • center (Sequence[float]) – The coordinates of the centroid of the sphere (Default value: (0, 0, 0)).

Example

>>> sphere = coxeter.shapes.Sphere(1.0)
>>> assert np.isclose(sphere.radius, 1.0)
>>> assert np.allclose(sphere.centroid, [0., 0., 0.])
>>> sphere.gsd_shape_spec
{'type': 'Sphere', 'diameter': 2.0}
>>> assert np.allclose(
...   np.diag(sphere.inertia_tensor),
...   8. / 15. * np.pi)
>>> sphere.iq
1
>>> sphere.surface_area
12.56637...
>>> sphere.volume
4.18879...

Attributes:

center

Alias for centroid.

centroid

Get or set the centroid of the shape.

diameter

Get or set the radius of the sphere.

gsd_shape_spec

Get a complete GSD specification.

inertia_tensor

Get the inertia tensor.

iq

The isoperimetric quotient.

maximal_bounded_sphere

Get the largest bounded sphere.

maximal_bounded_sphere_radius

Get or set the radius of the maximal bounded sphere.

maximal_centered_bounded_sphere

Get the largest bounded concentric sphere.

maximal_centered_bounded_sphere_radius

Get or set the radius of the maximal centered bounded sphere.

minimal_bounding_sphere

Get the smallest bounding sphere.

minimal_bounding_sphere_radius

Get or set the radius of the minimal bounding sphere.

minimal_centered_bounding_sphere

Get the smallest bounding concentric sphere.

minimal_centered_bounding_sphere_radius

Get or set the radius of the minimal concentric bounding sphere.

radius

Get or set the radius of the sphere.

surface_area

Get the surface area.

volume

Get the volume of the sphere.

Methods:

compute_form_factor_amplitude(q[, density])

Calculate the form factor intensity.

distance_to_surface(angles)

Compute the distance to the surface of the shape at the given angles.

is_inside(points)

Determine whether a set of points are contained in this sphere.

plot()

Plot the shape.

to_hoomd()

Get a dict of JSON-serializable subset of Sphere properties.

to_json(attributes)

Get a JSON-serializable subset of shape properties.

to_plato_scene([backend, scene, scene_kwargs])

Add this shape to a new or existing plato.draw.Scene.

property center#

Alias for centroid.

Type:

\((3, )\) numpy.ndarray of float

property centroid#

Get or set the centroid of the shape.

Type:

\((3, )\) numpy.ndarray of float

compute_form_factor_amplitude(q, density=1.0)#

Calculate the form factor intensity.

In solid state physics, scattering theory is concerned with understanding the ways in which radiation is scattered from a sample. For a single point particle at position P, the the amplitude of a scattered wave observed at position Q is the product of the incoming wave amplitude (which follows the standard equation for a traveling wave) and the scattering density at P. For a crystal composed of many point particles, the intensity of the resulting superposition of waves can be identified as the Fourier transform of the total scattering density. When the particles are not point particles, the scattering density of the particles in their local coordinate systems are no longer identical. Conveniently, this component is separable in the Fourier transform of the total density; as a result, the scattering scattering intensity can be decomposed into two terms, the Fourier transform of the distribution of scatterers and the Fourier transform of each scatterer in its local coordinate system. The first term is known as the static structure factor \(S(\vec{q})\) and describes the spatial distribution of scatterers, while the second term is called the form factor \(f(\vec{q})\) and describes the local scattering profile.

While the form factor (the scattering intensity) can be measured from diffraction experiments, the Fourier transform of a single particle cannot. However, it can be computed theoretically for a known scattering volume and can be inserted directly into the expression for the total scattering intensity. This local profile directly describes the wave emitted from a single scatterer (in reciprocal space) and is known as the form factor amplitude. This function computes the form factor amplitude for a given wavevector \(q\).

property diameter#

Get or set the radius of the sphere.

Type:

float

distance_to_surface(angles)#

Compute the distance to the surface of the shape at the given angles.

Gets the distance to the surface at each of the angles provided, where the definition of the angles depends on the dimensionality of the shape (a single angle in 2D, or the phi/theta angles in 3D). All angles are relative to the x axis. In general, the distance is computed from the centroid of the shape unless stated otherwise.

Parameters:

angles (\((N, d-1)\) numpy.ndarray) – Angles between \(0\) and \(2 \pi\) over which to calculate the distances. \(d\) is the number of dimensions.

Returns:

An array of distances from the center of the shape to its surface at each of the given angles.

Return type:

\((N,)\) numpy.ndarray

property gsd_shape_spec#

Get a complete GSD specification.

Type:

dict

property inertia_tensor#

Get the inertia tensor.

Assumes a constant density of 1.

Type:

\((3, 3)\) numpy.ndarray

property iq#

The isoperimetric quotient.

This is 1 by definition for spheres.

Type:

float

is_inside(points)#

Determine whether a set of points are contained in this sphere.

Note

Points on the boundary of the shape will return True.

Parameters:

points (\((N, 3)\) numpy.ndarray) – The points to test.

Returns:

Boolean array indicating which points are contained in the sphere.

Return type:

\((N, )\) numpy.ndarray

Example

>>> sphere = coxeter.shapes.Sphere(1.0)
>>> sphere.is_inside([[0, 0, 0], [20, 20, 20]])
array([ True, False])
property maximal_bounded_sphere#

Get the largest bounded sphere.

Type:

Sphere

property maximal_bounded_sphere_radius#

Get or set the radius of the maximal bounded sphere.

See maximal_bounded_sphere() for more information.

Type:

float

property maximal_centered_bounded_sphere#

Get the largest bounded concentric sphere.

Type:

Sphere

property maximal_centered_bounded_sphere_radius#

Get or set the radius of the maximal centered bounded sphere.

See maximal_centered_bounded_sphere() for more information.

Type:

float

property minimal_bounding_sphere#

Get the smallest bounding sphere.

Type:

Sphere

property minimal_bounding_sphere_radius#

Get or set the radius of the minimal bounding sphere.

See minimal_bounding_sphere() for more information.

Type:

float

property minimal_centered_bounding_sphere#

Get the smallest bounding concentric sphere.

Type:

Sphere

property minimal_centered_bounding_sphere_radius#

Get or set the radius of the minimal concentric bounding sphere.

See minimal_centered_bounding_sphere() for more information.

Type:

float

plot()#

Plot the shape.

property radius#

Get or set the radius of the sphere.

Type:

float

property surface_area#

Get the surface area.

Type:

float

to_hoomd()#

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. Stored values are based on the shape with its centroid at the origin.

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] per HOOMD’s spec.

  • volume (float)

    The volume of the shape.

  • moment_inertia (list(list))

    The shape’s inertia tensor.

Returns:

Dict containing a subset of shape properties required for HOOMD function.

Return type:

dict

to_json(attributes: list)#

Get a JSON-serializable subset of shape properties.

Parameters:

attributes (list) – List of attributes to export. Each element must be a valid attribute of the class.

Returns:

A dict containing the requested attributes.

Return type:

dict

Raises:

AttributeError: – If any keys in the input list are invalid.

to_plato_scene(backend='matplotlib', scene=None, scene_kwargs=None)#

Add this shape to a new or existing plato.draw.Scene.

The plato visualization package provides support for several backends, including matplotlib, fresnel, povray, pythreejs, and vispy. The backend package must be separately installed by the user. Each backend supports different primitives (geometry objects) and may not support the primitive corresponding to a specific shape class in coxeter. Please refer to the plato documentation for more information about supported primitives for each backend.

Parameters:
  • backend (str) – Name of backend to use from plato. The backend must support the primitive corresponding to this shape (Default value: "matplotlib"). Supported values include "matplotlib", "fresnel", "povray", "pythreejs", "vispy", and "zdog". See plato documentation for more information about each backend.

  • scene (plato.draw.Scene) – Scene object to render into. If not provided or None, a new scene is created (Default value: None).

  • scene_kwargs (dict) – Keyword arguments forwarded to the plato.draw.Scene (Default value: None). Only used if scene is not provided or None.

Returns:

A scene containing this shape.

Return type:

plato.draw.Scene

Raises:
  • NotImplementedError: – If no plato primitive corresponds to this coxeter shape class.

  • AttributeError: – If the selected plato backend does not support the primitive for this coxeter shape class.

property volume#

Get the volume of the sphere.

Type:

float