Skip to content
dsh.fish
Bundle

dsh-crystal-viewer

A crystal-structure visualization window for DeepSeek Harness (DSH): a 3D structure + Q-peak viewer and parameter panel, opened as a dsh-better-sidebar tab.

Source
Nth-5620
License
MIT
Updated
Updated 6 days ago

Readme

# dsh-crystal-viewer

<strong>A crystal-structure visualization window for <a href="https://github.com/deepseek-ai/DeepSeek-Harness">DeepSeek Harness</a> (DSH).</strong>

`dsh-crystal-viewer` is a standalone DSH plugin that gives a human user a window for inspecting crystal and molecular structures directly inside DeepSeek Harness. It combines an **interactive 3D structure** (rendered with a modified build of [3Dmol.js](#open-source-attribution--gratitude)), a **Q-peak (electron-density peak) layer**, and a **live parameter panel** showing unit cell, symmetry, elements, atom statistics, Q-peak statistics and refinement R factors.

It opens as a **sidebar / bottom-dock tab** — exactly like DSH's built-in `Terminal` / `Browser` tabs — via the `dsh-better-sidebar` tab-registration API. It also registers a **file previewer** so that clicking a `.res` / `.ins` / `.cif` / `.xyz` / `.mol` / `.pdb` file in the Files tree renders it in 3D instead of a plain code viewer.

> **What this plugin is:** a *human-facing* **viewer**. It self-parses structure files (unit cell, symmetry operators, atoms, Q peaks, bonds) to draw the structure and fill the panel. It is **not** a crystallographic computation engine — solving / refinement decisions and deep geometry analysis are out of scope for this plugin.

---

## Table of contents

- [Why a viewer at all](#why-a-viewer-at-all)
- [Feature tour](#feature-tour)
- [Screenshots](#screenshots)
  - [Main view — periodic structure + full parameter panel](#main-view--periodic-structure--full-parameter-panel)
  - [Display Style dialog — Atom tab](#display-style-dialog--atom-tab)
  - [Display Style dialog — Lattice tab & the unit-cell "Style" (packing)](#display-style-dialog--lattice-tab--the-unit-cell-style-packing)
  - [Display Style dialog — View tab (projection & background)](#display-style-dialog--view-tab-projection--background)
  - [Light ⇄ dark theme linkage](#light--dark-theme-linkage)
  - [Periodic vs. non-periodic structures](#periodic-vs-non-periodic-structures)
- [Supported file formats](#supported-file-formats)
- [Getting started](#getting-started)
- [Open-source attribution & gratitude](#open-source-attribution--gratitude)
- [Compatibility](#compatibility)
- [Repository layout](#repository-layout)
- [License](#license)

---

## Why a viewer at all

A **human still needs to see the structure**. This plugin is the window that a person looks at to make the calls that actually drive a structure-solution / refinement workflow:

- Is the unit cell correct, and did I pick the right space group (or is it still P1)?
- Have R1 / wR2 / GooF converged, or do I need another refinement cycle?
- Are there large Q peaks left that I should assign as atoms, or is the electron-density map "clean"?
- Is the coordination geometry an octahedron, a square plane, or a tetrahedron?

All of these are "look at it" judgements — exactly what this viewer is for. It renders the structure and fills the panel so those calls can be made at a glance.

---

## Feature tour

A condensed, feature-oriented summary — every item below is described further in the Screenshots section with a matching image.

### 3D rendering

- **Interactive 3D structure viewer** (WebGL, no WASM dependency).
- **Atom display styles**: `None` · `Line` · `Stick` · `Ball and stick` · `CPK` (space-filling) · `Polyhedron` (coordination polyhedra).
- **Coloring**: `Custom` (one uniform color) · `Color by Element` (Jmol scheme) · `Color by Group` (periodic-table main group / transition-metal gold).
- **Bond order** toggle (show double / triple bonds when the file carries them, e.g. SDF / MOL2) · **Label atoms** toggle.
- Fine numeric controls with both **type-to-edit and ▲/▼ steppers**: line width, stick radius, ball radius, CPK scale.
- **Lattice / unit-cell box** rendering: `None` · `Dashed line` · `Line` · `Stick`, with **per-axis range** (0..2 = 2×2×2 supercell), line width / stick radius, **axis coloring** (a·b·c axes) or a custom color, and **axis labels** (a / b / c).
- **View** controls: **Perspective (center) ⇄ Parallel (orthographic)** projection, **Background** (`Follow theme` / `White` / `Dark gray` / `Custom:`), and an **Outline** edge effect.
- **Correct mouse-wheel zoom direction** (relative zoom, no jump-back) and an **un-clamped fit distance** so Perspective and Parallel render at the same apparent size.

### Crystallography

- **Complete periodic symmetry expansion** — the plugin closes the `SYMM` generator set (group multiplication) *and* applies the `LATT` lattice translation (body-centered I / face-centered F / base-centered A, B, C), so high-symmetry space groups (e.g. MOF `Fm-3m`, `Im-3`) render a **full 1×1×1 unit cell** instead of a sparse one. The tool can derive the full general-position set from just the generators + LATT (e.g. 11 `SYMM` rows + `LATT -2` → 24 general positions).
- **Lattice "Style" (packing) modes** — how symmetry operations are applied to the displayed atoms (display-only; the file is never modified):
  - **In Cell** (default) — apply symmetry to fill a complete 1×1×1 unit cell (edge atoms retained).
  - **Original** — apply symmetry but keep the raw coordinates, which may fall outside the cell.
  - **No Packing** — show the file's atoms as-is, with **no** symmetry operations. This is the key view for inspecting the **true asymmetric unit** during structure solution.
- **Q-peak (electron-density peak) layer** — rendered as an **independent, un-bonded model** (yellow point layer), toggleable. Directly shows unassigned-density candidates during structure solution.
- **Unit-cell box + supercell / grow** — unit-cell box style, supercell (2×2×2) via the `Grow` toggle or the Lattice range, and axis labels.

### Parameter panel

A live **7-group panel** populated from the parsed file:

1. **Source** — file format + name, structure title, collection temperature.
2. **Refinement** (highlighted) — `R1` · `wR2` · `GooF`, `d_max` resolution, observed / total reflections, completeness, highest difference peak / deepest hole (Δρ).
3. **Cell** — a / b / c, α / β / γ, volume V, wavelength λ, Z. (Periodic structures only.)
4. **Symmetry** — space-group hint, LATT, symmetry-operator count. (Periodic structures only.)
5. **Elements (SFAC)** — element list + `UNIT:` formula counts.
6. **Atoms** — total atom count, per-element counts.
7. **Q peaks** — collapsible group listing the number of unassigned peaks and the **top 5** by height (label, height in e/ų, fractional coordinates) with a `max` summary. Hidden entirely when there are no Q peaks.

The panel is built to answer "is it converging / should I continue?" at a glance.

### Polished UX

- **DSH-native theming** — all colors come from DSH `--dsw-*` design tokens, so the panel, the Display Style dialog and the canvas background **automatically follow the harness light / dark theme** (see the theme screenshot below). A `MutationObserver` on `body[data-ds-dark-theme]` re-renders the "Follow theme" background **live** when you flip the theme.
- **Smart UI adaptation** — the Display Style dialog shows a **Lattice tab only for periodic** structures; non-periodic (`.xyz`/`.mol`/`.pdb`) structures get only Atom + View tabs, and the panel omits Cell / Symmetry.
- **Performance gate** — the tab pauses its subscription / polling when the panel is collapsed or inactive.

---

## Screenshots

All screenshots below were taken from the **real plugin running inside a DeepSeek Harness session** — the `crystal-viewer` tab/window in the DSH UI, exactly as a user would see it. Demonstrations use the **public HKUST-1 (Cu-BTC) MOF** and the **caffeine molecule** as examples.

### Main view — periodic structure + full parameter panel

The **crystal-viewer** window shows an interactive 3D structure in the centre and the live **parameter panel** on the right. This is **HKUST-1 / Cu-BTC** (`F m -3 m`, a ≈ 26.29 Å). The plugin used the CIF's symmetry operations to render a **complete unit cell** — note how all the Cu paddle-wheel clusters and organic linkers fill the cell rather than a single asymmetric unit. The unit-cell box and axis labels are drawn.

![crystal-viewer main view — HKUST-1 complete unit cell plus full parameter panel](docs/assets/structure-hkust1-in-cell.png)

### Display Style dialog — Atom tab

Clicking **Display Style** slides in a dialog on the **left** (so it never covers the parameter panel on the right). The **Atom** tab controls how atoms and bonds are drawn:

- **Display style**: None / Line / Stick / Ball and stick / CPK / Polyhedron.
- **Coloring**: Custom (one color) or Color by (Element = Jmol scheme, or Group = periodic-table group).
- **Bond order** (show double / triple bonds) and **Label atoms** toggles.
- Context-aware numeric fields (Line width, Stick radius, Ball radius, CPK scale) with **type-to-edit and ▲/▼ steppers**.

![Display Style dialog — Atom tab alongside the full parameter panel](docs/assets/display-style-atom.png)

Switching to **Polyhedron** replaces the display with the coordination polyhedra: the framework is shown as thin sticks (bonds only), and each metal centre is drawn as a small sphere with its first coordination shell as a semi-transparent polyhedron plus the metal-to-ligand bonds — e.g. the Cu paddlewheel centres in HKUST-1 show their square-planar (4 × O) coordination. This is the "show me the coordination geometry" view that makes the "octahedron? square plane? tetrahedron?" call immediately. Centers are detected automatically by chemical character (a metal / low-electronegativity atom surrounded by donor ligands), so it works for both periodic frameworks (CIF) and molecular complexes (XYZ/PBD).

![Display Style dialog — Polyhedron display style](docs/assets/display-style-polyhedron.png)

### Display Style dialog — Lattice tab & the unit-cell "Style" (packing)

The **Lattice** tab exposes two material ideas at once:

- **Style** — the unit-cell **packing** mode, i.e. how symmetry operations are applied to the displayed atoms (display-only, never modifies the file):
  - **In Cell** — fill a complete 1×1×1 unit cell (default; the full-symmetry view above).
  - **Original** — apply symmetry but keep raw coordinates (may fall outside the cell).
  - **No Packing** — show the file's atoms as-is with no symmetry operations (the true **asymmetric unit**).
- **Range** — cells to display per direction (0..2 → 2×2×2 supercell).
- **Lattice** — unit-cell box style (None / Dashed line / Line / Stick), line width / stick radius, axis coloring (a·b·c) or a custom color, and axis labels.

![Display Style dialog — Lattice tab with In Cell packing and range controls](docs/assets/display-style-lattice.png)

The **No Packing** mode is a key structure-solution helper. Here the same HKUST-1 CIF shows **only the single asymmetric unit** (a Cu paddle-wheel fragment) in a nearly-empty cell — versus the full symmetry-packed cell above. This is what you inspect when you need to see an atom's true fractional coordinates and connectivity without the clutter of symmetry mates.

![Display Style dialog — No Packing shows the true asymmetric unit](docs/assets/display-style-no-packing.png)

### Display Style dialog — View tab (projection & background)

The **View** tab controls the projection and the canvas background:

- **Projection**: **Perspective (center)** ⇄ **Parallel** (orthographic view).
- **Background**: **Follow theme** (adapts to the harness light / dark mode), White, Dark gray, or Custom.
- **Rendering**: an **Outline** edge effect.

![Display Style dialog — View tab (projection, background, outline)](docs/assets/display-style-view.png)

### Light ⇄ dark theme linkage

The whole plugin — the parameter panel, the Display Style dialog and the 3D canvas background — consumes DSH `--dsw-*` design tokens and follows the harness theme. Here the same HKUST-1 structure is shown with the harness switched to **dark** and the background set to **Follow theme**: the canvas backdrop becomes a dark gray instead of white, and every panel re-themes in lockstep. A `MutationObserver` on the theme attribute re-renders the background live, so toggling the theme updates the view instantly.

![Dark theme — canvas background and all panels follow the harness dark mode](docs/assets/theme-dark-display-style.png)

### Periodic vs. non-periodic structures

The plugin adapts to whether the file is a **periodic** crystal (has a unit cell + symmetry) or a **non-periodic** molecular structure. Open the **caffeine** molecule (a 3D conformer) and the difference is immediate:

- **No unit-cell box**, no lattice, no axis labels.
- The parameter panel omits the **Cell** and **Symmetry** groups — it shows only Source, Elements (SFAC) and Atoms.
- The Display Style dialog presents **only the Atom and View tabs**; the **Lattice tab is hidden** (no lattice concept for a molecule).

![Non-periodic molecular structure (caffeine) — no unit cell, panel shows only Source/Elements/Atoms](docs/assets/non-periodic-xyz-caffeine.png)

![Non-periodic Display Style dialog — Lattice tab is hidden](docs/assets/non-periodic-display-style.png)

---

## Supported file formats

| Format | Role | Notes |
|--------|------|-------|
| `.cif` | Crystallographic Information File | Self-written parser + symmetry-expanded clean CIF re-emission for 3Dmol. |
| `.ins` / `.res` | SHELX input / output | Self-written parser reads unit cell, symmetry, SFAC/UNIT, atoms, Q peaks, MOLE groups, aniso / riding H; the `.res` `REM` block supplies R1 / wR2 / GooF, reflection counts and Δρ. Displayed in 3D; no screenshots are shown for this format in the README. |
| `.xyz` | Cartesian coordinates | Lightweight parser for the panel (non-periodic). |
| `.mol` | V2000 molfile | Lightweight parser for the panel; raw text fed to 3Dmol (bond order supported). |
| `.pdb` | Protein Data Bank | Lightweight parser for the panel; raw text fed to 3Dmol. |
| `.hkl` | Reflection data | **Not parsed** (not needed for 3D display; R factors come from `.res` / `.lst`). |

The `.ins` / `.res` (SHELX read/write) path fully supports round-tripping: parse the structure, view it in 3D, and read back the unit cell, symmetry, atoms, Q peaks and refinement statistics into the panel.

---

## Getting started

### Requirements

- **Node.js ≥ 22.18** — required by `tsdown` 0.22.14 (uses `Promise.withResolvers`). CI runs Node 22.
- **DeepSeek Harness (DSH)** web runtime — the plugin is a DSH *external* plugin (bundle), loaded by the DSH profile.
- **pnpm** (`corepack` or local install).

### Build

```bash
pnpm install
pnpm build        # emits lib/index.js (host) + lib/client.js (client)
pnpm typecheck
```

> `.npmrc` sets `auto-install-peers=false` because DSH host packages (`@deepseek-ai/cordis`, `dsh-better-sidebar`, `react`) are resolved at runtime from the DSH profile's hoisted `node_modules`, not from the npm registry.

### Install into a DSH profile

```bash
dsh plugin --profile <name> add dsh-crystal-viewer
# or, for local development:
dsh web --patch /abs/path/cordis.patch.yml
```

Then open the DSH web UI, click the **Crystal** entry (sidebar `+` menu / bottom dock), and open a structure file — either via the path box or by clicking a `.res`/`.cif`/`.xyz` in the Files tree.

**Hard-refresh the browser (Ctrl+F5)** after installing or updating the client bundle.

---

## Open-source attribution & gratitude

This project stands on the shoulders of several excellent open-source projects. **We are deeply grateful to their maintainers and contributors** — [`LICENSE`](LICENSE) holds this project's MIT license, and [`NOTICE`](NOTICE) records the full legal text of every third-party license we inherit.

### This plugin's own license: MIT

The `dsh-crystal-viewer` plugin itself is released under the **MIT License** (see [`LICENSE`](LICENSE)). You are free to use, copy, modify, merge, publish, distribute, sublicense and sell it, under the MIT conditions.

### 3Dmol.js — rendered & *modified*

- **Project:** [3Dmol.js](https://github.com/3dmol/3Dmol.js) — institutional-grade molecular visualization for web.
- **License:** BSD-3-Clause.
- **Role:** the rendering base (WebGL, no WASM dependency). Its `GLViewer` adds models, applies styles, draws the unit cell and handles CIF.
- **Modifications in this plugin (shipped as a modified/integrated build):**
  - Self-written SHELX/CIF **symmetry expansion** (group closure of `SYMM` generators + `LATT` lattice translations) so 1×1×1 cells of high-symmetry space groups are fully populated.
  - **Q-peak multi-layer rendering** (a separate model with bond creation disabled).
  - **Mouse-wheel zoom direction & step overrides** (relative zoom; correct direction, no jump-back), and **un-clamped fit distance** so Perspective and Parallel projections render at the same size.

### GLmol — inherited from 3Dmol.js

- **Project:** GLmol (`GLmol – Molecular Viewer on WebGL/Javascript`, v0.47).
- **Copyright:** 2011–2012, biochem_fan.
- **License:** dual-licensed MIT / LGPL3.
- **Role:** a foundational dependency bundled within 3Dmol.js; its copyright and license notices are retained in `NOTICE`.

### React

- **Project:** [React](https://react.dev/) 18.
- **License:** MIT.
- **Role:** the UI layer (viewer, parameter panel, Display Style dialog).

### dsh-better-sidebar (DSH plugin)

- **Project:** [DSH-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) — the DSH sidebar workbench this plugin hooks into.
- **License:** MIT.
- **Role:** provides the `ctx.betterSidebar` tab API; this plugin registers its `crystal-viewer` tab through it.
- **Optional peer dependency** — if it is not installed, the plugin still loads but registers no tab (graceful degradation).

---

## Compatibility

### DeepSeek Harness version

Verified and developed against **DeepSeek Harness (DSH) v0.1.1-rc.2** (stable, port 3080) and **v0.1.2-alpha.1** (developer channel, port 3081). The plugin declares `engines.dsh: ">=0.1.0"` in `dsh.plugin.json`, targeting the DSH `dsh-external` bundle/plugin interface.

> **Recommendation:** run the DSH **developer channel / alpha** profile for the newest harness APIs, or the stable `0.1.1-rc.2` profile — both are supported. Hard-refresh the browser (Ctrl+F5) after installing/updating.

### Plugin compatibility

- **`dsh-better-sidebar`** — **required for the tab entry**. This plugin registers its `crystal-viewer` tab through `ctx.betterSidebar`. Verified against **v0.17.1** (optional peer; graceful degradation if absent).
- **`@deepseek-ai/dsh-client-*`** — DSH client runtime / locale / UI-slots / conversation / modules modules are injected by the DSH profile (client bundle `inject` list in `package.json` `dsh` field).

### Known behaviors & limitations

- **Q-peak display** requires the structure to actually contain Q peaks (`.res` rows labeled `Q#`); structures without Q peaks simply have no Q-peak layer.
- Parsing is **display-oriented (thin)**, not a full crystallographic engine. Deep analyses (twinning, disorder-occupancy merge, space-group derivation, SQUEEZE, CheckCIF) are intentionally out of scope for this viewer.
- We do **not** maintain or re-distribute 3Dmol.js upstream; we ship a bundled, **modified** build. See `LICENSE` and the attribution section above.

---

## Repository layout

```
dsh-crystal-viewer/
├── src/
│   ├── index.ts              # host half: /crystal-viewer/api/read route (optional fallback)
│   ├── client/
│   │   ├── index.tsx         # client half: registerTab (entry, same mechanism as Terminal/Browser)
│   │   ├── CrystalViewer.tsx  # 3D canvas (3Dmol): atom model + Q-peak model + Display Style + toolbar
│   │   ├── CrystalEmbed.tsx  # file previewer (clicking a structure file in the Files tree)
│   │   ├── CrystalPanel.tsx  # parameter panel (7 groups, incl. Refinement + Q-peak stats)
│   │   ├── display/          # displayStyle.ts (settings model + math) / render.ts / DisplayStylePanel.tsx
│   │   └── useCrystalModel.ts# path/format → structure → CrystalModel/ViewerModel
│   └── crystal-parse/
│       ├── shelx.ts          # self-written .ins/.res parser (CELL/symmetry/atoms/Q peaks/MOLE)
│       ├── model.ts          # CrystalModel / ViewerModel / QPeak types
│       ├── assemble.ts       # parsed structure → CrystalModel/ViewerModel + formatFromPath
│       ├── cif.ts            # CrystalModel → atomCif/qPeakCif + symmetry expansion (group closure + LATT)
│       ├── cif-parse.ts      # generic .cif parser
│       ├── xyz-parse.ts      # generic .xyz parser
│       ├── mol-parse.ts      # generic .mol (V2000) parser
│       ├── pdb-parse.ts      # generic .pdb parser
│       ├── parse.ts          # unified dispatch (ins/res/cif/xyz/mol/pdb)
│       └── lst.ts            # .lst refinement statistics
├── docs/
│   └── assets/               # README screenshots
├── LICENSE                   # MIT (this project)
├── NOTICE                    # third-party notices (3Dmol.js, GLmol, React, better-sidebar)
├── package.json / dsh.plugin.json / cordis.patch.yml
├── tsconfig*.json / tsdown.config.ts
└── README.md
```

---

## License

- **This plugin:** **MIT** (see [`LICENSE`](LICENSE)).
- **Imported / modified projects:** 3Dmol.js (BSD-3-Clause), GLmol (MIT/LGPL3 dual), React (MIT), dsh-better-sidebar (MIT).

We are deeply grateful to the maintainers of these projects. If you use this plugin, please respect their licenses as well — the full third-party texts are in [`NOTICE`](NOTICE).

---

*Thank you to all open-source maintainers whose work made this possible.*

Install

dsh plugin --profile web add github:Nth-5620/dsh-crystal-viewer

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source