matterviz 0.3.7 → 0.4.1
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/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +1 -1
- package/dist/api/optimade.js +32 -26
- package/dist/app.css +0 -3
- package/dist/brillouin/BrillouinZone.svelte +76 -148
- package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
- package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
- package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +89 -90
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +3 -1
- package/dist/chempot-diagram/chempot-worker.js +2 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +4 -4
- package/dist/chempot-diagram/compute.js +20 -20
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.js +8 -7
- package/dist/composition/FormulaFilter.svelte +18 -11
- package/dist/composition/PieChart.svelte +11 -10
- package/dist/composition/chem-sys.d.ts +8 -0
- package/dist/composition/chem-sys.js +86 -0
- package/dist/composition/format.js +7 -4
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.d.ts +0 -1
- package/dist/composition/parse.js +41 -31
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +8 -10
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +106 -185
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +179 -683
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +183 -687
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +88 -7
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +36 -175
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/GasPressureControls.svelte +4 -4
- package/dist/convex-hull/TemperatureSlider.svelte +2 -2
- package/dist/convex-hull/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
- package/dist/convex-hull/demo-temperature.d.ts +1 -1
- package/dist/convex-hull/demo-temperature.js +20 -22
- package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
- package/dist/convex-hull/gas-thermodynamics.js +22 -30
- package/dist/convex-hull/helpers.d.ts +42 -7
- package/dist/convex-hull/helpers.js +171 -78
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +10 -8
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +136 -960
- package/dist/convex-hull/types.d.ts +13 -5
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +27 -34
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/element/BohrAtom.svelte +2 -1
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +18 -0
- package/dist/feedback/DragOverlay.svelte +3 -1
- package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
- package/dist/feedback/StatusMessage.svelte +13 -3
- package/dist/fermi-surface/FermiSlice.svelte +13 -5
- package/dist/fermi-surface/FermiSurface.svelte +78 -151
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
- package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
- package/dist/fermi-surface/compute.js +67 -66
- package/dist/fermi-surface/export.js +6 -16
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +71 -79
- package/dist/fermi-surface/types.d.ts +3 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +3 -2
- package/dist/heatmap-matrix/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +166 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.js +5 -4
- package/dist/io/export.d.ts +9 -5
- package/dist/io/export.js +77 -51
- package/dist/io/fetch.d.ts +2 -1
- package/dist/io/fetch.js +5 -1
- package/dist/io/file-drop.d.ts +8 -1
- package/dist/io/file-drop.js +48 -36
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +10 -0
- package/dist/io/types.d.ts +13 -0
- package/dist/io/url-drop.js +64 -33
- package/dist/isosurface/parse.js +52 -51
- package/dist/isosurface/slice.js +5 -4
- package/dist/isosurface/types.js +1 -1
- package/dist/keyboard.d.ts +3 -0
- package/dist/keyboard.js +23 -0
- package/dist/labels.d.ts +1 -1
- package/dist/labels.js +9 -8
- package/dist/layout/FullscreenButton.svelte +33 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +8 -14
- package/dist/layout/PropertyFilter.svelte +3 -2
- package/dist/layout/SettingsSection.svelte +1 -1
- package/dist/layout/ViewerChrome.svelte +116 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +37 -0
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/layout/json-tree/JsonNode.svelte +1 -1
- package/dist/layout/json-tree/JsonTree.svelte +2 -2
- package/dist/layout/json-tree/utils.js +5 -4
- package/dist/marching-cubes.js +8 -13
- package/dist/math.d.ts +12 -4
- package/dist/math.js +42 -30
- package/dist/overlays/DraggablePane.svelte +4 -4
- package/dist/overlays/index.d.ts +4 -0
- package/dist/periodic-table/PeriodicTable.svelte +27 -15
- package/dist/periodic-table/PropertySelect.svelte +1 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
- package/dist/phase-diagram/build-diagram.js +2 -2
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/phase-diagram/parse.js +6 -5
- package/dist/phase-diagram/types.d.ts +1 -1
- package/dist/phase-diagram/utils.d.ts +3 -3
- package/dist/phase-diagram/utils.js +8 -12
- package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
- package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
- package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
- package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
- package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
- package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
- package/dist/plot/bar/data.d.ts +40 -0
- package/dist/plot/bar/data.js +154 -0
- package/dist/plot/bar/geometry.d.ts +39 -0
- package/dist/plot/bar/geometry.js +60 -0
- package/dist/plot/bar/index.d.ts +3 -0
- package/dist/plot/bar/index.js +3 -0
- package/dist/plot/box/BoxPlot.svelte +1292 -0
- package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
- package/dist/plot/box/BoxPlotControls.svelte +109 -0
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
- package/dist/plot/box/Violin.svelte +14 -0
- package/dist/plot/box/Violin.svelte.d.ts +70 -0
- package/dist/plot/box/box-plot.d.ts +56 -0
- package/dist/plot/box/box-plot.js +129 -0
- package/dist/plot/box/index.d.ts +5 -0
- package/dist/plot/box/index.js +5 -0
- package/dist/plot/box/kde.d.ts +17 -0
- package/dist/plot/box/kde.js +160 -0
- package/dist/plot/box/quantile.d.ts +3 -0
- package/dist/plot/box/quantile.js +53 -0
- package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
- package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
- package/dist/plot/core/axis-utils.d.ts +46 -0
- package/dist/plot/core/axis-utils.js +110 -0
- package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
- package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
- package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
- package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
- package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
- package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
- package/dist/plot/core/components/ControlPane.svelte +46 -0
- package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
- package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
- package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
- package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
- package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
- package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
- package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
- package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
- package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
- package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
- package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
- package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
- package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
- package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
- package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
- package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
- package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
- package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
- package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
- package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
- package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
- package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
- package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
- package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
- package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
- package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
- package/dist/plot/core/components/index.d.ts +17 -0
- package/dist/plot/core/components/index.js +17 -0
- package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
- package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
- package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
- package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
- package/dist/plot/core/fill-utils.d.ts +34 -0
- package/dist/plot/core/fill-utils.js +391 -0
- package/dist/plot/core/index.d.ts +10 -0
- package/dist/plot/core/index.js +11 -0
- package/dist/plot/core/interactions.d.ts +39 -0
- package/dist/plot/core/interactions.js +209 -0
- package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
- package/dist/plot/{layout.js → core/layout.js} +16 -8
- package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
- package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
- package/dist/plot/core/scales.d.ts +40 -0
- package/dist/plot/{scales.js → core/scales.js} +94 -93
- package/dist/plot/core/svg.d.ts +3 -0
- package/dist/plot/core/svg.js +41 -0
- package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
- package/dist/plot/{types.js → core/types.js} +1 -1
- package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
- package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
- package/dist/plot/core/utils/series-visibility.d.ts +26 -0
- package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
- package/dist/plot/core/utils.d.ts +12 -0
- package/dist/plot/core/utils.js +27 -0
- package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
- package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
- package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
- package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
- package/dist/plot/histogram/index.d.ts +2 -0
- package/dist/plot/histogram/index.js +2 -0
- package/dist/plot/index.d.ts +8 -41
- package/dist/plot/index.js +10 -39
- package/dist/plot/sankey/Sankey.svelte +697 -0
- package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
- package/dist/plot/sankey/SankeyControls.svelte +98 -0
- package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
- package/dist/plot/sankey/index.d.ts +4 -0
- package/dist/plot/sankey/index.js +3 -0
- package/dist/plot/sankey/sankey-types.d.ts +42 -0
- package/dist/plot/sankey/sankey-types.js +4 -0
- package/dist/plot/sankey/sankey.d.ts +52 -0
- package/dist/plot/sankey/sankey.js +189 -0
- package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
- package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
- package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
- package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
- package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
- package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
- package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
- package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
- package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
- package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
- package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
- package/dist/plot/scatter/index.d.ts +7 -0
- package/dist/plot/scatter/index.js +5 -0
- package/dist/plot/scatter/scatter-data.d.ts +19 -0
- package/dist/plot/scatter/scatter-data.js +212 -0
- package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
- package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
- package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
- package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
- package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
- package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
- package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
- package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
- package/dist/plot/scatter-3d/index.d.ts +4 -0
- package/dist/plot/scatter-3d/index.js +4 -0
- package/dist/plot/sunburst/Sunburst.svelte +1041 -0
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
- package/dist/plot/sunburst/SunburstControls.svelte +200 -0
- package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
- package/dist/plot/sunburst/index.d.ts +4 -0
- package/dist/plot/sunburst/index.js +4 -0
- package/dist/plot/sunburst/render.d.ts +34 -0
- package/dist/plot/sunburst/render.js +122 -0
- package/dist/plot/sunburst/sunburst.d.ts +62 -0
- package/dist/plot/sunburst/sunburst.js +269 -0
- package/dist/rdf/RdfPlot.svelte +2 -1
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +11 -24
- package/dist/sanitize.js +14 -3
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +14 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +79 -3
- package/dist/settings.js +321 -1
- package/dist/spectral/Bands.svelte +47 -36
- package/dist/spectral/Bands.svelte.d.ts +6 -6
- package/dist/spectral/BandsAndDos.svelte +23 -25
- package/dist/spectral/BrillouinBandsDos.svelte +42 -30
- package/dist/spectral/Dos.svelte +15 -23
- package/dist/spectral/Dos.svelte.d.ts +4 -3
- package/dist/spectral/helpers.d.ts +8 -6
- package/dist/spectral/helpers.js +137 -65
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +0 -6
- package/dist/structure/Arrow.svelte +2 -4
- package/dist/structure/AtomLegend.svelte +8 -9
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CanvasTooltip.svelte +1 -0
- package/dist/structure/CellSelect.svelte +12 -5
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Cylinder.svelte +12 -8
- package/dist/structure/Cylinder.svelte.d.ts +4 -1
- package/dist/structure/Lattice.svelte +2 -2
- package/dist/structure/Structure.svelte +365 -423
- package/dist/structure/Structure.svelte.d.ts +5 -15
- package/dist/structure/StructureControls.svelte +217 -2
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +54 -156
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +10 -9
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
- package/dist/structure/StructureScene.svelte +376 -208
- package/dist/structure/StructureScene.svelte.d.ts +22 -20
- package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
- package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +17 -22
- package/dist/structure/bond-order-perception.js +3 -5
- package/dist/structure/bonding.d.ts +4 -0
- package/dist/structure/bonding.js +134 -63
- package/dist/structure/export.d.ts +24 -4
- package/dist/structure/export.js +89 -143
- package/dist/structure/index.d.ts +4 -4
- package/dist/structure/index.js +3 -3
- package/dist/structure/measure.d.ts +3 -2
- package/dist/structure/measure.js +6 -5
- package/dist/structure/parse.d.ts +3 -2
- package/dist/structure/parse.js +419 -438
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +1 -1
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +190 -13
- package/dist/structure/polyhedra.d.ts +41 -0
- package/dist/structure/polyhedra.js +602 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.js +3 -2
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +354 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +113 -8
- package/dist/symmetry/WyckoffTable.svelte +68 -7
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +7 -14
- package/dist/symmetry/index.d.ts +14 -4
- package/dist/symmetry/index.js +291 -72
- package/dist/symmetry/spacegroups.d.ts +12 -1
- package/dist/symmetry/spacegroups.js +63 -14
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +66 -25
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/index.d.ts +1 -3
- package/dist/table/index.js +1 -1
- package/dist/theme/index.js +8 -8
- package/dist/tooltip/KCoords.svelte +45 -0
- package/dist/tooltip/KCoords.svelte.d.ts +8 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +123 -100
- package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
- package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +17 -37
- package/dist/trajectory/format-detect.d.ts +1 -1
- package/dist/trajectory/format-detect.js +27 -19
- package/dist/trajectory/frame-reader.d.ts +0 -1
- package/dist/trajectory/frame-reader.js +63 -162
- package/dist/trajectory/helpers.d.ts +10 -2
- package/dist/trajectory/helpers.js +56 -36
- package/dist/trajectory/index.js +1 -1
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -0
- package/dist/trajectory/parse/hdf5.js +1 -1
- package/dist/trajectory/parse/index.d.ts +1 -1
- package/dist/trajectory/parse/index.js +65 -105
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +8 -6
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +38 -18
- package/dist/trajectory/parse/xyz.d.ts +13 -1
- package/dist/trajectory/parse/xyz.js +102 -94
- package/dist/trajectory/plotting.d.ts +1 -2
- package/dist/trajectory/plotting.js +16 -113
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +7 -5
- package/dist/xrd/XrdPlot.svelte +16 -30
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/calc-xrd.js +18 -20
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.js +2 -2
- package/package.json +43 -26
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/PlotControls.svelte.d.ts +0 -4
- package/dist/plot/axis-utils.d.ts +0 -19
- package/dist/plot/axis-utils.js +0 -78
- package/dist/plot/defaults.d.ts +0 -19
- package/dist/plot/defaults.js +0 -9
- package/dist/plot/fill-utils.d.ts +0 -46
- package/dist/plot/fill-utils.js +0 -322
- package/dist/plot/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/hover-lock.svelte.js +0 -46
- package/dist/plot/interactions.d.ts +0 -12
- package/dist/plot/interactions.js +0 -101
- package/dist/plot/scales.d.ts +0 -48
- package/dist/plot/svg.d.ts +0 -1
- package/dist/plot/svg.js +0 -11
- package/dist/plot/utils/series-visibility.d.ts +0 -15
- package/dist/plot/utils.d.ts +0 -1
- package/dist/plot/utils.js +0 -14
- /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
- /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
|
@@ -9,14 +9,8 @@
|
|
|
9
9
|
} from '../colors'
|
|
10
10
|
import { normalize_show_controls } from '../controls'
|
|
11
11
|
import { sanitize_html } from '../sanitize'
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
set_fullscreen_bg,
|
|
16
|
-
setup_fullscreen_effect,
|
|
17
|
-
toggle_fullscreen,
|
|
18
|
-
} from '../layout'
|
|
19
|
-
import { ColorBar, PlotTooltip } from '../plot'
|
|
12
|
+
import { Spinner } from '../feedback'
|
|
13
|
+
import { ColorBar } from '../plot'
|
|
20
14
|
import { create_pulse_animation } from '../effects.svelte'
|
|
21
15
|
import { DEFAULTS } from '../settings'
|
|
22
16
|
import type { AnyStructure } from '../structure'
|
|
@@ -25,38 +19,41 @@
|
|
|
25
19
|
compute_4d_coords,
|
|
26
20
|
TETRAHEDRON_VERTICES,
|
|
27
21
|
} from './barycentric-coords'
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import ConvexHullTooltip from './ConvexHullTooltip.svelte'
|
|
22
|
+
import { create_canvas_interactions } from './canvas-interactions.svelte'
|
|
23
|
+
import ConvexHullChrome from './ConvexHullChrome.svelte'
|
|
31
24
|
import GasPressureControls from './GasPressureControls.svelte'
|
|
32
25
|
import * as helpers from './helpers'
|
|
26
|
+
import { create_hull_data_pipeline } from './hull-state.svelte'
|
|
33
27
|
import type { BaseConvexHullProps, Hull3DProps } from './index'
|
|
34
28
|
import { CONVEX_HULL_STYLE, default_controls, default_hull_config } from './index'
|
|
35
|
-
import StructurePopup from './StructurePopup.svelte'
|
|
36
29
|
import TemperatureSlider from './TemperatureSlider.svelte'
|
|
37
30
|
import type { Point4D } from './thermodynamics'
|
|
38
31
|
import * as thermo from './thermodynamics'
|
|
39
32
|
import type {
|
|
40
33
|
ConvexHullEntry,
|
|
41
34
|
HighlightStyle,
|
|
42
|
-
HoverData3D,
|
|
43
35
|
HullFaceColorMode,
|
|
36
|
+
PhaseData,
|
|
44
37
|
} from './types'
|
|
38
|
+
import { MAGNETIC_ORDERING_CATEGORY } from './types'
|
|
45
39
|
import { compute_hull_stability } from './helpers'
|
|
46
40
|
|
|
47
41
|
let {
|
|
48
42
|
entries = [],
|
|
49
43
|
controls = {},
|
|
50
44
|
config = {},
|
|
45
|
+
show_controls,
|
|
51
46
|
on_point_click,
|
|
52
47
|
on_point_hover,
|
|
53
48
|
fullscreen = $bindable(DEFAULTS.convex_hull.quaternary.fullscreen),
|
|
54
|
-
|
|
49
|
+
fullscreen_toggle = true,
|
|
55
50
|
enable_info_pane = true,
|
|
56
51
|
wrapper = $bindable(),
|
|
57
52
|
label_threshold = 50,
|
|
58
53
|
show_stable = $bindable(DEFAULTS.convex_hull.quaternary.show_stable),
|
|
59
54
|
show_unstable = $bindable(DEFAULTS.convex_hull.quaternary.show_unstable),
|
|
55
|
+
entry_category = MAGNETIC_ORDERING_CATEGORY,
|
|
56
|
+
hidden_categories = $bindable([]),
|
|
60
57
|
show_hull_faces = $bindable(DEFAULTS.convex_hull.quaternary.show_hull_faces),
|
|
61
58
|
hull_face_opacity = $bindable(DEFAULTS.convex_hull.quaternary.hull_face_opacity),
|
|
62
59
|
hull_face_color_mode = $bindable(
|
|
@@ -68,7 +65,7 @@
|
|
|
68
65
|
DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName,
|
|
69
66
|
),
|
|
70
67
|
info_pane_open = $bindable(DEFAULTS.convex_hull.quaternary.info_pane_open),
|
|
71
|
-
|
|
68
|
+
controls_open = $bindable(DEFAULTS.convex_hull.quaternary.legend_pane_open),
|
|
72
69
|
max_hull_dist_show_phases = $bindable(
|
|
73
70
|
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
74
71
|
),
|
|
@@ -104,7 +101,7 @@
|
|
|
104
101
|
} = $props()
|
|
105
102
|
|
|
106
103
|
const merged_controls = $derived({ ...default_controls, ...controls })
|
|
107
|
-
const controls_config = $derived(normalize_show_controls(
|
|
104
|
+
const controls_config = $derived(normalize_show_controls(show_controls))
|
|
108
105
|
const merged_config = $derived({
|
|
109
106
|
...default_hull_config,
|
|
110
107
|
...config,
|
|
@@ -117,87 +114,36 @@
|
|
|
117
114
|
$effect(() => watch_dark_mode((dark) => dark_mode = dark))
|
|
118
115
|
const text_color = $derived(helpers.get_canvas_text_color(dark_mode))
|
|
119
116
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const {
|
|
146
|
-
entries: gas_corrected_entries,
|
|
147
|
-
analysis: gas_analysis,
|
|
148
|
-
merged_config: merged_gas_config,
|
|
149
|
-
} = $derived(
|
|
150
|
-
helpers.get_gas_corrected_entries(
|
|
151
|
-
temp_filtered_entries,
|
|
152
|
-
gas_config,
|
|
153
|
-
gas_pressures,
|
|
154
|
-
temperature ?? helpers.DEFAULT_GAS_TEMP,
|
|
155
|
-
),
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
let { // Compute energy mode information
|
|
159
|
-
has_precomputed_e_form,
|
|
160
|
-
has_precomputed_hull,
|
|
161
|
-
can_compute_e_form,
|
|
162
|
-
can_compute_hull,
|
|
163
|
-
energy_mode,
|
|
164
|
-
unary_refs,
|
|
165
|
-
} = $derived(
|
|
166
|
-
helpers.compute_energy_mode_info(
|
|
167
|
-
gas_corrected_entries,
|
|
168
|
-
thermo.find_lowest_energy_unary_refs,
|
|
169
|
-
energy_source_mode,
|
|
170
|
-
),
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
const effective_entries = $derived(
|
|
174
|
-
helpers.get_effective_entries(
|
|
175
|
-
gas_corrected_entries,
|
|
176
|
-
energy_mode,
|
|
177
|
-
unary_refs,
|
|
178
|
-
thermo.compute_e_form_per_atom,
|
|
179
|
-
),
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
// Process convex hull data with unified PhaseData interface using effective entries
|
|
183
|
-
const pd_data = $derived(thermo.process_hull_entries(effective_entries))
|
|
184
|
-
|
|
185
|
-
// Pre-compute polymorph stats once for O(1) tooltip lookups
|
|
186
|
-
const polymorph_stats_map = $derived(
|
|
187
|
-
helpers.compute_all_polymorph_stats(effective_entries),
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
const elements = $derived.by(() => {
|
|
191
|
-
if (pd_data.elements.length > 4) {
|
|
192
|
-
console.error(
|
|
193
|
-
`ConvexHull4D: Dataset contains ${pd_data.elements.length} elements, but quaternary diagrams require exactly 4. Found: [${
|
|
194
|
-
pd_data.elements.join(`, `)
|
|
195
|
-
}]`,
|
|
196
|
-
)
|
|
197
|
-
return []
|
|
198
|
-
}
|
|
199
|
-
return pd_data.elements
|
|
117
|
+
// Shared reactive data pipeline (temperature → gas → energy mode → hull data → threshold)
|
|
118
|
+
// Explicit generic breaks the circular type inference through the all_enriched_entries thunk
|
|
119
|
+
const hull_data = create_hull_data_pipeline<ConvexHullEntry>({
|
|
120
|
+
dim: 4,
|
|
121
|
+
entries: () => entries,
|
|
122
|
+
temperature: () => temperature,
|
|
123
|
+
interpolate_temperature: () => interpolate_temperature,
|
|
124
|
+
max_interpolation_gap: () => max_interpolation_gap,
|
|
125
|
+
gas_config: () => gas_config,
|
|
126
|
+
gas_pressures: () => gas_pressures,
|
|
127
|
+
energy_source_mode: () => energy_source_mode,
|
|
128
|
+
all_enriched_entries: () => all_enriched_entries,
|
|
129
|
+
max_hull_dist_show_phases: () => max_hull_dist_show_phases,
|
|
130
|
+
show_stable: () => show_stable,
|
|
131
|
+
show_unstable: () => show_unstable,
|
|
132
|
+
entry_category: () => entry_category,
|
|
133
|
+
hidden_categories: () => hidden_categories,
|
|
134
|
+
// Always include stable entries and elemental reference points
|
|
135
|
+
keep_plot_entry: (entry, max_dist) =>
|
|
136
|
+
helpers.entry_is_stable(entry) ||
|
|
137
|
+
(typeof entry.e_above_hull === `number` && entry.e_above_hull <= max_dist),
|
|
138
|
+
set_temperature: (next_temp) => temperature = next_temp,
|
|
139
|
+
set_max_hull_dist_show_phases: (value) => max_hull_dist_show_phases = value,
|
|
140
|
+
set_stable_entries: (value) => stable_entries = value,
|
|
141
|
+
set_unstable_entries: (value) => unstable_entries = value,
|
|
200
142
|
})
|
|
143
|
+
const merged_gas_config = $derived(hull_data.merged_gas_config)
|
|
144
|
+
const pd_data = $derived(hull_data.pd_data)
|
|
145
|
+
const elements = $derived(hull_data.elements)
|
|
146
|
+
const plot_entries = $derived(hull_data.plot_entries)
|
|
201
147
|
|
|
202
148
|
// Compute 4D hull for visualization (always compute when we have formation energies)
|
|
203
149
|
const hull_4d = $derived.by(() => {
|
|
@@ -234,11 +180,12 @@
|
|
|
234
180
|
})
|
|
235
181
|
|
|
236
182
|
// Enrich coords with e_above_hull (before filtering)
|
|
237
|
-
|
|
183
|
+
// Explicit return type breaks circular type inference with the hull_data pipeline
|
|
184
|
+
const all_enriched_entries = $derived.by((): ConvexHullEntry[] => {
|
|
238
185
|
if (elements.length !== 4) return []
|
|
239
186
|
try {
|
|
240
187
|
const coords = compute_4d_coords(pd_data.entries, elements)
|
|
241
|
-
if (energy_mode !== `on-the-fly` || hull_4d.length === 0) return coords
|
|
188
|
+
if (hull_data.energy_mode !== `on-the-fly` || hull_4d.length === 0) return coords
|
|
242
189
|
|
|
243
190
|
// Build 4D points, tracking original indices for mapping hull distances back
|
|
244
191
|
const valid = coords.flatMap((entry, idx) => {
|
|
@@ -267,51 +214,8 @@
|
|
|
267
214
|
}
|
|
268
215
|
})
|
|
269
216
|
|
|
270
|
-
// Auto threshold: show all for few entries, use default for many, interpolate between
|
|
271
|
-
const max_hull_dist_in_data = $derived(
|
|
272
|
-
helpers.calc_max_hull_dist_in_data(all_enriched_entries),
|
|
273
|
-
)
|
|
274
|
-
const auto_default_threshold = $derived(helpers.compute_auto_hull_dist_threshold(
|
|
275
|
-
all_enriched_entries.length,
|
|
276
|
-
max_hull_dist_in_data,
|
|
277
|
-
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
278
|
-
))
|
|
279
|
-
|
|
280
|
-
const next_auto_threshold = helpers.auto_threshold_reset(
|
|
281
|
-
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
282
|
-
)
|
|
283
|
-
$effect(() => {
|
|
284
|
-
max_hull_dist_show_phases = next_auto_threshold(
|
|
285
|
-
entries,
|
|
286
|
-
max_hull_dist_show_phases,
|
|
287
|
-
auto_default_threshold,
|
|
288
|
-
) ?? max_hull_dist_show_phases
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
// Filter by threshold; visibility is a view predicate, not entry state.
|
|
292
|
-
const plot_entries = $derived(
|
|
293
|
-
all_enriched_entries.filter((entry) => {
|
|
294
|
-
// Always include stable entries and elemental reference points
|
|
295
|
-
if (helpers.entry_is_stable(entry)) return true
|
|
296
|
-
return typeof entry.e_above_hull === `number` &&
|
|
297
|
-
entry.e_above_hull <= max_hull_dist_show_phases
|
|
298
|
-
}),
|
|
299
|
-
)
|
|
300
|
-
const visible_entries = $derived(helpers.visible_entries(
|
|
301
|
-
plot_entries,
|
|
302
|
-
show_stable,
|
|
303
|
-
show_unstable,
|
|
304
|
-
))
|
|
305
|
-
|
|
306
|
-
// Stable and unstable entries exposed as bindable props
|
|
307
|
-
$effect(() => {
|
|
308
|
-
stable_entries = plot_entries.filter(helpers.entry_is_stable)
|
|
309
|
-
unstable_entries = plot_entries.filter(helpers.entry_is_unstable)
|
|
310
|
-
})
|
|
311
|
-
|
|
312
217
|
let canvas: HTMLCanvasElement | undefined = undefined
|
|
313
218
|
let ctx: CanvasRenderingContext2D | null = null
|
|
314
|
-
let frame_id = 0 // Performance optimization
|
|
315
219
|
|
|
316
220
|
// Camera state - following Materials Project's 3D camera setup
|
|
317
221
|
let camera = $state({
|
|
@@ -322,43 +226,60 @@
|
|
|
322
226
|
center_y: 20, // Slight offset to avoid legend overlap
|
|
323
227
|
})
|
|
324
228
|
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
229
|
+
// Shared canvas-interaction scaffold (mouse/keyboard handlers, hover/drag/popup
|
|
230
|
+
// state, canvas sizing, render scheduler). Rotation math + keydown actions stay local.
|
|
231
|
+
const interactions = create_canvas_interactions({
|
|
232
|
+
wheel_clamp: [1.0, 15],
|
|
233
|
+
fullscreen_bg_var: `--hull-4d-bg-fullscreen`,
|
|
234
|
+
canvas: () => canvas,
|
|
235
|
+
wrapper: () => wrapper,
|
|
236
|
+
ctx: () => ctx,
|
|
237
|
+
set_ctx: (context) => ctx = context,
|
|
238
|
+
set_canvas_dims: (dims) => canvas_dims = dims,
|
|
239
|
+
visible_entries: () => hull_data.visible_entries,
|
|
240
|
+
plot_entries: () => plot_entries,
|
|
241
|
+
selected_entry: () => selected_entry,
|
|
242
|
+
set_selected_entry: (entry) => selected_entry = entry,
|
|
243
|
+
fullscreen: () => fullscreen,
|
|
244
|
+
enable_click_selection: () => enable_click_selection,
|
|
245
|
+
enable_structure_preview: () => enable_structure_preview,
|
|
246
|
+
on_point_click: () => on_point_click,
|
|
247
|
+
on_point_hover: () => on_point_hover,
|
|
248
|
+
on_file_drop: () => on_file_drop,
|
|
249
|
+
entry_category: () => entry_category,
|
|
250
|
+
zoom: () => camera.zoom,
|
|
251
|
+
set_zoom: (zoom) => camera.zoom = zoom,
|
|
252
|
+
project_point: project_3d_point,
|
|
253
|
+
extract_structure: extract_structure_from_entry,
|
|
254
|
+
render_frame,
|
|
255
|
+
on_drag: (dx, dy, panning) => {
|
|
256
|
+
if (panning) {
|
|
257
|
+
camera.center_x += dx
|
|
258
|
+
camera.center_y += dy
|
|
259
|
+
} else {
|
|
260
|
+
camera.rotation_y += dx * 0.005
|
|
261
|
+
camera.rotation_x = Math.max(
|
|
262
|
+
-Math.PI / 3,
|
|
263
|
+
Math.min(Math.PI / 3, camera.rotation_x - dy * 0.005),
|
|
264
|
+
)
|
|
359
265
|
}
|
|
360
|
-
}
|
|
266
|
+
},
|
|
267
|
+
// Reset pan center when entering/exiting fullscreen
|
|
268
|
+
on_fullscreen_change: () => {
|
|
269
|
+
camera.center_x = 0
|
|
270
|
+
camera.center_y = 20
|
|
271
|
+
},
|
|
272
|
+
actions: () => ({
|
|
273
|
+
r: reset_camera,
|
|
274
|
+
b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
|
|
275
|
+
s: () => show_stable = !show_stable,
|
|
276
|
+
u: () => show_unstable = !show_unstable,
|
|
277
|
+
h: () => show_hull_faces = !show_hull_faces,
|
|
278
|
+
l: () => show_stable_labels = !show_stable_labels,
|
|
279
|
+
}),
|
|
361
280
|
})
|
|
281
|
+
const { render_once } = interactions
|
|
282
|
+
const sorted_points_cache = $derived(interactions.sorted_points_cache)
|
|
362
283
|
|
|
363
284
|
// Hull face color (customizable via controls)
|
|
364
285
|
let hull_face_color = $state(`#4caf50`)
|
|
@@ -382,32 +303,27 @@
|
|
|
382
303
|
// Re-render when important state changes
|
|
383
304
|
$effect(() => {
|
|
384
305
|
// oxfmt-ignore
|
|
385
|
-
void [show_hull_faces, color_mode, color_scale, camera.rotation_x, camera.rotation_y, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, text_color, elements] // track reactively
|
|
306
|
+
void [show_hull_faces, color_mode, color_scale, camera.rotation_x, camera.rotation_y, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_data.visible_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, text_color, elements] // track reactively
|
|
386
307
|
|
|
387
308
|
render_once()
|
|
388
309
|
})
|
|
389
310
|
|
|
390
311
|
// Visibility toggles are now bindable props
|
|
391
312
|
|
|
392
|
-
// Smart label defaults
|
|
313
|
+
// Smart label defaults: hide labels for large datasets. Applied once per dataset
|
|
314
|
+
// (keyed on the entries prop) so later entry-count changes from temperature/gas
|
|
315
|
+
// filtering don't clobber the user's label toggles.
|
|
316
|
+
let label_defaults_applied_for: PhaseData[] | null = null
|
|
393
317
|
$effect(() => {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
} else {
|
|
399
|
-
// For smaller datasets, show stable labels by default
|
|
400
|
-
show_stable_labels = true
|
|
401
|
-
show_unstable_labels = false
|
|
402
|
-
}
|
|
318
|
+
if (label_defaults_applied_for === entries) return
|
|
319
|
+
label_defaults_applied_for = entries
|
|
320
|
+
show_stable_labels = hull_data.effective_entries.length <= label_threshold
|
|
321
|
+
show_unstable_labels = false
|
|
403
322
|
})
|
|
404
323
|
|
|
405
|
-
//
|
|
406
|
-
function extract_structure_from_entry(
|
|
407
|
-
|
|
408
|
-
): AnyStructure | null {
|
|
409
|
-
const orig_entry = entries.find((ent) => ent.entry_id === entry.entry_id)
|
|
410
|
-
return orig_entry?.structure as AnyStructure || null
|
|
324
|
+
// function (not const) so the create_canvas_interactions options above can reference it
|
|
325
|
+
function extract_structure_from_entry(entry: ConvexHullEntry): AnyStructure | null {
|
|
326
|
+
return helpers.extract_structure_from_entry(entries, entry)
|
|
411
327
|
}
|
|
412
328
|
|
|
413
329
|
const reset_camera = () => {
|
|
@@ -421,15 +337,16 @@
|
|
|
421
337
|
reset_camera()
|
|
422
338
|
fullscreen = DEFAULTS.convex_hull.quaternary.fullscreen
|
|
423
339
|
info_pane_open = DEFAULTS.convex_hull.quaternary.info_pane_open
|
|
424
|
-
|
|
340
|
+
controls_open = DEFAULTS.convex_hull.quaternary.legend_pane_open
|
|
425
341
|
color_mode = DEFAULTS.convex_hull.quaternary.color_mode
|
|
426
342
|
color_scale = DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName
|
|
427
343
|
show_stable = DEFAULTS.convex_hull.quaternary.show_stable
|
|
428
344
|
show_unstable = DEFAULTS.convex_hull.quaternary.show_unstable
|
|
345
|
+
hidden_categories = []
|
|
429
346
|
show_stable_labels = DEFAULTS.convex_hull.quaternary.show_stable_labels
|
|
430
347
|
show_unstable_labels = DEFAULTS.convex_hull.quaternary.show_unstable_labels
|
|
431
348
|
// Use auto-computed threshold based on entry count instead of static default
|
|
432
|
-
max_hull_dist_show_phases = auto_default_threshold
|
|
349
|
+
max_hull_dist_show_phases = hull_data.auto_default_threshold
|
|
433
350
|
max_hull_dist_show_labels =
|
|
434
351
|
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels
|
|
435
352
|
show_hull_faces = DEFAULTS.convex_hull.quaternary.show_hull_faces
|
|
@@ -439,69 +356,6 @@
|
|
|
439
356
|
.hull_face_color_mode as HullFaceColorMode
|
|
440
357
|
}
|
|
441
358
|
|
|
442
|
-
const handle_keydown = (event: KeyboardEvent) => {
|
|
443
|
-
const target = event.target
|
|
444
|
-
// Skip if focus is on an interactive element that handles Enter natively
|
|
445
|
-
const interactive_selector =
|
|
446
|
-
`input,textarea,select,button,a,[contenteditable="true"],[role="button"],[tabindex]:not([tabindex="-1"])`
|
|
447
|
-
if (
|
|
448
|
-
target instanceof HTMLElement &&
|
|
449
|
-
target.matches(interactive_selector) &&
|
|
450
|
-
target !== canvas
|
|
451
|
-
) return
|
|
452
|
-
|
|
453
|
-
// Prevent double handling from canvas + wrapper bubbling
|
|
454
|
-
if (event.target !== event.currentTarget && event.currentTarget !== canvas) return
|
|
455
|
-
|
|
456
|
-
// Handle Enter for keyboard accessibility - select hovered entry
|
|
457
|
-
if (event.key === `Enter`) {
|
|
458
|
-
const entry = hover_data?.entry
|
|
459
|
-
if (entry) {
|
|
460
|
-
on_point_click?.(entry)
|
|
461
|
-
if (enable_click_selection) {
|
|
462
|
-
selected_entry = entry
|
|
463
|
-
if (enable_structure_preview) {
|
|
464
|
-
const structure = extract_structure_from_entry(entry)
|
|
465
|
-
if (structure) {
|
|
466
|
-
selected_structure = structure
|
|
467
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
468
|
-
modal_open = true
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
} else if (modal_open) {
|
|
473
|
-
close_structure_popup()
|
|
474
|
-
}
|
|
475
|
-
return
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const actions: Record<string, () => void> = {
|
|
479
|
-
r: reset_camera,
|
|
480
|
-
b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
|
|
481
|
-
s: () => show_stable = !show_stable,
|
|
482
|
-
u: () => show_unstable = !show_unstable,
|
|
483
|
-
h: () => show_hull_faces = !show_hull_faces,
|
|
484
|
-
l: () => show_stable_labels = !show_stable_labels,
|
|
485
|
-
}
|
|
486
|
-
actions[event.key.toLowerCase()]?.()
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
async function handle_file_drop(event: DragEvent): Promise<void> {
|
|
490
|
-
drag_over = false
|
|
491
|
-
const data = await helpers.parse_hull_entries_from_drop(event)
|
|
492
|
-
if (data) on_file_drop?.(data)
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
async function copy_entry_data(
|
|
496
|
-
entry: ConvexHullEntry,
|
|
497
|
-
position: { x: number; y: number },
|
|
498
|
-
) {
|
|
499
|
-
await helpers.copy_entry_to_clipboard(entry, position, (visible, pos) => {
|
|
500
|
-
copy_feedback.visible = visible
|
|
501
|
-
copy_feedback.position = pos
|
|
502
|
-
})
|
|
503
|
-
}
|
|
504
|
-
|
|
505
359
|
const get_point_color = (entry: ConvexHullEntry): string =>
|
|
506
360
|
helpers.get_point_color_for_entry(
|
|
507
361
|
entry,
|
|
@@ -630,11 +484,8 @@
|
|
|
630
484
|
for (let idx = 0; idx < 4; idx++) {
|
|
631
485
|
const vx = vertices[idx]
|
|
632
486
|
// Direction from centroid to vertex
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
y: vx.y - centroid.y,
|
|
636
|
-
z: vx.z - centroid.z,
|
|
637
|
-
}
|
|
487
|
+
const { x: cx, y: cy, z: cz } = centroid
|
|
488
|
+
const dir = { x: vx.x - cx, y: vx.y - cy, z: vx.z - cz }
|
|
638
489
|
const len = Math.hypot(dir.x, dir.y, dir.z) || 1
|
|
639
490
|
const label_pos = {
|
|
640
491
|
x: vx.x + (dir.x / len) * distance,
|
|
@@ -740,14 +591,14 @@
|
|
|
740
591
|
triangles.sort((a, b) => a.avg_depth - b.avg_depth)
|
|
741
592
|
|
|
742
593
|
// Lazy computation for uniform mode: normalize alpha by formation energy
|
|
743
|
-
let norm_alpha: ((
|
|
594
|
+
let norm_alpha: ((energy: number) => number) | null = null
|
|
744
595
|
if (hull_face_color_mode === `uniform`) {
|
|
745
596
|
norm_alpha = (energy: number) => {
|
|
746
|
-
const
|
|
597
|
+
const frac = Math.max(
|
|
747
598
|
0,
|
|
748
599
|
Math.min(1, (0 - energy) / Math.max(1e-6, 0 - formation_energy_min)),
|
|
749
600
|
)
|
|
750
|
-
return
|
|
601
|
+
return frac * hull_face_opacity
|
|
751
602
|
}
|
|
752
603
|
}
|
|
753
604
|
|
|
@@ -813,59 +664,16 @@
|
|
|
813
664
|
|
|
814
665
|
function draw_data_points(): void {
|
|
815
666
|
if (!ctx || sorted_points_cache.length === 0) return
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
ctx.fillStyle = `rgba(0, 0, 0, 0.2)`
|
|
827
|
-
const shadow_path = helpers.create_marker_path(size * 0.8, marker)
|
|
828
|
-
ctx.save()
|
|
829
|
-
ctx.translate(projected.x + shadow_offset, projected.y + shadow_offset)
|
|
830
|
-
ctx.fill(shadow_path)
|
|
831
|
-
ctx.restore()
|
|
832
|
-
|
|
833
|
-
// Highlights
|
|
834
|
-
if (selected_entry && entry.entry_id === selected_entry.entry_id) {
|
|
835
|
-
helpers.draw_selection_highlight(
|
|
836
|
-
ctx,
|
|
837
|
-
projected,
|
|
838
|
-
size,
|
|
839
|
-
canvas_dims.scale,
|
|
840
|
-
pulse.time,
|
|
841
|
-
pulse_opacity,
|
|
842
|
-
)
|
|
843
|
-
}
|
|
844
|
-
if (is_entry_highlighted) {
|
|
845
|
-
helpers.draw_highlight_effect(
|
|
846
|
-
ctx,
|
|
847
|
-
projected,
|
|
848
|
-
size,
|
|
849
|
-
canvas_dims.scale,
|
|
850
|
-
pulse.time,
|
|
851
|
-
merged_highlight_style,
|
|
852
|
-
)
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
// Main point with marker symbol
|
|
856
|
-
ctx.fillStyle =
|
|
857
|
-
is_entry_highlighted && merged_highlight_style.effect === `color`
|
|
858
|
-
? merged_highlight_style.color
|
|
859
|
-
: color
|
|
860
|
-
ctx.strokeStyle = is_stable ? `#ffffff` : `#000000`
|
|
861
|
-
ctx.lineWidth = 0.5 * canvas_dims.scale
|
|
862
|
-
const marker_path = helpers.create_marker_path(size, marker)
|
|
863
|
-
ctx.save()
|
|
864
|
-
ctx.translate(projected.x, projected.y)
|
|
865
|
-
ctx.fill(marker_path)
|
|
866
|
-
ctx.stroke(marker_path)
|
|
867
|
-
ctx.restore()
|
|
868
|
-
}
|
|
667
|
+
helpers.draw_hull_points(ctx, sorted_points_cache, {
|
|
668
|
+
scale: canvas_dims.scale,
|
|
669
|
+
shadow_factor: 2,
|
|
670
|
+
selected_entry,
|
|
671
|
+
is_highlighted,
|
|
672
|
+
get_point_color,
|
|
673
|
+
highlight_style: merged_highlight_style,
|
|
674
|
+
pulse_time: pulse.time,
|
|
675
|
+
pulse_opacity,
|
|
676
|
+
})
|
|
869
677
|
|
|
870
678
|
if (!merged_config.show_labels) return
|
|
871
679
|
|
|
@@ -929,169 +737,7 @@
|
|
|
929
737
|
draw_data_points() // Draw data points (on top)
|
|
930
738
|
}
|
|
931
739
|
|
|
932
|
-
|
|
933
|
-
is_dragging = true
|
|
934
|
-
drag_started = false
|
|
935
|
-
hover_data = null
|
|
936
|
-
on_point_hover?.(null)
|
|
937
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
const handle_mouse_move = (event: MouseEvent) => {
|
|
941
|
-
if (!is_dragging) return
|
|
942
|
-
const [dx, dy] = [event.clientX - last_mouse.x, event.clientY - last_mouse.y]
|
|
943
|
-
|
|
944
|
-
// Mark as drag if any movement occurred
|
|
945
|
-
if (dx !== 0 || dy !== 0) drag_started = true
|
|
946
|
-
|
|
947
|
-
// With Cmd/Ctrl held: pan the view instead of rotating
|
|
948
|
-
if (event.metaKey || event.ctrlKey) {
|
|
949
|
-
camera.center_x += dx
|
|
950
|
-
camera.center_y += dy
|
|
951
|
-
} else {
|
|
952
|
-
camera.rotation_y += dx * 0.005
|
|
953
|
-
camera.rotation_x = Math.max(
|
|
954
|
-
-Math.PI / 3,
|
|
955
|
-
Math.min(Math.PI / 3, camera.rotation_x - dy * 0.005),
|
|
956
|
-
)
|
|
957
|
-
}
|
|
958
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
const handle_wheel = (event: WheelEvent) => {
|
|
962
|
-
event.preventDefault()
|
|
963
|
-
camera.zoom = Math.max(
|
|
964
|
-
1.0,
|
|
965
|
-
Math.min(15, camera.zoom * (event.deltaY > 0 ? 0.98 : 1.02)),
|
|
966
|
-
)
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
const handle_hover = (event: MouseEvent) => {
|
|
970
|
-
if (is_dragging) return
|
|
971
|
-
const entry = find_entry_at_mouse(event)
|
|
972
|
-
hover_data = entry
|
|
973
|
-
? { entry, position: { x: event.clientX, y: event.clientY } }
|
|
974
|
-
: null
|
|
975
|
-
on_point_hover?.(hover_data)
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
const find_entry_at_mouse = (event: MouseEvent): ConvexHullEntry | null =>
|
|
979
|
-
helpers.find_hull_entry_at_mouse(
|
|
980
|
-
canvas,
|
|
981
|
-
event,
|
|
982
|
-
visible_entries,
|
|
983
|
-
(x: number, y: number, z: number) => {
|
|
984
|
-
const projected = project_3d_point(x, y, z)
|
|
985
|
-
return { x: projected.x, y: projected.y }
|
|
986
|
-
},
|
|
987
|
-
)
|
|
988
|
-
|
|
989
|
-
const handle_click = (event: MouseEvent) => {
|
|
990
|
-
event.stopPropagation()
|
|
991
|
-
|
|
992
|
-
// Check if this was a drag operation (any mouse movement during drag)
|
|
993
|
-
const was_drag = drag_started
|
|
994
|
-
drag_started = false // Reset for next interaction
|
|
995
|
-
if (was_drag) return // Don't trigger click if this was a drag
|
|
996
|
-
|
|
997
|
-
const entry = find_entry_at_mouse(event)
|
|
998
|
-
if (entry) {
|
|
999
|
-
on_point_click?.(entry)
|
|
1000
|
-
if (enable_click_selection) {
|
|
1001
|
-
selected_entry = entry
|
|
1002
|
-
if (enable_structure_preview) {
|
|
1003
|
-
const structure = extract_structure_from_entry(entry)
|
|
1004
|
-
if (structure) {
|
|
1005
|
-
selected_structure = structure
|
|
1006
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
1007
|
-
modal_open = true
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
} else if (modal_open) close_structure_popup()
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
function close_structure_popup() {
|
|
1015
|
-
modal_open = false
|
|
1016
|
-
selected_structure = null
|
|
1017
|
-
selected_entry = null
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
const handle_double_click = (event: MouseEvent) => {
|
|
1021
|
-
const entry = find_entry_at_mouse(event)
|
|
1022
|
-
if (entry) {
|
|
1023
|
-
copy_entry_data(entry, {
|
|
1024
|
-
x: event.clientX,
|
|
1025
|
-
y: event.clientY,
|
|
1026
|
-
})
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
function render_once() {
|
|
1031
|
-
if (!frame_id) {
|
|
1032
|
-
frame_id = requestAnimationFrame(() => {
|
|
1033
|
-
render_frame()
|
|
1034
|
-
frame_id = 0
|
|
1035
|
-
})
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
function update_canvas_size() {
|
|
1040
|
-
if (!canvas) return
|
|
1041
|
-
const dpr = globalThis.devicePixelRatio || 1
|
|
1042
|
-
const container = canvas.parentElement
|
|
1043
|
-
const rect = container?.getBoundingClientRect()
|
|
1044
|
-
const [width, height] = rect ? [rect.width, rect.height] : [400, 400]
|
|
1045
|
-
|
|
1046
|
-
const new_width = Math.max(0, Math.round(width * dpr))
|
|
1047
|
-
const new_height = Math.max(0, Math.round(height * dpr))
|
|
1048
|
-
canvas_dims = { width, height, scale: Math.min(width, height) / 600 }
|
|
1049
|
-
|
|
1050
|
-
if (!ctx || canvas.width !== new_width || canvas.height !== new_height) {
|
|
1051
|
-
canvas.width = new_width
|
|
1052
|
-
canvas.height = new_height
|
|
1053
|
-
ctx = canvas.getContext(`2d`)
|
|
1054
|
-
if (ctx) {
|
|
1055
|
-
ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
|
|
1056
|
-
ctx.imageSmoothingEnabled = true
|
|
1057
|
-
ctx.imageSmoothingQuality = `high`
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
render_once()
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
$effect(() => {
|
|
1064
|
-
if (!canvas) return
|
|
1065
|
-
|
|
1066
|
-
// Initial setup
|
|
1067
|
-
update_canvas_size()
|
|
1068
|
-
|
|
1069
|
-
// Watch for resize events - only update canvas, don't reset camera
|
|
1070
|
-
const resize_observer = new ResizeObserver(update_canvas_size)
|
|
1071
|
-
|
|
1072
|
-
const container = canvas.parentElement
|
|
1073
|
-
if (container) resize_observer.observe(container)
|
|
1074
|
-
|
|
1075
|
-
return () => { // Cleanup on unmount
|
|
1076
|
-
if (frame_id) cancelAnimationFrame(frame_id)
|
|
1077
|
-
resize_observer.disconnect()
|
|
1078
|
-
}
|
|
1079
|
-
})
|
|
1080
|
-
|
|
1081
|
-
// Fullscreen handling with camera reset
|
|
1082
|
-
let was_fullscreen = $state(fullscreen)
|
|
1083
|
-
$effect(() => {
|
|
1084
|
-
setup_fullscreen_effect(fullscreen, wrapper, (entering_fullscreen) => {
|
|
1085
|
-
if (entering_fullscreen !== was_fullscreen) {
|
|
1086
|
-
camera.center_x = 0
|
|
1087
|
-
camera.center_y = 20
|
|
1088
|
-
was_fullscreen = entering_fullscreen
|
|
1089
|
-
}
|
|
1090
|
-
})
|
|
1091
|
-
set_fullscreen_bg(wrapper, fullscreen, `--hull-4d-bg-fullscreen`)
|
|
1092
|
-
})
|
|
1093
|
-
|
|
1094
|
-
// Performance: Cache canvas dimensions and pre-compute sorted point projections
|
|
740
|
+
// Performance: Cache canvas dimensions and formation energy minimum
|
|
1095
741
|
let canvas_dims = $state({ width: 600, height: 600, scale: 1 })
|
|
1096
742
|
const formation_energy_min = $derived.by(() => {
|
|
1097
743
|
let min_energy = 0
|
|
@@ -1100,57 +746,33 @@
|
|
|
1100
746
|
}
|
|
1101
747
|
return min_energy
|
|
1102
748
|
})
|
|
1103
|
-
const sorted_points_cache = $derived.by(() => {
|
|
1104
|
-
if (!canvas || visible_entries.length === 0) return []
|
|
1105
|
-
return visible_entries
|
|
1106
|
-
.map((entry) => ({
|
|
1107
|
-
entry,
|
|
1108
|
-
projected: project_3d_point(entry.x, entry.y, entry.z),
|
|
1109
|
-
}))
|
|
1110
|
-
.sort((a, b) => a.projected.depth - b.projected.depth)
|
|
1111
|
-
})
|
|
1112
749
|
|
|
1113
|
-
let style = $derived(
|
|
1114
|
-
`--hull-stable-color:${merged_config.colors?.stable || `#0072B2`};
|
|
1115
|
-
--hull-unstable-color:${merged_config.colors?.unstable || `#E69F00`};
|
|
1116
|
-
--hull-edge-color:${merged_config.colors?.edge || `var(--text-color, #212121)`};
|
|
1117
|
-
--hull-text-color:${
|
|
1118
|
-
merged_config.colors?.annotation || `var(--text-color, #212121)`
|
|
1119
|
-
}`,
|
|
1120
|
-
)
|
|
750
|
+
let style = $derived(helpers.hull_style_css(merged_config.colors))
|
|
1121
751
|
</script>
|
|
1122
752
|
|
|
1123
753
|
<svelte:document
|
|
1124
754
|
onfullscreenchange={() => {
|
|
1125
|
-
fullscreen
|
|
755
|
+
// tie fullscreen state to this component's own wrapper, not any fullscreen element
|
|
756
|
+
fullscreen = document.fullscreenElement === wrapper
|
|
1126
757
|
}}
|
|
1127
|
-
onmousemove={handle_mouse_move}
|
|
1128
|
-
onmouseup={
|
|
758
|
+
onmousemove={interactions.handle_mouse_move}
|
|
759
|
+
onmouseup={interactions.handle_mouse_up}
|
|
1129
760
|
/>
|
|
1130
761
|
|
|
1131
762
|
<div
|
|
1132
763
|
{...rest}
|
|
1133
764
|
class="convex-hull-4d {rest.class ?? ``}"
|
|
1134
|
-
class:dragover={drag_over}
|
|
765
|
+
class:dragover={interactions.drag_over}
|
|
1135
766
|
style={`${style}; ${rest.style ?? ``}`}
|
|
1136
767
|
data-has-selection={selected_entry !== null}
|
|
1137
|
-
data-has-hover={hover_data !== null}
|
|
1138
|
-
data-is-dragging={is_dragging}
|
|
768
|
+
data-has-hover={interactions.hover_data !== null}
|
|
769
|
+
data-is-dragging={interactions.is_dragging}
|
|
1139
770
|
data-rotation-x={camera.rotation_x.toFixed(4)}
|
|
1140
771
|
data-rotation-y={camera.rotation_y.toFixed(4)}
|
|
1141
772
|
bind:this={wrapper}
|
|
1142
773
|
role="application"
|
|
1143
774
|
tabindex="-1"
|
|
1144
|
-
|
|
1145
|
-
ondrop={handle_file_drop}
|
|
1146
|
-
ondragover={(event) => {
|
|
1147
|
-
event.preventDefault()
|
|
1148
|
-
drag_over = true
|
|
1149
|
-
}}
|
|
1150
|
-
ondragleave={(event) => {
|
|
1151
|
-
event.preventDefault()
|
|
1152
|
-
drag_over = false
|
|
1153
|
-
}}
|
|
775
|
+
{...interactions.wrapper_handlers}
|
|
1154
776
|
aria-label="Convex hull visualization"
|
|
1155
777
|
>
|
|
1156
778
|
{@render children?.({
|
|
@@ -1167,12 +789,7 @@
|
|
|
1167
789
|
bind:this={canvas}
|
|
1168
790
|
tabindex="0"
|
|
1169
791
|
aria-label={merged_controls.title || phase_stats?.chemical_system || `4D Convex Hull`}
|
|
1170
|
-
|
|
1171
|
-
onmousemove={handle_hover}
|
|
1172
|
-
onclick={handle_click}
|
|
1173
|
-
onkeydown={handle_keydown}
|
|
1174
|
-
ondblclick={handle_double_click}
|
|
1175
|
-
onwheel={handle_wheel}
|
|
792
|
+
{...interactions.canvas_handlers}
|
|
1176
793
|
></canvas>
|
|
1177
794
|
|
|
1178
795
|
{#if entries.length === 0}
|
|
@@ -1184,14 +801,9 @@
|
|
|
1184
801
|
|
|
1185
802
|
<!-- Energy above hull Color Bar -->
|
|
1186
803
|
{#if color_mode === `energy` && plot_entries.length > 0}
|
|
1187
|
-
{@const hull_distances = plot_entries
|
|
1188
|
-
.map((entry) => entry.e_above_hull)
|
|
1189
|
-
.filter((val): val is number => typeof val === `number`)}
|
|
1190
|
-
{@const min_energy = hull_distances.length > 0 ? Math.min(...hull_distances) : 0}
|
|
1191
|
-
{@const max_energy = hull_distances.length > 0 ? Math.max(...hull_distances, 0.1) : 0.1}
|
|
1192
804
|
<ColorBar
|
|
1193
805
|
title="Energy above hull (eV/atom)"
|
|
1194
|
-
range={
|
|
806
|
+
range={helpers.hull_distance_range(plot_entries)}
|
|
1195
807
|
{color_scale}
|
|
1196
808
|
wrapper_style="position: absolute; bottom: 2em; left: 1em; width: 200px;"
|
|
1197
809
|
bar_style="height: 12px;"
|
|
@@ -1199,88 +811,52 @@
|
|
|
1199
811
|
/>
|
|
1200
812
|
{/if}
|
|
1201
813
|
|
|
1202
|
-
<!--
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
bind:controls_open={legend_pane_open}
|
|
1246
|
-
bind:color_mode
|
|
1247
|
-
bind:color_scale
|
|
1248
|
-
bind:show_stable
|
|
1249
|
-
bind:show_unstable
|
|
1250
|
-
bind:show_stable_labels
|
|
1251
|
-
bind:show_unstable_labels
|
|
1252
|
-
bind:max_hull_dist_show_phases
|
|
1253
|
-
bind:max_hull_dist_show_labels
|
|
1254
|
-
{max_hull_dist_in_data}
|
|
1255
|
-
{stable_entries}
|
|
1256
|
-
{unstable_entries}
|
|
1257
|
-
{camera}
|
|
1258
|
-
{merged_controls}
|
|
1259
|
-
toggle_props={{ class: `legend-controls-btn` }}
|
|
1260
|
-
{show_hull_faces}
|
|
1261
|
-
on_hull_faces_change={(value: boolean) => show_hull_faces = value}
|
|
1262
|
-
{hull_face_color}
|
|
1263
|
-
on_hull_face_color_change={(value: string) => hull_face_color = value}
|
|
1264
|
-
{hull_face_opacity}
|
|
1265
|
-
on_hull_face_opacity_change={(value: number) => hull_face_opacity = value}
|
|
1266
|
-
{hull_face_color_mode}
|
|
1267
|
-
on_hull_face_color_mode_change={(value: HullFaceColorMode) =>
|
|
1268
|
-
hull_face_color_mode = value}
|
|
1269
|
-
bind:energy_source_mode
|
|
1270
|
-
{has_precomputed_e_form}
|
|
1271
|
-
{can_compute_e_form}
|
|
1272
|
-
{has_precomputed_hull}
|
|
1273
|
-
{can_compute_hull}
|
|
1274
|
-
/>
|
|
1275
|
-
{/if}
|
|
1276
|
-
</section>
|
|
814
|
+
<!-- Toolbar + tooltip/copy-feedback/drag/structure-popup chrome -->
|
|
815
|
+
<ConvexHullChrome
|
|
816
|
+
{interactions}
|
|
817
|
+
{hull_data}
|
|
818
|
+
{controls_config}
|
|
819
|
+
{reset_all}
|
|
820
|
+
reset_title="Reset view and settings"
|
|
821
|
+
{enable_info_pane}
|
|
822
|
+
{phase_stats}
|
|
823
|
+
{label_threshold}
|
|
824
|
+
{fullscreen}
|
|
825
|
+
{fullscreen_toggle}
|
|
826
|
+
{wrapper}
|
|
827
|
+
{camera}
|
|
828
|
+
{merged_controls}
|
|
829
|
+
{stable_entries}
|
|
830
|
+
{unstable_entries}
|
|
831
|
+
{get_point_color}
|
|
832
|
+
{merged_highlight_style}
|
|
833
|
+
{is_highlighted}
|
|
834
|
+
{tooltip}
|
|
835
|
+
{selected_entry}
|
|
836
|
+
bind:show_hull_faces
|
|
837
|
+
bind:hull_face_color
|
|
838
|
+
bind:hull_face_opacity
|
|
839
|
+
bind:hull_face_color_mode
|
|
840
|
+
bind:info_pane_open
|
|
841
|
+
bind:controls_open
|
|
842
|
+
bind:color_mode
|
|
843
|
+
bind:color_scale
|
|
844
|
+
bind:show_stable
|
|
845
|
+
bind:show_unstable
|
|
846
|
+
{entry_category}
|
|
847
|
+
bind:hidden_categories
|
|
848
|
+
bind:show_stable_labels
|
|
849
|
+
bind:show_unstable_labels
|
|
850
|
+
bind:max_hull_dist_show_phases
|
|
851
|
+
bind:max_hull_dist_show_labels
|
|
852
|
+
bind:energy_source_mode
|
|
853
|
+
/>
|
|
854
|
+
|
|
855
|
+
{#if hull_data.has_temp_data && temperature !== undefined}
|
|
856
|
+
<TemperatureSlider available_temperatures={hull_data.available_temperatures} bind:temperature />
|
|
1277
857
|
{/if}
|
|
1278
858
|
|
|
1279
|
-
{#if
|
|
1280
|
-
<TemperatureSlider {available_temperatures} bind:temperature />
|
|
1281
|
-
{/if}
|
|
1282
|
-
|
|
1283
|
-
{#if gas_analysis.has_gas_dependent_elements && merged_gas_config}
|
|
859
|
+
{#if hull_data.gas_analysis.has_gas_dependent_elements && merged_gas_config}
|
|
1284
860
|
<GasPressureControls
|
|
1285
861
|
config={merged_gas_config}
|
|
1286
862
|
bind:pressures={gas_pressures}
|
|
@@ -1288,48 +864,6 @@
|
|
|
1288
864
|
/>
|
|
1289
865
|
{/if}
|
|
1290
866
|
|
|
1291
|
-
<!-- Hover tooltip -->
|
|
1292
|
-
{#if hover_data}
|
|
1293
|
-
{@const { entry, position } = hover_data}
|
|
1294
|
-
{@const entry_highlight = is_highlighted(entry) ? merged_highlight_style : undefined}
|
|
1295
|
-
{@const tooltip_style =
|
|
1296
|
-
`z-index: ${CONVEX_HULL_STYLE.z_index.tooltip}; backdrop-filter: blur(4px);
|
|
1297
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);`}
|
|
1298
|
-
<PlotTooltip
|
|
1299
|
-
x={position.x}
|
|
1300
|
-
y={position.y}
|
|
1301
|
-
offset={{ x: 10, y: -10 }}
|
|
1302
|
-
bg_color={get_point_color(entry)}
|
|
1303
|
-
fixed
|
|
1304
|
-
style={tooltip_style}
|
|
1305
|
-
>
|
|
1306
|
-
<ConvexHullTooltip
|
|
1307
|
-
{entry}
|
|
1308
|
-
{polymorph_stats_map}
|
|
1309
|
-
highlight_style={entry_highlight}
|
|
1310
|
-
{tooltip}
|
|
1311
|
-
/>
|
|
1312
|
-
</PlotTooltip>
|
|
1313
|
-
{/if}
|
|
1314
|
-
|
|
1315
|
-
<!-- Copy-to-clipboard feedback (double-click on point) -->
|
|
1316
|
-
<ClickFeedback bind:visible={copy_feedback.visible} position={copy_feedback.position} />
|
|
1317
|
-
|
|
1318
|
-
<!-- Drag over overlay -->
|
|
1319
|
-
<DragOverlay visible={drag_over} />
|
|
1320
|
-
|
|
1321
|
-
{#if modal_open && selected_structure}
|
|
1322
|
-
<StructurePopup
|
|
1323
|
-
structure={selected_structure}
|
|
1324
|
-
place_right={modal_place_right}
|
|
1325
|
-
stats={{
|
|
1326
|
-
id: selected_entry?.entry_id,
|
|
1327
|
-
e_above_hull: selected_entry?.e_above_hull,
|
|
1328
|
-
e_form: selected_entry?.e_form_per_atom,
|
|
1329
|
-
}}
|
|
1330
|
-
onclose={close_structure_popup}
|
|
1331
|
-
/>
|
|
1332
|
-
{/if}
|
|
1333
867
|
</div>
|
|
1334
868
|
|
|
1335
869
|
<style>
|
|
@@ -1357,42 +891,4 @@
|
|
|
1357
891
|
canvas:active {
|
|
1358
892
|
cursor: grabbing;
|
|
1359
893
|
}
|
|
1360
|
-
.control-buttons {
|
|
1361
|
-
position: absolute;
|
|
1362
|
-
top: 1ex;
|
|
1363
|
-
right: 1ex;
|
|
1364
|
-
display: flex;
|
|
1365
|
-
gap: 8px;
|
|
1366
|
-
transition: opacity 0.2s ease-in-out;
|
|
1367
|
-
}
|
|
1368
|
-
.control-buttons.hover-visible {
|
|
1369
|
-
opacity: 0;
|
|
1370
|
-
pointer-events: none;
|
|
1371
|
-
}
|
|
1372
|
-
.convex-hull-4d:hover .control-buttons.hover-visible,
|
|
1373
|
-
.convex-hull-4d:focus-within .control-buttons.hover-visible {
|
|
1374
|
-
opacity: 1;
|
|
1375
|
-
pointer-events: auto;
|
|
1376
|
-
}
|
|
1377
|
-
.control-buttons.always-visible {
|
|
1378
|
-
opacity: 1;
|
|
1379
|
-
pointer-events: auto;
|
|
1380
|
-
}
|
|
1381
|
-
.control-buttons :global(.draggable-pane) {
|
|
1382
|
-
z-index: 1001 !important;
|
|
1383
|
-
}
|
|
1384
|
-
.control-buttons :global(button) {
|
|
1385
|
-
background: transparent;
|
|
1386
|
-
border: none;
|
|
1387
|
-
padding: 4px;
|
|
1388
|
-
cursor: pointer;
|
|
1389
|
-
border-radius: 3px;
|
|
1390
|
-
color: var(--text-color, currentColor);
|
|
1391
|
-
transition: background-color 0.2s;
|
|
1392
|
-
display: flex;
|
|
1393
|
-
font-size: clamp(0.85em, 2cqmin, 1.3em);
|
|
1394
|
-
}
|
|
1395
|
-
.control-buttons :global(button):hover {
|
|
1396
|
-
background-color: color-mix(in srgb, currentColor 8%, transparent);
|
|
1397
|
-
}
|
|
1398
894
|
</style>
|