matterviz 0.1.13 → 0.1.14
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 +1 -1
- package/dist/FilePicker.svelte.d.ts +1 -1
- package/dist/bands/Bands.svelte +137 -71
- package/dist/bands/Bands.svelte.d.ts +3 -1
- package/dist/bands/BandsAndDos.svelte +12 -3
- package/dist/bands/BandsAndDos.svelte.d.ts +3 -2
- package/dist/bands/BrillouinBandsDos.svelte +122 -0
- package/dist/bands/BrillouinBandsDos.svelte.d.ts +19 -0
- package/dist/bands/Dos.svelte +86 -42
- package/dist/bands/Dos.svelte.d.ts +5 -3
- package/dist/bands/helpers.d.ts +11 -7
- package/dist/bands/helpers.js +109 -8
- package/dist/bands/index.d.ts +3 -2
- package/dist/bands/index.js +3 -2
- package/dist/bands/types.d.ts +7 -1
- package/dist/brillouin/BrillouinZone.svelte +12 -5
- package/dist/brillouin/BrillouinZone.svelte.d.ts +13 -3
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +2 -2
- package/dist/brillouin/BrillouinZoneScene.svelte +89 -31
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +10 -1
- package/dist/brillouin/compute.js +6 -6
- package/dist/colors/index.d.ts +1 -0
- package/dist/colors/index.js +18 -0
- package/dist/composition/BarChart.svelte +3 -1
- package/dist/composition/BarChart.svelte.d.ts +4 -1
- package/dist/composition/BubbleChart.svelte +6 -5
- package/dist/composition/BubbleChart.svelte.d.ts +4 -1
- package/dist/composition/Formula.svelte +181 -0
- package/dist/composition/Formula.svelte.d.ts +18 -0
- package/dist/composition/PieChart.svelte +3 -1
- package/dist/composition/PieChart.svelte.d.ts +4 -1
- package/dist/composition/index.d.ts +2 -1
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.d.ts +15 -1
- package/dist/composition/parse.js +98 -2
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +17 -0
- package/dist/coordination/CoordinationBarPlot.svelte +76 -66
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +2 -2
- package/dist/coordination/calc-coordination.js +11 -24
- package/dist/element/ElementTile.svelte +7 -8
- package/dist/feedback/CopyFeedback.svelte +42 -0
- package/dist/feedback/CopyFeedback.svelte.d.ts +10 -0
- package/dist/feedback/DragOverlay.svelte +34 -0
- package/dist/feedback/DragOverlay.svelte.d.ts +7 -0
- package/dist/feedback/StatusMessage.svelte +69 -0
- package/dist/feedback/StatusMessage.svelte.d.ts +9 -0
- package/dist/feedback/index.d.ts +4 -0
- package/dist/feedback/index.js +4 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +5 -8
- package/dist/index.js +5 -15
- package/dist/io/export.js +16 -16
- package/dist/labels.js +1 -2
- package/dist/{InfoCard.svelte → layout/InfoCard.svelte} +1 -1
- package/dist/{Nav.svelte → layout/Nav.svelte} +1 -1
- package/dist/{Nav.svelte.d.ts → layout/Nav.svelte.d.ts} +1 -1
- package/dist/{SettingsSection.svelte → layout/SettingsSection.svelte} +2 -2
- package/dist/{SettingsSection.svelte.d.ts → layout/SettingsSection.svelte.d.ts} +7 -1
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/{ContextMenu.svelte → overlays/ContextMenu.svelte} +1 -1
- package/dist/{DraggablePane.svelte → overlays/DraggablePane.svelte} +2 -2
- package/dist/{DraggablePane.svelte.d.ts → overlays/DraggablePane.svelte.d.ts} +9 -2
- package/dist/overlays/index.d.ts +2 -0
- package/dist/overlays/index.js +2 -0
- package/dist/periodic-table/PeriodicTable.svelte +2 -3
- package/dist/periodic-table/PropertySelect.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagram2D.svelte +211 -269
- package/dist/phase-diagram/PhaseDiagram2D.svelte.d.ts +2 -2
- package/dist/phase-diagram/PhaseDiagram3D.svelte +57 -146
- package/dist/phase-diagram/PhaseDiagram3D.svelte.d.ts +4 -2
- package/dist/phase-diagram/PhaseDiagram4D.svelte +52 -135
- package/dist/phase-diagram/PhaseDiagram4D.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +83 -81
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramInfoPane.svelte +1 -1
- package/dist/phase-diagram/PhaseDiagramInfoPane.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramStats.svelte +7 -8
- package/dist/phase-diagram/PhaseEntryTooltip.svelte +43 -0
- package/dist/phase-diagram/PhaseEntryTooltip.svelte.d.ts +7 -0
- package/dist/phase-diagram/StructurePopup.svelte +0 -10
- package/dist/phase-diagram/helpers.d.ts +18 -1
- package/dist/phase-diagram/helpers.js +73 -0
- package/dist/phase-diagram/index.d.ts +4 -0
- package/dist/phase-diagram/thermodynamics.js +6 -8
- package/dist/phase-diagram/types.d.ts +9 -2
- package/dist/plot/BarPlot.svelte +62 -42
- package/dist/plot/BarPlot.svelte.d.ts +7 -7
- package/dist/plot/BarPlotControls.svelte +4 -4
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ElementScatter.svelte +1 -1
- package/dist/plot/ElementScatter.svelte.d.ts +2 -2
- package/dist/plot/Histogram.svelte +339 -280
- package/dist/plot/Histogram.svelte.d.ts +3 -10
- package/dist/plot/HistogramControls.svelte +5 -7
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/PlotControls.svelte +35 -40
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPlot.svelte +189 -297
- package/dist/plot/ScatterPlot.svelte.d.ts +6 -11
- package/dist/plot/ScatterPlotControls.svelte +2 -4
- package/dist/plot/ScatterPlotControls.svelte.d.ts +2 -3
- package/dist/plot/SpacegroupBarPlot.svelte +17 -21
- package/dist/plot/data-transform.js +1 -1
- package/dist/plot/index.d.ts +0 -14
- package/dist/plot/index.js +0 -28
- package/dist/plot/layout.d.ts +1 -0
- package/dist/plot/layout.js +3 -1
- package/dist/plot/scales.d.ts +11 -0
- package/dist/plot/scales.js +40 -1
- package/dist/plot/types.d.ts +53 -9
- package/dist/plot/types.js +26 -1
- package/dist/plot/utils/label-placement.d.ts +40 -0
- package/dist/plot/utils/label-placement.js +91 -0
- package/dist/plot/utils/series-visibility.d.ts +7 -0
- package/dist/plot/utils/series-visibility.js +53 -0
- package/dist/rdf/RdfPlot.svelte +133 -76
- package/dist/rdf/RdfPlot.svelte.d.ts +7 -2
- package/dist/rdf/calc-rdf.js +3 -2
- package/dist/settings.d.ts +6 -0
- package/dist/settings.js +30 -6
- package/dist/structure/{Vector.svelte.d.ts → Arrow.svelte.d.ts} +3 -3
- package/dist/structure/Bond.svelte +22 -38
- package/dist/structure/CanvasTooltip.svelte +1 -1
- package/dist/structure/CanvasTooltip.svelte.d.ts +3 -1
- package/dist/structure/Structure.svelte +165 -9
- package/dist/structure/Structure.svelte.d.ts +9 -2
- package/dist/structure/StructureControls.svelte +80 -45
- package/dist/structure/StructureControls.svelte.d.ts +2 -1
- package/dist/structure/StructureExportPane.svelte +1 -1
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +19 -37
- package/dist/structure/StructureInfoPane.svelte.d.ts +3 -1
- package/dist/structure/StructureScene.svelte +60 -33
- package/dist/structure/StructureScene.svelte.d.ts +6 -1
- package/dist/structure/bonding.js +6 -5
- package/dist/structure/index.d.ts +5 -5
- package/dist/structure/index.js +11 -13
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +3 -2
- package/dist/structure/parse.js +24 -25
- package/dist/structure/pbc.js +4 -6
- package/dist/structure/supercell.d.ts +1 -1
- package/dist/structure/supercell.js +50 -52
- package/dist/structure/validation.d.ts +2 -0
- package/dist/structure/validation.js +8 -0
- package/dist/symmetry/SymmetryStats.svelte +157 -0
- package/dist/symmetry/SymmetryStats.svelte.d.ts +18 -0
- package/dist/symmetry/WyckoffTable.svelte +1 -1
- package/dist/symmetry/index.d.ts +21 -2
- package/dist/symmetry/index.js +39 -56
- package/dist/symmetry/spacegroups.d.ts +2 -2
- package/dist/symmetry/spacegroups.js +8 -11
- package/dist/trajectory/Trajectory.svelte +11 -11
- package/dist/trajectory/Trajectory.svelte.d.ts +3 -1
- package/dist/trajectory/TrajectoryExportPane.svelte +1 -1
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +8 -10
- package/dist/trajectory/index.d.ts +1 -1
- package/dist/trajectory/index.js +13 -16
- package/dist/trajectory/parse.js +18 -15
- package/dist/trajectory/plotting.js +16 -14
- package/dist/xrd/XrdPlot.svelte +70 -55
- package/dist/xrd/XrdPlot.svelte.d.ts +2 -3
- package/dist/xrd/calc-xrd.js +14 -27
- package/dist/xrd/index.d.ts +2 -2
- package/package.json +26 -18
- /package/dist/{Spinner.svelte → feedback/Spinner.svelte} +0 -0
- /package/dist/{Spinner.svelte.d.ts → feedback/Spinner.svelte.d.ts} +0 -0
- /package/dist/{InfoCard.svelte.d.ts → layout/InfoCard.svelte.d.ts} +0 -0
- /package/dist/{ContextMenu.svelte.d.ts → overlays/ContextMenu.svelte.d.ts} +0 -0
- /package/dist/structure/{Vector.svelte → Arrow.svelte} +0 -0
package/dist/FilePicker.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">import { tooltip } from 'svelte-multiselect';
|
|
2
|
-
let { files, active_files = [], show_category_filters = false, on_drag_start, on_drag_end, type_mapper, file_type_colors = {
|
|
2
|
+
let { files = [], active_files = [], show_category_filters = false, on_drag_start, on_drag_end, type_mapper, file_type_colors = {
|
|
3
3
|
cif: `rgba(100, 149, 237, 0.8)`,
|
|
4
4
|
xyz: `rgba(50, 205, 50, 0.8)`,
|
|
5
5
|
extxyz: `rgba(50, 205, 50, 0.8)`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FileInfo } from './';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
4
|
-
files
|
|
4
|
+
files?: FileInfo[];
|
|
5
5
|
active_files?: string[];
|
|
6
6
|
show_category_filters?: boolean;
|
|
7
7
|
on_drag_start?: (file: FileInfo, event: DragEvent) => void;
|
package/dist/bands/Bands.svelte
CHANGED
|
@@ -1,55 +1,49 @@
|
|
|
1
1
|
<script lang="ts">import * as helpers from './helpers';
|
|
2
2
|
import { plot_colors } from '../colors';
|
|
3
3
|
import ScatterPlot from '../plot/ScatterPlot.svelte';
|
|
4
|
-
|
|
4
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
5
|
+
let { band_structs, line_kwargs = {}, path_mode = `strict`, band_type = undefined, show_legend = true, x_axis = {}, y_axis = {}, x_positions = $bindable(undefined), reference_frequency = null, ...rest } = $props();
|
|
5
6
|
// Helper function to get line styling for a band
|
|
6
7
|
function get_line_style(color, is_acoustic, mode_type, frequencies, band_idx) {
|
|
7
|
-
|
|
8
|
-
let stroke_width = is_acoustic ? 1.5 : 1;
|
|
8
|
+
const defaults = { stroke: color, stroke_width: is_acoustic ? 1.5 : 1 };
|
|
9
9
|
if (typeof line_kwargs === `function`) {
|
|
10
10
|
const custom = line_kwargs(frequencies, band_idx);
|
|
11
11
|
return {
|
|
12
|
-
stroke: custom.stroke ?? stroke,
|
|
13
|
-
stroke_width: custom.stroke_width ?? stroke_width,
|
|
12
|
+
stroke: custom.stroke ?? defaults.stroke,
|
|
13
|
+
stroke_width: custom.stroke_width ?? defaults.stroke_width,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
if (typeof line_kwargs === `object` && line_kwargs !== null) {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
stroke_width = mode_kwargs.stroke_width ?? stroke_width;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
// Global styling for all bands
|
|
28
|
-
stroke = lk.stroke ?? stroke;
|
|
29
|
-
stroke_width = lk.stroke_width ?? stroke_width;
|
|
30
|
-
}
|
|
17
|
+
const mode_kwargs = line_kwargs[mode_type];
|
|
18
|
+
const source = (mode_kwargs ?? line_kwargs);
|
|
19
|
+
return {
|
|
20
|
+
stroke: source.stroke ?? defaults.stroke,
|
|
21
|
+
stroke_width: source.stroke_width ?? defaults.stroke_width,
|
|
22
|
+
};
|
|
31
23
|
}
|
|
32
|
-
return
|
|
24
|
+
return defaults;
|
|
33
25
|
}
|
|
34
26
|
// Normalize input to dict format
|
|
35
27
|
let band_structs_dict = $derived.by(() => {
|
|
36
28
|
if (!band_structs)
|
|
37
29
|
return {};
|
|
38
|
-
const
|
|
39
|
-
if (is_single_struct) {
|
|
40
|
-
const normalized = helpers.normalize_band_structure(band_structs);
|
|
41
|
-
return normalized ? { default: normalized } : {};
|
|
42
|
-
}
|
|
43
|
-
// Normalize each structure in the dict
|
|
30
|
+
const is_single = `qpoints` in band_structs && `branches` in band_structs;
|
|
44
31
|
const result = {};
|
|
45
|
-
|
|
46
|
-
const normalized = helpers.normalize_band_structure(
|
|
32
|
+
if (is_single) {
|
|
33
|
+
const normalized = helpers.normalize_band_structure(band_structs);
|
|
47
34
|
if (normalized)
|
|
48
|
-
result
|
|
35
|
+
result.default = normalized;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
for (const [key, bs] of Object.entries(band_structs)) {
|
|
39
|
+
const normalized = helpers.normalize_band_structure(bs);
|
|
40
|
+
if (normalized)
|
|
41
|
+
result[key] = normalized;
|
|
42
|
+
}
|
|
49
43
|
}
|
|
50
44
|
return result;
|
|
51
45
|
});
|
|
52
|
-
let detected_band_type = $derived
|
|
46
|
+
let detected_band_type = $derived(band_type ?? `phonon`);
|
|
53
47
|
// Determine which segments to plot based on path_mode
|
|
54
48
|
let segments_to_plot = $derived.by(() => {
|
|
55
49
|
const all_segments = {};
|
|
@@ -79,13 +73,14 @@ let segments_to_plot = $derived.by(() => {
|
|
|
79
73
|
return new Set(Object.keys(all_segments));
|
|
80
74
|
});
|
|
81
75
|
// Map segments to x-axis positions
|
|
82
|
-
|
|
76
|
+
$effect(() => {
|
|
83
77
|
const positions = {};
|
|
84
78
|
let current_x = 0;
|
|
85
79
|
// Preserve physical path order using the first available structure
|
|
86
80
|
const canonical = Object.values(band_structs_dict)[0];
|
|
87
81
|
const ordered_segments = helpers.get_ordered_segments(canonical, segments_to_plot);
|
|
88
|
-
for (
|
|
82
|
+
for (let seg_idx = 0; seg_idx < ordered_segments.length; seg_idx++) {
|
|
83
|
+
const segment_key = ordered_segments[seg_idx];
|
|
89
84
|
if (positions[segment_key])
|
|
90
85
|
continue;
|
|
91
86
|
const [start_label, end_label] = segment_key.split(`_`);
|
|
@@ -97,15 +92,23 @@ let x_positions = $derived.by(() => {
|
|
|
97
92
|
return branch_start === start_label && branch_end === end_label;
|
|
98
93
|
});
|
|
99
94
|
if (matching_branch) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
// Check if this is a discontinuity: consecutive indices mean no path between points
|
|
96
|
+
const is_discontinuity = matching_branch.end_index - matching_branch.start_index === 1;
|
|
97
|
+
if (is_discontinuity) {
|
|
98
|
+
// Place at same x position as current, no advancement
|
|
99
|
+
positions[segment_key] = [current_x, current_x];
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const segment_len = bs.distance[matching_branch.end_index] -
|
|
103
|
+
bs.distance[matching_branch.start_index];
|
|
104
|
+
positions[segment_key] = [current_x, current_x + segment_len];
|
|
105
|
+
current_x += segment_len;
|
|
106
|
+
}
|
|
104
107
|
break;
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
|
-
|
|
111
|
+
x_positions = positions;
|
|
109
112
|
});
|
|
110
113
|
// Convert band structures to scatter plot series
|
|
111
114
|
let series_data = $derived.by(() => {
|
|
@@ -124,14 +127,18 @@ let series_data = $derived.by(() => {
|
|
|
124
127
|
const segment_key = helpers.get_segment_key(start_label, end_label);
|
|
125
128
|
if (!segments_to_plot.has(segment_key))
|
|
126
129
|
continue;
|
|
127
|
-
|
|
130
|
+
// Skip discontinuous segments (consecutive labeled points)
|
|
131
|
+
const is_discontinuity = branch.end_index - branch.start_index === 1;
|
|
132
|
+
if (is_discontinuity)
|
|
133
|
+
continue;
|
|
134
|
+
const [x_start, x_end] = x_positions?.[segment_key] || [0, 1];
|
|
128
135
|
// Scale distances for this segment
|
|
129
136
|
const segment_distances = bs.distance.slice(start_idx, end_idx);
|
|
130
137
|
const dist_min = segment_distances[0];
|
|
131
138
|
const dist_range = segment_distances[segment_distances.length - 1] - dist_min;
|
|
132
139
|
const scaled_distances = dist_range === 0
|
|
133
140
|
? segment_distances.map(() => (x_start + x_end) / 2)
|
|
134
|
-
: segment_distances.map((
|
|
141
|
+
: segment_distances.map((dist) => x_start + ((dist - dist_min) / dist_range) * (x_end - x_start));
|
|
135
142
|
// Create series for each band
|
|
136
143
|
for (let band_idx = 0; band_idx < bs.nb_bands; band_idx++) {
|
|
137
144
|
const frequencies = bs.bands[band_idx].slice(start_idx, end_idx);
|
|
@@ -145,6 +152,7 @@ let series_data = $derived.by(() => {
|
|
|
145
152
|
markers: `line`,
|
|
146
153
|
label: structure_label,
|
|
147
154
|
line_style,
|
|
155
|
+
metadata: { band_idx },
|
|
148
156
|
});
|
|
149
157
|
}
|
|
150
158
|
}
|
|
@@ -153,31 +161,62 @@ let series_data = $derived.by(() => {
|
|
|
153
161
|
});
|
|
154
162
|
// Get x-axis tick positions with custom labels for symmetry points
|
|
155
163
|
let x_axis_ticks = $derived.by(() => {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
? helpers.pretty_sym_point(start_label)
|
|
164
|
-
: ``;
|
|
165
|
-
if (pretty_start)
|
|
166
|
-
tick_labels[x_start] = pretty_start;
|
|
167
|
-
}
|
|
168
|
-
// Add end label
|
|
169
|
-
const pretty_end = end_label !== `null`
|
|
170
|
-
? helpers.pretty_sym_point(end_label)
|
|
164
|
+
const tick_map = new SvelteMap();
|
|
165
|
+
Object.entries(x_positions ?? {})
|
|
166
|
+
.sort(([, [a]], [, [b]]) => a - b)
|
|
167
|
+
.forEach(([segment_key, [x_start, x_end]]) => {
|
|
168
|
+
const [start_lbl, end_lbl] = segment_key.split(`_`);
|
|
169
|
+
const pretty_start = start_lbl !== `null`
|
|
170
|
+
? helpers.pretty_sym_point(start_lbl)
|
|
171
171
|
: ``;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
const pretty_end = end_lbl !== `null` ? helpers.pretty_sym_point(end_lbl) : ``;
|
|
173
|
+
// Check if this is a discontinuity (zero-length segment)
|
|
174
|
+
const is_discontinuity = Math.abs(x_end - x_start) < 1e-6;
|
|
175
|
+
if (is_discontinuity && pretty_start && pretty_end) {
|
|
176
|
+
// Combine labels at discontinuity points
|
|
177
|
+
if (!tick_map.has(x_start))
|
|
178
|
+
tick_map.set(x_start, []);
|
|
179
|
+
const labels = tick_map.get(x_start);
|
|
180
|
+
if (!labels.includes(pretty_start))
|
|
181
|
+
labels.push(pretty_start);
|
|
182
|
+
if (!labels.includes(pretty_end))
|
|
183
|
+
labels.push(pretty_end);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// Normal segment with distinct start/end
|
|
187
|
+
if (pretty_start) {
|
|
188
|
+
if (!tick_map.has(x_start))
|
|
189
|
+
tick_map.set(x_start, []);
|
|
190
|
+
const labels = tick_map.get(x_start);
|
|
191
|
+
if (!labels.includes(pretty_start))
|
|
192
|
+
labels.push(pretty_start);
|
|
193
|
+
}
|
|
194
|
+
if (pretty_end) {
|
|
195
|
+
if (!tick_map.has(x_end))
|
|
196
|
+
tick_map.set(x_end, []);
|
|
197
|
+
const labels = tick_map.get(x_end);
|
|
198
|
+
if (!labels.includes(pretty_end))
|
|
199
|
+
labels.push(pretty_end);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
// Merge labels at same position with pipe separator
|
|
204
|
+
return Object.fromEntries(Array.from(tick_map.entries()).map(([pos, labels]) => [
|
|
205
|
+
pos,
|
|
206
|
+
labels.join(` | `),
|
|
207
|
+
]));
|
|
176
208
|
});
|
|
177
209
|
let x_range = $derived.by(() => {
|
|
178
|
-
const
|
|
179
|
-
return [
|
|
210
|
+
const flat = Object.values(x_positions ?? {}).flat();
|
|
211
|
+
return [flat[0] ?? 0, flat.at(-1) ?? 1];
|
|
212
|
+
});
|
|
213
|
+
let final_y_axis = $derived({
|
|
214
|
+
label: detected_band_type === `phonon` ? `Frequency (THz)` : `Energy (eV)`,
|
|
215
|
+
format: `.2f`,
|
|
216
|
+
label_shift: { y: 15 },
|
|
217
|
+
...y_axis,
|
|
180
218
|
});
|
|
219
|
+
let display = $state({ x_grid: false, y_grid: true, y_zero_line: true });
|
|
181
220
|
</script>
|
|
182
221
|
|
|
183
222
|
<ScatterPlot
|
|
@@ -186,22 +225,35 @@ let x_range = $derived.by(() => {
|
|
|
186
225
|
label: `Wave Vector`,
|
|
187
226
|
ticks: Object.keys(x_axis_ticks).length > 0 ? x_axis_ticks : undefined,
|
|
188
227
|
format: ``,
|
|
189
|
-
range: x_range,
|
|
228
|
+
range: x_range,
|
|
190
229
|
...x_axis,
|
|
191
230
|
}}
|
|
192
|
-
y_axis={
|
|
193
|
-
|
|
194
|
-
format: `.2f`,
|
|
195
|
-
...y_axis,
|
|
196
|
-
}}
|
|
197
|
-
display={{ x_grid: false, y_grid: true, y_zero_line: true }}
|
|
231
|
+
y_axis={final_y_axis}
|
|
232
|
+
bind:display
|
|
198
233
|
legend={show_legend && Object.keys(band_structs_dict).length > 1 ? {} : null}
|
|
234
|
+
hover_config={{ threshold_px: 50 }}
|
|
199
235
|
{...rest}
|
|
200
236
|
>
|
|
201
|
-
{#snippet
|
|
202
|
-
|
|
203
|
-
{@const
|
|
204
|
-
|
|
237
|
+
{#snippet tooltip({ x, y_formatted, label, metadata })}
|
|
238
|
+
{@const y_label_full = final_y_axis.label ?? ``}
|
|
239
|
+
{@const [, y_label, y_unit] = y_label_full.match(/^(.+?)\s*\(([^)]+)\)$/) ??
|
|
240
|
+
[, y_label_full, ``]}
|
|
241
|
+
{@const segment = Object.entries(x_positions ?? {}).find(([, [start, end]]) =>
|
|
242
|
+
x >= start && x <= end
|
|
243
|
+
)}
|
|
244
|
+
{@const path = segment?.[0].split(`_`).map((lbl) =>
|
|
245
|
+
lbl !== `null` ? helpers.pretty_sym_point(lbl) : ``
|
|
246
|
+
).filter(Boolean).join(` → `) || null}
|
|
247
|
+
{@const band_idx = metadata?.band_idx}
|
|
248
|
+
{@const num_structs = Object.keys(band_structs_dict).length}
|
|
249
|
+
{#if num_structs > 1 && label}<strong>{label}</strong><br />{/if}
|
|
250
|
+
{y_label || `Value`}: {y_formatted}{y_unit ? ` ${y_unit}` : ``}<br />
|
|
251
|
+
{#if path}Path: {path}<br />{/if}
|
|
252
|
+
{#if typeof band_idx === `number`}Band: {band_idx + 1}{/if}
|
|
253
|
+
{/snippet}
|
|
254
|
+
|
|
255
|
+
{#snippet user_content({ height, x_scale_fn, y_scale_fn, pad })}
|
|
256
|
+
{#each Object.keys(x_axis_ticks).map(Number) as x_pos (x_pos)}
|
|
205
257
|
<line
|
|
206
258
|
x1={x_scale_fn(x_pos)}
|
|
207
259
|
x2={x_scale_fn(x_pos)}
|
|
@@ -212,5 +264,19 @@ let x_range = $derived.by(() => {
|
|
|
212
264
|
opacity="var(--bands-symmetry-line-opacity, 0.5)"
|
|
213
265
|
/>
|
|
214
266
|
{/each}
|
|
267
|
+
{#if reference_frequency !== null}
|
|
268
|
+
{@const y_pos = y_scale_fn(reference_frequency)}
|
|
269
|
+
{@const x_end = x_scale_fn(Object.values(x_positions ?? {}).flat().at(-1) ?? 1)}
|
|
270
|
+
<line
|
|
271
|
+
x1={pad.l}
|
|
272
|
+
x2={x_end}
|
|
273
|
+
y1={y_pos}
|
|
274
|
+
y2={y_pos}
|
|
275
|
+
stroke="var(--bands-reference-line-color, light-dark(#d48860, #c47850))"
|
|
276
|
+
stroke-width="var(--bands-reference-line-width, 1)"
|
|
277
|
+
stroke-dasharray="var(--bands-reference-line-dash, 4,3)"
|
|
278
|
+
opacity="var(--bands-reference-line-opacity, 0.5)"
|
|
279
|
+
/>
|
|
280
|
+
{/if}
|
|
215
281
|
{/snippet}
|
|
216
282
|
</ScatterPlot>
|
|
@@ -10,7 +10,9 @@ type $$ComponentProps = ComponentProps<typeof ScatterPlot> & {
|
|
|
10
10
|
path_mode?: PathMode;
|
|
11
11
|
band_type?: BandStructureType;
|
|
12
12
|
show_legend?: boolean;
|
|
13
|
+
x_positions?: Record<string, [number, number]>;
|
|
14
|
+
reference_frequency?: number | null;
|
|
13
15
|
};
|
|
14
|
-
declare const Bands: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
16
|
+
declare const Bands: import("svelte").Component<$$ComponentProps, {}, "x_positions">;
|
|
15
17
|
type Bands = ReturnType<typeof Bands>;
|
|
16
18
|
export default Bands;
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
<script lang="ts">import Bands from './Bands.svelte';
|
|
2
2
|
import Dos from './Dos.svelte';
|
|
3
|
-
let { band_structs, doses, bands_props = {}, dos_props = {}, shared_y_axis = true, ...rest } = $props();
|
|
3
|
+
let { band_structs, doses, bands_props = {}, dos_props = {}, shared_y_axis = true, children, ...rest } = $props();
|
|
4
4
|
// Shared y-axis configuration - use single object when shared_y_axis is true
|
|
5
5
|
let shared_y_axis_obj = $state({});
|
|
6
6
|
let bands_y_axis = $derived(shared_y_axis ? shared_y_axis_obj : {});
|
|
7
7
|
let dos_y_axis = $derived(shared_y_axis ? shared_y_axis_obj : {});
|
|
8
|
-
|
|
8
|
+
// Track hovered frequency from DOS to show reference line in Bands
|
|
9
|
+
let hovered_frequency = $state(null);
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
|
-
<div
|
|
12
|
+
<div
|
|
13
|
+
{...rest}
|
|
14
|
+
class="bands-and-dos {rest.class ?? ``}"
|
|
15
|
+
style={`display: grid; grid-template-columns: 1fr 200px; gap: 0;` + (rest.style ?? ``)}
|
|
16
|
+
>
|
|
17
|
+
{@render children?.({ hovered_frequency })}
|
|
12
18
|
<Bands
|
|
13
19
|
{band_structs}
|
|
14
20
|
y_axis={bands_y_axis}
|
|
21
|
+
reference_frequency={hovered_frequency}
|
|
15
22
|
{...bands_props}
|
|
16
23
|
padding={{ r: 15 }}
|
|
17
24
|
/>
|
|
@@ -20,6 +27,8 @@ let grid_style = $derived(`display: grid; grid-template-columns: 1fr 200px; gap:
|
|
|
20
27
|
{doses}
|
|
21
28
|
orientation="horizontal"
|
|
22
29
|
y_axis={{ ...dos_y_axis, label: `` }}
|
|
30
|
+
bind:hovered_frequency
|
|
31
|
+
reference_frequency={hovered_frequency}
|
|
23
32
|
padding={{ l: 15 }}
|
|
24
33
|
{...dos_props}
|
|
25
34
|
/>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ComponentProps } from 'svelte';
|
|
1
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import Bands from './Bands.svelte';
|
|
4
4
|
import Dos from './Dos.svelte';
|
|
5
|
-
import type { BaseBandStructure,
|
|
5
|
+
import type { BaseBandStructure, DosData, HoveredData } from './types';
|
|
6
6
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
7
7
|
band_structs: BaseBandStructure | Record<string, BaseBandStructure>;
|
|
8
8
|
doses: DosData | Record<string, DosData>;
|
|
@@ -10,6 +10,7 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
10
10
|
dos_props?: Partial<ComponentProps<typeof Dos>>;
|
|
11
11
|
shared_y_axis?: boolean;
|
|
12
12
|
class?: string;
|
|
13
|
+
children?: Snippet<[HoveredData]>;
|
|
13
14
|
};
|
|
14
15
|
declare const BandsAndDos: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
15
16
|
type BandsAndDos = ReturnType<typeof BandsAndDos>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts">import { BrillouinZone, reciprocal_lattice } from '../brillouin';
|
|
2
|
+
import Bands from './Bands.svelte';
|
|
3
|
+
import Dos from './Dos.svelte';
|
|
4
|
+
import * as helpers from './helpers';
|
|
5
|
+
let { structure, band_structs, doses, bands_props = {}, dos_props = {}, bz_props = {}, children, ...rest } = $props();
|
|
6
|
+
let first_band_struct = $derived(`qpoints` in band_structs
|
|
7
|
+
? band_structs
|
|
8
|
+
: band_structs[Object.keys(band_structs)[0]]);
|
|
9
|
+
// Convert fractional k-point coordinates to Cartesian reciprocal space
|
|
10
|
+
// using the structure's reciprocal lattice (consistent with BZ computation)
|
|
11
|
+
let k_path_points = $derived.by(() => {
|
|
12
|
+
if (!first_band_struct?.qpoints || !structure?.lattice?.matrix)
|
|
13
|
+
return [];
|
|
14
|
+
const k_lattice = reciprocal_lattice(structure.lattice.matrix);
|
|
15
|
+
return helpers.extract_k_path_points(first_band_struct, k_lattice);
|
|
16
|
+
});
|
|
17
|
+
let hovered_band_point = $state(null);
|
|
18
|
+
let bands_x_positions = $state({});
|
|
19
|
+
let hovered_qpoint_index = $derived(hovered_band_point && first_band_struct &&
|
|
20
|
+
Object.keys(bands_x_positions).length > 0
|
|
21
|
+
? helpers.find_qpoint_at_rescaled_x(first_band_struct, hovered_band_point.x, bands_x_positions)
|
|
22
|
+
: null);
|
|
23
|
+
let hovered_k_point = $derived(hovered_qpoint_index !== null
|
|
24
|
+
? k_path_points[hovered_qpoint_index]
|
|
25
|
+
: null);
|
|
26
|
+
const [desktop_width, tablet_width] = [1200, 600];
|
|
27
|
+
let clientWidth = $state(desktop_width);
|
|
28
|
+
let is_desktop = $derived(clientWidth >= desktop_width);
|
|
29
|
+
let is_mobile = $derived(clientWidth < tablet_width);
|
|
30
|
+
let screen_class = $derived(clientWidth >= desktop_width
|
|
31
|
+
? `desktop`
|
|
32
|
+
: clientWidth >= tablet_width
|
|
33
|
+
? `tablet`
|
|
34
|
+
: `phone`);
|
|
35
|
+
let y_axis_dos = $derived({
|
|
36
|
+
...(is_desktop ? { label: `` } : {}),
|
|
37
|
+
...dos_props.y_axis,
|
|
38
|
+
});
|
|
39
|
+
// Track hovered frequency from DOS to show reference line in Bands
|
|
40
|
+
let hovered_frequency = $state(null);
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div
|
|
44
|
+
{...rest}
|
|
45
|
+
class="bands-dos-brillouin {screen_class} {rest.class ?? ``}"
|
|
46
|
+
bind:clientWidth
|
|
47
|
+
>
|
|
48
|
+
{@render children?.({ hovered_frequency, hovered_band_point, hovered_qpoint_index })}
|
|
49
|
+
<Bands
|
|
50
|
+
style="grid-area: bands; min-width: 0; min-height: 0; overflow: hidden"
|
|
51
|
+
{band_structs}
|
|
52
|
+
padding={{ r: is_desktop ? 10 : 5, ...bands_props.padding }}
|
|
53
|
+
bind:x_positions={bands_x_positions}
|
|
54
|
+
reference_frequency={hovered_frequency}
|
|
55
|
+
on_point_hover={(event) => {
|
|
56
|
+
hovered_band_point = event?.point ?? null
|
|
57
|
+
bands_props.on_point_hover?.(event)
|
|
58
|
+
}}
|
|
59
|
+
{...bands_props}
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<BrillouinZone
|
|
63
|
+
style="grid-area: bz; min-width: 0; min-height: 0; overflow: hidden; height: 100%"
|
|
64
|
+
{structure}
|
|
65
|
+
{k_path_points}
|
|
66
|
+
k_path_labels={first_band_struct?.qpoints?.flatMap((q, idx) =>
|
|
67
|
+
k_path_points[idx]
|
|
68
|
+
? [{
|
|
69
|
+
position: k_path_points[idx],
|
|
70
|
+
label: q.label ? helpers.pretty_sym_point(q.label) : null,
|
|
71
|
+
}]
|
|
72
|
+
: []
|
|
73
|
+
) ?? []}
|
|
74
|
+
{hovered_k_point}
|
|
75
|
+
{hovered_qpoint_index}
|
|
76
|
+
{...bz_props}
|
|
77
|
+
/>
|
|
78
|
+
|
|
79
|
+
<Dos
|
|
80
|
+
style="grid-area: dos; min-width: 0; min-height: 0; overflow: hidden"
|
|
81
|
+
{doses}
|
|
82
|
+
orientation={is_desktop ? `horizontal` : `vertical`}
|
|
83
|
+
x_axis={{ ticks: 4 }}
|
|
84
|
+
y_axis={y_axis_dos}
|
|
85
|
+
bind:hovered_frequency
|
|
86
|
+
reference_frequency={hovered_frequency}
|
|
87
|
+
padding={{
|
|
88
|
+
l: is_desktop ? 20 : undefined,
|
|
89
|
+
r: is_mobile ? 0 : undefined,
|
|
90
|
+
...dos_props.padding,
|
|
91
|
+
}}
|
|
92
|
+
{...dos_props}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<style>
|
|
97
|
+
.bands-dos-brillouin {
|
|
98
|
+
width: var(--bz-bands-dos-width, 100%);
|
|
99
|
+
height: var(--bz-bands-dos-height, 600px);
|
|
100
|
+
min-height: var(--bz-bands-dos-min-height, 400px);
|
|
101
|
+
display: grid;
|
|
102
|
+
gap: var(--bz-bands-dos-gap, 1em);
|
|
103
|
+
}
|
|
104
|
+
.bands-dos-brillouin.desktop {
|
|
105
|
+
/* layout: BZ | bands | DOS side by side */
|
|
106
|
+
grid-template-columns: 30% 55% 15%;
|
|
107
|
+
grid-template-areas: 'bz bands dos';
|
|
108
|
+
}
|
|
109
|
+
.bands-dos-brillouin.tablet {
|
|
110
|
+
/* layout: bands on top, BZ and DOS below */
|
|
111
|
+
grid-template-columns: 40% 60%;
|
|
112
|
+
grid-template-rows: 50% 50%;
|
|
113
|
+
grid-template-areas:
|
|
114
|
+
'bands bands'
|
|
115
|
+
'bz dos';
|
|
116
|
+
}
|
|
117
|
+
.bands-dos-brillouin.phone {
|
|
118
|
+
/* layout: all stacked vertically */
|
|
119
|
+
grid-template-columns: 1fr;
|
|
120
|
+
grid-template-areas: 'bands' 'dos' 'bz';
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BrillouinZone } from '../brillouin';
|
|
2
|
+
import type { PymatgenStructure } from '../structure';
|
|
3
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
import Bands from './Bands.svelte';
|
|
6
|
+
import Dos from './Dos.svelte';
|
|
7
|
+
import type { BaseBandStructure, DosData, HoveredData } from './types';
|
|
8
|
+
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
9
|
+
structure: PymatgenStructure;
|
|
10
|
+
band_structs: BaseBandStructure | Record<string, BaseBandStructure>;
|
|
11
|
+
doses: DosData | Record<string, DosData>;
|
|
12
|
+
bands_props?: Partial<ComponentProps<typeof Bands>>;
|
|
13
|
+
dos_props?: Partial<ComponentProps<typeof Dos>>;
|
|
14
|
+
bz_props?: Partial<ComponentProps<typeof BrillouinZone>>;
|
|
15
|
+
children?: Snippet<[HoveredData]>;
|
|
16
|
+
};
|
|
17
|
+
declare const BrillouinBandsDos: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
18
|
+
type BrillouinBandsDos = ReturnType<typeof BrillouinBandsDos>;
|
|
19
|
+
export default BrillouinBandsDos;
|