matterviz 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +12 -14
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/app.css +53 -0
- package/dist/brillouin/BrillouinZone.svelte +75 -85
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
- package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +37 -31
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +7 -11
- package/dist/composition/Formula.svelte +18 -25
- package/dist/composition/FormulaFilter.svelte +92 -95
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +1 -1
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -2
- package/dist/composition/parse.js +11 -10
- package/dist/constants.js +11 -9
- package/dist/convex-hull/ConvexHull.svelte +12 -15
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +93 -92
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +109 -140
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +75 -94
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
- package/dist/convex-hull/ConvexHullControls.svelte +46 -48
- package/dist/convex-hull/ConvexHullStats.svelte +193 -195
- package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +17 -21
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +36 -36
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +18 -17
- package/dist/coordination/CoordinationBarPlot.svelte +38 -33
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +5 -8
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +24 -29
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +1 -2
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +1 -4
- package/dist/element/index.js +3 -18
- package/dist/feedback/DragOverlay.svelte +5 -5
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
- package/dist/feedback/StatusMessage.svelte +7 -4
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +14 -22
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +3 -3
- package/dist/fermi-surface/parse.js +22 -24
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/index.d.ts +5 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/io/ExportPane.svelte +10 -6
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -35
- package/dist/io/export.d.ts +4 -0
- package/dist/io/export.js +5 -1
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/index.d.ts +0 -1
- package/dist/io/index.js +2 -9
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/url-drop.js +13 -25
- package/dist/isosurface/Isosurface.svelte +17 -23
- package/dist/isosurface/IsosurfaceControls.svelte +37 -42
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +6 -6
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +43 -13
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +7 -18
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +21 -17
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +9 -10
- package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.js +1 -2
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +8 -11
- package/dist/layout/json-tree/JsonTree.svelte +53 -77
- package/dist/layout/json-tree/JsonValue.svelte +7 -15
- package/dist/layout/json-tree/utils.js +14 -23
- package/dist/math.d.ts +2 -0
- package/dist/math.js +19 -0
- package/dist/overlays/ContextMenu.svelte +4 -2
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +81 -26
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
- package/dist/overlays/GlassChip.svelte +30 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +7 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +113 -145
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +3 -3
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +21 -15
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +430 -391
- package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
- package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +301 -209
- package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
- package/dist/plot/box/Violin.svelte.d.ts +1 -0
- package/dist/plot/box/box-plot.js +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +101 -106
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +18 -9
- package/dist/plot/core/components/Line.svelte.d.ts +2 -0
- package/dist/plot/core/components/PlotAxis.svelte +40 -17
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
- package/dist/plot/core/components/ReferencePlane.svelte +7 -8
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +27 -474
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +3 -1
- package/dist/plot/core/fill-utils.js +28 -6
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.js +0 -2
- package/dist/plot/core/layout.d.ts +3 -1
- package/dist/plot/core/layout.js +22 -13
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/reference-line.js +1 -1
- package/dist/plot/core/scales.d.ts +23 -0
- package/dist/plot/core/scales.js +39 -13
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
- package/dist/plot/core/utils/hierarchy-chart.js +179 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +99 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +304 -325
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +78 -69
- package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +477 -385
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
- package/dist/plot/sunburst/Sunburst.svelte +251 -329
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +10 -3
- package/dist/plot/treemap/Treemap.svelte +907 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
- package/dist/plot/treemap/index.d.ts +3 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/treemap.d.ts +26 -0
- package/dist/plot/treemap/treemap.js +99 -0
- package/dist/rdf/RdfPlot.svelte +22 -26
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +4 -8
- package/dist/sanitize.js +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +77 -50
- package/dist/spectral/Bands.svelte +223 -230
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -27
- package/dist/spectral/Dos.svelte +70 -73
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +25 -35
- package/dist/state.svelte.js +5 -18
- package/dist/structure/Arrow.svelte +5 -18
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +115 -75
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +11 -26
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +473 -419
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +157 -399
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +72 -66
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +467 -476
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +16 -12
- package/dist/structure/atom-label-placement.js +70 -37
- package/dist/structure/atom-properties.d.ts +2 -0
- package/dist/structure/atom-properties.js +104 -38
- package/dist/structure/bonding.d.ts +10 -3
- package/dist/structure/bonding.js +84 -28
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +1 -0
- package/dist/structure/export.js +39 -31
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +22 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +16 -1
- package/dist/structure/index.js +13 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +2 -1
- package/dist/structure/parse.js +243 -222
- package/dist/structure/partial-occupancy.js +4 -2
- package/dist/structure/pbc.js +78 -98
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +3 -18
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +7 -13
- package/dist/symmetry/SymmetryElements.svelte +11 -15
- package/dist/symmetry/SymmetryStats.svelte +56 -68
- package/dist/symmetry/WyckoffTable.svelte +5 -24
- package/dist/symmetry/cell-transform.js +1 -0
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +8 -2
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1102 -365
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +5 -12
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/index.d.ts +1 -5
- package/dist/theme/index.js +4 -10
- package/dist/theme/themes.mjs +14 -7
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +2 -5
- package/dist/trajectory/Trajectory.svelte +515 -308
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
- package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
- package/dist/trajectory/extract.js +56 -34
- package/dist/trajectory/format-detect.js +11 -9
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +33 -29
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +18 -7
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +2 -3
- package/dist/trajectory/parse/index.js +17 -20
- package/dist/trajectory/parse/lammps.js +8 -12
- package/dist/trajectory/parse/vasp.js +10 -7
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
- package/dist/trajectory/parse/vaspout-h5.js +284 -0
- package/dist/trajectory/parse/xyz.js +11 -7
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +99 -27
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +47 -61
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +2 -4
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +61 -33
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as math from '../math';
|
|
3
3
|
import { MAX_METADATA_SIZE } from './constants';
|
|
4
4
|
import { copy_numeric_fields, count_xyz_frames, iter_xyz_frames, validate_3x3_matrix, } from './helpers';
|
|
5
|
-
import { strip_compression_extensions } from '../io';
|
|
5
|
+
import { strip_compression_extensions } from '../io/decompress';
|
|
6
6
|
import { decode_ase_frame, read_ase_header } from './parse/ase';
|
|
7
7
|
import { build_xyz_frame, parse_xyz_comment_metadata } from './parse/xyz';
|
|
8
8
|
// Restrict frame metadata to the requested property keys (no-op when unset)
|
|
@@ -14,6 +14,9 @@ const filter_properties = (metadata, properties) => {
|
|
|
14
14
|
export class TrajFrameReader {
|
|
15
15
|
format;
|
|
16
16
|
global_numbers;
|
|
17
|
+
// Split lines + per-frame start indices for the last XYZ payload, so repeat seeks are
|
|
18
|
+
// O(1) lookup instead of re-splitting + rescanning from line 0 (was O(n²) over playback)
|
|
19
|
+
xyz_cache;
|
|
17
20
|
constructor(filename) {
|
|
18
21
|
const base_filename = strip_compression_extensions(filename);
|
|
19
22
|
this.format = base_filename.endsWith(`.traj`) ? `ase` : `xyz`;
|
|
@@ -108,26 +111,19 @@ export class TrajFrameReader {
|
|
|
108
111
|
if (this.format === `xyz`) {
|
|
109
112
|
const lines = data.trim().split(/\r?\n/);
|
|
110
113
|
let current_frame = 0;
|
|
111
|
-
for (const {
|
|
114
|
+
for (const { comment } of iter_xyz_frames(lines)) {
|
|
112
115
|
if (current_frame >= total_frames)
|
|
113
116
|
break;
|
|
114
117
|
if (current_frame % sample_rate === 0) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
catch (error) {
|
|
125
|
-
console.warn(`Failed to parse XYZ metadata for frame ${current_frame} at line ${start + 1}:`, error);
|
|
126
|
-
}
|
|
127
|
-
if (frame_metadata) {
|
|
128
|
-
filter_properties(frame_metadata, properties);
|
|
129
|
-
metadata_list.push(frame_metadata);
|
|
130
|
-
}
|
|
118
|
+
// parse_xyz_comment_metadata is pure regex/parseFloat and never throws
|
|
119
|
+
const { step, properties: props } = parse_xyz_comment_metadata(comment);
|
|
120
|
+
const frame_metadata = {
|
|
121
|
+
frame_number: current_frame,
|
|
122
|
+
step: step ?? current_frame,
|
|
123
|
+
properties: props,
|
|
124
|
+
};
|
|
125
|
+
filter_properties(frame_metadata, properties);
|
|
126
|
+
metadata_list.push(frame_metadata);
|
|
131
127
|
}
|
|
132
128
|
current_frame++;
|
|
133
129
|
if (on_progress && current_frame % 5000 === 0) {
|
|
@@ -169,18 +165,26 @@ export class TrajFrameReader {
|
|
|
169
165
|
}
|
|
170
166
|
return metadata_list;
|
|
171
167
|
}
|
|
172
|
-
|
|
168
|
+
// Build + cache the line array and per-frame start indices once per payload
|
|
169
|
+
get_xyz_cache(data) {
|
|
170
|
+
if (this.xyz_cache?.data === data)
|
|
171
|
+
return this.xyz_cache;
|
|
173
172
|
const lines = data.trim().split(/\r?\n/);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
const frame_starts = Array.from(iter_xyz_frames(lines), ({ start }) => start);
|
|
174
|
+
this.xyz_cache = { data, lines, frame_starts };
|
|
175
|
+
return this.xyz_cache;
|
|
176
|
+
}
|
|
177
|
+
load_xyz_frame(data, frame_number) {
|
|
178
|
+
const { lines, frame_starts } = this.get_xyz_cache(data);
|
|
179
|
+
const start = frame_starts[frame_number];
|
|
180
|
+
if (start === undefined)
|
|
181
|
+
return null; // out-of-range frame
|
|
182
|
+
const num_atoms = Math.trunc(Number(lines[start]?.trim()));
|
|
183
|
+
const comment = lines[start + 1] ?? ``;
|
|
184
|
+
return build_xyz_frame(lines, { start, num_atoms, comment }, {
|
|
185
|
+
frame_label: `indexed frame ${frame_number}`,
|
|
186
|
+
default_step: frame_number,
|
|
187
|
+
});
|
|
184
188
|
}
|
|
185
189
|
load_ase_frame(data, frame_number) {
|
|
186
190
|
try {
|
|
@@ -5,6 +5,7 @@ import type { Pbc } from '../structure/pbc';
|
|
|
5
5
|
import type { TrajectoryFrame } from './index';
|
|
6
6
|
export declare function validate_3x3_matrix(data: unknown): math.Matrix3x3;
|
|
7
7
|
export declare const convert_atomic_numbers: (numbers: number[]) => ElementSymbol[];
|
|
8
|
+
export declare const count_elements: (elements: readonly string[]) => Record<string, number>;
|
|
8
9
|
export declare const create_structure: (positions: number[][], elements: ElementSymbol[], lattice_matrix?: math.Matrix3x3, pbc?: Pbc, force_data?: number[][]) => AnyStructure;
|
|
9
10
|
export declare const create_trajectory_frame: (positions: number[][], elements: ElementSymbol[], lattice_matrix: math.Matrix3x3 | undefined, pbc: Pbc | undefined, step: number, metadata?: Record<string, unknown>) => TrajectoryFrame;
|
|
10
11
|
export declare const read_ndarray_from_view: (view: DataView, ref: {
|
|
@@ -15,6 +16,7 @@ export declare function calc_force_stats(forces: number[][]): {
|
|
|
15
16
|
force_max: number;
|
|
16
17
|
force_norm: number;
|
|
17
18
|
} | null;
|
|
19
|
+
export declare const is_xyz_atom_line: (parts: string[] | undefined) => boolean;
|
|
18
20
|
export declare function iter_xyz_frames(lines: string[]): Generator<{
|
|
19
21
|
start: number;
|
|
20
22
|
num_atoms: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Shared utilities for trajectory parsing
|
|
2
2
|
import { ATOMIC_NUMBER_TO_SYMBOL } from '../composition/parse';
|
|
3
|
-
import { is_elem_symbol } from '../element';
|
|
3
|
+
import { is_elem_symbol } from '../element/helpers';
|
|
4
4
|
import * as math from '../math';
|
|
5
5
|
import { make_site } from '../structure/site';
|
|
6
6
|
const is_valid_row = (row) => {
|
|
@@ -27,6 +27,13 @@ export const convert_atomic_numbers = (numbers) => numbers.map((num) => {
|
|
|
27
27
|
}
|
|
28
28
|
return symbol;
|
|
29
29
|
});
|
|
30
|
+
// Tally per-element atom counts for trajectory metadata.element_counts
|
|
31
|
+
export const count_elements = (elements) => {
|
|
32
|
+
const counts = {};
|
|
33
|
+
for (const element of elements)
|
|
34
|
+
counts[element] = (counts[element] || 0) + 1;
|
|
35
|
+
return counts;
|
|
36
|
+
};
|
|
30
37
|
export const create_structure = (positions, elements, lattice_matrix, pbc, force_data) => {
|
|
31
38
|
if (positions.length !== elements.length) {
|
|
32
39
|
throw new Error(`create_structure requires matching positions and elements lengths, got positions=${positions.length}, elements=${elements.length}`);
|
|
@@ -141,6 +148,14 @@ export function calc_force_stats(forces) {
|
|
|
141
148
|
return { force_max, force_norm: Math.sqrt(sum_sq / forces.length) };
|
|
142
149
|
}
|
|
143
150
|
// Walk concatenated (ext)XYZ frames in `lines`, yielding each frame's atom-count line
|
|
151
|
+
// True when a whitespace-split line looks like an XYZ atom line: a short
|
|
152
|
+
// non-numeric element token followed by three numeric coordinates. Shared by
|
|
153
|
+
// trajectory frame iteration and structure-format sniffing so both stay in sync.
|
|
154
|
+
export const is_xyz_atom_line = (parts) => parts !== undefined &&
|
|
155
|
+
parts.length >= 4 &&
|
|
156
|
+
isNaN(Number(parts[0])) &&
|
|
157
|
+
parts[0].length <= 3 &&
|
|
158
|
+
parts.slice(1, 4).every((coord) => coord !== `` && !isNaN(Number(coord)));
|
|
144
159
|
// index, parsed atom count, and comment line. A candidate frame is accepted only when its
|
|
145
160
|
// first few atom lines look like "<element> <x> <y> <z>"; otherwise we advance one line and
|
|
146
161
|
// rescan. That validation doubles as content sniffing so numeric-leading non-XYZ formats
|
|
@@ -149,7 +164,7 @@ export function calc_force_stats(forces) {
|
|
|
149
164
|
export function* iter_xyz_frames(lines) {
|
|
150
165
|
let line_idx = 0;
|
|
151
166
|
while (line_idx < lines.length) {
|
|
152
|
-
const num_atoms =
|
|
167
|
+
const num_atoms = Math.trunc(Number(lines[line_idx]?.trim()));
|
|
153
168
|
if (isNaN(num_atoms) || num_atoms <= 0 || line_idx + num_atoms + 2 > lines.length) {
|
|
154
169
|
line_idx++; // skip blank/invalid lines until the next frame's atom-count line
|
|
155
170
|
continue;
|
|
@@ -157,11 +172,7 @@ export function* iter_xyz_frames(lines) {
|
|
|
157
172
|
let valid_coords = 0;
|
|
158
173
|
const sample = Math.min(num_atoms, 3);
|
|
159
174
|
for (let idx = 0; idx < sample; idx++) {
|
|
160
|
-
|
|
161
|
-
if (parts?.length >= 4 &&
|
|
162
|
-
isNaN(parseInt(parts[0], 10)) &&
|
|
163
|
-
parts[0].length <= 3 &&
|
|
164
|
-
parts.slice(1, 4).every((coord) => !isNaN(parseFloat(coord))))
|
|
175
|
+
if (is_xyz_atom_line(lines[line_idx + 2 + idx]?.trim().split(/\s+/)))
|
|
165
176
|
valid_coords++;
|
|
166
177
|
}
|
|
167
178
|
if (valid_coords < sample) {
|
|
@@ -7,6 +7,7 @@ export { default as TrajectoryExportPane } from './TrajectoryExportPane.svelte';
|
|
|
7
7
|
export { default as TrajectoryInfoPane } from './TrajectoryInfoPane.svelte';
|
|
8
8
|
export type TrajectoryFormat = `hdf5` | `json` | `xyz` | `xdatcar` | `traj` | `unknown`;
|
|
9
9
|
export type { AtomTypeMapping } from './types';
|
|
10
|
+
export declare const FRAME_LOAD_DEBOUNCE_MS = 75;
|
|
10
11
|
export interface ParseProgress {
|
|
11
12
|
current: number;
|
|
12
13
|
total: number;
|
package/dist/trajectory/index.js
CHANGED
|
@@ -2,6 +2,9 @@ export { default as Trajectory } from './Trajectory.svelte';
|
|
|
2
2
|
export { default as TrajectoryError } from './TrajectoryError.svelte';
|
|
3
3
|
export { default as TrajectoryExportPane } from './TrajectoryExportPane.svelte';
|
|
4
4
|
export { default as TrajectoryInfoPane } from './TrajectoryInfoPane.svelte';
|
|
5
|
+
// Debounce for on-demand frame loads while scrubbing: skips fetches for steps
|
|
6
|
+
// the user slides past. Exported so tests stay in sync with the real delay.
|
|
7
|
+
export const FRAME_LOAD_DEBOUNCE_MS = 75;
|
|
5
8
|
export function validate_trajectory(trajectory) {
|
|
6
9
|
// with detailed error reporting
|
|
7
10
|
const errors = [];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ElementSymbol } from '../../element/types';
|
|
2
|
+
import type { Matrix3x3 } from '../../math';
|
|
3
|
+
import type { Dataset, Entity, Group } from 'h5wasm';
|
|
4
|
+
import * as h5wasm from 'h5wasm';
|
|
5
|
+
export declare const is_hdf5_dataset: (entity: Entity | null) => entity is Dataset;
|
|
6
|
+
export declare const is_hdf5_group: (entity: Entity | null) => entity is Group;
|
|
7
|
+
export declare const read_dataset: (h5_file: h5wasm.File, path: string) => unknown;
|
|
8
|
+
export declare const to_string_array: (data: unknown) => string[] | null;
|
|
9
|
+
export declare const to_number_array: (data: unknown) => number[] | null;
|
|
10
|
+
export declare const to_scalar_number: (data: unknown) => number | null;
|
|
11
|
+
export declare const scale_matrix: (matrix: Matrix3x3, scale: number) => Matrix3x3;
|
|
12
|
+
export declare const expand_ion_types: (ion_types: string[], ion_counts: number[]) => ElementSymbol[];
|
|
13
|
+
export declare function with_h5_file<T>(buffer: ArrayBuffer, filename: string | undefined, callback: (h5_file: h5wasm.File) => T | Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Shared h5wasm plumbing for HDF5 trajectory parsers: type guards plus the
|
|
2
|
+
// write-to-in-memory-FS/open/cleanup lifecycle both torch-sim and vaspout
|
|
3
|
+
// parsing need (the FS write is the expensive part, so parsers share one open
|
|
4
|
+
// file handle instead of re-opening per format probe).
|
|
5
|
+
import { is_elem_symbol } from '../../element/helpers';
|
|
6
|
+
import * as h5wasm from 'h5wasm';
|
|
7
|
+
export const is_hdf5_dataset = (entity) => entity !== null && `to_array` in entity && entity instanceof h5wasm.Dataset;
|
|
8
|
+
export const is_hdf5_group = (entity) => entity !== null && `keys` in entity && entity instanceof h5wasm.Group;
|
|
9
|
+
// Datasets in interrupted files can be torn mid-chunk, making to_array throw —
|
|
10
|
+
// treat unreadable datasets like missing ones so callers keep what parsed so far.
|
|
11
|
+
export const read_dataset = (h5_file, path) => {
|
|
12
|
+
try {
|
|
13
|
+
const entity = h5_file.get(path);
|
|
14
|
+
return is_hdf5_dataset(entity) ? entity.to_array() : null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
// h5wasm returns JS strings for variable-length UTF-8 but may hand back byte
|
|
21
|
+
// arrays for fixed-length string datasets (like VASP's |S2 ion_types).
|
|
22
|
+
export const to_string_array = (data) => {
|
|
23
|
+
if (!Array.isArray(data))
|
|
24
|
+
return null;
|
|
25
|
+
const decoder = new TextDecoder();
|
|
26
|
+
const strings = [];
|
|
27
|
+
for (const item of data) {
|
|
28
|
+
if (typeof item === `string`)
|
|
29
|
+
strings.push(item.trim());
|
|
30
|
+
else if (item instanceof Uint8Array)
|
|
31
|
+
strings.push(decoder.decode(item).trim());
|
|
32
|
+
else
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return strings;
|
|
36
|
+
};
|
|
37
|
+
// Integer datasets (like int64 number_ion_types) can surface as BigInt
|
|
38
|
+
// values or typed arrays depending on dtype; normalize to plain numbers.
|
|
39
|
+
export const to_number_array = (data) => {
|
|
40
|
+
const values = Array.isArray(data)
|
|
41
|
+
? data
|
|
42
|
+
: ArrayBuffer.isView(data)
|
|
43
|
+
? Array.from(data)
|
|
44
|
+
: null;
|
|
45
|
+
if (!values)
|
|
46
|
+
return null;
|
|
47
|
+
const numbers = values.map((item) => (typeof item === `bigint` ? Number(item) : item));
|
|
48
|
+
return numbers.every((item) => typeof item === `number` && Number.isFinite(item))
|
|
49
|
+
? numbers
|
|
50
|
+
: null;
|
|
51
|
+
};
|
|
52
|
+
// Scalar datasets surface as plain numbers, 1-element arrays, or BigInt
|
|
53
|
+
// depending on dtype; normalize to a finite number or null.
|
|
54
|
+
export const to_scalar_number = (data) => {
|
|
55
|
+
const value = Array.isArray(data) ? data[0] : data;
|
|
56
|
+
if (typeof value === `bigint`)
|
|
57
|
+
return Number(value);
|
|
58
|
+
return typeof value === `number` && Number.isFinite(value) ? value : null;
|
|
59
|
+
};
|
|
60
|
+
// Apply VASP's POSCAR-style universal scaling factor to lattice vectors
|
|
61
|
+
export const scale_matrix = (matrix, scale) => scale === 1 ? matrix : matrix.map((row) => row.map((val) => val * scale));
|
|
62
|
+
// Expand VASP's (ion_types, number_ion_types) pair into per-atom symbols,
|
|
63
|
+
// e.g. ([Ga, Sb], [1, 1]) -> [Ga, Sb]. Throws on unknown symbols and
|
|
64
|
+
// malformed counts so torn/corrupt HDF5 input fails loudly, not by dropping atoms.
|
|
65
|
+
export const expand_ion_types = (ion_types, ion_counts) => {
|
|
66
|
+
if (ion_types.length !== ion_counts.length) {
|
|
67
|
+
throw new Error(`ion_types (${ion_types.length}) and ion_counts (${ion_counts.length}) length mismatch`);
|
|
68
|
+
}
|
|
69
|
+
const elements = [];
|
|
70
|
+
for (const [type_idx, symbol] of ion_types.entries()) {
|
|
71
|
+
if (!is_elem_symbol(symbol)) {
|
|
72
|
+
throw new Error(`Unknown element symbol in ion_types: ${symbol}`);
|
|
73
|
+
}
|
|
74
|
+
const ion_count = ion_counts[type_idx];
|
|
75
|
+
if (!Number.isFinite(ion_count) || !Number.isInteger(ion_count) || ion_count < 0) {
|
|
76
|
+
throw new Error(`Invalid ion count for ${symbol}: ${ion_count}`);
|
|
77
|
+
}
|
|
78
|
+
for (let count = 0; count < ion_count; count++)
|
|
79
|
+
elements.push(symbol);
|
|
80
|
+
}
|
|
81
|
+
return elements;
|
|
82
|
+
};
|
|
83
|
+
// Writes the buffer to h5wasm's in-memory FS under a unique temp name, opens
|
|
84
|
+
// it, runs the callback (awaiting async ones so cleanup can't race reads),
|
|
85
|
+
// and always closes + unlinks afterwards.
|
|
86
|
+
export async function with_h5_file(buffer, filename, callback) {
|
|
87
|
+
const { FS } = await h5wasm.ready;
|
|
88
|
+
const file_basename = filename
|
|
89
|
+
?.split(`/`)
|
|
90
|
+
.at(-1)
|
|
91
|
+
?.replaceAll(/[^\w.-]/g, `_`) ?? `temp`;
|
|
92
|
+
const unique_suffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
93
|
+
const temp_filename = `${file_basename}-${unique_suffix}.h5`;
|
|
94
|
+
FS.writeFile(temp_filename, new Uint8Array(buffer));
|
|
95
|
+
let h5_file = null;
|
|
96
|
+
try {
|
|
97
|
+
h5_file = new h5wasm.File(temp_filename, `r`);
|
|
98
|
+
return await callback(h5_file);
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
h5_file?.close();
|
|
102
|
+
try {
|
|
103
|
+
FS.unlink(temp_filename);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
/* temp file cleanup is best-effort */
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { TrajectoryType } from '../index';
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function parse_hdf5_trajectory(buffer: ArrayBuffer, filename?: string): Promise<TrajectoryType>;
|
|
@@ -1,78 +1,96 @@
|
|
|
1
|
-
// HDF5 trajectory parsing
|
|
1
|
+
// HDF5 trajectory parsing: dispatches between VASP vaspout.h5 and the
|
|
2
|
+
// torch-sim / generic dataset-alias layout after a single file open.
|
|
2
3
|
import { calc_lattice_params, transpose_3x3_matrix } from '../../math';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
if (result)
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
4
|
+
import { convert_atomic_numbers, count_elements, create_trajectory_frame, validate_3x3_matrix, } from '../helpers';
|
|
5
|
+
import { is_hdf5_dataset, is_hdf5_group, read_dataset, with_h5_file } from './h5-utils';
|
|
6
|
+
import { is_vaspout_h5_file, parse_vaspout_h5_file } from './vaspout-h5';
|
|
7
|
+
// Routes an opened HDF5 file to the right parser: vaspout.h5 has the VASP 6.x
|
|
8
|
+
// root-group layout, everything else falls through to the torch-sim recursive
|
|
9
|
+
// dataset-name search. One FS write + open, no parse-and-fallback.
|
|
10
|
+
export async function parse_hdf5_trajectory(buffer, filename) {
|
|
11
|
+
return with_h5_file(buffer, filename, (h5_file) => is_vaspout_h5_file(h5_file)
|
|
12
|
+
? parse_vaspout_h5_file(h5_file)
|
|
13
|
+
: parse_torch_sim_h5_file(h5_file));
|
|
14
|
+
}
|
|
15
|
+
// Dataset-name aliases searched (in order) across the whole group tree
|
|
16
|
+
const POSITION_ALIASES = [`positions`, `coords`, `coordinates`];
|
|
17
|
+
const ATOMIC_NUMBER_ALIASES = [`atomic_numbers`, `numbers`, `Z`, `species`];
|
|
18
|
+
const CELL_ALIASES = [`cell`, `cells`, `lattice`];
|
|
19
|
+
const ENERGY_ALIASES = [`potential_energy`, `energy`];
|
|
20
|
+
function parse_torch_sim_h5_file(h5_file) {
|
|
21
|
+
const alias_groups = [POSITION_ALIASES, ATOMIC_NUMBER_ALIASES, CELL_ALIASES, ENERGY_ALIASES];
|
|
22
|
+
const all_aliases = new Set(alias_groups.flat());
|
|
23
|
+
const found_paths = {};
|
|
24
|
+
const found_alias_groups = new Set();
|
|
25
|
+
let total_groups_found = 0;
|
|
26
|
+
const discover = (parent, path = ``) => {
|
|
27
|
+
total_groups_found++;
|
|
28
|
+
for (const name of parent.keys()) {
|
|
29
|
+
const item = parent.get(name);
|
|
30
|
+
const full_path = path ? `${path}/${name}` : `/${name}`;
|
|
31
|
+
if (is_hdf5_dataset(item) && all_aliases.has(name)) {
|
|
32
|
+
found_paths[name] ??= full_path;
|
|
33
|
+
for (const [group_idx, aliases] of alias_groups.entries()) {
|
|
34
|
+
if (aliases.includes(name))
|
|
35
|
+
found_alias_groups.add(group_idx);
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return discover(h5_file);
|
|
42
|
-
};
|
|
43
|
-
const positions_data = find_dataset([`positions`, `coords`, `coordinates`])?.to_array();
|
|
44
|
-
const atomic_numbers_data = find_dataset([
|
|
45
|
-
`atomic_numbers`,
|
|
46
|
-
`numbers`,
|
|
47
|
-
`Z`,
|
|
48
|
-
`species`,
|
|
49
|
-
])?.to_array();
|
|
50
|
-
const cells_data = find_dataset([`cell`, `cells`, `lattice`])?.to_array();
|
|
51
|
-
const energies_data = find_dataset([`potential_energy`, `energy`])?.to_array();
|
|
52
|
-
if (!positions_data || !atomic_numbers_data) {
|
|
53
|
-
const missing_datasets = [];
|
|
54
|
-
if (!positions_data) {
|
|
55
|
-
missing_datasets.push(`positions (tried: positions, coords, coordinates)`);
|
|
37
|
+
if (found_alias_groups.size === alias_groups.length)
|
|
38
|
+
return;
|
|
56
39
|
}
|
|
57
|
-
if (
|
|
58
|
-
|
|
40
|
+
else if (is_hdf5_group(item)) {
|
|
41
|
+
discover(item, full_path);
|
|
42
|
+
if (found_alias_groups.size === alias_groups.length)
|
|
43
|
+
return;
|
|
59
44
|
}
|
|
60
|
-
const missing_str = missing_datasets.join(`, `);
|
|
61
|
-
const available_str = Array.from(h5_file.keys()).join(`, `);
|
|
62
|
-
throw new Error(`Missing required dataset(s) in HDF5 file: ${missing_str}. Available datasets: ${available_str}`);
|
|
63
45
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
46
|
+
};
|
|
47
|
+
discover(h5_file);
|
|
48
|
+
const first_path = (names) => names.map((name) => found_paths[name]).find(Boolean);
|
|
49
|
+
const find_dataset = (names) => {
|
|
50
|
+
const path = first_path(names);
|
|
51
|
+
return path ? read_dataset(h5_file, path) : null;
|
|
52
|
+
};
|
|
53
|
+
const positions_data = find_dataset(POSITION_ALIASES);
|
|
54
|
+
const atomic_numbers_data = find_dataset(ATOMIC_NUMBER_ALIASES);
|
|
55
|
+
const cells_data = find_dataset(CELL_ALIASES);
|
|
56
|
+
const energies_data = find_dataset(ENERGY_ALIASES);
|
|
57
|
+
if (!positions_data || !atomic_numbers_data) {
|
|
58
|
+
const missing_datasets = [];
|
|
59
|
+
if (!positions_data) {
|
|
60
|
+
missing_datasets.push(`positions (tried: ${POSITION_ALIASES.join(`, `)})`);
|
|
61
|
+
}
|
|
62
|
+
if (!atomic_numbers_data) {
|
|
63
|
+
missing_datasets.push(`atomic numbers (tried: ${ATOMIC_NUMBER_ALIASES.join(`, `)})`);
|
|
64
|
+
}
|
|
65
|
+
const missing_str = missing_datasets.join(`, `);
|
|
66
|
+
const available_str = [...h5_file.keys()].join(`, `);
|
|
67
|
+
throw new Error(`Missing required dataset(s) in HDF5 file: ${missing_str}. Available datasets: ${available_str}`);
|
|
68
|
+
}
|
|
69
|
+
const positions_are_frames = positions_data.length > 0 &&
|
|
70
|
+
positions_data.every((entry) => Array.isArray(entry) && entry.every((coord) => Array.isArray(coord)));
|
|
71
|
+
const positions = positions_are_frames ? positions_data : [positions_data];
|
|
72
|
+
const atomic_numbers_are_frames = atomic_numbers_data.length > 0 &&
|
|
73
|
+
atomic_numbers_data.every((entry) => Array.isArray(entry));
|
|
74
|
+
const atomic_numbers = atomic_numbers_are_frames
|
|
75
|
+
? atomic_numbers_data
|
|
76
|
+
: [atomic_numbers_data];
|
|
77
|
+
// A constant cell may be stored as a single 3x3 matrix; normalize to a
|
|
78
|
+
// per-frame array so cells[idx] always yields a full lattice (indexing a bare
|
|
79
|
+
// 3x3 with a frame index would hand a single row to validate_3x3_matrix)
|
|
80
|
+
const cells_are_frames = cells_data?.every((entry) => Array.isArray(entry) && entry.every((row) => Array.isArray(row)));
|
|
81
|
+
const cells = cells_data
|
|
82
|
+
? cells_are_frames
|
|
83
|
+
? cells_data
|
|
84
|
+
: [cells_data]
|
|
85
|
+
: null;
|
|
86
|
+
const frames = [];
|
|
87
|
+
let dropped_steps = 0;
|
|
88
|
+
for (const [idx, frame_pos] of positions.entries()) {
|
|
89
|
+
try {
|
|
73
90
|
const frame_atomic_numbers = atomic_numbers[idx] || atomic_numbers[0];
|
|
74
91
|
const frame_elements = convert_atomic_numbers(frame_atomic_numbers);
|
|
75
|
-
|
|
92
|
+
// constant-cell files reuse the single normalized cell for every frame
|
|
93
|
+
const cell = cells_are_frames ? cells?.[idx] : cells?.[0];
|
|
76
94
|
const lattice_mat = cell ? transpose_3x3_matrix(validate_3x3_matrix(cell)) : undefined;
|
|
77
95
|
const energy_entry = energies_data?.[idx];
|
|
78
96
|
const energy = Array.isArray(energy_entry) ? energy_entry[0] : energy_entry;
|
|
@@ -83,45 +101,37 @@ export async function parse_torch_sim_hdf5(buffer, filename) {
|
|
|
83
101
|
metadata.volume = calc_lattice_params(lattice_mat).volume;
|
|
84
102
|
}
|
|
85
103
|
const pbc = lattice_mat ? [true, true, true] : [false, false, false];
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
const first_frame_elements = frames[0]?.structure.sites.map((site) => site.species[0].element) ?? [];
|
|
89
|
-
return {
|
|
90
|
-
frames,
|
|
91
|
-
metadata: {
|
|
92
|
-
source_format: `hdf5_trajectory`,
|
|
93
|
-
frame_count: frames.length,
|
|
94
|
-
num_atoms: first_frame_elements.length,
|
|
95
|
-
periodic_boundary_conditions: cells_data ? [true, true, true] : [false, false, false],
|
|
96
|
-
element_counts: first_frame_elements.reduce((counts, element) => {
|
|
97
|
-
counts[element] = (counts[element] || 0) + 1;
|
|
98
|
-
return counts;
|
|
99
|
-
}, {}),
|
|
100
|
-
discovered_datasets: {
|
|
101
|
-
positions: found_paths.positions ||
|
|
102
|
-
found_paths.coords ||
|
|
103
|
-
found_paths.coordinates ||
|
|
104
|
-
`unknown`,
|
|
105
|
-
atomic_numbers: found_paths.atomic_numbers ||
|
|
106
|
-
found_paths.numbers ||
|
|
107
|
-
found_paths.Z ||
|
|
108
|
-
found_paths.species ||
|
|
109
|
-
`unknown`,
|
|
110
|
-
cells: found_paths.cell || found_paths.cells || found_paths.lattice,
|
|
111
|
-
energies: found_paths.potential_energy || found_paths.energy,
|
|
112
|
-
},
|
|
113
|
-
total_groups_found,
|
|
114
|
-
has_cell_info: Boolean(cells_data),
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
finally {
|
|
119
|
-
h5_file?.close();
|
|
120
|
-
try {
|
|
121
|
-
FS.unlink(temp_filename);
|
|
104
|
+
frames.push(create_trajectory_frame(frame_pos, frame_elements, lattice_mat, pbc, idx, metadata));
|
|
122
105
|
}
|
|
123
|
-
catch {
|
|
124
|
-
|
|
106
|
+
catch (err) {
|
|
107
|
+
// Same torn-tail resiliency as the vaspout parser: interrupted writers
|
|
108
|
+
// zero-fill trailing chunks (atomic number 0, degenerate cells), which
|
|
109
|
+
// fails validation — keep the frames parsed so far and report the rest
|
|
110
|
+
// as dropped. A file whose very first frame is unparsable still throws.
|
|
111
|
+
if (frames.length === 0)
|
|
112
|
+
throw err;
|
|
113
|
+
dropped_steps = positions.length - idx;
|
|
114
|
+
break;
|
|
125
115
|
}
|
|
126
116
|
}
|
|
117
|
+
const first_frame_elements = frames[0]?.structure.sites.map((site) => site.species[0].element) ?? [];
|
|
118
|
+
return {
|
|
119
|
+
frames,
|
|
120
|
+
metadata: {
|
|
121
|
+
source_format: `hdf5_trajectory`,
|
|
122
|
+
frame_count: frames.length,
|
|
123
|
+
num_atoms: first_frame_elements.length,
|
|
124
|
+
periodic_boundary_conditions: cells_data ? [true, true, true] : [false, false, false],
|
|
125
|
+
element_counts: count_elements(first_frame_elements),
|
|
126
|
+
discovered_datasets: {
|
|
127
|
+
positions: first_path(POSITION_ALIASES) ?? `unknown`,
|
|
128
|
+
atomic_numbers: first_path(ATOMIC_NUMBER_ALIASES) ?? `unknown`,
|
|
129
|
+
cells: first_path(CELL_ALIASES),
|
|
130
|
+
energies: first_path(ENERGY_ALIASES),
|
|
131
|
+
},
|
|
132
|
+
total_groups_found,
|
|
133
|
+
has_cell_info: Boolean(cells_data),
|
|
134
|
+
...(dropped_steps > 0 ? { dropped_steps } : {}),
|
|
135
|
+
},
|
|
136
|
+
};
|
|
127
137
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { is_trajectory_file } from '../format-detect';
|
|
2
|
-
import { TrajFrameReader } from '../frame-reader';
|
|
3
1
|
import type { FrameLoader, ParseProgress, TrajectoryType } from '../index';
|
|
4
2
|
import type { AtomTypeMapping, LoadingOptions } from '../types';
|
|
5
3
|
export { LARGE_FILE_THRESHOLD, MAX_BIN_FILE_SIZE, MAX_TEXT_FILE_SIZE, } from '../constants';
|
|
6
4
|
export type { AtomTypeMapping, LoadingOptions } from '../types';
|
|
7
|
-
export { is_trajectory_file
|
|
5
|
+
export { is_trajectory_file } from '../format-detect';
|
|
6
|
+
export { TrajFrameReader } from '../frame-reader';
|
|
8
7
|
export declare function parse_trajectory_data(data: unknown, filename?: string, atom_type_mapping?: AtomTypeMapping): Promise<TrajectoryType>;
|
|
9
8
|
export declare function get_unsupported_format_message(filename: string, content: string): string | null;
|
|
10
9
|
export declare function parse_trajectory_async(data: ArrayBuffer | string, filename: string, on_progress?: (progress: ParseProgress) => void, options?: LoadingOptions): Promise<TrajectoryType>;
|