npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@matteria-js/io

v0.1.0

Published

Structure and molecule file I/O for MATTERIA.

Readme

@matteria-js/io

Basic MATTERIA file I/O for the first migration slice. This package is the file-format boundary above @matteria-js/core: it parses strings into core data objects or simple records and writes them back to strings.

@matteria-js/io should stay boring and explicit. It should not own filesystem access, uploads, rendering, adapters, solvers, or analysis.

Public API

  • parsePoscar(text): parse VASP POSCAR/CONTCAR text into a Structure.
  • writePoscar(structure): write a Structure as POSCAR-style text.
  • parseXdatcar(text): parse a VASP XDATCAR trajectory into fixed-lattice frame records.
  • xdatcarFrameToStructure(file, frameIndex): convert one parsed XDATCAR frame into a Structure.
  • parseCif(text): parse a simple CIF structure from cell parameters and fractional atom sites.
  • writeCif(structure): write a simple P1 CIF.
  • parseXsf(text): parse a CRYSTAL XSF file with PRIMVEC and PRIMCOORD.
  • parseXsfFile(text): parse a CRYSTAL XSF structure plus DATAGRID_3D scalar grids.
  • parseXsfDatagrids(text): parse XSF DATAGRID_3D scalar grids without requiring callers to use the structure record.
  • writeXsf(structure): write a Structure as CRYSTAL/PRIMCOORD XSF.
  • parseCube(text): parse scalar Gaussian CUBE text into a CubeFile.
  • writeCube(cube): write a scalar CubeFile or compatible input as CUBE text.
  • parseVaspVolumetric(text): parse a CHGCAR/PARCHG/LOCPOT/ELFCAR-like VASP scalar volumetric file, including consecutive extra scalar-grid sections when present.
  • writeVaspVolumetric(file): write the supported VASP scalar volumetric subset.
  • parseQePwInput(text): parse a Quantum ESPRESSO pw.x input with ibrav = 0 into a Structure plus namelist, atomic-species, and k-point metadata.
  • parseQuantumEspressoPwInput(text): parse a richer Quantum ESPRESSO pw.x input record with namelists, cards, atomic species, positions, cell, k-points, and optional structure.
  • parseQuantumEspressoPwOutput(text): parse a Quantum ESPRESSO pw.x output summary for convergence, energies, forces, stress, magnetization, warnings, and Fermi level.
  • parseQuantumEspressoPpOutput(text): parse a Quantum ESPRESSO pp.x stdout summary for generated files, plot settings, warnings, and errors.
  • parseQuantumEspressoDos(text): parse Quantum ESPRESSO dos.x total DOS text into @matteria-js/electronic DensityOfStates.
  • parseQuantumEspressoProjectedDos(text): parse Quantum ESPRESSO projwfc.x .pdos_tot or .pdos_atm#... text into @matteria-js/electronic ProjectedDensityOfStates.
  • parseQuantumEspressoBands(text): parse Quantum ESPRESSO bands.x filband or GNU output into @matteria-js/electronic BandStructure.
  • parseDoscar(text): parse VASP DOSCAR total DOS into DensityOfStates and common site-projected DOS blocks into ProjectedDensityOfStates.
  • parseEigenval(text): parse VASP EIGENVAL band eigenvalues into @matteria-js/electronic BandStructure.
  • parseProcar(text): parse VASP PROCAR LORBIT-style site/orbital projections into typed arrays and a BandStructure.
  • parseVasprunXml(text): parse a common VASP vasprun.xml subset into structures, k-points, energies, forces, stress, total DOS, and band eigenvalues.
  • parsePhonopyYaml(text): parse phonopy-style band.yaml q-points, frequencies, distances, and optional eigenvectors into @matteria-js/phonons.
  • parsePhonopyTotalDos(text): parse phonopy total_dos.dat into @matteria-js/phonons PhononDensityOfStates.
  • parsePhonopyProjectedDos(text): parse phonopy projected_dos.dat frequency and projected-DOS columns.
  • parsePhonopyThermalPropertiesYaml(text): parse phonopy thermal_properties.yaml into @matteria-js/phonons PhononThermalProperties.
  • parsePhonopyForceConstants(text): parse phonopy text FORCE_CONSTANTS into @matteria-js/phonons PhononForceConstants.
  • parseXyz(text): parse simple XYZ text with element symbols and Cartesian coordinates.
  • parseXyz(text, { lattice }): parse XYZ Cartesian coordinates into a Structure when a lattice is explicitly supplied.
  • writeXyz(record): write parsed XYZ data or another { comment, atoms } record as XYZ text.
  • parseDftProject(entries): detect VASP and Quantum ESPRESSO files from virtual project entries and parse supported lightweight VASP/QE summaries without reading the filesystem.
  • collectDftProjectEntries(sources) / parseDftProjectSources(sources): consume callback-backed virtual sources such as browser File.text() wrappers or Node-side file wrappers supplied by the caller.

