Source code for schrodinger.graphics3d.hemisphere

"""
Maestro 3D hemispheres.

The hemisphere module allows creation of hemispheres.  Clients add hemispheres
to Group instances, and Maesto draws them.

Control over the center, radius, color, resolution and opacity of a hemisphere
are provided. See the Hemisphere class for more info.

To add any number of hemispheres, create the Hemisphere instance and add it to
a Group instance. Hemispheres can be shown or hidden through the Group instance.

Copyright Schrodinger, LLC. All rights reserved.

"""

import numpy

import schrodinger

from . import common
from .common import OPACITY_MAX
from .common import OPACITY_MIN
from .common import TRANSPARENCY_MAX  # noqa: F401
from .common import TRANSPARENCY_MIN  # noqa: F401
from .common import Group  # noqa: F401

maestro = schrodinger.get_maestro()

RESOLUTION_MIN = 4
RESOLUTION_MAX = 50
RESOLUTION_DEFAULT = 16

TRANSPARENCY_DEFAULT = 0.0  # for backwards-compatibility
OPACITY_DEFAULT = 1.0

# Constants used to calculate bounding box:
BOUNDING_BOX_INIT_VALUE = 100000000.0

#############################################################################
#                              CLASSES                                      #
#############################################################################


[docs]class MaestroHemisphere(common._MaestroPrimitiveMixin, common.Primitive): """ Class to create a 3D hemisphere in Maestro. This hemisphere will be drawn at the appropriate time in Maestro to interact properly with transparent objects. Hemispheres should be added to a Group and drawing done via the Group. See Group documentation. API Example:: import schrodinger.maestro.maestro as maestro import schrodinger.graphics3d.common as common import schrodinger.graphics3d.hemisphere as hemisphere hemisphere_grp = common.Group() st = maestro.workspace_get() for at in st.atom: hemisph = hemisphere.MaestroHemisphere( center=(at.x, at.y, at.z) radius=1.0, resolution=20, opacity=0.8, color='red' ) # Add the primative to the container. hemisphere_grp.add(hemisph) # Unlike Hemisphere MaestroHemisphere simply needs to be shown to be # drawn. # No special callback like there is for Hemispheres is needed. hemisphere_grp.show() # Hide the markers. hemisphere_grp.hide() # Remove the markers hemisphere_grp.clear() """
[docs] def __init__(self, center=None, color=None, direction=(0.0, 0.0, 1.0), radius=None, opacity=OPACITY_DEFAULT, resolution=RESOLUTION_DEFAULT, angle_dep_transparency=False): """ Constructor requires: :param center: List of 3 Angstrom values indicating the center coordinate of the icosahedron. :type center: list(float, float, float) color: One of: Color object Color name (string) Tuple of (R, G, B) (each 0.0-1.0) radius: radius of the hemisphere in Angstroms Optional arguments: opacity: 0.0 (transparent) through 1.0 (opaque) Defaults to 1.0 resolution: 4 to 50 Defaults to 16 angle_dep_transparency: if true, then we modify the color of the hemisphere based on the angle from the center """ # Need to set this first because it is used by helper functions when # we set properties. self.hemisphere = None # These variables are all accessed when assign to .x, .y, or .z, so # they need to be initialized here. self._x = 0 self._y = 0 self._z = 0 if center is None: raise ValueError( "Must specify center value to define the hemisphere center") elif radius is None: raise ValueError("Must specify a value for radius") else: self.x, self.y, self.z = center self.radius = radius self.direction = direction if color is not None: self.r, self.g, self.b = common.color_arg_to_rgb(color) else: raise ValueError("Must specify a color") # Clamp to range of 0.0 and 1.0, inclusive if opacity < OPACITY_MIN: self.opacity = OPACITY_MIN elif opacity > OPACITY_MAX: self.opacity = OPACITY_MAX else: self.opacity = opacity # Clamp the resolution if resolution < RESOLUTION_MIN: self.resolution = RESOLUTION_MIN elif resolution > RESOLUTION_MAX: self.resolution = RESOLUTION_MAX else: self.resolution = resolution self.angle_dep_transparency = angle_dep_transparency self.hemisphere = maestro.create_hemisphere( self.x, self.y, self.z, self.direction[0], self.direction[1], self.direction[2], self.r, self.g, self.b, self.radius, self.opacity, self.resolution, self.angle_dep_transparency) maestro_objects = [self.hemisphere] common.Primitive.__init__(self, maestro_objects)
def _calculateBoundingBox(self, mat): xyzmin = [] xyzmax = [] for k in range(6): xyzmin.append(BOUNDING_BOX_INIT_VALUE) xyzmax.append(-BOUNDING_BOX_INIT_VALUE) x = self.x y = self.y z = self.z r = self.radius vertex = [[x - r, y - r, z + r], [x + r, y - r, z + r], [x + r, y + r, z + r], [x - r, y + r, z + r], [x - r, y - r, z - r], [x + r, y - r, z - r], [x + r, y + r, z - r], [x - r, y + r, z - r]] # yapf: disable transform = numpy.matrix(mat) tmp = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] for i in range(8): for k in range(3): tmp[k + 3] = vertex[i][k] vec = numpy.array([tmp[3], tmp[4], tmp[5], 1]) out = transform.dot(vec) for k in range(3): tmp[k] = out[0, k] xyzmin = numpy.minimum(xyzmin, tmp).tolist() xyzmax = numpy.maximum(xyzmax, tmp).tolist() return (xyzmin, xyzmax) # Helper functions
[docs] def setCoords(self): if self.hemisphere: maestro.set_coords(self.hemisphere, self._x, self._y, self._z)
[docs] def setXYZCoords(self, x, y, z): self._x = x self._y = y self._z = z self.setCoords()
# Properties @property def x(self): """Get X coordinate""" return self._x @x.setter def x(self, value): self._x = value self.setCoords() @property def y(self): """Get Y coordinate""" return self._y @y.setter def y(self, value): self._y = value self.setCoords() @property def z(self): """Get Z coordinate""" return self._z @z.setter def z(self, value): self._z = value self.setCoords() @property def radius(self): """Get hemisphere's radius in angstroms""" return self._radius @radius.setter def radius(self, value): if value <= 0.: raise ValueError("Radius must be greater than 0.") self._radius = value if self.hemisphere: maestro.set_radius(self.hemisphere, self._radius)