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/spectral/helpers.js
CHANGED
|
@@ -81,7 +81,7 @@ export const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005; // Clamp negatives < 0.5% a
|
|
|
81
81
|
export function pretty_sym_point(symbol) {
|
|
82
82
|
if (!symbol)
|
|
83
83
|
return ``;
|
|
84
|
-
// Remove underscores
|
|
84
|
+
// Remove underscores so S_0 and S0 are treated alike
|
|
85
85
|
// Replace common symmetry point names with Greek letters
|
|
86
86
|
// Handle both plain names (GAMMA) and LaTeX notation (\Gamma) from pymatgen
|
|
87
87
|
// Handle subscripts: convert S0 to S₀, K1 to K₁, Γ1 to Γ₁, etc.
|
|
@@ -336,35 +336,15 @@ const SPIN_DOWN_KEYS = [`-1`, `Spin.down`];
|
|
|
336
336
|
export function extract_spin_channels(data) {
|
|
337
337
|
if (Array.isArray(data))
|
|
338
338
|
return { up: data, down: null };
|
|
339
|
-
if (data
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
// Extract spin-down channel
|
|
351
|
-
for (const key of SPIN_DOWN_KEYS) {
|
|
352
|
-
if (key in record) {
|
|
353
|
-
spin_down = record[key];
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
// Fall back to first key if no spin-up key found
|
|
358
|
-
if (spin_up === null) {
|
|
359
|
-
const keys = Object.keys(record);
|
|
360
|
-
if (keys.length > 0)
|
|
361
|
-
spin_up = record[keys[0]];
|
|
362
|
-
}
|
|
363
|
-
if (spin_up === null)
|
|
364
|
-
return null;
|
|
365
|
-
return { up: spin_up, down: spin_down };
|
|
366
|
-
}
|
|
367
|
-
return null;
|
|
339
|
+
if (!data || typeof data !== `object`)
|
|
340
|
+
return null;
|
|
341
|
+
const record = data;
|
|
342
|
+
const up_key = SPIN_UP_KEYS.find((key) => key in record);
|
|
343
|
+
const down_key = SPIN_DOWN_KEYS.find((key) => key in record);
|
|
344
|
+
// No spin-up key: do not fall back to Object.keys()[0] (could be spin-down)
|
|
345
|
+
if (up_key === undefined)
|
|
346
|
+
return null;
|
|
347
|
+
return { up: record[up_key], down: down_key !== undefined ? record[down_key] : null };
|
|
368
348
|
}
|
|
369
349
|
// Convert pymatgen PhononBandStructureSymmLine or BandStructure to matterviz format
|
|
370
350
|
function convert_pymatgen_band_structure(pmg) {
|
|
@@ -640,6 +620,8 @@ export function find_qpoint_at_distance(band_struct, target) {
|
|
|
640
620
|
return null;
|
|
641
621
|
return distance.reduce((closest, dist, idx) => Math.abs(dist - target) < Math.abs(distance[closest] - target) ? idx : closest, 0);
|
|
642
622
|
}
|
|
623
|
+
// Look up a branch's x-range in the plot via its start/end q-point labels
|
|
624
|
+
const branch_x_range = (bs, branch, x_positions) => x_positions[get_segment_key(bs.qpoints[branch.start_index]?.label ?? undefined, bs.qpoints[branch.end_index]?.label ?? undefined)];
|
|
643
625
|
// Rescaled x-position of a q-point index along the band plot path. Inverse of
|
|
644
626
|
// find_qpoint_at_rescaled_x, used to highlight a q-point hovered in the Brillouin zone.
|
|
645
627
|
// Returns null if the index doesn't fall on a plotted (non-discontinuity) branch.
|
|
@@ -649,9 +631,7 @@ export function qpoint_x_position(band_struct, qpoint_index, x_positions) {
|
|
|
649
631
|
for (const branch of band_struct.branches) {
|
|
650
632
|
if (qpoint_index < branch.start_index || qpoint_index > branch.end_index)
|
|
651
633
|
continue;
|
|
652
|
-
const
|
|
653
|
-
const end_label = band_struct.qpoints[branch.end_index]?.label ?? undefined;
|
|
654
|
-
const range = x_positions[get_segment_key(start_label, end_label)];
|
|
634
|
+
const range = branch_x_range(band_struct, branch, x_positions);
|
|
655
635
|
if (!range)
|
|
656
636
|
continue;
|
|
657
637
|
const [x_start, x_end] = range;
|
|
@@ -671,74 +651,50 @@ export function find_qpoint_at_rescaled_x(band_struct, rescaled_x, x_positions)
|
|
|
671
651
|
return null;
|
|
672
652
|
// Find which segment contains this x coordinate
|
|
673
653
|
for (const branch of band_struct.branches) {
|
|
674
|
-
const start_idx = branch
|
|
675
|
-
const
|
|
676
|
-
const start_label = band_struct.qpoints[start_idx]?.label ?? undefined;
|
|
677
|
-
const end_label = band_struct.qpoints[end_idx]?.label ?? undefined;
|
|
678
|
-
const segment_key = get_segment_key(start_label, end_label);
|
|
679
|
-
const segment_range = x_positions[segment_key];
|
|
654
|
+
const { start_index: start_idx, end_index: end_idx } = branch;
|
|
655
|
+
const segment_range = branch_x_range(band_struct, branch, x_positions);
|
|
680
656
|
if (!segment_range)
|
|
681
657
|
continue;
|
|
682
658
|
const [x_start, x_end] = segment_range;
|
|
683
|
-
//
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
// For discontinuities, check if x is exactly at this point
|
|
687
|
-
if (Math.abs(rescaled_x - x_start) < 1e-6) {
|
|
659
|
+
// Discontinuity (zero-length segment): match only if x is exactly at this point
|
|
660
|
+
if (Math.abs(x_end - x_start) < 1e-6) {
|
|
661
|
+
if (Math.abs(rescaled_x - x_start) < 1e-6)
|
|
688
662
|
return start_idx;
|
|
689
|
-
}
|
|
690
663
|
continue;
|
|
691
664
|
}
|
|
692
665
|
// Check if x is within this segment (with small tolerance for edges)
|
|
693
666
|
if (rescaled_x >= x_start - 1e-6 && rescaled_x <= x_end + 1e-6) {
|
|
694
667
|
// Map from rescaled x back to original distance
|
|
695
|
-
const
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
const dist_range = dist_max - dist_min;
|
|
699
|
-
// Handle zero-length segments
|
|
700
|
-
if (dist_range === 0) {
|
|
668
|
+
const dist_min = band_struct.distance[start_idx];
|
|
669
|
+
const dist_range = band_struct.distance[end_idx] - dist_min;
|
|
670
|
+
if (dist_range === 0)
|
|
701
671
|
return start_idx;
|
|
702
|
-
}
|
|
703
672
|
// Inverse of the scaling: x = x_start + ((dist - dist_min) / dist_range) * (x_end - x_start)
|
|
704
|
-
// Solving for dist: dist = dist_min + ((x - x_start) / (x_end - x_start)) * dist_range
|
|
705
673
|
const normalized_x = (rescaled_x - x_start) / (x_end - x_start);
|
|
706
674
|
const target_dist = dist_min + normalized_x * dist_range;
|
|
707
675
|
// Find closest qpoint in this branch to the target distance
|
|
708
|
-
let closest_idx = start_idx;
|
|
709
|
-
let min_diff = Math.abs(band_struct.distance[start_idx] - target_dist);
|
|
676
|
+
let [closest_idx, min_diff] = [start_idx, Infinity];
|
|
710
677
|
for (let idx = start_idx; idx <= end_idx; idx++) {
|
|
711
678
|
const diff = Math.abs(band_struct.distance[idx] - target_dist);
|
|
712
|
-
if (diff < min_diff)
|
|
713
|
-
min_diff = diff;
|
|
714
|
-
closest_idx = idx;
|
|
715
|
-
}
|
|
679
|
+
if (diff < min_diff)
|
|
680
|
+
[closest_idx, min_diff] = [idx, diff];
|
|
716
681
|
}
|
|
717
682
|
return closest_idx;
|
|
718
683
|
}
|
|
719
684
|
}
|
|
720
685
|
// Fallback: find closest labeled point
|
|
721
|
-
let closest_idx = 0;
|
|
722
|
-
let min_dist = Infinity;
|
|
686
|
+
let [closest_idx, min_dist] = [0, Infinity];
|
|
723
687
|
for (const branch of band_struct.branches) {
|
|
724
|
-
const
|
|
725
|
-
const end_idx = branch.end_index;
|
|
726
|
-
const start_label = band_struct.qpoints[start_idx]?.label ?? undefined;
|
|
727
|
-
const end_label = band_struct.qpoints[end_idx]?.label ?? undefined;
|
|
728
|
-
const segment_key = get_segment_key(start_label, end_label);
|
|
729
|
-
const segment_range = x_positions[segment_key];
|
|
688
|
+
const segment_range = branch_x_range(band_struct, branch, x_positions);
|
|
730
689
|
if (!segment_range)
|
|
731
690
|
continue;
|
|
732
|
-
const [x_start, x_end] = segment_range;
|
|
733
691
|
for (const [x_pos, idx] of [
|
|
734
|
-
[
|
|
735
|
-
[
|
|
692
|
+
[segment_range[0], branch.start_index],
|
|
693
|
+
[segment_range[1], branch.end_index],
|
|
736
694
|
]) {
|
|
737
695
|
const dist = Math.abs(rescaled_x - x_pos);
|
|
738
|
-
if (dist < min_dist)
|
|
739
|
-
min_dist = dist;
|
|
740
|
-
closest_idx = idx;
|
|
741
|
-
}
|
|
696
|
+
if (dist < min_dist)
|
|
697
|
+
[closest_idx, min_dist] = [idx, dist];
|
|
742
698
|
}
|
|
743
699
|
}
|
|
744
700
|
return closest_idx;
|
|
@@ -791,24 +747,15 @@ const shift_dos_energies = (dos, shift) => ({
|
|
|
791
747
|
// Recursively shifts nested DOS in atom_dos and spd_dos for consistency
|
|
792
748
|
export function shift_to_fermi(dos) {
|
|
793
749
|
const shift = dos.efermi;
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
// Shift nested atom_dos if present
|
|
797
|
-
const atom_dos = dos.atom_dos
|
|
798
|
-
? Object.fromEntries(Object.entries(dos.atom_dos).map(([key, nested_dos]) => [
|
|
799
|
-
key,
|
|
800
|
-
shift_dos_energies(nested_dos, shift),
|
|
801
|
-
]))
|
|
802
|
-
: undefined;
|
|
803
|
-
// Shift nested spd_dos if present
|
|
804
|
-
const spd_dos = dos.spd_dos
|
|
805
|
-
? Object.fromEntries(Object.entries(dos.spd_dos).map(([key, nested_dos]) => [
|
|
750
|
+
const shift_nested = (nested) => nested &&
|
|
751
|
+
Object.fromEntries(Object.entries(nested).map(([key, nested_dos]) => [
|
|
806
752
|
key,
|
|
807
753
|
shift_dos_energies(nested_dos, shift),
|
|
808
|
-
]))
|
|
809
|
-
|
|
754
|
+
]));
|
|
755
|
+
const atom_dos = shift_nested(dos.atom_dos);
|
|
756
|
+
const spd_dos = shift_nested(dos.spd_dos);
|
|
810
757
|
return {
|
|
811
|
-
...
|
|
758
|
+
...shift_dos_energies(dos, shift),
|
|
812
759
|
efermi: 0, // Explicitly set to 0 (shift_dos_energies would give efermi - shift)
|
|
813
760
|
...(atom_dos && { atom_dos }),
|
|
814
761
|
...(spd_dos && { spd_dos }),
|
|
@@ -905,26 +852,14 @@ export function compute_frequency_range(band_structs, doses, padding_factor = 0.
|
|
|
905
852
|
const all_freqs = [];
|
|
906
853
|
// Check raw band_structs for electronic markers before normalization
|
|
907
854
|
// (normalized structures always have qpoints, so we can't detect from them)
|
|
908
|
-
let has_electronic_bs = false;
|
|
909
855
|
// Support both qpoints (phonon) and kpoints (electronic) to detect single vs dict
|
|
910
856
|
const is_single_bs = band_structs &&
|
|
911
857
|
typeof band_structs === `object` &&
|
|
912
858
|
(`qpoints` in band_structs || `kpoints` in band_structs);
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
}
|
|
918
|
-
else if (!is_single_bs) {
|
|
919
|
-
// Dict of band structures - check each value
|
|
920
|
-
for (const bs_val of Object.values(band_structs)) {
|
|
921
|
-
if (is_electronic_band_struct(bs_val)) {
|
|
922
|
-
has_electronic_bs = true;
|
|
923
|
-
break;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
859
|
+
const has_electronic_bs = band_structs &&
|
|
860
|
+
typeof band_structs === `object` &&
|
|
861
|
+
(is_electronic_band_struct(band_structs) ||
|
|
862
|
+
(!is_single_bs && Object.values(band_structs).some(is_electronic_band_struct)));
|
|
928
863
|
const bs_list = band_structs
|
|
929
864
|
? is_single_bs
|
|
930
865
|
? [normalize_band_structure(band_structs)]
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { contrast_color, default_element_colors } from '../colors'
|
|
3
3
|
import type { CompositionType } from '../composition'
|
|
4
|
-
import type
|
|
5
|
-
import { element_data } from '../element'
|
|
4
|
+
import { element_by_symbol, is_elem_symbol, type ElementSymbol } from '../element'
|
|
6
5
|
import Icon from '../Icon.svelte'
|
|
7
6
|
import { ELEM_SYMBOLS, format_num } from '../labels'
|
|
8
7
|
import { ColorBar } from '../plot'
|
|
@@ -26,7 +25,6 @@
|
|
|
26
25
|
property_colors = null,
|
|
27
26
|
elements,
|
|
28
27
|
elem_color_picker_title = `Double click to reset color`,
|
|
29
|
-
labels = $bindable([]),
|
|
30
28
|
amount_format = `.3~f`,
|
|
31
29
|
show_amounts = true,
|
|
32
30
|
get_element_label,
|
|
@@ -49,7 +47,6 @@
|
|
|
49
47
|
property_colors?: AtomPropertyColors | null
|
|
50
48
|
elements?: CompositionType
|
|
51
49
|
elem_color_picker_title?: string
|
|
52
|
-
labels?: HTMLLabelElement[]
|
|
53
50
|
amount_format?: string // Float formatting for element amounts (default: 3 significant digits)
|
|
54
51
|
show_amounts?: boolean // Whether to show element amounts
|
|
55
52
|
get_element_label?: (element: string, amount: number) => string // Custom label function
|
|
@@ -161,12 +158,11 @@
|
|
|
161
158
|
if (!remap_search) return ELEM_SYMBOLS
|
|
162
159
|
const query = remap_search.toLowerCase()
|
|
163
160
|
return ELEM_SYMBOLS.filter((elem) => {
|
|
164
|
-
const data =
|
|
161
|
+
const data = element_by_symbol.get(elem)
|
|
165
162
|
return elem.toLowerCase().includes(query) || data?.name?.toLowerCase().includes(query)
|
|
166
163
|
})
|
|
167
164
|
})
|
|
168
165
|
|
|
169
|
-
const known_element_symbols = new Set(ELEM_SYMBOLS)
|
|
170
166
|
let sorted_element_entries = $derived.by(() => {
|
|
171
167
|
if (!elements) return []
|
|
172
168
|
const element_amounts = elements as Record<string, number>
|
|
@@ -175,9 +171,7 @@
|
|
|
175
171
|
return amount === undefined ? [] : [[element_symbol, amount] as const]
|
|
176
172
|
})
|
|
177
173
|
const unknown_entries = Object.entries(element_amounts)
|
|
178
|
-
.filter(
|
|
179
|
-
([element_symbol]) => !known_element_symbols.has(element_symbol as ElementSymbol),
|
|
180
|
-
)
|
|
174
|
+
.filter(([element_symbol]) => !is_elem_symbol(element_symbol))
|
|
181
175
|
.sort(([element_a], [element_b]) => element_a.localeCompare(element_b))
|
|
182
176
|
return [...ordered_known_entries, ...unknown_entries]
|
|
183
177
|
})
|
|
@@ -326,13 +320,12 @@
|
|
|
326
320
|
{#if show_element_legend}
|
|
327
321
|
<div {...rest} class={[`atom-legend element-legend`, rest.class]}>
|
|
328
322
|
{@render mode_selector_snippet()}
|
|
329
|
-
{#each sorted_element_entries as [elem, amt]
|
|
323
|
+
{#each sorted_element_entries as [elem, amt] (elem)}
|
|
330
324
|
{@const is_hidden = hidden_elements.has(elem as ElementSymbol)}
|
|
331
325
|
{@const displayed_elem = element_mapping?.[elem as ElementSymbol] || elem}
|
|
332
326
|
<div class="legend-item">
|
|
333
327
|
<label
|
|
334
|
-
|
|
335
|
-
title="{element_data?.find((el) => el.symbol === displayed_elem)?.name ??
|
|
328
|
+
title="{element_by_symbol.get(displayed_elem as ElementSymbol)?.name ??
|
|
336
329
|
``}{displayed_elem !== elem ? ` (remapped from ${elem})` : ``}"
|
|
337
330
|
{@attach tooltip()}
|
|
338
331
|
style:background-color={colors.element[displayed_elem]}
|
|
@@ -445,7 +438,7 @@
|
|
|
445
438
|
</button>
|
|
446
439
|
{/if}
|
|
447
440
|
{#each filtered_elements as target_elem (target_elem)}
|
|
448
|
-
{@const elem_info =
|
|
441
|
+
{@const elem_info = element_by_symbol.get(target_elem)}
|
|
449
442
|
<button
|
|
450
443
|
class="remap-option"
|
|
451
444
|
class:selected={displayed_elem === target_elem}
|
|
@@ -550,6 +543,8 @@
|
|
|
550
543
|
.atom-legend {
|
|
551
544
|
position: absolute;
|
|
552
545
|
z-index: var(--legend-z-index, 1);
|
|
546
|
+
/* own compositing layer, or WKWebView paints the canvas over this (see app.css) */
|
|
547
|
+
will-change: transform;
|
|
553
548
|
pointer-events: auto;
|
|
554
549
|
visibility: visible;
|
|
555
550
|
filter: var(--legend-filter, grayscale(10%) brightness(0.95) saturate(0.8));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CompositionType } from '../composition';
|
|
2
|
-
import type
|
|
2
|
+
import { type ElementSymbol } from '../element';
|
|
3
3
|
import type { AnyStructure } from './';
|
|
4
4
|
import type { AtomColorConfig, AtomPropertyColors } from './atom-properties';
|
|
5
5
|
import type { MoyoDataset } from '@spglib/moyo-wasm';
|
|
@@ -11,7 +11,6 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
|
|
|
11
11
|
property_colors?: AtomPropertyColors | null;
|
|
12
12
|
elements?: CompositionType;
|
|
13
13
|
elem_color_picker_title?: string;
|
|
14
|
-
labels?: HTMLLabelElement[];
|
|
15
14
|
amount_format?: string;
|
|
16
15
|
show_amounts?: boolean;
|
|
17
16
|
get_element_label?: (element: string, amount: number) => string;
|
|
@@ -30,6 +29,6 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
|
|
|
30
29
|
structure?: AnyStructure | null;
|
|
31
30
|
}]>;
|
|
32
31
|
};
|
|
33
|
-
declare const AtomLegend: import("svelte").Component<$$ComponentProps, {}, "
|
|
32
|
+
declare const AtomLegend: import("svelte").Component<$$ComponentProps, {}, "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "atom_color_config" | "element_mapping">;
|
|
34
33
|
type AtomLegend = ReturnType<typeof AtomLegend>;
|
|
35
34
|
export default AtomLegend;
|
|
@@ -29,6 +29,26 @@
|
|
|
29
29
|
let input_value = $state(supercell_scaling)
|
|
30
30
|
let input_valid = $derived(is_valid_supercell_input(input_value))
|
|
31
31
|
|
|
32
|
+
// Hover-intent gate: opening instantly on mouseenter made the menu pop open
|
|
33
|
+
// when merely scrubbing the pointer across compact embeds (carousel cards).
|
|
34
|
+
// Deliberate hovers still open it; keyboard focus and clicks open instantly.
|
|
35
|
+
const hover_open_delay_ms = 200
|
|
36
|
+
let hover_timer: ReturnType<typeof setTimeout> | undefined
|
|
37
|
+
|
|
38
|
+
const schedule_hover_open = () => {
|
|
39
|
+
if (suppress_hover) return
|
|
40
|
+
clearTimeout(hover_timer)
|
|
41
|
+
// re-check suppression at fire time: a sibling popover may have opened meanwhile
|
|
42
|
+
hover_timer = setTimeout(() => (menu_open = !suppress_hover), hover_open_delay_ms)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const close_menu = () => {
|
|
46
|
+
clearTimeout(hover_timer)
|
|
47
|
+
menu_open = false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$effect(() => () => clearTimeout(hover_timer))
|
|
51
|
+
|
|
32
52
|
const supercell_presets = [`1x1x1`, `2x2x2`, `3x3x3`, `2x2x1`, `3x3x1`, `2x1x1`]
|
|
33
53
|
|
|
34
54
|
// Always show all 3 cell types - Prim/Conv disabled without sym_data
|
|
@@ -51,13 +71,13 @@
|
|
|
51
71
|
function apply_preset(preset: string) {
|
|
52
72
|
supercell_scaling = preset
|
|
53
73
|
input_value = preset
|
|
54
|
-
|
|
74
|
+
close_menu()
|
|
55
75
|
}
|
|
56
76
|
|
|
57
77
|
function handle_input_submit() {
|
|
58
78
|
if (input_valid && input_value !== supercell_scaling) {
|
|
59
79
|
supercell_scaling = input_value
|
|
60
|
-
|
|
80
|
+
close_menu()
|
|
61
81
|
}
|
|
62
82
|
}
|
|
63
83
|
|
|
@@ -69,11 +89,11 @@
|
|
|
69
89
|
!(next_target instanceof Node) ||
|
|
70
90
|
!current_target.contains(next_target)
|
|
71
91
|
)
|
|
72
|
-
|
|
92
|
+
close_menu()
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
function handle_key_down(event: KeyboardEvent, submit_on_enter: boolean = false) {
|
|
76
|
-
if (event.key === `Escape`)
|
|
96
|
+
if (event.key === `Escape`) close_menu()
|
|
77
97
|
if (submit_on_enter && event.key === `Enter`) handle_input_submit()
|
|
78
98
|
}
|
|
79
99
|
|
|
@@ -87,22 +107,25 @@
|
|
|
87
107
|
// Close + keep closed while suppressed so the menu can't obscure a sibling popover
|
|
88
108
|
// (e.g. the atom color-mode dropdown) the user is actively interacting with
|
|
89
109
|
$effect(() => {
|
|
90
|
-
if (suppress_hover)
|
|
110
|
+
if (suppress_hover) close_menu()
|
|
91
111
|
})
|
|
92
112
|
</script>
|
|
93
113
|
|
|
94
114
|
<div
|
|
95
115
|
class="cell-select"
|
|
96
116
|
role="group"
|
|
97
|
-
{@attach click_outside({ callback:
|
|
98
|
-
onmouseenter={
|
|
99
|
-
onmouseleave={
|
|
117
|
+
{@attach click_outside({ callback: close_menu })}
|
|
118
|
+
onmouseenter={schedule_hover_open}
|
|
119
|
+
onmouseleave={close_menu}
|
|
100
120
|
onfocusin={() => (menu_open = !suppress_hover)}
|
|
101
121
|
onfocusout={handle_focus_out}
|
|
102
122
|
>
|
|
103
123
|
<button
|
|
104
124
|
type="button"
|
|
105
|
-
onclick={() =>
|
|
125
|
+
onclick={() => {
|
|
126
|
+
clearTimeout(hover_timer)
|
|
127
|
+
menu_open = !suppress_hover && !menu_open
|
|
128
|
+
}}
|
|
106
129
|
onkeydown={handle_key_down}
|
|
107
130
|
class="toggle-btn"
|
|
108
131
|
class:active={menu_open}
|
|
@@ -224,7 +247,9 @@
|
|
|
224
247
|
display: flex;
|
|
225
248
|
flex-direction: column;
|
|
226
249
|
gap: 5px;
|
|
227
|
-
z-index: 100;
|
|
250
|
+
z-index: var(--z-index-viewer-dropdown, 100);
|
|
251
|
+
/* own compositing layer, or WKWebView paints the canvas over this (see app.css) */
|
|
252
|
+
will-change: transform;
|
|
228
253
|
font-size: var(--struct-cell-select-dropdown-font, max(10px, 1em));
|
|
229
254
|
min-width: 118px;
|
|
230
255
|
}
|