matterviz 0.4.1 → 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.
Files changed (499) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +48 -60
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/api/optimade.js +10 -7
  6. package/dist/app.css +68 -0
  7. package/dist/brillouin/BrillouinZone.svelte +90 -91
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  9. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  12. package/dist/brillouin/BrillouinZoneScene.svelte +46 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  14. package/dist/brillouin/compute.js +10 -16
  15. package/dist/brillouin/geometry.js +2 -2
  16. package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
  17. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
  20. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  21. package/dist/chempot-diagram/async-compute.svelte.js +13 -14
  22. package/dist/chempot-diagram/color.d.ts +21 -1
  23. package/dist/chempot-diagram/color.js +70 -1
  24. package/dist/chempot-diagram/compute.d.ts +7 -0
  25. package/dist/chempot-diagram/compute.js +85 -26
  26. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  27. package/dist/chempot-diagram/export.js +1 -6
  28. package/dist/chempot-diagram/temperature.js +9 -10
  29. package/dist/colors/index.d.ts +0 -4
  30. package/dist/colors/index.js +19 -20
  31. package/dist/composition/BarChart.svelte +30 -26
  32. package/dist/composition/BubbleChart.svelte +17 -17
  33. package/dist/composition/Composition.svelte +10 -19
  34. package/dist/composition/Formula.svelte +20 -27
  35. package/dist/composition/FormulaFilter.svelte +115 -184
  36. package/dist/composition/PieChart.svelte +55 -41
  37. package/dist/composition/format.js +7 -9
  38. package/dist/composition/index.d.ts +2 -0
  39. package/dist/composition/index.js +14 -0
  40. package/dist/composition/parse.d.ts +2 -2
  41. package/dist/composition/parse.js +61 -115
  42. package/dist/constants.d.ts +0 -1
  43. package/dist/constants.js +17 -26
  44. package/dist/convex-hull/ConvexHull.svelte +12 -15
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +93 -94
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +127 -186
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +131 -180
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  53. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  54. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  55. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  56. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  57. package/dist/convex-hull/StructurePopup.svelte +18 -22
  58. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  59. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  60. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  61. package/dist/convex-hull/gas-thermodynamics.js +21 -53
  62. package/dist/convex-hull/helpers.d.ts +8 -10
  63. package/dist/convex-hull/helpers.js +37 -43
  64. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  65. package/dist/convex-hull/thermodynamics.js +37 -44
  66. package/dist/coordination/CoordinationBarPlot.svelte +49 -53
  67. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  68. package/dist/coordination/calc-coordination.d.ts +1 -1
  69. package/dist/coordination/calc-coordination.js +28 -25
  70. package/dist/element/BohrAtom.svelte +5 -9
  71. package/dist/element/ElementHeading.svelte +4 -1
  72. package/dist/element/ElementPhoto.svelte +11 -9
  73. package/dist/element/ElementStats.svelte +12 -10
  74. package/dist/element/ElementTile.svelte +44 -67
  75. package/dist/element/Nucleus.svelte +4 -2
  76. package/dist/element/data.d.ts +3 -2
  77. package/dist/element/data.js +5 -1
  78. package/dist/element/helpers.d.ts +4 -0
  79. package/dist/element/helpers.js +18 -0
  80. package/dist/element/index.d.ts +2 -5
  81. package/dist/element/index.js +4 -19
  82. package/dist/feedback/DragOverlay.svelte +5 -5
  83. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  84. package/dist/feedback/StatusMessage.svelte +7 -4
  85. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  86. package/dist/fermi-surface/FermiSurface.svelte +35 -44
  87. package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
  88. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  89. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  90. package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
  91. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  92. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  93. package/dist/fermi-surface/compute.js +25 -58
  94. package/dist/fermi-surface/parse.js +54 -88
  95. package/dist/file-viewer/JsonBrowser.svelte +1043 -0
  96. package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
  97. package/dist/file-viewer/PlotPanel.svelte +350 -0
  98. package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
  99. package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
  100. package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
  101. package/dist/file-viewer/detect.d.ts +11 -0
  102. package/dist/file-viewer/detect.js +381 -0
  103. package/dist/file-viewer/eligibility.d.ts +4 -0
  104. package/dist/file-viewer/eligibility.js +53 -0
  105. package/dist/file-viewer/host-protocol.d.ts +50 -0
  106. package/dist/file-viewer/host-transfer.d.ts +25 -0
  107. package/dist/file-viewer/host-transfer.js +42 -0
  108. package/dist/file-viewer/index.d.ts +5 -0
  109. package/dist/file-viewer/index.js +5 -0
  110. package/dist/file-viewer/main.d.ts +44 -0
  111. package/dist/file-viewer/main.js +535 -0
  112. package/dist/file-viewer/parse.d.ts +9 -0
  113. package/dist/file-viewer/parse.js +170 -0
  114. package/dist/file-viewer/plot-utils.d.ts +24 -0
  115. package/dist/file-viewer/plot-utils.js +191 -0
  116. package/dist/file-viewer/types.d.ts +4 -0
  117. package/dist/file-viewer/types.js +5 -0
  118. package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
  119. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  120. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  121. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  122. package/dist/heatmap-matrix/index.d.ts +5 -0
  123. package/dist/icons.d.ts +4 -0
  124. package/dist/icons.js +4 -0
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +1 -1
  127. package/dist/io/ExportPane.svelte +11 -7
  128. package/dist/io/decompress.d.ts +4 -1
  129. package/dist/io/decompress.js +24 -36
  130. package/dist/io/export.d.ts +11 -4
  131. package/dist/io/export.js +75 -19
  132. package/dist/io/fetch.d.ts +0 -3
  133. package/dist/io/fetch.js +0 -11
  134. package/dist/io/file-drop.js +60 -35
  135. package/dist/io/index.d.ts +0 -1
  136. package/dist/io/index.js +2 -9
  137. package/dist/io/is-binary.d.ts +9 -0
  138. package/dist/io/is-binary.js +45 -1
  139. package/dist/io/url-drop.d.ts +2 -0
  140. package/dist/io/url-drop.js +40 -40
  141. package/dist/isosurface/Isosurface.svelte +700 -215
  142. package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
  143. package/dist/isosurface/IsosurfaceControls.svelte +590 -116
  144. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
  145. package/dist/isosurface/VolumeSlice.svelte +224 -0
  146. package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
  147. package/dist/isosurface/coloring.d.ts +20 -0
  148. package/dist/isosurface/coloring.js +118 -0
  149. package/dist/isosurface/geometry-worker-types.d.ts +38 -0
  150. package/dist/isosurface/geometry.worker.d.ts +1 -0
  151. package/dist/isosurface/geometry.worker.js +59 -0
  152. package/dist/isosurface/grid.d.ts +10 -0
  153. package/dist/isosurface/grid.js +31 -0
  154. package/dist/isosurface/index.d.ts +4 -0
  155. package/dist/isosurface/index.js +4 -0
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +6 -6
  159. package/dist/isosurface/profile.d.ts +12 -0
  160. package/dist/isosurface/profile.js +19 -0
  161. package/dist/isosurface/sampling.d.ts +34 -0
  162. package/dist/isosurface/sampling.js +408 -0
  163. package/dist/isosurface/slice-rendering.d.ts +13 -0
  164. package/dist/isosurface/slice-rendering.js +79 -0
  165. package/dist/isosurface/slice.d.ts +22 -2
  166. package/dist/isosurface/slice.js +200 -116
  167. package/dist/isosurface/types.d.ts +24 -1
  168. package/dist/isosurface/types.js +120 -8
  169. package/dist/json-path.d.ts +4 -0
  170. package/dist/json-path.js +89 -0
  171. package/dist/labels.d.ts +6 -2
  172. package/dist/labels.js +44 -14
  173. package/dist/layout/FullscreenButton.svelte +2 -1
  174. package/dist/layout/FullscreenToggle.svelte +10 -4
  175. package/dist/layout/InfoCard.svelte +8 -21
  176. package/dist/layout/InfoTag.svelte +1 -3
  177. package/dist/layout/NumberRangeInput.svelte +46 -0
  178. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  179. package/dist/layout/PropertyFilter.svelte +2 -6
  180. package/dist/layout/SettingsSection.svelte +57 -62
  181. package/dist/layout/SettingsSection.svelte.d.ts +6 -7
  182. package/dist/layout/SubpageGrid.svelte +3 -1
  183. package/dist/layout/ViewerChrome.svelte +16 -11
  184. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  185. package/dist/layout/fullscreen.js +3 -5
  186. package/dist/layout/fullscreen.svelte.js +1 -2
  187. package/dist/layout/index.d.ts +1 -0
  188. package/dist/layout/index.js +1 -0
  189. package/dist/layout/json-tree/JsonNode.svelte +22 -59
  190. package/dist/layout/json-tree/JsonTree.svelte +101 -172
  191. package/dist/layout/json-tree/JsonValue.svelte +9 -32
  192. package/dist/layout/json-tree/utils.d.ts +0 -3
  193. package/dist/layout/json-tree/utils.js +50 -188
  194. package/dist/marching-cubes.d.ts +8 -1
  195. package/dist/marching-cubes.js +115 -48
  196. package/dist/math.d.ts +5 -2
  197. package/dist/math.js +48 -38
  198. package/dist/overlays/ContextMenu.svelte +19 -34
  199. package/dist/overlays/CopyButton.svelte +11 -5
  200. package/dist/overlays/DragControlTab.svelte +6 -1
  201. package/dist/overlays/DraggablePane.svelte +110 -74
  202. package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
  203. package/dist/overlays/GlassChip.svelte +32 -0
  204. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  205. package/dist/overlays/InfoPaneCards.svelte +11 -23
  206. package/dist/overlays/index.d.ts +7 -0
  207. package/dist/overlays/index.js +26 -0
  208. package/dist/overlays/portal.d.ts +2 -0
  209. package/dist/overlays/portal.js +14 -0
  210. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  211. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  212. package/dist/periodic-table/PeriodicTableControls.svelte +37 -115
  213. package/dist/periodic-table/TableInset.svelte +9 -4
  214. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
  215. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  216. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  217. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  218. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  219. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  220. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  221. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  222. package/dist/phase-diagram/build-diagram.js +4 -9
  223. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  224. package/dist/phase-diagram/parse.js +15 -15
  225. package/dist/phase-diagram/svg-to-diagram.js +28 -27
  226. package/dist/phase-diagram/utils.js +2 -3
  227. package/dist/plot/bar/BarPlot.svelte +461 -426
  228. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  229. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  230. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  231. package/dist/plot/bar/SpacegroupBarPlot.svelte +46 -77
  232. package/dist/plot/bar/data.d.ts +5 -4
  233. package/dist/plot/bar/data.js +2 -1
  234. package/dist/plot/box/BoxPlot.svelte +322 -226
  235. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  236. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  237. package/dist/plot/box/box-plot.js +1 -1
  238. package/dist/plot/core/auto-place.d.ts +1 -1
  239. package/dist/plot/core/auto-place.js +2 -2
  240. package/dist/plot/core/axis-utils.d.ts +12 -7
  241. package/dist/plot/core/axis-utils.js +48 -48
  242. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  243. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  244. package/dist/plot/core/components/ColorBar.svelte +101 -106
  245. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  246. package/dist/plot/core/components/FillArea.svelte +10 -17
  247. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  248. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  249. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  250. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  251. package/dist/plot/core/components/Line.svelte +18 -9
  252. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  253. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  254. package/dist/plot/core/components/PlotControls.svelte +65 -41
  255. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  256. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  257. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  258. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  259. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  260. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  261. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  262. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +27 -474
  271. package/dist/plot/core/data-transform.d.ts +1 -2
  272. package/dist/plot/core/data-transform.js +9 -15
  273. package/dist/plot/core/fill-utils.d.ts +3 -1
  274. package/dist/plot/core/fill-utils.js +28 -6
  275. package/dist/plot/core/index.d.ts +1 -0
  276. package/dist/plot/core/index.js +1 -0
  277. package/dist/plot/core/interactions.js +0 -2
  278. package/dist/plot/core/layout.d.ts +15 -6
  279. package/dist/plot/core/layout.js +57 -38
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
  283. package/dist/plot/core/pan-zoom.svelte.js +34 -17
  284. package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -21
  286. package/dist/plot/core/reference-line.js +1 -1
  287. package/dist/plot/core/scales.d.ts +23 -0
  288. package/dist/plot/core/scales.js +39 -13
  289. package/dist/plot/core/svg.js +0 -1
  290. package/dist/plot/core/types/fills.d.ts +101 -0
  291. package/dist/plot/core/types/fills.js +15 -0
  292. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  293. package/dist/plot/core/types/plot-3d.js +4 -0
  294. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  295. package/dist/plot/core/types/reference-lines.js +9 -0
  296. package/dist/plot/core/types.d.ts +29 -324
  297. package/dist/plot/core/types.js +23 -20
  298. package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
  299. package/dist/plot/core/utils/hierarchy-chart.js +191 -0
  300. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  301. package/dist/plot/core/utils/hierarchy-labels.js +100 -0
  302. package/dist/plot/core/utils/label-placement.js +2 -2
  303. package/dist/plot/histogram/Histogram.svelte +314 -340
  304. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  305. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  306. package/dist/plot/histogram/histogram.d.ts +31 -0
  307. package/dist/plot/histogram/histogram.js +70 -0
  308. package/dist/plot/histogram/index.d.ts +1 -0
  309. package/dist/plot/histogram/index.js +1 -0
  310. package/dist/plot/index.d.ts +1 -0
  311. package/dist/plot/index.js +1 -0
  312. package/dist/plot/sankey/Sankey.svelte +78 -69
  313. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  314. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  315. package/dist/plot/sankey/sankey.js +13 -9
  316. package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
  317. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  318. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  319. package/dist/plot/scatter/ScatterPlot.svelte +517 -410
  320. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  321. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  322. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  323. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  324. package/dist/plot/scatter/adaptive-density.d.ts +1 -1
  325. package/dist/plot/scatter/adaptive-density.js +36 -20
  326. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  327. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  328. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  329. package/dist/plot/scatter/scatter-data.js +8 -7
  330. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  331. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  332. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  333. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  334. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  335. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  336. package/dist/plot/sunburst/Sunburst.svelte +269 -347
  337. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  338. package/dist/plot/sunburst/index.d.ts +1 -1
  339. package/dist/plot/sunburst/index.js +2 -1
  340. package/dist/plot/sunburst/render.d.ts +2 -2
  341. package/dist/plot/sunburst/render.js +47 -22
  342. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  343. package/dist/plot/sunburst/sunburst.js +10 -3
  344. package/dist/plot/treemap/Treemap.svelte +1022 -0
  345. package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
  346. package/dist/plot/treemap/index.d.ts +4 -0
  347. package/dist/plot/treemap/index.js +4 -0
  348. package/dist/plot/treemap/labels.d.ts +38 -0
  349. package/dist/plot/treemap/labels.js +80 -0
  350. package/dist/plot/treemap/treemap.d.ts +28 -0
  351. package/dist/plot/treemap/treemap.js +102 -0
  352. package/dist/rdf/RdfPlot.svelte +37 -59
  353. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  354. package/dist/rdf/calc-rdf.js +63 -52
  355. package/dist/rdf/index.d.ts +0 -1
  356. package/dist/sanitize.js +85 -27
  357. package/dist/scene/SceneCamera.svelte +1 -1
  358. package/dist/scene/SceneCamera.svelte.d.ts +1 -1
  359. package/dist/scene/bind-renderer.svelte.js +14 -6
  360. package/dist/scene/index.d.ts +1 -2
  361. package/dist/scene/index.js +1 -1
  362. package/dist/scene/{props.js → props.svelte.js} +15 -1
  363. package/dist/settings.d.ts +19 -9
  364. package/dist/settings.js +229 -525
  365. package/dist/spectral/Bands.svelte +207 -221
  366. package/dist/spectral/BandsAndDos.svelte +11 -9
  367. package/dist/spectral/BrillouinBandsDos.svelte +19 -42
  368. package/dist/spectral/Dos.svelte +92 -93
  369. package/dist/spectral/helpers.d.ts +3 -3
  370. package/dist/spectral/helpers.js +65 -140
  371. package/dist/state.svelte.js +5 -18
  372. package/dist/structure/Arrow.svelte +5 -18
  373. package/dist/structure/ArrowInstances.svelte +160 -0
  374. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  375. package/dist/structure/AtomLegend.svelte +120 -85
  376. package/dist/structure/AtomLegend.svelte.d.ts +2 -3
  377. package/dist/structure/Bond.svelte +31 -23
  378. package/dist/structure/CanvasTooltip.svelte +15 -3
  379. package/dist/structure/CellSelect.svelte +45 -35
  380. package/dist/structure/Cylinder.svelte +24 -40
  381. package/dist/structure/InstancedAtoms.svelte +114 -0
  382. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  383. package/dist/structure/Lattice.svelte +85 -149
  384. package/dist/structure/SiteLabels.svelte +122 -0
  385. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  386. package/dist/structure/Structure.svelte +636 -504
  387. package/dist/structure/Structure.svelte.d.ts +4 -2
  388. package/dist/structure/StructureCarousel.svelte +637 -0
  389. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  390. package/dist/structure/StructureControls.svelte +165 -425
  391. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  392. package/dist/structure/StructureExportPane.svelte +17 -21
  393. package/dist/structure/StructureInfoPane.svelte +128 -133
  394. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  395. package/dist/structure/StructureScene.svelte +535 -578
  396. package/dist/structure/StructureScene.svelte.d.ts +6 -2
  397. package/dist/structure/StructureViewport.svelte +451 -0
  398. package/dist/structure/StructureViewport.svelte.d.ts +65 -0
  399. package/dist/structure/atom-label-placement.d.ts +16 -12
  400. package/dist/structure/atom-label-placement.js +70 -37
  401. package/dist/structure/atom-properties.d.ts +2 -0
  402. package/dist/structure/atom-properties.js +105 -38
  403. package/dist/structure/bond-order-perception.js +3 -8
  404. package/dist/structure/bonding.d.ts +9 -3
  405. package/dist/structure/bonding.js +95 -46
  406. package/dist/structure/edit-history.d.ts +6 -0
  407. package/dist/structure/edit-history.js +27 -0
  408. package/dist/structure/export.d.ts +1 -0
  409. package/dist/structure/export.js +89 -105
  410. package/dist/structure/format-detect.d.ts +1 -0
  411. package/dist/structure/format-detect.js +20 -0
  412. package/dist/structure/geometry.d.ts +9 -0
  413. package/dist/structure/geometry.js +27 -0
  414. package/dist/structure/index.d.ts +16 -1
  415. package/dist/structure/index.js +15 -10
  416. package/dist/structure/measure.d.ts +1 -1
  417. package/dist/structure/measure.js +6 -12
  418. package/dist/structure/parse.d.ts +2 -1
  419. package/dist/structure/parse.js +272 -313
  420. package/dist/structure/partial-occupancy.js +10 -5
  421. package/dist/structure/pbc.js +85 -107
  422. package/dist/structure/polyhedra.d.ts +0 -1
  423. package/dist/structure/polyhedra.js +7 -21
  424. package/dist/structure/prop-groups.d.ts +85 -0
  425. package/dist/structure/prop-groups.js +18 -0
  426. package/dist/structure/supercell.d.ts +1 -2
  427. package/dist/structure/supercell.js +7 -13
  428. package/dist/symmetry/SymmetryElements.svelte +11 -15
  429. package/dist/symmetry/SymmetryStats.svelte +55 -71
  430. package/dist/symmetry/WyckoffTable.svelte +10 -28
  431. package/dist/symmetry/cell-transform.js +6 -14
  432. package/dist/symmetry/index.d.ts +1 -0
  433. package/dist/symmetry/index.js +13 -10
  434. package/dist/symmetry/spacegroups.js +3 -2
  435. package/dist/table/HeatmapTable.svelte +1142 -447
  436. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  437. package/dist/table/ToggleMenu.svelte +168 -53
  438. package/dist/table/ToggleMenu.svelte.d.ts +1 -1
  439. package/dist/table/index.d.ts +21 -6
  440. package/dist/table/index.js +34 -21
  441. package/dist/theme/ThemeControl.svelte +16 -8
  442. package/dist/theme/embedded.d.ts +18 -0
  443. package/dist/theme/embedded.js +206 -0
  444. package/dist/theme/index.d.ts +5 -5
  445. package/dist/theme/index.js +5 -12
  446. package/dist/theme/themes.mjs +44 -66
  447. package/dist/tooltip/KCoords.svelte +4 -1
  448. package/dist/tooltip/TooltipContent.svelte +3 -6
  449. package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
  450. package/dist/tooltip/index.d.ts +8 -1
  451. package/dist/trajectory/Trajectory.svelte +613 -386
  452. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  453. package/dist/trajectory/TrajectoryError.svelte +12 -74
  454. package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
  455. package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
  456. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
  457. package/dist/trajectory/extract.js +61 -49
  458. package/dist/trajectory/format-detect.d.ts +2 -0
  459. package/dist/trajectory/format-detect.js +17 -13
  460. package/dist/trajectory/frame-reader.d.ts +2 -0
  461. package/dist/trajectory/frame-reader.js +35 -32
  462. package/dist/trajectory/helpers.d.ts +2 -0
  463. package/dist/trajectory/helpers.js +34 -56
  464. package/dist/trajectory/index.d.ts +1 -0
  465. package/dist/trajectory/index.js +5 -8
  466. package/dist/trajectory/parse/ase.js +1 -1
  467. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  468. package/dist/trajectory/parse/h5-utils.js +109 -0
  469. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  470. package/dist/trajectory/parse/hdf5.js +116 -106
  471. package/dist/trajectory/parse/index.d.ts +6 -6
  472. package/dist/trajectory/parse/index.js +25 -33
  473. package/dist/trajectory/parse/lammps.js +8 -12
  474. package/dist/trajectory/parse/vasp.js +10 -7
  475. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  476. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  477. package/dist/trajectory/parse/vaspout-h5.d.ts +4 -0
  478. package/dist/trajectory/parse/vaspout-h5.js +281 -0
  479. package/dist/trajectory/parse/xyz.js +59 -9
  480. package/dist/trajectory/plotting.d.ts +8 -9
  481. package/dist/trajectory/plotting.js +113 -64
  482. package/dist/utils.d.ts +3 -0
  483. package/dist/utils.js +7 -0
  484. package/dist/xrd/XrdPlot.svelte +79 -118
  485. package/dist/xrd/broadening.js +2 -1
  486. package/dist/xrd/calc-xrd.js +24 -62
  487. package/dist/xrd/parse.d.ts +0 -1
  488. package/dist/xrd/parse.js +69 -95
  489. package/package.json +94 -34
  490. package/readme.md +6 -5
  491. package/dist/api/mp.d.ts +0 -6
  492. package/dist/api/mp.js +0 -22
  493. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  494. package/dist/scene/types.d.ts +0 -26
  495. package/dist/tooltip/types.d.ts +0 -8
  496. package/dist/trajectory/constants.d.ts +0 -6
  497. package/dist/trajectory/constants.js +0 -11
  498. /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
  499. /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
