ase-ts
v0.1.5
Published
ASE-compatible Atoms object and readers in TypeScript
Readme
ase-ts
TypeScript reimplementation of key ASE behavior for JS/TS environments.
Scope
Atomscore data model compatible with ASE-style usage (numbers,symbols,positions,cell,pbc,arrays,info,calc)- Core geometry/mutation methods (
repeat,translate,wrap, COM, distances/angles/dihedral, rotation, formula) - Single-point result storage (
SinglePointCalculator,getPotentialEnergy(),getForces()) - ASE-style read/write API:
read()/readAll(),write()/writeAll() - Fixed-atom constraint storage (
fixedmask) for files that carry it - Implemented readers:
xyzextxyzcifpdbvasp(POSCAR/CONTCAR)vasprun-xml(vasprun.xml, structure trajectory + selectiveF F Ffixed mask + energy/forces when present)orca-output(geometry frames + energy/forces from ORCA stdout when present)traj(ASE native binary trajectory, ULM format)
- Implemented writers:
xyzextxyz(withmove_maskfor constraints)vasp/poscar(withSelective dynamicsfor constraints)pdbtraj(ASE native binary trajectory, ULM format, withFixAtoms)
Fixed Constraints
- Stored in
Atomsas a boolean mask per atom. - Read APIs:
atoms.getFixedMask()atoms.getFixedIndices()
- Auto-imported from:
extxyzmove_mask(atoms with non-movable rows are marked fixed)vaspselective dynamics (F F Frows are marked fixed)vasprun-xmlselective flags instructure name="initialpos"(F F Frows marked fixed)trajFixAtomsconstraint objects
- Auto-exported to:
extxyzmove_mask:L:1column (F= fixed,T= movable)vaspSelective dynamicssection withF F F/T T Tper-atom flagstrajFixAtomsconstraint JSON with atom indices
Reference Source
Implementation was mapped against ASE source cloned from:
- https://gitlab.com/ase/ase
Quick Start
import { Atoms, read, write } from "ase-ts";
const atoms = new Atoms({
symbols: "H2O",
positions: [[0, 0, 0], [0, 0, 1], [1, 0, 0]],
});
const xyz = `2\ncomment\nH 0 0 0\nO 0 0 1\n`;
const parsed = read(xyz, { data: true });Calculation results from supported output formats are attached as single-point calculators:
const atoms = read(orcaOutputText, { data: true, format: "orca-output" }) as Atoms;
console.log(atoms.getPotentialEnergy()); // eV
console.log(atoms.getForces()); // eV / AngstromJS Project Usage
Node / Bundler
npm install ase-tsimport { read, readAll, write, writeAll } from "ase-ts";
// --- Reading ---
// text formats
const atoms = read(inputText, { data: true, format: "extxyz" });
// binary formats — pass a file path directly (extension detected automatically)
const traj = read("path/to/md.traj"); // last frame
const frames = readAll("path/to/md.traj"); // all frames
// --- Writing ---
// write single atoms object to a file (format inferred from extension)
write(atoms, "output.extxyz");
write(atoms, "POSCAR"); // vasp format
// write trajectory
writeAll(frames, "output.traj");
// explicit format override
write(atoms, "out.txt", { format: "xyz" });Writing with constraints:
import { Atoms, write } from "ase-ts";
const atoms = new Atoms({
symbols: ["Si", "Si"],
positions: [[0, 0, 0], [1.3575, 1.3575, 1.3575]],
cell: [[5.43, 0, 0], [0, 5.43, 0], [0, 0, 5.43]],
pbc: true,
});
atoms.setFixedMask([true, false]); // first atom fixed
// extxyz → writes move_mask:L:1 column (F = fixed, T = movable)
write(atoms, "out.extxyz");
// POSCAR → writes Selective dynamics + F F F / T T T flags
write(atoms, "POSCAR");
// traj (binary) → writes FixAtoms JSON constraint with indices
write(atoms, "md.traj");Binary formats (traj) in the browser
The browser build exposes readBinary / readAllBinary for ArrayBuffer input and writeBinary / writeAllBinary for ArrayBuffer output:
<script type="module">
import { readBinary, writeBinary } from "https://cdn.jsdelivr.net/gh/<OWNER>/<REPO>@<TAG>/dist/browser.js";
// Read
const response = await fetch("md.traj");
const buffer = await response.arrayBuffer();
const atoms = readBinary(buffer, { format: "traj" }); // last frame
console.log(atoms.getChemicalFormula("hill"));
// Write — returns ArrayBuffer
const outBuf = writeBinary(atoms, { format: "traj" });
const blob = new Blob([outBuf], { type: "application/octet-stream" });
const url = URL.createObjectURL(blob);
// trigger download or send to server
</script>The browser build also exposes write / writeAll (text + binary) and writeBinary / writeAllBinary:
<script type="module">
import { write, writeBinary } from "https://cdn.jsdelivr.net/gh/<OWNER>/<REPO>@<TAG>/dist/browser.js";
const xyzText = write(atoms, "xyz"); // string
const trajBuffer = writeBinary([atoms], { format: "traj" }); // ArrayBuffer
</script>Browser (CDN) — text formats
<script type="module">
import { read, write } from "https://cdn.jsdelivr.net/gh/<OWNER>/<REPO>@<TAG>/dist/browser.js";
// Read
const atoms = read("2\ncomment\nH 0 0 0\nO 0 0 1\n", { data: true, format: "xyz" });
console.log(atoms.getChemicalFormula("hill"));
// Write — returns string for text formats
const extxyz = write(atoms, "extxyz");
console.log(extxyz);
// With constraints
atoms.setFixedMask([true, false]);
const poscar = write(atoms, "vasp"); // Selective dynamics included
const extxyzWithMask = write(atoms, "extxyz"); // move_mask column included
</script>Use a release tag (for example @v0.1.0) instead of branch names for stable caching.
Write options
| Option | Formats | Default | Description |
|--------|---------|---------|-------------|
| format | all | (from extension) | Explicit format override |
| comment | xyz, extxyz | "" | Comment / title line |
| direct | vasp | false | Write fractional (Direct) coords instead of Cartesian |
| vasp5 | vasp | true | Include species-name header line (VASP5 format) |
| sort | vasp | false | Sort atoms by species before writing |
Test
npm testBuild
npm run buildBuild output is generated in dist/.
ASE Parity Test
Runs side-by-side comparison between:
- TypeScript implementation output
- ASE output from cloned source at
.tmp_ase_ref
npm run test:parityNotes:
- parity runner uses Python with ASE and NumPy available on
python3 - compares
numbers,positions,cell,pbc, formula, masses, COM, distances, scaled positions, fixed mask, and single-point energy/forces when present
Tutorial Demo
- Notebook-style tutorial/demo page source:
demo/index.html - Browser runtime script:
demo/main.js
Deploy with GitHub Actions
GitHub-hosted runner workflow:
- File:
.github/workflows/deploy-demo.yml - Trigger: push to
main(and manualworkflow_dispatch)
Self-hosted runner workflow (manual only):
- File:
.github/workflows/deploy-demo-self-hosted.yml - Trigger:
workflow_dispatchonly (user clicks Run workflow)
Shared build/deploy chain:
npm ci->npm run build:siteactions/configure-pages@v5+actions/upload-pages-artifact@v3+actions/deploy-pages@v4
One-time repo setup:
- Open repository settings -> Pages.
- Set source to
GitHub Actions. - Open Actions tab and run
Deploy Demo (Self-Hosted)manually when needed.
