Source code for schrodinger.graphics3d.tube

"""
Module for drawing a tube in the Workspace.

Copyright Schrodinger, LLC. All rights reserved.
"""

import schrodinger

from . import arrow
from . import common

maestro = schrodinger.get_maestro()


[docs]class MaestroTube(common.Primitive): """ A graphical tube (bond) drawn in the Workspace """
[docs] def __init__(self, point1, point2, color, radius, opacity=1.0): """ Create a Tube instance :param list point1: The [X, Y, Z] points of the first tube end :param list point2: The [X, Y, Z] points of the other tube end :param tuple color: A tuple of (R, G, B) values between 0 and 1 :param float radius: The radius of the tube in ?Angstroms? """ self.points = [point1, point2] self.color = color self.radius = radius self.opacity = opacity self.calculateXYZBox() self.createObject() super().__init__([self.obj])
[docs] def calculateXYZBox(self): """ Pre-calculate some data used in the bounding box function """ self.xbox = sorted(a[0] for a in self.points) self.ybox = sorted(a[1] for a in self.points) self.zbox = sorted(a[2] for a in self.points)
[docs] def createObject(self): """ Create a graphics object """ self.obj = maestro.create_cylinder(*self.points[0], *self.points[1], *self.color, self.radius, self.opacity, arrow.RESOLUTION_DEFAULT, remove_endcaps=False)
def _calculateBoundingBox(self, mat): """ Determine the bounding box for the current workspace rotation This method is required for all graphics primitives and is used to determine the extent of the graphics when fitting the Workspace view to its contents. :param mat: workspace rotation matrix :rtype: (list, list) :return: Each list is 6 items long and specifies the bounding box (and no, I don't undestand how) """ # Initialize lists xyzmin = [] xyzmax = [] for k in range(6): xyzmin.append(arrow.BOUNDING_BOX_INIT_VALUE) xyzmax.append(-arrow.BOUNDING_BOX_INIT_VALUE) # Determine the unrotated vertexes of an orthogonal box that completely # contains the primitive. These are the 8 points that are formed by the # minimum and maximum values of the X, Y and Z extents of the primative. # Since this is a tube, the radius entends those values in the - and + # directions as well. The points are (xmin - radius, ymin - radius, # zmin-radius), (xmin - radius, ymax + radius, zmin - radius), i.e. all # eight combinations of x, y and z min and max values. pm_radius = (-self.radius, self.radius) vertexes = [] for xval, rxval in zip(self.xbox, pm_radius): for yval, ryval in zip(self.ybox, pm_radius): for zval, rzval in zip(self.zbox, pm_radius): vertexes.append((xval + rxval, yval + ryval, zval, rzval)) # This magic is stolen from the boundary box methods in the # other schrodinger.graphics3d shape classes. 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] = vertexes[i][k] tmp[0] = mat[0][0] * tmp[3] + mat[0][1] * tmp[4] + mat[0][2] * tmp[ 5] + mat[0][3] tmp[1] = mat[1][0] * tmp[3] + mat[1][1] * tmp[4] + mat[1][2] * tmp[ 5] + mat[1][3] tmp[2] = mat[2][0] * tmp[3] + mat[2][1] * tmp[4] + mat[2][2] * tmp[ 5] + mat[2][3] for k in range(6): if xyzmin[k] > tmp[k]: xyzmin[k] = tmp[k] if xyzmax[k] < tmp[k]: xyzmax[k] = tmp[k] return (xyzmin, xyzmax)
[docs] def setColor(self, color): """ Set the color of the object :param tuple color: The (R, G, B) values in the range of 0-1 """ self.color = color maestro.set_colors(self.obj, *color, self.opacity)
[docs] def setRadius(self, radius): """ Set the radius of the object :param float radius: The radius of the object """ self.radius = radius maestro.set_radius(self.obj, radius)
[docs] def setPoints(self, point1, point2): """ Set the coordinates of the tube ends :param list point1: The [X, Y, Z] points of the first tube end :param list point2: The [X, Y, Z] points of the other tube end """ self.points = [point1, point2] self.calculateXYZBox() maestro.set_coords1(self.obj, *point1) maestro.set_coords2(self.obj, *point2)
[docs] def setEntryID(self, eid): """ Set the entry id of the object. This is used for placing the workspace graphics when the workspace is tiled. :param str eid: The entry ID to associate the graphics with """ maestro.set_entry_id(self.obj, eid)