matterviz 0.3.1 → 0.3.3
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 -2
- package/dist/FilePicker.svelte +154 -96
- package/dist/Icon.svelte +20 -14
- package/dist/MillerIndexInput.svelte +27 -21
- package/dist/api/optimade.js +6 -6
- package/dist/app.css +216 -178
- package/dist/brillouin/BrillouinZone.svelte +299 -198
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
- package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
- package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
- package/dist/brillouin/compute.js +11 -6
- package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +77 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +32 -0
- package/dist/chempot-diagram/compute.d.ts +48 -0
- package/dist/chempot-diagram/compute.js +812 -0
- package/dist/chempot-diagram/index.d.ts +6 -0
- package/dist/chempot-diagram/index.js +6 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +36 -0
- package/dist/chempot-diagram/types.d.ts +86 -0
- package/dist/chempot-diagram/types.js +28 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +9 -3
- package/dist/composition/BarChart.svelte +141 -77
- package/dist/composition/BubbleChart.svelte +107 -52
- package/dist/composition/Composition.svelte +100 -79
- package/dist/composition/Formula.svelte +108 -62
- package/dist/composition/FormulaFilter.svelte +973 -353
- package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
- package/dist/composition/PieChart.svelte +199 -99
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/composition/format.d.ts +5 -0
- package/dist/composition/format.js +20 -3
- package/dist/composition/parse.js +14 -9
- package/dist/convex-hull/ConvexHull.svelte +93 -38
- package/dist/convex-hull/ConvexHull2D.svelte +551 -393
- package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
- package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
- package/dist/convex-hull/ConvexHullControls.svelte +115 -28
- package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
- package/dist/convex-hull/ConvexHullStats.svelte +821 -249
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
- package/dist/convex-hull/GasPressureControls.svelte +104 -61
- package/dist/convex-hull/StructurePopup.svelte +25 -4
- package/dist/convex-hull/TemperatureSlider.svelte +45 -25
- package/dist/convex-hull/barycentric-coords.js +13 -7
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +40 -0
- package/dist/convex-hull/gas-thermodynamics.js +17 -12
- package/dist/convex-hull/helpers.d.ts +10 -1
- package/dist/convex-hull/helpers.js +79 -38
- package/dist/convex-hull/index.d.ts +1 -0
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +163 -69
- package/dist/convex-hull/types.d.ts +12 -12
- package/dist/convex-hull/types.js +0 -12
- package/dist/coordination/CoordinationBarPlot.svelte +232 -176
- package/dist/element/BohrAtom.svelte +56 -13
- package/dist/element/ElementHeading.svelte +7 -2
- package/dist/element/ElementPhoto.svelte +15 -9
- package/dist/element/ElementStats.svelte +10 -4
- package/dist/element/ElementTile.svelte +137 -73
- package/dist/element/Nucleus.svelte +39 -11
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/feedback/ClickFeedback.svelte +16 -5
- package/dist/feedback/DragOverlay.svelte +10 -2
- package/dist/feedback/Spinner.svelte +4 -2
- package/dist/feedback/StatusMessage.svelte +8 -2
- package/dist/fermi-surface/FermiSlice.svelte +118 -88
- package/dist/fermi-surface/FermiSurface.svelte +336 -239
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
- package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
- package/dist/fermi-surface/compute.js +16 -20
- package/dist/fermi-surface/parse.js +37 -33
- package/dist/fermi-surface/symmetry.js +2 -7
- package/dist/fermi-surface/types.d.ts +3 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +111 -0
- package/dist/icons.js +158 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.d.ts +3 -0
- package/dist/io/export.js +138 -140
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +2 -2
- package/dist/io/index.js +2 -112
- package/dist/io/is-binary.js +2 -3
- package/dist/io/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +117 -0
- package/dist/isosurface/Isosurface.svelte +220 -110
- package/dist/isosurface/IsosurfaceControls.svelte +65 -28
- package/dist/isosurface/parse.js +104 -56
- package/dist/isosurface/slice.d.ts +2 -1
- package/dist/isosurface/slice.js +8 -13
- package/dist/isosurface/types.d.ts +14 -1
- package/dist/isosurface/types.js +152 -5
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +12 -8
- package/dist/layout/FullscreenToggle.svelte +11 -2
- package/dist/layout/InfoCard.svelte +38 -6
- package/dist/layout/InfoTag.svelte +125 -94
- package/dist/layout/PropertyFilter.svelte +82 -37
- package/dist/layout/SettingsSection.svelte +85 -55
- package/dist/layout/SubpageGrid.svelte +82 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +266 -223
- package/dist/layout/json-tree/JsonTree.svelte +516 -429
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +281 -173
- package/dist/layout/json-tree/types.d.ts +10 -2
- package/dist/layout/json-tree/utils.d.ts +2 -0
- package/dist/layout/json-tree/utils.js +37 -2
- package/dist/marching-cubes.js +25 -2
- package/dist/math.d.ts +20 -17
- package/dist/math.js +474 -57
- package/dist/overlays/ContextMenu.svelte +66 -40
- package/dist/overlays/DraggablePane.svelte +331 -154
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/periodic-table/PeriodicTable.svelte +278 -145
- package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
- package/dist/periodic-table/PropertySelect.svelte +25 -7
- package/dist/periodic-table/TableInset.svelte +8 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
- package/dist/phase-diagram/build-diagram.js +9 -9
- package/dist/phase-diagram/colors.js +1 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/parse.js +10 -9
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +869 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +8 -4
- package/dist/phase-diagram/utils.js +219 -74
- package/dist/plot/AxisLabel.svelte +51 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +1461 -768
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +33 -6
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +533 -383
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ColorScaleSelect.svelte +28 -7
- package/dist/plot/ElementScatter.svelte +38 -16
- package/dist/plot/FillArea.svelte +152 -92
- package/dist/plot/Histogram.svelte +1162 -709
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte +81 -18
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte +34 -11
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte +63 -28
- package/dist/plot/PlotControls.svelte +221 -96
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +174 -91
- package/dist/plot/PlotTooltip.svelte +45 -6
- package/dist/plot/PortalSelect.svelte +175 -146
- package/dist/plot/ReferenceLine.svelte +77 -22
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferenceLine3D.svelte +132 -107
- package/dist/plot/ReferencePlane.svelte +146 -123
- package/dist/plot/ScatterPlot.svelte +1880 -1156
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte +256 -131
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +300 -297
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
- package/dist/plot/ScatterPlot3DScene.svelte +608 -406
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +150 -70
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +98 -26
- package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
- package/dist/plot/SpacegroupBarPlot.svelte +142 -85
- package/dist/plot/Surface3D.svelte +159 -108
- package/dist/plot/ZeroLines.svelte +96 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +23 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/axis-utils.js +1 -3
- package/dist/plot/data-cleaning.js +12 -28
- package/dist/plot/data-transform.js +2 -1
- package/dist/plot/fill-utils.js +2 -0
- package/dist/plot/index.d.ts +6 -2
- package/dist/plot/index.js +6 -2
- package/dist/plot/interactions.d.ts +8 -10
- package/dist/plot/interactions.js +2 -3
- package/dist/plot/layout.d.ts +11 -2
- package/dist/plot/layout.js +44 -17
- package/dist/plot/reference-line.d.ts +5 -22
- package/dist/plot/reference-line.js +12 -84
- package/dist/plot/scales.js +24 -36
- package/dist/plot/types.d.ts +53 -40
- package/dist/plot/types.js +12 -7
- package/dist/plot/utils/label-placement.d.ts +32 -15
- package/dist/plot/utils/label-placement.js +227 -63
- package/dist/plot/utils/series-visibility.js +2 -3
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +173 -132
- package/dist/rdf/calc-rdf.js +4 -5
- package/dist/sanitize.d.ts +4 -0
- package/dist/sanitize.js +107 -0
- package/dist/settings.d.ts +21 -6
- package/dist/settings.js +63 -19
- package/dist/spectral/Bands.svelte +963 -412
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/BandsAndDos.svelte +90 -49
- package/dist/spectral/BrillouinBandsDos.svelte +151 -93
- package/dist/spectral/Dos.svelte +389 -258
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +119 -51
- package/dist/spectral/types.d.ts +2 -0
- package/dist/state.svelte.d.ts +1 -1
- package/dist/state.svelte.js +3 -2
- package/dist/structure/Arrow.svelte +59 -20
- package/dist/structure/AtomLegend.svelte +231 -129
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +73 -47
- package/dist/structure/CanvasTooltip.svelte +10 -2
- package/dist/structure/CellSelect.svelte +148 -51
- package/dist/structure/Cylinder.svelte +33 -17
- package/dist/structure/Lattice.svelte +88 -33
- package/dist/structure/Structure.svelte +1077 -821
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +373 -139
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +124 -89
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +304 -231
- package/dist/structure/StructureScene.svelte +919 -445
- package/dist/structure/StructureScene.svelte.d.ts +16 -7
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +42 -29
- package/dist/structure/bonding.js +6 -7
- package/dist/structure/export.js +22 -34
- package/dist/structure/ferrox-wasm-types.d.ts +3 -2
- package/dist/structure/ferrox-wasm-types.js +0 -3
- package/dist/structure/ferrox-wasm.d.ts +3 -2
- package/dist/structure/ferrox-wasm.js +2 -3
- package/dist/structure/index.d.ts +16 -0
- package/dist/structure/index.js +88 -6
- package/dist/structure/measure.d.ts +2 -2
- package/dist/structure/measure.js +4 -44
- package/dist/structure/parse.js +130 -155
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +99 -0
- package/dist/structure/pbc.d.ts +1 -0
- package/dist/structure/pbc.js +16 -6
- package/dist/structure/supercell.d.ts +2 -2
- package/dist/structure/supercell.js +12 -22
- package/dist/structure/validation.js +5 -3
- package/dist/symmetry/SymmetryStats.svelte +94 -37
- package/dist/symmetry/WyckoffTable.svelte +42 -14
- package/dist/symmetry/cell-transform.js +5 -3
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +87 -21
- package/dist/symmetry/spacegroups.js +148 -148
- package/dist/table/HeatmapTable.svelte +1112 -516
- package/dist/table/HeatmapTable.svelte.d.ts +12 -1
- package/dist/table/ToggleMenu.svelte +125 -90
- package/dist/table/index.d.ts +2 -0
- package/dist/table/index.js +2 -4
- package/dist/theme/ThemeControl.svelte +21 -12
- package/dist/time.js +4 -1
- package/dist/tooltip/TooltipContent.svelte +33 -8
- package/dist/trajectory/Trajectory.svelte +889 -687
- package/dist/trajectory/TrajectoryError.svelte +14 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +13 -31
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +332 -0
- package/dist/trajectory/helpers.d.ts +14 -0
- package/dist/trajectory/helpers.js +172 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +23 -14
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +77 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +129 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +299 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +179 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +68 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +110 -0
- package/dist/trajectory/plotting.js +13 -8
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +17 -0
- package/dist/xrd/XrdPlot.svelte +337 -245
- package/dist/xrd/broadening.js +14 -9
- package/dist/xrd/calc-xrd.js +12 -19
- package/dist/xrd/parse.d.ts +1 -1
- package/dist/xrd/parse.js +17 -17
- package/package.json +103 -101
- package/readme.md +4 -4
- package/dist/trajectory/parse.d.ts +0 -42
- package/dist/trajectory/parse.js +0 -1267
- /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
- /package/dist/theme/{themes.js → themes.mjs} +0 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { load_binary_traj } from '../trajectory/parse';
|
|
2
|
+
const BINARY_EXTENSIONS = new Set(`h5 hdf5 traj npz pkl dat gz gzip zip bz2 xz brml`.split(` `));
|
|
3
|
+
const TEXT_EXTENSIONS = new Set(`xyz extxyz json cif poscar yaml yml txt md py js ts css html xml`.split(` `));
|
|
4
|
+
const VASP_BASENAME_RE = /^(poscar|xdatcar|contcar)$/i;
|
|
5
|
+
// Extract filename from Content-Disposition header, falling back to url_basename.
|
|
6
|
+
function extract_filename(headers, fallback) {
|
|
7
|
+
if (!headers)
|
|
8
|
+
return fallback;
|
|
9
|
+
const content_disposition_str = headers.get(`content-disposition`);
|
|
10
|
+
if (!content_disposition_str)
|
|
11
|
+
return fallback;
|
|
12
|
+
const star_match = /filename\*=(?:UTF-8''|)([^;]+)/i.exec(content_disposition_str);
|
|
13
|
+
if (star_match?.[1]) {
|
|
14
|
+
const raw = star_match[1].trim().replace(/^"|"$/g, ``);
|
|
15
|
+
try {
|
|
16
|
+
return decodeURIComponent(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return raw;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const plain_match = /filename\s*=\s*"?([^";]+)"?/i.exec(content_disposition_str);
|
|
23
|
+
return plain_match?.[1]?.trim() || fallback;
|
|
24
|
+
}
|
|
25
|
+
// Handle URL-based file drop data by fetching content lazily
|
|
26
|
+
export async function handle_url_drop(drag_event, callback) {
|
|
27
|
+
const json_data = drag_event.dataTransfer?.getData(`application/json`);
|
|
28
|
+
if (!json_data)
|
|
29
|
+
return false;
|
|
30
|
+
let file_info;
|
|
31
|
+
try {
|
|
32
|
+
file_info = JSON.parse(json_data);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (!file_info.url)
|
|
38
|
+
return false;
|
|
39
|
+
await load_from_url(file_info.url, callback);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
export async function load_from_url(url, callback) {
|
|
43
|
+
const url_basename = url.split(`/`).pop() || url;
|
|
44
|
+
const ext = url_basename.split(`.`).pop()?.toLowerCase() || ``;
|
|
45
|
+
if (BINARY_EXTENSIONS.has(ext)) {
|
|
46
|
+
// Force binary mode for known binary files to handle GitHub Pages content-type issues
|
|
47
|
+
const resp = await fetch(url);
|
|
48
|
+
if (!resp.ok)
|
|
49
|
+
throw new Error(`Fetch failed: ${resp.status}`);
|
|
50
|
+
const filename = extract_filename(resp.headers, url_basename);
|
|
51
|
+
// Handle gzipped files with proper content-encoding detection
|
|
52
|
+
if (ext === `gz` || ext === `gzip`) {
|
|
53
|
+
if (resp.headers.get(`content-encoding`) === `gzip`) {
|
|
54
|
+
// Browser automatically decompressed it, so it's text
|
|
55
|
+
return callback(await resp.text(), filename);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Need to decompress manually
|
|
59
|
+
const { decompress_data } = await import(`./decompress`);
|
|
60
|
+
const buffer = await resp.arrayBuffer();
|
|
61
|
+
const content = await decompress_data(buffer, `gzip`);
|
|
62
|
+
// Remove .gz extension when manually decompressing
|
|
63
|
+
return callback(content, filename.replace(/\.gz$/, ``));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// For H5 files, always load as binary regardless of signature
|
|
67
|
+
// to handle files that have .h5/.hdf5 extensions but may not have the proper HDF5 signature
|
|
68
|
+
if (ext === `h5` || ext === `hdf5`) {
|
|
69
|
+
const result = await load_binary_traj(resp, `H5`, true);
|
|
70
|
+
// Log warning if signature doesn't match (only for ArrayBuffer results)
|
|
71
|
+
if (result instanceof ArrayBuffer && result.byteLength >= 8) {
|
|
72
|
+
const view = new Uint8Array(result.slice(0, 8));
|
|
73
|
+
const hdf5_signature = [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
74
|
+
if (!hdf5_signature.every((byte, idx) => view[idx] === byte)) {
|
|
75
|
+
console.warn(`File has .h5/.hdf5 extension but missing HDF5 signature`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return callback(result, filename);
|
|
79
|
+
}
|
|
80
|
+
// For .traj files, ensure we always get ArrayBuffer for proper ASE parsing
|
|
81
|
+
if (ext === `traj`) {
|
|
82
|
+
const buffer = await load_binary_traj(resp, `.traj`);
|
|
83
|
+
return callback(buffer, filename);
|
|
84
|
+
}
|
|
85
|
+
if (resp.headers.get(`content-encoding`) === `gzip`) {
|
|
86
|
+
return callback(await resp.text(), filename);
|
|
87
|
+
}
|
|
88
|
+
return callback(await resp.arrayBuffer(), filename);
|
|
89
|
+
}
|
|
90
|
+
// Skip Range requests for known text formats to avoid production server issues
|
|
91
|
+
// Include VASP files that don't have extensions (POSCAR, XDATCAR, CONTCAR)
|
|
92
|
+
const is_known_text = TEXT_EXTENSIONS.has(ext) || VASP_BASENAME_RE.test(url_basename);
|
|
93
|
+
if (!is_known_text) {
|
|
94
|
+
try {
|
|
95
|
+
// Check for magic bytes only for unknown formats
|
|
96
|
+
const head = await fetch(url, { headers: { Range: `bytes=0-15` } });
|
|
97
|
+
if (head.ok) {
|
|
98
|
+
const buf = new Uint8Array(await head.arrayBuffer());
|
|
99
|
+
const is_gzip = buf[0] === 0x1f && buf[1] === 0x8b;
|
|
100
|
+
const is_hdf5 = buf[0] === 0x89 && buf[1] === 0x48 && buf[2] === 0x44 && buf[3] === 0x46;
|
|
101
|
+
if (is_gzip || is_hdf5) {
|
|
102
|
+
const resp = await fetch(url);
|
|
103
|
+
if (!resp.ok)
|
|
104
|
+
throw new Error(`Fetch failed: ${resp.status}`);
|
|
105
|
+
return callback(await resp.arrayBuffer(), extract_filename(resp.headers, url_basename));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Fall through to text fetch if HEAD request fails
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const resp = await fetch(url);
|
|
114
|
+
if (!resp.ok)
|
|
115
|
+
throw new Error(`Fetch failed: ${resp.status}`);
|
|
116
|
+
return callback(await resp.text(), extract_filename(resp.headers, url_basename));
|
|
117
|
+
}
|
|
@@ -1,122 +1,232 @@
|
|
|
1
|
-
<script lang="ts"
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Threlte component that renders isosurface meshes from volumetric data using marching cubes.
|
|
3
|
+
// Supports multiple layers at different isovalues with independent colors,
|
|
4
|
+
// plus positive/negative lobes and two-pass transparency.
|
|
5
|
+
import { marching_cubes } from '../marching-cubes'
|
|
6
|
+
import type { Matrix3x3, Vec3 } from '../math'
|
|
7
|
+
import { T } from '@threlte/core'
|
|
8
|
+
import {
|
|
9
|
+
BackSide,
|
|
10
|
+
BufferAttribute,
|
|
11
|
+
BufferGeometry,
|
|
12
|
+
DoubleSide,
|
|
13
|
+
FrontSide,
|
|
14
|
+
Uint32BufferAttribute,
|
|
15
|
+
} from 'three'
|
|
16
|
+
import type { IsosurfaceLayer, IsosurfaceSettings, VolumetricData } from './types'
|
|
17
|
+
import {
|
|
18
|
+
DEFAULT_ISOSURFACE_SETTINGS,
|
|
19
|
+
downsample_grid,
|
|
20
|
+
pad_periodic_grid,
|
|
21
|
+
} from './types'
|
|
22
|
+
|
|
23
|
+
let { volume, settings = DEFAULT_ISOSURFACE_SETTINGS }: {
|
|
24
|
+
volume: VolumetricData
|
|
25
|
+
settings?: IsosurfaceSettings
|
|
26
|
+
} = $props()
|
|
27
|
+
|
|
28
|
+
// Resolve layers: use explicit layers array if provided, else build from single-isovalue settings
|
|
29
|
+
let resolved_layers = $derived.by((): IsosurfaceLayer[] => {
|
|
30
|
+
if (settings.layers?.length) return settings.layers
|
|
13
31
|
return [{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
isovalue: settings.isovalue,
|
|
33
|
+
color: settings.positive_color,
|
|
34
|
+
opacity: settings.opacity,
|
|
35
|
+
visible: true,
|
|
36
|
+
show_negative: settings.show_negative,
|
|
37
|
+
negative_color: settings.negative_color,
|
|
38
|
+
}]
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// Build indexed BufferGeometry from marching cubes output.
|
|
42
|
+
// Uses Three.js index buffer to avoid tripling vertex data, and
|
|
43
|
+
// computeVertexNormals() for fast GPU-friendly normals.
|
|
44
|
+
function build_geometry(
|
|
45
|
+
vertices: Vec3[],
|
|
46
|
+
faces: number[][],
|
|
47
|
+
): BufferGeometry | null {
|
|
48
|
+
if (vertices.length === 0 || faces.length === 0) return null
|
|
49
|
+
|
|
28
50
|
// Flatten vertices: Vec3[] → Float32Array
|
|
29
|
-
const positions = new Float32Array(vertices.length * 3)
|
|
51
|
+
const positions = new Float32Array(vertices.length * 3)
|
|
30
52
|
for (let idx = 0; idx < vertices.length; idx++) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
const vert = vertices[idx]
|
|
54
|
+
positions[idx * 3] = vert[0]
|
|
55
|
+
positions[idx * 3 + 1] = vert[1]
|
|
56
|
+
positions[idx * 3 + 2] = vert[2]
|
|
35
57
|
}
|
|
58
|
+
|
|
36
59
|
// Flatten face indices: number[][] → Uint32Array
|
|
37
|
-
const indices = new Uint32Array(faces.length * 3)
|
|
60
|
+
const indices = new Uint32Array(faces.length * 3)
|
|
38
61
|
for (let idx = 0; idx < faces.length; idx++) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
const face = faces[idx]
|
|
63
|
+
indices[idx * 3] = face[0]
|
|
64
|
+
indices[idx * 3 + 1] = face[1]
|
|
65
|
+
indices[idx * 3 + 2] = face[2]
|
|
43
66
|
}
|
|
44
|
-
|
|
45
|
-
geometry
|
|
46
|
-
geometry.
|
|
47
|
-
geometry.
|
|
48
|
-
geometry.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
if (!volume
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return;
|
|
67
|
+
|
|
68
|
+
const geometry = new BufferGeometry()
|
|
69
|
+
geometry.setAttribute(`position`, new BufferAttribute(positions, 3))
|
|
70
|
+
geometry.setIndex(new Uint32BufferAttribute(indices, 1))
|
|
71
|
+
geometry.computeVertexNormals()
|
|
72
|
+
geometry.computeBoundingSphere()
|
|
73
|
+
return geometry
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Downsample large grids once when volume changes to keep marching cubes interactive
|
|
77
|
+
let ds_result = $derived.by(() => {
|
|
78
|
+
if (!volume) return undefined
|
|
79
|
+
return downsample_grid(volume.grid, volume.grid_dims)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Run marching cubes at the given isovalue with pre-prepared grid/lattice/shift.
|
|
83
|
+
function extract_surface(
|
|
84
|
+
isovalue: number,
|
|
85
|
+
mc_grid: number[][][],
|
|
86
|
+
mc_lattice: Matrix3x3,
|
|
87
|
+
origin_shift: Vec3 | null,
|
|
88
|
+
): BufferGeometry | null {
|
|
89
|
+
if (isovalue === 0) return null
|
|
90
|
+
|
|
91
|
+
const result = marching_cubes(mc_grid, isovalue, mc_lattice, {
|
|
92
|
+
periodic: false,
|
|
93
|
+
interpolate: true,
|
|
94
|
+
centered: false,
|
|
95
|
+
normals: false,
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
if (origin_shift) {
|
|
99
|
+
for (const vert of result.vertices) {
|
|
100
|
+
vert[0] += origin_shift[0]
|
|
101
|
+
vert[1] += origin_shift[1]
|
|
102
|
+
vert[2] += origin_shift[2]
|
|
103
|
+
}
|
|
82
104
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
|
|
106
|
+
return build_geometry(result.vertices, result.faces)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// === Multi-layer geometry management ===
|
|
110
|
+
// Each layer produces up to 2 geometries (positive + optional negative lobe).
|
|
111
|
+
// Keyed by "layer_idx:sign" for cache invalidation.
|
|
112
|
+
type GeoEntry = {
|
|
113
|
+
geometry: BufferGeometry
|
|
114
|
+
color: string
|
|
115
|
+
opacity: number
|
|
116
|
+
render_order: number
|
|
117
|
+
}
|
|
118
|
+
let active_geometries = $state<GeoEntry[]>([])
|
|
119
|
+
let raf_id = 0
|
|
120
|
+
let debounce_id = 0
|
|
121
|
+
|
|
122
|
+
// Dispose all current geometries
|
|
123
|
+
function dispose_all() {
|
|
124
|
+
for (const entry of active_geometries) entry.geometry.dispose()
|
|
125
|
+
active_geometries = []
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Dispose on unmount
|
|
129
|
+
$effect(() => () => dispose_all())
|
|
130
|
+
|
|
131
|
+
function rebuild_geometries(layers: IsosurfaceLayer[]) {
|
|
132
|
+
if (!volume || !ds_result) return
|
|
133
|
+
const old = active_geometries
|
|
134
|
+
const entries: GeoEntry[] = []
|
|
135
|
+
|
|
136
|
+
// Prepare grid/lattice/shift once for all layers.
|
|
137
|
+
// When halo > 0 for periodic volumes, the downsampled grid is padded with
|
|
138
|
+
// halo cells from the opposite face so isosurfaces extend beyond the unit
|
|
139
|
+
// cell and close into complete enclosed shapes around boundary atoms.
|
|
140
|
+
let mc_grid = ds_result.grid
|
|
141
|
+
let mc_lattice: Matrix3x3 = volume.lattice
|
|
142
|
+
let origin_shift: Vec3 | null = null
|
|
143
|
+
|
|
144
|
+
if (settings.halo > 0 && volume.periodic) {
|
|
145
|
+
const padded = pad_periodic_grid(ds_result.grid, ds_result.dims, settings.halo)
|
|
146
|
+
mc_grid = padded.grid
|
|
147
|
+
// marching_cubes maps [0,1] fractional -> Cartesian via lattice.
|
|
148
|
+
// The padded grid covers a wider fractional range, so scale the lattice
|
|
149
|
+
// to match. Then shift all vertices by the fractional offset.
|
|
150
|
+
const [la, lb, lc] = volume.lattice
|
|
151
|
+
const sx = padded.dims[0] / ds_result.dims[0]
|
|
152
|
+
const sy = padded.dims[1] / ds_result.dims[1]
|
|
153
|
+
const sz = padded.dims[2] / ds_result.dims[2]
|
|
154
|
+
mc_lattice = [
|
|
155
|
+
[la[0] * sx, la[1] * sx, la[2] * sx],
|
|
156
|
+
[lb[0] * sy, lb[1] * sy, lb[2] * sy],
|
|
157
|
+
[lc[0] * sz, lc[1] * sz, lc[2] * sz],
|
|
158
|
+
]
|
|
159
|
+
const [ox, oy, oz] = padded.offset
|
|
160
|
+
origin_shift = [
|
|
161
|
+
ox * la[0] + oy * lb[0] + oz * lc[0],
|
|
162
|
+
ox * la[1] + oy * lb[1] + oz * lc[1],
|
|
163
|
+
ox * la[2] + oy * lb[2] + oz * lc[2],
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const surface_at = (isovalue: number) =>
|
|
168
|
+
extract_surface(isovalue, mc_grid, mc_lattice, origin_shift)
|
|
169
|
+
|
|
170
|
+
// Render lower-isovalue (outer) shells earlier so per-layer back/front passes
|
|
171
|
+
// interleave back-to-front across shells and reduce transparency artefacts.
|
|
172
|
+
const layer_render_rank = new Map<number, number>(
|
|
173
|
+
layers
|
|
174
|
+
.map((layer, layer_idx) => ({ layer_idx, isovalue: layer.isovalue }))
|
|
175
|
+
.sort((layer_a, layer_b) => layer_a.isovalue - layer_b.isovalue)
|
|
176
|
+
.map(({ layer_idx }, rank) => [layer_idx, rank]),
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
for (let layer_idx = 0; layer_idx < layers.length; layer_idx++) {
|
|
180
|
+
const layer = layers[layer_idx]
|
|
181
|
+
if (!layer.visible || layer.isovalue <= 0) continue
|
|
182
|
+
|
|
183
|
+
// Each layer gets 4 slots (positive back/front + negative back/front).
|
|
184
|
+
const base_order = (layer_render_rank.get(layer_idx) ?? layer_idx) * 4
|
|
185
|
+
|
|
186
|
+
const pos_geo = surface_at(layer.isovalue)
|
|
187
|
+
if (pos_geo) {
|
|
188
|
+
entries.push({
|
|
189
|
+
geometry: pos_geo,
|
|
190
|
+
color: layer.color,
|
|
191
|
+
opacity: layer.opacity,
|
|
192
|
+
render_order: base_order,
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (layer.show_negative) {
|
|
197
|
+
const neg_geo = surface_at(-layer.isovalue)
|
|
198
|
+
if (neg_geo) {
|
|
199
|
+
entries.push({
|
|
200
|
+
geometry: neg_geo,
|
|
201
|
+
color: layer.negative_color,
|
|
202
|
+
opacity: layer.opacity,
|
|
203
|
+
render_order: base_order + 2,
|
|
204
|
+
})
|
|
113
205
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
active_geometries = entries
|
|
210
|
+
for (const entry of old) entry.geometry.dispose()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Rebuild all layer geometries when layers or volume change.
|
|
214
|
+
// Debounces rapid changes (e.g. slider drags) to avoid repeated expensive marching cubes.
|
|
215
|
+
$effect(() => {
|
|
216
|
+
const layers = resolved_layers
|
|
217
|
+
void settings.halo
|
|
218
|
+
if (!ds_result) {
|
|
219
|
+
dispose_all()
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
debounce_id = window.setTimeout(() => {
|
|
223
|
+
raf_id = requestAnimationFrame(() => rebuild_geometries(layers))
|
|
224
|
+
}, 50)
|
|
225
|
+
return () => {
|
|
226
|
+
clearTimeout(debounce_id)
|
|
227
|
+
cancelAnimationFrame(raf_id)
|
|
228
|
+
}
|
|
229
|
+
})
|
|
120
230
|
</script>
|
|
121
231
|
|
|
122
232
|
<!-- Render each geometry entry with appropriate material -->
|
|
@@ -1,35 +1,53 @@
|
|
|
1
|
-
<script lang="ts"
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Controls panel for isosurface visualization settings (isovalue, opacity, colors, etc.)
|
|
3
|
+
// Supports both single-isovalue mode and multi-layer mode.
|
|
4
|
+
import { format_num } from '../labels'
|
|
5
|
+
import { SettingsSection } from '../layout'
|
|
6
|
+
import { tooltip } from 'svelte-multiselect/attachments'
|
|
7
|
+
import type { IsosurfaceLayer, IsosurfaceSettings, VolumetricData } from './types'
|
|
8
|
+
import { DEFAULT_ISOSURFACE_SETTINGS, generate_layers } from './types'
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
settings = $bindable({ ...DEFAULT_ISOSURFACE_SETTINGS }),
|
|
12
|
+
volumes = [],
|
|
13
|
+
active_volume_idx = $bindable(0),
|
|
14
|
+
}: {
|
|
15
|
+
settings?: IsosurfaceSettings
|
|
16
|
+
volumes?: VolumetricData[]
|
|
17
|
+
active_volume_idx?: number
|
|
18
|
+
} = $props()
|
|
19
|
+
|
|
20
|
+
// Clamp active_volume_idx when volumes list changes (e.g. dataset swap)
|
|
21
|
+
$effect(() => {
|
|
10
22
|
if (volumes.length > 0 && active_volume_idx >= volumes.length) {
|
|
11
|
-
|
|
23
|
+
active_volume_idx = 0
|
|
12
24
|
}
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Use precomputed data_range from the active volume
|
|
28
|
+
let data_range = $derived(
|
|
29
|
+
volumes[active_volume_idx]?.data_range ?? { min: 0, max: 1, abs_max: 1, mean: 0 },
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
let slider_max = $derived(Math.max(data_range.abs_max, 0.001))
|
|
33
|
+
let step = $derived(slider_max / 200)
|
|
34
|
+
let is_multi_layer = $derived((settings.layers?.length ?? 0) > 0)
|
|
35
|
+
let n_layers = $derived(settings.layers?.length ?? 1)
|
|
36
|
+
|
|
37
|
+
function set_layer_count(count: number) {
|
|
21
38
|
if (count <= 1) {
|
|
22
|
-
|
|
39
|
+
settings.layers = undefined
|
|
40
|
+
} else {
|
|
41
|
+
settings.layers = generate_layers(data_range, count)
|
|
23
42
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function update_layer(idx: number, updates: Partial<IsosurfaceLayer>) {
|
|
46
|
+
if (!settings.layers) return
|
|
47
|
+
settings.layers = settings.layers.map((layer, layer_idx) =>
|
|
48
|
+
layer_idx === idx ? { ...layer, ...updates } : layer
|
|
49
|
+
)
|
|
50
|
+
}
|
|
33
51
|
</script>
|
|
34
52
|
|
|
35
53
|
<SettingsSection
|
|
@@ -39,6 +57,7 @@ function update_layer(idx, updates) {
|
|
|
39
57
|
opacity: settings.opacity,
|
|
40
58
|
show_negative: settings.show_negative,
|
|
41
59
|
wireframe: settings.wireframe,
|
|
60
|
+
halo: settings.halo,
|
|
42
61
|
layers: n_layers,
|
|
43
62
|
}}
|
|
44
63
|
on_reset={() => {
|
|
@@ -205,6 +224,24 @@ function update_layer(idx, updates) {
|
|
|
205
224
|
</div>
|
|
206
225
|
{/if}
|
|
207
226
|
|
|
227
|
+
{#if volumes?.[active_volume_idx]?.periodic}
|
|
228
|
+
<label
|
|
229
|
+
{@attach tooltip({
|
|
230
|
+
content:
|
|
231
|
+
`Extend isosurface beyond cell boundaries to close partial spheres (fraction of cell)`,
|
|
232
|
+
})}
|
|
233
|
+
>
|
|
234
|
+
Halo: {format_num(settings.halo, `.2f`)}
|
|
235
|
+
<input
|
|
236
|
+
type="range"
|
|
237
|
+
min={0}
|
|
238
|
+
max={0.5}
|
|
239
|
+
step={0.01}
|
|
240
|
+
bind:value={settings.halo}
|
|
241
|
+
/>
|
|
242
|
+
</label>
|
|
243
|
+
{/if}
|
|
244
|
+
|
|
208
245
|
{#if volumes[active_volume_idx]}
|
|
209
246
|
<div class="grid-info">
|
|
210
247
|
{volumes[active_volume_idx].grid_dims.join(` × `)} grid | [{
|