matterviz 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FilePicker.svelte +40 -50
- package/dist/api/optimade.js +10 -7
- package/dist/app.css +15 -0
- package/dist/brillouin/BrillouinZone.svelte +18 -9
- package/dist/brillouin/BrillouinZoneScene.svelte +20 -29
- package/dist/brillouin/compute.js +10 -16
- package/dist/brillouin/geometry.js +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +18 -15
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +17 -113
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +104 -264
- package/dist/chempot-diagram/async-compute.svelte.js +12 -13
- package/dist/chempot-diagram/color.d.ts +21 -1
- package/dist/chempot-diagram/color.js +70 -1
- package/dist/chempot-diagram/compute.d.ts +7 -0
- package/dist/chempot-diagram/compute.js +85 -26
- package/dist/chempot-diagram/export.js +1 -6
- package/dist/chempot-diagram/temperature.js +9 -10
- package/dist/composition/BarChart.svelte +7 -9
- package/dist/composition/Composition.svelte +3 -8
- package/dist/composition/Formula.svelte +2 -2
- package/dist/composition/FormulaFilter.svelte +27 -93
- package/dist/composition/format.js +6 -8
- package/dist/composition/parse.js +50 -105
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +6 -17
- package/dist/convex-hull/ConvexHull2D.svelte +0 -2
- package/dist/convex-hull/ConvexHull3D.svelte +19 -47
- package/dist/convex-hull/ConvexHull4D.svelte +65 -95
- package/dist/convex-hull/StructurePopup.svelte +1 -1
- package/dist/convex-hull/gas-thermodynamics.js +21 -53
- package/dist/convex-hull/helpers.js +1 -7
- package/dist/convex-hull/thermodynamics.js +19 -27
- package/dist/coordination/CoordinationBarPlot.svelte +12 -21
- package/dist/element/BohrAtom.svelte +0 -1
- package/dist/element/ElementTile.svelte +26 -44
- package/dist/element/data.d.ts +2 -0
- package/dist/element/data.js +5 -1
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -1
- package/dist/fermi-surface/FermiSurface.svelte +22 -23
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +2 -6
- package/dist/fermi-surface/FermiSurfaceScene.svelte +32 -77
- package/dist/fermi-surface/compute.js +22 -55
- package/dist/fermi-surface/parse.js +38 -70
- package/dist/file-viewer/JsonBrowser.svelte +1043 -0
- package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
- package/dist/file-viewer/PlotPanel.svelte +350 -0
- package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
- package/dist/file-viewer/detect.d.ts +11 -0
- package/dist/file-viewer/detect.js +381 -0
- package/dist/file-viewer/eligibility.d.ts +4 -0
- package/dist/file-viewer/eligibility.js +53 -0
- package/dist/file-viewer/host-protocol.d.ts +50 -0
- package/dist/file-viewer/host-transfer.d.ts +25 -0
- package/dist/file-viewer/host-transfer.js +42 -0
- package/dist/file-viewer/index.d.ts +5 -0
- package/dist/file-viewer/index.js +5 -0
- package/dist/file-viewer/main.d.ts +44 -0
- package/dist/file-viewer/main.js +535 -0
- package/dist/file-viewer/parse.d.ts +9 -0
- package/dist/file-viewer/parse.js +170 -0
- package/dist/file-viewer/plot-utils.d.ts +24 -0
- package/dist/file-viewer/plot-utils.js +191 -0
- package/dist/file-viewer/types.d.ts +4 -0
- package/dist/file-viewer/types.js +5 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +57 -84
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/io/ExportPane.svelte +1 -1
- package/dist/io/decompress.d.ts +2 -0
- package/dist/io/decompress.js +3 -2
- package/dist/io/export.d.ts +7 -4
- package/dist/io/export.js +70 -18
- package/dist/io/file-drop.js +60 -35
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +28 -16
- package/dist/isosurface/Isosurface.svelte +687 -196
- package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +564 -85
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
- package/dist/isosurface/VolumeSlice.svelte +224 -0
- package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
- package/dist/isosurface/coloring.d.ts +20 -0
- package/dist/isosurface/coloring.js +118 -0
- package/dist/isosurface/geometry-worker-types.d.ts +38 -0
- package/dist/isosurface/geometry.worker.d.ts +1 -0
- package/dist/isosurface/geometry.worker.js +59 -0
- package/dist/isosurface/grid.d.ts +10 -0
- package/dist/isosurface/grid.js +31 -0
- package/dist/isosurface/index.d.ts +4 -0
- package/dist/isosurface/index.js +4 -0
- package/dist/isosurface/profile.d.ts +12 -0
- package/dist/isosurface/profile.js +19 -0
- package/dist/isosurface/sampling.d.ts +34 -0
- package/dist/isosurface/sampling.js +408 -0
- package/dist/isosurface/slice-rendering.d.ts +13 -0
- package/dist/isosurface/slice-rendering.js +79 -0
- package/dist/isosurface/slice.d.ts +22 -2
- package/dist/isosurface/slice.js +200 -116
- package/dist/isosurface/types.d.ts +24 -1
- package/dist/isosurface/types.js +120 -8
- package/dist/json-path.d.ts +4 -0
- package/dist/json-path.js +89 -0
- package/dist/labels.js +1 -1
- package/dist/layout/InfoCard.svelte +1 -3
- package/dist/layout/SettingsSection.svelte +52 -61
- package/dist/layout/SettingsSection.svelte.d.ts +6 -7
- package/dist/layout/ViewerChrome.svelte +7 -1
- package/dist/layout/json-tree/JsonNode.svelte +14 -48
- package/dist/layout/json-tree/JsonTree.svelte +48 -95
- package/dist/layout/json-tree/JsonValue.svelte +3 -18
- package/dist/layout/json-tree/utils.d.ts +0 -3
- package/dist/layout/json-tree/utils.js +50 -179
- package/dist/marching-cubes.d.ts +8 -1
- package/dist/marching-cubes.js +115 -48
- package/dist/math.d.ts +3 -2
- package/dist/math.js +29 -38
- package/dist/overlays/ContextMenu.svelte +15 -32
- package/dist/overlays/DraggablePane.svelte +39 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -1
- package/dist/overlays/GlassChip.svelte +3 -1
- package/dist/periodic-table/PeriodicTableControls.svelte +26 -52
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +18 -34
- package/dist/phase-diagram/build-diagram.js +1 -6
- package/dist/phase-diagram/svg-to-diagram.js +9 -14
- package/dist/plot/bar/BarPlot.svelte +38 -42
- package/dist/plot/bar/SpacegroupBarPlot.svelte +18 -42
- package/dist/plot/box/BoxPlot.svelte +27 -23
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/data-transform.d.ts +1 -2
- package/dist/plot/core/data-transform.js +0 -10
- package/dist/plot/core/layout.d.ts +12 -5
- package/dist/plot/core/layout.js +37 -27
- package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
- package/dist/plot/core/pan-zoom.svelte.js +34 -17
- package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -21
- package/dist/plot/core/svg.js +0 -1
- package/dist/plot/core/utils/hierarchy-chart.d.ts +1 -0
- package/dist/plot/core/utils/hierarchy-chart.js +12 -0
- package/dist/plot/core/utils/hierarchy-labels.js +3 -2
- package/dist/plot/histogram/Histogram.svelte +21 -26
- package/dist/plot/sankey/sankey.js +13 -9
- package/dist/plot/scatter/BinnedScatterPlot.svelte +59 -43
- package/dist/plot/scatter/ScatterPlot.svelte +67 -52
- package/dist/plot/scatter/adaptive-density.d.ts +1 -1
- package/dist/plot/scatter/adaptive-density.js +36 -20
- package/dist/plot/sunburst/Sunburst.svelte +20 -20
- package/dist/plot/treemap/Treemap.svelte +175 -60
- package/dist/plot/treemap/Treemap.svelte.d.ts +6 -0
- package/dist/plot/treemap/index.d.ts +1 -0
- package/dist/plot/treemap/labels.d.ts +38 -0
- package/dist/plot/treemap/labels.js +80 -0
- package/dist/plot/treemap/treemap.d.ts +4 -2
- package/dist/plot/treemap/treemap.js +5 -2
- package/dist/rdf/RdfPlot.svelte +17 -35
- package/dist/rdf/calc-rdf.js +59 -44
- package/dist/rdf/index.d.ts +0 -1
- package/dist/sanitize.js +84 -26
- package/dist/scene/SceneCamera.svelte +1 -1
- package/dist/scene/SceneCamera.svelte.d.ts +1 -1
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +1 -1
- package/dist/scene/{props.js → props.svelte.js} +15 -1
- package/dist/settings.js +159 -482
- package/dist/spectral/Bands.svelte +151 -158
- package/dist/spectral/BrillouinBandsDos.svelte +4 -19
- package/dist/spectral/Dos.svelte +26 -24
- package/dist/spectral/helpers.js +40 -105
- package/dist/structure/AtomLegend.svelte +8 -13
- package/dist/structure/AtomLegend.svelte.d.ts +2 -3
- package/dist/structure/CellSelect.svelte +35 -10
- package/dist/structure/Structure.svelte +177 -99
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureCarousel.svelte +10 -3
- package/dist/structure/StructureControls.svelte +8 -26
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +65 -76
- package/dist/structure/StructureScene.svelte +75 -109
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +120 -55
- package/dist/structure/StructureViewport.svelte.d.ts +3 -1
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +4 -3
- package/dist/structure/bond-order-perception.js +3 -8
- package/dist/structure/bonding.d.ts +0 -1
- package/dist/structure/bonding.js +16 -23
- package/dist/structure/export.js +50 -74
- package/dist/structure/format-detect.js +5 -7
- package/dist/structure/index.js +6 -12
- package/dist/structure/parse.js +38 -100
- package/dist/structure/partial-occupancy.js +7 -4
- package/dist/structure/pbc.js +8 -10
- package/dist/structure/polyhedra.js +5 -4
- package/dist/structure/prop-groups.d.ts +85 -0
- package/dist/structure/prop-groups.js +18 -0
- package/dist/symmetry/SymmetryStats.svelte +0 -4
- package/dist/symmetry/WyckoffTable.svelte +5 -4
- package/dist/symmetry/cell-transform.js +5 -14
- package/dist/symmetry/index.js +6 -9
- package/dist/table/HeatmapTable.svelte +61 -103
- package/dist/table/ToggleMenu.svelte +166 -44
- package/dist/table/ToggleMenu.svelte.d.ts +1 -1
- package/dist/theme/embedded.d.ts +18 -0
- package/dist/theme/embedded.js +206 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +1 -2
- package/dist/theme/themes.mjs +31 -60
- package/dist/tooltip/TooltipContent.svelte +1 -1
- package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
- package/dist/tooltip/index.d.ts +8 -1
- package/dist/trajectory/Trajectory.svelte +140 -120
- package/dist/trajectory/TrajectoryError.svelte +1 -66
- package/dist/trajectory/TrajectoryExportPane.svelte +0 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +55 -80
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
- package/dist/trajectory/extract.js +19 -29
- package/dist/trajectory/format-detect.d.ts +2 -0
- package/dist/trajectory/format-detect.js +7 -5
- package/dist/trajectory/frame-reader.js +3 -4
- package/dist/trajectory/helpers.js +16 -49
- package/dist/trajectory/index.js +2 -8
- package/dist/trajectory/parse/ase.js +1 -1
- package/dist/trajectory/parse/index.d.ts +4 -3
- package/dist/trajectory/parse/index.js +12 -17
- package/dist/trajectory/parse/vaspout-h5.d.ts +0 -1
- package/dist/trajectory/parse/vaspout-h5.js +1 -4
- package/dist/trajectory/parse/xyz.js +48 -2
- package/dist/trajectory/plotting.js +14 -37
- package/dist/xrd/XrdPlot.svelte +43 -68
- package/dist/xrd/calc-xrd.js +22 -58
- package/dist/xrd/parse.js +13 -22
- package/package.json +40 -8
- package/readme.md +6 -5
- package/dist/scene/types.d.ts +0 -26
- package/dist/tooltip/types.d.ts +0 -8
- package/dist/trajectory/constants.d.ts +0 -6
- package/dist/trajectory/constants.js +0 -11
- /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
- /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
import { SETTINGS_CONFIG } from '../settings'
|
|
9
9
|
import type { AnyStructure } from '../structure'
|
|
10
10
|
import type { ComponentProps } from 'svelte'
|
|
11
|
-
import type { TrajectoryType } from './index'
|
|
11
|
+
import type { TrajectoryFrame, TrajectoryType } from './index'
|
|
12
12
|
|
|
13
13
|
let {
|
|
14
14
|
trajectory,
|
|
15
15
|
current_step_idx,
|
|
16
|
+
current_frame = null,
|
|
16
17
|
current_filename,
|
|
17
18
|
current_file_path,
|
|
18
19
|
file_size,
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
}: Omit<ComponentProps<typeof DraggablePane>, `children`> & {
|
|
25
26
|
trajectory: TrajectoryType
|
|
26
27
|
current_step_idx: number
|
|
28
|
+
current_frame?: TrajectoryFrame | null
|
|
27
29
|
current_filename?: string | null
|
|
28
30
|
current_file_path?: string | null
|
|
29
31
|
file_size?: number | null
|
|
@@ -76,14 +78,18 @@
|
|
|
76
78
|
)
|
|
77
79
|
return []
|
|
78
80
|
|
|
79
|
-
// For indexed trajectories,
|
|
80
|
-
const
|
|
81
|
+
// For indexed trajectories, the resolved frame may live outside sparse frame arrays.
|
|
82
|
+
const displayed_frame = current_frame ?? trajectory.frames?.[current_step_idx]
|
|
81
83
|
const total_frames = trajectory.total_frames ?? trajectory.frames?.length ?? 0
|
|
82
84
|
|
|
83
85
|
const sections: { title: string; items: InfoItem[] }[] = []
|
|
86
|
+
// Append a section unless every item filtered out as falsy
|
|
87
|
+
const push_section = (title: string, items: unknown[]) => {
|
|
88
|
+
const valid_items = items.filter(is_info_item)
|
|
89
|
+
if (valid_items.length > 0) sections.push({ title, items: valid_items })
|
|
90
|
+
}
|
|
84
91
|
|
|
85
|
-
|
|
86
|
-
const file_items = [
|
|
92
|
+
push_section(`File`, [
|
|
87
93
|
current_filename &&
|
|
88
94
|
safe_item(`Name`, current_filename, `file-name`, current_file_path || undefined),
|
|
89
95
|
file_size &&
|
|
@@ -97,14 +103,9 @@
|
|
|
97
103
|
),
|
|
98
104
|
trajectory.metadata?.source_format &&
|
|
99
105
|
safe_item(`Format`, String(trajectory.metadata.source_format), `file-format`),
|
|
100
|
-
]
|
|
101
|
-
|
|
102
|
-
if (file_items.length > 0) {
|
|
103
|
-
sections.push({ title: `File`, items: file_items })
|
|
104
|
-
}
|
|
106
|
+
])
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
const traj_items = [
|
|
108
|
+
push_section(`Trajectory`, [
|
|
108
109
|
safe_item(
|
|
109
110
|
`Total Frames`,
|
|
110
111
|
`${format_num(total_frames, `.3~s`)} (current: ${format_num(
|
|
@@ -134,20 +135,16 @@
|
|
|
134
135
|
`plot-metadata`,
|
|
135
136
|
`Pre-extracted metadata for plotting`,
|
|
136
137
|
),
|
|
137
|
-
]
|
|
138
|
-
|
|
139
|
-
if (traj_items.length > 0) {
|
|
140
|
-
sections.push({ title: `Trajectory`, items: traj_items })
|
|
141
|
-
}
|
|
138
|
+
])
|
|
142
139
|
|
|
143
140
|
// Structure info section (only if we have the current frame)
|
|
144
|
-
if (
|
|
145
|
-
const { structure } =
|
|
141
|
+
if (displayed_frame?.structure?.sites) {
|
|
142
|
+
const { structure } = displayed_frame
|
|
146
143
|
const lattice = `lattice` in structure ? structure.lattice : null
|
|
147
144
|
const { volume, a, b, c, alpha, beta, gamma } = lattice || {}
|
|
148
145
|
const formula = safe_formula(structure)
|
|
149
146
|
|
|
150
|
-
|
|
147
|
+
push_section(`Structure`, [
|
|
151
148
|
safe_item(`Atoms`, `${structure.sites.length}`, `atoms`),
|
|
152
149
|
formula && safe_item(`Formula`, String(formula), `formula`),
|
|
153
150
|
is_valid_number(volume) &&
|
|
@@ -158,7 +155,7 @@
|
|
|
158
155
|
structure.sites.length > 0 &&
|
|
159
156
|
safe_item(
|
|
160
157
|
`Density`,
|
|
161
|
-
`${format_num(structure.sites.length / volume, `.
|
|
158
|
+
`${format_num(structure.sites.length / volume, `.3~s`)} atoms/ų`,
|
|
162
159
|
`density`,
|
|
163
160
|
),
|
|
164
161
|
[a, b, c].every(is_valid_number) &&
|
|
@@ -179,77 +176,59 @@
|
|
|
179
176
|
)}°, ${format_num(gamma as number, `.2~f`)}°`,
|
|
180
177
|
`cell-angles`,
|
|
181
178
|
),
|
|
182
|
-
]
|
|
183
|
-
|
|
184
|
-
if (structure_items.length > 0) {
|
|
185
|
-
sections.push({ title: `Structure`, items: structure_items })
|
|
186
|
-
}
|
|
179
|
+
])
|
|
187
180
|
} else if (trajectory.is_indexed) {
|
|
188
181
|
// For indexed trajectories, show a note that frame data is loaded on demand
|
|
189
|
-
|
|
182
|
+
push_section(`Structure`, [
|
|
190
183
|
safe_item(
|
|
191
184
|
`Frame Loading`,
|
|
192
185
|
`On-demand`,
|
|
193
186
|
`frame-loading`,
|
|
194
187
|
`Structure data loaded when frame is accessed`,
|
|
195
188
|
),
|
|
196
|
-
]
|
|
197
|
-
|
|
198
|
-
if (structure_items.length > 0) {
|
|
199
|
-
sections.push({ title: `Structure`, items: structure_items })
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Energy section (only for regular trajectories with multiple frames)
|
|
204
|
-
if (!trajectory.is_indexed && trajectory.frames.length > 1) {
|
|
205
|
-
const energies = extract_numeric_array(trajectory.frames, `energy`)
|
|
206
|
-
if (energies.length > 1) {
|
|
207
|
-
const current_energy = current_frame?.metadata?.energy
|
|
208
|
-
const energy_range = format_range(energies, `eV`, `.3~s`)
|
|
209
|
-
|
|
210
|
-
const energy_items = [
|
|
211
|
-
is_valid_number(current_energy) &&
|
|
212
|
-
safe_item(
|
|
213
|
-
`Current Energy`,
|
|
214
|
-
`${format_num(current_energy, `.3~s`)} eV`,
|
|
215
|
-
`energy-current`,
|
|
216
|
-
),
|
|
217
|
-
energy_range && safe_item(`Energy Range`, energy_range, `energy-range`),
|
|
218
|
-
].filter(is_info_item)
|
|
219
|
-
|
|
220
|
-
if (energy_items.length > 0) {
|
|
221
|
-
sections.push({ title: `Energy`, items: energy_items })
|
|
222
|
-
}
|
|
223
|
-
}
|
|
189
|
+
])
|
|
224
190
|
}
|
|
225
191
|
|
|
226
|
-
// Forces
|
|
192
|
+
// Energy/Forces sections (only for regular trajectories with multiple frames)
|
|
227
193
|
if (!trajectory.is_indexed && trajectory.frames.length > 1) {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
194
|
+
const range_sections = [
|
|
195
|
+
{
|
|
196
|
+
title: `Energy`,
|
|
197
|
+
prop: `energy`,
|
|
198
|
+
unit: `eV`,
|
|
199
|
+
key: `energy`,
|
|
200
|
+
current_label: `Current Energy`,
|
|
201
|
+
range_label: `Energy Range`,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: `Forces`,
|
|
205
|
+
prop: `force_max`,
|
|
206
|
+
unit: `eV/Å`,
|
|
207
|
+
key: `force`,
|
|
208
|
+
current_label: `Max Force`,
|
|
209
|
+
range_label: `Force Range`,
|
|
210
|
+
},
|
|
211
|
+
] as const
|
|
212
|
+
for (const { title, prop, unit, key, current_label, range_label } of range_sections) {
|
|
213
|
+
const values = extract_numeric_array(trajectory.frames, prop)
|
|
214
|
+
if (values.length <= 1) continue
|
|
215
|
+
const current = displayed_frame?.metadata?.[prop]
|
|
216
|
+
push_section(title, [
|
|
217
|
+
is_valid_number(current) &&
|
|
235
218
|
safe_item(
|
|
236
|
-
|
|
237
|
-
`${format_num(
|
|
238
|
-
|
|
219
|
+
current_label,
|
|
220
|
+
`${format_num(current, `.3~s`)} ${unit}`,
|
|
221
|
+
`${key}-current`,
|
|
239
222
|
),
|
|
240
|
-
|
|
241
|
-
]
|
|
242
|
-
|
|
243
|
-
if (force_items.length > 0) {
|
|
244
|
-
sections.push({ title: `Forces`, items: force_items })
|
|
245
|
-
}
|
|
223
|
+
safe_item(range_label, format_range(values, unit, `.3~s`), `${key}-range`),
|
|
224
|
+
])
|
|
246
225
|
}
|
|
247
226
|
}
|
|
248
227
|
|
|
249
228
|
// Volume change section (only for regular trajectories)
|
|
250
|
-
if (!trajectory.is_indexed &&
|
|
229
|
+
if (!trajectory.is_indexed && displayed_frame?.structure && trajectory.frames.length > 1) {
|
|
251
230
|
const lattice =
|
|
252
|
-
`lattice` in
|
|
231
|
+
`lattice` in displayed_frame.structure ? displayed_frame.structure.lattice : null
|
|
253
232
|
if (lattice) {
|
|
254
233
|
const volumes = trajectory.frames
|
|
255
234
|
.map(({ structure }) => `lattice` in structure && structure.lattice?.volume)
|
|
@@ -260,13 +239,9 @@
|
|
|
260
239
|
const vol_change =
|
|
261
240
|
(Math.max(...volumes) - Math.min(...volumes)) / Math.min(...volumes)
|
|
262
241
|
if (Math.abs(vol_change) > 0.1 && is_valid_number(vol_change)) {
|
|
263
|
-
|
|
242
|
+
push_section(`Volume`, [
|
|
264
243
|
safe_item(`Volume Change`, `${format_num(vol_change, `.2~%`)}`, `vol-change`),
|
|
265
|
-
]
|
|
266
|
-
|
|
267
|
-
if (vol_items.length > 0) {
|
|
268
|
-
sections.push({ title: `Volume`, items: vol_items })
|
|
269
|
-
}
|
|
244
|
+
])
|
|
270
245
|
}
|
|
271
246
|
}
|
|
272
247
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { PaneProps, PaneToggleProps } from '../overlays';
|
|
2
2
|
import DraggablePane from '../overlays/DraggablePane.svelte';
|
|
3
3
|
import type { ComponentProps } from 'svelte';
|
|
4
|
-
import type { TrajectoryType } from './index';
|
|
4
|
+
import type { TrajectoryFrame, TrajectoryType } from './index';
|
|
5
5
|
type $$ComponentProps = Omit<ComponentProps<typeof DraggablePane>, `children`> & {
|
|
6
6
|
trajectory: TrajectoryType;
|
|
7
7
|
current_step_idx: number;
|
|
8
|
+
current_frame?: TrajectoryFrame | null;
|
|
8
9
|
current_filename?: string | null;
|
|
9
10
|
current_file_path?: string | null;
|
|
10
11
|
file_size?: number | null;
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
// Data extraction functions for trajectory analysis and plotting
|
|
2
2
|
import { get_density } from '../structure/index';
|
|
3
3
|
import { calc_force_stats, copy_numeric_fields } from './helpers';
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
const data = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (frame.metadata) {
|
|
10
|
-
// Extract energy-related properties
|
|
11
|
-
copy_numeric_fields(data, frame.metadata, [
|
|
12
|
-
`energy`,
|
|
13
|
-
`energy_per_atom`,
|
|
14
|
-
`potential_energy`,
|
|
15
|
-
`kinetic_energy`,
|
|
16
|
-
`total_energy`,
|
|
17
|
-
]);
|
|
18
|
-
}
|
|
4
|
+
// Build an extractor that copies the listed numeric metadata fields (plus Step)
|
|
5
|
+
const make_metadata_extractor = (fields) => (frame) => {
|
|
6
|
+
const data = { Step: frame.step };
|
|
7
|
+
if (frame.metadata)
|
|
8
|
+
copy_numeric_fields(data, frame.metadata, fields);
|
|
19
9
|
return data;
|
|
20
10
|
};
|
|
11
|
+
// Common data extractor that extracts energy-related properties
|
|
12
|
+
export const energy_data_extractor = make_metadata_extractor([
|
|
13
|
+
`energy`,
|
|
14
|
+
`energy_per_atom`,
|
|
15
|
+
`potential_energy`,
|
|
16
|
+
`kinetic_energy`,
|
|
17
|
+
`total_energy`,
|
|
18
|
+
]);
|
|
21
19
|
// Data extractor for forces and stresses
|
|
22
20
|
export const force_stress_data_extractor = (frame) => {
|
|
23
21
|
const data = {
|
|
@@ -55,20 +53,12 @@ export const force_stress_data_extractor = (frame) => {
|
|
|
55
53
|
// Data extractor for SCF/electronic-convergence properties. Parsers emit these
|
|
56
54
|
// per frame (per ionic step, or per SCF step for static single-point runs) —
|
|
57
55
|
// e.g. the vaspout.h5 parser fills them from VASP's OSZICAR data.
|
|
58
|
-
const scf_data_extractor = (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`n_scf_steps`,
|
|
65
|
-
`scf_energy_delta`,
|
|
66
|
-
`scf_rms`,
|
|
67
|
-
`scf_charge_rms`,
|
|
68
|
-
]);
|
|
69
|
-
}
|
|
70
|
-
return data;
|
|
71
|
-
};
|
|
56
|
+
const scf_data_extractor = make_metadata_extractor([
|
|
57
|
+
`n_scf_steps`,
|
|
58
|
+
`scf_energy_delta`,
|
|
59
|
+
`scf_rms`,
|
|
60
|
+
`scf_charge_rms`,
|
|
61
|
+
]);
|
|
72
62
|
// Data extractor for structural properties
|
|
73
63
|
export const structural_data_extractor = (frame) => {
|
|
74
64
|
const data = {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare function ext_hint(filename: string | undefined, ext_regex: RegExp): boolean | null;
|
|
2
|
+
export declare const indexed_trajectory_format: (filename: string) => `ase` | `xyz`;
|
|
3
|
+
export declare const is_indexable_trajectory_filename: (filename: string) => boolean;
|
|
2
4
|
export declare const FORMAT_PATTERNS: {
|
|
3
5
|
readonly ase: (data: unknown, filename?: string) => boolean;
|
|
4
6
|
readonly hdf5: (data: unknown, filename?: string) => boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Format detection for trajectory files
|
|
2
|
-
import { CONFIG_DIRS_REGEX, MD_SIM_EXCLUDE_REGEX, TRAJ_EXTENSIONS_REGEX, TRAJ_FALLBACK_EXTENSIONS_REGEX,
|
|
2
|
+
import { CONFIG_DIRS_REGEX, MD_SIM_EXCLUDE_REGEX, TRAJ_EXTENSIONS_REGEX, TRAJ_FALLBACK_EXTENSIONS_REGEX, TRAJ_KEYWORDS_REGEX, XDATCAR_REGEX, } from '../constants';
|
|
3
3
|
import { strip_compression_extensions } from '../io/decompress';
|
|
4
4
|
import { parse_leading_num } from '../utils';
|
|
5
5
|
import { count_xyz_frames } from './helpers';
|
|
@@ -18,6 +18,9 @@ export function ext_hint(filename, ext_regex) {
|
|
|
18
18
|
return true;
|
|
19
19
|
return KNOWN_FORMAT_EXT_REGEX.test(base) ? false : null;
|
|
20
20
|
}
|
|
21
|
+
// Large-file frame indexing currently supports text XYZ/EXTXYZ and binary ASE .traj.
|
|
22
|
+
export const indexed_trajectory_format = (filename) => strip_compression_extensions(filename).endsWith(`.traj`) ? `ase` : `xyz`;
|
|
23
|
+
export const is_indexable_trajectory_filename = (filename) => /\.(?:xyz|extxyz|traj)$/i.test(strip_compression_extensions(filename));
|
|
21
24
|
// Unified format detection. Each pattern trusts a matching file extension when present
|
|
22
25
|
// but falls back to content/magic-byte detection when the filename gives no hint
|
|
23
26
|
// (e.g. blob: object URLs, extensionless API endpoints).
|
|
@@ -67,7 +70,7 @@ export function is_trajectory_file(filename, content) {
|
|
|
67
70
|
if (/\.(?:xyz|extxyz)$/i.test(base_name)) {
|
|
68
71
|
if (content)
|
|
69
72
|
return count_xyz_frames(content) >= 2;
|
|
70
|
-
return
|
|
73
|
+
return TRAJ_KEYWORDS_REGEX.test(base_name);
|
|
71
74
|
}
|
|
72
75
|
// Always detect these specific trajectory formats
|
|
73
76
|
if (TRAJ_EXTENSIONS_REGEX.test(base_name) || XDATCAR_REGEX.test(base_name))
|
|
@@ -78,9 +81,8 @@ export function is_trajectory_file(filename, content) {
|
|
|
78
81
|
// For .h5/.hdf5 files, require trajectory keywords. vaspout.h5 (VASP's
|
|
79
82
|
// HDF5 output) is always trajectory-shaped regardless of keywords.
|
|
80
83
|
if (/\.(?:h5|hdf5)$/i.test(base_name)) {
|
|
81
|
-
return /vaspout/i.test(base_name) ||
|
|
84
|
+
return /vaspout/i.test(base_name) || TRAJ_KEYWORDS_REGEX.test(base_name);
|
|
82
85
|
}
|
|
83
86
|
// For other extensions, require both keywords and specific extensions
|
|
84
|
-
return
|
|
85
|
-
TRAJ_FALLBACK_EXTENSIONS_REGEX.test(base_name));
|
|
87
|
+
return TRAJ_KEYWORDS_REGEX.test(base_name) && TRAJ_FALLBACK_EXTENSIONS_REGEX.test(base_name);
|
|
86
88
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Unified frame loader for XYZ and ASE trajectories (large file indexing)
|
|
2
2
|
import * as math from '../math';
|
|
3
|
-
import { MAX_METADATA_SIZE } from './constants';
|
|
4
3
|
import { copy_numeric_fields, count_xyz_frames, iter_xyz_frames, validate_3x3_matrix, } from './helpers';
|
|
5
|
-
import {
|
|
4
|
+
import { indexed_trajectory_format } from './format-detect';
|
|
6
5
|
import { decode_ase_frame, read_ase_header } from './parse/ase';
|
|
7
6
|
import { build_xyz_frame, parse_xyz_comment_metadata } from './parse/xyz';
|
|
7
|
+
const MAX_METADATA_SIZE = 50 * 1024 * 1024; // 50MB limit for metadata
|
|
8
8
|
// Restrict frame metadata to the requested property keys (no-op when unset)
|
|
9
9
|
const filter_properties = (metadata, properties) => {
|
|
10
10
|
if (!properties)
|
|
@@ -18,8 +18,7 @@ export class TrajFrameReader {
|
|
|
18
18
|
// O(1) lookup instead of re-splitting + rescanning from line 0 (was O(n²) over playback)
|
|
19
19
|
xyz_cache;
|
|
20
20
|
constructor(filename) {
|
|
21
|
-
|
|
22
|
-
this.format = base_filename.endsWith(`.traj`) ? `ase` : `xyz`;
|
|
21
|
+
this.format = indexed_trajectory_format(filename);
|
|
23
22
|
}
|
|
24
23
|
async get_total_frames(data) {
|
|
25
24
|
if (this.format === `xyz`) {
|
|
@@ -3,11 +3,6 @@ import { ATOMIC_NUMBER_TO_SYMBOL } from '../composition/parse';
|
|
|
3
3
|
import { is_elem_symbol } from '../element/helpers';
|
|
4
4
|
import * as math from '../math';
|
|
5
5
|
import { make_site } from '../structure/site';
|
|
6
|
-
const is_valid_row = (row) => {
|
|
7
|
-
if (!(Array.isArray(row) || (ArrayBuffer.isView(row) && `length` in row)))
|
|
8
|
-
return false;
|
|
9
|
-
return math.is_finite_vec3_like(row);
|
|
10
|
-
};
|
|
11
6
|
const is_valid_vec3 = (coords) => Array.isArray(coords) && math.is_finite_vec3_like(coords);
|
|
12
7
|
// Validate that data is a proper 3x3 matrix
|
|
13
8
|
// Accepts both regular arrays and typed arrays (Float32Array, Float64Array, etc.)
|
|
@@ -15,7 +10,8 @@ export function validate_3x3_matrix(data) {
|
|
|
15
10
|
if (!Array.isArray(data) || data.length !== 3) {
|
|
16
11
|
throw new Error(`Expected 3x3 matrix, got array of length ${Array.isArray(data) ? data.length : `non-array`}`);
|
|
17
12
|
}
|
|
18
|
-
if (!data.every(
|
|
13
|
+
if (!data.every((row) => (Array.isArray(row) || (ArrayBuffer.isView(row) && `length` in row)) &&
|
|
14
|
+
math.is_finite_vec3_like(row))) {
|
|
19
15
|
throw new Error(`Invalid 3x3 matrix structure`);
|
|
20
16
|
}
|
|
21
17
|
return data;
|
|
@@ -69,54 +65,25 @@ export const create_trajectory_frame = (positions, elements, lattice_matrix, pbc
|
|
|
69
65
|
export const read_ndarray_from_view = (view, ref) => {
|
|
70
66
|
const [shape, dtype, array_offset] = ref.ndarray;
|
|
71
67
|
const total = shape.reduce((product, dim_size) => product * dim_size, 1);
|
|
72
|
-
const data = [];
|
|
73
|
-
let pos = array_offset;
|
|
74
68
|
const readers = {
|
|
75
|
-
int64: {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
pos += 8;
|
|
80
|
-
return value;
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
int32: {
|
|
84
|
-
bytes_per_element: 4,
|
|
85
|
-
read: () => {
|
|
86
|
-
const value = view.getInt32(pos, true);
|
|
87
|
-
pos += 4;
|
|
88
|
-
return value;
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
float64: {
|
|
92
|
-
bytes_per_element: 8,
|
|
93
|
-
read: () => {
|
|
94
|
-
const value = view.getFloat64(pos, true);
|
|
95
|
-
pos += 8;
|
|
96
|
-
return value;
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
float32: {
|
|
100
|
-
bytes_per_element: 4,
|
|
101
|
-
read: () => {
|
|
102
|
-
const value = view.getFloat32(pos, true);
|
|
103
|
-
pos += 4;
|
|
104
|
-
return value;
|
|
105
|
-
},
|
|
106
|
-
},
|
|
69
|
+
int64: { bytes: 8, read: (pos) => Number(view.getBigInt64(pos, true)) },
|
|
70
|
+
int32: { bytes: 4, read: (pos) => view.getInt32(pos, true) },
|
|
71
|
+
float64: { bytes: 8, read: (pos) => view.getFloat64(pos, true) },
|
|
72
|
+
float32: { bytes: 4, read: (pos) => view.getFloat32(pos, true) },
|
|
107
73
|
};
|
|
108
|
-
const
|
|
109
|
-
if (!
|
|
74
|
+
const reader = readers[dtype];
|
|
75
|
+
if (!reader)
|
|
110
76
|
throw new Error(`Unsupported dtype: ${dtype}`);
|
|
111
77
|
if (!Number.isInteger(array_offset) || array_offset < 0) {
|
|
112
78
|
throw new Error(`Invalid array_offset: expected non-negative integer, got ${array_offset}`);
|
|
113
79
|
}
|
|
114
|
-
|
|
115
|
-
if (array_offset + bytes_needed > view.byteLength) {
|
|
80
|
+
if (array_offset + total * reader.bytes > view.byteLength) {
|
|
116
81
|
throw new Error(`Out-of-bounds read: array_offset + bytesNeeded exceeds view.byteLength`);
|
|
117
82
|
}
|
|
118
|
-
|
|
119
|
-
|
|
83
|
+
const data = [];
|
|
84
|
+
for (let idx = 0; idx < total; idx++) {
|
|
85
|
+
data.push(reader.read(array_offset + idx * reader.bytes));
|
|
86
|
+
}
|
|
120
87
|
return shape.length === 1
|
|
121
88
|
? [data]
|
|
122
89
|
: shape.length === 2
|
|
@@ -147,7 +114,6 @@ export function calc_force_stats(forces) {
|
|
|
147
114
|
}
|
|
148
115
|
return { force_max, force_norm: Math.sqrt(sum_sq / forces.length) };
|
|
149
116
|
}
|
|
150
|
-
// Walk concatenated (ext)XYZ frames in `lines`, yielding each frame's atom-count line
|
|
151
117
|
// True when a whitespace-split line looks like an XYZ atom line: a short
|
|
152
118
|
// non-numeric element token followed by three numeric coordinates. Shared by
|
|
153
119
|
// trajectory frame iteration and structure-format sniffing so both stay in sync.
|
|
@@ -156,7 +122,8 @@ export const is_xyz_atom_line = (parts) => parts !== undefined &&
|
|
|
156
122
|
isNaN(Number(parts[0])) &&
|
|
157
123
|
parts[0].length <= 3 &&
|
|
158
124
|
parts.slice(1, 4).every((coord) => coord !== `` && !isNaN(Number(coord)));
|
|
159
|
-
//
|
|
125
|
+
// Walk concatenated (ext)XYZ frames in `lines`, yielding each frame's start line index,
|
|
126
|
+
// parsed atom count, and comment line. A candidate frame is accepted only when its
|
|
160
127
|
// first few atom lines look like "<element> <x> <y> <z>"; otherwise we advance one line and
|
|
161
128
|
// rescan. That validation doubles as content sniffing so numeric-leading non-XYZ formats
|
|
162
129
|
// (e.g. VASP XDATCAR) aren't misread as frames, and keeps count_xyz_frames consistent with
|
|
@@ -185,7 +152,7 @@ export function* iter_xyz_frames(lines) {
|
|
|
185
152
|
}
|
|
186
153
|
// Count XYZ frames via iter_xyz_frames so total_frames matches what gets indexed/loaded
|
|
187
154
|
export function count_xyz_frames(data) {
|
|
188
|
-
if (!data
|
|
155
|
+
if (!data)
|
|
189
156
|
return 0;
|
|
190
157
|
const frames = iter_xyz_frames(data.trim().split(/\r?\n/));
|
|
191
158
|
let frame_count = 0;
|
package/dist/trajectory/index.js
CHANGED
|
@@ -6,7 +6,6 @@ export { default as TrajectoryInfoPane } from './TrajectoryInfoPane.svelte';
|
|
|
6
6
|
// the user slides past. Exported so tests stay in sync with the real delay.
|
|
7
7
|
export const FRAME_LOAD_DEBOUNCE_MS = 75;
|
|
8
8
|
export function validate_trajectory(trajectory) {
|
|
9
|
-
// with detailed error reporting
|
|
10
9
|
const errors = [];
|
|
11
10
|
const { frames, total_frames, indexed_frames, plot_metadata, is_indexed } = trajectory;
|
|
12
11
|
if (!frames?.length)
|
|
@@ -113,13 +112,8 @@ export function get_trajectory_stats(trajectory) {
|
|
|
113
112
|
else
|
|
114
113
|
stats.atom_count_range = [Math.min(...all_counts), Math.max(...all_counts)];
|
|
115
114
|
}
|
|
116
|
-
else
|
|
117
|
-
//
|
|
118
|
-
stats.steps = [];
|
|
119
|
-
stats.step_range = undefined;
|
|
120
|
-
stats.constant_atom_count = undefined;
|
|
121
|
-
stats.total_atoms = undefined;
|
|
122
|
-
}
|
|
115
|
+
else
|
|
116
|
+
stats.steps = []; // empty trajectory
|
|
123
117
|
// Additional metadata for large files
|
|
124
118
|
if (indexed_frames)
|
|
125
119
|
stats.indexed_frame_count = indexed_frames.length;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ASE trajectory (.traj) parsing - binary format
|
|
2
2
|
import * as math from '../../math';
|
|
3
|
-
import { MAX_SAFE_STRING_LENGTH } from '../constants';
|
|
4
3
|
import { convert_atomic_numbers, create_trajectory_frame, read_ndarray_from_view, validate_3x3_matrix, } from '../helpers';
|
|
4
|
+
const MAX_SAFE_STRING_LENGTH = 0x1fffffe8 * 0.5; // 50% of JS max string length as safety
|
|
5
5
|
// ULM header: frame count lives at byte 32, frame-offsets table position at byte 40
|
|
6
6
|
export const read_ase_header = (view) => ({
|
|
7
7
|
n_items: Number(view.getBigInt64(32, true)),
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ParseProgress, TrajectoryType } from '../index';
|
|
2
2
|
import type { AtomTypeMapping, LoadingOptions } from '../types';
|
|
3
|
-
export
|
|
3
|
+
export declare const LARGE_FILE_THRESHOLD: number;
|
|
4
|
+
export declare const MAX_BIN_FILE_SIZE: number;
|
|
5
|
+
export declare const MAX_TEXT_FILE_SIZE: number;
|
|
4
6
|
export type { AtomTypeMapping, LoadingOptions } from '../types';
|
|
5
7
|
export { is_trajectory_file } from '../format-detect';
|
|
6
8
|
export { TrajFrameReader } from '../frame-reader';
|
|
7
9
|
export declare function parse_trajectory_data(data: unknown, filename?: string, atom_type_mapping?: AtomTypeMapping): Promise<TrajectoryType>;
|
|
8
10
|
export declare function get_unsupported_format_message(filename: string, content: string): string | null;
|
|
9
11
|
export declare function parse_trajectory_async(data: ArrayBuffer | string, filename: string, on_progress?: (progress: ParseProgress) => void, options?: LoadingOptions): Promise<TrajectoryType>;
|
|
10
|
-
export declare function create_frame_loader(filename: string): FrameLoader;
|
|
11
12
|
export declare function load_binary_traj(resp: Response, type: string, fallback?: boolean): Promise<ArrayBuffer | string>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// Parsing functions for trajectory data from various formats
|
|
2
2
|
import { is_binary } from '../../io/is-binary';
|
|
3
3
|
import { is_plain_object } from '../../utils';
|
|
4
|
+
import { DEFAULTS } from '../../settings';
|
|
4
5
|
import { is_parsed_structure, parse_xyz } from '../../structure/parse';
|
|
5
|
-
import {
|
|
6
|
-
import { strip_compression_extensions } from '../../io/decompress';
|
|
7
|
-
import { ext_hint, FORMAT_PATTERNS } from '../format-detect';
|
|
6
|
+
import { ext_hint, FORMAT_PATTERNS, indexed_trajectory_format, is_indexable_trajectory_filename, } from '../format-detect';
|
|
8
7
|
import { TrajFrameReader } from '../frame-reader';
|
|
9
8
|
import { count_xyz_frames } from '../helpers';
|
|
10
9
|
import { parse_ase_trajectory } from './ase';
|
|
@@ -21,8 +20,14 @@ const assert_frame_structure = (structure, label) => {
|
|
|
21
20
|
throw new Error(`Invalid structure in ${context}: expected non-empty 'sites' array with species and coordinates`);
|
|
22
21
|
}
|
|
23
22
|
};
|
|
24
|
-
//
|
|
25
|
-
export
|
|
23
|
+
// Constants for trajectory parsing and large file handling
|
|
24
|
+
export const LARGE_FILE_THRESHOLD = 400 * 1024 * 1024; // 400MB
|
|
25
|
+
const INDEX_SAMPLE_RATE = 100; // Default sample rate for frame indexing
|
|
26
|
+
// Fallback thresholds for component usage without loading_options, derived from the
|
|
27
|
+
// settings schema so settings-driven contexts (e.g. the VSCode extension) and direct
|
|
28
|
+
// component use agree on when large-file/indexed loading kicks in.
|
|
29
|
+
export const MAX_BIN_FILE_SIZE = DEFAULTS.trajectory.bin_file_threshold; // 50MB
|
|
30
|
+
export const MAX_TEXT_FILE_SIZE = DEFAULTS.trajectory.text_file_threshold; // 25MB
|
|
26
31
|
export { is_trajectory_file } from '../format-detect';
|
|
27
32
|
export { TrajFrameReader } from '../frame-reader';
|
|
28
33
|
export async function parse_trajectory_data(data, filename, atom_type_mapping) {
|
|
@@ -154,8 +159,7 @@ export async function parse_trajectory_async(data, filename, on_progress, option
|
|
|
154
159
|
// Use indexed loading for supported large files (including compressed names).
|
|
155
160
|
// When the filename gives no format hint (e.g. blob: URLs), sniff a content
|
|
156
161
|
// prefix for XYZ frames so large extensionless files still get indexed.
|
|
157
|
-
const
|
|
158
|
-
const can_index = /\.(?:xyz|extxyz|traj)$/.test(base_filename) ||
|
|
162
|
+
const can_index = is_indexable_trajectory_filename(filename) ||
|
|
159
163
|
(typeof data === `string` &&
|
|
160
164
|
ext_hint(filename, /\.(?:xyz|extxyz)$/) === null &&
|
|
161
165
|
count_xyz_frames(data.slice(0, 2 ** 20)) >= 1);
|
|
@@ -213,9 +217,7 @@ async function parse_with_unified_loader(data, filename, options, on_progress) {
|
|
|
213
217
|
}
|
|
214
218
|
const stage = `Ready: ${total_frames} frames indexed`;
|
|
215
219
|
on_progress?.({ current: 100, total: 100, stage });
|
|
216
|
-
const source_format = filename
|
|
217
|
-
? `ase_trajectory`
|
|
218
|
-
: `xyz_trajectory`;
|
|
220
|
+
const source_format = `${indexed_trajectory_format(filename)}_trajectory`;
|
|
219
221
|
return {
|
|
220
222
|
frames,
|
|
221
223
|
metadata: { source_format, frame_count: total_frames },
|
|
@@ -226,13 +228,6 @@ async function parse_with_unified_loader(data, filename, options, on_progress) {
|
|
|
226
228
|
frame_loader: loader,
|
|
227
229
|
};
|
|
228
230
|
}
|
|
229
|
-
// Factory function for frame loader (simplified)
|
|
230
|
-
export function create_frame_loader(filename) {
|
|
231
|
-
if (!/\.(?:xyz|extxyz|traj)$/.test(filename.toLowerCase())) {
|
|
232
|
-
throw new Error(`Unsupported format for frame loading: ${filename}`);
|
|
233
|
-
}
|
|
234
|
-
return new TrajFrameReader(filename);
|
|
235
|
-
}
|
|
236
231
|
export async function load_binary_traj(resp, type, fallback = false) {
|
|
237
232
|
try {
|
|
238
233
|
// Read binary from a clone so the original can be used for text fallback
|
|
@@ -2,4 +2,3 @@ import type * as h5wasm from 'h5wasm';
|
|
|
2
2
|
import type { TrajectoryType } from '../index';
|
|
3
3
|
export declare const is_vaspout_h5_file: (h5_file: h5wasm.File) => boolean;
|
|
4
4
|
export declare function parse_vaspout_h5_file(h5_file: h5wasm.File): TrajectoryType;
|
|
5
|
-
export declare function parse_vaspout_h5(buffer: ArrayBuffer, filename?: string): Promise<TrajectoryType>;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// VASP 6.x schema definitions).
|
|
18
18
|
import { calc_lattice_params, create_frac_to_cart } from '../../math';
|
|
19
19
|
import { count_elements, create_trajectory_frame, validate_3x3_matrix, } from '../helpers';
|
|
20
|
-
import { expand_ion_types, is_hdf5_group, read_dataset, scale_matrix, to_number_array, to_scalar_number, to_string_array,
|
|
20
|
+
import { expand_ion_types, is_hdf5_group, read_dataset, scale_matrix, to_number_array, to_scalar_number, to_string_array, } from './h5-utils';
|
|
21
21
|
import { read_vaspout_dos, read_vaspout_electronic } from './vaspout-electronic';
|
|
22
22
|
const FINAL_ION_TYPES = `results/positions/ion_types`;
|
|
23
23
|
const FINAL_ION_COUNTS = `results/positions/number_ion_types`;
|
|
@@ -279,6 +279,3 @@ export function parse_vaspout_h5_file(h5_file) {
|
|
|
279
279
|
},
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
|
-
export async function parse_vaspout_h5(buffer, filename) {
|
|
283
|
-
return with_h5_file(buffer, filename, parse_vaspout_h5_file);
|
|
284
|
-
}
|