Source code for microstructpy.geometry.n_box

"""N-Dimensional Box

This module contains the NBox class.

"""
# --------------------------------------------------------------------------- #
#                                                                             #
# Import Modules                                                              #
#                                                                             #
# --------------------------------------------------------------------------- #

from __future__ import division

import numpy as np

__author__ = 'Kenneth (Kip) Hart'


# --------------------------------------------------------------------------- #
#                                                                             #
# NBox Class                                                                  #
#                                                                             #
# --------------------------------------------------------------------------- #
[docs]class NBox(object): """N-dimensional box This class contains a generic, n-dimensinoal box. Args: side_lengths (list): *(optional)* Side lengths. center (list): *(optional)* Center of box. corner (list): *(optional)* Bottom-left corner. bounds (list): *(optional)* Bounds of box. Expected in the form [(xmin, xmax), (ymin, ymax), ...]. limits : Alias for *bounds*. matrix (list, numpy.ndarray): *(optional)* Rotation matrix, nxn """ def __init__(self, **kwargs): if 'bounds' in kwargs: lims = kwargs['bounds'] elif 'limits' in kwargs: lims = kwargs['limits'] if ('bounds' in kwargs) or ('limits' in kwargs): self.center = [0.5 * (lb + ub) for lb, ub in lims] self.side_lengths = [ub - lb for lb, ub in lims] elif ('side_lengths' in kwargs) and ('center' in kwargs): self.center = kwargs['center'] self.side_lengths = kwargs['side_lengths'] elif ('side_lengths' in kwargs) and ('corner' in kwargs): corner = kwargs['corner'] side_lens = kwargs['side_lengths'] cen = [xc + 0.5 * sl for xc, sl in zip(corner, side_lens)] self.center = cen self.side_lengths = side_lens elif ('center' in kwargs) and ('corner' in kwargs): corner = kwargs['corner'] center = kwargs['center'] side_lens = [2 * abs(x1 - x2) for x1, x2 in zip(center, corner)] self.center = center self.side_lengths = side_lens elif 'center' in kwargs: self.center = kwargs['center'] self.side_lengths = [1 for _ in self.center] elif 'side_lengths' in kwargs: self.side_lengths = kwargs['side_lengths'] self.center = [0 for _ in self.side_lengths] elif 'corner' in kwargs: self.side_lengths = [1 for _ in kwargs['corner']] self.center = [xc + 0.5 for xc in kwargs['corner']] if 'matrix' in kwargs: self.matrix = kwargs['matrix'] else: try: self.matrix = np.eye(self.n_dim) except AttributeError: self.matrix = np.eye(len(self.side_lengths)) # ----------------------------------------------------------------------- # # String and Representation Functions # # ----------------------------------------------------------------------- # def __str__(self): cen = np.array(self.center) sides = np.array(self.side_lengths) cen_str = np.array2string(cen, separator=', ') sides_str = np.array2string(sides, separator=', ') str_str = 'Center: ' + cen_str + '\n' str_str += 'Side Lengths: ' + sides_str + '\n' str_str += 'Matrix: (' for row in self.matrix: str_str += '(' str_str += ', '.join([str(val) for val in row]) str_str += '),' str_str = str_str[:-1] + ')' return str_str def __repr__(self): repr_str = 'NBox(' repr_str += 'center=' + repr(tuple(self.center)) + ', ' repr_str += 'side_lengths=' + repr(tuple(self.side_lengths)) + ', ' repr_str += 'matrix=' repr_str += repr(tuple([tuple(r) for r in self.matrix])) + ')' return repr_str # ----------------------------------------------------------------------- # # Dimension Getters # # ----------------------------------------------------------------------- # @property def corner(self): """list: bottom-left corner""" c_rel = -0.5 * np.array(self.matrix).dot(self.side_lengths) return np.array(self.center) + c_rel @property def limits(self): """list: (lower, upper) bounds of the box""" cen = self.center side_lens = self.side_lengths n_dim = len(cen) powers = np.power(2, np.arange(n_dim)) n_pts = np.power(2, n_dim) pts = np.zeros((n_pts, n_dim)) for i in range(n_pts): for j in range(n_dim): ind = (i // powers[j]) % 2 pts[i, j] = (ind - 0.5) * side_lens[j] pts = np.array(cen) + pts.dot(np.array(self.matrix).T) mins = pts.min(axis=0) maxs = pts.max(axis=0) return np.array([mins, maxs]).T @property def bounds(self): """list: (lower, upper) bounds of the box""" return self.limits # ----------------------------------------------------------------------- # # Sample Limits # # ----------------------------------------------------------------------- # @property def sample_limits(self): """ list: (lower, upper) bounds of the sampling region of the box""" cen = self.center lens = self.side_lengths tol = 1e-4 * max(lens) return [(x - 0.5 * s + tol, x + 0.5 * s - tol) for x, s in zip(cen, lens)] # ----------------------------------------------------------------------- # # Area/Volume # # ----------------------------------------------------------------------- # @property def n_vol(self): """float: area, volume of n-box""" return np.prod(self.side_lengths) # ----------------------------------------------------------------------- # # Within Test # # ----------------------------------------------------------------------- #
[docs] def within(self, points): """Test if points are within n-box. This function tests whether a point or set of points are within the n-box. For the set of points, a list of booleans is returned to indicate which points are within the n-box. Args: points (list or numpy.ndarray): Point or list of points. Returns: bool or numpy.ndarray: Flags set to True for points in geometry. """ pts = np.array(points) single_pt = pts.ndim == 1 if single_pt: pts = pts.reshape(1, -1) rel_pos = pts - np.array(self.center) min_dist = 0.5 * np.array(self.side_lengths) mask = np.all(np.abs(rel_pos) <= min_dist, axis=-1) if single_pt: return mask[0] else: return mask