POSCAR / CONTCAR

import { parsePoscar, writePoscar } from "@matteria-js/io";

const poscarText = `Si
1.0
5.431 0 0
0 5.431 0
0 0 5.431
Si
2
Direct
0 0 0
0.25 0.25 0.25
`;

const structure = parsePoscar(poscarText);
console.log(structure.reducedFormula); // Si
console.log(structure.lattice.a); // 5.431

const roundTripped = writePoscar(structure);

POSCAR/CONTCAR is the periodic crystal format in this slice. Use it when lattice vectors and fractional/cartesian site coordinates must round-trip.

Current POSCAR limits:

  • VASP 5-style files with an explicit species-symbol line are required.
  • Direct and Cartesian coordinate modes are supported.
  • Selective dynamics lines and flags are accepted so common files parse, but flags are not preserved or written yet.
  • Velocities, predictor-corrector blocks, lattice velocities, and temperature metadata are deferred.

XDATCAR

parseXdatcar reads VASP XDATCAR trajectory text as a POSCAR-like fixed-lattice header plus one or more ionic-configuration frames. Frames keep the frame index from Direct configuration= ... lines when present. Use xdatcarFrameToStructure when an individual frame should become a Structure.

import { parseXdatcar, xdatcarFrameToStructure } from "@matteria-js/io";

const trajectory = parseXdatcar(xdatcarText);
const lastFrame = xdatcarFrameToStructure(trajectory, trajectory.frameCount - 1);

console.log(trajectory.frameCount);
console.log(trajectory.frames[0]?.coordinateMode);
console.log(lastFrame.reducedFormula);

Current XDATCAR limits:

  • VASP 5-style symbol lines are required.
  • Direct and Cartesian frame coordinate modes are supported.
  • The lattice is read once from the header; variable-cell trajectories are not modeled yet.
  • Frame velocities, predictor-corrector metadata, and writer support are deferred.

CIF

import { parseCif, writeCif } from "@matteria-js/io";

const structure = parseCif(cifText);
const roundTripped = writeCif(structure, { dataName: "MATTERIA" });

CIF support is deliberately small. It reads _cell_length_*, _cell_angle_*, and an _atom_site loop with type symbols and fractional coordinates. It understands quoted values, simple fractions, and uncertainty suffixes such as 5.431(2).

Current CIF limits:

  • writes P1 CIF only
  • does not preserve symmetry operations, occupancies, disorder, labels, oxidation states, or metadata
  • reads the first atom-site loop matching the supported headers

XSF

import { parseXsf, parseXsfDatagrids, parseXsfFile, writeXsf } from "@matteria-js/io";

const structure = parseXsf(xsfText);
const roundTripped = writeXsf(structure);

const xsfFile = parseXsfFile(xsfWithGridText);
const firstGrid = xsfFile.datagrids[0]?.grid;

console.log(firstGrid?.dimensions);
console.log(firstGrid?.valueLayout); // x-fastest
console.log(firstGrid?.planarAverage("z").values);

const gridsOnly = parseXsfDatagrids(qePpXsfText);

