Skip to content

MolViewSpec primitives

MolViewSpec supports geometric primitives such as circles, arrows, tubes etc. These can be freely added to scenes as needed and provide a powerful tool to add custom annotations. Primitives usually require that one or more positions are defined, which can be done by providing 3D vectors or by leveraging Selectors. Selectors can reference the position of specific atoms or residues without requiring you to manually obtain their 3D coordinates.

Custom visuals using 3D vectors

Acquire a builder instance as usual. Call .primitives to enter the primitives mode and start defining one or more geometric shapes. You can customize the visuals of all primitives at this stage as well and make e.g. everything semi-transparent.

builder = create_builder()
builder.primitives(opacity=0.66)

A range of functions are available to define: mesh | lines | tube | arrow | distance | angle | label | ellipse | ellipsoid | sphere | box.

Most of them expect positions to be provided to define start and end point or the direction/orientation of a shape. Each shape can be further customized using representation-specific parameters.

.arrow(
    start=(1, 1, 1),
    direction=(0, 2.2, 0),
    tube_radius=0.05,
    show_end_cap=True,
    color="#ff00ff",
    tooltip="Y",
)

Combining primitives with ComponentExpression selections

Selectors are compatible with this part of the API, allowing you to reference the spatial coordinates of parts of a structure without the need of obtaining their 3D positional data explicitly.

The following example showcases how a ComponentExpression is used to defined start and end point of a distance measurement that will add a dashed length between both referenced residues and label it with the computed distance between the two residues.

builder = create_builder()
structure = builder.download(url=_url_for_mmcif("1tqn")).parse(format="mmcif").model_structure()
(structure.component(selector="polymer").representation().color(color="blue"))
(
    structure.component(selector=[ComponentExpression(auth_seq_id=258), ComponentExpression(auth_seq_id=508)])
    .representation(type="ball_and_stick")
    .color(color="green")
)

The following snippet creates primitives in the context of this structure.

structure.primitives()
.distance(
    start=ComponentExpression(auth_seq_id=258),
    end=ComponentExpression(auth_seq_id=508),
    color="red",
    radius=0.1,
    dash_length=0.1,
    label_template="Distance: {{distance}}",
    label_color="red",
)

Using references

More complex cases will involve multiple structures. ComponentExpression can be tied to specific structures using explicit references. This allows e.g. to distance measurements between two distinct structures.

This example loads two structures: 1tqn and 1cbs. Note the .model_structure(ref="X") invocations that assign a user-defined reference to each structures. This allows pointing to these structures as X and Y when defining primitives using Selectors.

builder = create_builder()
_1tqn = builder.download(url=_url_for_mmcif("1tqn")).parse(format="mmcif").model_structure(ref="X")
_1tqn.component(selector="polymer").representation().color(color="blue")
(
    _1tqn.component(selector=ComponentExpression(auth_seq_id=508))
    .representation(type="ball_and_stick")
    .color(color="green")
)

_1cbs = builder.download(url=_url_for_mmcif("1cbs")).parse(format="mmcif").model_structure(ref="Y")
_1cbs.component(selector="polymer").representation().color(color="blue")
(
    _1cbs.component(selector=ComponentExpression(auth_seq_id=200))
    .representation(type="ball_and_stick")
    .color(color="green")
)

Now, individual sequence positions can be used as value for the start and end position of this distance measurement despite them coming from separate structures.

(
    builder.primitives().distance(
        start=PrimitiveComponentExpressions(structure_ref="X", expressions=[ComponentExpression(auth_seq_id=508)]),
        end=PrimitiveComponentExpressions(structure_ref="Y", expressions=[ComponentExpression(auth_seq_id=200)]),
        color="purple",
        radius=1,
        dash_length=1,
        label_template="Ligand Distance: {{distance}}",
        label_color="red",
    )
)

Distance