matterviz 0.4.2 → 0.4.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/FilePicker.svelte +40 -50
- package/dist/api/optimade.js +10 -7
- package/dist/app.css +15 -0
- package/dist/brillouin/BrillouinZone.svelte +18 -9
- package/dist/brillouin/BrillouinZoneScene.svelte +20 -29
- package/dist/brillouin/compute.js +10 -16
- package/dist/brillouin/geometry.js +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +18 -15
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +17 -113
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +104 -264
- package/dist/chempot-diagram/async-compute.svelte.js +12 -13
- package/dist/chempot-diagram/color.d.ts +21 -1
- package/dist/chempot-diagram/color.js +70 -1
- package/dist/chempot-diagram/compute.d.ts +7 -0
- package/dist/chempot-diagram/compute.js +85 -26
- package/dist/chempot-diagram/export.js +1 -6
- package/dist/chempot-diagram/temperature.js +9 -10
- package/dist/composition/BarChart.svelte +7 -9
- package/dist/composition/Composition.svelte +3 -8
- package/dist/composition/Formula.svelte +2 -2
- package/dist/composition/FormulaFilter.svelte +27 -93
- package/dist/composition/format.js +6 -8
- package/dist/composition/parse.js +50 -105
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +6 -17
- package/dist/convex-hull/ConvexHull2D.svelte +0 -2
- package/dist/convex-hull/ConvexHull3D.svelte +19 -47
- package/dist/convex-hull/ConvexHull4D.svelte +65 -95
- package/dist/convex-hull/StructurePopup.svelte +1 -1
- package/dist/convex-hull/gas-thermodynamics.js +21 -53
- package/dist/convex-hull/helpers.js +1 -7
- package/dist/convex-hull/thermodynamics.js +19 -27
- package/dist/coordination/CoordinationBarPlot.svelte +12 -21
- package/dist/element/BohrAtom.svelte +0 -1
- package/dist/element/ElementTile.svelte +26 -44
- package/dist/element/data.d.ts +2 -0
- package/dist/element/data.js +5 -1
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -1
- package/dist/fermi-surface/FermiSurface.svelte +22 -23
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +2 -6
- package/dist/fermi-surface/FermiSurfaceScene.svelte +32 -77
- package/dist/fermi-surface/compute.js +22 -55
- package/dist/fermi-surface/parse.js +38 -70
- package/dist/file-viewer/JsonBrowser.svelte +1043 -0
- package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
- package/dist/file-viewer/PlotPanel.svelte +350 -0
- package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
- package/dist/file-viewer/detect.d.ts +11 -0
- package/dist/file-viewer/detect.js +381 -0
- package/dist/file-viewer/eligibility.d.ts +4 -0
- package/dist/file-viewer/eligibility.js +53 -0
- package/dist/file-viewer/host-protocol.d.ts +50 -0
- package/dist/file-viewer/host-transfer.d.ts +25 -0
- package/dist/file-viewer/host-transfer.js +42 -0
- package/dist/file-viewer/index.d.ts +5 -0
- package/dist/file-viewer/index.js +5 -0
- package/dist/file-viewer/main.d.ts +44 -0
- package/dist/file-viewer/main.js +535 -0
- package/dist/file-viewer/parse.d.ts +9 -0
- package/dist/file-viewer/parse.js +170 -0
- package/dist/file-viewer/plot-utils.d.ts +24 -0
- package/dist/file-viewer/plot-utils.js +191 -0
- package/dist/file-viewer/types.d.ts +4 -0
- package/dist/file-viewer/types.js +5 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +57 -84
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/io/ExportPane.svelte +1 -1
- package/dist/io/decompress.d.ts +2 -0
- package/dist/io/decompress.js +3 -2
- package/dist/io/export.d.ts +7 -4
- package/dist/io/export.js +70 -18
- package/dist/io/file-drop.js +60 -35
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +28 -16
- package/dist/isosurface/Isosurface.svelte +687 -196
- package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +564 -85
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
- package/dist/isosurface/VolumeSlice.svelte +224 -0
- package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
- package/dist/isosurface/coloring.d.ts +20 -0
- package/dist/isosurface/coloring.js +118 -0
- package/dist/isosurface/geometry-worker-types.d.ts +38 -0
- package/dist/isosurface/geometry.worker.d.ts +1 -0
- package/dist/isosurface/geometry.worker.js +59 -0
- package/dist/isosurface/grid.d.ts +10 -0
- package/dist/isosurface/grid.js +31 -0
- package/dist/isosurface/index.d.ts +4 -0
- package/dist/isosurface/index.js +4 -0
- package/dist/isosurface/profile.d.ts +12 -0
- package/dist/isosurface/profile.js +19 -0
- package/dist/isosurface/sampling.d.ts +34 -0
- package/dist/isosurface/sampling.js +408 -0
- package/dist/isosurface/slice-rendering.d.ts +13 -0
- package/dist/isosurface/slice-rendering.js +79 -0
- package/dist/isosurface/slice.d.ts +22 -2
- package/dist/isosurface/slice.js +200 -116
- package/dist/isosurface/types.d.ts +24 -1
- package/dist/isosurface/types.js +120 -8
- package/dist/json-path.d.ts +4 -0
- package/dist/json-path.js +89 -0
- package/dist/labels.js +1 -1
- package/dist/layout/InfoCard.svelte +1 -3
- package/dist/layout/SettingsSection.svelte +52 -61
- package/dist/layout/SettingsSection.svelte.d.ts +6 -7
- package/dist/layout/ViewerChrome.svelte +7 -1
- package/dist/layout/json-tree/JsonNode.svelte +14 -48
- package/dist/layout/json-tree/JsonTree.svelte +48 -95
- package/dist/layout/json-tree/JsonValue.svelte +3 -18
- package/dist/layout/json-tree/utils.d.ts +0 -3
- package/dist/layout/json-tree/utils.js +50 -179
- package/dist/marching-cubes.d.ts +8 -1
- package/dist/marching-cubes.js +115 -48
- package/dist/math.d.ts +3 -2
- package/dist/math.js +29 -38
- package/dist/overlays/ContextMenu.svelte +15 -32
- package/dist/overlays/DraggablePane.svelte +39 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -1
- package/dist/overlays/GlassChip.svelte +3 -1
- package/dist/periodic-table/PeriodicTableControls.svelte +26 -52
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +18 -34
- package/dist/phase-diagram/build-diagram.js +1 -6
- package/dist/phase-diagram/svg-to-diagram.js +9 -14
- package/dist/plot/bar/BarPlot.svelte +38 -42
- package/dist/plot/bar/SpacegroupBarPlot.svelte +18 -42
- package/dist/plot/box/BoxPlot.svelte +27 -23
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/data-transform.d.ts +1 -2
- package/dist/plot/core/data-transform.js +0 -10
- package/dist/plot/core/layout.d.ts +12 -5
- package/dist/plot/core/layout.js +37 -27
- package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
- package/dist/plot/core/pan-zoom.svelte.js +34 -17
- package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -21
- package/dist/plot/core/svg.js +0 -1
- package/dist/plot/core/utils/hierarchy-chart.d.ts +1 -0
- package/dist/plot/core/utils/hierarchy-chart.js +12 -0
- package/dist/plot/core/utils/hierarchy-labels.js +3 -2
- package/dist/plot/histogram/Histogram.svelte +21 -26
- package/dist/plot/sankey/sankey.js +13 -9
- package/dist/plot/scatter/BinnedScatterPlot.svelte +59 -43
- package/dist/plot/scatter/ScatterPlot.svelte +67 -52
- package/dist/plot/scatter/adaptive-density.d.ts +1 -1
- package/dist/plot/scatter/adaptive-density.js +36 -20
- package/dist/plot/sunburst/Sunburst.svelte +20 -20
- package/dist/plot/treemap/Treemap.svelte +175 -60
- package/dist/plot/treemap/Treemap.svelte.d.ts +6 -0
- package/dist/plot/treemap/index.d.ts +1 -0
- package/dist/plot/treemap/labels.d.ts +38 -0
- package/dist/plot/treemap/labels.js +80 -0
- package/dist/plot/treemap/treemap.d.ts +4 -2
- package/dist/plot/treemap/treemap.js +5 -2
- package/dist/rdf/RdfPlot.svelte +17 -35
- package/dist/rdf/calc-rdf.js +59 -44
- package/dist/rdf/index.d.ts +0 -1
- package/dist/sanitize.js +84 -26
- package/dist/scene/SceneCamera.svelte +1 -1
- package/dist/scene/SceneCamera.svelte.d.ts +1 -1
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +1 -1
- package/dist/scene/{props.js → props.svelte.js} +15 -1
- package/dist/settings.js +159 -482
- package/dist/spectral/Bands.svelte +151 -158
- package/dist/spectral/BrillouinBandsDos.svelte +4 -19
- package/dist/spectral/Dos.svelte +26 -24
- package/dist/spectral/helpers.js +40 -105
- package/dist/structure/AtomLegend.svelte +8 -13
- package/dist/structure/AtomLegend.svelte.d.ts +2 -3
- package/dist/structure/CellSelect.svelte +35 -10
- package/dist/structure/Structure.svelte +177 -99
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureCarousel.svelte +10 -3
- package/dist/structure/StructureControls.svelte +8 -26
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +65 -76
- package/dist/structure/StructureScene.svelte +75 -109
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +120 -55
- package/dist/structure/StructureViewport.svelte.d.ts +3 -1
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +4 -3
- package/dist/structure/bond-order-perception.js +3 -8
- package/dist/structure/bonding.d.ts +0 -1
- package/dist/structure/bonding.js +16 -23
- package/dist/structure/export.js +50 -74
- package/dist/structure/format-detect.js +5 -7
- package/dist/structure/index.js +6 -12
- package/dist/structure/parse.js +38 -100
- package/dist/structure/partial-occupancy.js +7 -4
- package/dist/structure/pbc.js +8 -10
- package/dist/structure/polyhedra.js +5 -4
- package/dist/structure/prop-groups.d.ts +85 -0
- package/dist/structure/prop-groups.js +18 -0
- package/dist/symmetry/SymmetryStats.svelte +0 -4
- package/dist/symmetry/WyckoffTable.svelte +5 -4
- package/dist/symmetry/cell-transform.js +5 -14
- package/dist/symmetry/index.js +6 -9
- package/dist/table/HeatmapTable.svelte +61 -103
- package/dist/table/ToggleMenu.svelte +166 -44
- package/dist/table/ToggleMenu.svelte.d.ts +1 -1
- package/dist/theme/embedded.d.ts +18 -0
- package/dist/theme/embedded.js +206 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +1 -2
- package/dist/theme/themes.mjs +31 -60
- package/dist/tooltip/TooltipContent.svelte +1 -1
- package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
- package/dist/tooltip/index.d.ts +8 -1
- package/dist/trajectory/Trajectory.svelte +140 -120
- package/dist/trajectory/TrajectoryError.svelte +1 -66
- package/dist/trajectory/TrajectoryExportPane.svelte +0 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +55 -80
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
- package/dist/trajectory/extract.js +19 -29
- package/dist/trajectory/format-detect.d.ts +2 -0
- package/dist/trajectory/format-detect.js +7 -5
- package/dist/trajectory/frame-reader.js +3 -4
- package/dist/trajectory/helpers.js +16 -49
- package/dist/trajectory/index.js +2 -8
- package/dist/trajectory/parse/ase.js +1 -1
- package/dist/trajectory/parse/index.d.ts +4 -3
- package/dist/trajectory/parse/index.js +12 -17
- package/dist/trajectory/parse/vaspout-h5.d.ts +0 -1
- package/dist/trajectory/parse/vaspout-h5.js +1 -4
- package/dist/trajectory/parse/xyz.js +48 -2
- package/dist/trajectory/plotting.js +14 -37
- package/dist/xrd/XrdPlot.svelte +43 -68
- package/dist/xrd/calc-xrd.js +22 -58
- package/dist/xrd/parse.js +13 -22
- package/package.json +40 -8
- package/readme.md +6 -5
- package/dist/scene/types.d.ts +0 -26
- package/dist/tooltip/types.d.ts +0 -8
- package/dist/trajectory/constants.d.ts +0 -6
- package/dist/trajectory/constants.js +0 -11
- /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
- /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
package/dist/element/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type * from './types';
|
|
2
2
|
export { default as BohrAtom } from './BohrAtom.svelte';
|
|
3
|
-
export { default as element_data } from './data';
|
|
3
|
+
export { default as element_data, element_by_symbol } from './data';
|
|
4
4
|
export { default as ElementHeading } from './ElementHeading.svelte';
|
|
5
5
|
export { default as ElementPhoto } from './ElementPhoto.svelte';
|
|
6
6
|
export { default as ElementStats } from './ElementStats.svelte';
|
package/dist/element/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as BohrAtom } from './BohrAtom.svelte';
|
|
2
|
-
export { default as element_data } from './data';
|
|
2
|
+
export { default as element_data, element_by_symbol } from './data';
|
|
3
3
|
export { default as ElementHeading } from './ElementHeading.svelte';
|
|
4
4
|
export { default as ElementPhoto } from './ElementPhoto.svelte';
|
|
5
5
|
export { default as ElementStats } from './ElementStats.svelte';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import EmptyState from '../EmptyState.svelte'
|
|
6
6
|
import { StatusMessage } from '../feedback'
|
|
7
7
|
import Spinner from '../feedback/Spinner.svelte'
|
|
8
|
-
import
|
|
8
|
+
import * as io from '../io'
|
|
9
9
|
import { type FullscreenToggleProp, toggle_fullscreen, ViewerChrome } from '../layout'
|
|
10
10
|
import { sync_fullscreen } from '../layout/fullscreen.svelte'
|
|
11
11
|
import { PlotTooltip } from '../plot'
|
|
@@ -34,13 +34,9 @@
|
|
|
34
34
|
RepresentationMode,
|
|
35
35
|
} from './types'
|
|
36
36
|
|
|
37
|
-
type
|
|
37
|
+
type FermiFullscreenData = {
|
|
38
38
|
fermi_data?: FermiSurfaceData
|
|
39
|
-
band_data?: BandGridData
|
|
40
39
|
bz_data?: BrillouinZoneData
|
|
41
|
-
filename?: string
|
|
42
|
-
file_size?: number
|
|
43
|
-
error_msg?: string
|
|
44
40
|
fullscreen?: boolean
|
|
45
41
|
}
|
|
46
42
|
|
|
@@ -140,7 +136,7 @@
|
|
|
140
136
|
on_file_drop?: (filename: string) => void
|
|
141
137
|
on_file_load?: (data: FermiFileLoadData) => void
|
|
142
138
|
on_error?: (data: FermiErrorData) => void
|
|
143
|
-
on_fullscreen_change?: (data:
|
|
139
|
+
on_fullscreen_change?: (data: FermiFullscreenData) => void
|
|
144
140
|
on_mu_change?: (mu: number) => void
|
|
145
141
|
tooltip_config?: Snippet<[{ hover_data: FermiHoverData }]> | FermiTooltipConfig
|
|
146
142
|
on_point_hover?: (data: FermiHoverData | null) => void
|
|
@@ -303,23 +299,26 @@
|
|
|
303
299
|
// Load from URL (with race condition protection for rapid URL changes)
|
|
304
300
|
let load_id = 0
|
|
305
301
|
$effect(() => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
})
|
|
319
|
-
|
|
302
|
+
const requested_url = data_url
|
|
303
|
+
if (!requested_url || fermi_data || band_data) return
|
|
304
|
+
const current_load_id = ++load_id
|
|
305
|
+
loading = true
|
|
306
|
+
error_msg = undefined
|
|
307
|
+
io.load_from_url(requested_url, (content, filename) => {
|
|
308
|
+
if (current_load_id !== load_id) return
|
|
309
|
+
return safe_parse(content, filename)
|
|
310
|
+
})
|
|
311
|
+
.catch((err) => {
|
|
312
|
+
if (current_load_id !== load_id) return
|
|
313
|
+
error_msg = to_error(err).message
|
|
314
|
+
on_error?.({ error_msg, filename: io.basename_from_url(requested_url) })
|
|
315
|
+
})
|
|
316
|
+
.finally(() => {
|
|
317
|
+
if (current_load_id === load_id) loading = false
|
|
318
|
+
})
|
|
320
319
|
})
|
|
321
320
|
|
|
322
|
-
const handle_file_drop = create_file_drop_handler({
|
|
321
|
+
const handle_file_drop = io.create_file_drop_handler({
|
|
323
322
|
allow: () => allow_file_drop,
|
|
324
323
|
on_drop: async (content, filename) => {
|
|
325
324
|
on_file_drop?.(filename)
|
|
@@ -368,7 +367,7 @@
|
|
|
368
367
|
onmouseenter={() => (hovered = true)}
|
|
369
368
|
onmouseleave={() => (hovered = false)}
|
|
370
369
|
ondrop={handle_file_drop}
|
|
371
|
-
{...drag_over_handlers({
|
|
370
|
+
{...io.drag_over_handlers({
|
|
372
371
|
allow: () => allow_file_drop,
|
|
373
372
|
set_dragover: (over) => (dragover = over),
|
|
374
373
|
})}
|
|
@@ -7,13 +7,9 @@ import type { Crystal } from '../structure';
|
|
|
7
7
|
import type { ComponentProps, Snippet } from 'svelte';
|
|
8
8
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
9
9
|
import type { BandGridData, ColorProperty, FermiErrorData, FermiFileLoadData, FermiHoverData, FermiSurfaceData, FermiTooltipConfig, RepresentationMode } from './types';
|
|
10
|
-
type
|
|
10
|
+
type FermiFullscreenData = {
|
|
11
11
|
fermi_data?: FermiSurfaceData;
|
|
12
|
-
band_data?: BandGridData;
|
|
13
12
|
bz_data?: BrillouinZoneData;
|
|
14
|
-
filename?: string;
|
|
15
|
-
file_size?: number;
|
|
16
|
-
error_msg?: string;
|
|
17
13
|
fullscreen?: boolean;
|
|
18
14
|
};
|
|
19
15
|
type $$ComponentProps = {
|
|
@@ -59,7 +55,7 @@ type $$ComponentProps = {
|
|
|
59
55
|
on_file_drop?: (filename: string) => void;
|
|
60
56
|
on_file_load?: (data: FermiFileLoadData) => void;
|
|
61
57
|
on_error?: (data: FermiErrorData) => void;
|
|
62
|
-
on_fullscreen_change?: (data:
|
|
58
|
+
on_fullscreen_change?: (data: FermiFullscreenData) => void;
|
|
63
59
|
on_mu_change?: (mu: number) => void;
|
|
64
60
|
tooltip_config?: Snippet<[{
|
|
65
61
|
hover_data: FermiHoverData;
|
|
@@ -172,21 +172,11 @@
|
|
|
172
172
|
|
|
173
173
|
// Map from surface to its render order based on size (inner surfaces first)
|
|
174
174
|
let surface_render_orders = $derived.by((): Map<Isosurface, number> => {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
surface,
|
|
181
|
-
radius: compute_surface_radius(surface),
|
|
182
|
-
}))
|
|
183
|
-
surfaces_with_radius.sort((a, b) => a.radius - b.radius)
|
|
184
|
-
|
|
185
|
-
// Assign render order: smaller radius (inner) = lower order = rendered first
|
|
186
|
-
for (let idx = 0; idx < surfaces_with_radius.length; idx++) {
|
|
187
|
-
order_map.set(surfaces_with_radius[idx].surface, idx)
|
|
188
|
-
}
|
|
189
|
-
return order_map
|
|
175
|
+
const by_radius = visible_surfaces
|
|
176
|
+
.map((surface) => ({ surface, radius: compute_surface_radius(surface) }))
|
|
177
|
+
.toSorted((surf_a, surf_b) => surf_a.radius - surf_b.radius)
|
|
178
|
+
// Smaller radius (inner) = lower order = rendered first
|
|
179
|
+
return new SvelteMap(by_radius.map(({ surface }, idx) => [surface, idx]))
|
|
190
180
|
})
|
|
191
181
|
|
|
192
182
|
// Compute property range for color scaling
|
|
@@ -538,79 +528,44 @@
|
|
|
538
528
|
|
|
539
529
|
{#if geo_data}
|
|
540
530
|
{#each symmetry_ops as sym_matrix, sym_idx (`sym-${sym_idx}`)}
|
|
541
|
-
{#
|
|
531
|
+
{#snippet mesh_pass(order: number, pass: `wireframe` | `front` | `back`)}
|
|
542
532
|
<T.Mesh
|
|
543
533
|
geometry={geo_data.geometry}
|
|
544
534
|
matrix={sym_matrix}
|
|
545
535
|
matrixAutoUpdate={false}
|
|
546
|
-
{
|
|
536
|
+
renderOrder={order}
|
|
547
537
|
onpointermove={(event: ThreltePointerEvent) =>
|
|
548
538
|
handle_pointer_move(event, surface, surface_color, sym_idx, sym_matrix)}
|
|
549
539
|
onpointerleave={clear_hover}
|
|
550
540
|
>
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
541
|
+
{#if pass === `wireframe`}
|
|
542
|
+
<T.MeshBasicMaterial
|
|
543
|
+
color={surface_color}
|
|
544
|
+
wireframe
|
|
545
|
+
transparent={surface_opacity < 1}
|
|
546
|
+
opacity={surface_opacity}
|
|
547
|
+
depthWrite={true}
|
|
548
|
+
depthTest={true}
|
|
549
|
+
/>
|
|
550
|
+
{:else}
|
|
551
|
+
<T.MeshStandardMaterial
|
|
552
|
+
{...get_material_props(surface_color, use_vertex_colors, surface_idx, pass)}
|
|
553
|
+
metalness={0.1}
|
|
554
|
+
roughness={0.6}
|
|
555
|
+
flatShading={false}
|
|
556
|
+
/>
|
|
557
|
+
{/if}
|
|
559
558
|
</T.Mesh>
|
|
559
|
+
{/snippet}
|
|
560
|
+
|
|
561
|
+
{#if representation === `wireframe`}
|
|
562
|
+
{@render mesh_pass(renderOrder, `wireframe`)}
|
|
560
563
|
{:else if surface_opacity < 1}
|
|
561
|
-
<!-- Two-pass rendering
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
geometry={geo_data.geometry}
|
|
565
|
-
matrix={sym_matrix}
|
|
566
|
-
matrixAutoUpdate={false}
|
|
567
|
-
renderOrder={renderOrder * 2}
|
|
568
|
-
onpointermove={(event: ThreltePointerEvent) =>
|
|
569
|
-
handle_pointer_move(event, surface, surface_color, sym_idx, sym_matrix)}
|
|
570
|
-
onpointerleave={clear_hover}
|
|
571
|
-
>
|
|
572
|
-
<T.MeshStandardMaterial
|
|
573
|
-
{...get_material_props(surface_color, use_vertex_colors, surface_idx, `back`)}
|
|
574
|
-
metalness={0.1}
|
|
575
|
-
roughness={0.6}
|
|
576
|
-
flatShading={false}
|
|
577
|
-
/>
|
|
578
|
-
</T.Mesh>
|
|
579
|
-
<!-- Pass 2: Front faces (rendered second, higher renderOrder) -->
|
|
580
|
-
<T.Mesh
|
|
581
|
-
geometry={geo_data.geometry}
|
|
582
|
-
matrix={sym_matrix}
|
|
583
|
-
matrixAutoUpdate={false}
|
|
584
|
-
renderOrder={renderOrder * 2 + 1}
|
|
585
|
-
onpointermove={(event: ThreltePointerEvent) =>
|
|
586
|
-
handle_pointer_move(event, surface, surface_color, sym_idx, sym_matrix)}
|
|
587
|
-
onpointerleave={clear_hover}
|
|
588
|
-
>
|
|
589
|
-
<T.MeshStandardMaterial
|
|
590
|
-
{...get_material_props(surface_color, use_vertex_colors, surface_idx, `front`)}
|
|
591
|
-
metalness={0.1}
|
|
592
|
-
roughness={0.6}
|
|
593
|
-
flatShading={false}
|
|
594
|
-
/>
|
|
595
|
-
</T.Mesh>
|
|
564
|
+
<!-- Two-pass transparent rendering: back faces first, front faces on top -->
|
|
565
|
+
{@render mesh_pass(renderOrder * 2, `back`)}
|
|
566
|
+
{@render mesh_pass(renderOrder * 2 + 1, `front`)}
|
|
596
567
|
{:else}
|
|
597
|
-
|
|
598
|
-
<T.Mesh
|
|
599
|
-
geometry={geo_data.geometry}
|
|
600
|
-
matrix={sym_matrix}
|
|
601
|
-
matrixAutoUpdate={false}
|
|
602
|
-
{renderOrder}
|
|
603
|
-
onpointermove={(event: ThreltePointerEvent) =>
|
|
604
|
-
handle_pointer_move(event, surface, surface_color, sym_idx, sym_matrix)}
|
|
605
|
-
onpointerleave={clear_hover}
|
|
606
|
-
>
|
|
607
|
-
<T.MeshStandardMaterial
|
|
608
|
-
{...get_material_props(surface_color, use_vertex_colors, surface_idx, `front`)}
|
|
609
|
-
metalness={0.1}
|
|
610
|
-
roughness={0.6}
|
|
611
|
-
flatShading={false}
|
|
612
|
-
/>
|
|
613
|
-
</T.Mesh>
|
|
568
|
+
{@render mesh_pass(renderOrder, `front`)}
|
|
614
569
|
{/if}
|
|
615
570
|
{/each}
|
|
616
571
|
{/if}
|
|
@@ -26,18 +26,15 @@ function tricubic_interpolate(grid, fx, fy, fz, px, py, pz) {
|
|
|
26
26
|
const iy = Math.floor(fy);
|
|
27
27
|
const iz = Math.floor(fz);
|
|
28
28
|
// Precompute Catmull-Rom coefficients
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
29
|
+
const cx = catmull_rom_coeffs(fx - ix);
|
|
30
|
+
const cy = catmull_rom_coeffs(fy - iy);
|
|
31
|
+
const cz = catmull_rom_coeffs(fz - iz);
|
|
32
32
|
// Wrapped stencil indices (modulo hoisted out of the inner loop); a zero period
|
|
33
33
|
// (single-point axis) has no neighbours, so collapse the stencil onto index 0
|
|
34
34
|
const stencil = (idx, period) => [idx - 1, idx, idx + 1, idx + 2].map((stencil_idx) => period > 0 ? ((stencil_idx % period) + period) % period : 0);
|
|
35
35
|
const [wx, wy, wz] = [stencil(ix, px), stencil(iy, py), stencil(iz, pz)];
|
|
36
36
|
// Interpolate along z, then y, then x (fully inlined)
|
|
37
37
|
let result = 0;
|
|
38
|
-
const cx = [cx0, cx1, cx2, cx3];
|
|
39
|
-
const cy = [cy0, cy1, cy2, cy3];
|
|
40
|
-
const cz = [cz0, cz1, cz2, cz3];
|
|
41
38
|
for (let xi = 0; xi < 4; xi++) {
|
|
42
39
|
const row = grid[wx[xi]];
|
|
43
40
|
let y_sum = 0;
|
|
@@ -286,36 +283,26 @@ function analyze_surface_topology(surface, k_lattice) {
|
|
|
286
283
|
spans[axis_idx] = surface_size > SPANNING_THRESHOLD * bz_size;
|
|
287
284
|
}
|
|
288
285
|
const n_spanning = spans.filter(Boolean).length;
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
// 0 spanning = closed 3D pocket; 3 spanning = complex warped network
|
|
287
|
+
if (n_spanning === 0)
|
|
291
288
|
return { dimensionality: `3D`, orientation: null };
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
else if (n_spanning === 2) {
|
|
301
|
-
// 1D noodle-like (tube spanning 2 directions, bounded in 1)
|
|
302
|
-
const axis_idx = spans.indexOf(false);
|
|
303
|
-
const orientation = [0, 0, 0];
|
|
304
|
-
orientation[axis_idx] = 1;
|
|
305
|
-
return { dimensionality: `1D`, orientation };
|
|
306
|
-
}
|
|
307
|
-
// Spans all 3 directions - complex warped network
|
|
308
|
-
return { dimensionality: `quasi-2D`, orientation: null };
|
|
289
|
+
if (n_spanning === 3)
|
|
290
|
+
return { dimensionality: `quasi-2D`, orientation: null };
|
|
291
|
+
// 1 spanning = 2D sheet (oriented along the spanning axis);
|
|
292
|
+
// 2 spanning = 1D noodle-like tube (oriented along the bounded axis)
|
|
293
|
+
const axis_idx = n_spanning === 1 ? spans.indexOf(true) : spans.indexOf(false);
|
|
294
|
+
const orientation = [0, 0, 0];
|
|
295
|
+
orientation[axis_idx] = 1;
|
|
296
|
+
return { dimensionality: n_spanning === 1 ? `2D` : `1D`, orientation };
|
|
309
297
|
}
|
|
310
298
|
// Compute 2D Fermi slice along a specified plane
|
|
311
299
|
export function compute_fermi_slice(fermi_data, options = {}) {
|
|
312
300
|
const { miller_indices = [0, 0, 1], distance = 0 } = options;
|
|
313
|
-
|
|
314
|
-
if (miller_indices[0] === 0 && miller_indices[1] === 0 && miller_indices[2] === 0) {
|
|
301
|
+
if (miller_indices.every((miller_idx) => miller_idx === 0)) {
|
|
315
302
|
throw new Error(`Invalid miller indices [0, 0, 0]: at least one index must be non-zero to define a plane`);
|
|
316
303
|
}
|
|
317
304
|
// Compute plane normal in Cartesian coordinates
|
|
318
|
-
const plane_normal = math.add(math.
|
|
305
|
+
const plane_normal = math.add(math.scale(fermi_data.k_lattice[0], miller_indices[0]), math.scale(fermi_data.k_lattice[1], miller_indices[1]), math.scale(fermi_data.k_lattice[2], miller_indices[2]));
|
|
319
306
|
const normal_len = Math.hypot(...plane_normal);
|
|
320
307
|
if (normal_len < EPS) {
|
|
321
308
|
throw new Error(`Degenerate plane normal: k_lattice vectors produce a zero-length normal for miller indices [${miller_indices.join(`, `)}]`);
|
|
@@ -324,11 +311,7 @@ export function compute_fermi_slice(fermi_data, options = {}) {
|
|
|
324
311
|
// Compute in-plane basis vectors
|
|
325
312
|
const [in_plane_u, in_plane_v] = math.compute_in_plane_basis(unit_normal);
|
|
326
313
|
// Slice each isosurface
|
|
327
|
-
const isolines =
|
|
328
|
-
for (const surface of fermi_data.isosurfaces) {
|
|
329
|
-
const lines = slice_surface_with_plane(surface, unit_normal, distance, in_plane_u, in_plane_v);
|
|
330
|
-
isolines.push(...lines);
|
|
331
|
-
}
|
|
314
|
+
const isolines = fermi_data.isosurfaces.flatMap((surface) => slice_surface_with_plane(surface, unit_normal, distance, in_plane_u, in_plane_v));
|
|
332
315
|
return {
|
|
333
316
|
isolines,
|
|
334
317
|
plane_normal: unit_normal,
|
|
@@ -340,8 +323,6 @@ export function compute_fermi_slice(fermi_data, options = {}) {
|
|
|
340
323
|
},
|
|
341
324
|
};
|
|
342
325
|
}
|
|
343
|
-
// Helper to create edge key (sorted vertex indices)
|
|
344
|
-
const make_edge_key = (v0_idx, v1_idx) => `${Math.min(v0_idx, v1_idx)},${Math.max(v0_idx, v1_idx)}`;
|
|
345
326
|
// Compute intersection point on an edge
|
|
346
327
|
function compute_edge_intersection(surface, vertex_distances, v0_idx, v1_idx) {
|
|
347
328
|
const d0 = vertex_distances[v0_idx];
|
|
@@ -383,7 +364,7 @@ function slice_surface_with_plane(surface, plane_normal, plane_distance, in_plan
|
|
|
383
364
|
for (let edge_idx = 0; edge_idx < face.length; edge_idx++) {
|
|
384
365
|
const v0_idx = face[edge_idx];
|
|
385
366
|
const v1_idx = face[(edge_idx + 1) % face.length];
|
|
386
|
-
const edge_key =
|
|
367
|
+
const edge_key = `${Math.min(v0_idx, v1_idx)},${Math.max(v0_idx, v1_idx)}`;
|
|
387
368
|
const intersection = compute_edge_intersection(surface, vertex_distances, v0_idx, v1_idx);
|
|
388
369
|
if (intersection) {
|
|
389
370
|
crossing_edges.push({ edge_key, intersection });
|
|
@@ -516,24 +497,10 @@ function slice_surface_with_plane(surface, plane_normal, plane_distance, in_plan
|
|
|
516
497
|
// For cubic Oh symmetry, this is the region where all vertices are in the first octant
|
|
517
498
|
// (x >= 0, y >= 0, z >= 0) with some tolerance. Such data needs tiling to show the full BZ.
|
|
518
499
|
export function detect_irreducible_bz(fermi_data) {
|
|
519
|
-
|
|
500
|
+
const vertex_count = fermi_data.isosurfaces.reduce((sum, surface) => sum + surface.vertices.length, 0);
|
|
501
|
+
// Only consider it irreducible if we have significant data and all vertices are
|
|
502
|
+
// in the positive octant (with small tolerance for numerical error)
|
|
503
|
+
if (vertex_count <= IRREDUCIBLE_BZ_MIN_VERTICES)
|
|
520
504
|
return false;
|
|
521
|
-
|
|
522
|
-
let all_positive = true;
|
|
523
|
-
let vertex_count = 0;
|
|
524
|
-
for (const surface of fermi_data.isosurfaces) {
|
|
525
|
-
for (const vertex of surface.vertices) {
|
|
526
|
-
vertex_count++;
|
|
527
|
-
if (vertex[0] < -IRREDUCIBLE_BZ_TOLERANCE ||
|
|
528
|
-
vertex[1] < -IRREDUCIBLE_BZ_TOLERANCE ||
|
|
529
|
-
vertex[2] < -IRREDUCIBLE_BZ_TOLERANCE) {
|
|
530
|
-
all_positive = false;
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
if (!all_positive)
|
|
535
|
-
break;
|
|
536
|
-
}
|
|
537
|
-
// Only consider it irreducible if we have significant data and all positive
|
|
538
|
-
return all_positive && vertex_count > IRREDUCIBLE_BZ_MIN_VERTICES;
|
|
505
|
+
return fermi_data.isosurfaces.every((surface) => surface.vertices.every((vertex) => vertex.every((coord) => coord >= -IRREDUCIBLE_BZ_TOLERANCE)));
|
|
539
506
|
}
|
|
@@ -95,18 +95,11 @@ function parse_bxsf(content) {
|
|
|
95
95
|
if (energy_values.length < total_points) {
|
|
96
96
|
throw new Error(`Band ${band_idx}: expected ${total_points} values, got ${energy_values.length}`);
|
|
97
97
|
}
|
|
98
|
-
// Reshape into 3D grid [kx][ky][kz]
|
|
99
|
-
const band_grid = Array(nx)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
for (let iy = 0; iy < ny; iy++) {
|
|
104
|
-
const iz_arr = energy_values.slice(val_idx, val_idx + nz);
|
|
105
|
-
val_idx += nz;
|
|
106
|
-
iy_arr[iy] = iz_arr;
|
|
107
|
-
}
|
|
108
|
-
band_grid[ix] = iy_arr;
|
|
109
|
-
}
|
|
98
|
+
// Reshape into 3D grid [kx][ky][kz]
|
|
99
|
+
const band_grid = Array.from({ length: nx }, (_x_row, ix) => Array.from({ length: ny }, (_y_row, iy) => {
|
|
100
|
+
const offset = (ix * ny + iy) * nz;
|
|
101
|
+
return energy_values.slice(offset, offset + nz);
|
|
102
|
+
}));
|
|
110
103
|
energies[0].push(band_grid);
|
|
111
104
|
}
|
|
112
105
|
// Try to find Fermi energy (often in a comment or as FERMI_ENERGY keyword)
|
|
@@ -159,58 +152,40 @@ function parse_frmsf(content) {
|
|
|
159
152
|
if (isNaN(n_bands) || n_bands <= 0) {
|
|
160
153
|
throw new Error(`FRMSF: Invalid number of bands`);
|
|
161
154
|
}
|
|
162
|
-
// FRMSF format has single spin channel (no spin-polarized support in standard format)
|
|
163
|
-
const n_spins = 1;
|
|
164
155
|
// Lines 4-6: reciprocal lattice vectors (in Bohr^-1, convert to Å^-1)
|
|
165
156
|
const inv_bohr = 1 / constants.BOHR_TO_ANGSTROM;
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
parse_floats(lines[line_idx++])
|
|
171
|
-
.slice(0, 3)
|
|
172
|
-
.map((val) => val * inv_bohr),
|
|
173
|
-
parse_floats(lines[line_idx++])
|
|
174
|
-
.slice(0, 3)
|
|
175
|
-
.map((val) => val * inv_bohr),
|
|
176
|
-
];
|
|
157
|
+
const parse_k_vector = () => parse_floats(lines[line_idx++])
|
|
158
|
+
.slice(0, 3)
|
|
159
|
+
.map((val) => val * inv_bohr);
|
|
160
|
+
const k_lattice = [parse_k_vector(), parse_k_vector(), parse_k_vector()];
|
|
177
161
|
const [nx, ny, nz] = k_grid;
|
|
178
162
|
const total_points = nx * ny * nz;
|
|
179
|
-
// Parse band energies
|
|
180
|
-
//
|
|
181
|
-
// (e.g. auxiliary color/velocity data) are ignored to prevent grid corruption.
|
|
182
|
-
const energies = [];
|
|
183
|
-
for (let
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
if (energy_values.length < total_points) {
|
|
197
|
-
throw new Error(`FRMSF spin ${spin_idx} band ${band_idx}: expected ${total_points} values, got ${energy_values.length}`);
|
|
198
|
-
}
|
|
199
|
-
// Reshape into 3D grid [kx][ky][kz]
|
|
200
|
-
const band_grid = [];
|
|
201
|
-
let val_idx = 0;
|
|
202
|
-
for (let ix = 0; ix < nx; ix++) {
|
|
203
|
-
band_grid[ix] = [];
|
|
204
|
-
for (let iy = 0; iy < ny; iy++) {
|
|
205
|
-
band_grid[ix][iy] = [];
|
|
206
|
-
for (let iz = 0; iz < nz; iz++) {
|
|
207
|
-
// FRMSF uses Hartree, convert to eV
|
|
208
|
-
band_grid[ix][iy][iz] = energy_values[val_idx++] * constants.HARTREE_TO_EV;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
energies[spin_idx].push(band_grid);
|
|
163
|
+
// Parse band energies (FRMSF has a single spin channel — no spin-polarized support
|
|
164
|
+
// in the standard format). One energy value per line per grid point; any additional
|
|
165
|
+
// columns (e.g. auxiliary color/velocity data) are ignored to prevent grid corruption.
|
|
166
|
+
const energies = [[]];
|
|
167
|
+
for (let band_idx = 0; band_idx < n_bands; band_idx++) {
|
|
168
|
+
const energy_values = [];
|
|
169
|
+
// Read energy values (first value per line only, ignore auxiliary columns;
|
|
170
|
+
// normalize Fortran D-exponents like parse_floats does)
|
|
171
|
+
while (energy_values.length < total_points && line_idx < lines.length) {
|
|
172
|
+
const energy = parse_leading_num(normalize_scientific_notation(lines[line_idx] ?? ``));
|
|
173
|
+
if (isNaN(energy))
|
|
174
|
+
break;
|
|
175
|
+
energy_values.push(energy);
|
|
176
|
+
line_idx++;
|
|
177
|
+
}
|
|
178
|
+
if (energy_values.length < total_points) {
|
|
179
|
+
throw new Error(`FRMSF band ${band_idx}: expected ${total_points} values, got ${energy_values.length}`);
|
|
213
180
|
}
|
|
181
|
+
// Reshape into 3D grid [kx][ky][kz], converting Hartree to eV
|
|
182
|
+
const band_grid = Array.from({ length: nx }, (_x_row, ix) => Array.from({ length: ny }, (_y_row, iy) => {
|
|
183
|
+
const offset = (ix * ny + iy) * nz;
|
|
184
|
+
return energy_values
|
|
185
|
+
.slice(offset, offset + nz)
|
|
186
|
+
.map((energy) => energy * constants.HARTREE_TO_EV);
|
|
187
|
+
}));
|
|
188
|
+
energies[0].push(band_grid);
|
|
214
189
|
}
|
|
215
190
|
return {
|
|
216
191
|
energies,
|
|
@@ -218,7 +193,7 @@ function parse_frmsf(content) {
|
|
|
218
193
|
k_lattice,
|
|
219
194
|
fermi_energy: 0, // FRMSF typically expects Fermi level at 0
|
|
220
195
|
n_bands,
|
|
221
|
-
n_spins,
|
|
196
|
+
n_spins: 1,
|
|
222
197
|
periodic: true, // FRMSF stores k=i/n with no duplicated endpoint (unlike BXSF)
|
|
223
198
|
};
|
|
224
199
|
}
|
|
@@ -357,16 +332,9 @@ function parse_ifermi_surface(data) {
|
|
|
357
332
|
const faces = ifermi_iso.faces;
|
|
358
333
|
// Compute vertex normals from faces
|
|
359
334
|
const normals = compute_vertex_normals(vertices, faces);
|
|
360
|
-
//
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// IFermi stores properties like fermi_velocity, spin, etc.
|
|
364
|
-
const prop_keys = Object.keys(ifermi_iso.properties);
|
|
365
|
-
if (prop_keys.length > 0) {
|
|
366
|
-
// Use first available property as vertex colors
|
|
367
|
-
properties = ifermi_iso.properties[prop_keys[0]];
|
|
368
|
-
}
|
|
369
|
-
}
|
|
335
|
+
// IFermi stores properties like fermi_velocity, spin, etc.
|
|
336
|
+
// Use first available property as vertex colors
|
|
337
|
+
const properties = Object.values(ifermi_iso.properties ?? {})[0];
|
|
370
338
|
// Parse dimensionality
|
|
371
339
|
let dimensionality;
|
|
372
340
|
if (ifermi_iso.dimensionality) {
|