XSF support covers periodic CRYSTAL files with PRIMVEC and PRIMCOORD. Atom rows may use element symbols or integer atomic numbers. parseXsfFile also reads 3D scalar datagrids from BEGIN_BLOCK_DATAGRID_3D sections, including common QE pp.x XSF output, into ScalarFieldGrid with explicit x-fastest value layout and Angstrom length metadata.

Current XSF limits:

  • does not read molecular ATOMS blocks
  • does not read animation frames
  • reads 3D scalar datagrid blocks but does not write them
  • does not read 2D grids, animation grids, or molecular-grid variants

XYZ

import { Lattice } from "@matteria-js/core";
import { parseXyz, writeXyz } from "@matteria-js/io";

const xyzText = `2
silicon pair
Si 0 0 0
Si 1.35775 1.35775 1.35775
`;

const xyzRecord = parseXyz(xyzText);
const roundTripped = writeXyz(xyzRecord);

const boxedStructure = parseXyz(xyzText, { lattice: Lattice.cubic(10) });

XYZ is intentionally limited to simple element-symbol and Cartesian-coordinate records. Plain XYZ does not carry lattice vectors, periodic images, charges, bonding, or site properties, so it is not a full crystal serialization format.

DFT Project Manifests

import { parseDftProject } from "@matteria-js/io";

const manifest = parseDftProject([
  { path: "calc/POSCAR", text: poscarText },
  { path: "calc/INCAR", text: incarText },
  { path: "calc/KPOINTS", text: kpointsText },
  { path: "calc/OUTCAR", text: outcarText },
  { path: "calc/XDATCAR", text: xdatcarText },
  { path: "calc/vasprun.xml", size: 123_456 },
]);

console.log(manifest.codeFamily); // vasp
console.log(manifest.files.map((file) => file.role)); // ["poscar", "incar", "kpoints", "outcar", "xdatcar", "vasprun"]
console.log(manifest.files.find((file) => file.role === "incar")?.parsed?.vaspIncar?.parameters.ENCUT);
console.log(manifest.files.find((file) => file.role === "kpoints")?.parsed?.vaspKpoints?.mode);
console.log(manifest.files.find((file) => file.role === "outcar")?.parsed?.vaspOutput?.finalEnergy);
console.log(manifest.files.find((file) => file.role === "xdatcar")?.parsed?.vaspXdatcar?.frameCount);

DFT project manifests are browser/Node-compatible metadata records. Callers pass virtual entries with path or name, optional text, and optional sizeBytes/size; @matteria-js/io does not read directories or files. VASP POSCAR/CONTCAR text and explicit-cell QE pw.x inputs can be stored as serializable structure dictionaries. VASP INCAR, KPOINTS, OUTCAR/OSZICAR, XDATCAR, QE pw.x outputs, and QE pp.x outputs are parsed into compact manifest summaries for settings, k-point mode, energy/Fermi/convergence, force/stress metadata, post-processing files, and trajectory frame metadata. Large XML, volumetric, electronic, and binary-like outputs are still recorded by presence and metadata; pass vasprun.xml text to parseVasprunXml when you want the parsed VASP XML result subset.

When the caller owns an async source boundary, use parseDftProjectSources instead of giving MATTERIA filesystem access:

import { parseDftProjectSources } from "@matteria-js/io";

const manifest = await parseDftProjectSources([
  { path: "calc/POSCAR", readText: () => poscarFile.text() },
  { path: "calc/INCAR", readText: () => incarFile.text() },
  { path: "calc/CHGCAR", sizeBytes: chgcarFile.size },
]);

The default source policy reads known lightweight summary files and unknown files small enough to inspect. Use { readText: "all" } to read every source under maxTextBytes, { readText: "never" } to only detect from names and sizes, or { maxTextBytes } to cap callback-backed reads.

Use { parseStructures: false } to skip POSCAR/CONTCAR, QE input structures, and XDATCAR final-frame structure dictionaries. Use { parseVaspSummaries: false } to detect VASP files without parsing INCAR, KPOINTS, OUTCAR/OSZICAR, or XDATCAR summaries. Use { parseQeSummaries: false } to detect QE files without parsing pw.x or pp.x output summaries.

