Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file, following t

## [Unreleased]

- Add snapshot animation support
- Add `load/s` to `MVSJ` object
- Add `find_ref` to `State` and `MVSJ` objects
- Add `ref/custom` props to builder methods where previously missing
Expand All @@ -17,7 +18,9 @@ All notable changes to this project will be documented in this file, following t
- Add `matrix` field support to `TransformParams`
- Add `instance` node type
- Add `surface_type` (`molecular` / `gaussian`) to the surface representation
- Add `transform.rotation_center` to support rotating objects around their centroids or defined points
- Support transforms and instancing on structures, components, and volumes
- Make `canvas.background_color` optional

## [v1.6.0] - 2025-04-22

Expand Down
24 changes: 23 additions & 1 deletion docs/docs/animations.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,26 @@ states = States(snapshots=[snapshot1, snapshot2], metadata=GlobalMetadata(descri

The output is valid MolViewSpec JSON that can be opened in Mol*. Mol* will interpolate between individual substates and
add smooth transitions by default. You can further customize this behavior using the `transition_duration_ms` and
`linger_duration_ms` properties.
`linger_duration_ms` properties.

## Animating Snapshots

Properties within a single snapshots can be animated. For example:

```python
builder = create_builder()
structure = builder.download(url="https://files.wwpdb.org/download/1cbs.cif").parse(format="mmcif").model_structure()
structure.component(selector="polymer").representation(type="cartoon").clip(
ref="clip", type="plane", point=[22, 13, 0], normal=[0, 0, 1]
)

anim = builder.animation()
anim.interpolate(
kind="scalar",
target_ref="clip",
duration_ms=2000,
property=["point", 2],
end=55,
easing="sin-in",
)
```
142 changes: 142 additions & 0 deletions molviewspec/app/api/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -2485,6 +2485,148 @@ def _ping_pong(key: str, snapshot_key: str, attachment: LabelAttachmentT, text:
return JSONResponse(States(snapshots=snapshots, metadata=metadata).to_dict())


@router.get("/testing/animation")
async def animation_testing_example() -> MVSResponse:
"""
Example that tests all animations
"""

builder = create_builder()
structure = builder.download(url=_url_for_mmcif("1cbs")).parse(format="mmcif").model_structure()
structure.component(selector="polymer").representation(type="cartoon").clip(
ref="clip", type="plane", point=[22, 13, 0], normal=[0, 0, 1]
).color(ref="polymer-color", color="white")

(
structure.component(selector="ligand")
.transform(
ref="xform",
translation=[5, 20, -20],
rotation=[1, 0, 0, 0, 1, 0, 0, 0, 1],
rotation_center="centroid",
)
.representation(type="ball_and_stick")
.color(ref="ligand-color", color="blue")
)

primitives1 = builder.primitives(
ref="primitives-xform",
instances=[
[
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
]
],
)

primitives1.ellipsoid(center=[0, 0, 0], radius=[2, 3, 2.5], color="red")

builder.primitives().lines(
ref="lines1",
vertices=[22, 13, 0, 22, 13, 0],
indices=[0, 1],
color="purple",
width=2,
)
builder.primitives().lines(
ref="lines2",
vertices=[23, 13, 0, 23, 13, 0],
indices=[0, 1],
color="green",
width=2,
)

anim = builder.animation(loop=True, duration_ms=2500)

anim.interpolate(
kind="scalar",
target_ref="clip",
duration_ms=2000,
property=["point", 2],
end=55,
easing="sin-in",
)

anim.interpolate(
kind="vec3",
target_ref="xform",
duration_ms=2000,
property="translation",
end=[0, 0, 0],
noise_magnitude=1,
)

anim.interpolate(
kind="vec3",
target_ref="lines1",
duration_ms=2000,
property="vertices",
end=[22, 13, 0, 22, 13, 50],
noise_magnitude=0.5,
)

anim.interpolate(
kind="scalar",
target_ref="lines2",
duration_ms=2000,
property="vertices",
end=[23, 13, 0, 23, 13, 50],
)

anim.interpolate(
kind="rotation_matrix",
target_ref="xform",
duration_ms=2000,
property="rotation",
noise_magnitude=0.2,
)

anim.interpolate(
kind="color",
target_ref="ligand-color",
property="color",
duration_ms=2000,
end="red",
)

anim.interpolate(
kind="color",
target_ref="polymer-color",
property="color",
duration_ms=2000,
frequency=3,
palette={"kind": "continuous", "colors": ["white", "purple", "white"]},
)

anim.interpolate(
kind="transform_matrix",
target_ref="primitives-xform",
property=["instances", 0],
translation_start=[20.24, 29.64, 14.85],
translation_end=[21.84, 21.71, 27.04],
pivot=[0, 0, 0],
rotation_noise_magnitude=0.2,
scale_end=[0.01, 0.01, 0.01],
duration_ms=1000,
)

return JSONResponse(builder.get_state().to_dict())


##############################################################################
# MVS specification of existing visualizations

Expand Down
Loading