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
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// Data type detection for JSON values -- determines which visualization component to use.
|
|
2
|
+
// Used by JsonBrowser and the file renderer to select visualization components.
|
|
3
|
+
import { build_path } from '../json-path';
|
|
4
|
+
import { is_optimade_raw } from '../structure/parse';
|
|
5
|
+
export { resolve_path } from '../json-path';
|
|
6
|
+
// Human-readable labels for badge display
|
|
7
|
+
export const TYPE_LABELS = {
|
|
8
|
+
structure: `Structure`,
|
|
9
|
+
fermi_surface: `Fermi Surface`,
|
|
10
|
+
band_grid: `Band Grid`,
|
|
11
|
+
convex_hull: `Convex Hull`,
|
|
12
|
+
volumetric: `Volumetric`,
|
|
13
|
+
phase_diagram: `Phase Diagram`,
|
|
14
|
+
band_structure: `Band Structure`,
|
|
15
|
+
dos: `DOS`,
|
|
16
|
+
bands_and_dos: `Bands + DOS`,
|
|
17
|
+
brillouin_zone: `Brillouin Zone`,
|
|
18
|
+
xrd: `XRD`,
|
|
19
|
+
table: `Table`,
|
|
20
|
+
plot: `Plot`,
|
|
21
|
+
};
|
|
22
|
+
// Badge colors per type (CSS color values)
|
|
23
|
+
export const TYPE_COLORS = {
|
|
24
|
+
structure: `#4fc3f7`,
|
|
25
|
+
fermi_surface: `#ab47bc`,
|
|
26
|
+
band_grid: `#7e57c2`,
|
|
27
|
+
convex_hull: `#66bb6a`,
|
|
28
|
+
volumetric: `#ffa726`,
|
|
29
|
+
phase_diagram: `#ef5350`,
|
|
30
|
+
band_structure: `#29b6f6`,
|
|
31
|
+
dos: `#26a69a`,
|
|
32
|
+
bands_and_dos: `#5c6bc0`,
|
|
33
|
+
brillouin_zone: `#8d6e63`,
|
|
34
|
+
xrd: `#ec407a`,
|
|
35
|
+
table: `#78909c`,
|
|
36
|
+
plot: `#7c3aed`,
|
|
37
|
+
};
|
|
38
|
+
// === Type Guards ===
|
|
39
|
+
// Narrows unknown to a non-array object record; used by every type guard below
|
|
40
|
+
const as_record = (obj) => obj && typeof obj === `object` && !Array.isArray(obj)
|
|
41
|
+
? obj
|
|
42
|
+
: null;
|
|
43
|
+
// Check that `key` on `data` is an Array with exactly `len` elements (or any length if omitted)
|
|
44
|
+
const has_array = (data, key, len) => {
|
|
45
|
+
const val = data[key];
|
|
46
|
+
return Array.isArray(val) && (len === undefined || val.length === len);
|
|
47
|
+
};
|
|
48
|
+
// Structure: must have non-empty `sites` array where first site has `species` + coordinates
|
|
49
|
+
function is_structure(obj) {
|
|
50
|
+
const data = as_record(obj);
|
|
51
|
+
if (!data || !has_array(data, `sites`))
|
|
52
|
+
return false;
|
|
53
|
+
const sites = data.sites;
|
|
54
|
+
if (sites.length === 0)
|
|
55
|
+
return false;
|
|
56
|
+
const first_site = as_record(sites[0]);
|
|
57
|
+
if (!first_site)
|
|
58
|
+
return false;
|
|
59
|
+
const has_species = Array.isArray(first_site.species) && first_site.species.length > 0;
|
|
60
|
+
return has_species && (Array.isArray(first_site.abc) || Array.isArray(first_site.xyz));
|
|
61
|
+
}
|
|
62
|
+
// FermiSurfaceData: pre-computed isosurfaces with reciprocal lattice info
|
|
63
|
+
function is_fermi_surface(obj) {
|
|
64
|
+
const data = as_record(obj);
|
|
65
|
+
if (!data)
|
|
66
|
+
return false;
|
|
67
|
+
return (has_array(data, `isosurfaces`) &&
|
|
68
|
+
has_array(data, `k_lattice`, 3) &&
|
|
69
|
+
typeof data.fermi_energy === `number` &&
|
|
70
|
+
(data.reciprocal_cell === `wigner_seitz` || data.reciprocal_cell === `parallelepiped`) &&
|
|
71
|
+
Boolean(as_record(data.metadata)));
|
|
72
|
+
}
|
|
73
|
+
// BandGridData: raw band energies on a k-grid (needs marching cubes extraction)
|
|
74
|
+
function is_band_grid(obj) {
|
|
75
|
+
const data = as_record(obj);
|
|
76
|
+
if (!data)
|
|
77
|
+
return false;
|
|
78
|
+
return (has_array(data, `energies`) &&
|
|
79
|
+
has_array(data, `k_grid`, 3) &&
|
|
80
|
+
has_array(data, `k_lattice`, 3) &&
|
|
81
|
+
typeof data.fermi_energy === `number` &&
|
|
82
|
+
typeof data.n_bands === `number` &&
|
|
83
|
+
typeof data.n_spins === `number`);
|
|
84
|
+
}
|
|
85
|
+
// ConvexHull entries: array of objects with `composition` (object) + energy field
|
|
86
|
+
// Accepts `energy`, `e_form_per_atom`, or `energy_per_atom` as the energy key
|
|
87
|
+
function is_convex_hull_entries(obj) {
|
|
88
|
+
if (!Array.isArray(obj) || obj.length < 2)
|
|
89
|
+
return false;
|
|
90
|
+
// Check first few entries to avoid false positives on random arrays
|
|
91
|
+
return obj.slice(0, 3).every((item) => {
|
|
92
|
+
const entry = as_record(item);
|
|
93
|
+
return (entry &&
|
|
94
|
+
as_record(entry.composition) &&
|
|
95
|
+
(typeof entry.energy === `number` ||
|
|
96
|
+
typeof entry.e_form_per_atom === `number` ||
|
|
97
|
+
typeof entry.energy_per_atom === `number`));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// VolumetricData: 3D scalar grid with lattice info
|
|
101
|
+
function is_volumetric(obj) {
|
|
102
|
+
const data = as_record(obj);
|
|
103
|
+
if (!data || !has_array(data, `grid`))
|
|
104
|
+
return false;
|
|
105
|
+
// grid must be a 3D array (array of arrays of arrays)
|
|
106
|
+
const grid = data.grid;
|
|
107
|
+
if (grid.length === 0)
|
|
108
|
+
return false;
|
|
109
|
+
const first_slice = grid[0];
|
|
110
|
+
if (!Array.isArray(first_slice) || !first_slice.length || !Array.isArray(first_slice[0]))
|
|
111
|
+
return false;
|
|
112
|
+
return (has_array(data, `grid_dims`, 3) &&
|
|
113
|
+
has_array(data, `lattice`, 3) &&
|
|
114
|
+
has_array(data, `origin`, 3) &&
|
|
115
|
+
Boolean(as_record(data.data_range)) &&
|
|
116
|
+
typeof data.periodic === `boolean`);
|
|
117
|
+
}
|
|
118
|
+
// PhaseDiagramData: binary phase diagram with components, regions, boundaries
|
|
119
|
+
function is_phase_diagram(obj) {
|
|
120
|
+
const data = as_record(obj);
|
|
121
|
+
if (!data)
|
|
122
|
+
return false;
|
|
123
|
+
if (!has_array(data, `components`, 2))
|
|
124
|
+
return false;
|
|
125
|
+
const [comp_a, comp_b] = data.components;
|
|
126
|
+
if (typeof comp_a !== `string` || typeof comp_b !== `string`)
|
|
127
|
+
return false;
|
|
128
|
+
return (has_array(data, `regions`) &&
|
|
129
|
+
has_array(data, `boundaries`) &&
|
|
130
|
+
has_array(data, `temperature_range`, 2));
|
|
131
|
+
}
|
|
132
|
+
// BandStructure: normalized format (qpoints, branches, bands, nb_bands)
|
|
133
|
+
// or pymatgen format (kpoints, branches, bands with spin keys, labels_dict)
|
|
134
|
+
function is_band_structure(obj) {
|
|
135
|
+
const data = as_record(obj);
|
|
136
|
+
if (!data)
|
|
137
|
+
return false;
|
|
138
|
+
if (!has_array(data, `branches`) || data.branches.length === 0) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (!as_record(data.labels_dict))
|
|
142
|
+
return false;
|
|
143
|
+
// Normalized format
|
|
144
|
+
if (has_array(data, `qpoints`) &&
|
|
145
|
+
has_array(data, `bands`) &&
|
|
146
|
+
typeof data.nb_bands === `number`)
|
|
147
|
+
return true;
|
|
148
|
+
// Pymatgen format: kpoints + bands object (not array) + efermi
|
|
149
|
+
if (has_array(data, `kpoints`) && as_record(data.bands)) {
|
|
150
|
+
return typeof data.efermi === `number`;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
// DOS: pymatgen CompleteDos format or normalized DosData
|
|
155
|
+
// CompleteDos: has energies, densities, efermi, and @class containing "Dos"
|
|
156
|
+
// DosData: has type ("phonon"|"electronic"), frequencies/energies, densities
|
|
157
|
+
function is_dos(obj) {
|
|
158
|
+
const data = as_record(obj);
|
|
159
|
+
if (!data)
|
|
160
|
+
return false;
|
|
161
|
+
const has_spectra = has_array(data, `energies`) || has_array(data, `frequencies`);
|
|
162
|
+
// pymatgen CompleteDos format
|
|
163
|
+
if (typeof data[`@class`] === `string` &&
|
|
164
|
+
data[`@class`].includes(`Dos`) &&
|
|
165
|
+
has_spectra &&
|
|
166
|
+
data.densities !== undefined)
|
|
167
|
+
return true;
|
|
168
|
+
// Normalized DosData format
|
|
169
|
+
if ((data.type === `phonon` || data.type === `electronic`) &&
|
|
170
|
+
has_spectra &&
|
|
171
|
+
has_array(data, `densities`))
|
|
172
|
+
return true;
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
// BandsAndDos: object containing both band_structure and dos data at the same level.
|
|
176
|
+
// Must be a focused wrapper (few keys), not a large object that happens to have both.
|
|
177
|
+
function is_bands_and_dos(obj) {
|
|
178
|
+
const data = as_record(obj);
|
|
179
|
+
if (!data)
|
|
180
|
+
return false;
|
|
181
|
+
const keys = Object.keys(data).filter((key) => !key.startsWith(`@`) && !key.startsWith(`_`));
|
|
182
|
+
// Wrapper format: { band_structure: {...}, dos: {...} } with few extra keys
|
|
183
|
+
const has_bands = as_record(data.band_structure) && is_band_structure(data.band_structure);
|
|
184
|
+
const has_dos_key = as_record(data.dos) && is_dos(data.dos);
|
|
185
|
+
if (has_bands && has_dos_key && keys.length <= 5)
|
|
186
|
+
return true;
|
|
187
|
+
// Combined-fields format: single object with both band structure and DOS fields mixed in
|
|
188
|
+
const has_bands_fields = has_array(data, `branches`) && as_record(data.labels_dict);
|
|
189
|
+
const has_dos_fields = (has_array(data, `energies`) || has_array(data, `frequencies`)) &&
|
|
190
|
+
data.densities !== undefined &&
|
|
191
|
+
(data.atom_dos !== undefined || data.spd_dos !== undefined);
|
|
192
|
+
return Boolean(has_bands_fields && has_dos_fields);
|
|
193
|
+
}
|
|
194
|
+
// BrillouinZone: reciprocal lattice data with optional k-path info
|
|
195
|
+
// Matches objects with a lattice that has reciprocal vectors (k_lattice or reciprocal_lattice)
|
|
196
|
+
// and optionally k-path points/labels for overlaying on the zone
|
|
197
|
+
function is_brillouin_zone(obj) {
|
|
198
|
+
const data = as_record(obj);
|
|
199
|
+
if (!data)
|
|
200
|
+
return false;
|
|
201
|
+
// Must have reciprocal lattice vectors (3x3 matrix)
|
|
202
|
+
const has_k_lattice = has_array(data, `k_lattice`, 3) || has_array(data, `reciprocal_lattice`, 3);
|
|
203
|
+
if (!has_k_lattice)
|
|
204
|
+
return false;
|
|
205
|
+
// Must have k-path or explicit BZ data to distinguish from Fermi surface data
|
|
206
|
+
// (Fermi surface also has k_lattice but additionally has isosurfaces)
|
|
207
|
+
if (has_array(data, `isosurfaces`))
|
|
208
|
+
return false; // that's a Fermi surface, not a plain BZ
|
|
209
|
+
// Accept if it has k_path labels/points, or a structure with lattice
|
|
210
|
+
return (has_array(data, `k_path`) ||
|
|
211
|
+
has_array(data, `k_points`) ||
|
|
212
|
+
Boolean(as_record(data.k_labels)) ||
|
|
213
|
+
Boolean(as_record(data.labels_dict)) ||
|
|
214
|
+
data.bz_order !== undefined);
|
|
215
|
+
}
|
|
216
|
+
// XRD pattern: x + y arrays of equal length (2-theta angles vs intensities)
|
|
217
|
+
// with optional hkls (Miller indices) and d_hkls (d-spacings)
|
|
218
|
+
function is_xrd_pattern(obj) {
|
|
219
|
+
const data = as_record(obj);
|
|
220
|
+
if (!data)
|
|
221
|
+
return false;
|
|
222
|
+
if (!has_array(data, `x`) || !has_array(data, `y`))
|
|
223
|
+
return false;
|
|
224
|
+
const x_arr = data.x;
|
|
225
|
+
const y_arr = data.y;
|
|
226
|
+
if (x_arr.length !== y_arr.length || x_arr.length === 0)
|
|
227
|
+
return false;
|
|
228
|
+
// Must have numeric x/y values
|
|
229
|
+
if (typeof x_arr[0] !== `number` || typeof y_arr[0] !== `number`)
|
|
230
|
+
return false;
|
|
231
|
+
// Distinguish from generic scatter data: XRD patterns typically have hkls or d_hkls,
|
|
232
|
+
// or have @class containing "Xrd"
|
|
233
|
+
return (has_array(data, `hkls`) ||
|
|
234
|
+
has_array(data, `d_hkls`) ||
|
|
235
|
+
(typeof data[`@class`] === `string` && data[`@class`].includes(`Xrd`)) ||
|
|
236
|
+
typeof data.wavelength === `number`);
|
|
237
|
+
}
|
|
238
|
+
// Tabular data: array of objects with consistent keys (row-based table format)
|
|
239
|
+
// or object with parallel arrays (column-based format)
|
|
240
|
+
function is_tabular_data(obj) {
|
|
241
|
+
// Row-based: array of objects with string keys and numeric/string values
|
|
242
|
+
if (Array.isArray(obj) && obj.length >= 3) {
|
|
243
|
+
const first = as_record(obj[0]);
|
|
244
|
+
const second = as_record(obj[1]);
|
|
245
|
+
if (!first || !second)
|
|
246
|
+
return false;
|
|
247
|
+
const first_keys = Object.keys(first);
|
|
248
|
+
if (first_keys.length < 2)
|
|
249
|
+
return false;
|
|
250
|
+
// Check that rows have consistent keys and mostly numeric/string values
|
|
251
|
+
const second_keys = Object.keys(second);
|
|
252
|
+
const overlap = first_keys.filter((key) => second_keys.includes(key));
|
|
253
|
+
if (overlap.length < first_keys.length * 0.5)
|
|
254
|
+
return false;
|
|
255
|
+
// At least some values should be numbers (not just metadata objects)
|
|
256
|
+
const num_count = first_keys.filter((key) => typeof first[key] === `number`).length;
|
|
257
|
+
return num_count >= 1;
|
|
258
|
+
}
|
|
259
|
+
// Column-based: object where multiple values are equal-length arrays
|
|
260
|
+
const data = as_record(obj);
|
|
261
|
+
if (!data)
|
|
262
|
+
return false;
|
|
263
|
+
const entries = Object.entries(data);
|
|
264
|
+
if (entries.length < 2)
|
|
265
|
+
return false;
|
|
266
|
+
const array_entries = entries.filter(([, val]) => Array.isArray(val) && val.length > 0);
|
|
267
|
+
if (array_entries.length < 2)
|
|
268
|
+
return false;
|
|
269
|
+
// Check that arrays have consistent lengths
|
|
270
|
+
const lengths = array_entries.map(([, val]) => val.length);
|
|
271
|
+
const first_len = lengths[0];
|
|
272
|
+
if (!lengths.every((len) => len === first_len))
|
|
273
|
+
return false;
|
|
274
|
+
// At least one column must contain numbers
|
|
275
|
+
return array_entries.some(([, val]) => typeof val[0] === `number`);
|
|
276
|
+
}
|
|
277
|
+
// Plottable data: tabular data with at least 2 numeric columns (enough for a scatter plot).
|
|
278
|
+
// Samples multiple rows/elements to handle leading nulls.
|
|
279
|
+
export function is_plottable_data(obj) {
|
|
280
|
+
if (!is_tabular_data(obj))
|
|
281
|
+
return false;
|
|
282
|
+
if (Array.isArray(obj)) {
|
|
283
|
+
const sample = obj.slice(0, 10).map(as_record).filter(Boolean);
|
|
284
|
+
if (sample.length === 0)
|
|
285
|
+
return false;
|
|
286
|
+
const all_keys = new Set(sample.flatMap(Object.keys));
|
|
287
|
+
const num_cols = [...all_keys].filter((key) => sample.some((row) => typeof row[key] === `number`)).length;
|
|
288
|
+
return num_cols >= 2;
|
|
289
|
+
}
|
|
290
|
+
const data = as_record(obj);
|
|
291
|
+
if (!data)
|
|
292
|
+
return false;
|
|
293
|
+
const array_entries = Object.entries(data).filter(([, val]) => Array.isArray(val) && val.length > 0);
|
|
294
|
+
const num_cols = array_entries.filter(([, val]) => val.some((elem) => typeof elem === `number`)).length;
|
|
295
|
+
return num_cols >= 2;
|
|
296
|
+
}
|
|
297
|
+
// === Main Detection Function ===
|
|
298
|
+
// Detect the visualization type for a given JSON value.
|
|
299
|
+
// Returns the type if the value matches a known format, or null if not renderable.
|
|
300
|
+
// Checks are ordered from most specific to least specific to minimize false positives:
|
|
301
|
+
// OPTIMADE before generic structure, combined bands+DOS before individual band/dos,
|
|
302
|
+
// structure late (structures are common building blocks inside other data types),
|
|
303
|
+
// and generic tabular data last.
|
|
304
|
+
export function detect_view_type(value) {
|
|
305
|
+
if (value == null)
|
|
306
|
+
return null;
|
|
307
|
+
if (as_record(value) && is_optimade_raw(value))
|
|
308
|
+
return `structure`;
|
|
309
|
+
if (is_fermi_surface(value))
|
|
310
|
+
return `fermi_surface`;
|
|
311
|
+
if (is_band_grid(value))
|
|
312
|
+
return `band_grid`;
|
|
313
|
+
if (is_phase_diagram(value))
|
|
314
|
+
return `phase_diagram`;
|
|
315
|
+
if (is_bands_and_dos(value))
|
|
316
|
+
return `bands_and_dos`;
|
|
317
|
+
if (is_band_structure(value))
|
|
318
|
+
return `band_structure`;
|
|
319
|
+
if (is_dos(value))
|
|
320
|
+
return `dos`;
|
|
321
|
+
if (is_brillouin_zone(value))
|
|
322
|
+
return `brillouin_zone`;
|
|
323
|
+
if (is_xrd_pattern(value))
|
|
324
|
+
return `xrd`;
|
|
325
|
+
if (is_volumetric(value))
|
|
326
|
+
return `volumetric`;
|
|
327
|
+
if (is_structure(value))
|
|
328
|
+
return `structure`;
|
|
329
|
+
if (is_convex_hull_entries(value))
|
|
330
|
+
return `convex_hull`;
|
|
331
|
+
if (is_tabular_data(value))
|
|
332
|
+
return `table`;
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
// Recursively scan a JSON object to find all paths that contain renderable data.
|
|
336
|
+
// Returns a Map of JSON path strings to their detected type.
|
|
337
|
+
// Used to show badges on JsonTree nodes indicating which subtrees contain visualizable data.
|
|
338
|
+
export function scan_renderable_paths(obj, prefix = ``, max_depth = 10) {
|
|
339
|
+
const results = new Map();
|
|
340
|
+
const visited = new WeakSet();
|
|
341
|
+
function walk(value, path, depth) {
|
|
342
|
+
if (depth > max_depth)
|
|
343
|
+
return;
|
|
344
|
+
if (value == null)
|
|
345
|
+
return;
|
|
346
|
+
if (typeof value !== `object`)
|
|
347
|
+
return;
|
|
348
|
+
// Circular reference protection
|
|
349
|
+
const obj_ref = value;
|
|
350
|
+
if (visited.has(obj_ref))
|
|
351
|
+
return;
|
|
352
|
+
visited.add(obj_ref);
|
|
353
|
+
// Check if this value itself is renderable
|
|
354
|
+
const detected_type = detect_view_type(value);
|
|
355
|
+
if (detected_type) {
|
|
356
|
+
results.set(path, { type: detected_type, label: TYPE_LABELS[detected_type] });
|
|
357
|
+
// If tabular data is also plottable, register a plot badge too
|
|
358
|
+
if (detected_type === `table` && is_plottable_data(value)) {
|
|
359
|
+
const plot_path = path ? `${path}\u0000plot` : `\u0000plot`;
|
|
360
|
+
results.set(plot_path, { type: `plot`, label: TYPE_LABELS.plot });
|
|
361
|
+
}
|
|
362
|
+
// Don't recurse into renderable objects -- their children are part of the data
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
// Recurse into children
|
|
366
|
+
if (Array.isArray(value)) {
|
|
367
|
+
// For arrays, only scan first few elements to avoid huge arrays
|
|
368
|
+
const scan_count = Math.min(value.length, 20);
|
|
369
|
+
for (let idx = 0; idx < scan_count; idx++) {
|
|
370
|
+
walk(value[idx], build_path(path, idx), depth + 1);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
for (const [key, child_value] of Object.entries(value)) {
|
|
375
|
+
walk(child_value, build_path(path, key), depth + 1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
walk(obj, prefix, 0);
|
|
380
|
+
return results;
|
|
381
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const normalize_browser_supported_filename: (filename: string) => string | null;
|
|
2
|
+
export declare const should_encode_filename_as_base64: (filename: string) => boolean;
|
|
3
|
+
export declare const is_matterviz_filename: (filename: unknown) => boolean;
|
|
4
|
+
export declare const is_auto_renderable_filename: (filename: unknown) => boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { COMPRESSION_EXTENSIONS_REGEX, CONFIG_DIRS_REGEX, TRAJ_KEYWORDS_REGEX, } from '../constants';
|
|
2
|
+
import { FERMI_FILE_RE, VOLUMETRIC_EXT_RE, VOLUMETRIC_VASP_RE } from './types';
|
|
3
|
+
import { detect_compression_format, is_browser_decompressible_format, } from '../io/decompress';
|
|
4
|
+
import { is_structure_file } from '../structure/format-detect';
|
|
5
|
+
import { is_trajectory_file } from '../trajectory/format-detect';
|
|
6
|
+
// Return the browser-visible filename after removing one supported compression
|
|
7
|
+
// wrapper. Nested and unsupported wrappers are deliberately rejected because the
|
|
8
|
+
// parser only decompresses one layer.
|
|
9
|
+
export const normalize_browser_supported_filename = (filename) => {
|
|
10
|
+
const format = detect_compression_format(filename);
|
|
11
|
+
if (!format)
|
|
12
|
+
return filename;
|
|
13
|
+
if (!is_browser_decompressible_format(format))
|
|
14
|
+
return null;
|
|
15
|
+
const normalized = filename.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
16
|
+
return detect_compression_format(normalized) ? null : normalized;
|
|
17
|
+
};
|
|
18
|
+
export const should_encode_filename_as_base64 = (filename) => detect_compression_format(filename) !== null || /\.(?:traj|h5|hdf5)$/i.test(filename);
|
|
19
|
+
const normalize_eligible_filename = (filename) => {
|
|
20
|
+
if (typeof filename !== `string` || !filename || CONFIG_DIRS_REGEX.test(filename))
|
|
21
|
+
return null;
|
|
22
|
+
return normalize_browser_supported_filename(filename.split(/[\\/]/).pop() ?? ``);
|
|
23
|
+
};
|
|
24
|
+
// Broad: MatterViz can open/view this file (JSON/YAML structures, keyword trajs, …).
|
|
25
|
+
export const is_matterviz_filename = (filename) => {
|
|
26
|
+
const normalized = normalize_eligible_filename(filename);
|
|
27
|
+
if (normalized === null)
|
|
28
|
+
return false;
|
|
29
|
+
return (FERMI_FILE_RE.test(normalized) ||
|
|
30
|
+
VOLUMETRIC_EXT_RE.test(normalized) ||
|
|
31
|
+
VOLUMETRIC_VASP_RE.test(normalized) ||
|
|
32
|
+
is_structure_file(normalized) ||
|
|
33
|
+
is_trajectory_file(normalized));
|
|
34
|
+
};
|
|
35
|
+
// Conservative auto-open list: only unambiguous structure / trajectory / volumetric /
|
|
36
|
+
// Fermi filenames. No JSON/YAML/XML, no keyword+.log/.out/.dat/.data heuristics.
|
|
37
|
+
const AUTO_RENDER_EXT_RE = /\.(?:cif|mcif|mmcif|xyz|extxyz|poscar|vasp|cube|pdb|mol|mol2|sdf|lmp|dump|traj|xtc|lammpstrj)$/i;
|
|
38
|
+
const AUTO_RENDER_VASP_NAME_RE = /(?:^|[\\/_.-])(?:poscar|contcar|xdatcar)(?:[\\/_.-]|$)/i;
|
|
39
|
+
export const is_auto_renderable_filename = (filename) => {
|
|
40
|
+
const normalized = normalize_eligible_filename(filename);
|
|
41
|
+
if (normalized === null)
|
|
42
|
+
return false;
|
|
43
|
+
if (FERMI_FILE_RE.test(normalized) ||
|
|
44
|
+
VOLUMETRIC_EXT_RE.test(normalized) ||
|
|
45
|
+
VOLUMETRIC_VASP_RE.test(normalized) ||
|
|
46
|
+
AUTO_RENDER_VASP_NAME_RE.test(normalized) ||
|
|
47
|
+
AUTO_RENDER_EXT_RE.test(normalized)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
// HDF5 only when the name clearly marks a trajectory
|
|
51
|
+
return (/\.(?:h5|hdf5)$/i.test(normalized) &&
|
|
52
|
+
(/vaspout/i.test(normalized) || TRAJ_KEYWORDS_REGEX.test(normalized)));
|
|
53
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DefaultSettings } from '../settings';
|
|
2
|
+
import type { ThemeName } from '../theme';
|
|
3
|
+
export interface FileData {
|
|
4
|
+
filename: string;
|
|
5
|
+
content: string;
|
|
6
|
+
is_base64: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface WebviewBootstrapData {
|
|
9
|
+
data: FileData;
|
|
10
|
+
theme: ThemeName;
|
|
11
|
+
defaults?: DefaultSettings;
|
|
12
|
+
moyo_wasm_url?: string;
|
|
13
|
+
}
|
|
14
|
+
type WatchedFileContext = {
|
|
15
|
+
file_path: string;
|
|
16
|
+
request_id?: string;
|
|
17
|
+
filename?: string;
|
|
18
|
+
frame_index?: number;
|
|
19
|
+
};
|
|
20
|
+
type HostFileRequest = {
|
|
21
|
+
request_id: string;
|
|
22
|
+
file_path: string;
|
|
23
|
+
};
|
|
24
|
+
export type FileChangeMessage = WatchedFileContext & ({
|
|
25
|
+
command: `fileUpdated`;
|
|
26
|
+
data: FileData;
|
|
27
|
+
theme?: ThemeName;
|
|
28
|
+
} | {
|
|
29
|
+
command: `fileDeleted`;
|
|
30
|
+
});
|
|
31
|
+
export type WebviewToHostMessage = {
|
|
32
|
+
command: `info` | `error`;
|
|
33
|
+
text: string;
|
|
34
|
+
} | ({
|
|
35
|
+
command: `request_large_file`;
|
|
36
|
+
} & HostFileRequest) | ({
|
|
37
|
+
command: `request_frame`;
|
|
38
|
+
frame_index: number;
|
|
39
|
+
} & HostFileRequest) | {
|
|
40
|
+
command: `saveAs`;
|
|
41
|
+
filename: string;
|
|
42
|
+
content: string;
|
|
43
|
+
is_binary?: boolean;
|
|
44
|
+
} | ({
|
|
45
|
+
command: `startWatching`;
|
|
46
|
+
} & WatchedFileContext) | {
|
|
47
|
+
command: `stopWatching`;
|
|
48
|
+
file_path: string;
|
|
49
|
+
};
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface LargeFileMarker {
|
|
2
|
+
file_path: string;
|
|
3
|
+
file_size: number;
|
|
4
|
+
}
|
|
5
|
+
export declare const format_large_file_marker: ({ file_path, file_size, }: LargeFileMarker) => string;
|
|
6
|
+
export declare const parse_large_file_marker: (content: string) => LargeFileMarker | null;
|
|
7
|
+
export type HostTransferRejectReason = `file-too-large` | `unsupported-compression` | `unsupported-large-format`;
|
|
8
|
+
export type HostFileTransferPlan = {
|
|
9
|
+
kind: `inline`;
|
|
10
|
+
is_base64: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
kind: `marker`;
|
|
13
|
+
content: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: `reject`;
|
|
16
|
+
reason: HostTransferRejectReason;
|
|
17
|
+
max_file_size?: number;
|
|
18
|
+
};
|
|
19
|
+
export interface HostFileTransferInput extends LargeFileMarker {
|
|
20
|
+
filename: string;
|
|
21
|
+
large_file_threshold: number;
|
|
22
|
+
max_file_size: number;
|
|
23
|
+
max_text_file_size: number;
|
|
24
|
+
}
|
|
25
|
+
export declare const plan_host_file_transfer: ({ filename, file_path, file_size, large_file_threshold, max_file_size, max_text_file_size, }: HostFileTransferInput) => HostFileTransferPlan;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { normalize_browser_supported_filename, should_encode_filename_as_base64, } from './eligibility';
|
|
2
|
+
import { indexed_trajectory_format, is_indexable_trajectory_filename, } from '../trajectory/format-detect';
|
|
3
|
+
export const format_large_file_marker = ({ file_path, file_size, }) => {
|
|
4
|
+
if (!file_path || !Number.isSafeInteger(file_size) || file_size < 0)
|
|
5
|
+
throw new Error(`Invalid large file marker data`);
|
|
6
|
+
return `LARGE_FILE:${file_path}:${file_size}`;
|
|
7
|
+
};
|
|
8
|
+
export const parse_large_file_marker = (content) => {
|
|
9
|
+
const prefix = `LARGE_FILE:`;
|
|
10
|
+
if (!content.startsWith(prefix))
|
|
11
|
+
return null;
|
|
12
|
+
const separator_idx = content.lastIndexOf(`:`);
|
|
13
|
+
const file_path = content.slice(prefix.length, separator_idx);
|
|
14
|
+
const size_text = content.slice(separator_idx + 1);
|
|
15
|
+
const file_size = Number(size_text);
|
|
16
|
+
if (!file_path || !/^\d+$/.test(size_text) || !Number.isSafeInteger(file_size))
|
|
17
|
+
throw new Error(`Malformed large file marker`);
|
|
18
|
+
return { file_path, file_size };
|
|
19
|
+
};
|
|
20
|
+
export const plan_host_file_transfer = ({ filename, file_path, file_size, large_file_threshold, max_file_size, max_text_file_size, }) => {
|
|
21
|
+
const normalized_filename = normalize_browser_supported_filename(filename);
|
|
22
|
+
const is_large_file = file_size > large_file_threshold;
|
|
23
|
+
const trajectory_format = normalized_filename !== null && is_indexable_trajectory_filename(normalized_filename)
|
|
24
|
+
? indexed_trajectory_format(normalized_filename)
|
|
25
|
+
: null;
|
|
26
|
+
const format_max_file_size = is_large_file && trajectory_format === `xyz`
|
|
27
|
+
? Math.min(max_text_file_size, max_file_size)
|
|
28
|
+
: max_file_size;
|
|
29
|
+
if (file_size > format_max_file_size) {
|
|
30
|
+
return { kind: `reject`, reason: `file-too-large`, max_file_size: format_max_file_size };
|
|
31
|
+
}
|
|
32
|
+
if (!is_large_file)
|
|
33
|
+
return { kind: `inline`, is_base64: should_encode_filename_as_base64(filename) };
|
|
34
|
+
if (normalized_filename === null)
|
|
35
|
+
return { kind: `reject`, reason: `unsupported-compression` };
|
|
36
|
+
if (!trajectory_format)
|
|
37
|
+
return { kind: `reject`, reason: `unsupported-large-format` };
|
|
38
|
+
return {
|
|
39
|
+
kind: `marker`,
|
|
40
|
+
content: format_large_file_marker({ file_path, file_size }),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import '../app.css';
|
|
2
|
+
import '../theme/themes.mjs';
|
|
3
|
+
import type { FrameIndex, FrameLoader, TrajectoryFrame, TrajectoryMetadata } from '../trajectory';
|
|
4
|
+
import type { WebviewBootstrapData } from './host-protocol';
|
|
5
|
+
import type { ParseResult } from './parse';
|
|
6
|
+
export type MatterVizData = WebviewBootstrapData;
|
|
7
|
+
export interface MatterVizApp {
|
|
8
|
+
$on?(type: string, callback: (event: Event) => void): () => void;
|
|
9
|
+
$set?(props: Partial<Record<string, unknown>>): void;
|
|
10
|
+
}
|
|
11
|
+
export interface DisplayOptions {
|
|
12
|
+
initial_step_idx?: number;
|
|
13
|
+
on_step_change?: (step_idx: number, total_frames: number) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare class VSCodeFrameLoader implements FrameLoader {
|
|
16
|
+
private readonly file_path;
|
|
17
|
+
private readonly vscode_api;
|
|
18
|
+
constructor(file_path: string, vscode_api: VSCodeAPI);
|
|
19
|
+
load_frame(_data: string | ArrayBuffer, frame_index: number, timeout?: number): Promise<TrajectoryFrame | null>;
|
|
20
|
+
get_total_frames(): Promise<number>;
|
|
21
|
+
build_frame_index(): Promise<FrameIndex[]>;
|
|
22
|
+
extract_plot_metadata(): Promise<TrajectoryMetadata[]>;
|
|
23
|
+
}
|
|
24
|
+
export interface VSCodeAPI {
|
|
25
|
+
postMessage(message: unknown): void;
|
|
26
|
+
}
|
|
27
|
+
declare global {
|
|
28
|
+
interface Window {
|
|
29
|
+
matterviz_data?: MatterVizData;
|
|
30
|
+
initializeMatterViz?: () => Promise<MatterVizApp | null>;
|
|
31
|
+
cleanupMatterViz?: () => Promise<void>;
|
|
32
|
+
download?: (data: string | Blob, filename: string) => void;
|
|
33
|
+
}
|
|
34
|
+
var matterviz_data: MatterVizData | undefined;
|
|
35
|
+
function acquireVsCodeApi(): VSCodeAPI;
|
|
36
|
+
}
|
|
37
|
+
export declare const setup_vscode_download: () => void;
|
|
38
|
+
type DisplayResult = ParseResult & {
|
|
39
|
+
streaming_info?: {
|
|
40
|
+
file_path: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare const create_display: (container: HTMLElement, result: DisplayResult, display_options?: DisplayOptions) => MatterVizApp;
|
|
44
|
+
export {};
|