def __init__(self, pmin=None, pmax=None, xmin=0, ymin=0, zmin=0, xmax=1, ymax=1, zmax=1): super().__init__() self._pmin = Point() self._pmax = Point() if pmin is None: pmin = [xmin, ymin, zmin] self.pmin = pmin if pmax is None: pmax = [xmax, ymax, zmax] self.pmax = pmax # assert self.pmin <= self.pmax assert np.all(np.less_equal(self.pmin, self.pmax)) self.points.extend([self.pmin, self.pmax]) self.fmtstr = "pmin={pmin!r}, pmax={pmax!r}"
def test6(): p2 = Point(np.zeros(3), nd=2) p3 = Point(np.zeros(2), nd=3) assert_equal(p2, Point(np.zeros(2))) assert_equal(p3, Point(np.zeros(3))) assert_true(len(p2) == 2) assert_true(len(p3) == 3)
def test_parallelepiped(): r = Parallelepiped() assert_is_instance(r, Parallelepiped) assert_equal(r.o, Point([0, 0, 0])) assert_true(np.allclose(r.measure, 1.0)) assert_equal(r.centroid, Point([1, 1, 0.5])) assert_true(r.contains([0.5, 0.5, 0.5])) assert_false(r.contains([0, 0, 1])) assert_is_instance(r.centroid, Point)
def test_cone(): r = Cone() assert_is_instance(r, Cone) assert_true(np.allclose(r.measure, 2 * np.pi / 3)) assert_equal(r.p1, Point(np.zeros(3))) assert_equal(r.p2, Point([0, 0, 2])) assert_true(r.contains([0, 0, 1])) assert_false(r.contains([0, 0, 2.1])) assert_is_instance(r.centroid, Point) assert_is_instance(r.axis, Vector)
def generate(self): """Generate structure data.""" super().generate() if self.L0 is not None and self.fix_Lz: Lz_cutoff = 10 * self.L0 + 1 region_bounds = Cuboid(pmin=Point([-np.inf, -np.inf, 0]), pmax=Point([np.inf, np.inf, Lz_cutoff])) self.atoms.clip_bounds(region_bounds)
def test_triangle(): r = Triangle() assert_is_instance(r, Triangle) assert_equal(r.centroid, Point([1 / 3, 1 / 3])) assert_true(np.allclose(r.measure, 0.5)) assert_equal(r.p1, Point(nd=2)) assert_equal(r.p2, Point([0, 1])) assert_equal(r.p3, Point([1, 0])) assert_true(r.contains([0.25, 0.25])) assert_false(r.contains([1, 1])) assert_is_instance(r.centroid, Point)
def test_cylinder(): r = Cylinder() assert_is_instance(r, Cylinder) assert_true(np.allclose(r.measure, 2 * np.pi)) assert_equal(r.p1, Point([0, 0, -1])) assert_equal(r.p2, Point([0, 0, 1])) assert_true(r.contains([0, 0, 0])) assert_false(r.contains([1.1, 0, 0])) assert_equal(r.centroid, Point()) r.p2 = [0, 0, 2] assert_equal(r.centroid, Point([0, 0, 0.5])) assert_is_instance(r.centroid, Point) assert_is_instance(r.axis, Vector)
def test1(): p = Point() assert_true(np.allclose(p, np.zeros(3))) p = Point([0, 0, 0], dtype=float) assert_true(np.allclose(p, np.zeros(3))) p = Point(np.ones(3)) assert_true(np.allclose(p, np.ones(3))) p = Point([None, None, None]) assert_true(np.allclose(p, np.zeros(3))) p = Point(np.arange(10)) assert_true(np.allclose(p, np.arange(10)))
def test1(): print('generating graphene structure') graphene = GrapheneGenerator(armchair_edge_length=5, zigzag_edge_length=5) lattice = graphene.lattice print('graphene.bounds:\n{}'.format(graphene.bounds)) print('graphene.centroid:\n{}'.format(graphene.centroid)) print('graphene.lattice:\n{}'.format(lattice)) print('graphene.lattice.a1:\n{}'.format(lattice.a1)) print('graphene.lattice.a2:\n{}'.format(lattice.a2)) print('graphene.lattice.a3:\n{}'.format(lattice.a3)) print('graphene.lattice.orientation_matrix:\n{}'.format( lattice.orientation_matrix)) print('rotating graphene') graphene.rotate(angle=-np.pi / 2, axis='x') print('graphene.bounds:\n{}'.format(graphene.bounds)) print('graphene.centroid:\n{}'.format(graphene.centroid)) print('graphene.lattice:\n{}'.format(lattice)) print('graphene.lattice.a1:\n{}'.format(lattice.a1)) print('graphene.lattice.a2:\n{}'.format(lattice.a2)) print('graphene.lattice.a3:\n{}'.format(lattice.a3)) print('graphene.lattice.orientation_matrix:\n{}'.format( lattice.orientation_matrix)) assert_true(np.allclose(lattice.angles, 3 * [90.0])) lattice_region = Cuboid(pmax=lattice.lengths) # lattice_region = Parallelepiped(u=lattice.a * xhat, # v=lattice.b * yhat, # w=lattice.c * zhat) assert_equal(lattice_region.a, lattice.a) assert_equal(lattice_region.b, lattice.b) assert_equal(lattice_region.c, lattice.c) print('lattice_region:\n{}'.format(lattice_region)) print('lattice_region.centroid:\n{}'.format(lattice_region.centroid)) print('\nrotating lattice_region') lattice_region.rotate(transform_matrix=lattice.orientation_matrix) # assert_equal(lattice_region.a, lattice.a) # assert_equal(lattice_region.b, lattice.b) # assert_equal(lattice_region.c, lattice.c) print('lattice_region:\n{}'.format(lattice_region)) print('lattice_region.centroid:\n{}'.format(lattice_region.centroid)) print('\ncentering lattice_region on graphene centroid') tvec = Vector(Point(graphene.centroid) - lattice_region.centroid) lattice_region.translate(tvec) # assert_equal(lattice_region.a, lattice.a) # assert_equal(lattice_region.b, lattice.b) # assert_equal(lattice_region.c, lattice.c) print('lattice_region:\n{}'.format(lattice_region)) print('lattice_region.centroid:\n{}'.format(lattice_region.centroid)) bounding_box = generate_bounding_box(from_lattice=lattice, center=graphene.centroid, verbose=True) print('bounding_box:\n{}'.format(bounding_box)) assert_equal(bounding_box, lattice_region) print('lattice_region.lengths: {}, {}, {}'.format(lattice_region.a, lattice_region.b, lattice_region.c))
def test13(): latt = Crystal3DLattice(a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90) print(latt) p = [2.1, 0.9, 0.5] assert_true( np.allclose(latt.wrap_fractional_coordinate(p), Point( (0.1, 0.9, 0.5))))
def contains(self, point): """Test region membership of `point` in :class:`Sphere`. Parameters ---------- point : array_like Returns ------- :class:`~python:bool` `True` if `point` is within :class:`Sphere`, `False` otherwise. Notes ----- A `point` :math:`(p_x, p_y, p_z)` is within the bounded region of a sphere with center :math:`(h, k, l)` and radius :math:`r` if the following is true: .. math:: (p_x - h)^2 + (p_y - k)^2 + (p_z - l)^2 \\le r^2 """ x, y, z = Point(point) h, k, l = self.center r = self.r return (x - h)**2 + (y - k)**2 + (z - l)**2 <= r**2
def contains(self, point): """Test region membership of `point` in :class:`Ellipsoid`. Parameters ---------- point : array_like Returns ------- :class:`~python:bool` `True` if `point` is within :class:`Ellipsoid`, `False` otherwise Notes ----- A `point` :math:`(p_x, p_y, p_z)` is within the bounded region of an ellipsoid with center :math:`(c_x, c_y, c_z)` and semi-axes lengths :math:`r_x, r_y, r_z` if the following is true: .. math:: \\left(\\frac{p_x - c_x}{r_x}\\right)^2 + \\left(\\frac{p_y - c_y}{r_y}\\right)^2 + \\left(\\frac{p_z - c_z}{r_z}\\right)^2\\le 1 """ px, py, pz = Point(point) cx, cy, cz = self.center rx, ry, rz = self.rx, self.ry, self.rz q1 = (px - cx)**2 / rx**2 q2 = (py - cy)**2 / ry**2 q3 = (pz - cz)**2 / rz**2 return q1 + q2 + q3 <= 1.0
def centroid(self): """:class:`Triangle` centroid, :math:`(c_x, c_y)`. Computed as 2D :class:`Point` :math:`(c_x, c_y)` with coordinates: .. math:: c_x = \\frac{x_1 + x_2 + x_3}{3} c_y = \\frac{y_1 + y_2 + y_3}{3} Returns ------- :class:`Point` 2D :class:`Point` of centroid. """ x1, y1 = self.p1 x2, y2 = self.p2 x3, y3 = self.p3 cx = (x1 + x2 + x3) / 3 cy = (y1 + y2 + y3) / 3 return Point([cx, cy])
def __init__(self, o=None, u=None, v=None, w=None): self._o = Point() self._u = Vector() self._v = Vector() self._w = Vector() super().__init__() if o is None: o = [0, 0, 0] self.o = o if u is None: u = [1, 0, 0] self.u = u if v is None: v = [1, 1, 0] self.v = v if w is None: w = [0, 1, 1] self.w = w self.points.append(self.o) self.vectors.extend([self.u, self.v, self.w]) self.fmtstr = "o={o!r}, u={u!r}, v={v!r}, w={w!r}"
def contains(self, point): """Test region membership of `point` in :class:`Square`. Parameters ---------- point : array_like Returns ------- :class:`~python:bool` `True` if `point` is within :class:`Square`, `False` otherwise. Notes ----- A `point` :math:`(p_x, p_y)` is within the bounded region of a square with center :math:`(c_x, c_y)` and side length :math:`a` if the following is true: .. math:: c_i - \\frac{a}{2}\\le p_i\\le c_i + \\frac{a}{2}\\forall i\\in \\{x, y\\} """ px, py = Point(point) cx, cy = self.center a = self.a xmin = cx - a / 2 xmax = cx + a / 2 ymin = cy - a / 2 ymax = cy + a / 2 return (px >= xmin) and (px <= xmax) and (py >= ymin) and (py <= ymax)
def centroid(self): """Paralleogram centroid, :math:`(c_x, c_y)`. Computed as the 2D point :math:`(c_x, c_y)` with coordinates: .. math:: c_x = o_x + \\frac{u_x + v_x}{2} c_y = o_y + \\frac{u_y + v_y}{2} where :math:`(o_x, o_y)`, :math:`(u_x, u_y)`, and :math:`(v_x, v_y)` are the :math:`(x, y)` coordinates of the origin :math:`o` and :math:`(x, y)` components of the direction vectors :math:`\\mathbf{u}` and :math:`\\mathbf{v}`, respectively. Returns ------- :class:`Point` 2D :class:`Point` of centroid. """ ox, oy = self.o ux, uy = self.u vx, vy = self.v cx = ox + (ux + vx) / 2 cy = oy + (uy + vy) / 2 return Point([cx, cy])
def __init__(self, p1=None, p2=None, r=1): super().__init__() self._p1 = Point() self._p2 = Point() if p1 is None: p1 = [0, 0, -1] if p2 is None: p2 = [0, 0, 1] self.p1 = p1 self.p2 = p2 self.points.extend([self.p1, self.p2]) self.r = r self.fmtstr = "p1={p1!r}, p2={p2!r}, r={r:.3f}"
def test_rectangle(): r = Rectangle() assert_is_instance(r, Rectangle) assert_equal(r.measure, 1) assert_equal(r.centroid, Point([0.5, 0.5])) assert_true(r.contains(r.centroid)) assert_false(r.contains([1.1, 1.1])) assert_is_instance(r.centroid, Point)
def test_cuboid(): r = Cuboid() assert_is_instance(r, Cuboid) assert_equal(r.centroid, Point([0.5, 0.5, 0.5])) assert_true(np.allclose(r.measure, 1.0)) assert_true(r.contains(r.centroid)) assert_false(r.contains([-0.1, 0, 0])) assert_is_instance(r.centroid, Point)
def test_square(): r = Square() assert_is_instance(r, Square) assert_equal(r.measure, 1) assert_equal(r.centroid, Point([0, 0])) assert_true(r.contains([0, 0])) assert_false(r.contains([1, 1])) assert_is_instance(r.centroid, Point)
def __init__(self, nd=None, cell_matrix=None, orientation_matrix=None, offset=None): super().__init__() self.nd = nd self.offset = Point(offset, nd=3) if cell_matrix is not None and orientation_matrix is None: orientation_matrix = cell_matrix.T * self.fractional_matrix if orientation_matrix is None: orientation_matrix = np.asmatrix(np.identity(3)) self.orientation_matrix = np.asmatrix(orientation_matrix) self.lattice_type = None
def test_ellipsoid(): r = Ellipsoid() assert_is_instance(r, Ellipsoid) assert_equal(r.centroid, Point([0, 0, 0])) assert_true(np.allclose(r.measure, 4 / 3 * np.pi)) assert_true(r.contains(r.centroid)) assert_false(r.contains([1.01, 1.01, 1.01])) assert_is_instance(r.centroid, Point)
def test_cube(): r = Cube() assert_is_instance(r, Cube) assert_equal(r.centroid, Point([0, 0, 0])) assert_true(np.allclose(r.measure, 1.0)) assert_true(r.contains([0, 0, 0])) assert_false(r.contains([1, 1, 1])) assert_is_instance(r.centroid, Point)
def __init__(self, pmin=None, pmax=None, xmin=0, ymin=0, xmax=1, ymax=1): super().__init__() self._pmin = Point(nd=2) self._pmax = Point(nd=2) if pmin is None: pmin = [xmin, ymin] self.pmin = pmin if pmax is None: pmax = [xmax, ymax] self.pmax = pmax self.points.append([self.pmin, self.pmax]) self.fmtstr = "pmin={pmin!r}, pmax={pmax!r}"
def test_circle(): r = Circle() assert_is_instance(r, Circle) assert_equal(r.measure, np.pi) assert_equal(r.centroid, Point([0, 0])) assert_equal(r.r, 1.0) assert_true(r.contains([0, 0])) assert_false(r.contains([1.1, 0])) assert_is_instance(r.centroid, Point)
def test_sphere(): r = Sphere() assert_is_instance(r, Sphere) assert_equal(r.center, Point([0, 0, 0])) assert_equal(r.r, 1.0) assert_true(np.allclose(r.measure, 4 / 3 * np.pi)) assert_true(r.contains([0, 0, 0])) assert_false(r.contains([1.1, 1.1, 1.1])) assert_is_instance(r.centroid, Point)
def contains(self, point): """Test region membership of `point` in :class:`Cone`. Parameters ---------- point : array_like Returns ------- :class:`~python:bool` `True` if `point` is within :class:`Cone`, `False` otherwise. Notes ----- A `point` :math:`(p_x, p_y, p_z)` is within the bounded region of a cone with a base of radius :math:`r` centered at :math:`p_1=(x_1, y_1, z_1)` and tip at :math:`p_2 = (x_2, y_2, z_2)` if the following is true: .. math:: 0\\le q\\le 1\\land (x_1 - p_x + (x_2 - x_1) q)^2 + (y_1 - p_y + (y_2 - y_1) q)^2 + (z_1 - p_z + (z_2 - z_1) q)^2 \\le r^2 q^2 where :math:`q` is: .. math:: q = \\frac{(p_x - x_1)(x_2 - x_1) + (p_y - y_1)(y_2 - y_1) + (p_z - z_1)(z_2 - z_1)}{(x_2 - x_1)^2 + (y_2 - y_1)^2 + (z_2 - z_1)^2} """ px, py, pz = Point(point) x1, y1, z1 = self.p1 x2, y2, z2 = self.p2 r = self.r q1 = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1) + (pz - z1) * (z2 - z1)) / \ ((x2 - x1) ** 2 + (y2 - y1) ** 2 + (z2 - z1) ** 2) q2 = (x1 - px + (x2 - x1) * q1) ** 2 + \ (y1 - py + (y2 - y1) * q1) ** 2 + \ (z1 - pz + (z2 - z1) * q1) ** 2 q3 = r**2 * q1**2 return (not np.allclose(x1, x2) or not np.allclose(y1, y2) or not np.allclose(z1, z2)) and r > 0 and q1 >= 0 and q1 <= 1 \ and q2 <= q3
def __init__(self, p1=None, p2=None, p3=None): super().__init__() self._p1 = Point(nd=2) self._p2 = Point(nd=2) self._p3 = Point(nd=2) if p1 is None: p1 = [0, 0] if p2 is None: p2 = [0, 1] if p3 is None: p3 = [1, 0] self.p1 = p1 self.p2 = p2 self.p3 = p3 self.points.extend([self.p1, self.p2, self.p3]) self.fmtstr = "p1={p1!r}, p2={p2!r}, p3={p3!r}"
def test_point_rotation(): assert_true( np.allclose(rotate(Point([1.0, 0.0]), np.pi / 2), np.array([0.0, 1.0]))) with assert_raises(ValueError): np.allclose(rotate(Point([1.0, 0.0, 0.0]), angle=np.pi / 2), np.array([0.0, 1.0, 0.0])) assert_true( np.allclose( rotate(Point([1.0, 0.0, 0.0]), angle=np.pi / 2, axis=Vector([1.0, 0.0, 0.0])), np.array([1.0, 0.0, 0.0]))) assert_true( np.allclose( rotate(Point([0.0, 1.0, 0.0]), angle=np.pi / 2, axis=Vector([1.0, 0.0, 0.0])), np.array([0.0, 0.0, 1.0])))
def i(self, value): """Set :math:`i_x, i_y, i_z` image flags. Parameters ---------- value : array_like """ if not isinstance(value, (list, np.ndarray)): raise TypeError('Expected an array_like object') self._i[:] = Point(value, nd=3, dtype=int)
def test3(): p = Point([1.0, 0.0, 0.0]) p.rotate(np.pi/2, rot_axis='z') assert_true(np.allclose(p, np.array([0, 1, 0]))) p.rotate(np.pi/2, rot_axis='z') assert_true(np.allclose(p, np.array([-1, 0, 0]))) p.rotate(np.pi/2, rot_axis='z') assert_true(np.allclose(p, np.array([0, -1, 0]))) p.rotate(np.pi/2, rot_axis='z') assert_true(np.allclose(p, np.array([1, 0, 0]))) p.rotate(np.pi/2, rot_axis=[0, 0, 1], rot_point=[1, 1, 0]) assert_true(np.allclose(p, np.array([2, 1, 0])))
def test2(): p = Point([1e-9, 1e-11, -1e-16]) p.rezero(epsilon=1e-10) assert_not_equal(p.x, 0.0) assert_equal(p.y, 0.0) assert_equal(p.z, 0.0)
class LatticeBase(BaseClass): """Base class for crystallographic lattice objects. Parameters ---------- nd : int cell_matrix : array_like orientation_matrix : array_like, optional offset : array_like, optional """ def __init__(self, nd=None, cell_matrix=None, orientation_matrix=None, offset=None): super().__init__() self.nd = nd self.offset = Point(offset, nd=3) if cell_matrix is not None and orientation_matrix is None: orientation_matrix = cell_matrix.T * self.fractional_matrix if orientation_matrix is None: orientation_matrix = np.asmatrix(np.identity(3)) self.orientation_matrix = np.asmatrix(orientation_matrix) self.lattice_type = None def __dir__(self): return ['nd', 'offset', 'orientation_matrix'] def __eq__(self, other): if isinstance(other, type(self)): return self is other or \ all([np.allclose(getattr(self, attr), getattr(other, attr)) for attr in dir(self)]) def __lt__(self, other): if isinstance(other, type(self)): try: return self.cell_volume < other.cell_volume except AttributeError: return self.cell_area < other.cell_area @property def cell_matrix(self): """Matrix of lattice row vectors. Same as :attr:`Crystal2DLattice.ortho_matrix`\ .T or :attr:`Crystal3DLattice.ortho_matrix`\ .T. """ return (self.orientation_matrix * self.ortho_matrix).T @property def matrix(self): """Alias for \ :attr:`~sknano.core.crystallography.LatticeBase.cell_matrix`.""" return self.cell_matrix @property def fractional_matrix(self): """Transformation matrix to convert from cartesian coordinates to \ fractional coordinates.""" return np.linalg.inv(self.ortho_matrix) @property def metric_tensor(self): """Metric tensor.""" return self.cell_matrix * self.cell_matrix.T def fractional_to_cartesian(self, fcoords): """Convert fractional coordinate to cartesian coordinate. Parameters ---------- fcoords : array_like Returns ------- :class:`~numpy:numpy.ndarray` """ ccoords = self.orientation_matrix * self.ortho_matrix * \ np.asmatrix(fcoords).T + self.offset.column_matrix try: return ccoords.T.A.reshape((3, )) except ValueError: return ccoords.T.A.reshape((len(fcoords), 3)) def cartesian_to_fractional(self, ccoords): """Convert cartesian coordinate to fractional coordinate. Parameters ---------- ccoords : array_like Returns ------- :class:`~numpy:numpy.ndarray` """ fcoords = np.linalg.inv(self.ortho_matrix) * \ np.linalg.inv(self.orientation_matrix) * \ (np.asmatrix(ccoords).T - self.offset.column_matrix) try: return fcoords.T.A.reshape((3, )) except ValueError: return fcoords.T.A.reshape((len(ccoords), 3)) def wrap_fractional_coordinate(self, p, epsilon=1e-6, pbc=None): """Wrap fractional coordinate to lie within unit cell. Parameters ---------- p : array_like Returns ------- :class:`~numpy:numpy.ndarray` """ if pbc is None: pbc = np.asarray(np.ones(3), dtype=bool) p = np.ma.array(p, mask=~pbc) p = np.ma.fmod(p, 1) p[np.ma.where(p < 0)] += 1 p[np.ma.where(p > 1 - epsilon)] -= 1 p[np.ma.where(np.logical_or((p > 1 - epsilon), (p < epsilon)))] = 0 p.mask = np.ma.nomask return p.tolist() def wrap_cartesian_coordinate(self, p, pbc=None): """Wrap cartesian coordinate to lie within unit cell. Parameters ---------- p : array_like Returns ------- :class:`~numpy:numpy.ndarray` """ return self.fractional_to_cartesian( self.wrap_fractional_coordinate(self.cartesian_to_fractional(p), pbc=pbc)) def rotate(self, angle=None, axis=None, anchor_point=None, rot_point=None, from_vector=None, to_vector=None, degrees=False, transform_matrix=None, verbose=False, **kwargs): """Rotate unit cell. Parameters ---------- angle : float axis : :class:`~sknano.core.math.Vector`, optional anchor_point : :class:`~sknano.core.math.Point`, optional rot_point : :class:`~sknano.core.math.Point`, optional from_vector, to_vector : :class:`~sknano.core.math.Vector`, optional degrees : bool, optional transform_matrix : :class:`~numpy:numpy.ndarray` See Also -------- core.math.rotate """ if self.nd == 2: axis = 'z' if transform_matrix is None: transform_matrix = \ np.asmatrix( rotation_matrix(angle=angle, axis=axis, anchor_point=anchor_point, rot_point=rot_point, from_vector=from_vector, to_vector=to_vector, degrees=degrees, verbose=verbose, **kwargs)) # print('transform_matrix: {}'.format(transform_matrix)) # transform_matrix = \ # transformation_matrix(angle=angle, axis=axis, # anchor_point=anchor_point, # rot_point=rot_point, # from_vector=from_vector, # to_vector=to_vector, degrees=degrees, # verbose=verbose, **kwargs) self.orientation_matrix = \ transform_matrix * self.orientation_matrix def translate(self, t): """Translate lattice. Parameters ---------- t : :class:`Vector` See Also -------- core.math.translate """ self.offset.translate(t)