CUBE

CUBE is the first volumetric file boundary. parseCube returns a CubeFile with comments, atom metadata, a Structure, and a ScalarFieldGrid from @matteria-js/volumetric. The grid stores Angstrom-space origin, a full-cell lattice, integer dimensions, explicit x-fastest typed data, length-unit metadata, and step vectors derived from that lattice.

import { parseCube, writeCube } from "@matteria-js/io";

const cube = parseCube(cubeText);

console.log(cube.structure.numSites);
console.log(cube.grid.dimensions);
console.log(cube.grid.valueLayout); // x-fastest
console.log(cube.grid.lengthUnit); // angstrom
console.log(cube.grid.data);
console.log(cube.grid.planarAverage("z").values);

const nextText = writeCube(cube, { precision: 6 });

Current CUBE limits:

  • scalar fields only
  • one value per grid point
  • no negative atom-count multi-dataset CUBE files
  • geometry is normalized to Angstrom after parsing
  • positive grid counts are treated as Bohr in auto mode; negative grid counts are treated as Angstrom
  • Structure coordinates are stored relative to the grid origin because @matteria-js/core does not carry a separate origin yet

VASP Volumetric

parseVaspVolumetric reads CHGCAR/PARCHG/LOCPOT/ELFCAR-like files with a VASP 5 POSCAR-style header and a primary scalar grid. The primary grid is returned as ScalarFieldGrid on grid; consecutive extra scalar-grid sections are exposed through gridSections and additionalGrids.

import { parseVaspVolumetric, writeVaspVolumetric } from "@matteria-js/io";

const parsed = parseVaspVolumetric(chgcarText, { kind: "CHGCAR" });

console.log(parsed.structure.reducedFormula);
console.log(parsed.grid.dimensions);
console.log(parsed.grid.valueLayout); // x-fastest
console.log(parsed.grid.lengthUnit); // angstrom
console.log(parsed.gridSections[0]?.role);
console.log(parsed.additionalGrids?.[0]?.role);
console.log(parsed.grid.planarAverage("z").distances);

const text = writeVaspVolumetric(parsed, { valuesPerLine: 5 });

Current VASP volumetric limits:

  • VASP 5 symbol lines are required
  • one primary scalar grid is supported for writing
  • consecutive extra scalar grids are parsed into additionalGrids; for CHGCAR/PARCHG the first extra grid is labeled as magnetization density metadata
  • separated-band/k-point PARCHG variants, unlabeled trailing grids, interleaved augmentation-plus-grid blocks, and full augmentation parsing are not supported
  • clearly labeled augmentation sections are recorded as ignored metadata
  • code-specific projection metadata is deferred

Quantum ESPRESSO

parseQePwInput reads a basic Quantum ESPRESSO pw.x input with ibrav = 0, CELL_PARAMETERS, ATOMIC_SPECIES, ATOMIC_POSITIONS, and optional K_POINTS. parseQuantumEspressoPwInput preserves a richer card/namelist record while also building a Structure when the explicit cell can be resolved.

import {
  parseQeBands,
  parseQeDos,
  parseQePpOutput,
  parseQeProjectedDos,
  parseQePwInput,
  parseQePwOutput,
  parseQuantumEspressoPwInput,
} from "@matteria-js/io";

const parsed = parseQePwInput(pwInputText);
const richInput = parseQuantumEspressoPwInput(pwInputText);
const output = parseQePwOutput(pwOutputText);
const pp = parseQePpOutput(ppOutputText);
const dos = parseQeDos(dosText);
const projected = parseQeProjectedDos(projwfcPdosText, {
  sourceName: "Si.pdos_atm#1(Si)_wfc#2(p)",
});
const bands = parseQeBands(bandsText);

console.log(parsed.structure.reducedFormula);
console.log(parsed.namelists.SYSTEM?.ecutwfc);
console.log(parsed.atomicSpecies[0]?.pseudoFile);
console.log(parsed.kpoints?.mode);
console.log(richInput.cards.length);
console.log(output.finalEnergy?.value);
console.log(pp.outputFile);
console.log(dos.dos.fermiLevel);
console.log(projected.projectedDos.selectRecords({ element: "Si", orbital: "pz" }));
console.log(bands.bandStructure.getBandEnergies()[0]?.length);

Current QE limits:

  • the structure-building input path still expects explicit cell vectors; generic ibrav expansion is not implemented
  • CELL_PARAMETERS units angstrom, bohr, and alat are supported
  • ATOMIC_POSITIONS modes crystal, angstrom, bohr, and alat are supported
  • K_POINTS modes gamma, automatic, crystal, crystal_b, tpiba, and tpiba_b are parsed as metadata
  • pw.x output parsing extracts summary data only; it does not reconstruct full trajectories or XML/HDF5 results
  • pp.x output parsing extracts namelist settings, generated file names, job completion, warnings, and errors from stdout; scalar XSF grids written by pp.x are read through parseXsfFile or parseXsfDatagrids
  • dos.x support is total-DOS focused; projected DOS from projwfc.x .pdos_tot and .pdos_atm#... text files is parsed separately by parseQuantumEspressoProjectedDos
  • projwfc.x projected-DOS support preserves LDOS, atom/site metadata inferred from filenames, and component labels such as s, px, py, pz, but it does not parse the full projwfc.out log or wavefunction coefficients
  • bands.x support covers filband and GNU-style numeric outputs; labels and rich path metadata are caller supplied later
  • CUBE variants, XML/HDF5 results, non-DOS projection data, and projected wavefunction files are still future slices

DOSCAR

parseDoscar reads the DOSCAR header and the total-DOS section into a DensityOfStates object from @matteria-js/electronic. It supports both non-spin rows with energy DOS integrated-DOS and spin-polarized rows with energy DOS(up) DOS(down) integrated(up) integrated(down). When the DOSCAR contains common VASP l- or lm-decomposed per-ion blocks, it also returns a ProjectedDensityOfStates object.

import { parseDoscar } from "@matteria-js/io";
import { Spin } from "@matteria-js/electronic";

const parsed = parseDoscar(doscarText);

console.log(parsed.header.fermiLevel);
console.log(parsed.totalDos.energies); // Float64Array
console.log(parsed.totalDos.getDensity(Spin.Up));
console.log(parsed.integratedDensities[Spin.Up]);
console.log(parsed.projectedDos?.selectRecords({ siteIndex: 0, orbital: "px" }));

Current DOSCAR limits:

  • reads total DOS plus common l-decomposed s p d / s p d f and lm-decomposed s py pz px dxy dyz dz2 dxz dx2-y2 projected blocks
  • preserves integrated DOS arrays separately from DensityOfStates
  • can use siteElements and projectedOrbitalLabels options to attach element labels or parse unusual projection-column layouts
  • does not parse non-collinear spinor-resolved projected DOS or SOC-specific projected-DOS variants yet
  • does not write DOSCAR

EIGENVAL

parseEigenval reads VASP EIGENVAL band energies, k-point fractional coordinates, weights, occupations, and spin channels. It returns a BandStructure from @matteria-js/electronic plus the occupation arrays that EIGENVAL stores beside the eigenvalues.

import { parseEigenval } from "@matteria-js/io";
import { Spin } from "@matteria-js/electronic";

const parsed = parseEigenval(eigenvalText, { fermiLevel: 0 });

console.log(parsed.header.kpointCount);
console.log(parsed.bandStructure.getBandEnergies(Spin.Up));
console.log(parsed.occupations[Spin.Up]);

Current EIGENVAL limits:

  • reads spin and non-spin eigenvalue sections
  • preserves occupations separately from BandStructure
  • uses the EIGENVAL ISPIN header to choose row shape
  • does not parse projections, k-point labels, velocities, or line-mode path metadata
  • does not write EIGENVAL

PROCAR

parseProcar reads VASP PROCAR LORBIT-style projection tables. It returns a BandStructure, occupation arrays, orbital labels, and one typed projection record per spin/k-point/band block.

