matterviz 0.1.0
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/BohrAtom.svelte +105 -0
- package/dist/BohrAtom.svelte.d.ts +21 -0
- package/dist/ControlPanel.svelte +158 -0
- package/dist/ControlPanel.svelte.d.ts +18 -0
- package/dist/Icon.svelte +23 -0
- package/dist/Icon.svelte.d.ts +8 -0
- package/dist/InfoCard.svelte +79 -0
- package/dist/InfoCard.svelte.d.ts +23 -0
- package/dist/Nucleus.svelte +64 -0
- package/dist/Nucleus.svelte.d.ts +16 -0
- package/dist/Spinner.svelte +44 -0
- package/dist/Spinner.svelte.d.ts +7 -0
- package/dist/api.d.ts +6 -0
- package/dist/api.js +30 -0
- package/dist/colors/alloy-colors.json +111 -0
- package/dist/colors/dark-mode-colors.json +111 -0
- package/dist/colors/index.d.ts +26 -0
- package/dist/colors/index.js +72 -0
- package/dist/colors/jmol-colors.json +111 -0
- package/dist/colors/muted-colors.json +111 -0
- package/dist/colors/pastel-colors.json +111 -0
- package/dist/colors/vesta-colors.json +111 -0
- package/dist/composition/BarChart.svelte +260 -0
- package/dist/composition/BarChart.svelte.d.ts +33 -0
- package/dist/composition/BubbleChart.svelte +166 -0
- package/dist/composition/BubbleChart.svelte.d.ts +30 -0
- package/dist/composition/Composition.svelte +73 -0
- package/dist/composition/Composition.svelte.d.ts +27 -0
- package/dist/composition/PieChart.svelte +236 -0
- package/dist/composition/PieChart.svelte.d.ts +36 -0
- package/dist/composition/index.d.ts +5 -0
- package/dist/composition/index.js +5 -0
- package/dist/composition/parse.d.ts +14 -0
- package/dist/composition/parse.js +307 -0
- package/dist/element/ElementHeading.svelte +21 -0
- package/dist/element/ElementHeading.svelte.d.ts +8 -0
- package/dist/element/ElementPhoto.svelte +56 -0
- package/dist/element/ElementPhoto.svelte.d.ts +9 -0
- package/dist/element/ElementStats.svelte +73 -0
- package/dist/element/ElementStats.svelte.d.ts +8 -0
- package/dist/element/ElementTile.svelte +449 -0
- package/dist/element/ElementTile.svelte.d.ts +25 -0
- package/dist/element/data.d.ts +4958 -0
- package/dist/element/data.js +5628 -0
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +4 -0
- package/dist/icons.d.ts +435 -0
- package/dist/icons.js +435 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +43 -0
- package/dist/io/decompress.d.ts +16 -0
- package/dist/io/decompress.js +78 -0
- package/dist/io/export.d.ts +9 -0
- package/dist/io/export.js +205 -0
- package/dist/io/parse.d.ts +53 -0
- package/dist/io/parse.js +747 -0
- package/dist/labels.d.ts +31 -0
- package/dist/labels.js +209 -0
- package/dist/material/MaterialCard.svelte +135 -0
- package/dist/material/MaterialCard.svelte.d.ts +10 -0
- package/dist/material/SymmetryCard.svelte +23 -0
- package/dist/material/SymmetryCard.svelte.d.ts +9 -0
- package/dist/material/index.d.ts +2 -0
- package/dist/material/index.js +2 -0
- package/dist/math.d.ts +24 -0
- package/dist/math.js +216 -0
- package/dist/periodic-table/PeriodicTable.svelte +284 -0
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +50 -0
- package/dist/periodic-table/PropertySelect.svelte +20 -0
- package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
- package/dist/periodic-table/TableInset.svelte +18 -0
- package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
- package/dist/periodic-table/index.d.ts +9 -0
- package/dist/periodic-table/index.js +3 -0
- package/dist/plot/ColorBar.svelte +414 -0
- package/dist/plot/ColorBar.svelte.d.ts +22 -0
- package/dist/plot/ColorScaleSelect.svelte +31 -0
- package/dist/plot/ColorScaleSelect.svelte.d.ts +15 -0
- package/dist/plot/ElementScatter.svelte +38 -0
- package/dist/plot/ElementScatter.svelte.d.ts +14 -0
- package/dist/plot/Line.svelte +42 -0
- package/dist/plot/Line.svelte.d.ts +15 -0
- package/dist/plot/PlotLegend.svelte +206 -0
- package/dist/plot/PlotLegend.svelte.d.ts +18 -0
- package/dist/plot/ScatterPlot.svelte +1753 -0
- package/dist/plot/ScatterPlot.svelte.d.ts +114 -0
- package/dist/plot/ScatterPlotControls.svelte +505 -0
- package/dist/plot/ScatterPlotControls.svelte.d.ts +33 -0
- package/dist/plot/ScatterPoint.svelte +72 -0
- package/dist/plot/ScatterPoint.svelte.d.ts +17 -0
- package/dist/plot/index.d.ts +168 -0
- package/dist/plot/index.js +46 -0
- package/dist/state.svelte.d.ts +12 -0
- package/dist/state.svelte.js +11 -0
- package/dist/structure/Bond.svelte +68 -0
- package/dist/structure/Bond.svelte.d.ts +13 -0
- package/dist/structure/Lattice.svelte +115 -0
- package/dist/structure/Lattice.svelte.d.ts +15 -0
- package/dist/structure/Structure.svelte +298 -0
- package/dist/structure/Structure.svelte.d.ts +28 -0
- package/dist/structure/StructureCard.svelte +26 -0
- package/dist/structure/StructureCard.svelte.d.ts +9 -0
- package/dist/structure/StructureControls.svelte +383 -0
- package/dist/structure/StructureControls.svelte.d.ts +23 -0
- package/dist/structure/StructureLegend.svelte +130 -0
- package/dist/structure/StructureLegend.svelte.d.ts +17 -0
- package/dist/structure/StructureScene.svelte +331 -0
- package/dist/structure/StructureScene.svelte.d.ts +47 -0
- package/dist/structure/bonding.d.ts +16 -0
- package/dist/structure/bonding.js +150 -0
- package/dist/structure/index.d.ts +98 -0
- package/dist/structure/index.js +114 -0
- package/dist/structure/pbc.d.ts +6 -0
- package/dist/structure/pbc.js +72 -0
- package/dist/trajectory/Sidebar.svelte +412 -0
- package/dist/trajectory/Sidebar.svelte.d.ts +14 -0
- package/dist/trajectory/Trajectory.svelte +1084 -0
- package/dist/trajectory/Trajectory.svelte.d.ts +49 -0
- package/dist/trajectory/TrajectoryError.svelte +120 -0
- package/dist/trajectory/TrajectoryError.svelte.d.ts +12 -0
- package/dist/trajectory/extract.d.ts +5 -0
- package/dist/trajectory/extract.js +157 -0
- package/dist/trajectory/index.d.ts +16 -0
- package/dist/trajectory/index.js +49 -0
- package/dist/trajectory/parse.d.ts +13 -0
- package/dist/trajectory/parse.js +1093 -0
- package/dist/trajectory/plotting.d.ts +12 -0
- package/dist/trajectory/plotting.js +148 -0
- package/license +21 -0
- package/package.json +131 -0
- package/readme.md +95 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Spinner, Structure } from '..';
|
|
2
|
+
import { ScatterPlot } from '../plot';
|
|
3
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
4
|
+
import type { Trajectory, TrajectoryDataExtractor } from './index';
|
|
5
|
+
interface Props {
|
|
6
|
+
trajectory?: Trajectory | undefined;
|
|
7
|
+
trajectory_url?: string;
|
|
8
|
+
current_step_idx?: number;
|
|
9
|
+
data_extractor?: TrajectoryDataExtractor;
|
|
10
|
+
allow_file_drop?: boolean;
|
|
11
|
+
on_file_drop?: (content: string, filename: string) => Promise<void> | void;
|
|
12
|
+
layout?: `horizontal` | `vertical`;
|
|
13
|
+
structure_props?: ComponentProps<typeof Structure>;
|
|
14
|
+
plot_props?: ComponentProps<typeof ScatterPlot>;
|
|
15
|
+
spinner_props?: ComponentProps<typeof Spinner>;
|
|
16
|
+
trajectory_controls?: Snippet<[
|
|
17
|
+
{
|
|
18
|
+
trajectory: Trajectory;
|
|
19
|
+
current_step_idx: number;
|
|
20
|
+
total_frames: number;
|
|
21
|
+
on_step_change: (idx: number) => void;
|
|
22
|
+
}
|
|
23
|
+
]>;
|
|
24
|
+
error_snippet?: Snippet<[{
|
|
25
|
+
error_message: string;
|
|
26
|
+
on_dismiss: () => void;
|
|
27
|
+
}]>;
|
|
28
|
+
show_controls?: boolean;
|
|
29
|
+
show_fullscreen_button?: boolean;
|
|
30
|
+
display_mode?: `both` | `structure` | `plot`;
|
|
31
|
+
step_labels?: number | number[] | undefined;
|
|
32
|
+
property_labels?: Record<string, string>;
|
|
33
|
+
units?: {
|
|
34
|
+
energy?: string;
|
|
35
|
+
energy_per_atom?: string;
|
|
36
|
+
force_max?: string;
|
|
37
|
+
force_norm?: string;
|
|
38
|
+
stress_max?: string;
|
|
39
|
+
volume?: string;
|
|
40
|
+
density?: string;
|
|
41
|
+
temperature?: string;
|
|
42
|
+
pressure?: string;
|
|
43
|
+
length?: string;
|
|
44
|
+
[key: string]: string | undefined;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
declare const Trajectory: import("svelte").Component<Props, {}, "trajectory" | "current_step_idx" | "display_mode">;
|
|
48
|
+
type Trajectory = ReturnType<typeof Trajectory>;
|
|
49
|
+
export default Trajectory;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<script lang="ts">let { error_message, on_dismiss, error_snippet } = $props();
|
|
2
|
+
export {};
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<div class="error-message">
|
|
6
|
+
{#if error_snippet}
|
|
7
|
+
{@render error_snippet({ error_message, on_dismiss })}
|
|
8
|
+
{:else if error_message.includes(`<div class="unsupported-format">`)}
|
|
9
|
+
<!-- Render HTML content for unsupported format messages -->
|
|
10
|
+
{@html error_message}
|
|
11
|
+
<button onclick={on_dismiss}>Dismiss</button>
|
|
12
|
+
{:else}
|
|
13
|
+
<h3>Error</h3>
|
|
14
|
+
<p>{error_message}</p>
|
|
15
|
+
<button onclick={on_dismiss}>Dismiss</button>
|
|
16
|
+
{/if}
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.error-message {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
height: 100%;
|
|
26
|
+
padding: 2rem;
|
|
27
|
+
text-align: center;
|
|
28
|
+
background: var(--trajectory-error-bg, #fff);
|
|
29
|
+
color: var(--trajectory-error-color, #d73a49);
|
|
30
|
+
border-radius: 8px;
|
|
31
|
+
border: 1px solid var(--trajectory-error-border, #f97583);
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
}
|
|
34
|
+
.error-message button {
|
|
35
|
+
margin-top: 1rem;
|
|
36
|
+
background: var(--trajectory-error-button-bg, #d73a49);
|
|
37
|
+
color: white;
|
|
38
|
+
border: none;
|
|
39
|
+
border-radius: 4px;
|
|
40
|
+
padding: 0.5rem 1rem;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
font-size: 0.9rem;
|
|
43
|
+
transition: background-color 0.2s;
|
|
44
|
+
}
|
|
45
|
+
.error-message button:hover {
|
|
46
|
+
background: var(--trajectory-error-button-hover-bg, #cb2431);
|
|
47
|
+
}
|
|
48
|
+
/* Styles for unsupported format messages */
|
|
49
|
+
.error-message :global(.unsupported-format) {
|
|
50
|
+
text-align: left;
|
|
51
|
+
max-width: 90%;
|
|
52
|
+
max-height: 70vh;
|
|
53
|
+
margin: 0 auto;
|
|
54
|
+
overflow-y: auto;
|
|
55
|
+
overflow-x: hidden;
|
|
56
|
+
}
|
|
57
|
+
.error-message :global(.unsupported-format h4) {
|
|
58
|
+
color: var(--trajectory-error-color, #d73a49);
|
|
59
|
+
margin: 0 0 1rem 0;
|
|
60
|
+
font-size: 1.1rem;
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: 0.5rem;
|
|
64
|
+
}
|
|
65
|
+
.error-message :global(.unsupported-format h5) {
|
|
66
|
+
color: var(--trajectory-text-color, #24292e);
|
|
67
|
+
margin: 0.75rem 0 0.25rem 0;
|
|
68
|
+
font-size: 0.9rem;
|
|
69
|
+
font-weight: 600;
|
|
70
|
+
}
|
|
71
|
+
.error-message :global(.unsupported-format p) {
|
|
72
|
+
color: var(--trajectory-text-color, #24292e);
|
|
73
|
+
margin: 0.25rem 0;
|
|
74
|
+
text-align: left;
|
|
75
|
+
font-size: 0.85rem;
|
|
76
|
+
}
|
|
77
|
+
.error-message :global(.unsupported-format ul) {
|
|
78
|
+
text-align: left;
|
|
79
|
+
margin: 0.5rem 0;
|
|
80
|
+
padding-left: 1.5rem;
|
|
81
|
+
}
|
|
82
|
+
.error-message :global(.unsupported-format li) {
|
|
83
|
+
color: var(--trajectory-text-color, #24292e);
|
|
84
|
+
margin: 0.25rem 0;
|
|
85
|
+
}
|
|
86
|
+
.error-message :global(.unsupported-format .code-options) {
|
|
87
|
+
margin: 1rem 0 0 0;
|
|
88
|
+
display: grid;
|
|
89
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
90
|
+
gap: 1.5rem;
|
|
91
|
+
}
|
|
92
|
+
.error-message :global(.unsupported-format .code-options > div) {
|
|
93
|
+
margin: 0;
|
|
94
|
+
}
|
|
95
|
+
.error-message :global(.unsupported-format .code-options strong) {
|
|
96
|
+
color: var(--trajectory-code-title-color, #0366d6);
|
|
97
|
+
display: block;
|
|
98
|
+
margin-bottom: 0.25rem;
|
|
99
|
+
font-size: 0.85rem;
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
}
|
|
102
|
+
.error-message :global(.unsupported-format pre) {
|
|
103
|
+
background: var(--trajectory-pre-bg, #f6f8fa);
|
|
104
|
+
padding: 0.5rem;
|
|
105
|
+
margin: 0;
|
|
106
|
+
overflow-x: auto;
|
|
107
|
+
font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;
|
|
108
|
+
font-size: 0.75rem;
|
|
109
|
+
line-height: 1.2;
|
|
110
|
+
max-height: 150px;
|
|
111
|
+
overflow-y: auto;
|
|
112
|
+
}
|
|
113
|
+
.error-message :global(.unsupported-format p code) {
|
|
114
|
+
background: var(--trajectory-inline-code-bg, rgba(175, 184, 193, 0.2));
|
|
115
|
+
padding: 0.2em 0.4em;
|
|
116
|
+
border-radius: 3px;
|
|
117
|
+
font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;
|
|
118
|
+
font-size: 0.85em;
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
error_message: string;
|
|
4
|
+
on_dismiss: () => void;
|
|
5
|
+
error_snippet?: Snippet<[{
|
|
6
|
+
error_message: string;
|
|
7
|
+
on_dismiss: () => void;
|
|
8
|
+
}]>;
|
|
9
|
+
}
|
|
10
|
+
declare const TrajectoryError: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type TrajectoryError = ReturnType<typeof TrajectoryError>;
|
|
12
|
+
export default TrajectoryError;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TrajectoryDataExtractor } from './index';
|
|
2
|
+
export declare const energy_data_extractor: TrajectoryDataExtractor;
|
|
3
|
+
export declare const force_stress_data_extractor: TrajectoryDataExtractor;
|
|
4
|
+
export declare const structural_data_extractor: TrajectoryDataExtractor;
|
|
5
|
+
export declare const full_data_extractor: TrajectoryDataExtractor;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Common data extractor that extracts energy and structural properties
|
|
2
|
+
export const energy_data_extractor = (frame, _trajectory) => {
|
|
3
|
+
const data = {
|
|
4
|
+
Step: frame.step,
|
|
5
|
+
};
|
|
6
|
+
if (frame.metadata) {
|
|
7
|
+
// Extract energy-related properties
|
|
8
|
+
const energy_fields = [
|
|
9
|
+
`energy`,
|
|
10
|
+
`energy_per_atom`,
|
|
11
|
+
`potential_energy`,
|
|
12
|
+
`kinetic_energy`,
|
|
13
|
+
`total_energy`,
|
|
14
|
+
];
|
|
15
|
+
for (const field of energy_fields) {
|
|
16
|
+
if (field in frame.metadata &&
|
|
17
|
+
typeof frame.metadata[field] === `number`) {
|
|
18
|
+
data[field] = frame.metadata[field];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
// Data extractor for forces and stresses
|
|
25
|
+
export const force_stress_data_extractor = (frame, _trajectory) => {
|
|
26
|
+
const data = {
|
|
27
|
+
Step: frame.step,
|
|
28
|
+
};
|
|
29
|
+
if (frame.metadata) {
|
|
30
|
+
// Calculate force properties from forces array if available (preferred)
|
|
31
|
+
if (frame.metadata.forces && Array.isArray(frame.metadata.forces)) {
|
|
32
|
+
const forces = frame.metadata.forces;
|
|
33
|
+
if (forces.length > 0) {
|
|
34
|
+
const force_magnitudes = forces.map((force) => Math.sqrt(force[0] ** 2 + force[1] ** 2 + force[2] ** 2));
|
|
35
|
+
data.force_max = Math.max(...force_magnitudes);
|
|
36
|
+
data.force_norm = Math.sqrt(force_magnitudes.reduce((sum, f) => sum + f ** 2, 0) /
|
|
37
|
+
force_magnitudes.length);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Fallback to metadata values if forces array not available
|
|
42
|
+
if (frame.metadata.force_max &&
|
|
43
|
+
typeof frame.metadata.force_max === `number`) {
|
|
44
|
+
data.force_max = frame.metadata.force_max;
|
|
45
|
+
}
|
|
46
|
+
// Prefer force_norm if available, fall back to force_rms
|
|
47
|
+
if (frame.metadata.force_norm &&
|
|
48
|
+
typeof frame.metadata.force_norm === `number`) {
|
|
49
|
+
data.force_norm = frame.metadata.force_norm;
|
|
50
|
+
}
|
|
51
|
+
else if (frame.metadata.force_rms &&
|
|
52
|
+
typeof frame.metadata.force_rms === `number`) {
|
|
53
|
+
data.force_norm = frame.metadata.force_rms; // Use force_rms as fallback
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Extract other stress and pressure properties (no duplicates expected)
|
|
57
|
+
const other_stress_fields = [
|
|
58
|
+
`stress_max`,
|
|
59
|
+
`stress_frobenius`,
|
|
60
|
+
`stress_trace`,
|
|
61
|
+
`pressure`,
|
|
62
|
+
];
|
|
63
|
+
for (const field of other_stress_fields) {
|
|
64
|
+
if (field in frame.metadata &&
|
|
65
|
+
typeof frame.metadata[field] === `number`) {
|
|
66
|
+
data[field] = frame.metadata[field];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return data;
|
|
71
|
+
};
|
|
72
|
+
// Data extractor for structural properties
|
|
73
|
+
export const structural_data_extractor = (frame, _trajectory) => {
|
|
74
|
+
const data = {
|
|
75
|
+
Step: frame.step,
|
|
76
|
+
};
|
|
77
|
+
// Extract lattice properties (preferred source for volume)
|
|
78
|
+
if (`lattice` in frame.structure) {
|
|
79
|
+
const lattice = frame.structure.lattice;
|
|
80
|
+
data.volume = lattice.volume; // Use consistent lowercase naming
|
|
81
|
+
data.a = lattice.a;
|
|
82
|
+
data.b = lattice.b;
|
|
83
|
+
data.c = lattice.c;
|
|
84
|
+
data.alpha = lattice.alpha;
|
|
85
|
+
data.beta = lattice.beta;
|
|
86
|
+
data.gamma = lattice.gamma;
|
|
87
|
+
}
|
|
88
|
+
if (frame.metadata) {
|
|
89
|
+
// Extract other structural properties, avoiding volume duplicate
|
|
90
|
+
const structural_fields = [`density`, `temperature`];
|
|
91
|
+
for (const field of structural_fields) {
|
|
92
|
+
if (field in frame.metadata &&
|
|
93
|
+
typeof frame.metadata[field] === `number`) {
|
|
94
|
+
data[field] = frame.metadata[field];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Only use metadata volume if lattice volume is not available
|
|
98
|
+
if (!data.volume &&
|
|
99
|
+
frame.metadata.volume &&
|
|
100
|
+
typeof frame.metadata.volume === `number`) {
|
|
101
|
+
data.volume = frame.metadata.volume;
|
|
102
|
+
}
|
|
103
|
+
// Note: pressure is handled by force_stress_data_extractor to avoid duplication
|
|
104
|
+
}
|
|
105
|
+
return data;
|
|
106
|
+
};
|
|
107
|
+
// Helper function to check if a property varies across trajectory frames
|
|
108
|
+
function property_varies(trajectory, property_key, tolerance = 1e-10) {
|
|
109
|
+
if (trajectory.frames.length <= 1)
|
|
110
|
+
return false;
|
|
111
|
+
const values = [];
|
|
112
|
+
for (const frame of trajectory.frames) {
|
|
113
|
+
// Check both direct structure properties and metadata
|
|
114
|
+
let value;
|
|
115
|
+
if (`lattice` in frame.structure) {
|
|
116
|
+
const lattice = frame.structure.lattice;
|
|
117
|
+
if (property_key in lattice &&
|
|
118
|
+
typeof lattice[property_key] === `number`) {
|
|
119
|
+
value = lattice[property_key];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (value === undefined &&
|
|
123
|
+
frame.metadata &&
|
|
124
|
+
property_key in frame.metadata) {
|
|
125
|
+
const metadata_value = frame.metadata[property_key];
|
|
126
|
+
if (typeof metadata_value === `number`) {
|
|
127
|
+
value = metadata_value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (value !== undefined) {
|
|
131
|
+
values.push(value);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (values.length <= 1)
|
|
135
|
+
return false;
|
|
136
|
+
const first_value = values[0];
|
|
137
|
+
return values.some((value) => Math.abs(value - first_value) > tolerance);
|
|
138
|
+
}
|
|
139
|
+
// Combined data extractor that extracts all common properties
|
|
140
|
+
export const full_data_extractor = (frame, trajectory) => {
|
|
141
|
+
const base_data = {
|
|
142
|
+
...energy_data_extractor(frame, trajectory),
|
|
143
|
+
...force_stress_data_extractor(frame, trajectory),
|
|
144
|
+
...structural_data_extractor(frame, trajectory),
|
|
145
|
+
};
|
|
146
|
+
// Check which lattice parameters vary
|
|
147
|
+
const lattice_params = [`a`, `b`, `c`, `alpha`, `beta`, `gamma`];
|
|
148
|
+
const result = { ...base_data };
|
|
149
|
+
// Add metadata to specify which properties don't vary
|
|
150
|
+
for (const param of lattice_params) {
|
|
151
|
+
if (!property_varies(trajectory, param)) {
|
|
152
|
+
// Mark individual lattice parameters as constant
|
|
153
|
+
result[`_constant_${param}`] = 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnyStructure } from '..';
|
|
2
|
+
export { default as Sidebar } from './Sidebar.svelte';
|
|
3
|
+
export { default as TrajectoryViewer } from './Trajectory.svelte';
|
|
4
|
+
export { default as TrajectoryError } from './TrajectoryError.svelte';
|
|
5
|
+
export type TrajectoryFrame = {
|
|
6
|
+
structure: AnyStructure;
|
|
7
|
+
step: number;
|
|
8
|
+
metadata?: Record<string, unknown>;
|
|
9
|
+
};
|
|
10
|
+
export type Trajectory = {
|
|
11
|
+
frames: TrajectoryFrame[];
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type TrajectoryDataExtractor = (frame: TrajectoryFrame, trajectory: Trajectory) => Record<string, number>;
|
|
15
|
+
export declare function validate_trajectory(trajectory: Trajectory): string[];
|
|
16
|
+
export declare function get_trajectory_stats(trajectory: Trajectory): Record<string, unknown>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export { default as Sidebar } from './Sidebar.svelte';
|
|
2
|
+
export { default as TrajectoryViewer } from './Trajectory.svelte';
|
|
3
|
+
export { default as TrajectoryError } from './TrajectoryError.svelte';
|
|
4
|
+
// Validate trajectory data
|
|
5
|
+
export function validate_trajectory(trajectory) {
|
|
6
|
+
const errors = [];
|
|
7
|
+
if (!trajectory.frames || trajectory.frames.length === 0) {
|
|
8
|
+
errors.push(`Trajectory must have at least one frame`);
|
|
9
|
+
}
|
|
10
|
+
for (let idx = 0; idx < trajectory.frames.length; idx++) {
|
|
11
|
+
const frame = trajectory.frames[idx];
|
|
12
|
+
if (!frame.structure) {
|
|
13
|
+
errors.push(`Frame ${idx} missing structure`);
|
|
14
|
+
}
|
|
15
|
+
else if (!frame.structure.sites || frame.structure.sites.length === 0) {
|
|
16
|
+
errors.push(`Frame ${idx} structure has no sites`);
|
|
17
|
+
}
|
|
18
|
+
if (typeof frame.step !== `number`) {
|
|
19
|
+
errors.push(`Frame ${idx} missing or invalid step number`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return errors;
|
|
23
|
+
}
|
|
24
|
+
// Get trajectory statistics
|
|
25
|
+
export function get_trajectory_stats(trajectory) {
|
|
26
|
+
const stats = {
|
|
27
|
+
frame_count: trajectory.frames.length,
|
|
28
|
+
steps: trajectory.frames.map((f) => f.step),
|
|
29
|
+
};
|
|
30
|
+
if (trajectory.frames.length > 0) {
|
|
31
|
+
const first_frame = trajectory.frames[0];
|
|
32
|
+
const last_frame = trajectory.frames[trajectory.frames.length - 1];
|
|
33
|
+
stats.step_range = [first_frame.step, last_frame.step];
|
|
34
|
+
// Check if all frames have the same number of atoms
|
|
35
|
+
const atom_counts = trajectory.frames.map((f) => f.structure.sites.length);
|
|
36
|
+
const constant_atoms = atom_counts.every((count) => count === atom_counts[0]);
|
|
37
|
+
stats.constant_atom_count = constant_atoms;
|
|
38
|
+
if (constant_atoms) {
|
|
39
|
+
stats.total_atoms = first_frame.structure.sites.length;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
stats.atom_count_range = [
|
|
43
|
+
Math.min(...atom_counts),
|
|
44
|
+
Math.max(...atom_counts),
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return stats;
|
|
49
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Trajectory } from './index';
|
|
2
|
+
export declare function array_buffer_to_data_url(buffer: ArrayBuffer): string;
|
|
3
|
+
export declare function data_url_to_array_buffer(data_url: string): ArrayBuffer;
|
|
4
|
+
export declare function load_trajectory_from_url(url: string): Promise<Trajectory>;
|
|
5
|
+
export declare function parse_torch_sim_hdf5(buffer: ArrayBuffer, filename?: string): Promise<Trajectory>;
|
|
6
|
+
export declare function is_torch_sim_hdf5(content: unknown, filename?: string): boolean;
|
|
7
|
+
export declare function parse_vasp_xdatcar(content: string): Trajectory;
|
|
8
|
+
export declare function is_vasp_xdatcar(content: string, filename?: string): boolean;
|
|
9
|
+
export declare function parse_xyz_trajectory(content: string): Trajectory;
|
|
10
|
+
export declare function is_xyz_trajectory(content: string, filename?: string): boolean;
|
|
11
|
+
export declare function parse_pymatgen_trajectory(obj_data: Record<string, unknown>, filename?: string): Trajectory;
|
|
12
|
+
export declare function parse_trajectory_data(data: unknown, filename?: string): Promise<Trajectory>;
|
|
13
|
+
export declare function get_unsupported_format_message(filename: string, content: string): string | null;
|