matterviz 0.4.0 → 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 +132 -219
- package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +80 -77
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +3 -3
- package/dist/chempot-diagram/compute.js +3 -1
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +21 -22
- 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 +96 -98
- package/dist/composition/PieChart.svelte +60 -46
- package/dist/composition/chem-sys.js +3 -2
- package/dist/composition/format.js +4 -3
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -3
- package/dist/composition/parse.js +27 -28
- package/dist/constants.js +11 -9
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +20 -25
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +176 -256
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +269 -804
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +236 -755
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +128 -49
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +210 -351
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- 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/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
- package/dist/convex-hull/helpers.d.ts +47 -17
- package/dist/convex-hull/helpers.js +186 -101
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +9 -7
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +109 -937
- package/dist/convex-hull/types.d.ts +12 -4
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +41 -43
- 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 +6 -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/ElementTile.svelte.d.ts +1 -1
- 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 -0
- package/dist/element/index.js +3 -0
- package/dist/feedback/DragOverlay.svelte +5 -3
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
- package/dist/feedback/StatusMessage.svelte +20 -7
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +78 -165
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +14 -13
- package/dist/fermi-surface/export.js +4 -15
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +84 -97
- package/dist/fermi-surface/types.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +8 -2
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +170 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -36
- package/dist/io/export.d.ts +9 -1
- package/dist/io/export.js +37 -29
- package/dist/io/fetch.d.ts +2 -4
- package/dist/io/fetch.js +0 -11
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +13 -0
- package/dist/io/index.d.ts +1 -0
- package/dist/io/index.js +3 -0
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/types.d.ts +13 -0
- 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 +50 -48
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +44 -14
- package/dist/layout/FullscreenButton.svelte +34 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +12 -12
- 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 +115 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +36 -0
- package/dist/layout/index.d.ts +4 -0
- package/dist/layout/index.js +4 -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 +9 -3
- package/dist/math.js +37 -21
- 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 +11 -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 +115 -146
- 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 +73 -96
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- 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/colors.js +1 -1
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.d.ts +2 -1
- 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 +494 -692
- package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
- package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +361 -439
- package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
- package/dist/plot/box/Violin.svelte.d.ts +2 -1
- package/dist/plot/box/box-plot.d.ts +3 -2
- package/dist/plot/box/box-plot.js +6 -3
- package/dist/plot/box/kde.d.ts +2 -1
- package/dist/plot/box/kde.js +4 -4
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +5 -2
- 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 +106 -111
- package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
- 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 +21 -11
- package/dist/plot/core/components/Line.svelte.d.ts +5 -2
- package/dist/plot/core/components/PlotAxis.svelte +42 -18
- package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
- 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 +56 -59
- package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
- package/dist/plot/core/components/ReferencePlane.svelte +9 -10
- package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
- 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 +29 -476
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +7 -4
- package/dist/plot/core/fill-utils.js +34 -9
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.d.ts +5 -1
- package/dist/plot/core/interactions.js +14 -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/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/core/reference-line.d.ts +10 -10
- package/dist/plot/core/reference-line.js +7 -7
- package/dist/plot/core/scales.d.ts +40 -25
- package/dist/plot/core/scales.js +49 -21
- package/dist/plot/core/svg.d.ts +2 -1
- 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 +47 -331
- 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.d.ts +1 -1
- package/dist/plot/core/utils/label-placement.js +5 -5
- package/dist/plot/core/utils.d.ts +2 -1
- package/dist/plot/histogram/Histogram.svelte +373 -631
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
- 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 +79 -73
- package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/sankey/sankey.js +3 -1
- package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +623 -821
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
- 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 +6 -12
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/index.d.ts +1 -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 +40 -60
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
- package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
- package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
- package/dist/plot/sunburst/Sunburst.svelte +256 -338
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
- 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 +14 -4
- 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 +14 -3
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +22 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +33 -11
- package/dist/settings.js +136 -51
- package/dist/spectral/Bands.svelte +231 -237
- package/dist/spectral/Bands.svelte.d.ts +3 -2
- package/dist/spectral/BandsAndDos.svelte +29 -29
- package/dist/spectral/BrillouinBandsDos.svelte +21 -29
- package/dist/spectral/Dos.svelte +75 -77
- package/dist/spectral/Dos.svelte.d.ts +2 -1
- package/dist/spectral/helpers.d.ts +9 -9
- package/dist/spectral/helpers.js +66 -70
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +5 -24
- package/dist/structure/Arrow.svelte +6 -21
- 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 +16 -3
- package/dist/structure/CellSelect.svelte +22 -29
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- 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 +725 -735
- package/dist/structure/Structure.svelte.d.ts +8 -16
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +298 -325
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +62 -168
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +77 -69
- package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
- package/dist/structure/StructureScene.svelte +758 -600
- package/dist/structure/StructureScene.svelte.d.ts +24 -20
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +18 -0
- package/dist/structure/atom-label-placement.js +115 -0
- package/dist/structure/atom-properties.d.ts +3 -1
- package/dist/structure/atom-properties.js +115 -54
- package/dist/structure/bond-order-perception.js +2 -4
- package/dist/structure/bonding.d.ts +12 -2
- package/dist/structure/bonding.js +172 -73
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +25 -4
- package/dist/structure/export.js +103 -153
- 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 +18 -1
- package/dist/structure/index.js +15 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +5 -3
- package/dist/structure/parse.js +551 -567
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +5 -3
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +204 -51
- package/dist/structure/polyhedra.d.ts +40 -0
- package/dist/structure/polyhedra.js +587 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +10 -15
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +350 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +142 -49
- package/dist/symmetry/WyckoffTable.svelte +58 -16
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +8 -14
- package/dist/symmetry/index.d.ts +15 -4
- package/dist/symmetry/index.js +308 -81
- package/dist/symmetry/spacegroups.d.ts +5 -1
- package/dist/symmetry/spacegroups.js +18 -3
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +1104 -378
- 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 +556 -352
- package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +73 -71
- package/dist/trajectory/format-detect.d.ts +0 -1
- package/dist/trajectory/format-detect.js +13 -17
- package/dist/trajectory/frame-reader.d.ts +2 -1
- package/dist/trajectory/frame-reader.js +74 -136
- package/dist/trajectory/helpers.d.ts +12 -2
- package/dist/trajectory/helpers.js +68 -37
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -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 +3 -4
- package/dist/trajectory/parse/index.js +68 -119
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +14 -16
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +13 -9
- 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.d.ts +9 -21
- package/dist/trajectory/parse/xyz.js +38 -39
- package/dist/trajectory/plotting.d.ts +8 -10
- package/dist/trajectory/plotting.js +102 -127
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +8 -1
- package/dist/xrd/XrdPlot.svelte +56 -85
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +8 -15
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +77 -36
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/core/hover-lock.svelte.js +0 -45
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
- package/dist/structure/label-placement.d.ts +0 -14
- package/dist/structure/label-placement.js +0 -72
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as math from '../../math';
|
|
2
|
+
import { calc_force_stats, create_trajectory_frame, validate_3x3_matrix, } from '../helpers';
|
|
3
|
+
import { is_plain_object } from '../../utils';
|
|
4
|
+
import { traj_warn } from './diagnostics';
|
|
5
|
+
// Non-empty array of pymatgen Species-like objects with non-empty string element
|
|
6
|
+
// symbols (predicate so callers get narrowing; rejects e.g. { element: null })
|
|
7
|
+
const is_species_array = (val) => Array.isArray(val) &&
|
|
8
|
+
val.length > 0 &&
|
|
9
|
+
val.every((sp) => sp != null &&
|
|
10
|
+
typeof sp === `object` &&
|
|
11
|
+
`element` in sp &&
|
|
12
|
+
typeof sp.element === `string` &&
|
|
13
|
+
sp.element.trim().length > 0);
|
|
14
|
+
// Parse an already-JSON-parsed pymatgen Trajectory object (detected via @class === 'Trajectory' with species/coords/lattice present)
|
|
15
|
+
export function parse_pymatgen_trajectory(obj, filename) {
|
|
16
|
+
// Validate shape upfront so malformed input fails with a clear message
|
|
17
|
+
// (callers gate only on truthiness, not structure) rather than a cryptic `.map` error
|
|
18
|
+
if (!is_species_array(obj.species)) {
|
|
19
|
+
throw new TypeError(`Invalid pymatgen Trajectory: 'species' must be a non-empty array of { element } objects`);
|
|
20
|
+
}
|
|
21
|
+
if (!Array.isArray(obj.coords)) {
|
|
22
|
+
throw new TypeError(`Invalid pymatgen Trajectory: 'coords' must be an array of frames`);
|
|
23
|
+
}
|
|
24
|
+
const frame_elements = obj.species.map((specie) => specie.element);
|
|
25
|
+
const coords = obj.coords;
|
|
26
|
+
const matrix = validate_3x3_matrix(obj.lattice);
|
|
27
|
+
const frame_properties = obj.frame_properties || [];
|
|
28
|
+
const frac_to_cart = math.create_frac_to_cart(matrix);
|
|
29
|
+
const frames = coords.map((frame_coords, idx) => {
|
|
30
|
+
const positions = frame_coords.map((abc) => frac_to_cart(abc));
|
|
31
|
+
// Process frame properties to extract numpy arrays
|
|
32
|
+
const raw_properties = frame_properties[idx] || {};
|
|
33
|
+
const processed_properties = {};
|
|
34
|
+
Object.entries(raw_properties).forEach(([key, value]) => {
|
|
35
|
+
if (is_plain_object(value) && value[`@class`] === `array`) {
|
|
36
|
+
processed_properties[key] = value.data;
|
|
37
|
+
if (key === `forces` && Array.isArray(value.data)) {
|
|
38
|
+
// Object.assign ignores the null calc_force_stats returns for empty forces
|
|
39
|
+
Object.assign(processed_properties, calc_force_stats(value.data));
|
|
40
|
+
}
|
|
41
|
+
if (key === `stress` && Array.isArray(value.data)) {
|
|
42
|
+
const stress_tensor = value.data;
|
|
43
|
+
if (!math.is_square_matrix(stress_tensor, 3)) {
|
|
44
|
+
traj_warn(`Invalid stress tensor structure in frame ${idx}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Calculate stress components (diagonal elements represent normal stresses)
|
|
48
|
+
const normal_stresses = [
|
|
49
|
+
stress_tensor[0][0],
|
|
50
|
+
stress_tensor[1][1],
|
|
51
|
+
stress_tensor[2][2],
|
|
52
|
+
];
|
|
53
|
+
processed_properties.stress_max = Math.max(...normal_stresses.map(Math.abs));
|
|
54
|
+
// Calculate hydrostatic pressure (negative of mean normal stress)
|
|
55
|
+
processed_properties.pressure =
|
|
56
|
+
-(normal_stresses[0] + normal_stresses[1] + normal_stresses[2]) / 3;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
processed_properties[key] = value;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return create_trajectory_frame(positions, frame_elements, matrix, [true, true, true], idx, processed_properties);
|
|
65
|
+
});
|
|
66
|
+
const metadata = {
|
|
67
|
+
filename,
|
|
68
|
+
source_format: `pymatgen_trajectory`,
|
|
69
|
+
frame_count: frames.length,
|
|
70
|
+
species_list: [...new Set(frame_elements)],
|
|
71
|
+
periodic_boundary_conditions: [true, true, true],
|
|
72
|
+
};
|
|
73
|
+
return { frames, metadata };
|
|
74
|
+
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as math from '../../math';
|
|
2
|
-
import {
|
|
2
|
+
import { is_elem_symbol } from '../../element/helpers';
|
|
3
|
+
import { create_trajectory_frame, validate_3x3_matrix } from '../helpers';
|
|
4
|
+
import { parse_leading_num } from '../../utils';
|
|
3
5
|
// Parse the 7-line XDATCAR header at lines[start]: title, scale factor, 3 lattice rows
|
|
4
6
|
// (multiplied by scale), element names, element counts
|
|
5
7
|
function parse_xdatcar_header(lines, start) {
|
|
6
|
-
const scale =
|
|
8
|
+
const scale = parse_leading_num(lines[start + 1]);
|
|
7
9
|
const rows = lines.slice(start + 2, start + 5).map((line) => line
|
|
8
10
|
.trim()
|
|
9
11
|
.split(/\s+/)
|
|
10
|
-
.map((val) =>
|
|
12
|
+
.map((val) => Number(val) * scale));
|
|
11
13
|
const names = lines[start + 5].trim().split(/\s+/);
|
|
12
14
|
const counts = lines[start + 6].trim().split(/\s+/).map(Number);
|
|
13
15
|
return { scale, rows, names, counts };
|
|
@@ -27,10 +29,12 @@ export function parse_vasp_xdatcar(content, filename) {
|
|
|
27
29
|
if (element_counts.some((count) => !Number.isFinite(count) || !Number.isInteger(count) || count <= 0)) {
|
|
28
30
|
throw new Error(`XDATCAR contains invalid element counts: expected finite positive integers`);
|
|
29
31
|
}
|
|
30
|
-
const bad_element = element_names.find((name) => !
|
|
32
|
+
const bad_element = element_names.find((name) => !is_elem_symbol(name));
|
|
31
33
|
if (bad_element)
|
|
32
34
|
throw new Error(`Invalid element symbol in XDATCAR: ${bad_element}`);
|
|
33
|
-
|
|
35
|
+
// "Na Cl" + [2, 2] -> [Na, Na, Cl, Cl]
|
|
36
|
+
const expand_element_counts = (names, counts) => names.flatMap((name, idx) => Array(counts[idx]).fill(name));
|
|
37
|
+
let elements = expand_element_counts(element_names, element_counts);
|
|
34
38
|
const frames = [];
|
|
35
39
|
let line_idx = 7;
|
|
36
40
|
let frac_to_cart = math.create_frac_to_cart(lattice_matrix);
|
|
@@ -46,16 +50,16 @@ export function parse_vasp_xdatcar(content, filename) {
|
|
|
46
50
|
lattice_matrix = validate_3x3_matrix(hdr.rows);
|
|
47
51
|
frac_to_cart = math.create_frac_to_cart(lattice_matrix);
|
|
48
52
|
if (hdr.names.length === hdr.counts.length &&
|
|
49
|
-
hdr.names.every(
|
|
53
|
+
hdr.names.every(is_elem_symbol) &&
|
|
50
54
|
hdr.counts.every((count) => Number.isInteger(count) && count > 0)) {
|
|
51
|
-
elements = hdr.names
|
|
55
|
+
elements = expand_element_counts(hdr.names, hdr.counts);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
}
|
|
55
59
|
const config_line = lines[config_idx];
|
|
56
60
|
line_idx = config_idx + 1;
|
|
57
|
-
const step_match = /configuration=\s*(
|
|
58
|
-
const step = step_match ?
|
|
61
|
+
const step_match = /configuration=\s*(?<step>\d+)/.exec(config_line);
|
|
62
|
+
const step = step_match ? Math.trunc(Number(step_match[1])) : frames.length + 1;
|
|
59
63
|
const positions = [];
|
|
60
64
|
for (let idx = 0; idx < elements.length && line_idx < lines.length; idx++) {
|
|
61
65
|
const coords = lines[line_idx].trim().split(/\s+/).slice(0, 3).map(Number);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ElectronicBandStructure, ElectronicDos } from '../../spectral';
|
|
2
|
+
import type * as h5wasm from 'h5wasm';
|
|
3
|
+
export interface VaspoutElectronicData {
|
|
4
|
+
dos: ElectronicDos | null;
|
|
5
|
+
bands: ElectronicBandStructure | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const read_vaspout_dos: (h5_file: h5wasm.File) => ElectronicDos | null;
|
|
8
|
+
export declare const line_mode_labels: (labels: string[] | null, per_segment_dataset: number | null, n_kpoints: number) => {
|
|
9
|
+
labels: (string | null)[];
|
|
10
|
+
per_segment: number;
|
|
11
|
+
} | null;
|
|
12
|
+
export declare const read_vaspout_bands: (h5_file: h5wasm.File, dos?: ElectronicDos | null) => ElectronicBandStructure | null;
|
|
13
|
+
export declare const read_vaspout_electronic: (h5_file: h5wasm.File) => VaspoutElectronicData | null;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// Electronic-structure results (DOS + band eigenvalues) from VASP 6.x vaspout.h5.
|
|
2
|
+
//
|
|
3
|
+
// Reads results/electron_dos* into the ElectronicDos shape and
|
|
4
|
+
// results/electron_eigenvalues* (incl. the _kpoints_opt variants written for
|
|
5
|
+
// band paths from KPOINTS_OPT, e.g. by phelel) into the matterviz
|
|
6
|
+
// ElectronicBandStructure shape consumed by the spectral components.
|
|
7
|
+
//
|
|
8
|
+
// Schema reference: ferrox src/io/vasp/hdf5/mod.rs path constants (which follow
|
|
9
|
+
// py4vasp's VASP 6.x schema definitions).
|
|
10
|
+
import { create_frac_to_cart, euclidean_dist, matrix_inverse_3x3, transpose_3x3_matrix, } from '../../math';
|
|
11
|
+
import { pretty_sym_point } from '../../spectral/helpers';
|
|
12
|
+
import { validate_3x3_matrix } from '../helpers';
|
|
13
|
+
import { read_dataset, scale_matrix, to_scalar_number, to_string_array } from './h5-utils';
|
|
14
|
+
const DOS_GROUPS = [`results/electron_dos`, `results/electron_dos_kpoints_opt`];
|
|
15
|
+
const DOS_ENERGY_NAMES = [`energies`, `energy`];
|
|
16
|
+
const DOS_TOTAL_NAMES = [`dos`, `total`];
|
|
17
|
+
const BANDS_GROUPS = [
|
|
18
|
+
`results/electron_eigenvalues`,
|
|
19
|
+
`results/electron_eigenvalues_kpoints_opt`,
|
|
20
|
+
];
|
|
21
|
+
const EIGENVALUE_NAMES = [`eigenvalues`, `eigenvalue`];
|
|
22
|
+
const KPOINT_COORD_NAMES = [`kpoints`, `kpoint_coords`];
|
|
23
|
+
const KPOINT_COORD_FALLBACKS = [`results/kpoints/coordinates`];
|
|
24
|
+
const KPOINT_LABEL_PATHS = [
|
|
25
|
+
`results/kpoints/labels`,
|
|
26
|
+
`input/kpoints_opt/labels_kpoints`,
|
|
27
|
+
`input/kpoints/labels_kpoints`,
|
|
28
|
+
];
|
|
29
|
+
const KPOINTS_PER_SEGMENT_PATHS = [
|
|
30
|
+
`input/kpoints_opt/number_kpoints`,
|
|
31
|
+
`input/kpoints/number_kpoints`,
|
|
32
|
+
];
|
|
33
|
+
const read_first_dataset = (h5_file, paths) => {
|
|
34
|
+
for (const path of paths) {
|
|
35
|
+
const data = read_dataset(h5_file, path);
|
|
36
|
+
if (data !== null)
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
const is_number_array = (data) => Array.isArray(data) && data.every((val) => typeof val === `number`);
|
|
42
|
+
export const read_vaspout_dos = (h5_file) => {
|
|
43
|
+
for (const group of DOS_GROUPS) {
|
|
44
|
+
const energies = read_first_dataset(h5_file, DOS_ENERGY_NAMES.map((name) => `${group}/${name}`));
|
|
45
|
+
const total = read_first_dataset(h5_file, DOS_TOTAL_NAMES.map((name) => `${group}/${name}`));
|
|
46
|
+
if (!is_number_array(energies) || !Array.isArray(total))
|
|
47
|
+
continue;
|
|
48
|
+
// Total DOS is (n_spin, n_energies) in real files but tolerate a flat array
|
|
49
|
+
const spin_channels = is_number_array(total) ? [total] : total;
|
|
50
|
+
const densities = spin_channels[0];
|
|
51
|
+
if (!is_number_array(densities) || densities.length !== energies.length)
|
|
52
|
+
continue;
|
|
53
|
+
const spin_down = spin_channels[1];
|
|
54
|
+
const spin_polarized = is_number_array(spin_down) && spin_down.length === energies.length;
|
|
55
|
+
const efermi = to_scalar_number(read_dataset(h5_file, `${group}/efermi`));
|
|
56
|
+
return {
|
|
57
|
+
type: `electronic`,
|
|
58
|
+
energies,
|
|
59
|
+
densities,
|
|
60
|
+
...(spin_polarized ? { spin_down_densities: spin_down, spin_polarized } : {}),
|
|
61
|
+
...(efermi !== null ? { efermi } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
};
|
|
66
|
+
// Real (row-vector) lattice for k-path distances: prefer the relaxed structure's
|
|
67
|
+
// lattice, fall back to the POSCAR input one (bands-only files keep only the latter)
|
|
68
|
+
const read_lattice = (h5_file) => {
|
|
69
|
+
for (const [lattice_path, scale_path] of [
|
|
70
|
+
[`results/positions/lattice_vectors`, `results/positions/scale`],
|
|
71
|
+
[`input/poscar/lattice_vectors`, `input/poscar/scale`],
|
|
72
|
+
]) {
|
|
73
|
+
const lattice_data = read_dataset(h5_file, lattice_path);
|
|
74
|
+
if (!lattice_data)
|
|
75
|
+
continue;
|
|
76
|
+
try {
|
|
77
|
+
const scale = to_scalar_number(read_dataset(h5_file, scale_path)) ?? 1;
|
|
78
|
+
return scale_matrix(validate_3x3_matrix(lattice_data), scale);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
// B = 2π (A⁻¹)ᵀ for row-vector real lattice A; falls back to 2π·identity so
|
|
87
|
+
// bands-only files without any (invertible) lattice still get monotonic path
|
|
88
|
+
// distances.
|
|
89
|
+
const reciprocal_lattice = (lattice) => {
|
|
90
|
+
let recip = [
|
|
91
|
+
[1, 0, 0],
|
|
92
|
+
[0, 1, 0],
|
|
93
|
+
[0, 0, 1],
|
|
94
|
+
];
|
|
95
|
+
try {
|
|
96
|
+
if (lattice)
|
|
97
|
+
recip = transpose_3x3_matrix(matrix_inverse_3x3(lattice));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
/* singular lattice: keep identity */
|
|
101
|
+
}
|
|
102
|
+
return recip.map((row) => row.map((val) => val * 2 * Math.PI));
|
|
103
|
+
};
|
|
104
|
+
// VASP line-mode label layout: 2 labels per path segment of `per_segment` points
|
|
105
|
+
// (e.g. 12 labels + 51 points/segment = 306 k-points). Returns per-kpoint labels
|
|
106
|
+
// (null between endpoints) or null when the layout doesn't match. When the
|
|
107
|
+
// input/kpoints*/number_kpoints dataset is absent (not all writers emit it),
|
|
108
|
+
// the segment length is inferred from the label/k-point counts instead.
|
|
109
|
+
export const line_mode_labels = (labels, per_segment_dataset, n_kpoints) => {
|
|
110
|
+
if (!labels || labels.length < 2 || labels.length % 2 !== 0)
|
|
111
|
+
return null;
|
|
112
|
+
const n_segments = labels.length / 2;
|
|
113
|
+
const per_segment = per_segment_dataset ?? n_kpoints / n_segments;
|
|
114
|
+
if (!Number.isInteger(per_segment) || per_segment < 2)
|
|
115
|
+
return null;
|
|
116
|
+
if (n_segments * per_segment !== n_kpoints)
|
|
117
|
+
return null;
|
|
118
|
+
const per_kpoint = Array.from({ length: n_kpoints }, () => null);
|
|
119
|
+
for (let seg = 0; seg < n_segments; seg++) {
|
|
120
|
+
per_kpoint[seg * per_segment] = pretty_sym_point(labels[2 * seg]);
|
|
121
|
+
per_kpoint[seg * per_segment + per_segment - 1] = pretty_sym_point(labels[2 * seg + 1]);
|
|
122
|
+
}
|
|
123
|
+
return { labels: per_kpoint, per_segment };
|
|
124
|
+
};
|
|
125
|
+
export const read_vaspout_bands = (h5_file, dos = read_vaspout_dos(h5_file)) => {
|
|
126
|
+
for (const group of BANDS_GROUPS) {
|
|
127
|
+
const eigenvalues = read_first_dataset(h5_file, EIGENVALUE_NAMES.map((name) => `${group}/${name}`));
|
|
128
|
+
const kpoint_data = read_first_dataset(h5_file, [
|
|
129
|
+
...KPOINT_COORD_NAMES.map((name) => `${group}/${name}`),
|
|
130
|
+
...KPOINT_COORD_FALLBACKS,
|
|
131
|
+
]);
|
|
132
|
+
if (!Array.isArray(eigenvalues) || !Array.isArray(kpoint_data))
|
|
133
|
+
continue;
|
|
134
|
+
// eigenvalues shape: (n_spin, n_kpoints, n_bands)
|
|
135
|
+
const n_kpoints = kpoint_data.length;
|
|
136
|
+
const spin_up = eigenvalues[0];
|
|
137
|
+
if (!Array.isArray(spin_up) || spin_up.length !== n_kpoints || n_kpoints === 0)
|
|
138
|
+
continue;
|
|
139
|
+
const n_bands = spin_up[0]?.length ?? 0;
|
|
140
|
+
if (n_bands === 0)
|
|
141
|
+
continue;
|
|
142
|
+
// [n_kpoints][n_bands] -> [n_bands][n_kpoints] as the spectral components expect
|
|
143
|
+
const transpose = (spin_eigs) => Array.from({ length: n_bands }, (_, band_idx) => spin_eigs.map((kpt_eigs) => kpt_eigs[band_idx]));
|
|
144
|
+
const bands = transpose(spin_up);
|
|
145
|
+
const spin_down = eigenvalues[1];
|
|
146
|
+
const spin_down_bands = Array.isArray(spin_down) && spin_down.length === n_kpoints
|
|
147
|
+
? transpose(spin_down)
|
|
148
|
+
: undefined;
|
|
149
|
+
const recip = reciprocal_lattice(read_lattice(h5_file));
|
|
150
|
+
const line_mode = line_mode_labels(to_string_array(read_first_dataset(h5_file, [`${group}/kpoints_labels`, ...KPOINT_LABEL_PATHS])), to_scalar_number(read_first_dataset(h5_file, KPOINTS_PER_SEGMENT_PATHS)), n_kpoints);
|
|
151
|
+
const labels = line_mode?.labels ?? null;
|
|
152
|
+
const distance = [];
|
|
153
|
+
const qpoints = [];
|
|
154
|
+
let path_length = 0;
|
|
155
|
+
let prev_cart = null;
|
|
156
|
+
const labels_dict = {};
|
|
157
|
+
const frac_to_cart = create_frac_to_cart(recip);
|
|
158
|
+
for (const [kpt_idx, kpt] of kpoint_data.entries()) {
|
|
159
|
+
const frac = [kpt[0] ?? 0, kpt[1] ?? 0, kpt[2] ?? 0];
|
|
160
|
+
const cart = frac_to_cart(frac);
|
|
161
|
+
if (prev_cart)
|
|
162
|
+
path_length += euclidean_dist(cart, prev_cart);
|
|
163
|
+
prev_cart = cart;
|
|
164
|
+
distance.push(path_length);
|
|
165
|
+
const label = labels?.[kpt_idx] ?? null;
|
|
166
|
+
qpoints.push({ label, frac_coords: frac });
|
|
167
|
+
if (label)
|
|
168
|
+
labels_dict[label] = frac;
|
|
169
|
+
}
|
|
170
|
+
// One branch per labeled line-mode segment, else a single whole-path branch
|
|
171
|
+
const per_segment = line_mode?.per_segment ?? 0;
|
|
172
|
+
const branches = [];
|
|
173
|
+
if (labels && Number.isInteger(per_segment) && per_segment >= 2) {
|
|
174
|
+
for (let start = 0; start < n_kpoints; start += per_segment) {
|
|
175
|
+
const end = start + per_segment - 1;
|
|
176
|
+
branches.push({
|
|
177
|
+
start_index: start,
|
|
178
|
+
end_index: end,
|
|
179
|
+
name: `${qpoints[start]?.label ?? `?`}-${qpoints[end]?.label ?? `?`}`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
branches.push({ start_index: 0, end_index: n_kpoints - 1, name: `path` });
|
|
185
|
+
const efermi = dos?.efermi;
|
|
186
|
+
return {
|
|
187
|
+
qpoints,
|
|
188
|
+
branches,
|
|
189
|
+
distance,
|
|
190
|
+
bands,
|
|
191
|
+
...(spin_down_bands ? { spin_down_bands } : {}),
|
|
192
|
+
nb_bands: n_bands,
|
|
193
|
+
labels_dict,
|
|
194
|
+
recip_lattice: { matrix: recip },
|
|
195
|
+
is_spin_polarized: spin_down_bands !== undefined,
|
|
196
|
+
...(efermi !== undefined ? { efermi } : {}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
};
|
|
201
|
+
// Bundle DOS + bands; null when the file carries neither (so callers can keep
|
|
202
|
+
// their "no structure data" error for files with nothing to show).
|
|
203
|
+
export const read_vaspout_electronic = (h5_file) => {
|
|
204
|
+
const dos = read_vaspout_dos(h5_file);
|
|
205
|
+
const bands = read_vaspout_bands(h5_file, dos);
|
|
206
|
+
return dos || bands ? { dos, bands } : null;
|
|
207
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type * as h5wasm from 'h5wasm';
|
|
2
|
+
import type { TrajectoryType } from '../index';
|
|
3
|
+
export declare const is_vaspout_h5_file: (h5_file: h5wasm.File) => boolean;
|
|
4
|
+
export declare function parse_vaspout_h5_file(h5_file: h5wasm.File): TrajectoryType;
|
|
5
|
+
export declare function parse_vaspout_h5(buffer: ArrayBuffer, filename?: string): Promise<TrajectoryType>;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// Parser for VASP 6.x HDF5 output (vaspout.h5, written with LH5=.TRUE.).
|
|
2
|
+
// Reads the ionic-relaxation trajectory from intermediate/ion_dynamics (with
|
|
3
|
+
// per-frame energy/forces so convergence plots come for free) and falls back
|
|
4
|
+
// to the final structure in results/positions for static (NSW=0) runs, which
|
|
5
|
+
// render as single-frame trajectories (structure only, plots hidden).
|
|
6
|
+
//
|
|
7
|
+
// Tolerates files from incomplete/running calculations: datasets flushed
|
|
8
|
+
// mid-write may disagree on step counts (e.g. 5 energies but 4 position
|
|
9
|
+
// frames), so frame count is the minimum over required datasets and per-step
|
|
10
|
+
// reads never index past any dataset's end.
|
|
11
|
+
//
|
|
12
|
+
// Electronic results (results/electron_dos, results/electron_eigenvalues*)
|
|
13
|
+
// are read by ./vaspout-electronic.ts and attached as metadata.electronic;
|
|
14
|
+
// vaspwave.h5 charge density is handled by isosurface/parse-vaspwave.ts.
|
|
15
|
+
//
|
|
16
|
+
// Schema reference: ferrox src/io/vasp/hdf5/mod.rs (which follows py4vasp's
|
|
17
|
+
// VASP 6.x schema definitions).
|
|
18
|
+
import { calc_lattice_params, create_frac_to_cart } from '../../math';
|
|
19
|
+
import { count_elements, create_trajectory_frame, validate_3x3_matrix, } from '../helpers';
|
|
20
|
+
import { expand_ion_types, is_hdf5_group, read_dataset, scale_matrix, to_number_array, to_scalar_number, to_string_array, with_h5_file, } from './h5-utils';
|
|
21
|
+
import { read_vaspout_dos, read_vaspout_electronic } from './vaspout-electronic';
|
|
22
|
+
const FINAL_ION_TYPES = `results/positions/ion_types`;
|
|
23
|
+
const FINAL_ION_COUNTS = `results/positions/number_ion_types`;
|
|
24
|
+
const FINAL_LATTICE = `results/positions/lattice_vectors`;
|
|
25
|
+
const FINAL_POSITIONS = `results/positions/position_ions`;
|
|
26
|
+
const FINAL_SCALE = `results/positions/scale`;
|
|
27
|
+
const TRAJ_SCALE = `intermediate/ion_dynamics/scale`;
|
|
28
|
+
const TRAJ_LATTICE = `intermediate/ion_dynamics/lattice_vectors`;
|
|
29
|
+
const TRAJ_POSITIONS = `intermediate/ion_dynamics/position_ions`;
|
|
30
|
+
const TRAJ_FORCES = `intermediate/ion_dynamics/forces`;
|
|
31
|
+
const ENERGY_VALUES = `intermediate/ion_dynamics/energies`;
|
|
32
|
+
const ENERGY_LABELS = `intermediate/ion_dynamics/energies_tags`;
|
|
33
|
+
const OSZICAR_ROWS = `intermediate/ion_dynamics/oszicar`;
|
|
34
|
+
const OSZICAR_LABELS = `intermediate/ion_dynamics/oszicar_label`;
|
|
35
|
+
const ELECTRONIC_STEP_ENERGIES = `intermediate/electronic_steps/energies`;
|
|
36
|
+
// vaspout.h5 root groups per the VASP 6.x schema. torch-sim files use flat
|
|
37
|
+
// dataset names (positions/atomic_numbers/...) and never these groups.
|
|
38
|
+
export const is_vaspout_h5_file = (h5_file) => [`results`, `intermediate`].some((name) => is_hdf5_group(h5_file.get(name))) &&
|
|
39
|
+
[`input`, `version`, `results`, `intermediate`].filter((name) => is_hdf5_group(h5_file.get(name))).length >= 2;
|
|
40
|
+
// Final-structure datasets may carry a leading singleton step axis
|
|
41
|
+
// ([1, 3, 3] lattices, [1, n_atoms, 3] positions) depending on VASP version.
|
|
42
|
+
const squeeze_leading_axis = (data) => Array.isArray(data) &&
|
|
43
|
+
data.length === 1 &&
|
|
44
|
+
Array.isArray(data[0]) &&
|
|
45
|
+
Array.isArray(data[0][0])
|
|
46
|
+
? data[0]
|
|
47
|
+
: data;
|
|
48
|
+
// VASP writes several energy kinds per step; energies_tags names the columns.
|
|
49
|
+
// Prefer the free energy (TOTEN), then energy(sigma->0), then column 0.
|
|
50
|
+
const pick_energy_column = (tags) => {
|
|
51
|
+
if (!tags)
|
|
52
|
+
return { idx: 0, tag: null };
|
|
53
|
+
for (const needle of [`TOTEN`, `sigma->0`]) {
|
|
54
|
+
const idx = tags.findIndex((tag) => tag.includes(needle));
|
|
55
|
+
if (idx !== -1)
|
|
56
|
+
return { idx, tag: tags[idx] };
|
|
57
|
+
}
|
|
58
|
+
return { idx: 0, tag: tags[0] ?? null };
|
|
59
|
+
};
|
|
60
|
+
const finite_or_null = (value) => typeof value === `number` && Number.isFinite(value) ? value : null;
|
|
61
|
+
// OSZICAR rows are [total_scf_rows, n_cols] with oszicar_label naming columns
|
|
62
|
+
// (N, E, dE, d eps, ncg, rms, rms(c)). The N counter resets to 1 at each new
|
|
63
|
+
// ionic step, which is how rows group into ionic steps (same as ferrox).
|
|
64
|
+
const read_oszicar_history = (h5_file) => {
|
|
65
|
+
const rows = read_dataset(h5_file, OSZICAR_ROWS);
|
|
66
|
+
const labels = to_string_array(read_dataset(h5_file, OSZICAR_LABELS));
|
|
67
|
+
if (!rows || !labels)
|
|
68
|
+
return null;
|
|
69
|
+
const col = (name) => labels.findIndex((label) => label.trim() === name);
|
|
70
|
+
const [n_col, energy_col] = [col(`N`), col(`E`)];
|
|
71
|
+
if (n_col < 0 || energy_col < 0)
|
|
72
|
+
return null;
|
|
73
|
+
const [delta_col, rms_col, charge_rms_col] = [col(`dE`), col(`rms`), col(`rms(c)`)];
|
|
74
|
+
const ionic_steps = [];
|
|
75
|
+
let current = null;
|
|
76
|
+
let previous_scf_counter = Infinity;
|
|
77
|
+
for (const row of rows) {
|
|
78
|
+
const scf_counter = row[n_col];
|
|
79
|
+
const energy = finite_or_null(row[energy_col]);
|
|
80
|
+
if (energy === null || !Number.isFinite(scf_counter))
|
|
81
|
+
return null;
|
|
82
|
+
if (scf_counter <= previous_scf_counter || !current) {
|
|
83
|
+
current = { energies: [], energy_deltas: [], rms: [], charge_rms: [] };
|
|
84
|
+
ionic_steps.push(current);
|
|
85
|
+
}
|
|
86
|
+
current.energies.push(energy);
|
|
87
|
+
current.energy_deltas.push(delta_col >= 0 ? finite_or_null(row[delta_col]) : null);
|
|
88
|
+
current.rms.push(rms_col >= 0 ? finite_or_null(row[rms_col]) : null);
|
|
89
|
+
current.charge_rms.push(charge_rms_col >= 0 ? finite_or_null(row[charge_rms_col]) : null);
|
|
90
|
+
previous_scf_counter = scf_counter;
|
|
91
|
+
}
|
|
92
|
+
return ionic_steps.length > 0 ? ionic_steps : null;
|
|
93
|
+
};
|
|
94
|
+
// Fallback when the OSZICAR mirror is absent: the explicit per-ionic-step SCF
|
|
95
|
+
// energy dataset (shape [n_ionic, n_scf]); deltas derived from consecutive
|
|
96
|
+
// energies, no density residuals available.
|
|
97
|
+
const read_electronic_step_history = (h5_file) => {
|
|
98
|
+
const rows = read_dataset(h5_file, ELECTRONIC_STEP_ENERGIES);
|
|
99
|
+
if (!rows)
|
|
100
|
+
return null;
|
|
101
|
+
const ionic_steps = rows
|
|
102
|
+
.map((row) => {
|
|
103
|
+
const energies = (Array.isArray(row) ? row : [row]).filter((val) => typeof val === `number` && Number.isFinite(val));
|
|
104
|
+
return {
|
|
105
|
+
energies,
|
|
106
|
+
energy_deltas: energies.map((energy, idx) => idx > 0 ? energy - energies[idx - 1] : null),
|
|
107
|
+
rms: energies.map(() => null),
|
|
108
|
+
charge_rms: energies.map(() => null),
|
|
109
|
+
};
|
|
110
|
+
})
|
|
111
|
+
.filter((step) => step.energies.length > 0);
|
|
112
|
+
return ionic_steps.length > 0 ? ionic_steps : null;
|
|
113
|
+
};
|
|
114
|
+
const read_scf_history = (h5_file) => read_oszicar_history(h5_file) ?? read_electronic_step_history(h5_file);
|
|
115
|
+
// Convergence fields (|dE|, density residuals) for one SCF step; negative idx
|
|
116
|
+
// counts from the end (-1 = final step). Shared by the per-frame summary below
|
|
117
|
+
// and the SCF pseudo-frame expansion for single-point runs.
|
|
118
|
+
const scf_step_metadata = (scf, idx) => {
|
|
119
|
+
const metadata = {};
|
|
120
|
+
const delta = scf.energy_deltas.at(idx);
|
|
121
|
+
if (delta != null)
|
|
122
|
+
metadata.scf_energy_delta = Math.abs(delta);
|
|
123
|
+
const rms = scf.rms.at(idx);
|
|
124
|
+
if (rms != null)
|
|
125
|
+
metadata.scf_rms = rms;
|
|
126
|
+
const charge_rms = scf.charge_rms.at(idx);
|
|
127
|
+
if (charge_rms != null)
|
|
128
|
+
metadata.scf_charge_rms = charge_rms;
|
|
129
|
+
return metadata;
|
|
130
|
+
};
|
|
131
|
+
// Final-SCF-step summary attached to each ionic frame so relax trajectories
|
|
132
|
+
// plot SCF effort/residuals alongside energy and force_max.
|
|
133
|
+
const scf_frame_metadata = (scf) => {
|
|
134
|
+
if (!scf || scf.energies.length === 0)
|
|
135
|
+
return {};
|
|
136
|
+
const metadata = {
|
|
137
|
+
n_scf_steps: scf.energies.length,
|
|
138
|
+
...scf_step_metadata(scf, -1),
|
|
139
|
+
};
|
|
140
|
+
// interrupted writers can drop the final dE entry: derive it from the last two energies
|
|
141
|
+
if (!(`scf_energy_delta` in metadata) && scf.energies.length >= 2) {
|
|
142
|
+
metadata.scf_energy_delta = Math.abs(scf.energies.at(-1) - scf.energies.at(-2));
|
|
143
|
+
}
|
|
144
|
+
return metadata;
|
|
145
|
+
};
|
|
146
|
+
// Bands/DOS-only outputs (e.g. phelel band-path files) carry no (complete)
|
|
147
|
+
// structure datasets but still have renderable electronic results: surface
|
|
148
|
+
// them as a zero-frame trajectory the webview routes to the spectral
|
|
149
|
+
// components. Files with neither structure nor electronic data throw.
|
|
150
|
+
const electronic_only_trajectory = (h5_file, missing) => {
|
|
151
|
+
const electronic = read_vaspout_electronic(h5_file);
|
|
152
|
+
if (!electronic) {
|
|
153
|
+
throw new Error(`vaspout.h5 file has no structure data (missing ${missing}) — ` +
|
|
154
|
+
`and no electron_dos/electron_eigenvalues results either`);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
frames: [],
|
|
158
|
+
metadata: {
|
|
159
|
+
source_format: `vaspout_h5`,
|
|
160
|
+
frame_count: 0,
|
|
161
|
+
electronic,
|
|
162
|
+
vaspout_electronic_only: true,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
export function parse_vaspout_h5_file(h5_file) {
|
|
167
|
+
const ion_types = to_string_array(read_dataset(h5_file, FINAL_ION_TYPES));
|
|
168
|
+
const ion_counts = to_number_array(read_dataset(h5_file, FINAL_ION_COUNTS));
|
|
169
|
+
if (!ion_types || !ion_counts) {
|
|
170
|
+
return electronic_only_trajectory(h5_file, `${FINAL_ION_TYPES} / ${FINAL_ION_COUNTS}`);
|
|
171
|
+
}
|
|
172
|
+
// expand_ion_types throws on length mismatch and unknown symbols (fail loudly)
|
|
173
|
+
const elements = expand_ion_types(ion_types, ion_counts);
|
|
174
|
+
// POSCAR-style universal scaling factor; scalar in real files, but some
|
|
175
|
+
// writers store it as a 1-element array. Intermediate ion-dynamics frames
|
|
176
|
+
// carry their own scale (py4vasp's trajectory Cell reads
|
|
177
|
+
// intermediate/ion_dynamics/scale), distinct from the final-structure scale.
|
|
178
|
+
const scale = to_scalar_number(read_dataset(h5_file, FINAL_SCALE)) ?? 1;
|
|
179
|
+
const traj_scale = to_scalar_number(read_dataset(h5_file, TRAJ_SCALE)) ?? scale;
|
|
180
|
+
const traj_positions = read_dataset(h5_file, TRAJ_POSITIONS);
|
|
181
|
+
const traj_lattices = read_dataset(h5_file, TRAJ_LATTICE);
|
|
182
|
+
const traj_forces = read_dataset(h5_file, TRAJ_FORCES);
|
|
183
|
+
const energies = read_dataset(h5_file, ENERGY_VALUES);
|
|
184
|
+
const energy_tags = to_string_array(read_dataset(h5_file, ENERGY_LABELS));
|
|
185
|
+
const { idx: energy_col, tag: energy_tag } = pick_energy_column(energy_tags);
|
|
186
|
+
const scf_history = read_scf_history(h5_file);
|
|
187
|
+
const frames = [];
|
|
188
|
+
let dropped_steps = 0;
|
|
189
|
+
// Shared frame assembly for the per-step trajectory path and the
|
|
190
|
+
// final-structure fallback: validate + scale the lattice, convert fractional
|
|
191
|
+
// positions to Cartesian, attach volume/SCF/energy (and optional forces).
|
|
192
|
+
const build_frame = (lattice_data, frac_positions, step, scf, raw_energy, forces, frame_scale) => {
|
|
193
|
+
const lattice = scale_matrix(validate_3x3_matrix(lattice_data), frame_scale);
|
|
194
|
+
const frac_to_cart = create_frac_to_cart(lattice);
|
|
195
|
+
const positions = frac_positions.map((frac) => frac_to_cart(frac));
|
|
196
|
+
const metadata = {
|
|
197
|
+
volume: calc_lattice_params(lattice).volume,
|
|
198
|
+
...scf_frame_metadata(scf),
|
|
199
|
+
};
|
|
200
|
+
const energy = finite_or_null(raw_energy);
|
|
201
|
+
if (energy !== null)
|
|
202
|
+
metadata.energy = energy;
|
|
203
|
+
if (Array.isArray(forces))
|
|
204
|
+
metadata.forces = forces;
|
|
205
|
+
return create_trajectory_frame(positions, elements, lattice, [true, true, true], step, metadata);
|
|
206
|
+
};
|
|
207
|
+
if (traj_positions && traj_lattices) {
|
|
208
|
+
// A torn file's datasets may disagree on step count; never index past the
|
|
209
|
+
// shortest required one (forces/energies are optional per step).
|
|
210
|
+
const n_steps = Math.min(traj_positions.length, traj_lattices.length);
|
|
211
|
+
for (let step = 0; step < n_steps; step++) {
|
|
212
|
+
try {
|
|
213
|
+
frames.push(build_frame(traj_lattices[step], traj_positions[step], step, scf_history?.[step], energies?.[step]?.[energy_col], traj_forces?.[step], traj_scale));
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Torn final step: keep the frames parsed so far.
|
|
217
|
+
dropped_steps = n_steps - step;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Static (NSW=0) runs have no intermediate/ion_dynamics group at all; fall
|
|
223
|
+
// back to the final structure so the file still opens as a 1-frame view.
|
|
224
|
+
if (frames.length === 0) {
|
|
225
|
+
const final_lattice_data = squeeze_leading_axis(read_dataset(h5_file, FINAL_LATTICE));
|
|
226
|
+
const final_positions_data = squeeze_leading_axis(read_dataset(h5_file, FINAL_POSITIONS));
|
|
227
|
+
if (!final_lattice_data || !final_positions_data) {
|
|
228
|
+
// Ion species exist but geometry is missing/torn — a bands/DOS-only
|
|
229
|
+
// file can still render its electronic results.
|
|
230
|
+
return electronic_only_trajectory(h5_file, `${TRAJ_POSITIONS} / ${FINAL_POSITIONS}`);
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
frames.push(build_frame(final_lattice_data, final_positions_data, 0, scf_history?.at(-1), energies?.at(-1)?.[energy_col], undefined, scale));
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Geometry datasets present but malformed (file torn mid-write): same
|
|
237
|
+
// electronic-only fallback as when they're missing entirely.
|
|
238
|
+
return electronic_only_trajectory(h5_file, `${FINAL_LATTICE} / ${FINAL_POSITIONS}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Static/single-point runs (one ionic step) get their SCF electronic steps
|
|
242
|
+
// expanded into pseudo-frames: the structure stays fixed while energy, |dE|,
|
|
243
|
+
// and the density residuals (incl. OSZICAR's rms(c) charge-density residual)
|
|
244
|
+
// plot per SCF step — the convergence view that matters when watching a
|
|
245
|
+
// running static job. Multi-point plots need >=2 frames, so this also makes
|
|
246
|
+
// single-point files plottable at all.
|
|
247
|
+
let frames_are_scf_steps = false;
|
|
248
|
+
const only_scf = scf_history?.length === 1 ? scf_history[0] : null;
|
|
249
|
+
if (frames.length === 1 && only_scf && only_scf.energies.length >= 2) {
|
|
250
|
+
const base_frame = frames[0];
|
|
251
|
+
frames.length = 0;
|
|
252
|
+
for (const [scf_idx, scf_energy] of only_scf.energies.entries()) {
|
|
253
|
+
const metadata = {
|
|
254
|
+
energy: scf_energy,
|
|
255
|
+
volume: base_frame.metadata?.volume,
|
|
256
|
+
...scf_step_metadata(only_scf, scf_idx),
|
|
257
|
+
};
|
|
258
|
+
frames.push({ structure: base_frame.structure, step: scf_idx, metadata });
|
|
259
|
+
}
|
|
260
|
+
frames_are_scf_steps = true;
|
|
261
|
+
}
|
|
262
|
+
// Trajectory views only ever render the DOS panel, so skip reading the
|
|
263
|
+
// (potentially large) eigenvalue arrays here — bands are read only on the
|
|
264
|
+
// electronic-only paths above, which are the sole consumers.
|
|
265
|
+
const dos = read_vaspout_dos(h5_file);
|
|
266
|
+
return {
|
|
267
|
+
frames,
|
|
268
|
+
metadata: {
|
|
269
|
+
source_format: `vaspout_h5`,
|
|
270
|
+
frame_count: frames.length,
|
|
271
|
+
num_atoms: elements.length,
|
|
272
|
+
element_counts: count_elements(elements),
|
|
273
|
+
periodic_boundary_conditions: [true, true, true],
|
|
274
|
+
has_cell_info: true,
|
|
275
|
+
...(energy_tag ? { energy_tag } : {}),
|
|
276
|
+
...(dropped_steps > 0 ? { dropped_steps } : {}),
|
|
277
|
+
...(frames_are_scf_steps ? { frames_are_scf_steps: true } : {}),
|
|
278
|
+
...(dos ? { electronic: { dos, bands: null } } : {}),
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
export async function parse_vaspout_h5(buffer, filename) {
|
|
283
|
+
return with_h5_file(buffer, filename, parse_vaspout_h5_file);
|
|
284
|
+
}
|