import { parseProcar } from "@matteria-js/io";
import { Spin } from "@matteria-js/electronic";

const parsed = parseProcar(procarText, { fermiLevel: 0 });

console.log(parsed.header.ionCount);
console.log(parsed.orbitals);
console.log(parsed.bandStructure.getBandEnergies(Spin.Up));
console.log(parsed.projections[0]?.projections); // Float64Array

Current PROCAR limits:

  • reads ordinary LORBIT-style ion ... tot tables
  • preserves per-ion, per-orbital, ion-total, orbital-total, and grand-total values
  • supports explicit spin component 1 / spin component 2 sections
  • does not parse SOC, phase-factor, or complex-projection variants yet
  • does not write PROCAR

vasprun.xml

parseVasprunXml reads the common VASP XML result structure into existing MATTERIA containers. It returns atom symbols, parsed Structure records, initialStructure, finalStructure, k-points, per-ionic-step energies, final energy values, final forces, final stress, Fermi level, total DOS, integrated DOS, and band eigenvalues as BandStructure.

import { parseVasprunXml } from "@matteria-js/io";

const parsed = parseVasprunXml(vasprunXmlText);

console.log(parsed.finalStructure?.reducedFormula);
console.log(parsed.finalEnergy?.freeEnergy);
console.log(parsed.calculationSteps.map((step) => step.energy?.freeEnergy));
console.log(parsed.finalForces?.maxForce);
console.log(parsed.finalStress?.tensor);
console.log(parsed.fermiLevel);
console.log(parsed.totalDos?.energies);
console.log(parsed.bandStructure?.getBandEnergies()[0]);

Current vasprun.xml limits:

  • parses common atominfo, structure, kpoints, calculation/energy, calculation/varray[@name="forces"], calculation/varray[@name="stress"], dos/total, and eigenvalues blocks
  • maps spin 1 and spin 2 into @matteria-js/electronic Spin.Up and Spin.Down
  • reports force vectors in eV/angstrom by default and stress tensors in kB by default when the XML block does not carry an explicit unit attribute
  • does not parse projected DOS, dielectric/optical data, parameters, magnetization, Born charges, or Hessian-like data yet
  • uses a small browser-compatible XML reader for this subset; streaming very large XML files is deferred
  • does not write vasprun.xml

Phonopy YAML

parsePhonopyYaml reads the common phonopy band.yaml shape into a PhononBandStructure from @matteria-js/phonons. It preserves q-point fractional coordinates, labels, phonopy path distances, branch frequencies, and optional complex eigenvectors in qpoint-branch-atom-xyz typed-array layout.

import { parsePhonopyYaml } from "@matteria-js/io";

const parsed = parsePhonopyYaml(phonopyBandYaml);

console.log(parsed.bandStructure.branchCount);
console.log(parsed.distances); // Float64Array when band.yaml distances are present
console.log(parsed.bandStructure.getModeVector(0, 0, 0));

Current phonopy YAML limits:

  • supports phonon: - q-position: ... band: ... frequency: ... band/mesh-like blocks
  • supports phonopy path distance, label, weight, nqpoint, natom, and optional eigenvectors
  • does not parse group velocities, Born charges, force-constant YAML variants, or full YAML as a general-purpose YAML parser
  • does not write phonopy YAML

Phonopy DOS

parsePhonopyTotalDos reads phonopy total_dos.dat rows as frequency and total-DOS columns, with an optional third integrated-DOS column. parsePhonopyProjectedDos reads phonopy projected_dos.dat rows as one frequency column followed by one projected-DOS column per atom/component/group. The projected parser also returns a summed PhononDensityOfStates for callers that want a total curve.

import { parsePhonopyProjectedDos, parsePhonopyTotalDos } from "@matteria-js/io";

const total = parsePhonopyTotalDos(totalDosDat);
const projected = parsePhonopyProjectedDos(projectedDosDat, {
  labels: ["Na", "Cl"],
});

console.log(total.dos.densities); // Float64Array
console.log(total.integratedDensities); // Float64Array when present
console.log(projected.series[0]?.densities); // Float64Array
console.log(projected.totalDos.densities); // summed projections

