Skip to main content

marimol

Fast, reactive, and beautiful 3D molecular and crystal visualizer for marimo notebooks.

PyPI version Python 3.11+ License: MIT

marimol demo


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

  1. Fork the marimol repository to your own GitHub account by clicking the Fork button on GitHub.
  2. 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

  1. Create a feature branch on your fork: git checkout -b feature/my-new-feature
  2. Make your changes and commit them: git commit -m "feat: add support for XYZ"
  3. Push to your fork: git push origin feature/my-new-feature
  4. Open a Pull Request from your branch to the main branch 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

marimol-0.2.0.tar.gz (37.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

marimol-0.2.0-py3-none-any.whl (38.8 kB view details)

Uploaded Python 3

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

Hashes for marimol-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3e0bf986eee59cc731e066686cd9783121e3f36f6bafbd010a14e8c7312858de
MD5 ce52122d60b39550ae0337cfe1106e1c
BLAKE2b-256 0414e724b229ed5e60b33a076683a8ea3abfd55d15b4888b3ce5c113974171ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for marimol-0.2.0.tar.gz:

Publisher: publish.yml on Parzival1918/marimol

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for marimol-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fa27956028ba9c0d36f21ccbfab440117ac97fd5edc26b5f8fb387894648100f
MD5 2155f158a48d3892f9c9d062da88d4df
BLAKE2b-256 ff6e5c45bbbba83aace305eddd60f1681311db097f0e27b4c5f0a49cc89a9b25

See more details on using hashes here.

Provenance

The following attestation bundles were made for marimol-0.2.0-py3-none-any.whl:

Publisher: publish.yml on Parzival1918/marimol

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page