@@ -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
- // Common data extractor that extracts energy and structural properties
5
- export const energy_data_extractor = (frame) => {
6
- const data = {
7
- Step: frame.step,
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 = {
@@ -52,6 +50,15 @@ export const force_stress_data_extractor = (frame) => {
52
50
  }
53
51
  return data;
54
52
  };
53
+ // Data extractor for SCF/electronic-convergence properties. Parsers emit these
54
+ // per frame (per ionic step, or per SCF step for static single-point runs) —
55
+ // e.g. the vaspout.h5 parser fills them from VASP's OSZICAR data.
56
+ const scf_data_extractor = make_metadata_extractor([
57
+ `n_scf_steps`,
58
+ `scf_energy_delta`,
59
+ `scf_rms`,
60
+ `scf_charge_rms`,
61
+ ]);
55
62
  // Data extractor for structural properties
56
63
  export const structural_data_extractor = (frame) => {
57
64
  const data = {
@@ -93,50 +100,55 @@ export const structural_data_extractor = (frame) => {
93
100
  }
94
101
  return data;
95
102
  };
96
- // Helper function to check if a property varies across trajectory frames
97
- function property_varies(trajectory, property_key, tolerance = 1e-10) {
98
- if (trajectory.frames.length <= 1)
99
- return false;
100
- const values = [];
103
+ const LATTICE_PARAMS = [`a`, `b`, `c`, `alpha`, `beta`, `gamma`];
104
+ // Cache per trajectory: full_data_extractor runs once per frame, so without this it
105
+ // rescans all frames on every call (O(n²)). WeakMap → GC'd with the trajectory.
106
+ const constant_params_cache = new WeakMap();
107
+ // Lattice params constant across the trajectory, in a single pass (prefer lattice value,
108
+ // else metadata; tol 1e-10). A param must be observed in ≥1 frame to count as constant;
109
+ // params absent from every frame are excluded (not silently treated as "constant").
110
+ function get_constant_lattice_params(trajectory) {
111
+ const cached = constant_params_cache.get(trajectory);
112
+ if (cached)
113
+ return cached;
114
+ const tolerance = 1e-10;
115
+ const first_values = new Map();
116
+ const varies = new Set();
101
117
  for (const frame of trajectory.frames) {
102
- // Check both direct structure properties and metadata
103
- let value;
104
- if (`lattice` in frame.structure) {
105
- const lattice_value = frame.structure.lattice[property_key];
106
- if (typeof lattice_value === `number`)
107
- value = lattice_value;
108
- }
109
- if (value === undefined && frame.metadata && property_key in frame.metadata) {
110
- const metadata_value = frame.metadata[property_key];
111
- if (typeof metadata_value === `number`) {
112
- value = metadata_value;
113
- }
114
- }
115
- if (value !== undefined) {
116
- values.push(value);
118
+ const lattice = `lattice` in frame.structure
119
+ ? frame.structure.lattice
120
+ : null;
121
+ for (const param of LATTICE_PARAMS) {
122
+ if (varies.has(param))
123
+ continue; // already known to vary, skip
124
+ const lattice_value = lattice?.[param];
125
+ const value = typeof lattice_value === `number` ? lattice_value : frame.metadata?.[param];
126
+ // Number.isFinite: NaN is typeof `number` but Math.abs(next-NaN)=NaN → false constant
127
+ if (typeof value !== `number` || !Number.isFinite(value))
128
+ continue;
129
+ const first = first_values.get(param);
130
+ if (first === undefined)
131
+ first_values.set(param, value);
132
+ else if (Math.abs(value - first) > tolerance)
133
+ varies.add(param);
117
134
  }
118
135
  }
119
- if (values.length <= 1)
120
- return false;
121
- const first_value = values[0];
122
- return values.some((value) => Math.abs(value - first_value) > tolerance);
136
+ // only params observed in ≥1 frame; a never-present param is not "constant"
137
+ const constant = new Set([...first_values.keys()].filter((param) => !varies.has(param)));
138
+ constant_params_cache.set(trajectory, constant);
139
+ return constant;
123
140
  }
124
141
  // Combined data extractor that extracts all common properties
125
142
  export const full_data_extractor = (frame, trajectory) => {
126
- const base_data = {
143
+ const result = {
127
144
  ...energy_data_extractor(frame, trajectory),
128
145
  ...force_stress_data_extractor(frame, trajectory),
146
+ ...scf_data_extractor(frame, trajectory),
129
147
  ...structural_data_extractor(frame, trajectory),
130
148
  };
131
- // Check which lattice parameters vary
132
- const lattice_params = [`a`, `b`, `c`, `alpha`, `beta`, `gamma`];
133
- const result = { ...base_data };
134
- // Add metadata to specify which properties don't vary
135
- for (const param of lattice_params) {
136
- if (!property_varies(trajectory, param)) {
137
- // Mark individual lattice parameters as constant
138
- result[`constant_${param}`] = 1;
139
- }
149
+ // Mark individual lattice parameters that don't vary across the trajectory
150
+ for (const param of get_constant_lattice_params(trajectory)) {
151
+ result[`constant_${param}`] = 1;
140
152
  }
141
153
  return result;
142
154
  };
@@ -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,10 +1,11 @@
1
1
  // Format detection for trajectory files
2
- import { CONFIG_DIRS_REGEX, MD_SIM_EXCLUDE_REGEX, TRAJ_EXTENSIONS_REGEX, TRAJ_FALLBACK_EXTENSIONS_REGEX, TRAJ_KEYWORDS_SIMPLE_REGEX, XDATCAR_REGEX, } from '../constants';
3
- import { strip_compression_extensions } from '../io';
2
+ import { CONFIG_DIRS_REGEX, MD_SIM_EXCLUDE_REGEX, TRAJ_EXTENSIONS_REGEX, TRAJ_FALLBACK_EXTENSIONS_REGEX, TRAJ_KEYWORDS_REGEX, XDATCAR_REGEX, } from '../constants';
3
+ import { strip_compression_extensions } from '../io/decompress';
4
+ import { parse_leading_num } from '../utils';
4
5
  import { count_xyz_frames } from './helpers';
5
6
  // Extensions that explicitly identify a format — when present, format detection trusts
6
7
  // the extension instead of sniffing content
7
- const KNOWN_FORMAT_EXT_REGEX = /\.(xyz|extxyz|traj|h5|hdf5|lammpstrj|json|cif|poscar|vasp|yaml|yml|xml|csv)$/;
8
+ const KNOWN_FORMAT_EXT_REGEX = /\.(?:xyz|extxyz|traj|h5|hdf5|lammpstrj|json|cif|poscar|vasp|yaml|yml|xml|csv)$/;
8
9
  // Classify the filename hint for a format whose extensions match ext_regex:
9
10
  // true = filename matches, false = filename names a different known format,
10
11
  // null = no usable hint (missing filename or unrecognized extension, e.g. the UUID
@@ -17,6 +18,9 @@ export function ext_hint(filename, ext_regex) {
17
18
  return true;
18
19
  return KNOWN_FORMAT_EXT_REGEX.test(base) ? false : null;
19
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));
20
24
  // Unified format detection. Each pattern trusts a matching file extension when present
21
25
  // but falls back to content/magic-byte detection when the filename gives no hint
22
26
  // (e.g. blob: object URLs, extensionless API endpoints).
@@ -29,7 +33,7 @@ export const FORMAT_PATTERNS = {
29
33
  return [0x2d, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x6c, 0x6d].every((byte, idx) => view[idx] === byte);
30
34
  },
31
35
  hdf5: (data, filename) => {
32
- if (ext_hint(filename, /\.(h5|hdf5)$/) === false)
36
+ if (ext_hint(filename, /\.(?:h5|hdf5)$/) === false)
33
37
  return false;
34
38
  if (!(data instanceof ArrayBuffer) || data.byteLength < 8)
35
39
  return false;
@@ -43,11 +47,11 @@ export const FORMAT_PATTERNS = {
43
47
  const lines = data.trim().split(/\r?\n/);
44
48
  return (lines.length >= 10 &&
45
49
  lines.some((line) => line.includes(`Direct configuration=`)) &&
46
- !isNaN(parseFloat(lines[1])) &&
50
+ !isNaN(parse_leading_num(lines[1])) &&
47
51
  lines.slice(2, 5).every((line) => line.trim().split(/\s+/).length === 3));
48
52
  },
49
53
  xyz_multi: (data, filename) => {
50
- if (ext_hint(filename, /\.(xyz|extxyz)$/) === false)
54
+ if (ext_hint(filename, /\.(?:xyz|extxyz)$/) === false)
51
55
  return false;
52
56
  return count_xyz_frames(data) >= 2;
53
57
  },
@@ -63,10 +67,10 @@ export function is_trajectory_file(filename, content) {
63
67
  return false;
64
68
  const base_name = strip_compression_extensions(filename);
65
69
  // For xyz/extxyz files, use content-based detection if available
66
- if (/\.(xyz|extxyz)$/i.test(base_name)) {
70
+ if (/\.(?:xyz|extxyz)$/i.test(base_name)) {
67
71
  if (content)
68
72
  return count_xyz_frames(content) >= 2;
69
- return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
73
+ return TRAJ_KEYWORDS_REGEX.test(base_name);
70
74
  }
71
75
  // Always detect these specific trajectory formats
72
76
  if (TRAJ_EXTENSIONS_REGEX.test(base_name) || XDATCAR_REGEX.test(base_name))
@@ -74,11 +78,11 @@ export function is_trajectory_file(filename, content) {
74
78
  // Special exclusion for generic md_simulation pattern with certain extensions
75
79
  if (MD_SIM_EXCLUDE_REGEX.test(base_name))
76
80
  return false;
77
- // For .h5/.hdf5 files, require trajectory keywords
78
- if (/\.(h5|hdf5)$/i.test(base_name)) {
79
- return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
81
+ // For .h5/.hdf5 files, require trajectory keywords. vaspout.h5 (VASP's
82
+ // HDF5 output) is always trajectory-shaped regardless of keywords.
83
+ if (/\.(?:h5|hdf5)$/i.test(base_name)) {
84
+ return /vaspout/i.test(base_name) || TRAJ_KEYWORDS_REGEX.test(base_name);
80
85
  }
81
86
  // For other extensions, require both keywords and specific extensions
82
- return (TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name) &&
83
- TRAJ_FALLBACK_EXTENSIONS_REGEX.test(base_name));
87
+ return TRAJ_KEYWORDS_REGEX.test(base_name) && TRAJ_FALLBACK_EXTENSIONS_REGEX.test(base_name);
84
88
  }
@@ -2,6 +2,7 @@ import type { FrameIndex, FrameLoader, ParseProgress, TrajectoryFrame, Trajector
2
2
  export declare class TrajFrameReader implements FrameLoader {
3
3
  private readonly format;
4
4
  private global_numbers?;
5
+ private xyz_cache?;
5
6
  constructor(filename: string);
6
7
  get_total_frames(data: string | ArrayBuffer): Promise<number>;
7
8
  build_frame_index(data: string | ArrayBuffer, sample_rate: number, on_progress?: (progress: ParseProgress) => void): Promise<FrameIndex[]>;
@@ -10,6 +11,7 @@ export declare class TrajFrameReader implements FrameLoader {
10
11
  sample_rate?: number;
11
12
  properties?: string[];
12
13
  }, on_progress?: (progress: ParseProgress) => void): Promise<TrajectoryMetadata[]>;
14
+ private get_xyz_cache;
13
15
  private load_xyz_frame;
14
16
  private load_ase_frame;
15
17
  private parse_ase_metadata;
@@ -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 { strip_compression_extensions } from '../io';
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)
@@ -14,9 +14,11 @@ const filter_properties = (metadata, properties) => {
14
14
  export class TrajFrameReader {
15
15
  format;
16
16
  global_numbers;
17
+ // Split lines + per-frame start indices for the last XYZ payload, so repeat seeks are
18
+ // O(1) lookup instead of re-splitting + rescanning from line 0 (was O(n²) over playback)
19
+ xyz_cache;
17
20
  constructor(filename) {
18
- const base_filename = strip_compression_extensions(filename);
19
- this.format = base_filename.endsWith(`.traj`) ? `ase` : `xyz`;
21
+ this.format = indexed_trajectory_format(filename);
20
22
  }
21
23
  async get_total_frames(data) {
22
24
  if (this.format === `xyz`) {
@@ -108,26 +110,19 @@ export class TrajFrameReader {
108
110
  if (this.format === `xyz`) {
109
111
  const lines = data.trim().split(/\r?\n/);
110
112
  let current_frame = 0;
111
- for (const { start, comment } of iter_xyz_frames(lines)) {
113
+ for (const { comment } of iter_xyz_frames(lines)) {
112
114
  if (current_frame >= total_frames)
113
115
  break;
114
116
  if (current_frame % sample_rate === 0) {
115
- let frame_metadata = null;
116
- try {
117
- const { step, properties: props } = parse_xyz_comment_metadata(comment);
118
- frame_metadata = {
119
- frame_number: current_frame,
120
- step: step ?? current_frame,
121
- properties: props,
122
- };
123
- }
124
- catch (error) {
125
- console.warn(`Failed to parse XYZ metadata for frame ${current_frame} at line ${start + 1}:`, error);
126
- }
127
- if (frame_metadata) {
128
- filter_properties(frame_metadata, properties);
129
- metadata_list.push(frame_metadata);
130
- }
117
+ // parse_xyz_comment_metadata is pure regex/parseFloat and never throws
118
+ const { step, properties: props } = parse_xyz_comment_metadata(comment);
119
+ const frame_metadata = {
120
+ frame_number: current_frame,
121
+ step: step ?? current_frame,
122
+ properties: props,
123
+ };
124
+ filter_properties(frame_metadata, properties);
125
+ metadata_list.push(frame_metadata);
131
126
  }
132
127
  current_frame++;
133
128
  if (on_progress && current_frame % 5000 === 0) {
@@ -169,18 +164,26 @@ export class TrajFrameReader {
169
164
  }
170
165
  return metadata_list;
171
166
  }
172
- load_xyz_frame(data, frame_number) {
167
+ // Build + cache the line array and per-frame start indices once per payload
168
+ get_xyz_cache(data) {
169
+ if (this.xyz_cache?.data === data)
170
+ return this.xyz_cache;
173
171
  const lines = data.trim().split(/\r?\n/);
174
- let current_frame = 0;
175
- for (const frame of iter_xyz_frames(lines)) {
176
- if (current_frame++ < frame_number)
177
- continue; // skip frames before the target
178
- return build_xyz_frame(lines, frame, {
179
- frame_label: `indexed frame ${frame_number}`,
180
- default_step: frame_number,
181
- });
182
- }
183
- return null;
172
+ const frame_starts = Array.from(iter_xyz_frames(lines), ({ start }) => start);
173
+ this.xyz_cache = { data, lines, frame_starts };
174
+ return this.xyz_cache;
175
+ }
176
+ load_xyz_frame(data, frame_number) {
177
+ const { lines, frame_starts } = this.get_xyz_cache(data);
178
+ const start = frame_starts[frame_number];
179
+ if (start === undefined)
180
+ return null; // out-of-range frame
181
+ const num_atoms = Math.trunc(Number(lines[start]?.trim()));
182
+ const comment = lines[start + 1] ?? ``;
183
+ return build_xyz_frame(lines, { start, num_atoms, comment }, {
184
+ frame_label: `indexed frame ${frame_number}`,
185
+ default_step: frame_number,
186
+ });
184
187
  }
185
188
  load_ase_frame(data, frame_number) {
186
189
  try {
@@ -5,6 +5,7 @@ import type { Pbc } from '../structure/pbc';
5
5
  import type { TrajectoryFrame } from './index';
6
6
  export declare function validate_3x3_matrix(data: unknown): math.Matrix3x3;
7
7
  export declare const convert_atomic_numbers: (numbers: number[]) => ElementSymbol[];
8
+ export declare const count_elements: (elements: readonly string[]) => Record<string, number>;
8
9
  export declare const create_structure: (positions: number[][], elements: ElementSymbol[], lattice_matrix?: math.Matrix3x3, pbc?: Pbc, force_data?: number[][]) => AnyStructure;
9
10
  export declare const create_trajectory_frame: (positions: number[][], elements: ElementSymbol[], lattice_matrix: math.Matrix3x3 | undefined, pbc: Pbc | undefined, step: number, metadata?: Record<string, unknown>) => TrajectoryFrame;
10
11
  export declare const read_ndarray_from_view: (view: DataView, ref: {
@@ -15,6 +16,7 @@ export declare function calc_force_stats(forces: number[][]): {
15
16
  force_max: number;
16
17
  force_norm: number;
17
18
  } | null;
19
+ export declare const is_xyz_atom_line: (parts: string[] | undefined) => boolean;
18
20
  export declare function iter_xyz_frames(lines: string[]): Generator<{
19
21
  start: number;
20
22
  num_atoms: number;
@@ -1,13 +1,8 @@
1
1
  // Shared utilities for trajectory parsing
2
2
  import { ATOMIC_NUMBER_TO_SYMBOL } from '../composition/parse';
3
- import { is_elem_symbol } from '../element';
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(is_valid_row)) {
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;
@@ -27,6 +23,13 @@ export const convert_atomic_numbers = (numbers) => numbers.map((num) => {
27
23
  }
28
24
  return symbol;
29
25
  });
26
+ // Tally per-element atom counts for trajectory metadata.element_counts
27
+ export const count_elements = (elements) => {
28
+ const counts = {};
29
+ for (const element of elements)
30
+ counts[element] = (counts[element] || 0) + 1;
31
+ return counts;
32
+ };
30
33
  export const create_structure = (positions, elements, lattice_matrix, pbc, force_data) => {
31
34
  if (positions.length !== elements.length) {
32
35
  throw new Error(`create_structure requires matching positions and elements lengths, got positions=${positions.length}, elements=${elements.length}`);
@@ -62,54 +65,25 @@ export const create_trajectory_frame = (positions, elements, lattice_matrix, pbc
62
65
  export const read_ndarray_from_view = (view, ref) => {
63
66
  const [shape, dtype, array_offset] = ref.ndarray;
64
67
  const total = shape.reduce((product, dim_size) => product * dim_size, 1);
65
- const data = [];
66
- let pos = array_offset;
67
68
  const readers = {
68
- int64: {
69
- bytes_per_element: 8,
70
- read: () => {
71
- const value = Number(view.getBigInt64(pos, true));
72
- pos += 8;
73
- return value;
74
- },
75
- },
76
- int32: {
77
- bytes_per_element: 4,
78
- read: () => {
79
- const value = view.getInt32(pos, true);
80
- pos += 4;
81
- return value;
82
- },
83
- },
84
- float64: {
85
- bytes_per_element: 8,
86
- read: () => {
87
- const value = view.getFloat64(pos, true);
88
- pos += 8;
89
- return value;
90
- },
91
- },
92
- float32: {
93
- bytes_per_element: 4,
94
- read: () => {
95
- const value = view.getFloat32(pos, true);
96
- pos += 4;
97
- return value;
98
- },
99
- },
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) },
100
73
  };
101
- const reader_config = readers[dtype];
102
- if (!reader_config)
74
+ const reader = readers[dtype];
75
+ if (!reader)
103
76
  throw new Error(`Unsupported dtype: ${dtype}`);
104
77
  if (!Number.isInteger(array_offset) || array_offset < 0) {
105
78
  throw new Error(`Invalid array_offset: expected non-negative integer, got ${array_offset}`);
106
79
  }
107
- const bytes_needed = total * reader_config.bytes_per_element;
108
- if (array_offset + bytes_needed > view.byteLength) {
80
+ if (array_offset + total * reader.bytes > view.byteLength) {
109
81
  throw new Error(`Out-of-bounds read: array_offset + bytesNeeded exceeds view.byteLength`);
110
82
  }
111
- for (let idx = 0; idx < total; idx++)
112
- data.push(reader_config.read());
83
+ const data = [];
84
+ for (let idx = 0; idx < total; idx++) {
85
+ data.push(reader.read(array_offset + idx * reader.bytes));
86
+ }
113
87
  return shape.length === 1
114
88
  ? [data]
115
89
  : shape.length === 2
@@ -140,8 +114,16 @@ export function calc_force_stats(forces) {
140
114
  }
141
115
  return { force_max, force_norm: Math.sqrt(sum_sq / forces.length) };
142
116
  }
143
- // Walk concatenated (ext)XYZ frames in `lines`, yielding each frame's atom-count line
144
- // index, parsed atom count, and comment line. A candidate frame is accepted only when its
117
+ // True when a whitespace-split line looks like an XYZ atom line: a short
118
+ // non-numeric element token followed by three numeric coordinates. Shared by
119
+ // trajectory frame iteration and structure-format sniffing so both stay in sync.
120
+ export const is_xyz_atom_line = (parts) => parts !== undefined &&
121
+ parts.length >= 4 &&
122
+ isNaN(Number(parts[0])) &&
123
+ parts[0].length <= 3 &&
124
+ parts.slice(1, 4).every((coord) => coord !== `` && !isNaN(Number(coord)));
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
145
127
  // first few atom lines look like "<element> <x> <y> <z>"; otherwise we advance one line and
146
128
  // rescan. That validation doubles as content sniffing so numeric-leading non-XYZ formats
147
129
  // (e.g. VASP XDATCAR) aren't misread as frames, and keeps count_xyz_frames consistent with
@@ -149,7 +131,7 @@ export function calc_force_stats(forces) {
149
131
  export function* iter_xyz_frames(lines) {
150
132
  let line_idx = 0;
151
133
  while (line_idx < lines.length) {
152
- const num_atoms = parseInt(lines[line_idx]?.trim(), 10);
134
+ const num_atoms = Math.trunc(Number(lines[line_idx]?.trim()));
153
135
  if (isNaN(num_atoms) || num_atoms <= 0 || line_idx + num_atoms + 2 > lines.length) {
154
136
  line_idx++; // skip blank/invalid lines until the next frame's atom-count line
155
137
  continue;
@@ -157,11 +139,7 @@ export function* iter_xyz_frames(lines) {
157
139
  let valid_coords = 0;
158
140
  const sample = Math.min(num_atoms, 3);
159
141
  for (let idx = 0; idx < sample; idx++) {
160
- const parts = lines[line_idx + 2 + idx]?.trim().split(/\s+/);
161
- if (parts?.length >= 4 &&
162
- isNaN(parseInt(parts[0], 10)) &&
163
- parts[0].length <= 3 &&
164
- parts.slice(1, 4).every((coord) => !isNaN(parseFloat(coord))))
142
+ if (is_xyz_atom_line(lines[line_idx + 2 + idx]?.trim().split(/\s+/)))
165
143
  valid_coords++;
166
144
  }
167
145
  if (valid_coords < sample) {
@@ -174,7 +152,7 @@ export function* iter_xyz_frames(lines) {
174
152
  }
175
153
  // Count XYZ frames via iter_xyz_frames so total_frames matches what gets indexed/loaded
176
154
  export function count_xyz_frames(data) {
177
- if (!data || typeof data !== `string`)
155
+ if (!data)
178
156
  return 0;
179
157
  const frames = iter_xyz_frames(data.trim().split(/\r?\n/));
180
158
  let frame_count = 0;
@@ -7,6 +7,7 @@ export { default as TrajectoryExportPane } from './TrajectoryExportPane.svelte';
7
7
  export { default as TrajectoryInfoPane } from './TrajectoryInfoPane.svelte';
8
8
  export type TrajectoryFormat = `hdf5` | `json` | `xyz` | `xdatcar` | `traj` | `unknown`;
9
9
  export type { AtomTypeMapping } from './types';
10
+ export declare const FRAME_LOAD_DEBOUNCE_MS = 75;
10
11
  export interface ParseProgress {
11
12
  current: number;
12
13
  total: number;
@@ -2,8 +2,10 @@ export { default as Trajectory } from './Trajectory.svelte';
2
2
  export { default as TrajectoryError } from './TrajectoryError.svelte';
3
3
  export { default as TrajectoryExportPane } from './TrajectoryExportPane.svelte';
4
4
  export { default as TrajectoryInfoPane } from './TrajectoryInfoPane.svelte';
5
+ // Debounce for on-demand frame loads while scrubbing: skips fetches for steps
6
+ // the user slides past. Exported so tests stay in sync with the real delay.
7
+ export const FRAME_LOAD_DEBOUNCE_MS = 75;
5
8
  export function validate_trajectory(trajectory) {
6
- // with detailed error reporting
7
9
  const errors = [];
8
10
  const { frames, total_frames, indexed_frames, plot_metadata, is_indexed } = trajectory;
9
11
  if (!frames?.length)
@@ -110,13 +112,8 @@ export function get_trajectory_stats(trajectory) {
110
112
  else
111
113
  stats.atom_count_range = [Math.min(...all_counts), Math.max(...all_counts)];
112
114
  }
113
- else {
114
- // Handle empty trajectory case
115
- stats.steps = [];
116
- stats.step_range = undefined;
117
- stats.constant_atom_count = undefined;
118
- stats.total_atoms = undefined;
119
- }
115
+ else
116
+ stats.steps = []; // empty trajectory
120
117
  // Additional metadata for large files
121
118
  if (indexed_frames)
122
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)),
@@ -0,0 +1,13 @@
1
+ import type { ElementSymbol } from '../../element/types';
2
+ import type { Matrix3x3 } from '../../math';
3
+ import type { Dataset, Entity, Group } from 'h5wasm';
4
+ import * as h5wasm from 'h5wasm';
5
+ export declare const is_hdf5_dataset: (entity: Entity | null) => entity is Dataset;
6
+ export declare const is_hdf5_group: (entity: Entity | null) => entity is Group;
7
+ export declare const read_dataset: (h5_file: h5wasm.File, path: string) => unknown;
8
+ export declare const to_string_array: (data: unknown) => string[] | null;
9
+ export declare const to_number_array: (data: unknown) => number[] | null;
10
+ export declare const to_scalar_number: (data: unknown) => number | null;
11
+ export declare const scale_matrix: (matrix: Matrix3x3, scale: number) => Matrix3x3;
12
+ export declare const expand_ion_types: (ion_types: string[], ion_counts: number[]) => ElementSymbol[];
13
+ export declare function with_h5_file<T>(buffer: ArrayBuffer, filename: string | undefined, callback: (h5_file: h5wasm.File) => T | Promise<T>): Promise<T>;