Current phonopy DOS limits:

  • supports whitespace- or comma-separated numeric text rows
  • preserves comments only by ignoring them; file headers are not retained
  • does not infer atom names or projection grouping from external structure files
  • does not write phonopy DOS files

Phonopy Thermal Properties

parsePhonopyThermalPropertiesYaml reads phonopy thermal_properties.yaml curves into PhononThermalProperties from @matteria-js/phonons. It preserves the unit: section for temperature, free energy, entropy, and heat capacity when present, plus common top-level metadata such as zero-point energy, cutoff frequency, mode count, and integrated-mode count.

import { parsePhonopyThermalPropertiesYaml } from "@matteria-js/io";

const parsed = parsePhonopyThermalPropertiesYaml(thermalPropertiesYaml);

console.log(parsed.thermalProperties.temperatures); // Float64Array
console.log(parsed.thermalProperties.freeEnergies); // Float64Array
console.log(parsed.thermalProperties.interpolate(300));
console.log(parsed.metadata.zeroPointEnergy);

Current phonopy thermal-property limits:

  • supports the common thermal_properties: list with temperature, free_energy, entropy, and heat_capacity
  • preserves explicit Phonopy units but does not convert between units
  • does not parse projected thermal properties, thermal displacement files, or quasi-harmonic workflows
  • does not write thermal_properties.yaml

Phonopy FORCE_CONSTANTS

parsePhonopyForceConstants reads the standard text FORCE_CONSTANTS shape: an atom-count header followed by one 1-based source/target atom-pair header and three numeric rows for every pair. It stores values in PhononForceConstants with explicit source-target-cartesian-cartesian layout, so callers can look up a 3x3 matrix by zero-based source and target atom indices without depending on input block order.

import { parsePhonopyForceConstants } from "@matteria-js/io";

const parsed = parsePhonopyForceConstants(forceConstantsText, {
  unit: "eV/angstrom^2",
});

console.log(parsed.forceConstants.atomCount);
console.log(parsed.forceConstants.getMatrix(0, 1));
console.log(parsed.forceConstants.summary().maxTransposeResidual);

Current phonopy FORCE_CONSTANTS limits:

  • supports the plain text FORCE_CONSTANTS format with complete atom-pair blocks
  • validates duplicate pairs, missing pairs, malformed 3x3 rows, and out-of-range atom indices
  • preserves an optional caller-supplied unit string but does not infer or convert units
  • does not parse force_constants.hdf5, Born effective charges, displacement datasets, or YAML force-constant variants
  • does not generate force constants, build dynamical matrices, diagonalize phonons, or write FORCE_CONSTANTS

Next Slice

After the current CIF, XSF, XSF DATAGRID, scalar CUBE, QE pw.x input/output, QE pp.x output summaries, QE DOS/bands/projwfc PDOS, VASP volumetric, XDATCAR, DOSCAR total/projected-DOS, EIGENVAL, PROCAR, vasprun.xml, phonopy band.yaml, phonopy DOS, phonopy thermal-property, and phonopy FORCE_CONSTANTS subsets, add more VASP, Quantum ESPRESSO, and phonon result files in parser-sized increments:

  • richer CHGCAR/PARCHG/LOCPOT/ELFCAR variants, including interleaved augmentation and separated-band/k-point PARCHG metadata
  • richer vasprun.xml, DOSCAR spinor, and PROCAR variants
  • richer Quantum ESPRESSO post-processing grids, richer output variants, and non-DOS projection records
  • richer phonopy force-constant metadata, binary force constants, and richer thermal/displacement files

Each parser should state what it preserves, what it ignores, whether writing is supported, and how its data maps into @matteria-js/volumetric, @matteria-js/electronic, or @matteria-js/phonons.

Deferred

Filesystem helpers, upload widgets, network access, unimplemented trajectory formats, molecule-specific models, and adapter-specific conversions are out of scope for this package. Callers should pass strings, streams, or parsed records across explicit boundaries rather than asking @matteria-js/io to own application I/O.