matterviz 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FilePicker.svelte +37 -20
- package/dist/Icon.svelte +2 -2
- package/dist/MillerIndexInput.svelte +60 -0
- package/dist/MillerIndexInput.svelte.d.ts +7 -0
- package/dist/app.css +38 -2
- package/dist/brillouin/BrillouinZone.svelte +20 -62
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneExportPane.svelte +12 -20
- package/dist/brillouin/BrillouinZoneScene.svelte +2 -2
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +192 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +677 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2688 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +33 -0
- package/dist/chempot-diagram/compute.d.ts +38 -0
- package/dist/chempot-diagram/compute.js +650 -0
- package/dist/chempot-diagram/index.d.ts +5 -0
- package/dist/chempot-diagram/index.js +5 -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 +37 -0
- package/dist/chempot-diagram/types.d.ts +83 -0
- package/dist/chempot-diagram/types.js +27 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +4 -0
- package/dist/composition/BarChart.svelte +13 -22
- package/dist/composition/BubbleChart.svelte +5 -3
- package/dist/composition/FormulaFilter.svelte +770 -90
- package/dist/composition/FormulaFilter.svelte.d.ts +37 -1
- package/dist/composition/PieChart.svelte +43 -18
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/convex-hull/ConvexHull.svelte +14 -1
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +14 -45
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +396 -134
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +93 -42
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +94 -31
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +4 -2
- package/dist/convex-hull/ConvexHullStats.svelte +697 -128
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +1 -0
- package/dist/convex-hull/GasPressureControls.svelte +72 -38
- package/dist/convex-hull/GasPressureControls.svelte.d.ts +2 -1
- package/dist/convex-hull/TemperatureSlider.svelte +46 -19
- package/dist/convex-hull/TemperatureSlider.svelte.d.ts +2 -1
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +36 -0
- package/dist/convex-hull/gas-thermodynamics.js +16 -5
- package/dist/convex-hull/helpers.d.ts +7 -1
- package/dist/convex-hull/helpers.js +45 -15
- package/dist/convex-hull/index.d.ts +15 -1
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +106 -17
- package/dist/convex-hull/types.d.ts +7 -0
- package/dist/convex-hull/types.js +11 -0
- package/dist/coordination/CoordinationBarPlot.svelte +29 -46
- package/dist/element/BohrAtom.svelte +1 -1
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/fermi-surface/FermiSurface.svelte +21 -65
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/compute.js +1 -21
- package/dist/fermi-surface/marching-cubes.d.ts +2 -13
- package/dist/fermi-surface/marching-cubes.js +2 -519
- package/dist/fermi-surface/parse.js +17 -23
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1273 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +171 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +31 -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 +119 -0
- package/dist/icons.js +119 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/io/export.js +15 -3
- 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/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +118 -0
- package/dist/isosurface/Isosurface.svelte +231 -0
- package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
- package/dist/isosurface/IsosurfaceControls.svelte +273 -0
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
- package/dist/isosurface/index.d.ts +5 -0
- package/dist/isosurface/index.js +6 -0
- package/dist/isosurface/parse.d.ts +6 -0
- package/dist/isosurface/parse.js +548 -0
- package/dist/isosurface/slice.d.ts +11 -0
- package/dist/isosurface/slice.js +145 -0
- package/dist/isosurface/types.d.ts +55 -0
- package/dist/isosurface/types.js +178 -0
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +1 -0
- package/dist/layout/InfoTag.svelte +62 -62
- package/dist/layout/SubpageGrid.svelte +74 -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 +226 -53
- package/dist/layout/json-tree/JsonTree.svelte +425 -51
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +218 -97
- package/dist/layout/json-tree/types.d.ts +27 -2
- package/dist/layout/json-tree/utils.d.ts +14 -1
- package/dist/layout/json-tree/utils.js +254 -0
- package/dist/marching-cubes.d.ts +14 -0
- package/dist/marching-cubes.js +519 -0
- package/dist/math.d.ts +8 -0
- package/dist/math.js +374 -7
- package/dist/overlays/ContextMenu.svelte +3 -2
- package/dist/overlays/DraggablePane.svelte +163 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +232 -77
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +32 -11
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +103 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +102 -95
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +7 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +100 -26
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +865 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +7 -4
- package/dist/phase-diagram/utils.js +149 -59
- package/dist/plot/AxisLabel.svelte +26 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +473 -228
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +3 -2
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +54 -54
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ElementScatter.svelte +4 -3
- package/dist/plot/FillArea.svelte +4 -1
- package/dist/plot/Histogram.svelte +320 -230
- package/dist/plot/Histogram.svelte.d.ts +2 -2
- package/dist/plot/HistogramControls.svelte +29 -10
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +2 -2
- package/dist/plot/PlotControls.svelte +109 -27
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +1 -1
- package/dist/plot/PortalSelect.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferencePlane.svelte +1 -3
- package/dist/plot/ScatterPlot.svelte +343 -209
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +203 -250
- package/dist/plot/ScatterPlot3DScene.svelte +4 -7
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +95 -55
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ZeroLines.svelte +44 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +21 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/data-cleaning.js +1 -5
- 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 +10 -19
- package/dist/plot/layout.d.ts +7 -1
- package/dist/plot/layout.js +12 -4
- package/dist/plot/reference-line.d.ts +4 -21
- package/dist/plot/reference-line.js +7 -81
- package/dist/plot/types.d.ts +42 -17
- package/dist/plot/types.js +10 -0
- package/dist/plot/utils/label-placement.js +14 -11
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +55 -66
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/index.d.ts +1 -1
- package/dist/rdf/index.js +1 -1
- package/dist/settings.d.ts +5 -0
- package/dist/settings.js +37 -3
- package/dist/spectral/Bands.svelte +515 -143
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +65 -9
- package/dist/spectral/types.d.ts +2 -0
- package/dist/structure/AtomLegend.svelte +31 -10
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CellSelect.svelte +92 -22
- package/dist/structure/Lattice.svelte +2 -0
- package/dist/structure/Structure.svelte +716 -173
- package/dist/structure/Structure.svelte.d.ts +7 -2
- package/dist/structure/StructureControls.svelte +26 -14
- package/dist/structure/StructureControls.svelte.d.ts +5 -1
- package/dist/structure/StructureInfoPane.svelte +7 -1
- package/dist/structure/StructureScene.svelte +386 -95
- package/dist/structure/StructureScene.svelte.d.ts +15 -4
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +38 -25
- package/dist/structure/export.js +10 -7
- 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 +1 -2
- package/dist/structure/index.d.ts +7 -0
- package/dist/structure/index.js +22 -0
- package/dist/structure/parse.js +19 -16
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +102 -0
- package/dist/structure/validation.js +6 -3
- package/dist/symmetry/SymmetryStats.svelte +18 -4
- package/dist/symmetry/WyckoffTable.svelte +18 -10
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +83 -18
- package/dist/table/HeatmapTable.svelte +468 -69
- package/dist/table/HeatmapTable.svelte.d.ts +13 -1
- package/dist/table/ToggleMenu.svelte +291 -44
- package/dist/table/ToggleMenu.svelte.d.ts +4 -1
- package/dist/table/index.d.ts +3 -0
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +147 -145
- package/dist/trajectory/TrajectoryExportPane.svelte +13 -9
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +3 -5
- 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 +339 -0
- package/dist/trajectory/helpers.d.ts +15 -0
- package/dist/trajectory/helpers.js +187 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +11 -4
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +76 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +121 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +304 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +169 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +65 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +109 -0
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +4 -0
- package/dist/xrd/XrdPlot.svelte +6 -4
- package/dist/xrd/calc-xrd.js +0 -1
- package/package.json +33 -23
- 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
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ElementSymbol } from '../element';
|
|
2
|
+
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types';
|
|
2
3
|
import type { Vec3 } from '../math';
|
|
3
4
|
import { type CameraProjection, type ShowBonds } from '../settings';
|
|
4
|
-
import type { AnyStructure, Site } from './';
|
|
5
|
+
import type { AnyStructure, MeasureMode, Site } from './';
|
|
5
6
|
import { Lattice } from './';
|
|
6
7
|
import type { AtomColorConfig } from './atom-properties';
|
|
7
8
|
import type { MoyoDataset } from '@spglib/moyo-wasm';
|
|
@@ -9,7 +10,7 @@ import * as extras from '@threlte/extras';
|
|
|
9
10
|
import type { ComponentProps } from 'svelte';
|
|
10
11
|
import { type Snippet } from 'svelte';
|
|
11
12
|
import { SvelteMap } from 'svelte/reactivity';
|
|
12
|
-
import type
|
|
13
|
+
import { type Camera, type Scene } from 'three';
|
|
13
14
|
import type { BondingStrategy } from './bonding';
|
|
14
15
|
type $$ComponentProps = {
|
|
15
16
|
structure?: AnyStructure;
|
|
@@ -17,6 +18,7 @@ type $$ComponentProps = {
|
|
|
17
18
|
atom_radius?: number;
|
|
18
19
|
same_size_atoms?: boolean;
|
|
19
20
|
camera_position?: [x: number, y: number, z: number];
|
|
21
|
+
camera_target?: Vec3;
|
|
20
22
|
camera_projection?: CameraProjection;
|
|
21
23
|
rotation_damping?: number;
|
|
22
24
|
max_zoom?: number;
|
|
@@ -59,7 +61,7 @@ type $$ComponentProps = {
|
|
|
59
61
|
camera_is_moving?: boolean;
|
|
60
62
|
width?: number;
|
|
61
63
|
height?: number;
|
|
62
|
-
measure_mode?:
|
|
64
|
+
measure_mode?: MeasureMode;
|
|
63
65
|
selected_sites?: number[];
|
|
64
66
|
measured_sites?: number[];
|
|
65
67
|
added_bonds?: [number, number][];
|
|
@@ -79,7 +81,16 @@ type $$ComponentProps = {
|
|
|
79
81
|
site_radius_overrides?: Map<number, number> | SvelteMap<number, number>;
|
|
80
82
|
atom_color_config?: Partial<AtomColorConfig>;
|
|
81
83
|
sym_data?: MoyoDataset | null;
|
|
84
|
+
on_sites_moved?: (scene_indices: number[], delta: Vec3) => void;
|
|
85
|
+
on_operation_start?: () => void;
|
|
86
|
+
on_add_atom?: (xyz: Vec3, element: ElementSymbol) => void;
|
|
87
|
+
add_atom_mode?: boolean;
|
|
88
|
+
add_element?: ElementSymbol;
|
|
89
|
+
cursor?: string;
|
|
90
|
+
dragging_atoms?: boolean;
|
|
91
|
+
volumetric_data?: VolumetricData;
|
|
92
|
+
isosurface_settings?: IsosurfaceSettings;
|
|
82
93
|
};
|
|
83
|
-
declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "site_label_offset" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "hovered_idx" | "hovered_site" | "camera_is_moving" | "measured_sites" | "added_bonds" | "removed_bonds" | "active_sites" | "
|
|
94
|
+
declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "site_label_offset" | "scene" | "camera" | "orbit_controls" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "hovered_idx" | "hovered_site" | "camera_is_moving" | "measured_sites" | "added_bonds" | "removed_bonds" | "active_sites" | "rotation_target_ref" | "initial_computed_zoom" | "add_atom_mode" | "add_element" | "dragging_atoms">;
|
|
84
95
|
type StructureScene = ReturnType<typeof StructureScene>;
|
|
85
96
|
export default StructureScene;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AnyStructure, Site } from './';
|
|
2
1
|
import type { ColorScaleType, D3InterpolateName } from '../colors';
|
|
3
2
|
import type { AtomColorMode } from '../settings';
|
|
3
|
+
import type { AnyStructure, Site } from './';
|
|
4
4
|
import type { BondingStrategy } from './bonding';
|
|
5
5
|
import type { MoyoDataset } from '@spglib/moyo-wasm';
|
|
6
6
|
export interface AtomColorConfig {
|
|
@@ -16,6 +16,9 @@ export interface AtomPropertyColors {
|
|
|
16
16
|
max_value?: number;
|
|
17
17
|
unique_values?: (number | string)[];
|
|
18
18
|
}
|
|
19
|
+
type SymmetryDataWithOrigMap = MoyoDataset & {
|
|
20
|
+
orig_site_indices_by_std_idx?: number[][];
|
|
21
|
+
};
|
|
19
22
|
export declare const get_d3_color_scales: () => string[];
|
|
20
23
|
export declare function apply_color_scale(vals: number[], scale?: string, type?: ColorScaleType): {
|
|
21
24
|
colors: string[];
|
|
@@ -27,7 +30,8 @@ export declare const apply_categorical_color_scale: (vals: string[], scale?: str
|
|
|
27
30
|
};
|
|
28
31
|
export declare const get_orig_site_idx: (site: Site | undefined, site_idx: number) => number;
|
|
29
32
|
export declare function get_coordination_colors(structure: AnyStructure, strategy?: BondingStrategy, scale?: string, type?: ColorScaleType): AtomPropertyColors;
|
|
30
|
-
export declare function get_wyckoff_colors(structure: AnyStructure, sym_data:
|
|
33
|
+
export declare function get_wyckoff_colors(structure: AnyStructure, sym_data: SymmetryDataWithOrigMap | null, scale?: string): AtomPropertyColors;
|
|
31
34
|
export declare function get_custom_colors(structure: AnyStructure, fn: (site: Site, idx: number) => number | string, scale?: string, type?: ColorScaleType): AtomPropertyColors;
|
|
32
35
|
export declare function get_atom_colors(structure: AnyStructure, config: Partial<AtomColorConfig>, bonding_strategy?: BondingStrategy, sym_data?: MoyoDataset | null): AtomPropertyColors;
|
|
33
36
|
export declare function get_property_colors(structure: AnyStructure | undefined, config: Partial<AtomColorConfig>, bonding_strategy: BondingStrategy, sym_data: MoyoDataset | null): AtomPropertyColors | null;
|
|
37
|
+
export {};
|
|
@@ -15,6 +15,25 @@ const get_interpolator = (scale) => {
|
|
|
15
15
|
return interp_fn;
|
|
16
16
|
};
|
|
17
17
|
const to_hex = (interp_fn, t) => rgb(interp_fn(t)).formatHex();
|
|
18
|
+
const build_image_site = (site, lattice_T, offset, orig_idx) => {
|
|
19
|
+
const img_abc = [
|
|
20
|
+
site.abc[0] + offset[0],
|
|
21
|
+
site.abc[1] + offset[1],
|
|
22
|
+
site.abc[2] + offset[2],
|
|
23
|
+
];
|
|
24
|
+
return {
|
|
25
|
+
...site,
|
|
26
|
+
abc: img_abc,
|
|
27
|
+
xyz: math.mat3x3_vec3_multiply(lattice_T, img_abc),
|
|
28
|
+
properties: { ...site.properties, orig_site_idx: orig_idx },
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const get_all_offsets = (pbc) => [-1, 0, 1]
|
|
32
|
+
.flatMap((dx) => [-1, 0, 1].flatMap((dy) => [-1, 0, 1].map((dz) => [dx, dy, dz])))
|
|
33
|
+
.filter(([dx, dy, dz]) => !(dx === 0 && dy === 0 && dz === 0) &&
|
|
34
|
+
(pbc[0] || dx === 0) &&
|
|
35
|
+
(pbc[1] || dy === 0) &&
|
|
36
|
+
(pbc[2] || dz === 0));
|
|
18
37
|
const make_categorical = (vals, scale, sort_fn) => {
|
|
19
38
|
const interp_fn = get_interpolator(scale);
|
|
20
39
|
const uniq = sort_fn ? [...new Set(vals)].sort(sort_fn) : [...new Set(vals)].sort();
|
|
@@ -68,24 +87,10 @@ function expand_structure_for_pbc(structure) {
|
|
|
68
87
|
const { sites, lattice } = structure;
|
|
69
88
|
const lattice_T = math.transpose_3x3_matrix(lattice.matrix);
|
|
70
89
|
const pbc = lattice.pbc ?? [true, true, true];
|
|
71
|
-
|
|
72
|
-
const all_offsets = [-1, 0, 1]
|
|
73
|
-
.flatMap((dx) => [-1, 0, 1].flatMap((dy) => [-1, 0, 1].map((dz) => [dx, dy, dz])))
|
|
74
|
-
.filter(([dx, dy, dz]) => !(dx === 0 && dy === 0 && dz === 0) &&
|
|
75
|
-
(pbc[0] || dx === 0) &&
|
|
76
|
-
(pbc[1] || dy === 0) &&
|
|
77
|
-
(pbc[2] || dz === 0));
|
|
90
|
+
const all_offsets = get_all_offsets(pbc);
|
|
78
91
|
// Small structures: expand all atoms
|
|
79
92
|
if (sites.length < 20 || !pbc.some((periodic) => periodic)) {
|
|
80
|
-
const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((
|
|
81
|
-
const img_abc = [site.abc[0] + dx, site.abc[1] + dy, site.abc[2] + dz];
|
|
82
|
-
return {
|
|
83
|
-
...site,
|
|
84
|
-
abc: img_abc,
|
|
85
|
-
xyz: math.mat3x3_vec3_multiply(lattice_T, img_abc),
|
|
86
|
-
properties: { ...site.properties, orig_site_idx: orig_idx },
|
|
87
|
-
};
|
|
88
|
-
}));
|
|
93
|
+
const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((offset) => build_image_site(site, lattice_T, offset, orig_idx)));
|
|
89
94
|
return { ...structure, sites: [...sites, ...image_sites] };
|
|
90
95
|
}
|
|
91
96
|
// Large structures: only expand atoms near boundaries (within 5Å bond distance)
|
|
@@ -96,15 +101,7 @@ function expand_structure_for_pbc(structure) {
|
|
|
96
101
|
.filter(([dx, dy, dz]) => (dx === 0 || (dx === -1 ? norm[0] <= cutoff[0] : norm[0] >= 1 - cutoff[0])) &&
|
|
97
102
|
(dy === 0 || (dy === -1 ? norm[1] <= cutoff[1] : norm[1] >= 1 - cutoff[1])) &&
|
|
98
103
|
(dz === 0 || (dz === -1 ? norm[2] <= cutoff[2] : norm[2] >= 1 - cutoff[2])))
|
|
99
|
-
.map((
|
|
100
|
-
const img_abc = [site.abc[0] + dx, site.abc[1] + dy, site.abc[2] + dz];
|
|
101
|
-
return {
|
|
102
|
-
...site,
|
|
103
|
-
abc: img_abc,
|
|
104
|
-
xyz: math.mat3x3_vec3_multiply(lattice_T, img_abc),
|
|
105
|
-
properties: { ...site.properties, orig_site_idx: orig_idx },
|
|
106
|
-
};
|
|
107
|
-
});
|
|
104
|
+
.map((offset) => build_image_site(site, lattice_T, offset, orig_idx));
|
|
108
105
|
});
|
|
109
106
|
return { ...structure, sites: [...sites, ...image_sites] };
|
|
110
107
|
}
|
|
@@ -135,9 +132,25 @@ export function get_wyckoff_colors(structure, sym_data, scale = DEFAULT_COLOR_SC
|
|
|
135
132
|
unique_values: [`unknown`],
|
|
136
133
|
};
|
|
137
134
|
}
|
|
135
|
+
const wyckoff_by_orig_idx = new Map();
|
|
136
|
+
const mapping_by_std_idx = sym_data.orig_site_indices_by_std_idx;
|
|
137
|
+
if (mapping_by_std_idx) {
|
|
138
|
+
for (let std_idx = 0; std_idx < sym_data.wyckoffs.length; std_idx += 1) {
|
|
139
|
+
const wyckoff = sym_data.wyckoffs[std_idx];
|
|
140
|
+
for (const orig_idx of mapping_by_std_idx[std_idx] ?? []) {
|
|
141
|
+
if (!wyckoff_by_orig_idx.has(orig_idx))
|
|
142
|
+
wyckoff_by_orig_idx.set(orig_idx, wyckoff);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
138
146
|
// Create unique orbit identifiers: Wyckoff position + element symbol
|
|
139
147
|
const orbit_ids = structure.sites.map((site, idx) => {
|
|
140
148
|
const sym_idx = get_orig_site_idx(site, idx);
|
|
149
|
+
const mapped_wyckoff = wyckoff_by_orig_idx.get(sym_idx);
|
|
150
|
+
if (mapped_wyckoff !== undefined) {
|
|
151
|
+
const element = site.species[0]?.element ?? `?`;
|
|
152
|
+
return mapped_wyckoff ? `${mapped_wyckoff}|${element}` : `unknown`;
|
|
153
|
+
}
|
|
141
154
|
if (sym_idx >= sym_data.wyckoffs.length) {
|
|
142
155
|
console.error(`[get_wyckoff_colors] Site ${idx} (maps to ${sym_idx}) has no Wyckoff data. ` +
|
|
143
156
|
`Structure has ${n} sites but symmetry data only has ${sym_data.wyckoffs.length}.`);
|
package/dist/structure/export.js
CHANGED
|
@@ -10,13 +10,16 @@ export function has_color_property(mat) {
|
|
|
10
10
|
if (!(`color` in mat))
|
|
11
11
|
return false;
|
|
12
12
|
const color = mat.color;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
if (!color || typeof color !== `object`)
|
|
14
|
+
return false;
|
|
15
|
+
// Check for Color-like object with numeric r/g/b channels (duck typing)
|
|
16
|
+
const color_obj = color;
|
|
17
|
+
const red_channel = color_obj.r;
|
|
18
|
+
const green_channel = color_obj.g;
|
|
19
|
+
const blue_channel = color_obj.b;
|
|
20
|
+
return typeof red_channel === `number` &&
|
|
21
|
+
typeof green_channel === `number` &&
|
|
22
|
+
typeof blue_channel === `number`;
|
|
20
23
|
}
|
|
21
24
|
// Extract color from a ShaderMaterial by checking common color uniform patterns
|
|
22
25
|
function extract_shader_color(shader_mat) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Vec3 } from '../math';
|
|
1
2
|
export type WasmResult<T> = {
|
|
2
3
|
ok: T;
|
|
3
4
|
} | {
|
|
@@ -14,7 +15,7 @@ export declare function unwrap_or<T>(result: WasmResult<T>, default_value: T): T
|
|
|
14
15
|
export interface NeighborListResult {
|
|
15
16
|
center_indices: number[];
|
|
16
17
|
neighbor_indices: number[];
|
|
17
|
-
image_offsets: [
|
|
18
|
+
image_offsets: Vec3[];
|
|
18
19
|
distances: number[];
|
|
19
20
|
}
|
|
20
21
|
export interface MatcherOptions {
|
|
@@ -28,7 +29,7 @@ export interface MatcherOptions {
|
|
|
28
29
|
export type StructureFormat = `cif` | `poscar` | `json`;
|
|
29
30
|
export type ReductionAlgorithm = `niggli` | `lll`;
|
|
30
31
|
export interface HklInfo {
|
|
31
|
-
hkl:
|
|
32
|
+
hkl: Vec3;
|
|
32
33
|
multiplicity: number;
|
|
33
34
|
}
|
|
34
35
|
export interface XrdPattern {
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// Pure type definitions and utility functions for ferrox-wasm results.
|
|
2
|
-
// This module has no WASM side effects, making it safe to import in tests
|
|
3
|
-
// without triggering WASM resolution.
|
|
4
1
|
// Type guard to check if result is successful
|
|
5
2
|
export function is_ok(result) {
|
|
6
3
|
return `ok` in result;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Vec3 } from '../math';
|
|
1
2
|
import type { Crystal } from './';
|
|
2
3
|
import type { MatcherOptions, NeighborListResult, ReductionAlgorithm, StructureFormat, WasmResult, XrdOptions, XrdPattern } from './ferrox-wasm-types';
|
|
3
4
|
export * from './ferrox-wasm-types';
|
|
@@ -81,8 +82,8 @@ export declare function interpolate_structures(start: Crystal, end: Crystal, n_i
|
|
|
81
82
|
}): Promise<WasmResult<Crystal[]>>;
|
|
82
83
|
export declare function copy_structure(structure: Crystal, sanitize?: boolean): Promise<WasmResult<Crystal>>;
|
|
83
84
|
export declare function wrap_to_unit_cell(structure: Crystal): Promise<WasmResult<Crystal>>;
|
|
84
|
-
export declare function create_supercell_matrix(structure: Crystal, matrix: [
|
|
85
|
-
export declare function translate_sites(structure: Crystal, indices: number[], vector:
|
|
85
|
+
export declare function create_supercell_matrix(structure: Crystal, matrix: [Vec3, Vec3, Vec3]): Promise<WasmResult<Crystal>>;
|
|
86
|
+
export declare function translate_sites(structure: Crystal, indices: number[], vector: Vec3, frac_coords?: boolean): Promise<WasmResult<Crystal>>;
|
|
86
87
|
export declare function perturb_structure(structure: Crystal, distance: number, options?: {
|
|
87
88
|
min_distance?: number;
|
|
88
89
|
seed?: number;
|
|
@@ -25,8 +25,7 @@ export function ensure_ferrox_wasm_ready() {
|
|
|
25
25
|
init_promise = (async () => {
|
|
26
26
|
try {
|
|
27
27
|
// Dynamic import to avoid loading WASM until needed
|
|
28
|
-
const { default: init } = (await import(
|
|
29
|
-
/* @vite-ignore */ `matterviz-wasm`));
|
|
28
|
+
const { default: init } = (await import(`matterviz-wasm`));
|
|
30
29
|
// Initialize WASM module (the package handles WASM loading internally)
|
|
31
30
|
wasm_module = await init();
|
|
32
31
|
return wasm_module;
|
|
@@ -20,6 +20,7 @@ export { default as StructureExportPane } from './StructureExportPane.svelte';
|
|
|
20
20
|
export { default as StructureInfoPane } from './StructureInfoPane.svelte';
|
|
21
21
|
export { default as StructureScene } from './StructureScene.svelte';
|
|
22
22
|
export * from './supercell';
|
|
23
|
+
export type MeasureMode = `distance` | `angle` | `edit-bonds` | `edit-atoms`;
|
|
23
24
|
export type Species = {
|
|
24
25
|
element: ElementSymbol;
|
|
25
26
|
occu: number;
|
|
@@ -66,6 +67,11 @@ export declare function format_formula_by_electronegativity(structure: AnyStruct
|
|
|
66
67
|
export declare const atomic_radii: CompositionType;
|
|
67
68
|
export declare function get_density(structure: Crystal): number;
|
|
68
69
|
export declare function get_center_of_mass(structure: AnyStructure): Vec3;
|
|
70
|
+
export declare function get_site_vector_info(site: Site): {
|
|
71
|
+
vec: Vec3;
|
|
72
|
+
key: string;
|
|
73
|
+
} | null;
|
|
74
|
+
export declare function get_site_vector(site: Site): Vec3 | null;
|
|
69
75
|
export interface StructureHandlerData {
|
|
70
76
|
structure?: AnyStructure;
|
|
71
77
|
filename?: string;
|
|
@@ -74,6 +80,7 @@ export interface StructureHandlerData {
|
|
|
74
80
|
error_msg?: string;
|
|
75
81
|
fullscreen?: boolean;
|
|
76
82
|
camera_position?: Vec3;
|
|
83
|
+
camera_target?: Vec3;
|
|
77
84
|
camera_has_moved?: boolean;
|
|
78
85
|
color_scheme?: string;
|
|
79
86
|
performance_mode?: `quality` | `speed`;
|
package/dist/structure/index.js
CHANGED
|
@@ -84,3 +84,25 @@ export function get_center_of_mass(structure) {
|
|
|
84
84
|
}
|
|
85
85
|
return math.scale(center, 1 / total_weight);
|
|
86
86
|
}
|
|
87
|
+
// Property keys checked for per-site vector data (force, magnetic moment, spin)
|
|
88
|
+
const VECTOR_PROPERTY_KEYS = [`force`, `magmom`, `spin`];
|
|
89
|
+
// Extract a vector and its source key from a site's properties. Checks force, magmom,
|
|
90
|
+
// and spin in priority order. Scalar values are converted to z-directed vectors [0, 0, val].
|
|
91
|
+
export function get_site_vector_info(site) {
|
|
92
|
+
const props = site.properties;
|
|
93
|
+
if (!props)
|
|
94
|
+
return null;
|
|
95
|
+
for (const key of VECTOR_PROPERTY_KEYS) {
|
|
96
|
+
const val = props[key];
|
|
97
|
+
if (Array.isArray(val) && val.length === 3 &&
|
|
98
|
+
val.every((elem) => typeof elem === `number` && isFinite(elem)))
|
|
99
|
+
return { vec: val, key };
|
|
100
|
+
if (typeof val === `number` && isFinite(val))
|
|
101
|
+
return { vec: [0, 0, val], key };
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
// Convenience wrapper returning just the vector (preserves existing API)
|
|
106
|
+
export function get_site_vector(site) {
|
|
107
|
+
return get_site_vector_info(site)?.vec ?? null;
|
|
108
|
+
}
|
package/dist/structure/parse.js
CHANGED
|
@@ -2,9 +2,8 @@ import { COMPRESSION_EXTENSIONS_REGEX, CONFIG_DIRS_REGEX, STRUCT_KEYWORDS_REGEX,
|
|
|
2
2
|
import { ELEM_SYMBOLS } from '../labels';
|
|
3
3
|
import * as math from '../math';
|
|
4
4
|
import { wrap_to_unit_cell } from './pbc';
|
|
5
|
+
import { normalize_scientific_notation } from '../utils';
|
|
5
6
|
import { load as yaml_load } from 'js-yaml';
|
|
6
|
-
// Normalize scientific notation in coordinate strings (handles eEdD and *^ notation variants)
|
|
7
|
-
const normalize_scientific_notation = (str) => str.toLowerCase().replace(/d/g, `e`).replace(/\*\^/g, `e`);
|
|
8
7
|
// Parse a coordinate value that might be in various scientific notation formats
|
|
9
8
|
function parse_coordinate(str) {
|
|
10
9
|
const normalized = normalize_scientific_notation(str.trim());
|
|
@@ -939,11 +938,10 @@ function find_structure_in_json(obj, visited = new WeakSet()) {
|
|
|
939
938
|
return null;
|
|
940
939
|
}
|
|
941
940
|
// Check if this object looks like a valid structure
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
return potential_structure;
|
|
941
|
+
if (is_parsed_structure(obj))
|
|
942
|
+
return obj;
|
|
945
943
|
// Otherwise, recursively search through all properties
|
|
946
|
-
for (const value of Object.values(
|
|
944
|
+
for (const value of Object.values(obj)) {
|
|
947
945
|
const result = find_structure_in_json(value, visited);
|
|
948
946
|
if (result)
|
|
949
947
|
return result;
|
|
@@ -954,17 +952,19 @@ function find_structure_in_json(obj, visited = new WeakSet()) {
|
|
|
954
952
|
function is_parsed_structure(obj) {
|
|
955
953
|
if (!obj || typeof obj !== `object`)
|
|
956
954
|
return false;
|
|
957
|
-
const
|
|
958
|
-
|
|
959
|
-
if (!Array.isArray(
|
|
955
|
+
const parsed_obj = obj;
|
|
956
|
+
const sites = parsed_obj.sites;
|
|
957
|
+
if (!Array.isArray(sites) || sites.length === 0)
|
|
960
958
|
return false;
|
|
961
|
-
|
|
962
|
-
const first_site = record.sites[0];
|
|
959
|
+
const first_site = sites[0];
|
|
963
960
|
if (!first_site || typeof first_site !== `object`)
|
|
964
961
|
return false;
|
|
965
|
-
|
|
966
|
-
const
|
|
967
|
-
const
|
|
962
|
+
const first_site_obj = first_site;
|
|
963
|
+
const species = first_site_obj.species;
|
|
964
|
+
const abc = first_site_obj.abc;
|
|
965
|
+
const xyz = first_site_obj.xyz;
|
|
966
|
+
const has_species = Array.isArray(species) && species.length > 0;
|
|
967
|
+
const has_coords = Array.isArray(abc) || Array.isArray(xyz);
|
|
968
968
|
return has_species && has_coords;
|
|
969
969
|
}
|
|
970
970
|
// Normalize structure coordinates: wrap fractional coords to [0,1) and recompute Cartesian
|
|
@@ -1268,8 +1268,11 @@ function is_optimade_structure_object(value) {
|
|
|
1268
1268
|
if (!value || typeof value !== `object`)
|
|
1269
1269
|
return false;
|
|
1270
1270
|
const obj = value;
|
|
1271
|
-
|
|
1272
|
-
|
|
1271
|
+
const type = obj.type;
|
|
1272
|
+
const id = obj.id;
|
|
1273
|
+
const attributes = obj.attributes;
|
|
1274
|
+
return type === `structures` && typeof id === `string` &&
|
|
1275
|
+
typeof attributes === `object` && attributes !== null;
|
|
1273
1276
|
}
|
|
1274
1277
|
// Convert OPTIMADE structure to Crystal format
|
|
1275
1278
|
export function optimade_to_crystal(optimade_structure) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Site } from './';
|
|
2
|
+
export declare const PARTIAL_OCCUPANCY_SLICE_GAP_RAD = 0.001;
|
|
3
|
+
export type RenderSite = {
|
|
4
|
+
site_idx: number;
|
|
5
|
+
site: Site;
|
|
6
|
+
is_image_atom: boolean;
|
|
7
|
+
source_site_indices: number[];
|
|
8
|
+
};
|
|
9
|
+
export type SliceGeometry = {
|
|
10
|
+
element: string;
|
|
11
|
+
occupancy: number;
|
|
12
|
+
start_phi: number;
|
|
13
|
+
end_phi: number;
|
|
14
|
+
phi_length: number;
|
|
15
|
+
render_start_cap: boolean;
|
|
16
|
+
render_end_cap: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type CapArcConfig = {
|
|
19
|
+
start_cap_arc_start: number;
|
|
20
|
+
end_cap_arc_start: number;
|
|
21
|
+
arc_length: number;
|
|
22
|
+
};
|
|
23
|
+
export declare const PARTIAL_OCCUPANCY_CAP_ARC: CapArcConfig;
|
|
24
|
+
export declare const merge_split_partial_sites: (sites: Site[], hidden_elements?: ReadonlySet<string>) => RenderSite[];
|
|
25
|
+
export declare const compute_slice_geometry: (visible_species: Site[`species`], slice_gap_rad?: number) => SliceGeometry[];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export const PARTIAL_OCCUPANCY_SLICE_GAP_RAD = 1e-3;
|
|
2
|
+
const OCCUPANCY_EPS = 1e-6;
|
|
3
|
+
const MIN_PHI_LENGTH = 1e-4;
|
|
4
|
+
const MERGE_DISTANCE_TOLERANCE = 1e-8;
|
|
5
|
+
const CAP_ARC_START = Math.PI / 2;
|
|
6
|
+
const is_image_atom = (site) => typeof site.properties?.orig_site_idx === `number`;
|
|
7
|
+
const make_render_site = (sites, site_idx, source_site_indices, site_override) => ({
|
|
8
|
+
site_idx,
|
|
9
|
+
site: site_override ?? sites[site_idx],
|
|
10
|
+
is_image_atom: source_site_indices.some((source_site_idx) => is_image_atom(sites[source_site_idx])),
|
|
11
|
+
source_site_indices,
|
|
12
|
+
});
|
|
13
|
+
const sq_dist = (xyz_1, xyz_2) => (xyz_1[0] - xyz_2[0]) ** 2 +
|
|
14
|
+
(xyz_1[1] - xyz_2[1]) ** 2 +
|
|
15
|
+
(xyz_1[2] - xyz_2[2]) ** 2;
|
|
16
|
+
const is_split_partial_site = (site, hidden_elements) => {
|
|
17
|
+
const visible_species = site.species.filter(({ element }) => !hidden_elements.has(element));
|
|
18
|
+
const total_visible_occupancy = visible_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
|
|
19
|
+
return visible_species.length === 1 && total_visible_occupancy < 1 - OCCUPANCY_EPS;
|
|
20
|
+
};
|
|
21
|
+
const group_split_partial_indices = (sites, hidden_elements) => {
|
|
22
|
+
const grouped_centers = [];
|
|
23
|
+
const grouped_site_indices = [];
|
|
24
|
+
const non_grouped_site_indices = [];
|
|
25
|
+
for (const [site_idx, site] of sites.entries()) {
|
|
26
|
+
if (!is_split_partial_site(site, hidden_elements)) {
|
|
27
|
+
non_grouped_site_indices.push(site_idx);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const matched_group_idx = grouped_centers.findIndex((center_xyz) => sq_dist(center_xyz, site.xyz) <= MERGE_DISTANCE_TOLERANCE ** 2);
|
|
31
|
+
if (matched_group_idx === -1) {
|
|
32
|
+
grouped_centers.push(site.xyz);
|
|
33
|
+
grouped_site_indices.push([site_idx]);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
grouped_site_indices[matched_group_idx].push(site_idx);
|
|
37
|
+
}
|
|
38
|
+
return { non_grouped_site_indices, grouped_site_indices };
|
|
39
|
+
};
|
|
40
|
+
const build_render_sites = (sites, non_grouped_site_indices, grouped_site_indices) => {
|
|
41
|
+
const render_sites = non_grouped_site_indices.map((site_idx) => make_render_site(sites, site_idx, [site_idx]));
|
|
42
|
+
for (const grouped_indices of grouped_site_indices) {
|
|
43
|
+
if (grouped_indices.length === 1) {
|
|
44
|
+
const site_idx = grouped_indices[0];
|
|
45
|
+
render_sites.push(make_render_site(sites, site_idx, [site_idx]));
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const representative_site_idx = grouped_indices[0];
|
|
49
|
+
const representative_site = sites[representative_site_idx];
|
|
50
|
+
const merged_species = grouped_indices.flatMap((grouped_site_idx) => sites[grouped_site_idx].species);
|
|
51
|
+
render_sites.push(make_render_site(sites, representative_site_idx, [...grouped_indices], { ...representative_site, species: merged_species }));
|
|
52
|
+
}
|
|
53
|
+
return render_sites;
|
|
54
|
+
};
|
|
55
|
+
export const PARTIAL_OCCUPANCY_CAP_ARC = {
|
|
56
|
+
start_cap_arc_start: CAP_ARC_START,
|
|
57
|
+
end_cap_arc_start: CAP_ARC_START,
|
|
58
|
+
arc_length: Math.PI,
|
|
59
|
+
};
|
|
60
|
+
export const merge_split_partial_sites = (sites, hidden_elements = new Set()) => {
|
|
61
|
+
const grouped_indices = group_split_partial_indices(sites, hidden_elements);
|
|
62
|
+
return build_render_sites(sites, grouped_indices.non_grouped_site_indices, grouped_indices.grouped_site_indices);
|
|
63
|
+
};
|
|
64
|
+
export const compute_slice_geometry = (visible_species, slice_gap_rad = PARTIAL_OCCUPANCY_SLICE_GAP_RAD) => {
|
|
65
|
+
if (visible_species.length === 0)
|
|
66
|
+
return [];
|
|
67
|
+
const total_visible_occupancy = visible_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
|
|
68
|
+
// Preserve total angular coverage at one full turn for invalid overfull inputs.
|
|
69
|
+
const occupancy_scale_factor = total_visible_occupancy > 1 + OCCUPANCY_EPS
|
|
70
|
+
? 1 / total_visible_occupancy
|
|
71
|
+
: 1;
|
|
72
|
+
const normalized_species = visible_species.map(({ element, occu }) => ({
|
|
73
|
+
element,
|
|
74
|
+
occu: occu * occupancy_scale_factor,
|
|
75
|
+
}));
|
|
76
|
+
const normalized_total_occupancy = normalized_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
|
|
77
|
+
const has_vacancy_gap = normalized_total_occupancy < 1 - OCCUPANCY_EPS;
|
|
78
|
+
const last_visible_species_idx = normalized_species.length - 1;
|
|
79
|
+
let start_angle = 0;
|
|
80
|
+
return normalized_species.map(({ element, occu }, species_idx) => {
|
|
81
|
+
const start_phi_raw = 2 * Math.PI * start_angle;
|
|
82
|
+
const end_phi_raw = 2 * Math.PI * (start_angle += occu);
|
|
83
|
+
// Keep neighboring wedges from sharing the exact same plane (z-fighting).
|
|
84
|
+
const phi_span_raw = Math.max(0, end_phi_raw - start_phi_raw);
|
|
85
|
+
const max_safe_gap = Math.max(0, phi_span_raw - MIN_PHI_LENGTH);
|
|
86
|
+
const desired_gap = visible_species.length > 1
|
|
87
|
+
? Math.min(slice_gap_rad, phi_span_raw * 0.25)
|
|
88
|
+
: 0;
|
|
89
|
+
const phi_gap = Math.min(desired_gap, max_safe_gap);
|
|
90
|
+
const start_phi = start_phi_raw + phi_gap / 2;
|
|
91
|
+
const end_phi = end_phi_raw - phi_gap / 2;
|
|
92
|
+
return {
|
|
93
|
+
element,
|
|
94
|
+
occupancy: occu,
|
|
95
|
+
start_phi,
|
|
96
|
+
end_phi,
|
|
97
|
+
phi_length: Math.max(MIN_PHI_LENGTH, end_phi - start_phi),
|
|
98
|
+
render_start_cap: has_vacancy_gap && species_idx === 0,
|
|
99
|
+
render_end_cap: has_vacancy_gap && species_idx === last_visible_species_idx,
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export function is_crystal(obj) {
|
|
2
2
|
if (obj === null || typeof obj !== `object`)
|
|
3
3
|
return false;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const structure_obj = obj;
|
|
5
|
+
const sites = structure_obj.sites;
|
|
6
|
+
const lattice = structure_obj.lattice;
|
|
7
|
+
const has_sites = Array.isArray(sites) && sites.length > 0;
|
|
8
|
+
const has_lattice = lattice !== undefined && lattice !== null &&
|
|
9
|
+
typeof lattice === `object`;
|
|
7
10
|
return has_sites && has_lattice;
|
|
8
11
|
}
|
|
@@ -4,6 +4,7 @@ import { default_sym_settings, wyckoff_positions_from_moyo } from './index';
|
|
|
4
4
|
import * as spg from './spacegroups';
|
|
5
5
|
let { sym_data, settings = $bindable(default_sym_settings), show_tooltips = true, children, label = `Symmetry`, header, ...rest } = $props();
|
|
6
6
|
const wyckoff_count = $derived(sym_data ? wyckoff_positions_from_moyo(sym_data).length : 0);
|
|
7
|
+
const display_hm_symbol = $derived(sym_data?.hm_symbol?.replace(/\s+/g, ``) ?? `?`);
|
|
7
8
|
const sym_ops_counts = $derived.by(() => {
|
|
8
9
|
const EPS = 1e-10;
|
|
9
10
|
if (!sym_data?.operations) {
|
|
@@ -36,6 +37,13 @@ const titles = {
|
|
|
36
37
|
roto_translations: `Number of roto-translations in the crystal structure.`,
|
|
37
38
|
};
|
|
38
39
|
const tooltips = $derived(show_tooltips ? titles : {});
|
|
40
|
+
function get_step_from_order_of_magnitude(value) {
|
|
41
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
42
|
+
return 1e-5;
|
|
43
|
+
const exponent = Math.floor(Math.log10(value));
|
|
44
|
+
return Math.pow(10, exponent);
|
|
45
|
+
}
|
|
46
|
+
const symprec_step = $derived(get_step_from_order_of_magnitude(settings.symprec));
|
|
39
47
|
</script>
|
|
40
48
|
|
|
41
49
|
<div {...rest} class="symmetry-stats {rest.class ?? ``}">
|
|
@@ -55,15 +63,21 @@ const tooltips = $derived(show_tooltips ? titles : {});
|
|
|
55
63
|
<span {@attach tooltip()} title={tooltips?.symprec}>Precision</span>
|
|
56
64
|
<input
|
|
57
65
|
type="number"
|
|
58
|
-
step=
|
|
66
|
+
step={symprec_step}
|
|
59
67
|
value={settings.symprec}
|
|
60
|
-
|
|
68
|
+
oninput={(evt) => {
|
|
61
69
|
const { value } = evt.currentTarget
|
|
62
|
-
|
|
70
|
+
if (value === ``) return
|
|
71
|
+
const parsed = Number(value)
|
|
63
72
|
if (Number.isFinite(parsed)) {
|
|
64
73
|
settings = { ...settings, symprec: parsed }
|
|
65
74
|
}
|
|
66
75
|
}}
|
|
76
|
+
onkeydown={(evt) => {
|
|
77
|
+
if (evt.key === `Escape`) {
|
|
78
|
+
evt.currentTarget.blur()
|
|
79
|
+
}
|
|
80
|
+
}}
|
|
67
81
|
/>
|
|
68
82
|
</label>
|
|
69
83
|
<label>
|
|
@@ -91,7 +105,7 @@ const tooltips = $derived(show_tooltips ? titles : {});
|
|
|
91
105
|
title="{tooltips?.space_group} at {settings.symprec} (using {settings.algo} algo). {tooltips?.hermann_mauguin}"
|
|
92
106
|
{@attach tooltip()}
|
|
93
107
|
>
|
|
94
|
-
Space Group <strong>{sym_data.number} ({
|
|
108
|
+
Space Group <strong>{sym_data.number} ({display_hm_symbol})</strong>
|
|
95
109
|
</div>
|
|
96
110
|
<div title={tooltips?.crystal_system} {@attach tooltip()}>
|
|
97
111
|
Crystal System <strong>{spg.spacegroup_to_crystal_sys(sym_data.number)}</strong>
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { format_fractional } from '../labels';
|
|
3
3
|
import { colors } from '../state.svelte';
|
|
4
4
|
let { wyckoff_positions, on_hover, on_click, active_color = `#2563eb`, ...rest } = $props();
|
|
5
|
-
let
|
|
5
|
+
let selected_key = $state(null);
|
|
6
|
+
const get_row_key = (wyckoff_pos, row_idx) => `${wyckoff_pos.wyckoff}-${wyckoff_pos.elem}-${wyckoff_pos.site_indices?.join(`,`) ?? `none`}-${row_idx}`;
|
|
6
7
|
</script>
|
|
7
8
|
|
|
8
9
|
{#if wyckoff_positions && wyckoff_positions.length > 0}
|
|
@@ -22,10 +23,14 @@ let selected_wyckoff = $state(null);
|
|
|
22
23
|
</tr>
|
|
23
24
|
</thead>
|
|
24
25
|
<tbody>
|
|
25
|
-
{#each wyckoff_positions as
|
|
26
|
+
{#each wyckoff_positions as
|
|
27
|
+
wyckoff_pos,
|
|
28
|
+
row_idx
|
|
29
|
+
(get_row_key(wyckoff_pos, row_idx))
|
|
30
|
+
}
|
|
26
31
|
{@const { wyckoff, elem, abc, site_indices } = wyckoff_pos}
|
|
27
|
-
{@const
|
|
28
|
-
|
|
32
|
+
{@const row_key = get_row_key(wyckoff_pos, row_idx)}
|
|
33
|
+
{@const is_selected = selected_key === row_key}
|
|
29
34
|
<tr
|
|
30
35
|
class="wyckoff-row"
|
|
31
36
|
tabindex="0"
|
|
@@ -35,16 +40,14 @@ let selected_wyckoff = $state(null);
|
|
|
35
40
|
onmouseenter={() => on_hover?.(site_indices ?? null)}
|
|
36
41
|
onmouseleave={() => on_hover?.(null)}
|
|
37
42
|
onclick={() => {
|
|
38
|
-
|
|
39
|
-
on_click?.(
|
|
43
|
+
selected_key = is_selected ? null : row_key
|
|
44
|
+
on_click?.(is_selected ? null : (wyckoff_pos.site_indices ?? null))
|
|
40
45
|
}}
|
|
41
46
|
onkeydown={(event) => {
|
|
42
47
|
if ([`Enter`, ` `].includes(event.key)) {
|
|
43
48
|
event.preventDefault()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
selected_wyckoff = is_selected ? null : wyckoff_pos
|
|
47
|
-
on_click?.(selected_wyckoff?.site_indices ?? null)
|
|
49
|
+
selected_key = is_selected ? null : row_key
|
|
50
|
+
on_click?.(is_selected ? null : (wyckoff_pos.site_indices ?? null))
|
|
48
51
|
}
|
|
49
52
|
}}
|
|
50
53
|
>
|
|
@@ -69,6 +72,11 @@ let selected_wyckoff = $state(null);
|
|
|
69
72
|
.wyckoff-table {
|
|
70
73
|
margin-top: 1em;
|
|
71
74
|
}
|
|
75
|
+
.wyckoff-table :is(th, td) {
|
|
76
|
+
padding: 2px 6px;
|
|
77
|
+
text-align: center;
|
|
78
|
+
vertical-align: middle;
|
|
79
|
+
}
|
|
72
80
|
.wyckoff-row {
|
|
73
81
|
cursor: pointer;
|
|
74
82
|
transition: background-color 0.2s ease;
|