matterviz 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FilePicker.svelte +37 -20
- package/dist/Icon.svelte +2 -2
- package/dist/app.css +29 -0
- package/dist/brillouin/BrillouinZone.svelte +19 -61
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneExportPane.svelte +12 -20
- package/dist/brillouin/BrillouinZoneScene.svelte +2 -2
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +192 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +677 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2688 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +33 -0
- package/dist/chempot-diagram/compute.d.ts +38 -0
- package/dist/chempot-diagram/compute.js +650 -0
- package/dist/chempot-diagram/index.d.ts +5 -0
- package/dist/chempot-diagram/index.js +5 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +37 -0
- package/dist/chempot-diagram/types.d.ts +83 -0
- package/dist/chempot-diagram/types.js +27 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +4 -0
- package/dist/composition/BarChart.svelte +13 -22
- package/dist/composition/BubbleChart.svelte +5 -3
- package/dist/composition/FormulaFilter.svelte +586 -94
- package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
- package/dist/composition/PieChart.svelte +43 -18
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull.svelte +4 -2
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +13 -44
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +16 -7
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +17 -7
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullStats.svelte +701 -226
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +1 -0
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +36 -0
- package/dist/convex-hull/helpers.d.ts +1 -1
- package/dist/convex-hull/helpers.js +2 -4
- package/dist/convex-hull/index.d.ts +1 -0
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +106 -17
- package/dist/convex-hull/types.d.ts +5 -0
- package/dist/convex-hull/types.js +5 -0
- package/dist/coordination/CoordinationBarPlot.svelte +29 -46
- package/dist/element/BohrAtom.svelte +1 -1
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/fermi-surface/FermiSurface.svelte +20 -64
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/parse.js +16 -22
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1273 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +171 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +31 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +111 -0
- package/dist/icons.js +111 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/io/export.js +15 -3
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +2 -2
- package/dist/io/index.js +2 -112
- package/dist/io/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +118 -0
- package/dist/isosurface/Isosurface.svelte +101 -45
- package/dist/isosurface/IsosurfaceControls.svelte +19 -0
- package/dist/isosurface/parse.js +73 -30
- package/dist/isosurface/slice.d.ts +2 -1
- package/dist/isosurface/slice.js +3 -3
- package/dist/isosurface/types.d.ts +13 -1
- package/dist/isosurface/types.js +98 -0
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +1 -0
- package/dist/layout/InfoTag.svelte +62 -62
- package/dist/layout/SubpageGrid.svelte +74 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +83 -85
- package/dist/layout/json-tree/JsonTree.svelte +20 -19
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +196 -116
- package/dist/layout/json-tree/types.d.ts +10 -2
- package/dist/layout/json-tree/utils.d.ts +2 -0
- package/dist/layout/json-tree/utils.js +33 -0
- package/dist/math.d.ts +7 -0
- package/dist/math.js +358 -7
- package/dist/overlays/ContextMenu.svelte +3 -2
- package/dist/overlays/DraggablePane.svelte +163 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +232 -77
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +32 -11
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +103 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +102 -95
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +7 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +100 -26
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +865 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +7 -4
- package/dist/phase-diagram/utils.js +149 -59
- package/dist/plot/AxisLabel.svelte +26 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +473 -228
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +3 -2
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +54 -54
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ColorScaleSelect.svelte +1 -1
- package/dist/plot/ElementScatter.svelte +3 -2
- package/dist/plot/FillArea.svelte +4 -1
- package/dist/plot/Histogram.svelte +320 -230
- package/dist/plot/Histogram.svelte.d.ts +2 -2
- package/dist/plot/HistogramControls.svelte +29 -10
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +2 -2
- package/dist/plot/PlotControls.svelte +109 -27
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +1 -1
- package/dist/plot/PortalSelect.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferencePlane.svelte +1 -3
- package/dist/plot/ScatterPlot.svelte +343 -209
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +203 -250
- package/dist/plot/ScatterPlot3DScene.svelte +4 -7
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +95 -55
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ZeroLines.svelte +44 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +21 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/index.d.ts +6 -2
- package/dist/plot/index.js +6 -2
- package/dist/plot/interactions.d.ts +8 -10
- package/dist/plot/interactions.js +2 -3
- package/dist/plot/layout.d.ts +7 -1
- package/dist/plot/layout.js +12 -4
- package/dist/plot/reference-line.d.ts +4 -21
- package/dist/plot/reference-line.js +7 -81
- package/dist/plot/types.d.ts +42 -17
- package/dist/plot/types.js +10 -0
- package/dist/plot/utils/label-placement.js +13 -10
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +55 -66
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +17 -3
- package/dist/spectral/Bands.svelte +515 -143
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +65 -9
- package/dist/spectral/types.d.ts +2 -0
- package/dist/structure/AtomLegend.svelte +29 -8
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CellSelect.svelte +92 -22
- package/dist/structure/Structure.svelte +108 -118
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +25 -22
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +7 -1
- package/dist/structure/StructureScene.svelte +104 -66
- package/dist/structure/StructureScene.svelte.d.ts +2 -1
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +38 -25
- package/dist/structure/export.js +10 -7
- package/dist/structure/ferrox-wasm-types.d.ts +3 -2
- package/dist/structure/ferrox-wasm-types.js +0 -3
- package/dist/structure/ferrox-wasm.d.ts +3 -2
- package/dist/structure/ferrox-wasm.js +1 -2
- package/dist/structure/index.d.ts +6 -0
- package/dist/structure/index.js +22 -0
- package/dist/structure/parse.js +19 -16
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +102 -0
- package/dist/structure/validation.js +6 -3
- package/dist/symmetry/SymmetryStats.svelte +18 -4
- package/dist/symmetry/WyckoffTable.svelte +18 -10
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +83 -18
- package/dist/table/HeatmapTable.svelte +425 -65
- package/dist/table/HeatmapTable.svelte.d.ts +12 -1
- package/dist/table/ToggleMenu.svelte +2 -0
- package/dist/table/index.d.ts +2 -0
- package/dist/trajectory/Trajectory.svelte +147 -145
- package/dist/trajectory/TrajectoryExportPane.svelte +13 -9
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +3 -5
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +339 -0
- package/dist/trajectory/helpers.d.ts +15 -0
- package/dist/trajectory/helpers.js +187 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +11 -4
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +76 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +121 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +304 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +169 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +65 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +109 -0
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +4 -0
- package/dist/xrd/XrdPlot.svelte +6 -4
- package/dist/xrd/calc-xrd.js +0 -1
- package/package.json +30 -24
- package/readme.md +4 -4
- package/dist/trajectory/parse.d.ts +0 -42
- package/dist/trajectory/parse.js +0 -1267
- /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
|
@@ -17,6 +17,7 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
17
17
|
default_num_format?: string;
|
|
18
18
|
show_heatmap?: boolean;
|
|
19
19
|
heatmap_class?: string;
|
|
20
|
+
onrowclick?: (event: MouseEvent | KeyboardEvent, row: RowData) => void;
|
|
20
21
|
onrowdblclick?: (event: MouseEvent, row: RowData) => void;
|
|
21
22
|
column_order?: string[];
|
|
22
23
|
export_data?: ExportData;
|
|
@@ -27,12 +28,22 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
27
28
|
selected_rows?: RowData[];
|
|
28
29
|
hidden_columns?: string[];
|
|
29
30
|
scroll_style?: string;
|
|
31
|
+
root_style?: string;
|
|
30
32
|
onsort?: (column: string, dir: `asc` | `desc`) => Promise<RowData[]>;
|
|
31
33
|
onsorterror?: (error: unknown, column: string, dir: `asc` | `desc`) => void;
|
|
32
34
|
loading?: boolean;
|
|
33
35
|
sort_data?: boolean;
|
|
34
36
|
heatmap_opacity?: number;
|
|
37
|
+
empty_message?: string;
|
|
38
|
+
show_row_numbers?: boolean;
|
|
39
|
+
allow_better_toggle?: boolean;
|
|
40
|
+
show_controls?: boolean;
|
|
41
|
+
controls_open?: boolean;
|
|
42
|
+
header_cell?: Snippet<[{
|
|
43
|
+
col: Label;
|
|
44
|
+
}]>;
|
|
45
|
+
footer?: Snippet;
|
|
35
46
|
};
|
|
36
|
-
declare const HeatmapTable: import("svelte").Component<$$ComponentProps, {}, "sort" | "data" | "loading" | "show_heatmap" | "column_order" | "selected_rows" | "hidden_columns" | "heatmap_opacity">;
|
|
47
|
+
declare const HeatmapTable: import("svelte").Component<$$ComponentProps, {}, "sort" | "data" | "show_controls" | "controls_open" | "loading" | "show_heatmap" | "column_order" | "selected_rows" | "hidden_columns" | "heatmap_opacity">;
|
|
37
48
|
type HeatmapTable = ReturnType<typeof HeatmapTable>;
|
|
38
49
|
export default HeatmapTable;
|
|
@@ -69,6 +69,8 @@ function toggle_section(name) {
|
|
|
69
69
|
: [...collapsed_sections, name];
|
|
70
70
|
}
|
|
71
71
|
function toggle_column_visibility(col, event) {
|
|
72
|
+
if (!(event.target instanceof HTMLInputElement))
|
|
73
|
+
return;
|
|
72
74
|
col.visible = event.target.checked;
|
|
73
75
|
columns = [...columns]; // trigger reactivity on parent binding
|
|
74
76
|
}
|
package/dist/table/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type Label = {
|
|
|
22
22
|
sticky?: boolean;
|
|
23
23
|
visible?: boolean;
|
|
24
24
|
sortable?: boolean;
|
|
25
|
+
show_sort_indicator?: boolean;
|
|
25
26
|
disabled?: boolean;
|
|
26
27
|
style?: string;
|
|
27
28
|
cell_style?: string;
|
|
@@ -51,6 +52,7 @@ export type InitialSort = string | {
|
|
|
51
52
|
};
|
|
52
53
|
export type Pagination = boolean | {
|
|
53
54
|
page_size?: number;
|
|
55
|
+
page_sizes?: number[];
|
|
54
56
|
};
|
|
55
57
|
export type Search = boolean | {
|
|
56
58
|
placeholder?: string;
|
|
@@ -140,8 +140,12 @@ let extended_config = $derived.by(() => {
|
|
|
140
140
|
});
|
|
141
141
|
// Plot series state (not derived so we can update on legend toggle)
|
|
142
142
|
let plot_series = $state([]);
|
|
143
|
+
// Prevent circular updates when syncing legend toggles back to bindable visible_properties.
|
|
144
|
+
let syncing_visible_properties = false;
|
|
143
145
|
// Regenerate plot series when trajectory, config, or visible_properties change
|
|
144
146
|
$effect(() => {
|
|
147
|
+
if (syncing_visible_properties)
|
|
148
|
+
return;
|
|
145
149
|
const keys_set = visible_properties ? new Set(visible_properties) : undefined;
|
|
146
150
|
if (trajectory?.plot_metadata) {
|
|
147
151
|
plot_series = generate_streaming_plot_series(trajectory.plot_metadata, {
|
|
@@ -164,20 +168,21 @@ $effect(() => {
|
|
|
164
168
|
if (!plot_series.length)
|
|
165
169
|
return;
|
|
166
170
|
// Extract property keys from visible series metadata
|
|
167
|
-
const visible_keys = plot_series
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.map((srs) => {
|
|
171
|
+
const visible_keys = plot_series.flatMap((srs) => {
|
|
172
|
+
if (!srs.visible)
|
|
173
|
+
return [];
|
|
171
174
|
const metadata = Array.isArray(srs.metadata) ? srs.metadata[0] : srs.metadata;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
const key = metadata?.property_key;
|
|
176
|
+
return key ? [key] : [];
|
|
177
|
+
});
|
|
175
178
|
// Only update if changed (use untrack to avoid circular dependency)
|
|
176
179
|
const current = untrack(() => visible_properties) || [];
|
|
177
180
|
const has_changed = visible_keys.length !== current.length ||
|
|
178
181
|
!visible_keys.every((key, idx) => key === current[idx]);
|
|
179
182
|
if (has_changed) {
|
|
183
|
+
syncing_visible_properties = true;
|
|
180
184
|
visible_properties = visible_keys;
|
|
185
|
+
queueMicrotask(() => (syncing_visible_properties = false));
|
|
181
186
|
}
|
|
182
187
|
});
|
|
183
188
|
// Handler for legend toggle - updates plot_series state
|
|
@@ -194,7 +199,7 @@ let y_axis_labels = $derived(generate_axis_labels(plot_series));
|
|
|
194
199
|
let y_axis = $derived({
|
|
195
200
|
label: y_axis_labels.y1,
|
|
196
201
|
format: `.2~s`,
|
|
197
|
-
label_shift: { y:
|
|
202
|
+
label_shift: { y: 10 },
|
|
198
203
|
});
|
|
199
204
|
let y2_axis = $derived({
|
|
200
205
|
label: y_axis_labels.y2,
|
|
@@ -960,7 +965,7 @@ let fullscreen = $state(false);
|
|
|
960
965
|
controls={scatter_controls}
|
|
961
966
|
current_x_value={current_step_idx}
|
|
962
967
|
change={plot_skimming ? handle_plot_change : undefined}
|
|
963
|
-
padding={{ t: 20, b: 60, l:
|
|
968
|
+
padding={{ t: 20, b: 60, l: 52, r: has_y2_series ? 100 : 20 }}
|
|
964
969
|
range_padding={0}
|
|
965
970
|
style="height: 100%"
|
|
966
971
|
{...scatter_props}
|
|
@@ -973,14 +978,10 @@ let fullscreen = $state(false);
|
|
|
973
978
|
}}
|
|
974
979
|
class="plot {scatter_props.class ?? ``}"
|
|
975
980
|
>
|
|
976
|
-
{#snippet tooltip({ x, y, metadata })}
|
|
977
|
-
{
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
{:else}
|
|
981
|
-
Step: {Math.round(x)}<br />
|
|
982
|
-
Value: {typeof y === `number` ? format_num(y) : y}
|
|
983
|
-
{/if}
|
|
981
|
+
{#snippet tooltip({ x, y, metadata, label })}
|
|
982
|
+
{@const formatted_y = typeof y === `number` ? format_num(y) : y}
|
|
983
|
+
Step: {Math.round(x)}<br />
|
|
984
|
+
{@html metadata?.series_label || label || `Value`}: {formatted_y}
|
|
984
985
|
{/snippet}
|
|
985
986
|
</ScatterPlot>
|
|
986
987
|
{:else if display_mode === `histogram` || display_mode === `structure+histogram`}
|
|
@@ -1004,9 +1005,9 @@ let fullscreen = $state(false);
|
|
|
1004
1005
|
--ctrl-btn-top="6ex"
|
|
1005
1006
|
>
|
|
1006
1007
|
{#snippet tooltip({ value, count, property })}
|
|
1008
|
+
{#if property}<div><strong>{property}</strong></div>{/if}
|
|
1007
1009
|
<div>Value: {format_num(value)}</div>
|
|
1008
1010
|
<div>Count: {count}</div>
|
|
1009
|
-
<div>{property}</div>
|
|
1010
1011
|
{/snippet}
|
|
1011
1012
|
</Histogram>
|
|
1012
1013
|
{/if}
|
|
@@ -1049,61 +1050,55 @@ let fullscreen = $state(false);
|
|
|
1049
1050
|
contain: layout;
|
|
1050
1051
|
z-index: var(--traj-z-index, 1);
|
|
1051
1052
|
container-type: size; /* enable cqh for panes if explicit height is set */
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1053
|
+
:global(.plot) {
|
|
1054
|
+
background: var(--surface-bg);
|
|
1055
|
+
}
|
|
1056
|
+
&.active {
|
|
1057
|
+
z-index: 2; /* needed so info/control panes from an active viewer overlay those of the next (if there is one) */
|
|
1058
|
+
.trajectory-controls {
|
|
1059
|
+
z-index: 5; /* needed so info/control panes from an active viewer its own plot when active, not sure why needed */
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
&:fullscreen {
|
|
1063
|
+
height: 100vh !important;
|
|
1064
|
+
width: 100vw !important;
|
|
1065
|
+
border-radius: 0 !important;
|
|
1066
|
+
background: var(--surface-bg);
|
|
1067
|
+
overflow: hidden;
|
|
1068
|
+
}
|
|
1069
|
+
&.horizontal .content-area {
|
|
1070
|
+
grid-template-columns: 1fr 1fr;
|
|
1071
|
+
grid-template-rows: 1fr;
|
|
1072
|
+
}
|
|
1073
|
+
&.vertical .content-area {
|
|
1074
|
+
grid-template-columns: 1fr;
|
|
1075
|
+
grid-template-rows: 1fr 1fr;
|
|
1076
|
+
}
|
|
1077
|
+
/* Display mode specific layouts */
|
|
1078
|
+
&:is(.horizontal, .vertical) .content-area:is(.show-structure-only, .show-plot-only) {
|
|
1079
|
+
grid-template-columns: 1fr !important;
|
|
1080
|
+
grid-template-rows: 1fr !important;
|
|
1081
|
+
}
|
|
1082
|
+
&.dragover {
|
|
1083
|
+
background-color: var(--traj-dragover-bg, var(--dragover-bg));
|
|
1084
|
+
border: var(--traj-dragover-border, var(--dragover-border));
|
|
1085
|
+
}
|
|
1086
|
+
/* Mode: hover - controls visible on component hover */
|
|
1087
|
+
&:hover .trajectory-controls.hover-visible {
|
|
1088
|
+
opacity: 1;
|
|
1089
|
+
pointer-events: auto;
|
|
1090
|
+
}
|
|
1068
1091
|
}
|
|
1069
1092
|
/* Content area - grid container for equal sizing */
|
|
1070
1093
|
.content-area {
|
|
1071
1094
|
display: grid;
|
|
1072
1095
|
flex: 1;
|
|
1073
1096
|
min-height: 0; /* important for tall structure viewers not to overflow */
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
.trajectory.vertical .content-area {
|
|
1080
|
-
grid-template-columns: 1fr;
|
|
1081
|
-
grid-template-rows: 1fr 1fr;
|
|
1082
|
-
}
|
|
1083
|
-
/* When plot is hidden, structure takes full space */
|
|
1084
|
-
.content-area.hide-plot {
|
|
1085
|
-
grid-template-columns: 1fr !important;
|
|
1086
|
-
grid-template-rows: 1fr !important;
|
|
1087
|
-
}
|
|
1088
|
-
/* When structure is hidden, plot takes full space */
|
|
1089
|
-
.content-area.hide-structure {
|
|
1090
|
-
grid-template-columns: 1fr !important;
|
|
1091
|
-
grid-template-rows: 1fr !important;
|
|
1092
|
-
}
|
|
1093
|
-
/* Display mode specific layouts */
|
|
1094
|
-
.trajectory.horizontal .content-area.show-structure-only,
|
|
1095
|
-
.trajectory.vertical .content-area.show-structure-only {
|
|
1096
|
-
grid-template-columns: 1fr !important;
|
|
1097
|
-
grid-template-rows: 1fr !important;
|
|
1098
|
-
}
|
|
1099
|
-
.trajectory.horizontal .content-area.show-plot-only,
|
|
1100
|
-
.trajectory.vertical .content-area.show-plot-only {
|
|
1101
|
-
grid-template-columns: 1fr !important;
|
|
1102
|
-
grid-template-rows: 1fr !important;
|
|
1103
|
-
}
|
|
1104
|
-
.trajectory.dragover {
|
|
1105
|
-
background-color: var(--traj-dragover-bg, var(--dragover-bg));
|
|
1106
|
-
border: var(--traj-dragover-border, var(--dragover-border));
|
|
1097
|
+
/* When plot or structure is hidden, the other takes full space */
|
|
1098
|
+
&:is(.hide-plot, .hide-structure) {
|
|
1099
|
+
grid-template-columns: 1fr !important;
|
|
1100
|
+
grid-template-rows: 1fr !important;
|
|
1101
|
+
}
|
|
1107
1102
|
}
|
|
1108
1103
|
.trajectory-controls {
|
|
1109
1104
|
display: flex;
|
|
@@ -1117,27 +1112,29 @@ let fullscreen = $state(false);
|
|
|
1117
1112
|
opacity: 0;
|
|
1118
1113
|
pointer-events: none;
|
|
1119
1114
|
transition: opacity 0.2s ease;
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1115
|
+
/* Mode: always - controls always visible */
|
|
1116
|
+
&.always-visible {
|
|
1117
|
+
opacity: 1;
|
|
1118
|
+
pointer-events: auto;
|
|
1119
|
+
}
|
|
1120
|
+
/* Mode: never - stays hidden (default state, no additional CSS needed) */
|
|
1121
|
+
&:focus-within {
|
|
1122
|
+
z-index: var(--traj-controls-z-index, 999999999);
|
|
1123
|
+
}
|
|
1124
|
+
button {
|
|
1125
|
+
background: var(--btn-bg);
|
|
1126
|
+
font-size: clamp(0.8rem, 2cqw, 1rem);
|
|
1127
|
+
&:hover:not(:disabled) {
|
|
1128
|
+
background: var(--btn-bg-hover);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
input[type='number'] {
|
|
1132
|
+
&::-webkit-outer-spin-button,
|
|
1133
|
+
&::-webkit-inner-spin-button {
|
|
1134
|
+
-webkit-appearance: none;
|
|
1135
|
+
margin: 0;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1141
1138
|
}
|
|
1142
1139
|
.nav-section {
|
|
1143
1140
|
display: flex;
|
|
@@ -1210,68 +1207,73 @@ let fullscreen = $state(false);
|
|
|
1210
1207
|
.fullscreen-button {
|
|
1211
1208
|
background: transparent !important;
|
|
1212
1209
|
padding: 0;
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1210
|
+
&:hover:not(:disabled) {
|
|
1211
|
+
background: var(--border-color);
|
|
1212
|
+
}
|
|
1216
1213
|
}
|
|
1217
1214
|
.info-section {
|
|
1218
1215
|
display: flex;
|
|
1219
1216
|
align-items: center;
|
|
1220
|
-
gap: clamp(
|
|
1217
|
+
gap: clamp(3pt, 0.6cqw, 1ex);
|
|
1221
1218
|
position: relative;
|
|
1222
1219
|
}
|
|
1220
|
+
.info-section :global(:is(.trajectory-info-toggle, .trajectory-export-toggle)) {
|
|
1221
|
+
font-size: clamp(1rem, 2.2cqw, 1.1rem);
|
|
1222
|
+
}
|
|
1223
1223
|
.play-button {
|
|
1224
1224
|
min-width: clamp(32px, 4cqw, 36px);
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1225
|
+
&:hover:not(:disabled) {
|
|
1226
|
+
background: var(--traj-play-btn-bg-hover, var(--btn-bg-hover, rgba(0, 0, 0, 0.2)));
|
|
1227
|
+
}
|
|
1228
|
+
&.playing {
|
|
1229
|
+
background: var(--traj-pause-btn-bg, var(--btn-bg, rgba(0, 0, 0, 0.1)));
|
|
1230
|
+
&:hover:not(:disabled) {
|
|
1231
|
+
background: var(
|
|
1232
|
+
--traj-pause-btn-bg-hover,
|
|
1233
|
+
var(--btn-bg-hover, rgba(0, 0, 0, 0.1))
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1234
1237
|
}
|
|
1235
1238
|
:global(.trajectory-empty-state) {
|
|
1236
1239
|
padding: 2rem;
|
|
1237
1240
|
border-radius: var(--border-radius, 3pt);
|
|
1238
1241
|
background: var(--dropzone-bg);
|
|
1242
|
+
:where(p, ul) {
|
|
1243
|
+
color: var(--text-color-muted);
|
|
1244
|
+
}
|
|
1245
|
+
:where(ul, li, strong) {
|
|
1246
|
+
max-width: var(--trajectory-empty-state-max-width, 500px);
|
|
1247
|
+
margin-inline: auto;
|
|
1248
|
+
}
|
|
1239
1249
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1250
|
-
button:disabled {
|
|
1251
|
-
background: var(--btn-disabled-bg);
|
|
1252
|
-
color: var(--text-color-muted);
|
|
1253
|
-
cursor: not-allowed;
|
|
1254
|
-
}
|
|
1255
|
-
.trajectory-controls input[type='number']::-webkit-outer-spin-button,
|
|
1256
|
-
.trajectory-controls input[type='number']::-webkit-inner-spin-button {
|
|
1257
|
-
-webkit-appearance: none;
|
|
1258
|
-
margin: 0;
|
|
1250
|
+
button {
|
|
1251
|
+
&:hover:not(:disabled) {
|
|
1252
|
+
background: var(--border-color);
|
|
1253
|
+
}
|
|
1254
|
+
&:disabled {
|
|
1255
|
+
background: var(--btn-disabled-bg);
|
|
1256
|
+
color: var(--text-color-muted);
|
|
1257
|
+
cursor: not-allowed;
|
|
1258
|
+
}
|
|
1259
1259
|
}
|
|
1260
1260
|
/* Responsive design */
|
|
1261
1261
|
@media (orientation: portrait) {
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
}
|
|
1266
|
-
/* Modern browsers: use :has() for same effect */
|
|
1267
|
-
@supports selector(:has(.content-area)) {
|
|
1268
|
-
.trajectory:has(.content-area.show-both:not(.hide-plot):not(.hide-structure)) {
|
|
1262
|
+
.trajectory {
|
|
1263
|
+
/* Fallback class for browsers without :has() support */
|
|
1264
|
+
&.show-both-views {
|
|
1269
1265
|
min-height: calc(var(--min-height) * 2);
|
|
1270
1266
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1267
|
+
/* Modern browsers: use :has() for same effect */
|
|
1268
|
+
@supports selector(:has(.content-area)) {
|
|
1269
|
+
&:has(.content-area.show-both:not(.hide-plot):not(.hide-structure)) {
|
|
1270
|
+
min-height: calc(var(--min-height) * 2);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
.content-area.show-both:not(.hide-plot):not(.hide-structure) {
|
|
1274
|
+
grid-template-columns: 1fr !important;
|
|
1275
|
+
grid-template-rows: 1fr 1fr !important;
|
|
1276
|
+
}
|
|
1275
1277
|
}
|
|
1276
1278
|
}
|
|
1277
1279
|
.view-mode-dropdown-wrapper {
|
|
@@ -1297,19 +1299,19 @@ let fullscreen = $state(false);
|
|
|
1297
1299
|
border-radius: 0;
|
|
1298
1300
|
text-align: left;
|
|
1299
1301
|
transition: background-color 0.15s ease;
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1302
|
+
&:first-child {
|
|
1303
|
+
border-top-left-radius: 3px;
|
|
1304
|
+
border-top-right-radius: 3px;
|
|
1305
|
+
}
|
|
1306
|
+
&.selected {
|
|
1307
|
+
color: var(--accent-color);
|
|
1308
|
+
}
|
|
1309
|
+
span {
|
|
1310
|
+
font-weight: 500;
|
|
1311
|
+
white-space: nowrap;
|
|
1312
|
+
overflow: hidden;
|
|
1313
|
+
text-overflow: ellipsis;
|
|
1314
|
+
flex: 1;
|
|
1315
|
+
}
|
|
1314
1316
|
}
|
|
1315
1317
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<script lang="ts">import
|
|
1
|
+
<script lang="ts">import { export_trajectory_video, get_ffmpeg_conversion_command, } from '../io/export';
|
|
2
|
+
import SettingsSection from '../layout/SettingsSection.svelte';
|
|
2
3
|
import DraggablePane from '../overlays/DraggablePane.svelte';
|
|
3
|
-
import { export_trajectory_video, get_ffmpeg_conversion_command, } from '../io/export';
|
|
4
4
|
import { tooltip } from 'svelte-multiselect/attachments';
|
|
5
5
|
let { export_pane_open = $bindable(false), trajectory = undefined, wrapper = undefined, filename = `trajectory`, video_fps = $bindable(30), resolution_multiplier = $bindable(1), on_step_change = undefined, pane_props = {}, toggle_props = {}, ...rest } = $props();
|
|
6
6
|
let is_exporting = $state(false);
|
|
@@ -242,8 +242,9 @@ $effect(() => {
|
|
|
242
242
|
<style>
|
|
243
243
|
.field-label {
|
|
244
244
|
display: flex;
|
|
245
|
-
|
|
246
|
-
gap:
|
|
245
|
+
align-items: center;
|
|
246
|
+
gap: 6pt;
|
|
247
|
+
white-space: nowrap;
|
|
247
248
|
}
|
|
248
249
|
.warning, .error-message {
|
|
249
250
|
padding: 1ex;
|
|
@@ -275,13 +276,16 @@ $effect(() => {
|
|
|
275
276
|
color: var(--text-color-muted);
|
|
276
277
|
}
|
|
277
278
|
.resolution-buttons {
|
|
278
|
-
display: flex;
|
|
279
|
-
gap:
|
|
280
|
-
margin:
|
|
279
|
+
display: inline-flex;
|
|
280
|
+
gap: 3pt;
|
|
281
|
+
margin: 0;
|
|
282
|
+
margin-left: auto;
|
|
283
|
+
white-space: nowrap;
|
|
281
284
|
}
|
|
282
285
|
.resolution-buttons button {
|
|
283
|
-
flex:
|
|
284
|
-
|
|
286
|
+
flex: 0 0 auto;
|
|
287
|
+
min-width: 2.8em;
|
|
288
|
+
padding: 1pt 3pt;
|
|
285
289
|
border: 1px solid var(--border-color, rgba(255, 255, 255, 0.2));
|
|
286
290
|
background: var(--btn-bg, rgba(255, 255, 255, 0.1));
|
|
287
291
|
color: var(--text-color);
|
|
@@ -12,6 +12,6 @@ type $$ComponentProps = {
|
|
|
12
12
|
pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`];
|
|
13
13
|
toggle_props?: ComponentProps<typeof DraggablePane>[`toggle_props`];
|
|
14
14
|
};
|
|
15
|
-
declare const TrajectoryExportPane: import("svelte").Component<$$ComponentProps, {}, "
|
|
15
|
+
declare const TrajectoryExportPane: import("svelte").Component<$$ComponentProps, {}, "export_pane_open" | "resolution_multiplier" | "video_fps">;
|
|
16
16
|
type TrajectoryExportPane = ReturnType<typeof TrajectoryExportPane>;
|
|
17
17
|
export default TrajectoryExportPane;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const MAX_SAFE_STRING_LENGTH: number;
|
|
2
|
+
export declare const MAX_METADATA_SIZE: number;
|
|
3
|
+
export declare const LARGE_FILE_THRESHOLD: number;
|
|
4
|
+
export declare const INDEX_SAMPLE_RATE = 100;
|
|
5
|
+
export declare const MAX_BIN_FILE_SIZE: number;
|
|
6
|
+
export declare const MAX_TEXT_FILE_SIZE: number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Constants for trajectory parsing and large file handling
|
|
2
|
+
export const MAX_SAFE_STRING_LENGTH = 0x1fffffe8 * 0.5; // 50% of JS max string length as safety
|
|
3
|
+
export const MAX_METADATA_SIZE = 50 * 1024 * 1024; // 50MB limit for metadata
|
|
4
|
+
export const LARGE_FILE_THRESHOLD = 400 * 1024 * 1024; // 400MB
|
|
5
|
+
export const INDEX_SAMPLE_RATE = 100; // Default sample rate for frame indexing
|
|
6
|
+
export const MAX_BIN_FILE_SIZE = 100 * 1024 * 1024; // 100MB default for ArrayBuffer files
|
|
7
|
+
export const MAX_TEXT_FILE_SIZE = 50 * 1024 * 1024; // 50MB default for string files
|
|
@@ -136,11 +136,9 @@ function property_varies(trajectory, property_key, tolerance = 1e-10) {
|
|
|
136
136
|
// Check both direct structure properties and metadata
|
|
137
137
|
let value;
|
|
138
138
|
if (`lattice` in frame.structure) {
|
|
139
|
-
const
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
value = lattice[property_key];
|
|
143
|
-
}
|
|
139
|
+
const lattice_value = frame.structure.lattice[property_key];
|
|
140
|
+
if (typeof lattice_value === `number`)
|
|
141
|
+
value = lattice_value;
|
|
144
142
|
}
|
|
145
143
|
if (value === undefined &&
|
|
146
144
|
frame.metadata &&
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function strip_compression_extensions(filename: string): string;
|
|
2
|
+
export declare const FORMAT_PATTERNS: {
|
|
3
|
+
readonly ase: (data: unknown, filename?: string) => boolean;
|
|
4
|
+
readonly hdf5: (data: unknown, filename?: string) => boolean;
|
|
5
|
+
readonly vasp: (data: string, filename?: string) => boolean;
|
|
6
|
+
readonly xyz_multi: (data: string, filename?: string) => boolean;
|
|
7
|
+
readonly lammpstrj: (data: string, filename?: string) => boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function is_trajectory_file(filename: string, content?: string): boolean;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Format detection for trajectory files
|
|
2
|
+
import { COMPRESSION_EXTENSIONS_REGEX, CONFIG_DIRS_REGEX, MD_SIM_EXCLUDE_REGEX, TRAJ_EXTENSIONS_REGEX, TRAJ_FALLBACK_EXTENSIONS_REGEX, TRAJ_KEYWORDS_SIMPLE_REGEX, XDATCAR_REGEX, } from '../constants';
|
|
3
|
+
import { count_xyz_frames } from './helpers';
|
|
4
|
+
export function strip_compression_extensions(filename) {
|
|
5
|
+
let base_name = filename.toLowerCase();
|
|
6
|
+
while (COMPRESSION_EXTENSIONS_REGEX.test(base_name)) {
|
|
7
|
+
base_name = base_name.replace(COMPRESSION_EXTENSIONS_REGEX, ``);
|
|
8
|
+
}
|
|
9
|
+
return base_name;
|
|
10
|
+
}
|
|
11
|
+
// Unified format detection
|
|
12
|
+
export const FORMAT_PATTERNS = {
|
|
13
|
+
ase: (data, filename) => {
|
|
14
|
+
const base_name = filename ? strip_compression_extensions(filename) : undefined;
|
|
15
|
+
if (!base_name?.endsWith(`.traj`) || !(data instanceof ArrayBuffer)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const view = new Uint8Array(data.slice(0, 24));
|
|
19
|
+
return [0x2d, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x6c, 0x6d].every((byte, idx) => view[idx] === byte);
|
|
20
|
+
},
|
|
21
|
+
hdf5: (data, filename) => {
|
|
22
|
+
const base_name = filename ? strip_compression_extensions(filename) : undefined;
|
|
23
|
+
const has_ext = base_name?.match(/\.(h5|hdf5)$/);
|
|
24
|
+
if (!has_ext || !(data instanceof ArrayBuffer) || data.byteLength < 8)
|
|
25
|
+
return false;
|
|
26
|
+
const signature = new Uint8Array(data.slice(0, 8));
|
|
27
|
+
return [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a].every((b, idx) => signature[idx] === b);
|
|
28
|
+
},
|
|
29
|
+
vasp: (data, filename) => {
|
|
30
|
+
const basename = filename?.toLowerCase().split(`/`).pop() || ``;
|
|
31
|
+
if (basename === `xdatcar` || basename.startsWith(`xdatcar`))
|
|
32
|
+
return true;
|
|
33
|
+
const lines = data.trim().split(/\r?\n/);
|
|
34
|
+
return lines.length >= 10 &&
|
|
35
|
+
lines.some((line) => line.includes(`Direct configuration=`)) &&
|
|
36
|
+
!isNaN(parseFloat(lines[1])) &&
|
|
37
|
+
lines.slice(2, 5).every((line) => line.trim().split(/\s+/).length === 3);
|
|
38
|
+
},
|
|
39
|
+
xyz_multi: (data, filename) => {
|
|
40
|
+
const base = filename ? strip_compression_extensions(filename) : ``;
|
|
41
|
+
if (!/\.(xyz|extxyz)$/.test(base))
|
|
42
|
+
return false;
|
|
43
|
+
return count_xyz_frames(data) >= 2;
|
|
44
|
+
},
|
|
45
|
+
lammpstrj: (data, filename) => {
|
|
46
|
+
const base = filename ? strip_compression_extensions(filename) : ``;
|
|
47
|
+
if (!/\.lammpstrj$/.test(base))
|
|
48
|
+
return false;
|
|
49
|
+
return data.includes(`ITEM: TIMESTEP`) && data.includes(`ITEM: ATOMS`);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
// Check if file is a trajectory (supports both filename-only and content-based detection)
|
|
53
|
+
export function is_trajectory_file(filename, content) {
|
|
54
|
+
if (CONFIG_DIRS_REGEX.test(filename))
|
|
55
|
+
return false;
|
|
56
|
+
const base_name = strip_compression_extensions(filename);
|
|
57
|
+
// For xyz/extxyz files, use content-based detection if available
|
|
58
|
+
if (/\.(xyz|extxyz)$/i.test(base_name)) {
|
|
59
|
+
if (content)
|
|
60
|
+
return count_xyz_frames(content) >= 2;
|
|
61
|
+
return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
|
|
62
|
+
}
|
|
63
|
+
// Always detect these specific trajectory formats
|
|
64
|
+
if (TRAJ_EXTENSIONS_REGEX.test(base_name) || XDATCAR_REGEX.test(base_name))
|
|
65
|
+
return true;
|
|
66
|
+
// Special exclusion for generic md_simulation pattern with certain extensions
|
|
67
|
+
if (MD_SIM_EXCLUDE_REGEX.test(base_name))
|
|
68
|
+
return false;
|
|
69
|
+
// For .h5/.hdf5 files, require trajectory keywords
|
|
70
|
+
if (/\.(h5|hdf5)$/i.test(base_name)) {
|
|
71
|
+
return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
|
|
72
|
+
}
|
|
73
|
+
// For other extensions, require both keywords and specific extensions
|
|
74
|
+
return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name) &&
|
|
75
|
+
TRAJ_FALLBACK_EXTENSIONS_REGEX.test(base_name);
|
|
76
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FrameIndex, FrameLoader, ParseProgress, TrajectoryFrame, TrajectoryMetadata } from './index';
|
|
2
|
+
export declare class TrajFrameReader implements FrameLoader {
|
|
3
|
+
private format;
|
|
4
|
+
private global_numbers?;
|
|
5
|
+
constructor(filename: string);
|
|
6
|
+
get_total_frames(data: string | ArrayBuffer): Promise<number>;
|
|
7
|
+
build_frame_index(data: string | ArrayBuffer, sample_rate: number, on_progress?: (progress: ParseProgress) => void): Promise<FrameIndex[]>;
|
|
8
|
+
load_frame(data: string | ArrayBuffer, frame_number: number): Promise<TrajectoryFrame | null>;
|
|
9
|
+
extract_plot_metadata(data: string | ArrayBuffer, options?: {
|
|
10
|
+
sample_rate?: number;
|
|
11
|
+
properties?: string[];
|
|
12
|
+
}, on_progress?: (progress: ParseProgress) => void): Promise<TrajectoryMetadata[]>;
|
|
13
|
+
private load_xyz_frame;
|
|
14
|
+
private load_ase_frame;
|
|
15
|
+
private parse_xyz_metadata;
|
|
16
|
+
private parse_ase_metadata;
|
|
17
|
+
}
|