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
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
// Utility functions for computing atom properties and applying color scales
|
|
2
2
|
import { get_d3_interpolator } from '../colors';
|
|
3
|
-
import { calc_coordination_nums } from '../coordination';
|
|
3
|
+
import { calc_coordination_nums, } from '../coordination/calc-coordination';
|
|
4
4
|
import * as math from '../math';
|
|
5
|
-
import {
|
|
5
|
+
import { element_lookup, get_majority_element } from './bonding';
|
|
6
|
+
import { wrap_frac_coord } from './pbc';
|
|
6
7
|
import { rgb } from 'd3-color';
|
|
7
8
|
import * as d3_sc from 'd3-scale-chromatic';
|
|
8
9
|
const GRAY = `#808080`;
|
|
9
10
|
const DEFAULT_COLOR_SCALE = `interpolateViridis`;
|
|
11
|
+
// Cap on periodic image shells per axis when expanding for coordination. Guards
|
|
12
|
+
// against image explosion in very thin / highly oblique cells (coordination is ~O(n²)).
|
|
13
|
+
const MAX_IMAGE_SHELLS = 3;
|
|
14
|
+
// Max bond distance each strategy can form, mirroring the defaults in bonding.ts
|
|
15
|
+
// (electroneg_ratio.max_distance_ratio, solid_angle.max_distance). Used to size PBC
|
|
16
|
+
// image expansion just tightly enough that coordination never misses a bonded neighbor.
|
|
17
|
+
const ELECTRONEG_MAX_RATIO = 2;
|
|
18
|
+
const SOLID_ANGLE_MAX_DIST = 5; // Å
|
|
10
19
|
export const get_d3_color_scales = () => Object.keys(d3_sc).filter((key) => key.startsWith(`interpolate`));
|
|
11
20
|
const to_hex = (interp_fn, frac) => rgb(interp_fn(frac)).formatHex();
|
|
12
21
|
const build_image_site = (site, frac_to_cart, offset, orig_idx) => {
|
|
@@ -22,12 +31,6 @@ const build_image_site = (site, frac_to_cart, offset, orig_idx) => {
|
|
|
22
31
|
properties: { ...site.properties, orig_site_idx: orig_idx },
|
|
23
32
|
};
|
|
24
33
|
};
|
|
25
|
-
const get_all_offsets = (pbc) => [-1, 0, 1]
|
|
26
|
-
.flatMap((dx) => [-1, 0, 1].flatMap((dy) => [-1, 0, 1].map((dz) => [dx, dy, dz])))
|
|
27
|
-
.filter(([dx, dy, dz]) => !(dx === 0 && dy === 0 && dz === 0) &&
|
|
28
|
-
(pbc[0] || dx === 0) &&
|
|
29
|
-
(pbc[1] || dy === 0) &&
|
|
30
|
-
(pbc[2] || dz === 0));
|
|
31
34
|
const make_categorical = (vals, scale, sort_fn) => {
|
|
32
35
|
const interp_fn = get_d3_interpolator(scale);
|
|
33
36
|
const uniq = sort_fn
|
|
@@ -75,46 +78,109 @@ export const get_orig_site_idx = (site, site_idx) => typeof site?.properties?.or
|
|
|
75
78
|
: typeof site?.properties?.orig_site_idx === `number`
|
|
76
79
|
? site.properties.orig_site_idx
|
|
77
80
|
: site_idx;
|
|
78
|
-
// Expand structure with
|
|
79
|
-
|
|
81
|
+
// Expand a periodic structure with the neighbor images needed for correct
|
|
82
|
+
// coordination. Each atom's `reach` (the largest bond `strategy` can form for it —
|
|
83
|
+
// electroneg_ratio's (r + r_max)·ratio or solid_angle's flat cap) sizes how many whole
|
|
84
|
+
// cells to image per periodic axis, measured over the perpendicular cell height (not
|
|
85
|
+
// the lattice vector length, so oblique cells work), keeping only images within `reach`
|
|
86
|
+
// of the [0,1] cell and capping at MAX_IMAGE_SHELLS/axis (warns + may undercount beyond
|
|
87
|
+
// that — near-degenerate cells only). Smaller atoms image less; atoms with no covalent
|
|
88
|
+
// radius form no bonds and get no images.
|
|
89
|
+
function expand_structure_for_pbc(structure, strategy) {
|
|
80
90
|
if (!(`lattice` in structure) || !structure.lattice || structure.sites.length === 0) {
|
|
81
91
|
return structure;
|
|
82
92
|
}
|
|
83
93
|
const { sites, lattice } = structure;
|
|
84
|
-
const frac_to_cart = math.create_frac_to_cart(lattice.matrix);
|
|
85
94
|
const pbc = lattice.pbc ?? [true, true, true];
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return all_offsets
|
|
97
|
-
.filter(([dx, dy, dz]) => (dx === 0 || (dx === -1 ? norm[0] <= cutoff[0] : norm[0] >= 1 - cutoff[0])) &&
|
|
98
|
-
(dy === 0 || (dy === -1 ? norm[1] <= cutoff[1] : norm[1] >= 1 - cutoff[1])) &&
|
|
99
|
-
(dz === 0 || (dz === -1 ? norm[2] <= cutoff[2] : norm[2] >= 1 - cutoff[2])))
|
|
100
|
-
.map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx));
|
|
95
|
+
if (!pbc.some(Boolean))
|
|
96
|
+
return structure;
|
|
97
|
+
const frac_to_cart = math.create_frac_to_cart(lattice.matrix);
|
|
98
|
+
// Wrap into [0,1) along PERIODIC axes only so the near-cell filter and image
|
|
99
|
+
// building share one position (else boundary atoms image on the wrong side and lose
|
|
100
|
+
// neighbors). Vacuum axes keep their real coord — wrapping would fold apart atoms
|
|
101
|
+
// together and invent bonds.
|
|
102
|
+
const cell_sites = sites.map((site) => {
|
|
103
|
+
const abc = site.abc.map((coord, axis) => pbc[axis] ? wrap_frac_coord(coord) : coord);
|
|
104
|
+
return { ...site, abc, xyz: frac_to_cart(abc) };
|
|
101
105
|
});
|
|
102
|
-
|
|
106
|
+
// Covalent radius per atom (0 = unknown → forms no bonds → needs no images)
|
|
107
|
+
const radii = cell_sites.map((site) => {
|
|
108
|
+
const elem = get_majority_element(site);
|
|
109
|
+
return (elem ? element_lookup.get(elem)?.covalent_radius : undefined) ?? 0;
|
|
110
|
+
});
|
|
111
|
+
let max_radius = 0;
|
|
112
|
+
for (const radius of radii)
|
|
113
|
+
if (radius > max_radius)
|
|
114
|
+
max_radius = radius;
|
|
115
|
+
const reach_of = (radius) => strategy === `solid_angle`
|
|
116
|
+
? SOLID_ANGLE_MAX_DIST
|
|
117
|
+
: (radius + max_radius) * ELECTRONEG_MAX_RATIO;
|
|
118
|
+
const heights = math.cell_heights(lattice.matrix);
|
|
119
|
+
// Axes we image along: periodic and non-degenerate (finite height). Non-live axes
|
|
120
|
+
// (vacuum or degenerate) contribute no images — 0 shells + ∞ cutoff so their only
|
|
121
|
+
// copy (shift 0) always passes the near-cell filter. Loop-invariant, so hoisted out.
|
|
122
|
+
const live_axis = heights.map((height, axis) => pbc[axis] && Number.isFinite(height));
|
|
123
|
+
const image_near_cell = (frac, shift, axis_cutoff) => {
|
|
124
|
+
const shifted = frac + shift;
|
|
125
|
+
return shifted >= -axis_cutoff && shifted <= 1 + axis_cutoff;
|
|
126
|
+
};
|
|
127
|
+
let capped = false;
|
|
128
|
+
const image_sites = [];
|
|
129
|
+
for (const [orig_idx, site] of cell_sites.entries()) {
|
|
130
|
+
const radius = radii[orig_idx];
|
|
131
|
+
if (radius === 0)
|
|
132
|
+
continue; // no covalent radius → no bonds → no images
|
|
133
|
+
const reach = reach_of(radius);
|
|
134
|
+
// `cutoff` = fractional reach for the near-cell filter (keep an image shifted by `s`
|
|
135
|
+
// iff abc+s lands within `cutoff` of [0,1]); `n_shells` bounds the loop so no
|
|
136
|
+
// in-reach copy is missed.
|
|
137
|
+
const cutoff = heights.map((height, axis) => (live_axis[axis] ? reach / height : Infinity));
|
|
138
|
+
const n_shells = heights.map((height, axis) => {
|
|
139
|
+
if (!live_axis[axis])
|
|
140
|
+
return 0;
|
|
141
|
+
const shells = Math.floor(1 + reach / height);
|
|
142
|
+
if (shells > MAX_IMAGE_SHELLS)
|
|
143
|
+
capped = true;
|
|
144
|
+
return Math.min(MAX_IMAGE_SHELLS, shells);
|
|
145
|
+
});
|
|
146
|
+
const [frac_a, frac_b, frac_c] = site.abc; // periodic axes wrapped into [0, 1)
|
|
147
|
+
for (let dx = -n_shells[0]; dx <= n_shells[0]; dx++) {
|
|
148
|
+
if (!image_near_cell(frac_a, dx, cutoff[0]))
|
|
149
|
+
continue;
|
|
150
|
+
for (let dy = -n_shells[1]; dy <= n_shells[1]; dy++) {
|
|
151
|
+
if (!image_near_cell(frac_b, dy, cutoff[1]))
|
|
152
|
+
continue;
|
|
153
|
+
for (let dz = -n_shells[2]; dz <= n_shells[2]; dz++) {
|
|
154
|
+
if (dx === 0 && dy === 0 && dz === 0)
|
|
155
|
+
continue;
|
|
156
|
+
if (!image_near_cell(frac_c, dz, cutoff[2]))
|
|
157
|
+
continue;
|
|
158
|
+
image_sites.push(build_image_site(site, frac_to_cart, [dx, dy, dz], orig_idx));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (capped) {
|
|
164
|
+
console.warn(`[coordination] cell is very thin or oblique relative to bond reach; capping ` +
|
|
165
|
+
`PBC images at ${MAX_IMAGE_SHELLS} shells/axis, coordination near cell ` +
|
|
166
|
+
`boundaries may be undercounted`);
|
|
167
|
+
}
|
|
168
|
+
return { ...structure, sites: [...cell_sites, ...image_sites] };
|
|
103
169
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
170
|
+
// PBC-aware coordination: expand periodic cells with image atoms (so boundary atoms get
|
|
171
|
+
// full coordination), counting only original atoms as centers. Shared by the 3D viewer and
|
|
172
|
+
// CoordinationBarPlot so both report identical numbers.
|
|
173
|
+
export function calc_structure_coordination(structure, strategy = `electroneg_ratio`) {
|
|
107
174
|
const has_lattice = `lattice` in structure && structure.lattice !== undefined;
|
|
108
175
|
const pbc = has_lattice ? structure.lattice.pbc : undefined;
|
|
109
176
|
const has_pbc = has_lattice && (pbc === undefined || pbc.some(Boolean));
|
|
110
|
-
//
|
|
111
|
-
const coord_structure = has_pbc ? expand_structure_for_pbc(structure) : structure;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
.map((site) => site.coordination_num);
|
|
177
|
+
// Image atoms still count as neighbors but aren't iterated as centers (big speedup)
|
|
178
|
+
const coord_structure = has_pbc ? expand_structure_for_pbc(structure, strategy) : structure;
|
|
179
|
+
return calc_coordination_nums(coord_structure, strategy, structure.sites.length);
|
|
180
|
+
}
|
|
181
|
+
export function get_coordination_colors(structure, strategy = `electroneg_ratio`, scale = DEFAULT_COLOR_SCALE, type = `continuous`) {
|
|
182
|
+
// sites is already limited to the original atoms (calc_coordination_nums center_count)
|
|
183
|
+
const coord_nums = calc_structure_coordination(structure, strategy).sites.map((site) => site.coordination_num);
|
|
118
184
|
const { colors, unique_values } = apply_color_scale(coord_nums, scale, type);
|
|
119
185
|
return build_prop_colors(coord_nums, colors, unique_values);
|
|
120
186
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ElementSymbol } from '../element';
|
|
2
2
|
import type { Vec3 } from '../math';
|
|
3
3
|
import type { AnyStructure, BondOrder, BondPair, Site, StructureBond } from './';
|
|
4
|
-
export declare const element_lookup: Map<"
|
|
4
|
+
export declare const element_lookup: Map<"Ac" | "Ag" | "Al" | "Am" | "Ar" | "As" | "At" | "Au" | "B" | "Ba" | "Be" | "Bh" | "Bi" | "Bk" | "Br" | "C" | "Ca" | "Cd" | "Ce" | "Cf" | "Cl" | "Cm" | "Co" | "Cr" | "Cs" | "Cu" | "Db" | "Dy" | "Er" | "Es" | "Eu" | "F" | "Fe" | "Fm" | "Fr" | "Ga" | "Gd" | "Ge" | "H" | "He" | "Hf" | "Hg" | "Ho" | "Hs" | "I" | "In" | "Ir" | "K" | "Kr" | "La" | "Li" | "Lr" | "Lu" | "Md" | "Mg" | "Mn" | "Mo" | "Mt" | "N" | "Na" | "Nb" | "Nd" | "Ne" | "Ni" | "No" | "Np" | "O" | "Os" | "P" | "Pa" | "Pb" | "Pd" | "Pm" | "Po" | "Pr" | "Pt" | "Pu" | "Ra" | "Rb" | "Re" | "Rf" | "Rh" | "Rn" | "Ru" | "S" | "Sb" | "Sc" | "Se" | "Sg" | "Si" | "Sm" | "Sn" | "Sr" | "Ta" | "Tb" | "Tc" | "Te" | "Th" | "Ti" | "Tl" | "Tm" | "U" | "V" | "W" | "Xe" | "Y" | "Yb" | "Zn" | "Zr" | "Ds" | "Rg" | "Cn" | "Nh" | "Fl" | "Mc" | "Lv" | "Ts" | "Og", import("../element").ChemicalElement>;
|
|
5
5
|
export declare const get_majority_element: (site: Site | undefined) => ElementSymbol | null;
|
|
6
|
+
export declare const is_spectator_center: (element: string) => boolean;
|
|
7
|
+
export declare function has_framework_potential(elements: Iterable<string>): boolean;
|
|
6
8
|
export declare const normalize_structure_bond: (site_idx_1: number, site_idx_2: number, order: BondOrder, cell_shift?: Vec3) => StructureBond;
|
|
7
9
|
export declare const get_bond_key: (idx_1: number, idx_2: number, cell_shift?: Vec3) => string;
|
|
8
10
|
export declare function remap_bonds_after_deletion(bonds: readonly StructureBond[], deleted_indices: ReadonlySet<number>): StructureBond[];
|
|
@@ -39,12 +41,14 @@ export declare function apply_explicit_bond_metadata(structure: AnyStructure, bo
|
|
|
39
41
|
export declare function scale_and_offset_bond_matrix(transform_matrix: Float32Array, offset: number, radius_scale: number): Float32Array;
|
|
40
42
|
export declare function get_bond_render_matrices(bond: BondPair, bond_thickness: number): Float32Array[];
|
|
41
43
|
export declare function compute_bond_transform(pos_1: Vec3, pos_2: Vec3): Float32Array;
|
|
44
|
+
export declare const pack_cell_key: (x: number, y: number, z: number) => number;
|
|
42
45
|
export declare const BONDING_STRATEGIES: {
|
|
43
46
|
readonly electroneg_ratio: typeof electroneg_ratio;
|
|
44
47
|
readonly solid_angle: typeof solid_angle;
|
|
45
48
|
};
|
|
46
49
|
export type BondingStrategy = keyof typeof BONDING_STRATEGIES;
|
|
47
50
|
export type BondingAlgo = (typeof BONDING_STRATEGIES)[BondingStrategy];
|
|
51
|
+
export declare function compute_bonds(structure: AnyStructure, strategy: BondingStrategy, options?: Record<string, unknown>): BondPair[];
|
|
48
52
|
export declare function electroneg_ratio(structure: AnyStructure, { electronegativity_threshold, // Max electronegativity difference for bonding
|
|
49
53
|
max_distance_ratio, // Max distance as multiple of sum of covalent radii
|
|
50
54
|
min_bond_dist, // Minimum bond distance in Angstroms
|
|
@@ -52,7 +56,8 @@ metal_metal_penalty, // Strength penalty for metal-metal bonds
|
|
|
52
56
|
metal_nonmetal_bonus, // Strength bonus for metal-nonmetal bonds
|
|
53
57
|
similar_electronegativity_bonus, // Bonus for similar electronegativity
|
|
54
58
|
same_species_penalty, // Penalty for bonds between same element
|
|
55
|
-
strength_threshold,
|
|
59
|
+
strength_threshold, // Minimum bond strength to include in results
|
|
60
|
+
center_count, }?: {
|
|
56
61
|
electronegativity_threshold?: number | undefined;
|
|
57
62
|
max_distance_ratio?: number | undefined;
|
|
58
63
|
min_bond_dist?: number | undefined;
|
|
@@ -61,12 +66,14 @@ strength_threshold, }?: {
|
|
|
61
66
|
similar_electronegativity_bonus?: number | undefined;
|
|
62
67
|
same_species_penalty?: number | undefined;
|
|
63
68
|
strength_threshold?: number | undefined;
|
|
69
|
+
center_count?: number | undefined;
|
|
64
70
|
}): BondPair[];
|
|
65
|
-
export declare function solid_angle(structure: AnyStructure, { min_solid_angle, min_face_area, max_distance, min_bond_dist, strength_threshold, }?: {
|
|
71
|
+
export declare function solid_angle(structure: AnyStructure, { min_solid_angle, min_face_area, max_distance, min_bond_dist, strength_threshold, center_count, }?: {
|
|
66
72
|
min_solid_angle?: number | undefined;
|
|
67
73
|
min_face_area?: number | undefined;
|
|
68
74
|
max_distance?: number | undefined;
|
|
69
75
|
min_bond_dist?: number | undefined;
|
|
70
76
|
strength_threshold?: number | undefined;
|
|
77
|
+
center_count?: number | undefined;
|
|
71
78
|
}): BondPair[];
|
|
72
79
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Bonding algorithms for structure visualization
|
|
2
|
-
import { element_data } from '../element';
|
|
2
|
+
import { default as element_data } from '../element/data';
|
|
3
3
|
import * as math from '../math';
|
|
4
4
|
// Shared per-symbol element data lookup (also used by pbc.ts and polyhedra.ts)
|
|
5
5
|
export const element_lookup = new Map(element_data.map((el) => [el.symbol, el]));
|
|
@@ -10,6 +10,39 @@ export const get_majority_element = (site) => {
|
|
|
10
10
|
return null;
|
|
11
11
|
return site.species.reduce((max, spec) => (spec.occu > max.occu ? spec : max)).element;
|
|
12
12
|
};
|
|
13
|
+
// Large low-valent A-site cations whose coordination polyhedra (CN 8-12) tend to
|
|
14
|
+
// obscure the structural framework. VESTA-style figures draw the framework
|
|
15
|
+
// (e.g. TiO6 in BaTiO3, FeO6/PO4 in LiFePO4) and leave these as plain spheres.
|
|
16
|
+
// They still get polyhedra when they are the only qualifying cations (e.g. NaCl)
|
|
17
|
+
// or when force-included via `included_center_elements`. Shared by polyhedra.ts
|
|
18
|
+
// (vertex/center selection) and pbc.ts (phase-2 boundary completion) so the bond
|
|
19
|
+
// graph and the polyhedra it feeds stay consistent.
|
|
20
|
+
const SPECTATOR_CATEGORIES = new Set([`alkali metal`]);
|
|
21
|
+
const HEAVY_ALKALINE_EARTHS = new Set([`Ca`, `Sr`, `Ba`, `Ra`]);
|
|
22
|
+
export const is_spectator_center = (element) => SPECTATOR_CATEGORIES.has(element_lookup.get(element)?.category ?? ``) ||
|
|
23
|
+
HEAVY_ALKALINE_EARTHS.has(element);
|
|
24
|
+
// True if the composition contains a framework cation: a non-spectator element
|
|
25
|
+
// strictly less electronegative than the most electronegative element present
|
|
26
|
+
// (i.e. one that can coordinate the anions). When true, spectator A-site cations
|
|
27
|
+
// are hidden from coordination polyhedra (compute_polyhedra) and skipped by phase-2
|
|
28
|
+
// boundary completion (find_image_atoms) - sharing this keeps the bond graph and
|
|
29
|
+
// the polyhedra it feeds consistent. Purely ionic binaries (NaCl, Li2O) return
|
|
30
|
+
// false, so the spectator IS the framework and keeps its polyhedra/completions.
|
|
31
|
+
export function has_framework_potential(elements) {
|
|
32
|
+
const els = [...new Set(elements)]; // dedupe so callers can pass per-site element lists
|
|
33
|
+
let max_en = -Infinity;
|
|
34
|
+
for (const el of els) {
|
|
35
|
+
const en = element_lookup.get(el)?.electronegativity;
|
|
36
|
+
if (en != null && en > max_en)
|
|
37
|
+
max_en = en;
|
|
38
|
+
}
|
|
39
|
+
return els.some((el) => {
|
|
40
|
+
if (is_spectator_center(el))
|
|
41
|
+
return false;
|
|
42
|
+
const en = element_lookup.get(el)?.electronegativity;
|
|
43
|
+
return en != null && en < max_en;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
13
46
|
const is_zero_cell_shift = (cell_shift) => cell_shift === undefined || cell_shift.every((val) => val === 0);
|
|
14
47
|
const format_cell_shift = (cell_shift) => {
|
|
15
48
|
if (cell_shift === undefined || is_zero_cell_shift(cell_shift))
|
|
@@ -501,11 +534,22 @@ export function compute_bond_transform(pos_1, pos_2) {
|
|
|
501
534
|
1,
|
|
502
535
|
]);
|
|
503
536
|
}
|
|
537
|
+
// Build a BondPair between two sites (shared by electroneg_ratio and solid_angle)
|
|
538
|
+
const make_bond = (sites, idx_1, idx_2, bond_length, strength) => ({
|
|
539
|
+
pos_1: sites[idx_1].xyz,
|
|
540
|
+
pos_2: sites[idx_2].xyz,
|
|
541
|
+
site_idx_1: idx_1,
|
|
542
|
+
site_idx_2: idx_2,
|
|
543
|
+
bond_length,
|
|
544
|
+
strength,
|
|
545
|
+
transform_matrix: compute_bond_transform(sites[idx_1].xyz, sites[idx_2].xyz),
|
|
546
|
+
});
|
|
504
547
|
// Pack quantized cell coordinates into one integer key (exact for cell coords in
|
|
505
548
|
// [-512, 511], i.e. structures up to ~1000 cells per axis - far beyond any real
|
|
506
549
|
// case). Integer Map keys avoid per-lookup string building in the hot pair loop.
|
|
550
|
+
// Also used by pbc.ts for its phase-2 boundary-completion grid.
|
|
507
551
|
const CELL_OFFSET = 512;
|
|
508
|
-
const pack_cell_key = (x, y, z) => (x + CELL_OFFSET) * 1048576 + (y + CELL_OFFSET) * 1024 + (z + CELL_OFFSET);
|
|
552
|
+
export const pack_cell_key = (x, y, z) => (x + CELL_OFFSET) * 1048576 + (y + CELL_OFFSET) * 1024 + (z + CELL_OFFSET);
|
|
509
553
|
// Build spatial grid by dividing 3D space into cubic cells.
|
|
510
554
|
function build_spatial_grid(sites, cell_size) {
|
|
511
555
|
const grid = new Map();
|
|
@@ -520,24 +564,28 @@ function build_spatial_grid(sites, cell_size) {
|
|
|
520
564
|
return grid;
|
|
521
565
|
}
|
|
522
566
|
// Get all site indices in 3x3x3 cube of cells around position.
|
|
567
|
+
// Fills and returns a REUSED module-level array (valid until the next call):
|
|
568
|
+
// this runs once per bond center, so per-call allocations would dominate GC
|
|
569
|
+
// pressure when computing bonds for large supercells.
|
|
570
|
+
const scratch_neighbors = [];
|
|
523
571
|
function get_neighbors_from_grid(pos, grid, cell_size) {
|
|
524
572
|
const [cx, cy, cz] = [
|
|
525
573
|
Math.floor(pos[0] / cell_size),
|
|
526
574
|
Math.floor(pos[1] / cell_size),
|
|
527
575
|
Math.floor(pos[2] / cell_size),
|
|
528
576
|
];
|
|
529
|
-
|
|
577
|
+
scratch_neighbors.length = 0;
|
|
530
578
|
for (let dx = -1; dx <= 1; dx++) {
|
|
531
579
|
for (let dy = -1; dy <= 1; dy++) {
|
|
532
580
|
for (let dz = -1; dz <= 1; dz++) {
|
|
533
581
|
const cell = grid.get(pack_cell_key(cx + dx, cy + dy, cz + dz));
|
|
534
582
|
if (cell)
|
|
535
|
-
for (const
|
|
536
|
-
|
|
583
|
+
for (const site_idx of cell)
|
|
584
|
+
scratch_neighbors.push(site_idx);
|
|
537
585
|
}
|
|
538
586
|
}
|
|
539
587
|
}
|
|
540
|
-
return
|
|
588
|
+
return scratch_neighbors;
|
|
541
589
|
}
|
|
542
590
|
// Setup spatial decomposition for structures with >50 atoms.
|
|
543
591
|
function setup_spatial_grid(sites, cutoff) {
|
|
@@ -549,6 +597,23 @@ const get_candidates = (pos, sites, spatial) => spatial
|
|
|
549
597
|
? get_neighbors_from_grid(pos, spatial.grid, spatial.cell_size)
|
|
550
598
|
: Array.from({ length: sites.length }, (_, idx) => idx);
|
|
551
599
|
export const BONDING_STRATEGIES = { electroneg_ratio, solid_angle };
|
|
600
|
+
// Memo for the costly neighbor search: WeakMap keyed by structure (GC'd with it), each holding a
|
|
601
|
+
// per-signature (strategy + JSON options) map of results. The multi-side view's 4 panes share one
|
|
602
|
+
// search (identical inputs, one flush); the per-signature map also lets alternating
|
|
603
|
+
// strategies/options on the same structure reuse earlier results instead of thrashing one slot.
|
|
604
|
+
const bond_memo = new WeakMap();
|
|
605
|
+
export function compute_bonds(structure, strategy, options = {}) {
|
|
606
|
+
const sig = `${strategy}:${JSON.stringify(options)}`;
|
|
607
|
+
let by_sig = bond_memo.get(structure);
|
|
608
|
+
const cached = by_sig?.get(sig);
|
|
609
|
+
if (cached)
|
|
610
|
+
return cached;
|
|
611
|
+
const bonds = BONDING_STRATEGIES[strategy](structure, options);
|
|
612
|
+
if (!by_sig)
|
|
613
|
+
bond_memo.set(structure, (by_sig = new Map()));
|
|
614
|
+
by_sig.set(sig, bonds);
|
|
615
|
+
return bonds;
|
|
616
|
+
}
|
|
552
617
|
// Electronegativity-based bonding with chemical preferences.
|
|
553
618
|
// This algorithm considers electronegativity differences between atoms, metal/nonmetal
|
|
554
619
|
// properties, and distance to determine bond strength. Bonds are only created if the
|
|
@@ -561,7 +626,11 @@ metal_nonmetal_bonus = 1.5, // Strength bonus for metal-nonmetal bonds
|
|
|
561
626
|
similar_electronegativity_bonus = 1.2, // Bonus for similar electronegativity
|
|
562
627
|
same_species_penalty = 0.5, // Penalty for bonds between same element
|
|
563
628
|
strength_threshold = 0.3, // Minimum bond strength to include in results
|
|
564
|
-
|
|
629
|
+
// Only iterate the first `center_count` sites as bond centers (default: all).
|
|
630
|
+
// Coordination coloring sets this to the original-atom count so appended PBC image
|
|
631
|
+
// atoms are used as neighbors but not iterated as centers — identical coordination
|
|
632
|
+
// for the originals (by translational symmetry), far cheaper when images dominate.
|
|
633
|
+
center_count = Infinity, } = {}) {
|
|
565
634
|
const { sites } = structure;
|
|
566
635
|
if (sites.length < 2)
|
|
567
636
|
return [];
|
|
@@ -571,6 +640,7 @@ strength_threshold = 0.3, // Minimum bond strength to include in results
|
|
|
571
640
|
// millions of candidate pairs in large supercells, so object property chains
|
|
572
641
|
// and Map lookups are replaced with indexed array reads.
|
|
573
642
|
const n_sites = sites.length;
|
|
643
|
+
const n_center = Math.min(center_count, n_sites - 1);
|
|
574
644
|
const electronegs = new Float64Array(n_sites);
|
|
575
645
|
const radii = new Float64Array(n_sites); // 0 = no covalent radius known
|
|
576
646
|
const metal_flags = new Uint8Array(n_sites);
|
|
@@ -608,7 +678,7 @@ strength_threshold = 0.3, // Minimum bond strength to include in results
|
|
|
608
678
|
const max_cutoff = max_radius * 2 * max_distance_ratio;
|
|
609
679
|
const spatial = setup_spatial_grid(sites, max_cutoff);
|
|
610
680
|
const potential_bonds = [];
|
|
611
|
-
for (let idx_a = 0; idx_a <
|
|
681
|
+
for (let idx_a = 0; idx_a < n_center; idx_a++) {
|
|
612
682
|
const radius_a = radii[idx_a];
|
|
613
683
|
if (radius_a === 0)
|
|
614
684
|
continue; // no covalent radius -> no pairs (symmetric: idx_b skips too)
|
|
@@ -700,15 +770,7 @@ strength_threshold = 0.3, // Minimum bond strength to include in results
|
|
|
700
770
|
strength *= Math.exp(-(norm_dist / closest_dist_b - 1) / 0.5);
|
|
701
771
|
}
|
|
702
772
|
if (strength > strength_threshold) {
|
|
703
|
-
bonds.push(
|
|
704
|
-
pos_1: sites[site_idx_1].xyz,
|
|
705
|
-
pos_2: sites[site_idx_2].xyz,
|
|
706
|
-
site_idx_1,
|
|
707
|
-
site_idx_2,
|
|
708
|
-
bond_length: dist,
|
|
709
|
-
strength,
|
|
710
|
-
transform_matrix: compute_bond_transform(sites[site_idx_1].xyz, sites[site_idx_2].xyz),
|
|
711
|
-
});
|
|
773
|
+
bonds.push(make_bond(sites, site_idx_1, site_idx_2, dist, strength));
|
|
712
774
|
}
|
|
713
775
|
}
|
|
714
776
|
return apply_explicit_bond_metadata(structure, bonds);
|
|
@@ -718,7 +780,8 @@ strength_threshold = 0.3, // Minimum bond strength to include in results
|
|
|
718
780
|
// This algorithm computes bond strength based on the solid angle subtended by atoms
|
|
719
781
|
// and their distance penalty. Bonds are only created if the computed strength exceeds
|
|
720
782
|
// the strength_threshold parameter.
|
|
721
|
-
export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area = 0.05, max_distance = 5.0, min_bond_dist = 0.4, strength_threshold = 0.05,
|
|
783
|
+
export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area = 0.05, max_distance = 5.0, min_bond_dist = 0.4, strength_threshold = 0.05, center_count = Infinity, // see electroneg_ratio: limit bond centers to first N sites
|
|
784
|
+
} = {}) {
|
|
722
785
|
const { sites } = structure;
|
|
723
786
|
if (sites.length < 2)
|
|
724
787
|
return [];
|
|
@@ -726,7 +789,8 @@ export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area =
|
|
|
726
789
|
const min_dist_sq = min_bond_dist ** 2;
|
|
727
790
|
const max_dist_sq = max_distance ** 2;
|
|
728
791
|
const spatial = setup_spatial_grid(sites, max_distance);
|
|
729
|
-
|
|
792
|
+
const n_center = Math.min(center_count, sites.length - 1);
|
|
793
|
+
for (let idx_a = 0; idx_a < n_center; idx_a++) {
|
|
730
794
|
const [x1, y1, z1] = sites[idx_a].xyz;
|
|
731
795
|
const elem_a = get_majority_element(sites[idx_a]);
|
|
732
796
|
const radius_a = elem_a ? covalent_radii.get(elem_a) : undefined;
|
|
@@ -751,15 +815,7 @@ export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area =
|
|
|
751
815
|
const angle_strength = Math.min(bond_solid_angle / (4.0 * Math.PI), 1.0);
|
|
752
816
|
const strength = angle_strength * dist_penalty;
|
|
753
817
|
if (strength > strength_threshold) {
|
|
754
|
-
bonds.push(
|
|
755
|
-
pos_1: sites[idx_a].xyz,
|
|
756
|
-
pos_2: sites[idx_b].xyz,
|
|
757
|
-
site_idx_1: idx_a,
|
|
758
|
-
site_idx_2: idx_b,
|
|
759
|
-
bond_length: dist,
|
|
760
|
-
strength,
|
|
761
|
-
transform_matrix: compute_bond_transform(sites[idx_a].xyz, sites[idx_b].xyz),
|
|
762
|
-
});
|
|
818
|
+
bonds.push(make_bond(sites, idx_a, idx_b, dist, strength));
|
|
763
819
|
}
|
|
764
820
|
}
|
|
765
821
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type HistoryStacks<T> = [undo_stack: T[], redo_stack: T[]];
|
|
2
|
+
export declare function push_edit<T>([undo_stack]: HistoryStacks<T>, snapshot: T, max_history: number): HistoryStacks<T>;
|
|
3
|
+
export declare function step_history<T>([undo_stack, redo_stack]: HistoryStacks<T>, direction: `undo` | `redo`, current: T): {
|
|
4
|
+
stacks: HistoryStacks<T>;
|
|
5
|
+
restored: T;
|
|
6
|
+
} | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Pure undo/redo stack mechanics for Structure.svelte's edit-atoms history.
|
|
2
|
+
// Stacks are treated as immutable (updates return new arrays) so they work with
|
|
3
|
+
// $state.raw holders where only reassignment is reactive. Kept free of
|
|
4
|
+
// component state so the real logic (not a test-local mirror) is unit-testable.
|
|
5
|
+
// Record a new edit: push `snapshot` onto the undo stack (trimming to
|
|
6
|
+
// `max_history` entries) and invalidate the redo stack.
|
|
7
|
+
export function push_edit([undo_stack], snapshot, max_history) {
|
|
8
|
+
const trimmed = undo_stack.length >= max_history
|
|
9
|
+
? undo_stack.slice(undo_stack.length - max_history + 1)
|
|
10
|
+
: undo_stack;
|
|
11
|
+
return [[...trimmed, snapshot], []];
|
|
12
|
+
}
|
|
13
|
+
// Step the history in `direction`: pop that stack's top as the state to
|
|
14
|
+
// restore, pushing `current` onto the opposite stack. Returns null when there
|
|
15
|
+
// is nothing to step to (callers should snapshot `current` lazily by checking
|
|
16
|
+
// stack length first if snapshots are expensive).
|
|
17
|
+
export function step_history([undo_stack, redo_stack], direction, current) {
|
|
18
|
+
const source = direction === `undo` ? undo_stack : redo_stack;
|
|
19
|
+
const restored = source.at(-1);
|
|
20
|
+
if (restored === undefined)
|
|
21
|
+
return null;
|
|
22
|
+
const remaining = source.slice(0, -1);
|
|
23
|
+
const stacks = direction === `undo`
|
|
24
|
+
? [remaining, [...redo_stack, current]]
|
|
25
|
+
: [[...undo_stack, current], remaining];
|
|
26
|
+
return { stacks, restored };
|
|
27
|
+
}
|
|
@@ -7,6 +7,7 @@ export declare function has_color_property(mat: Material): mat is Material & {
|
|
|
7
7
|
export declare function extract_bond_color_for_instance(geometry: BufferGeometry, instance_idx: number): Color | null;
|
|
8
8
|
export declare function clean_geometry_for_export(geometry: BufferGeometry): void;
|
|
9
9
|
export declare function generate_mtl_content(scene: Scene): string;
|
|
10
|
+
export declare function convert_instanced_meshes_to_regular(scene: Scene): Scene;
|
|
10
11
|
export declare function create_structure_filename(structure: AnyStructure | undefined, extension: string): string;
|
|
11
12
|
export declare function structure_to_xyz_str(structure?: AnyStructure): string;
|
|
12
13
|
export declare function structure_to_cif_str(structure?: AnyStructure): string;
|
package/dist/structure/export.js
CHANGED
|
@@ -123,9 +123,10 @@ export function generate_mtl_content(scene) {
|
|
|
123
123
|
// Get diffuse color (main color)
|
|
124
124
|
if (has_color_property(mat)) {
|
|
125
125
|
const color = mat.color;
|
|
126
|
-
|
|
126
|
+
const fmt = (val) => val.toFixed(6);
|
|
127
|
+
lines.push(`Kd ${fmt(color.r)} ${fmt(color.g)} ${fmt(color.b)}`);
|
|
127
128
|
// Ambient is typically a fraction of diffuse
|
|
128
|
-
lines.push(`Ka ${(color.r * 0.2)
|
|
129
|
+
lines.push(`Ka ${fmt(color.r * 0.2)} ${fmt(color.g * 0.2)} ${fmt(color.b * 0.2)}`);
|
|
129
130
|
}
|
|
130
131
|
else {
|
|
131
132
|
// Default white if no color
|
|
@@ -157,7 +158,28 @@ function extract_material_color(mat) {
|
|
|
157
158
|
// Note: Threlte's InstancedMesh sets isInstancedMesh=true but type remains "Mesh"
|
|
158
159
|
// Type guard for InstancedMesh (Three.js uses isInstancedMesh property, not exposed in Object3D type)
|
|
159
160
|
const is_instanced_mesh = (obj) => obj.isInstancedMesh || obj.type === `InstancedMesh`;
|
|
160
|
-
|
|
161
|
+
// Resolve the export color for one instance of an InstancedMesh. Precedence:
|
|
162
|
+
// gradient bond midpoints (shader bonds), then per-instance colors on meshes
|
|
163
|
+
// flagged userData.per_instance_color (atoms/arrows keep a white base material
|
|
164
|
+
// and store real colors in the instanceColor buffer), then the shared material
|
|
165
|
+
// color (legacy threlte-instanced meshes carry an all-white instanceColor that
|
|
166
|
+
// must NOT win), then instanceColor as a last resort. null = keep default.
|
|
167
|
+
function resolve_instance_material_color(instanced_mesh, instance_idx, bond_colors, stored_color) {
|
|
168
|
+
const bond_color = bond_colors?.get(instance_idx);
|
|
169
|
+
if (bond_color)
|
|
170
|
+
return bond_color;
|
|
171
|
+
const { instanceColor } = instanced_mesh;
|
|
172
|
+
const per_instance = instanceColor
|
|
173
|
+
? new Color(instanceColor.getX(instance_idx), instanceColor.getY(instance_idx), instanceColor.getZ(instance_idx))
|
|
174
|
+
: null;
|
|
175
|
+
if (instanced_mesh.userData.per_instance_color && per_instance)
|
|
176
|
+
return per_instance;
|
|
177
|
+
if (stored_color)
|
|
178
|
+
return new Color(stored_color.r, stored_color.g, stored_color.b);
|
|
179
|
+
return per_instance;
|
|
180
|
+
}
|
|
181
|
+
// @internal exported only for tests - not part of the public API.
|
|
182
|
+
export function convert_instanced_meshes_to_regular(scene) {
|
|
161
183
|
// STEP 1: Collect material colors from ORIGINAL scene BEFORE cloning
|
|
162
184
|
// This is crucial because scene.clone() may not properly preserve Threlte's material colors
|
|
163
185
|
const material_colors = new Map();
|
|
@@ -244,24 +266,10 @@ function convert_instanced_meshes_to_regular(scene) {
|
|
|
244
266
|
roughness: 0.5,
|
|
245
267
|
});
|
|
246
268
|
new_material.name = `material_${mesh_idx}_${idx}`;
|
|
247
|
-
// Apply the correct color
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
new_material.color.copy(bond_color);
|
|
252
|
-
}
|
|
253
|
-
else if (stored_color) {
|
|
254
|
-
// Atom with shared material color
|
|
255
|
-
new_material.color.setRGB(stored_color.r, stored_color.g, stored_color.b);
|
|
256
|
-
}
|
|
257
|
-
else if (instanced_mesh.instanceColor) {
|
|
258
|
-
// Fallback: per-instance colors from instanceColor attribute
|
|
259
|
-
const color_r = instanced_mesh.instanceColor.getX(idx);
|
|
260
|
-
const color_g = instanced_mesh.instanceColor.getY(idx);
|
|
261
|
-
const color_b = instanced_mesh.instanceColor.getZ(idx);
|
|
262
|
-
new_material.color.setRGB(color_r, color_g, color_b);
|
|
263
|
-
}
|
|
264
|
-
// If no color found, material stays default white
|
|
269
|
+
// Apply the correct color (null = no color found, material stays default white)
|
|
270
|
+
const resolved_color = resolve_instance_material_color(instanced_mesh, idx, stored_bond_colors, stored_color);
|
|
271
|
+
if (resolved_color)
|
|
272
|
+
new_material.color.copy(resolved_color);
|
|
265
273
|
const mesh = new Mesh(cloned_geometry, new_material);
|
|
266
274
|
// Combine base transform with instance transform
|
|
267
275
|
const combined_matrix = new Matrix4();
|
|
@@ -372,9 +380,12 @@ export function structure_to_xyz_str(structure) {
|
|
|
372
380
|
const formula = get_electro_neg_formula(structure, true);
|
|
373
381
|
if (formula && formula !== `Unknown`)
|
|
374
382
|
comment_parts.push(formula);
|
|
383
|
+
const lattice_matrix = `lattice` in structure && structure.lattice?.matrix?.length === 3
|
|
384
|
+
? structure.lattice.matrix
|
|
385
|
+
: null;
|
|
375
386
|
// Include extended XYZ lattice information when available so round-trips preserve lattice
|
|
376
|
-
if (
|
|
377
|
-
const lattice_values =
|
|
387
|
+
if (lattice_matrix) {
|
|
388
|
+
const lattice_values = lattice_matrix
|
|
378
389
|
.flatMap((row) => row.map((value) => (Number.isFinite(value) ? value : 0).toFixed(8)))
|
|
379
390
|
.join(` `);
|
|
380
391
|
comment_parts.push(`Lattice="${lattice_values}"`);
|
|
@@ -382,9 +393,7 @@ export function structure_to_xyz_str(structure) {
|
|
|
382
393
|
const comment = comment_parts.length > 0 ? comment_parts.join(` `) : `Generated from structure`;
|
|
383
394
|
lines.push(comment);
|
|
384
395
|
// Cache converter for fractional→Cartesian (if lattice available)
|
|
385
|
-
const frac_to_cart =
|
|
386
|
-
? math.create_frac_to_cart(structure.lattice.matrix)
|
|
387
|
-
: null;
|
|
396
|
+
const frac_to_cart = lattice_matrix ? math.create_frac_to_cart(lattice_matrix) : null;
|
|
388
397
|
// Atom lines: element symbol followed by x, y, z coordinates
|
|
389
398
|
for (const site of structure.sites) {
|
|
390
399
|
const element_symbol = site_element(site);
|
|
@@ -536,11 +545,10 @@ export function structure_to_poscar_str(structure) {
|
|
|
536
545
|
lines.push(`1.0`); // Scale factor (1.0 for direct coordinates)
|
|
537
546
|
const lattice = structure.lattice;
|
|
538
547
|
if (lattice.matrix && Array.isArray(lattice.matrix) && lattice.matrix.length >= 3) {
|
|
539
|
-
//
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
lines.push(`${matrix[2][0].toFixed(8)} ${matrix[2][1].toFixed(8)} ${matrix[2][2].toFixed(8)}`);
|
|
548
|
+
// One line per lattice vector, exactly 3 components at 8-decimal fixed precision
|
|
549
|
+
for (const vec of lattice.matrix.slice(0, 3)) {
|
|
550
|
+
lines.push([vec[0], vec[1], vec[2]].map((coord) => coord.toFixed(8)).join(` `));
|
|
551
|
+
}
|
|
544
552
|
}
|
|
545
553
|
else {
|
|
546
554
|
throw new Error(`No valid lattice matrix for POSCAR export`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function is_structure_file(filename: string): boolean;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CONFIG_DIRS_REGEX, STRUCT_KEYWORDS_REGEX, STRUCT_KEYWORDS_STRICT_REGEX, STRUCTURE_EXTENSIONS_REGEX, TRAJ_KEYWORDS_REGEX, VASP_FILES_REGEX, } from '../constants';
|
|
2
|
+
import { strip_compression_extensions } from '../io/decompress';
|
|
3
|
+
// Filename-only detection lives apart from the parsers so lightweight callers
|
|
4
|
+
// (desktop recents, file pickers) do not load YAML, structure math, and element
|
|
5
|
+
// data just to choose an icon.
|
|
6
|
+
export function is_structure_file(filename) {
|
|
7
|
+
const name = strip_compression_extensions(filename);
|
|
8
|
+
if (/\.(?:traj|xtc|h5|hdf5)$/i.test(name) || /xdatcar/i.test(name))
|
|
9
|
+
return false;
|
|
10
|
+
if (STRUCTURE_EXTENSIONS_REGEX.test(name) || VASP_FILES_REGEX.test(name))
|
|
11
|
+
return true;
|
|
12
|
+
if (/\.(?:xyz|extxyz)$/i.test(name))
|
|
13
|
+
return !TRAJ_KEYWORDS_REGEX.test(name);
|
|
14
|
+
if (/\.(?:yaml|yml|xml)$/i.test(name) && STRUCT_KEYWORDS_REGEX.test(name))
|
|
15
|
+
return true;
|
|
16
|
+
if (/\.json$/i.test(name) &&
|
|
17
|
+
STRUCT_KEYWORDS_STRICT_REGEX.test(name) &&
|
|
18
|
+
!TRAJ_KEYWORDS_REGEX.test(name) &&
|
|
19
|
+
!CONFIG_DIRS_REGEX.test(name))
|
|
20
|
+
return true;
|
|
21
|
+
return false;
|
|
22
|
+
}
|