Skip to main content

A PyQt widget to display crystal structures

Project description

Fastmolwidget

A PyQt/PySide6 widget to display crystal structures

Fastmolwidget is a lightweight, embeddable Qt widget that renders molecular and crystal structures in 2D projection with interactive mouse controls. It supports anisotropic displacement parameter (ADP) ellipsoids, ball-and-stick diagrams, and plain sphere representations — all drawn with a pure-Python QPainter backend (no OpenGL required).

Screenshot

Fastmolwidget showing an ORTEP-style crystal structure

View of a crystal structure from a CIF file with ADP ellipsoids. The control bar allows toggling display options interactively.

Features

  • ADP ellipsoids at the 50 % probability level, rendered from anisotropic displacement parameters
  • Ball-and-stick and isotropic sphere representations as fallbacks or when speed is more important than detail
  • Interactive mouse controls: rotate (left-drag), zoom (right-drag), pan (middle-drag), scroll wheel to resize labels
  • Atom and bond selection: single click or Ctrl+click for multi-selection; emits atomClicked / bondClicked Qt signals
  • Hydrogen visibility toggle
  • Atom label display toggle with adjustable font size
  • Bond width adjustment via spin box
  • Multiple file formats: CIF, SHELX .res/.ins, and plain XYZ. More to come...
  • EmbeddableMoleculeWidget is a plain QWidget subclass; drop it into any layout
  • Ready-to-use MoleculeViewerWidget bundles the renderer with a full control bar

Supported File Formats

Extension Format Notes
.cif Crystallographic Information File Reads atoms, unit cell, and ADPs
.res / .ins SHELXL instruction file Reads atoms and unit cell via shelxfile
.xyz Standard XYZ coordinate file Cartesian coordinates, no cell or ADPs

Installation

pip install fastmolwidget

By default, fastmolwidget installs without a concrete Qt binding. Install one binding explicitly via extras:

pip install "fastmolwidget[pyside6]"
pip install "fastmolwidget[pyqt6]"

Requirements: Python >= 3.12, NumPy, gemmi, shelxfile, qtpy, and either PySide6 or PyQt6.

Quick Start

Standalone viewer

from qtpy.QtWidgets import QApplication
from fastmolwidget import MoleculeViewerWidget

app = QApplication([])
viewer = MoleculeViewerWidget()
viewer.load_file("structure.cif")
viewer.show()
app.exec()

Embedding in your own layout

from fastmolwidget import MoleculeWidget, MoleculeLoader

mol = MoleculeWidget(parent=self)
loader = MoleculeLoader(mol)
# The loader recognizes the file format from the extension and populates `mol` accordingly
loader.load_file("structure.cif")

# drop `mol` into any QLayout
layout.addWidget(mol)

Loading a different file at runtime

viewer.load_file("new_structure.res")

Reacting to atom / bond clicks

mol.atomClicked.connect(lambda label: print(f"Clicked atom: {label}"))
mol.bondClicked.connect(lambda a, b: print(f"Clicked bond: {a}{b}"))

Mouse Controls

Action Effect
Left-drag Rotate the molecule
Right-drag Zoom in / out
Middle-drag Pan the view
Scroll wheel Increase / decrease label font size
Left-click Select a single atom or bond
Ctrl + Left-click Toggle multi-selection

Control Bar Options (MoleculeViewerWidget)

Control Default Description
Show ADP Toggle ORTEP ellipsoid / isotropic sphere rendering
Show Labels Toggle non-hydrogen atom labels
Round Bonds Switch between 3D-shaded and flat bond drawing
Show Hydrogens Show or hide hydrogen atoms and their bonds
Bond Width 3 Stroke width for bonds (1–15 px)

API Overview

MoleculeViewerWidget(parent=None)

A self-contained widget combining MoleculeWidget with the control bar described above.

  • load_file(path) — load a structure file (format auto-detected from extension)
  • render_widget — read-only property exposing the underlying MoleculeWidget

MoleculeWidget(parent=None)

The low-level renderer widget. It is a plain QWidget subclass that you can drop into any layout. Provide atom data directly via open_molecule() instead of loading a file through MoleculeLoader.

Qt Signals

Signal Signature Emitted when
atomClicked (label: str) The user clicks on an atom; label is the atom name (e.g. "C1")
bondClicked (label1: str, label2: str) The user clicks on a bond; both atom labels are passed

Data Methods

  • open_molecule(atoms, cell=None, adps=None, keep_view=False)
    Load a new set of atoms and reset (or optionally preserve) the view.

    • atoms — list of Atomtuple(label, type, x, y, z, part) in Cartesian coordinates (Å)
    • cell — optional (a, b, c, α, β, γ) tuple of unit-cell parameters (Å / °); required for ADP rendering
    • adps — optional dict mapping atom labels to (U11, U22, U33, U23, U13, U12) ADP tensors
    • keep_view — when True, the current zoom, pan, and rotation are preserved (useful for live updates)
  • grow_molecule(atoms, cell=None, adps=None)
    Replace the atom set while always preserving the current view.
    Equivalent to calling open_molecule(..., keep_view=True).

  • clear()
    Remove all atoms and bonds from the display.

Display Methods

  • show_adps(value: bool)
    Toggle ORTEP-style ADP ellipsoid rendering. When False, atoms are drawn as isotropic spheres.

  • show_labels(value: bool)
    Show or hide non-hydrogen atom labels.

  • show_hydrogens(value: bool)
    Show or hide hydrogen / deuterium atoms and their bonds.

  • show_round_bonds(value: bool)
    Switch between 3D-shaded cylinder-style bonds (True, default) and flat single-colour bonds (False).

  • set_bond_width(width: int)
    Set the stroke width for bonds in pixels (valid range: 1–15).

  • setLabelFont(font_size: int)
    Set the pixel size used for atom labels.

  • set_background_color(color: QColor)
    Change the widget background colour.

  • reset_view()
    Reset zoom, pan, and rotation to their defaults.

Example — feeding atom data directly

from fastmolwidget import MoleculeWidget
from fastmolwidget.sdm import Atomtuple

mol = MoleculeWidget(parent=self)

atoms = [
    Atomtuple(label="C1", type="C", x=0.0,  y=0.0,  z=0.0,  part=0),
    Atomtuple(label="O1", type="O", x=1.22, y=0.0,  z=0.0,  part=0),
    Atomtuple(label="H1", type="H", x=-0.5, y=0.94, z=0.0,  part=0),
]

# ADP tensors: {atom_label: (U11, U22, U33, U23, U13, U12)}
adps = {
    "C1": (0.02, 0.02, 0.02, 0.0, 0.0, 0.0),
    "O1": (0.03, 0.03, 0.03, 0.0, 0.0, 0.0),
}

cell = (5.0, 5.0, 5.0, 90.0, 90.0, 90.0)   # optional

mol.open_molecule(atoms=atoms, cell=cell, adps=adps)
mol.atomClicked.connect(lambda label: print(f"Selected: {label}"))

layout.addWidget(mol)

MoleculeLoader(widget)

Format-aware loader that populates a MoleculeWidget.

  • load_file(path, keep_view=False) — parse file and call open_molecule / grow_molecule

License

BSD 2-Clause License — see LICENSE for details.

© 2026 Daniel Kratzert

Maintainer Release Workflow

The release workflow is tag-driven and currently publishes to TestPyPI only.

  1. Ensure project.version in pyproject.toml is the version to publish.
  2. Create and push a matching tag in the format version-X.Y.Z.
  3. GitHub Actions builds sdist/wheel and uploads to TestPyPI.

Example:

git tag version-0.1.0
git push origin version-0.1.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastmolwidget-0.5.1.tar.gz (50.1 kB view details)

Uploaded Source

Built Distribution

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

fastmolwidget-0.5.1-py3-none-any.whl (53.7 kB view details)

Uploaded Python 3

File details

Details for the file fastmolwidget-0.5.1.tar.gz.

File metadata

  • Download URL: fastmolwidget-0.5.1.tar.gz
  • Upload date:
  • Size: 50.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastmolwidget-0.5.1.tar.gz
Algorithm Hash digest
SHA256 aa9e3bc6715c1ab4f120d0acf5abbd1f1e967e95b29cc7ed244b2bed8096d348
MD5 c828f4642262d578c0173f581dff35bc
BLAKE2b-256 ea892efcf2288d737ba1442ac9557aca597246012514f2322c069bd976a97220

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmolwidget-0.5.1.tar.gz:

Publisher: python-publish.yml on dkratzert/Fastmolwidget

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

File details

Details for the file fastmolwidget-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: fastmolwidget-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 53.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastmolwidget-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d61d141266962bd279485a50ec4395224a7637da816bfb43ad29a1ecbd758a47
MD5 8d03c1a2047e19846eba2d5993282d71
BLAKE2b-256 0d5f0ab2d0b96087ad810e8ee0aefee2b0231d09fbc97b3a3968fb8ed324f0f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmolwidget-0.5.1-py3-none-any.whl:

Publisher: python-publish.yml on dkratzert/Fastmolwidget

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 Pingdom Monitoring Sentry Error logging StatusPage Status page