Shapes API¶
Nanome provides the ability to draw shapes to your workspace.
Shape Types¶
Sphere
Line
Label
Mesh
Basic Usage¶
from nanome.api.shapes import Shape, Sphere
from nanome.util import Color
sphere = Sphere()
sphere.radius = 1
sphere.color = Color.Blue()
Shape.upload(sphere)
from nanome.api.shapes import Mesh
from nanome.util import Color, Vector3
mesh = Mesh()
# Create a cube
mesh.vertices = [0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0]
mesh.normals = [-0.408, 0.408, 0.817, -0.667, -0.667, 0.333, 0.408, -0.408, 0.817, 0.667, 0.667, 0.333, -0.667, 0.667, -0.333, -0.408, -0.408, -0.817, 0.667, -0.667, -0.333, 0.408, 0.408, -0.817]
mesh.triangles = [0,1,2, 0,2,3, 7,6,5, 7,5,4, 3,2,6, 3,6,7, 4,0,3, 4,3,7, 4,5,1, 4,1,0, 1,5,6, 1,6,2]
mesh.anchors[0].anchor_type = nanome.util.enums.ShapeAnchorType.Workspace
mesh.anchors[0].position = Vector3(0, 0, 0)
mesh.color = Color(255, 255, 255, 255)
mesh.upload()
Positioning Shapes with Anchors¶
Shapes are positioned using associated Anchors
There are 3 main types of anchors, as enumerated in nanome.util.enums.ShapeAnchorType
ShapeAnchorTypes¶
- Workspace:
anchor.local_offset=Vector3
- Use anchor.local_offset to position the shape in the workspace
- Complex:
anchor.target=int
. (Complex Index)- Set anchor.target to the complex index, and Shape will be centered at the origin of the complex’s local coordinate space.
- Atom:
anchor.target=int
. (Atom Index)- Set anchor.target to the atom index, and Shape will be centered on the provided atom.
Anchor Tips¶
- Lines require 2 anchors.
- If multiple anchors are added to a shape, the shape will be positioned at the center of all the anchors.
- anchor.local_offset and anchor.global_offset can be used to offset the shape from the anchor point.
Shapes.Mesh API¶
Nanome provides the ability to import 3D meshes to your workspace.
Triangle array is a list of 0-based, positive integers. Vertices, normals and triangles are mandatory. Since 1.23.2, the normals are not mandatory and can be re-computed in Nanome.
Mesh coloring¶
There are several ways to color a mesh using the Shape API:
- Using the mesh color (mesh.color = Color(255, 255, 255, 128)) will uniformly color the mesh in transparent white.
- Using per-vertex colors (mesh.colors = [1.0, 1.0, 1.0, 1.0, …]) will color the mesh per-vertex (alpha is ignored).
- Using a texture (mesh.texture_path = ‘path/to/img.png’) will load the texture (jpeg or png format) and map it to the mesh using mesh.uv.
Note that the mesh color will blend with the per-vertex colors and the mesh texture.
Since Nanome 1.23.2, transparent meshes are also using textures and per-vertex colors.
As texturing the mesh uses the uv array, the texture will not be mapped if mesh.uv is not set.
Example Plugins¶
Shapes Example¶
import nanome
from nanome.api import structure
from nanome.api.shapes import Anchor, Label, Line, Shape, Sphere
from nanome.util import Vector3, enums, Color
from nanome.util.asyncio import async_callback
class ShapesExamplePlugin(nanome.AsyncPluginInstance):
"""Draw two spheres connected by a labeled line."""
@async_callback
async def on_run(self):
radius = 5
sphere1_position = Vector3(25, 100, 50)
sphere2_position = Vector3(50, 100, 50)
# Draw sphere anchored to point in Workspace
sphere1 = Sphere()
sphere1.radius = radius
sphere1.color = Color.Blue()
anchor1 = sphere1.anchors[0]
anchor1.anchor_type == enums.ShapeAnchorType.Workspace
anchor1.local_offset = sphere1_position
# Create atom, and draw sphere anchored to it
comp = self.add_complex(sphere2_position)
comp = (await self.add_to_workspace([comp]))[0]
atom = next(comp.atoms)
anchor2 = Anchor()
anchor2.anchor_type = enums.ShapeAnchorType.Atom
anchor2.target = atom.index
sphere2 = Sphere()
sphere2.radius = radius
sphere2.color = Color.Blue()
sphere2.anchors = [anchor2]
# Draw line between spheres.
line = Line()
line.thickness = 1
line.dash_distance = .75
line.color = Color.White()
line.anchors = [anchor1, anchor2]
await Shape.upload_multiple([sphere1, sphere2, line])
# Lets add a label that's centered on the line.
line_label = Label()
line_label.text = 'Label'
line_label.anchors = line.anchors
for anchor in line_label.anchors:
anchor.viewer_offset = Vector3(0, 0, -.1)
await Shape.upload(line_label)
def add_complex(self, position):
"""Add a Complex containing one atom to the workspace."""
comp = structure.Complex()
mol = structure.Molecule()
chain = structure.Chain()
res = structure.Residue()
atom = structure.Atom()
atom.label_text = 'Atom'
atom.position = position
res.add_atom(atom)
chain.add_residue(res)
mol.add_chain(chain)
comp.add_molecule(mol)
comp.name = "Test Complex"
return comp
def main():
title = 'Shapes and Lines Example'
description = 'Draw two spheres connected by a labeled line.'
advanced_settings = False
plugin = nanome.Plugin(title, description, advanced_settings)
plugin.set_plugin_class(ShapesExamplePlugin)
plugin.run()
if __name__ == '__main__':
main()
Mesh example¶
import nanome
from nanome.api.shapes import Mesh
from nanome.util import Color, Vector3
from nanome.util.asyncio import async_callback
class MeshExamplePlugin(nanome.AsyncPluginInstance):
@async_callback
async def on_run(self):
mesh = Mesh()
# Create a cube
mesh.vertices = [
0.0, 20.0, 20.0, 0.0, 0.0, 20.0, 20.0, 0.0, 20.0, 20.0, 20.0, 20.0,
0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 20.0, 20.0, 0.0]
mesh.normals = [
-0.408, 0.408, 0.817, -0.667, -0.667, 0.333, 0.408, -0.408, 0.817,
0.667, 0.667, 0.333, -0.667, 0.667, -0.333, -0.408, -0.408, -0.817,
0.667, -0.667, -0.333, 0.408, 0.408, -0.817]
mesh.triangles = [
0,1,2, 0,2,3, 7,6,5, 7,5,4, 3,2,6, 3,6,7, 4,0,3, 4,3,7, 4,5,1,
4,1,0, 1,5,6, 1,6,2]
mesh.anchors[0].anchor_type = nanome.util.enums.ShapeAnchorType.Workspace
mesh.anchors[0].position = Vector3(0, 0, 0)
mesh.color = Color(255, 255, 255, 255)
mesh.colors = [
1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 1.0]
mesh.upload()
def main():
title = "Mesh Example"
description = "Create a cube and color it with per-vertex colors"
advanced_settings = False
plugin = nanome.Plugin(title, description, advanced_settings)
plugin.set_plugin_class(MeshExamplePlugin)
plugin.run()
if __name__ == '__main__':
main()