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
|
@@ -73,7 +73,9 @@
|
|
|
73
73
|
{@attach section.tooltip
|
|
74
74
|
? tooltip({ allow_html: true, content: sanitize_html(section.tooltip) })
|
|
75
75
|
: () => {}}
|
|
76
|
-
>
|
|
76
|
+
>
|
|
77
|
+
{section.title}
|
|
78
|
+
</h4>
|
|
77
79
|
{/if}
|
|
78
80
|
<div class="export-grid">
|
|
79
81
|
{#each section.items as item, item_idx (item.label)}
|
|
@@ -81,9 +83,9 @@
|
|
|
81
83
|
<!-- not a <label>: it would forward label-text clicks to the first (download) button -->
|
|
82
84
|
<span class="export-item">
|
|
83
85
|
{#if item.hint}
|
|
84
|
-
<span
|
|
85
|
-
{
|
|
86
|
-
>
|
|
86
|
+
<span {@attach tooltip({ allow_html: true, content: sanitize_html(item.hint) })}
|
|
87
|
+
>{item.label}</span
|
|
88
|
+
>
|
|
87
89
|
{:else}
|
|
88
90
|
{item.label}
|
|
89
91
|
{/if}
|
|
@@ -110,14 +112,16 @@
|
|
|
110
112
|
</button>
|
|
111
113
|
{/if}
|
|
112
114
|
{#if item.show_dpi}
|
|
113
|
-
<span class="dpi-input"
|
|
115
|
+
<span class="dpi-input"
|
|
116
|
+
>(DPI: <input
|
|
114
117
|
type="number"
|
|
115
118
|
min={dpi_range[0]}
|
|
116
119
|
max={dpi_range[1]}
|
|
117
120
|
bind:value={png_dpi}
|
|
118
121
|
onchange={clamp_dpi}
|
|
119
122
|
title="Export resolution in dots per inch"
|
|
120
|
-
/>)</span
|
|
123
|
+
/>)</span
|
|
124
|
+
>
|
|
121
125
|
{/if}
|
|
122
126
|
</span>
|
|
123
127
|
{/each}
|
package/dist/io/decompress.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { COMPRESSION_EXTENSIONS } from '../constants';
|
|
2
2
|
import { COMPRESSION_FORMATS } from '../constants';
|
|
3
|
+
export declare function strip_compression_extensions(filename: string): string;
|
|
3
4
|
export type CompressionFormat = keyof typeof COMPRESSION_FORMATS;
|
|
4
5
|
export type CompressionExtension = (typeof COMPRESSION_EXTENSIONS)[number];
|
|
5
6
|
export declare function detect_compression_format(filename: string): CompressionFormat | null;
|
|
6
7
|
export declare function decompress_data(data: ArrayBuffer | ReadableStream<Uint8Array> | null, format: CompressionFormat): Promise<string>;
|
|
7
8
|
export declare function decompress_data_binary(data: ArrayBuffer | ReadableStream<Uint8Array> | null, format: CompressionFormat): Promise<ArrayBuffer>;
|
|
8
9
|
export declare function decompress_file(file: File): Promise<{
|
|
9
|
-
content: string;
|
|
10
|
+
content: string | ArrayBuffer;
|
|
10
11
|
filename: string;
|
|
11
12
|
}>;
|
package/dist/io/decompress.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { COMPRESSION_EXTENSIONS_REGEX, COMPRESSION_FORMATS } from '../constants';
|
|
2
|
-
import {
|
|
2
|
+
import { is_binary_payload } from './is-binary';
|
|
3
|
+
// Lowercase a filename and strip all trailing compression extensions (.gz, .zip, ...)
|
|
4
|
+
export function strip_compression_extensions(filename) {
|
|
5
|
+
let base_name = filename.toLowerCase();
|
|
6
|
+
while (COMPRESSION_EXTENSIONS_REGEX.test(base_name)) {
|
|
7
|
+
base_name = base_name.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
8
|
+
}
|
|
9
|
+
return base_name;
|
|
10
|
+
}
|
|
3
11
|
export function detect_compression_format(filename) {
|
|
4
12
|
const lower = filename.toLowerCase();
|
|
5
13
|
for (const [format, extensions] of Object.entries(COMPRESSION_FORMATS)) {
|
|
@@ -37,39 +45,18 @@ export async function decompress_data_binary(data, format) {
|
|
|
37
45
|
throw new Error(`Failed to decompress ${format} file: ${error}`, { cause: error });
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
const to_content = (filename, buffer) => is_binary_payload(filename, buffer) ? buffer : new TextDecoder().decode(buffer);
|
|
49
|
+
// Read a dropped file, decompressing supported formats. Binary payloads (by extension or
|
|
50
|
+
// magic bytes) return as ArrayBuffer so parsers get raw bytes; text decodes to string.
|
|
51
|
+
export async function decompress_file(file) {
|
|
41
52
|
const format = detect_compression_format(file.name);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (is_supported && format) {
|
|
52
|
-
if (!(result instanceof ArrayBuffer))
|
|
53
|
-
throw new Error(`Expected binary file data`);
|
|
54
|
-
decompress_data(result, format).then((content) => {
|
|
55
|
-
const filename = file.name.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
56
|
-
resolve({ content, filename });
|
|
57
|
-
}, reject);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
if (typeof result !== `string`)
|
|
61
|
-
throw new Error(`Expected text file data`);
|
|
62
|
-
resolve({ content: result, filename: file.name });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
reject(to_error(error));
|
|
67
|
-
}
|
|
68
|
-
}, { once: true });
|
|
69
|
-
reader.addEventListener(`error`, () => reject(new Error(`Failed to read file ${file.name}`)));
|
|
70
|
-
if (is_supported)
|
|
71
|
-
reader.readAsArrayBuffer(file);
|
|
72
|
-
else
|
|
73
|
-
reader.readAsText(file);
|
|
74
|
-
});
|
|
53
|
+
// zip/xz/bz2 are handled by their own code paths; null = not compressed
|
|
54
|
+
const decompressible = format !== null && format !== `zip` && format !== `xz` && format !== `bz2` ? format : null;
|
|
55
|
+
const buffer = await file.arrayBuffer();
|
|
56
|
+
if (decompressible) {
|
|
57
|
+
const filename = file.name.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
58
|
+
const decompressed = await decompress_data_binary(buffer, decompressible);
|
|
59
|
+
return { content: to_content(filename, decompressed), filename };
|
|
60
|
+
}
|
|
61
|
+
return { content: to_content(file.name, buffer), filename: file.name };
|
|
75
62
|
}
|
package/dist/io/export.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { AnyStructure } from '../structure';
|
|
2
2
|
import { type Camera, type Scene, type WebGLRenderer } from 'three';
|
|
3
3
|
export declare const renderer_registry: WeakMap<HTMLCanvasElement, WebGLRenderer>;
|
|
4
|
+
export declare const scene_registry: WeakMap<HTMLCanvasElement, {
|
|
5
|
+
scene: Scene;
|
|
6
|
+
camera: Camera;
|
|
7
|
+
}>;
|
|
4
8
|
export declare const dpi_to_scale: (png_dpi: number) => number;
|
|
5
9
|
export declare function canvas_to_png_blob(canvas: HTMLCanvasElement, png_dpi?: number, scene?: Scene | null, camera?: Camera | null): Promise<Blob>;
|
|
6
10
|
export declare function export_canvas_as_png(canvas: HTMLCanvasElement | null, structure_or_filename: AnyStructure | string | undefined, png_dpi?: number, scene?: Scene | null, camera?: Camera | null): void;
|
package/dist/io/export.js
CHANGED
|
@@ -5,6 +5,10 @@ import { Vector2 } from 'three';
|
|
|
5
5
|
// Maps a Threlte canvas to its WebGLRenderer so PNG export can look up the renderer for a
|
|
6
6
|
// given canvas without mutating the DOM element. Populated by bind_renderer (scene/).
|
|
7
7
|
export const renderer_registry = new WeakMap();
|
|
8
|
+
// Companion scene+camera mapping: WebGL buffers are cleared after present
|
|
9
|
+
// (preserveDrawingBuffer is off), so any capture of a live canvas must
|
|
10
|
+
// re-render synchronously first — which needs the scene and active camera.
|
|
11
|
+
export const scene_registry = new WeakMap();
|
|
8
12
|
// PNG DPI -> render scale relative to the 72 DPI baseline, capped at 10x. DPI floors
|
|
9
13
|
// at 1 (non-finite -> 72) so bad inputs can't yield 0x0 canvases or NaN pixel ratios.
|
|
10
14
|
export const dpi_to_scale = (png_dpi) => Math.min(Math.max(1, Number.isFinite(png_dpi) ? png_dpi : 72) / 72, 10);
|
|
@@ -303,7 +307,7 @@ export async function export_trajectory_video(canvas, filename, options = {}) {
|
|
|
303
307
|
is_resolved = true;
|
|
304
308
|
try {
|
|
305
309
|
const blob = new Blob(chunks, { type: `video/webm` });
|
|
306
|
-
const webm_filename = filename.replace(/\.(mp4|webm)$/i, `.webm`);
|
|
310
|
+
const webm_filename = filename.replace(/\.(?:mp4|webm)$/i, `.webm`);
|
|
307
311
|
download(blob, webm_filename, `video/webm`);
|
|
308
312
|
on_progress?.(100);
|
|
309
313
|
resolve();
|
package/dist/io/fetch.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
export declare const to_query: (params: Record<string, string | number | undefined>) => string;
|
|
2
|
-
export declare function fetch_zipped<T>(url: string, { unzip }?: {
|
|
3
|
-
unzip?: boolean | undefined;
|
|
4
|
-
}): Promise<T | null>;
|
|
5
2
|
export type DownloadData = string | Blob | ArrayBuffer | ArrayBufferView<ArrayBuffer>;
|
|
6
3
|
export declare function download(data: DownloadData, filename: string, type: string): void;
|
package/dist/io/fetch.js
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
import { decompress_data } from './decompress';
|
|
2
1
|
// Convert params object to URL query string, omitting empty/undefined values.
|
|
3
2
|
// Example: {foo: "bar", baz: 42, empty: ""} → "foo=bar&baz=42"
|
|
4
3
|
export const to_query = (params) => new URLSearchParams(Object.entries(params)
|
|
5
4
|
.filter(([, val]) => val !== `` && val !== undefined)
|
|
6
5
|
.map(([key, val]) => [key, String(val)])).toString();
|
|
7
|
-
export async function fetch_zipped(url, { unzip = true } = {}) {
|
|
8
|
-
const response = await fetch(url);
|
|
9
|
-
if (!response.ok) {
|
|
10
|
-
console.error(`${response.status} ${response.statusText} for ${response.url}`);
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
if (!unzip)
|
|
14
|
-
return (await response.blob());
|
|
15
|
-
return JSON.parse(await decompress_data(response.body, `gzip`));
|
|
16
|
-
}
|
|
17
6
|
// Original download implementation
|
|
18
7
|
function default_download(data, filename, type) {
|
|
19
8
|
const file = new Blob([data], { type });
|
package/dist/io/index.d.ts
CHANGED
package/dist/io/index.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { COMPRESSION_EXTENSIONS_REGEX } from '../constants';
|
|
2
1
|
export { default as ExportPane } from './ExportPane.svelte';
|
|
2
|
+
// strip_compression_extensions lives in ./decompress (Svelte-free) so parser
|
|
3
|
+
// modules can import it inside Web Workers; re-exported here.
|
|
3
4
|
export * from './decompress';
|
|
4
5
|
export * from './export';
|
|
5
6
|
export * from './fetch';
|
|
6
7
|
export * from './file-drop';
|
|
7
8
|
export * from './is-binary';
|
|
8
9
|
export * from './url-drop';
|
|
9
|
-
// Lowercase a filename and strip all trailing compression extensions (.gz, .zip, ...)
|
|
10
|
-
export function strip_compression_extensions(filename) {
|
|
11
|
-
let base_name = filename.toLowerCase();
|
|
12
|
-
while (COMPRESSION_EXTENSIONS_REGEX.test(base_name)) {
|
|
13
|
-
base_name = base_name.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
14
|
-
}
|
|
15
|
-
return base_name;
|
|
16
|
-
}
|
package/dist/io/is-binary.d.ts
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
1
|
export declare const is_binary: (content: string) => boolean;
|
|
2
|
+
export declare const has_gzip_magic: (bytes: Uint8Array) => boolean;
|
|
3
|
+
export declare const has_hdf5_magic: (bytes: Uint8Array) => boolean;
|
|
4
|
+
export declare const has_binary_magic: (bytes: Uint8Array) => boolean;
|
|
5
|
+
export declare const ext_of: (name: string) => string;
|
|
6
|
+
export declare const BINARY_EXTENSIONS: Set<string>;
|
|
7
|
+
export declare const is_known_text_file: (basename: string) => boolean;
|
|
8
|
+
export declare const strip_gz_ext: (filename: string) => string;
|
|
9
|
+
export declare const has_binary_inner_ext: (filename: string) => boolean;
|
|
10
|
+
export declare const is_binary_payload: (filename: string, buffer: ArrayBuffer) => boolean;
|
package/dist/io/is-binary.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Single source of truth for binary-vs-text detection in the io layer (used by
|
|
2
|
+
// decompress.ts and url-drop.ts): (1) is_binary string heuristic, (2) has_*_magic byte
|
|
3
|
+
// signatures, (3) extension/filename classification.
|
|
4
|
+
// === (1) string-content heuristic ===
|
|
5
|
+
// Detect binary from decoded text: a NUL byte or a high ratio of non-printable chars.
|
|
2
6
|
export const is_binary = (content) => {
|
|
3
7
|
if (!content)
|
|
4
8
|
return false;
|
|
@@ -18,3 +22,43 @@ export const is_binary = (content) => {
|
|
|
18
22
|
}
|
|
19
23
|
return (binary_char_count / content.length > 0.1 || printable_ascii_count / content.length < 0.7);
|
|
20
24
|
};
|
|
25
|
+
// === (2) magic-byte signatures ===
|
|
26
|
+
const starts_with = (bytes, sig) => bytes.length >= sig.length && sig.every((byte, idx) => bytes[idx] === byte);
|
|
27
|
+
// gzip member header
|
|
28
|
+
export const has_gzip_magic = (bytes) => starts_with(bytes, [0x1f, 0x8b]);
|
|
29
|
+
// Full 8-byte HDF5 superblock signature "\x89HDF\r\n\x1a\n" — used to validate that a file
|
|
30
|
+
// claiming a .h5/.hdf5 extension really is HDF5 (stricter than the binary sniff below).
|
|
31
|
+
export const has_hdf5_magic = (bytes) => starts_with(bytes, [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
32
|
+
// Leading bytes that mark a payload as binary so a lossy UTF-8 decode would corrupt it.
|
|
33
|
+
// HDF5 is matched by its 4-byte "\x89HDF" prefix (the non-ASCII 0x89 already rules out text
|
|
34
|
+
// starting with "HDF"); the full 4-byte ZIP signatures rule out text merely starting "PK".
|
|
35
|
+
export const has_binary_magic = (bytes) => has_gzip_magic(bytes) ||
|
|
36
|
+
starts_with(bytes, [0x89, 0x48, 0x44, 0x46]) || // HDF5 "\x89HDF"
|
|
37
|
+
starts_with(bytes, [0x50, 0x4b, 0x03, 0x04]) || // ZIP local file
|
|
38
|
+
starts_with(bytes, [0x50, 0x4b, 0x05, 0x06]) || // ZIP empty archive (EOCD)
|
|
39
|
+
starts_with(bytes, [0x50, 0x4b, 0x07, 0x08]) || // ZIP spanned
|
|
40
|
+
starts_with(bytes, [0x2d, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x6c, 0x6d]); // ASE .traj "- of Ulm"
|
|
41
|
+
// === (3) extension / filename classification ===
|
|
42
|
+
export const ext_of = (name) => name.split(`.`).pop()?.toLowerCase() ?? ``;
|
|
43
|
+
// Binary data formats whose lossy UTF-8 decode would corrupt bytes (post-decompression)
|
|
44
|
+
const BINARY_DATA_EXTENSIONS = new Set(`h5 hdf5 traj npz pkl dat brml raw`.split(` `));
|
|
45
|
+
// All extensions treated as binary: data formats + compressed wrappers that must be
|
|
46
|
+
// downloaded/kept as raw bytes (used for binary-fetch mode and .gz inner-format checks)
|
|
47
|
+
export const BINARY_EXTENSIONS = new Set([
|
|
48
|
+
...BINARY_DATA_EXTENSIONS,
|
|
49
|
+
...`gz gzip zip bz2 xz`.split(` `),
|
|
50
|
+
]);
|
|
51
|
+
// Known text formats (plus extensionless VASP files) — safe to fetch/sniff as text
|
|
52
|
+
const TEXT_EXTENSIONS = new Set(`xyz extxyz json cif poscar yaml yml txt md py js ts css html xml`.split(` `));
|
|
53
|
+
const VASP_BASENAME_RE = /^(?:poscar|xdatcar|contcar)$/i;
|
|
54
|
+
export const is_known_text_file = (basename) => TEXT_EXTENSIONS.has(ext_of(basename)) || VASP_BASENAME_RE.test(basename);
|
|
55
|
+
const GZ_EXT_RE = /\.(?:gz|gzip)$/i;
|
|
56
|
+
// Strip a trailing .gz/.gzip wrapper extension, leaving any inner extension intact
|
|
57
|
+
export const strip_gz_ext = (filename) => filename.replace(GZ_EXT_RE, ``);
|
|
58
|
+
// Whether the file inside a .gz/.gzip wrapper is a known binary format that a lossy text
|
|
59
|
+
// decode would corrupt (bytes >= 0x80 -> U+FFFD)
|
|
60
|
+
export const has_binary_inner_ext = (filename) => BINARY_EXTENSIONS.has(ext_of(strip_gz_ext(filename)));
|
|
61
|
+
// Binary if the (post-decompression) extension is a known binary data format or the leading
|
|
62
|
+
// bytes match a magic signature
|
|
63
|
+
export const is_binary_payload = (filename, buffer) => BINARY_DATA_EXTENSIONS.has(ext_of(filename)) ||
|
|
64
|
+
has_binary_magic(new Uint8Array(buffer.slice(0, 8)));
|
package/dist/io/url-drop.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { load_binary_traj } from '../trajectory/parse';
|
|
2
2
|
import { decompress_data_binary } from './decompress';
|
|
3
|
-
|
|
4
|
-
const TEXT_EXTENSIONS = new Set(`xyz extxyz json cif poscar yaml yml txt md py js ts css html xml`.split(` `));
|
|
5
|
-
const VASP_BASENAME_RE = /^(poscar|xdatcar|contcar)$/i;
|
|
6
|
-
const GZ_EXT_RE = /\.(gz|gzip)$/i;
|
|
3
|
+
import { BINARY_EXTENSIONS, ext_of, has_binary_inner_ext, has_binary_magic, has_gzip_magic, has_hdf5_magic, is_known_text_file, strip_gz_ext, } from './is-binary';
|
|
7
4
|
// Extract filename from Content-Disposition header, falling back to url_basename.
|
|
8
5
|
function extract_filename(headers, fallback) {
|
|
9
6
|
if (!headers)
|
|
@@ -11,11 +8,11 @@ function extract_filename(headers, fallback) {
|
|
|
11
8
|
const content_disposition_str = headers.get(`content-disposition`);
|
|
12
9
|
if (!content_disposition_str)
|
|
13
10
|
return fallback;
|
|
14
|
-
const star_match = /filename\*=([^;]+)/i.exec(content_disposition_str);
|
|
11
|
+
const star_match = /filename\*=(?<value>[^;]+)/i.exec(content_disposition_str);
|
|
15
12
|
if (star_match?.[1]) {
|
|
16
13
|
let raw = star_match[1].trim().replaceAll(/^"|"$/g, ``);
|
|
17
14
|
// Strip any RFC 5987 charset'language' prefix; bare values pass through unchanged
|
|
18
|
-
const ext_value_match = /^[\w!#$%&+^`{}~-]+'[\w-]*'(
|
|
15
|
+
const ext_value_match = /^[\w!#$%&+^`{}~-]+'[\w-]*'(?<value>.*)$/.exec(raw);
|
|
19
16
|
if (ext_value_match)
|
|
20
17
|
raw = ext_value_match[1];
|
|
21
18
|
try {
|
|
@@ -25,17 +22,13 @@ function extract_filename(headers, fallback) {
|
|
|
25
22
|
return raw;
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
|
-
const plain_match = /filename\s*=\s*"?([^";]+)"?/i.exec(content_disposition_str);
|
|
25
|
+
const plain_match = /filename\s*=\s*"?(?<value>[^";]+)"?/i.exec(content_disposition_str);
|
|
29
26
|
// truthiness check (not ??) so whitespace-only `filename=` values fall back too
|
|
30
27
|
const name = plain_match?.[1]?.trim();
|
|
31
28
|
if (!name)
|
|
32
29
|
return fallback;
|
|
33
30
|
return name;
|
|
34
31
|
}
|
|
35
|
-
const ext_of = (name) => name.split(`.`).pop()?.toLowerCase() ?? ``;
|
|
36
|
-
// Whether the file inside a .gz/.gzip wrapper is a known binary format that a
|
|
37
|
-
// lossy text decode would corrupt (bytes >= 0x80 → U+FFFD)
|
|
38
|
-
const has_binary_inner_ext = (filename) => BINARY_EXTENSIONS.has(ext_of(filename.replace(GZ_EXT_RE, ``)));
|
|
39
32
|
// Gunzip a fetched payload → [content, filename] with .gz/.gzip stripped; content
|
|
40
33
|
// stays an ArrayBuffer for binary inner formats, decoded string otherwise
|
|
41
34
|
async function decompress_gz_payload(buffer, filename) {
|
|
@@ -43,7 +36,7 @@ async function decompress_gz_payload(buffer, filename) {
|
|
|
43
36
|
const content = has_binary_inner_ext(filename)
|
|
44
37
|
? decompressed
|
|
45
38
|
: new TextDecoder().decode(decompressed);
|
|
46
|
-
return [content, filename
|
|
39
|
+
return [content, strip_gz_ext(filename)];
|
|
47
40
|
}
|
|
48
41
|
// Handle URL-based file drop data by fetching content lazily
|
|
49
42
|
export async function handle_url_drop(drag_event, callback) {
|
|
@@ -87,12 +80,10 @@ export async function load_from_url(url, callback) {
|
|
|
87
80
|
if (ext === `h5` || ext === `hdf5`) {
|
|
88
81
|
const result = await load_binary_traj(resp, `H5`, true);
|
|
89
82
|
// Log warning if signature doesn't match (only for ArrayBuffer results)
|
|
90
|
-
if (result instanceof ArrayBuffer &&
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
console.warn(`File has .h5/.hdf5 extension but missing HDF5 signature`);
|
|
95
|
-
}
|
|
83
|
+
if (result instanceof ArrayBuffer &&
|
|
84
|
+
result.byteLength >= 8 &&
|
|
85
|
+
!has_hdf5_magic(new Uint8Array(result.slice(0, 8)))) {
|
|
86
|
+
console.warn(`File has .h5/.hdf5 extension but missing HDF5 signature`);
|
|
96
87
|
}
|
|
97
88
|
return callback(result, filename);
|
|
98
89
|
}
|
|
@@ -108,7 +99,7 @@ export async function load_from_url(url, callback) {
|
|
|
108
99
|
}
|
|
109
100
|
// Skip Range requests for known text formats to avoid production server issues
|
|
110
101
|
// Include VASP files that don't have extensions (POSCAR, XDATCAR, CONTCAR)
|
|
111
|
-
const is_known_text =
|
|
102
|
+
const is_known_text = is_known_text_file(url_basename);
|
|
112
103
|
let sniffed_callback_args;
|
|
113
104
|
if (!is_known_text) {
|
|
114
105
|
// Only the Range sniff is guarded (failure → plain text fetch). Once magic bytes
|
|
@@ -121,13 +112,10 @@ export async function load_from_url(url, callback) {
|
|
|
121
112
|
const head = await fetch(url, { headers: { Range: `bytes=0-15` } });
|
|
122
113
|
if (head.ok) {
|
|
123
114
|
const buf = new Uint8Array(await head.arrayBuffer());
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// ASE .traj files start with the Ulm signature "- of Ulm"
|
|
127
|
-
const is_ase_traj = [0x2d, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x6c, 0x6d].every((byte, idx) => buf[idx] === byte);
|
|
128
|
-
if (is_gzip)
|
|
115
|
+
// gzip is gunzipped downstream; other binary magic (HDF5, ZIP, ASE Ulm) stays raw
|
|
116
|
+
if (has_gzip_magic(buf))
|
|
129
117
|
sniffed = `gzip`;
|
|
130
|
-
else if (
|
|
118
|
+
else if (has_binary_magic(buf))
|
|
131
119
|
sniffed = `binary`;
|
|
132
120
|
}
|
|
133
121
|
}
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
Uint32BufferAttribute,
|
|
15
15
|
} from 'three'
|
|
16
16
|
import type { IsosurfaceLayer, IsosurfaceSettings, VolumetricData } from './types'
|
|
17
|
-
import {
|
|
18
|
-
DEFAULT_ISOSURFACE_SETTINGS,
|
|
19
|
-
downsample_grid,
|
|
20
|
-
pad_periodic_grid,
|
|
21
|
-
} from './types'
|
|
17
|
+
import { DEFAULT_ISOSURFACE_SETTINGS, downsample_grid, pad_periodic_grid } from './types'
|
|
22
18
|
|
|
23
|
-
let {
|
|
19
|
+
let {
|
|
20
|
+
volume,
|
|
21
|
+
settings = DEFAULT_ISOSURFACE_SETTINGS,
|
|
22
|
+
}: {
|
|
24
23
|
volume: VolumetricData
|
|
25
24
|
settings?: IsosurfaceSettings
|
|
26
25
|
} = $props()
|
|
@@ -28,23 +27,22 @@
|
|
|
28
27
|
// Resolve layers: use explicit layers array if provided, else build from single-isovalue settings
|
|
29
28
|
let resolved_layers = $derived.by((): IsosurfaceLayer[] => {
|
|
30
29
|
if (settings.layers?.length) return settings.layers
|
|
31
|
-
return [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
isovalue: settings.isovalue,
|
|
33
|
+
color: settings.positive_color,
|
|
34
|
+
opacity: settings.opacity,
|
|
35
|
+
visible: true,
|
|
36
|
+
show_negative: settings.show_negative,
|
|
37
|
+
negative_color: settings.negative_color,
|
|
38
|
+
},
|
|
39
|
+
]
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
// Build indexed BufferGeometry from marching cubes output.
|
|
42
43
|
// Uses Three.js index buffer to avoid tripling vertex data, and
|
|
43
44
|
// computeVertexNormals() for fast GPU-friendly normals.
|
|
44
|
-
function build_geometry(
|
|
45
|
-
vertices: Vec3[],
|
|
46
|
-
faces: number[][],
|
|
47
|
-
): BufferGeometry | null {
|
|
45
|
+
function build_geometry(vertices: Vec3[], faces: number[][]): BufferGeometry | null {
|
|
48
46
|
if (vertices.length === 0 || faces.length === 0) return null
|
|
49
47
|
|
|
50
48
|
// Flatten vertices: Vec3[] → Float32Array
|
|
@@ -242,11 +240,7 @@
|
|
|
242
240
|
</T.Mesh>
|
|
243
241
|
{:else if entry.opacity < 1}
|
|
244
242
|
<!-- Two-pass rendering for correct transparency -->
|
|
245
|
-
<T.Mesh
|
|
246
|
-
geometry={entry.geometry}
|
|
247
|
-
renderOrder={entry.render_order}
|
|
248
|
-
frustumCulled={false}
|
|
249
|
-
>
|
|
243
|
+
<T.Mesh geometry={entry.geometry} renderOrder={entry.render_order} frustumCulled={false}>
|
|
250
244
|
<T.MeshStandardMaterial
|
|
251
245
|
color={entry.color}
|
|
252
246
|
transparent
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
function update_layer(idx: number, updates: Partial<IsosurfaceLayer>) {
|
|
46
46
|
if (!settings.layers) return
|
|
47
47
|
settings.layers = settings.layers.map((layer, layer_idx) =>
|
|
48
|
-
layer_idx === idx ? { ...layer, ...updates } : layer
|
|
48
|
+
layer_idx === idx ? { ...layer, ...updates } : layer,
|
|
49
49
|
)
|
|
50
50
|
}
|
|
51
51
|
</script>
|
|
@@ -68,7 +68,9 @@
|
|
|
68
68
|
<div class="pane-row compact-row">
|
|
69
69
|
{#if volumes.length > 1}
|
|
70
70
|
<label
|
|
71
|
-
{@attach tooltip({
|
|
71
|
+
{@attach tooltip({
|
|
72
|
+
content: `Select which volume to display (e.g. charge vs magnetization)`,
|
|
73
|
+
})}
|
|
72
74
|
>
|
|
73
75
|
<span>Volume:</span>
|
|
74
76
|
<select bind:value={active_volume_idx}>
|
|
@@ -79,13 +81,14 @@
|
|
|
79
81
|
</label>
|
|
80
82
|
{/if}
|
|
81
83
|
<label
|
|
82
|
-
{@attach tooltip({
|
|
84
|
+
{@attach tooltip({
|
|
85
|
+
content: `Number of isosurface shells at different density thresholds`,
|
|
86
|
+
})}
|
|
83
87
|
>
|
|
84
88
|
<span>Layers:</span>
|
|
85
89
|
<select
|
|
86
90
|
value={n_layers}
|
|
87
|
-
onchange={(event) =>
|
|
88
|
-
set_layer_count(Number(event.currentTarget.value))}
|
|
91
|
+
onchange={(event) => set_layer_count(Number(event.currentTarget.value))}
|
|
89
92
|
>
|
|
90
93
|
{#each [1, 2, 3, 4, 5] as count (count)}
|
|
91
94
|
<option value={count}>{count}</option>
|
|
@@ -95,14 +98,16 @@
|
|
|
95
98
|
<!-- Sync both settings.show_negative (single-layer fallback) and all layer entries
|
|
96
99
|
so the toggle works consistently regardless of which mode is active -->
|
|
97
100
|
<label
|
|
98
|
-
{@attach tooltip({
|
|
101
|
+
{@attach tooltip({
|
|
102
|
+
content: `Show negative lobe at −isovalue (for orbitals, ESP, magnetization)`,
|
|
103
|
+
})}
|
|
99
104
|
>
|
|
100
105
|
<span>Neg. lobe</span>
|
|
101
106
|
<input
|
|
102
107
|
type="checkbox"
|
|
103
108
|
checked={is_multi_layer
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
? (settings.layers?.some((layer) => layer.show_negative) ?? false)
|
|
110
|
+
: settings.show_negative}
|
|
106
111
|
onchange={(event) => {
|
|
107
112
|
const checked = event.currentTarget.checked
|
|
108
113
|
settings.show_negative = checked
|
|
@@ -115,9 +120,7 @@
|
|
|
115
120
|
}}
|
|
116
121
|
/>
|
|
117
122
|
</label>
|
|
118
|
-
<label
|
|
119
|
-
{@attach tooltip({ content: `Render as wireframe mesh instead of solid surface` })}
|
|
120
|
-
>
|
|
123
|
+
<label {@attach tooltip({ content: `Render as wireframe mesh instead of solid surface` })}>
|
|
121
124
|
<span>Wireframe</span>
|
|
122
125
|
<input type="checkbox" bind:checked={settings.wireframe} />
|
|
123
126
|
</label>
|
|
@@ -135,8 +138,7 @@
|
|
|
135
138
|
<input
|
|
136
139
|
type="color"
|
|
137
140
|
value={layer.color}
|
|
138
|
-
onchange={(event) =>
|
|
139
|
-
update_layer(idx, { color: event.currentTarget.value })}
|
|
141
|
+
onchange={(event) => update_layer(idx, { color: event.currentTarget.value })}
|
|
140
142
|
/>
|
|
141
143
|
<input
|
|
142
144
|
type="range"
|
|
@@ -145,9 +147,9 @@
|
|
|
145
147
|
{step}
|
|
146
148
|
value={layer.isovalue}
|
|
147
149
|
oninput={(event) =>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
update_layer(idx, {
|
|
151
|
+
isovalue: Number(event.currentTarget.value),
|
|
152
|
+
})}
|
|
151
153
|
style="flex: 1; min-width: 60px"
|
|
152
154
|
/>
|
|
153
155
|
<span class="layer-value">{format_num(layer.isovalue, `.3~g`)}</span>
|
|
@@ -158,9 +160,9 @@
|
|
|
158
160
|
step={0.05}
|
|
159
161
|
value={layer.opacity}
|
|
160
162
|
oninput={(event) =>
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
update_layer(idx, {
|
|
164
|
+
opacity: Number(event.currentTarget.value),
|
|
165
|
+
})}
|
|
164
166
|
style="width: 50px"
|
|
165
167
|
title="Opacity: {format_num(layer.opacity, `.2f`)}"
|
|
166
168
|
/>
|
|
@@ -169,23 +171,21 @@
|
|
|
169
171
|
{:else}
|
|
170
172
|
<!-- Single-layer: isovalue slider full width -->
|
|
171
173
|
<label
|
|
172
|
-
{@attach tooltip({
|
|
174
|
+
{@attach tooltip({
|
|
175
|
+
content: `Density threshold — surface is drawn where grid values equal this`,
|
|
176
|
+
})}
|
|
173
177
|
>
|
|
174
178
|
<span>Isovalue:</span>
|
|
175
|
-
<input
|
|
176
|
-
type="range"
|
|
177
|
-
min={step}
|
|
178
|
-
max={slider_max}
|
|
179
|
-
{step}
|
|
180
|
-
bind:value={settings.isovalue}
|
|
181
|
-
/>
|
|
179
|
+
<input type="range" min={step} max={slider_max} {step} bind:value={settings.isovalue} />
|
|
182
180
|
<span class="value">{format_num(settings.isovalue, `.4~g`)}</span>
|
|
183
181
|
</label>
|
|
184
182
|
|
|
185
183
|
<!-- Opacity + colors on one row -->
|
|
186
184
|
<div class="pane-row compact-row">
|
|
187
185
|
<label
|
|
188
|
-
{@attach tooltip({
|
|
186
|
+
{@attach tooltip({
|
|
187
|
+
content: `Surface transparency — lower values reveal inner structure`,
|
|
188
|
+
})}
|
|
189
189
|
>
|
|
190
190
|
<span>Opacity:</span>
|
|
191
191
|
<input
|
|
@@ -203,9 +203,7 @@
|
|
|
203
203
|
<input type="color" bind:value={settings.positive_color} />
|
|
204
204
|
</label>
|
|
205
205
|
{#if settings.show_negative}
|
|
206
|
-
<label
|
|
207
|
-
{@attach tooltip({ content: `Color for the negative (−isovalue) surface` })}
|
|
208
|
-
>
|
|
206
|
+
<label {@attach tooltip({ content: `Color for the negative (−isovalue) surface` })}>
|
|
209
207
|
<span>− Color</span>
|
|
210
208
|
<input type="color" bind:value={settings.negative_color} />
|
|
211
209
|
</label>
|
|
@@ -215,24 +213,21 @@
|
|
|
215
213
|
|
|
216
214
|
{#if volumes?.[active_volume_idx]?.periodic}
|
|
217
215
|
<label
|
|
218
|
-
{@attach tooltip({
|
|
216
|
+
{@attach tooltip({
|
|
217
|
+
content: `Extend isosurface beyond cell boundaries to close partial spheres (fraction of cell)`,
|
|
218
|
+
})}
|
|
219
219
|
>
|
|
220
220
|
Halo: {format_num(settings.halo, `.2f`)}
|
|
221
|
-
<input
|
|
222
|
-
type="range"
|
|
223
|
-
min={0}
|
|
224
|
-
max={0.5}
|
|
225
|
-
step={0.01}
|
|
226
|
-
bind:value={settings.halo}
|
|
227
|
-
/>
|
|
221
|
+
<input type="range" min={0} max={0.5} step={0.01} bind:value={settings.halo} />
|
|
228
222
|
</label>
|
|
229
223
|
{/if}
|
|
230
224
|
|
|
231
225
|
{#if volumes[active_volume_idx]}
|
|
232
226
|
<div class="grid-info">
|
|
233
|
-
{volumes[active_volume_idx].grid_dims.join(` × `)} grid | [{
|
|
234
|
-
|
|
235
|
-
|
|
227
|
+
{volumes[active_volume_idx].grid_dims.join(` × `)} grid | [{format_num(
|
|
228
|
+
data_range.min,
|
|
229
|
+
`.3~g`,
|
|
230
|
+
)}, {format_num(data_range.max, `.3~g`)}]
|
|
236
231
|
</div>
|
|
237
232
|
{/if}
|
|
238
233
|
</SettingsSection>
|