marimol
Fast, reactive, and beautiful 3D molecular and crystal visualizer for marimo notebooks.
marimol provides a clean, responsive, and interactive 3D WebGL molecular viewer built with Three.js and anywidget. It is designed from the ground up for marimo notebooks, enabling two-way reactivity: clicking atoms or playing through trajectories in the 3D viewport immediately updates downstream reactive notebook cells in real time.
Supports visualization of ASE, Pymatgen, mol-cspy, and native Python dictionaries with zero configuration.
For a more in depth documentation which includes interactive examples see: marimol.naujordep.com.
✨ Features
- ⚛️ Multi-format Support: Native visualizer functions for ASE (
ase.Atoms), Pymatgen (pymatgen.core.Structure/Molecule), mol-cspy (cspy.Crystal/cspy.Molecule), and standard Python dictionaries. - ⚡ Two-Way marimo Reactivity: Downstream cells automatically re-run when you click atoms (
viewer.selected_atoms) or scrub frames (viewer.current_frame). - 🎬 Trajectory Playback: Smooth multi-frame animations with play/pause, step forward/backward, configurable FPS, and an interactive frame scrubber slider.
- 📐 Measurement Tool: Built-in interactive ruler for measuring interatomic distances ($\text{Å}$), bond angles ($^\circ$), and dihedral / torsion angles ($^\circ$).
- 🧭 Coordinate Axis Snapping: Interactive XYZ triad in the corner—click X, Y, or Z to instantly align the camera along Cartesian axes.
- 🧊 Crystallography & Periodic Boundaries: Unit cell bounding boxes, crystallographic lattice vector indicators ($a, b, c$), and automatic molecule unwrapping across periodic boundary conditions (
unwrap_molecules=True). - 🎨 Visual Styles & Cel Shading: Ball-and-stick, Van der Waals (VDW), wireframe, stylized cartoon silhouette outlines (
draw_outlines=True), atom element/index labels (draw_labels=True), depth fog, and custom styles. - 📊 Metadata Drawer: Instant inspection of unit cell parameters ($a, b, c, \alpha, \beta, \gamma$), volume, density, and custom calculation results.
- 📸 Image Capture & Video Recording: High-resolution PNG screenshots (S) and WebM/MP4 animation recordings (R) of trajectories or auto-spin loops directly to your downloads.
- ❓ Interactive Help & Controls Overlay: Built-in cheatsheet of all keyboard and mouse interactions (toggle with H or the ? button).
📦 Installation
Install marimol via pip:
pip install marimol
To install with support for scientific packages (ASE, Pymatgen, and mol-cspy):
pip install "marimol[external]"
🚀 Quick Start
1. Visualizing with ASE
import marimo as mo
from ase.build import molecule
from marimol import view_ase
# Visualize a molecule
mol = molecule("CH4")
view_ase(mol)
2. Visualizing with Pymatgen
from pymatgen.core import Lattice, Structure
from marimol import view_pymatgen
# Visualize a periodic crystal structure
lattice = Lattice.cubic(4.2)
structure = Structure(lattice, ["Cs", "Cl"], [[0, 0, 0], [0.5, 0.5, 0.5]])
view_pymatgen(structure, show_axes=True, draw_outlines=True)
3. Visualizing with mol-cspy
from cspy import Molecule
from marimol import view_cspy
mol = Molecule.load("aspirin.xyz")
view_cspy(mol, style="ball-and-stick")
4. Native Python Dictionary / Trajectory
from marimol import view_structure
# Single structure or list of frames for trajectories
data = {
"positions": [[0.0, 0.0, 0.0], [1.1, 0.0, 0.0]],
"species": ["C", "O"],
"bonds": [{"source": 0, "target": 1}],
}
view_structure(data)
🔄 Two-Way Reactivity in marimo
Because marimol widgets connect directly to marimo's reactive dataflow graph, you can access and respond to user interactions in downstream notebook cells:
# Cell 1: Render the viewer and assign to a variable
viewer = view_ase(mol)
viewer
# Cell 2: Automatically updates whenever the user selects atoms in the 3D viewer!
selected_indices = viewer.selected_atoms
f"Selected {len(selected_indices)} atom(s): {selected_indices}"
# Cell 3: Access current frame during trajectory playback
current_step = viewer.current_frame
f"Currently viewing trajectory frame: {current_step}"
🎮 Viewer Controls & Shortcuts
| Action | Control |
|---|---|
| Rotate | Left-click + Drag |
| Pan | Right-click + Drag |
| Zoom | Scroll wheel / Pinch trackpad |
| Select / Inspect Atom | Click atom (displays index, species, coords in info panel) |
| Multi-select Atoms | Shift + Click atoms |
| Clear Selection | Click on background canvas |
| Snap View to Axis | Click X, Y, or Z on the bottom-left coordinate triad |
| Measurement Tool | Click the Ruler icon (top-right), then pick 2 (dist), 3 (angle), or 4 (dihedral) atoms |
| Extra Data Drawer | Click the List icon (top-right) to expand the metadata drawer |
| Capture Screenshot | Click the Camera icon or press S (when recording_tools=True) |
| Record Animation | Click the Video icon or press R (when recording_tools=True) |
| Help & Shortcuts | Press H or click the ? icon to open the controls overlay |
| Close Help | Press Esc or click outside the modal |
⚙️ Configuration & Parameters
All viewer functions (view_structure, view_ase, view_pymatgen, view_cspy) accept the following arguments:
| Parameter | Type | Default | Description |
|---|---|---|---|
data / atoms / structure |
dict | list[dict] |
Required | Structure dictionary, list of dictionaries, or external library structure object. |
config |
dict | str | PathLike |
None |
Configuration dictionary, TOML string, or path to a .toml file. Explicit arguments will overwrite config settings. |
style |
str | dict |
"ball-and-stick" |
Representation style: "ball-and-stick", "vdw", "wireframe", or custom dict. |
background_color |
str |
"white" |
Viewport background color (e.g. "white", "black", "#1e1e1e", "transparent"). |
show_axes |
bool |
False |
Display interactive XYZ coordinate triad in the bottom-left corner. |
projection |
str |
"orthographic" |
Camera projection: "orthographic" (parallel projection) or "perspective". |
width |
str |
"100%" |
CSS width of the viewer container (e.g. "100%", "600px"). |
height |
str |
"400px" |
CSS height of the viewer container (e.g. "400px", "500px"). |
viewer_outline |
bool | str |
False |
Draw border around the viewport. True for subtle border or CSS border string. |
fog |
bool |
False |
Distance fog effect for depth cueing in large lattices. |
fog_strength |
float |
0.5 |
Strength of the fog effect ($0.0$ to $1.0$). |
draw_outlines |
bool |
False |
Stylized cartoon / cel-shaded silhouette outlines around atoms and bonds. |
draw_labels |
bool |
False |
Element and index labels on atoms with 3D occlusion testing. |
measuring_tool |
bool |
False |
Enable ruler button in the top-right toolbar for distance and angle measurements. |
unwrap_molecules |
bool |
False |
Unwrap molecules split across periodic unit cell boundary conditions. |
spin |
bool |
False |
Continuous automatic 3D rotation of the structure. |
spin_axis |
tuple[float, float, float] |
(0.0, 1.0, 0.0) |
Cartesian 3D axis vector around which the structure rotates during spin. |
spin_speed |
float |
2.0 |
Angular rotation speed for auto-spin (positive for CW, negative for CCW). |
multi_traj |
bool |
True |
Trajectory media playback controls (play/pause) for multi-frame data. |
traj_fps |
float |
10.0 |
Playback speed in frames per second for trajectory animations. |
trajectory_slider |
bool |
False |
Scrubbable timeline slider in the trajectory control bar. |
compute_extra_data |
bool |
False |
Automatically compute density, volume, lattice lengths & angles, atom count, and MW for the metadata drawer. |
show_help |
bool |
True |
Show the help button and enable the H interactive controls overlay. |
recording_tools |
bool |
False |
Show screenshot (PNG) and video recording (WebM/MP4) buttons in the viewer toolbar. |
dpi |
int |
200 |
Resolution in dots per inch (DPI) for exported screenshots and video recordings. |
record_include_bgd |
bool |
False |
Include the background color in exported screenshots and video recordings (default is False for transparent backgrounds). |
record_include_ui |
bool |
False |
Include all viewer UI elements (playback controls, info panel, measurements, labels) in exported screenshots and video recordings. |
Configuration Presets (TOML / Dict)
You can maintain reusable visual presets across your notebooks using TOML strings, .toml files, or dictionaries:
toml_config = """
style = "ball-and-stick"
background_color = "#0f172a"
show_axes = true
spin = true
spin_speed = 1.5
measuring_tool = true
recording_tools = true
record_include_bgd = true
"""
# Explicit arguments take precedence and overwrite config values
view_structure(data, config=toml_config, background_color="#1e293b")
Custom Style Configuration
Pass a custom dictionary to style:
custom_style = {
"bond_radius": 0.12, # Cylinder radius for bonds in Å (0.0 hides bonds)
"atomic_radius_scaler": 0.8, # Scale factor multiplied by atomic/VdW radii
"hydrogen_atom_radius": 0.2, # Fixed radius override for hydrogen atoms
"fixed_atomic_radius": None, # Fixed radius override for all non-H atoms
"use_vdw_radii": False, # True for Van der Waals radii; False for covalent
}
view_structure(data, style=custom_style)
🚀 Interactive Examples
Interactive marimo example notebooks demonstrating molecules, trajectories, crystals, and presets are provided in the examples/ directory:
# Launch interactive marimo editor for all examples
uv run just examples
# Or edit a specific example notebook
uv run marimo edit examples/01_interactive_molecule_viewer.py
| Notebook | Description |
|---|---|
01_interactive_molecule_viewer.py |
Molecule visualization with UI controls (styles, themes, outlines, auto-spin) and two-way reactivity. |
02_trajectory_and_animation.py |
Multi-frame vibrational trajectory with media controls, scrubbable timeline, and video recording. |
03_crystal_structures_and_extra_data.py |
Periodic crystal lattices with unit cell wireframes, depth fog, and automated crystallographic metrics. |
04_toml_presets_and_themes.py |
Reusable visual presets loaded from TOML via config with parameter overrides. |
📝 Documentation
To run the interactive marimo documentation app locally:
uv run just docs-edit
Contributing
Contributions to marimol are very welcome! Whether you are reporting issues, adding support for new computational chemistry packages, improving WebGL performance, or enhancing documentation, here is how to get started:
1. Fork and clone the repository
- Fork the marimol repository to your own GitHub account by clicking the Fork button on GitHub.
- Clone your personal fork locally:
git clone https://github.com/<your-username>/marimol.git
cd marimol
2. Set up the development environment & pre-commit hooks
We use uv for fast, reproducible dependency management and just for task automation. Install dependencies with all optional extras and dev tools:
# Install dependencies with all optional extras and dev tools
uv sync --all-extras
To keep code formatting and linting consistent across the codebase, pre-commit hooks must be installed:
# Install Git hook shims via just or prek
uv run just install-hooks
Once installed, automated checks (such as Ruff formatting and linting, trailing whitespace trimming, and YAML validation) will run automatically before every commit.
3. Code style and formatting
This project uses Ruff for linting and formatting. You can run checks manually at any time:
# Run linter
uv run just lint
# Format code
uv run just format
4. Running tests
Execute the test suite using pytest:
uv run just test
5. Previewing documentation & examples
To launch and edit the interactive documentation notebook locally:
uv run just docs-edit
To launch and browse the interactive example notebooks:
uv run just examples
To test exporting the documentation to HTML:
uv run just docs-build
6. Submitting a Pull Request
- Create a feature branch on your fork:
git checkout -b feature/my-new-feature - Make your changes and commit them:
git commit -m "feat: add support for XYZ" - Push to your fork:
git push origin feature/my-new-feature - Open a Pull Request from your branch to the
mainbranch of Parzival1918/marimol.
📄 License
Distributed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file marimol-0.2.0.tar.gz.
File metadata
- Download URL: marimol-0.2.0.tar.gz
- Upload date:
- Size: 37.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e0bf986eee59cc731e066686cd9783121e3f36f6bafbd010a14e8c7312858de
|
|
| MD5 |
ce52122d60b39550ae0337cfe1106e1c
|
|
| BLAKE2b-256 |
0414e724b229ed5e60b33a076683a8ea3abfd55d15b4888b3ce5c113974171ca
|
Provenance
The following attestation bundles were made for marimol-0.2.0.tar.gz:
Publisher:
publish.yml on Parzival1918/marimol
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimol-0.2.0.tar.gz -
Subject digest:
3e0bf986eee59cc731e066686cd9783121e3f36f6bafbd010a14e8c7312858de - Sigstore transparency entry: 2479474075
- Sigstore integration time:
-
Permalink:
Parzival1918/marimol@40e6e2c8364be03dae52348f001a654693f342df -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Parzival1918
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40e6e2c8364be03dae52348f001a654693f342df -
Trigger Event:
release
-
Statement type:
File details
Details for the file marimol-0.2.0-py3-none-any.whl.
File metadata
- Download URL: marimol-0.2.0-py3-none-any.whl
- Upload date:
- Size: 38.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa27956028ba9c0d36f21ccbfab440117ac97fd5edc26b5f8fb387894648100f
|
|
| MD5 |
2155f158a48d3892f9c9d062da88d4df
|
|
| BLAKE2b-256 |
ff6e5c45bbbba83aace305eddd60f1681311db097f0e27b4c5f0a49cc89a9b25
|
Provenance
The following attestation bundles were made for marimol-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Parzival1918/marimol
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimol-0.2.0-py3-none-any.whl -
Subject digest:
fa27956028ba9c0d36f21ccbfab440117ac97fd5edc26b5f8fb387894648100f - Sigstore transparency entry: 2479474198
- Sigstore integration time:
-
Permalink:
Parzival1918/marimol@40e6e2c8364be03dae52348f001a654693f342df -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Parzival1918
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@40e6e2c8364be03dae52348f001a654693f342df -
Trigger Event:
release
-
Statement type: