Skip to main content

Terminal crystal structure viewer with ASCII and Unicode rendering

Project description

xtalui

CI PyPI

xtalui is a terminal-first crystal structure viewer for atomistic and crystalline structures.

xtalui demo

It renders structures directly in the terminal using:

  • ASCII, Unicode, and Braille rendering for cell edges, bonds, and atoms
  • depth-aware atom glyphs or element labels
  • interactive camera controls without launching a GUI
  • a single-command CLI: xtal STRUCTURE_FILE [STRUCTURE_FILE ...]

Features

  • Load structures through ASE
  • Load self-contained ABACUS STRU files with explicit LATTICE_VECTORS
  • Load multi-frame structure series supported by ASE
  • Accept multiple input files and concatenate all frames into one trajectory series
  • Show atoms, bonds, and the unit cell in the terminal
  • Toggle between point and sphere atom rendering
  • Display chemical formula, lattice vectors, cell lengths and angles, volume, and space group
  • Show both lattice-frame a/b/c and Cartesian x/y/z direction widgets
  • Show atomic positions and bond lengths in scrollable overlay panels
  • Calibrate the terminal aspect ratio with a Braille circle test pattern
  • Toggle labels, bonds, cell frame, color, sphere mode, and direction panels at runtime
  • Autoplay continuous rotation directly in the terminal
  • Autoplay multi-frame structure series directly in the terminal
  • Align the view along x, y, or z with one keypress
  • Wrap atoms back into the unit cell with --wrap / -w or the w key
  • Refine the cell using spglib symmetry operations with --refine or the R key
  • Filter multi-frame structures by label with --filter-label / -f

Installation

Recommended for daily use: install xtal as a standalone uv tool so it is not tied to a project virtual environment.

Once the package is published on PyPI:

uv tool install xtalui

Directly from GitHub:

uv tool install git+https://github.com/bonan-group/xtalui

Standard pip installation from PyPI:

python -m pip install xtalui

Standard pip installation directly from GitHub:

python -m pip install git+https://github.com/bonan-group/xtalui

From a local checkout:

git clone https://github.com/bonan-group/xtalui.git
cd xtalui
uv tool install --editable .

Local editable install with standard pip:

git clone https://github.com/bonan-group/xtalui.git
cd xtalui
python -m pip install -e .

If xtal is not yet on your PATH, run:

uv tool update-shell

Then you can launch the viewer directly:

xtal examples/silicon_diamond.cif

For development work inside the repository:

uv venv --python /usr/bin/python3 .venv
uv sync --extra dev

You can also run it without activating the environment:

uv run xtal --help
uv run python -m xtalui --help

Development

uv sync --extra dev
uv run pytest -q
uv run ruff check .
uv run ruff format --check .

Usage

uv run xtal structure.cif
uv run xtal frame1.xyz frame2.xyz
uv run xtal -n 1: trajectory.xyz
uv run xtal trajectory.xyz@::10 other.xyz@-5:
uv run xtal POSCAR -r 2 2 1
uv run xtal structure.cif -s 1e-3
uv run xtal structure.cif -c
uv run xtal structure.cif -w          # wrap atoms into unit cell
uv run xtal structure.cif --refine    # refine cell with spglib
uv run xtal trajectory.xyz -f Train -f Val  # filter by label
uv run xtal STRU

The repository also ships with generated sample structures:

uv run xtal examples/silicon_diamond.cif
uv run xtal examples/gaas_zincblende.cif
uv run xtal examples/graphite_hexagonal.cif

CLI Options

  • PATH: one or more structure files to open with ASE
  • If multiple paths are given, all frames from all files are concatenated into one trajectory series in the order provided
  • Append @SLICE to one filename to select a subset of frames from that file only, for example traj.xyz@::5
  • -n SLICE, --image-number SLICE: pick individual image(s) from each input file using Python slice syntax like 0, 1:, :10, or ::2
  • @SLICE on a filename overrides -n/--image-number for that file
  • -r NX NY NZ, --repeat NX NY NZ: repeat the structure along each lattice direction
  • --hide-cell: start with the unit cell hidden
  • -s FLOAT, --symprec FLOAT: set the symmetry tolerance used for space-group detection
  • -c, --color: start with element colors enabled
  • -w, --wrap: wrap atoms back into the unit cell
  • --refine: refine the cell using spglib symmetry operations
  • -f LABEL, --filter-label LABEL: only show structures whose atoms.info["label"] or atoms.info["dft_label"] matches LABEL (repeatable)

Controls

  • Left / Right: rotate around Y
  • Up / Down: rotate around X, or scroll the active overlay panel when one is open
  • x / y / z: align the view along the Cartesian axes
  • a: toggle automatic rotation
  • p: toggle the atomic positions overlay
  • B: toggle the bond-length overlay
  • t: toggle automatic frame playback for multi-frame series
  • T: toggle calibration mode
  • rXYZ: rebuild the displayed structure as an in-app XxYxZ supercell, for example r222
  • [ / ]: move backward or forward through a loaded structure series
  • j / k: scroll the active overlay panel down or up
  • 1: toggle the abc dirs panel
  • 2: toggle the xyz dirs panel
  • Shift+Left / Shift+Right: pan X
  • Shift+Up / Shift+Down: pan Y
  • + / -: zoom in/out
  • m: toggle line mode between Braille and Unicode wireframe
  • b: toggle bonds
  • c: toggle unit cell
  • C: toggle element colors
  • s: toggle sphere mode for atoms
  • w: toggle wrap (wrap atoms back into the unit cell)
  • R: toggle refine (refine the cell using spglib symmetry operations)
  • Left / Right or + / - in calibration mode: decrease or increase the render aspect ratio
  • Ctrl-R: reset the view camera, restore the launch repeat, and clear wrap/refine caches
  • l: toggle labels
  • Esc: cancel an in-progress repeat command
  • ?: toggle help
  • q: quit

Calibration

Press T to enter calibration mode. The main view is replaced by a Braille-rendered circle.

Adjust the aspect ratio with:

  • Left / Right
  • + / -

until the circle looks round in your terminal and font. The current value is shown in the footer as aspect=....

Press T again to return to the structure view. The calibrated aspect ratio is then used by:

  • the main crystal renderer
  • the abc dirs panel
  • the xyz dirs panel

Overlay Panels

Press p to show atomic positions for the current frame. The table includes:

  • atom index
  • element symbol
  • Cartesian coordinates
  • direct (fractional) coordinates

Press B to show the bond-length overlay. Each row lists:

  • the full indices of both atoms in the bond
  • the bond length
  • the periodic image offset used for that displayed bond

Both overlays are scrollable with:

  • Up / Down
  • j / k

The overlays are drawn over the main view, so opening them does not rescale the structure display.

Wrap and Refine

The viewer can apply two on-demand transforms to any frame, toggled at runtime without reloading:

  • Wrap (w key or --wrap / -w) — wraps all atomic positions back into the unit cell using ASE's atoms.wrap().
  • Refine (R key or --refine) — refines the cell and atomic positions using spglib's refine_cell(). Only supported for periodic structures.

Processing order

When both are active, refine runs first, then wrap:

raw frame → refine → wrap → displayed frame

Lazy evaluation and caching

Each frame is processed on demand when first viewed. The result is cached so that revisiting a frame does not repeat the computation. Toggling either option clears the entire cache.

Ctrl-R reset

Ctrl-R resets the camera, restores the launch repeat, turns both wrap and refine off, and clears all caches.

Atom Rendering

By default, atoms are shown as points. Press s to switch to sphere mode.

  • In Unicode mode, spheres use a constant filled-circle glyph
  • In Braille mode, spheres are rasterized on the Braille subcell grid
  • In label mode, element labels are still drawn on top of the spheres

Notes

  • The Python package name is xtalui, while the installed CLI command is xtal.
  • Space-group detection uses spglib through ASE-compatible structure data.
  • Bond detection follows the ASE GUI heuristic: a periodic neighbor list with a 1.5x covalent-radius cutoff.
  • Color mode uses ASE Jmol-style element colors for atoms and atom labels.
  • Label filtering (--filter-label / -f) matches against atoms.info["label"] or atoms.info["dft_label"] and is applied at load time only.
  • ABACUS STRU support is built in for files that include explicit LATTICE_VECTORS.
  • STRU files that rely on LATTICE_PARAMETER(S) plus latname from a separate INPUT file are not supported.
  • Braille mode is the default line renderer because it provides smoother terminal line quality.
  • Example CIF files in examples/ are generated with ASE for common crystal prototypes.

Release

Releases are tag-driven:

git tag v0.1.0
git push origin v0.1.0

The GitHub release workflow validates that the tag matches project.version, builds the package, publishes a GitHub Release, and uploads to PyPI.

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

xtalui-0.1.5.tar.gz (61.9 kB view details)

Uploaded Source

Built Distribution

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

xtalui-0.1.5-py3-none-any.whl (48.9 kB view details)

Uploaded Python 3

File details

Details for the file xtalui-0.1.5.tar.gz.

File metadata

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

File hashes

Hashes for xtalui-0.1.5.tar.gz
Algorithm Hash digest
SHA256 3d82c820747fcd07c6af1ddcefc0b8f7046176a838265b64036d22c827360af3
MD5 a1446535342f957bf2e946953cbe5f8c
BLAKE2b-256 c3417145c17799c7a0f524064c9d0db4dfc7b8f1b8a3ca8793fdf108ece4b2a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for xtalui-0.1.5.tar.gz:

Publisher: release.yml on bonan-group/xtalui

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

File details

Details for the file xtalui-0.1.5-py3-none-any.whl.

File metadata

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

File hashes

Hashes for xtalui-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 7cb625d707ac26077b49daf6ea92b515ca033ec8c1298eaa97397c043664a0bd
MD5 1f446d19ef27d01bb9f6b72973addaf2
BLAKE2b-256 34ec09e1552245cc519a7c628aaf3a76457d29cdbc5de174ffabc834f4517701

See more details on using hashes here.

Provenance

The following attestation bundles were made for xtalui-0.1.5-py3-none-any.whl:

Publisher: release.yml on bonan-group/xtalui

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