matterviz 0.4.0 → 0.4.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.
Files changed (527) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +132 -219
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  13. package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
  15. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  16. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  17. package/dist/brillouin/compute.d.ts +2 -0
  18. package/dist/brillouin/compute.js +80 -77
  19. package/dist/brillouin/geometry.d.ts +8 -0
  20. package/dist/brillouin/geometry.js +57 -0
  21. package/dist/brillouin/index.d.ts +2 -0
  22. package/dist/brillouin/index.js +2 -0
  23. package/dist/brillouin/types.d.ts +2 -2
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  25. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
  27. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
  29. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  30. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  31. package/dist/chempot-diagram/color.d.ts +3 -6
  32. package/dist/chempot-diagram/color.js +5 -5
  33. package/dist/chempot-diagram/compute.d.ts +3 -3
  34. package/dist/chempot-diagram/compute.js +3 -1
  35. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  36. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  37. package/dist/chempot-diagram/export.d.ts +47 -0
  38. package/dist/chempot-diagram/export.js +133 -0
  39. package/dist/chempot-diagram/index.d.ts +1 -0
  40. package/dist/chempot-diagram/index.js +1 -0
  41. package/dist/chempot-diagram/pointer.d.ts +0 -10
  42. package/dist/chempot-diagram/pointer.js +4 -4
  43. package/dist/chempot-diagram/types.d.ts +3 -3
  44. package/dist/colors/index.d.ts +0 -4
  45. package/dist/colors/index.js +21 -22
  46. package/dist/composition/BarChart.svelte +37 -31
  47. package/dist/composition/BubbleChart.svelte +17 -17
  48. package/dist/composition/Composition.svelte +7 -11
  49. package/dist/composition/Formula.svelte +18 -25
  50. package/dist/composition/FormulaFilter.svelte +96 -98
  51. package/dist/composition/PieChart.svelte +60 -46
  52. package/dist/composition/chem-sys.js +3 -2
  53. package/dist/composition/format.js +4 -3
  54. package/dist/composition/index.d.ts +2 -0
  55. package/dist/composition/index.js +14 -0
  56. package/dist/composition/parse.d.ts +2 -3
  57. package/dist/composition/parse.js +27 -28
  58. package/dist/constants.js +11 -9
  59. package/dist/controls.d.ts +1 -0
  60. package/dist/controls.js +0 -1
  61. package/dist/convex-hull/ConvexHull.svelte +20 -25
  62. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  63. package/dist/convex-hull/ConvexHull2D.svelte +176 -256
  64. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  65. package/dist/convex-hull/ConvexHull3D.svelte +269 -804
  66. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  67. package/dist/convex-hull/ConvexHull4D.svelte +236 -755
  68. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  69. package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
  70. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  71. package/dist/convex-hull/ConvexHullControls.svelte +128 -49
  72. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  73. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  74. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  75. package/dist/convex-hull/ConvexHullStats.svelte +210 -351
  76. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  77. package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
  78. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  79. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  80. package/dist/convex-hull/StructurePopup.svelte +17 -21
  81. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  82. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  83. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  84. package/dist/convex-hull/barycentric-coords.js +6 -33
  85. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  86. package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
  87. package/dist/convex-hull/helpers.d.ts +47 -17
  88. package/dist/convex-hull/helpers.js +186 -101
  89. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  90. package/dist/convex-hull/hull-state.svelte.js +124 -0
  91. package/dist/convex-hull/index.d.ts +9 -7
  92. package/dist/convex-hull/index.js +7 -2
  93. package/dist/convex-hull/thermodynamics.js +109 -937
  94. package/dist/convex-hull/types.d.ts +12 -4
  95. package/dist/convex-hull/types.js +12 -0
  96. package/dist/coordination/CoordinationBarPlot.svelte +41 -43
  97. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  98. package/dist/coordination/calc-coordination.d.ts +1 -1
  99. package/dist/coordination/calc-coordination.js +28 -25
  100. package/dist/element/BohrAtom.svelte +6 -8
  101. package/dist/element/ElementHeading.svelte +4 -1
  102. package/dist/element/ElementPhoto.svelte +11 -9
  103. package/dist/element/ElementStats.svelte +12 -10
  104. package/dist/element/ElementTile.svelte +24 -29
  105. package/dist/element/ElementTile.svelte.d.ts +1 -1
  106. package/dist/element/Nucleus.svelte +4 -2
  107. package/dist/element/data.d.ts +1 -2
  108. package/dist/element/helpers.d.ts +4 -0
  109. package/dist/element/helpers.js +18 -0
  110. package/dist/element/index.d.ts +1 -0
  111. package/dist/element/index.js +3 -0
  112. package/dist/feedback/DragOverlay.svelte +5 -3
  113. package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
  114. package/dist/feedback/StatusMessage.svelte +20 -7
  115. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  116. package/dist/fermi-surface/FermiSurface.svelte +78 -165
  117. package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
  118. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  119. package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
  120. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  121. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  122. package/dist/fermi-surface/compute.js +14 -13
  123. package/dist/fermi-surface/export.js +4 -15
  124. package/dist/fermi-surface/index.d.ts +0 -1
  125. package/dist/fermi-surface/index.js +0 -1
  126. package/dist/fermi-surface/parse.d.ts +1 -1
  127. package/dist/fermi-surface/parse.js +84 -97
  128. package/dist/fermi-surface/types.d.ts +2 -2
  129. package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
  130. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
  131. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
  132. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  133. package/dist/heatmap-matrix/index.d.ts +8 -2
  134. package/dist/icons.d.ts +4 -0
  135. package/dist/icons.js +4 -0
  136. package/dist/index.d.ts +1 -0
  137. package/dist/index.js +1 -0
  138. package/dist/io/ExportPane.svelte +170 -0
  139. package/dist/io/ExportPane.svelte.d.ts +17 -0
  140. package/dist/io/decompress.d.ts +2 -1
  141. package/dist/io/decompress.js +22 -36
  142. package/dist/io/export.d.ts +9 -1
  143. package/dist/io/export.js +37 -29
  144. package/dist/io/fetch.d.ts +2 -4
  145. package/dist/io/fetch.js +0 -11
  146. package/dist/io/file-drop.d.ts +7 -0
  147. package/dist/io/file-drop.js +13 -0
  148. package/dist/io/index.d.ts +1 -0
  149. package/dist/io/index.js +3 -0
  150. package/dist/io/is-binary.d.ts +9 -0
  151. package/dist/io/is-binary.js +45 -1
  152. package/dist/io/types.d.ts +13 -0
  153. package/dist/io/url-drop.js +13 -25
  154. package/dist/isosurface/Isosurface.svelte +17 -23
  155. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  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 +50 -48
  159. package/dist/labels.d.ts +6 -2
  160. package/dist/labels.js +44 -14
  161. package/dist/layout/FullscreenButton.svelte +34 -0
  162. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  163. package/dist/layout/FullscreenToggle.svelte +12 -12
  164. package/dist/layout/InfoCard.svelte +7 -18
  165. package/dist/layout/InfoTag.svelte +1 -3
  166. package/dist/layout/NumberRangeInput.svelte +46 -0
  167. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  168. package/dist/layout/PropertyFilter.svelte +2 -6
  169. package/dist/layout/SettingsSection.svelte +21 -17
  170. package/dist/layout/SubpageGrid.svelte +3 -1
  171. package/dist/layout/ViewerChrome.svelte +115 -0
  172. package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
  173. package/dist/layout/fullscreen.d.ts +4 -0
  174. package/dist/layout/fullscreen.js +3 -5
  175. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  176. package/dist/layout/fullscreen.svelte.js +36 -0
  177. package/dist/layout/index.d.ts +4 -0
  178. package/dist/layout/index.js +4 -0
  179. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  180. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  181. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  182. package/dist/layout/json-tree/utils.js +14 -23
  183. package/dist/math.d.ts +9 -3
  184. package/dist/math.js +37 -21
  185. package/dist/overlays/ContextMenu.svelte +4 -2
  186. package/dist/overlays/CopyButton.svelte +11 -5
  187. package/dist/overlays/DragControlTab.svelte +6 -1
  188. package/dist/overlays/DraggablePane.svelte +81 -26
  189. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  190. package/dist/overlays/GlassChip.svelte +30 -0
  191. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  192. package/dist/overlays/InfoPaneCards.svelte +11 -23
  193. package/dist/overlays/index.d.ts +11 -0
  194. package/dist/overlays/index.js +26 -0
  195. package/dist/overlays/portal.d.ts +2 -0
  196. package/dist/overlays/portal.js +14 -0
  197. package/dist/periodic-table/PeriodicTable.svelte +115 -146
  198. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  199. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  200. package/dist/periodic-table/TableInset.svelte +9 -4
  201. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  202. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  203. package/dist/phase-diagram/PhaseDiagramControls.svelte +73 -96
  204. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  205. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  206. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  207. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
  208. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  209. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  210. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  211. package/dist/phase-diagram/build-diagram.js +3 -3
  212. package/dist/phase-diagram/colors.js +1 -1
  213. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  214. package/dist/phase-diagram/parse.d.ts +2 -1
  215. package/dist/phase-diagram/parse.js +15 -15
  216. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  217. package/dist/phase-diagram/utils.js +2 -3
  218. package/dist/plot/bar/BarPlot.svelte +494 -692
  219. package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
  220. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  221. package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
  222. package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
  223. package/dist/plot/bar/data.d.ts +5 -4
  224. package/dist/plot/bar/data.js +2 -1
  225. package/dist/plot/box/BoxPlot.svelte +361 -439
  226. package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
  227. package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
  228. package/dist/plot/box/Violin.svelte.d.ts +2 -1
  229. package/dist/plot/box/box-plot.d.ts +3 -2
  230. package/dist/plot/box/box-plot.js +6 -3
  231. package/dist/plot/box/kde.d.ts +2 -1
  232. package/dist/plot/box/kde.js +4 -4
  233. package/dist/plot/core/auto-place.d.ts +1 -1
  234. package/dist/plot/core/auto-place.js +5 -2
  235. package/dist/plot/core/axis-utils.d.ts +12 -7
  236. package/dist/plot/core/axis-utils.js +48 -48
  237. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  238. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  239. package/dist/plot/core/components/ColorBar.svelte +106 -111
  240. package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
  241. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  242. package/dist/plot/core/components/FillArea.svelte +10 -17
  243. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  244. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  245. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  246. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  247. package/dist/plot/core/components/Line.svelte +21 -11
  248. package/dist/plot/core/components/Line.svelte.d.ts +5 -2
  249. package/dist/plot/core/components/PlotAxis.svelte +42 -18
  250. package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
  251. package/dist/plot/core/components/PlotControls.svelte +65 -41
  252. package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
  253. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  254. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  255. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  256. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  257. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  258. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  259. package/dist/plot/core/components/ReferenceLine3D.svelte +56 -59
  260. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
  261. package/dist/plot/core/components/ReferencePlane.svelte +9 -10
  262. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
  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 +29 -476
  271. package/dist/plot/core/data-transform.js +9 -5
  272. package/dist/plot/core/fill-utils.d.ts +7 -4
  273. package/dist/plot/core/fill-utils.js +34 -9
  274. package/dist/plot/core/index.d.ts +1 -0
  275. package/dist/plot/core/index.js +1 -0
  276. package/dist/plot/core/interactions.d.ts +5 -1
  277. package/dist/plot/core/interactions.js +14 -2
  278. package/dist/plot/core/layout.d.ts +3 -1
  279. package/dist/plot/core/layout.js +22 -13
  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 +35 -0
  283. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  284. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -0
  286. package/dist/plot/core/reference-line.d.ts +10 -10
  287. package/dist/plot/core/reference-line.js +7 -7
  288. package/dist/plot/core/scales.d.ts +40 -25
  289. package/dist/plot/core/scales.js +49 -21
  290. package/dist/plot/core/svg.d.ts +2 -1
  291. package/dist/plot/core/types/fills.d.ts +101 -0
  292. package/dist/plot/core/types/fills.js +15 -0
  293. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  294. package/dist/plot/core/types/plot-3d.js +4 -0
  295. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  296. package/dist/plot/core/types/reference-lines.js +9 -0
  297. package/dist/plot/core/types.d.ts +47 -331
  298. package/dist/plot/core/types.js +23 -20
  299. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  300. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  301. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  302. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  303. package/dist/plot/core/utils/label-placement.d.ts +1 -1
  304. package/dist/plot/core/utils/label-placement.js +5 -5
  305. package/dist/plot/core/utils.d.ts +2 -1
  306. package/dist/plot/histogram/Histogram.svelte +373 -631
  307. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  308. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  309. package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
  310. package/dist/plot/histogram/histogram.d.ts +31 -0
  311. package/dist/plot/histogram/histogram.js +70 -0
  312. package/dist/plot/histogram/index.d.ts +1 -0
  313. package/dist/plot/histogram/index.js +1 -0
  314. package/dist/plot/index.d.ts +1 -0
  315. package/dist/plot/index.js +1 -0
  316. package/dist/plot/sankey/Sankey.svelte +79 -73
  317. package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
  318. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  319. package/dist/plot/sankey/sankey.js +3 -1
  320. package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
  321. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
  322. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  323. package/dist/plot/scatter/ScatterPlot.svelte +623 -821
  324. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
  325. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  326. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  327. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  328. package/dist/plot/scatter/binned-scatter-types.d.ts +6 -12
  329. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  330. package/dist/plot/scatter/index.d.ts +1 -1
  331. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  332. package/dist/plot/scatter/scatter-data.js +8 -7
  333. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +40 -60
  334. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
  335. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
  336. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
  337. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
  338. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
  339. package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
  340. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
  341. package/dist/plot/sunburst/Sunburst.svelte +256 -338
  342. package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
  343. package/dist/plot/sunburst/index.d.ts +1 -1
  344. package/dist/plot/sunburst/index.js +2 -1
  345. package/dist/plot/sunburst/render.d.ts +2 -2
  346. package/dist/plot/sunburst/render.js +47 -22
  347. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  348. package/dist/plot/sunburst/sunburst.js +14 -4
  349. package/dist/plot/treemap/Treemap.svelte +907 -0
  350. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  351. package/dist/plot/treemap/index.d.ts +3 -0
  352. package/dist/plot/treemap/index.js +4 -0
  353. package/dist/plot/treemap/treemap.d.ts +26 -0
  354. package/dist/plot/treemap/treemap.js +99 -0
  355. package/dist/rdf/RdfPlot.svelte +22 -26
  356. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  357. package/dist/rdf/calc-rdf.js +4 -8
  358. package/dist/sanitize.js +14 -3
  359. package/dist/scene/SceneCamera.svelte +62 -0
  360. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  361. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  362. package/dist/scene/bind-renderer.svelte.js +22 -0
  363. package/dist/scene/index.d.ts +4 -0
  364. package/dist/scene/index.js +5 -0
  365. package/dist/scene/props.js +52 -0
  366. package/dist/scene/types.d.ts +26 -0
  367. package/dist/scene/types.js +1 -0
  368. package/dist/settings.d.ts +33 -11
  369. package/dist/settings.js +136 -51
  370. package/dist/spectral/Bands.svelte +231 -237
  371. package/dist/spectral/Bands.svelte.d.ts +3 -2
  372. package/dist/spectral/BandsAndDos.svelte +29 -29
  373. package/dist/spectral/BrillouinBandsDos.svelte +21 -29
  374. package/dist/spectral/Dos.svelte +75 -77
  375. package/dist/spectral/Dos.svelte.d.ts +2 -1
  376. package/dist/spectral/helpers.d.ts +9 -9
  377. package/dist/spectral/helpers.js +66 -70
  378. package/dist/state.svelte.d.ts +0 -7
  379. package/dist/state.svelte.js +5 -24
  380. package/dist/structure/Arrow.svelte +6 -21
  381. package/dist/structure/ArrowInstances.svelte +160 -0
  382. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  383. package/dist/structure/AtomLegend.svelte +115 -75
  384. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  385. package/dist/structure/Bond.svelte +31 -23
  386. package/dist/structure/CanvasTooltip.svelte +16 -3
  387. package/dist/structure/CellSelect.svelte +22 -29
  388. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  389. package/dist/structure/Cylinder.svelte +24 -40
  390. package/dist/structure/InstancedAtoms.svelte +114 -0
  391. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  392. package/dist/structure/Lattice.svelte +85 -149
  393. package/dist/structure/SiteLabels.svelte +122 -0
  394. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  395. package/dist/structure/Structure.svelte +725 -735
  396. package/dist/structure/Structure.svelte.d.ts +8 -16
  397. package/dist/structure/StructureCarousel.svelte +630 -0
  398. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  399. package/dist/structure/StructureControls.svelte +298 -325
  400. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  401. package/dist/structure/StructureExportPane.svelte +62 -168
  402. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  403. package/dist/structure/StructureInfoPane.svelte +77 -69
  404. package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
  405. package/dist/structure/StructureScene.svelte +758 -600
  406. package/dist/structure/StructureScene.svelte.d.ts +24 -20
  407. package/dist/structure/StructureViewport.svelte +386 -0
  408. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  409. package/dist/structure/atom-label-placement.d.ts +18 -0
  410. package/dist/structure/atom-label-placement.js +115 -0
  411. package/dist/structure/atom-properties.d.ts +3 -1
  412. package/dist/structure/atom-properties.js +115 -54
  413. package/dist/structure/bond-order-perception.js +2 -4
  414. package/dist/structure/bonding.d.ts +12 -2
  415. package/dist/structure/bonding.js +172 -73
  416. package/dist/structure/edit-history.d.ts +6 -0
  417. package/dist/structure/edit-history.js +27 -0
  418. package/dist/structure/export.d.ts +25 -4
  419. package/dist/structure/export.js +103 -153
  420. package/dist/structure/format-detect.d.ts +1 -0
  421. package/dist/structure/format-detect.js +22 -0
  422. package/dist/structure/geometry.d.ts +9 -0
  423. package/dist/structure/geometry.js +27 -0
  424. package/dist/structure/index.d.ts +18 -1
  425. package/dist/structure/index.js +15 -2
  426. package/dist/structure/measure.d.ts +1 -1
  427. package/dist/structure/measure.js +6 -12
  428. package/dist/structure/parse.d.ts +5 -3
  429. package/dist/structure/parse.js +551 -567
  430. package/dist/structure/partial-occupancy.d.ts +0 -1
  431. package/dist/structure/partial-occupancy.js +5 -3
  432. package/dist/structure/pbc.d.ts +1 -1
  433. package/dist/structure/pbc.js +204 -51
  434. package/dist/structure/polyhedra.d.ts +40 -0
  435. package/dist/structure/polyhedra.js +587 -0
  436. package/dist/structure/site.d.ts +4 -0
  437. package/dist/structure/site.js +1 -0
  438. package/dist/structure/supercell.d.ts +1 -2
  439. package/dist/structure/supercell.js +10 -15
  440. package/dist/structure/validation.js +5 -6
  441. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  442. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  443. package/dist/symmetry/SymmetryElements.svelte +350 -0
  444. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  445. package/dist/symmetry/SymmetryStats.svelte +142 -49
  446. package/dist/symmetry/WyckoffTable.svelte +58 -16
  447. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  448. package/dist/symmetry/cell-transform.js +8 -14
  449. package/dist/symmetry/index.d.ts +15 -4
  450. package/dist/symmetry/index.js +308 -81
  451. package/dist/symmetry/spacegroups.d.ts +5 -1
  452. package/dist/symmetry/spacegroups.js +18 -3
  453. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  454. package/dist/symmetry/symmetry-elements.js +521 -0
  455. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  456. package/dist/symmetry/wyckoff-db.js +87 -0
  457. package/dist/table/HeatmapTable.svelte +1104 -378
  458. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  459. package/dist/table/ToggleMenu.svelte +5 -12
  460. package/dist/table/index.d.ts +21 -6
  461. package/dist/table/index.js +34 -21
  462. package/dist/theme/ThemeControl.svelte +16 -8
  463. package/dist/theme/index.d.ts +1 -5
  464. package/dist/theme/index.js +4 -10
  465. package/dist/theme/themes.mjs +14 -7
  466. package/dist/tooltip/KCoords.svelte +4 -1
  467. package/dist/tooltip/TooltipContent.svelte +2 -5
  468. package/dist/trajectory/Trajectory.svelte +556 -352
  469. package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
  470. package/dist/trajectory/TrajectoryError.svelte +11 -8
  471. package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
  472. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  473. package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
  474. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  475. package/dist/trajectory/constants.js +6 -2
  476. package/dist/trajectory/extract.js +73 -71
  477. package/dist/trajectory/format-detect.d.ts +0 -1
  478. package/dist/trajectory/format-detect.js +13 -17
  479. package/dist/trajectory/frame-reader.d.ts +2 -1
  480. package/dist/trajectory/frame-reader.js +74 -136
  481. package/dist/trajectory/helpers.d.ts +12 -2
  482. package/dist/trajectory/helpers.js +68 -37
  483. package/dist/trajectory/index.d.ts +1 -0
  484. package/dist/trajectory/index.js +3 -0
  485. package/dist/trajectory/parse/ase.d.ts +9 -1
  486. package/dist/trajectory/parse/ase.js +47 -32
  487. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  488. package/dist/trajectory/parse/diagnostics.js +14 -0
  489. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  490. package/dist/trajectory/parse/h5-utils.js +109 -0
  491. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  492. package/dist/trajectory/parse/hdf5.js +116 -106
  493. package/dist/trajectory/parse/index.d.ts +3 -4
  494. package/dist/trajectory/parse/index.js +68 -119
  495. package/dist/trajectory/parse/lammps.d.ts +0 -2
  496. package/dist/trajectory/parse/lammps.js +14 -16
  497. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  498. package/dist/trajectory/parse/pymatgen.js +74 -0
  499. package/dist/trajectory/parse/vasp.js +13 -9
  500. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  501. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  502. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  503. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  504. package/dist/trajectory/parse/xyz.d.ts +9 -21
  505. package/dist/trajectory/parse/xyz.js +38 -39
  506. package/dist/trajectory/plotting.d.ts +8 -10
  507. package/dist/trajectory/plotting.js +102 -127
  508. package/dist/utils.d.ts +4 -0
  509. package/dist/utils.js +8 -1
  510. package/dist/xrd/XrdPlot.svelte +56 -85
  511. package/dist/xrd/broadening.d.ts +2 -1
  512. package/dist/xrd/broadening.js +2 -1
  513. package/dist/xrd/calc-xrd.js +8 -15
  514. package/dist/xrd/index.d.ts +2 -2
  515. package/dist/xrd/parse.d.ts +0 -1
  516. package/dist/xrd/parse.js +56 -73
  517. package/package.json +77 -36
  518. package/dist/api/mp.d.ts +0 -6
  519. package/dist/api/mp.js +0 -22
  520. package/dist/element/data.json +0 -11864
  521. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  522. package/dist/fermi-surface/marching-cubes.js +0 -2
  523. package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
  524. package/dist/plot/core/hover-lock.svelte.js +0 -45
  525. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  526. package/dist/structure/label-placement.d.ts +0 -14
  527. package/dist/structure/label-placement.js +0 -72
@@ -1,5 +1,6 @@
1
1
  // Data extraction functions for trajectory analysis and plotting
2
2
  import { get_density } from '../structure/index';
3
+ import { calc_force_stats, copy_numeric_fields } from './helpers';
3
4
  // Common data extractor that extracts energy and structural properties
4
5
  export const energy_data_extractor = (frame) => {
5
6
  const data = {
@@ -7,18 +8,13 @@ export const energy_data_extractor = (frame) => {
7
8
  };
8
9
  if (frame.metadata) {
9
10
  // Extract energy-related properties
10
- const energy_fields = [
11
+ copy_numeric_fields(data, frame.metadata, [
11
12
  `energy`,
12
13
  `energy_per_atom`,
13
14
  `potential_energy`,
14
15
  `kinetic_energy`,
15
16
  `total_energy`,
16
- ];
17
- for (const field of energy_fields) {
18
- if (field in frame.metadata && typeof frame.metadata[field] === `number`) {
19
- data[field] = frame.metadata[field];
20
- }
21
- }
17
+ ]);
22
18
  }
23
19
  return data;
24
20
  };
@@ -30,13 +26,8 @@ export const force_stress_data_extractor = (frame) => {
30
26
  if (frame.metadata) {
31
27
  // Calculate force properties from forces array if available (preferred)
32
28
  if (frame.metadata.forces && Array.isArray(frame.metadata.forces)) {
33
- const forces = frame.metadata.forces;
34
- if (forces.length > 0) {
35
- const force_magnitudes = forces.map((force) => Math.hypot(...force));
36
- data.force_max = Math.max(...force_magnitudes);
37
- // Calculate RMS (root mean square) of force magnitudes
38
- data.force_norm = Math.sqrt(force_magnitudes.reduce((sum, f) => sum + f ** 2, 0) / force_magnitudes.length);
39
- }
29
+ // Object.assign ignores the null calc_force_stats returns for empty forces
30
+ Object.assign(data, calc_force_stats(frame.metadata.forces));
40
31
  }
41
32
  else {
42
33
  // Fallback to metadata values if forces array not available
@@ -52,12 +43,29 @@ export const force_stress_data_extractor = (frame) => {
52
43
  }
53
44
  }
54
45
  // Extract other stress and pressure properties (no duplicates expected)
55
- const other_stress_fields = [`stress_max`, `stress_frobenius`, `stress_trace`, `pressure`];
56
- for (const field of other_stress_fields) {
57
- if (field in frame.metadata && typeof frame.metadata[field] === `number`) {
58
- data[field] = frame.metadata[field];
59
- }
60
- }
46
+ copy_numeric_fields(data, frame.metadata, [
47
+ `stress_max`,
48
+ `stress_frobenius`,
49
+ `stress_trace`,
50
+ `pressure`,
51
+ ]);
52
+ }
53
+ return data;
54
+ };
55
+ // Data extractor for SCF/electronic-convergence properties. Parsers emit these
56
+ // per frame (per ionic step, or per SCF step for static single-point runs) —
57
+ // e.g. the vaspout.h5 parser fills them from VASP's OSZICAR data.
58
+ const scf_data_extractor = (frame) => {
59
+ const data = {
60
+ Step: frame.step,
61
+ };
62
+ if (frame.metadata) {
63
+ copy_numeric_fields(data, frame.metadata, [
64
+ `n_scf_steps`,
65
+ `scf_energy_delta`,
66
+ `scf_rms`,
67
+ `scf_charge_rms`,
68
+ ]);
61
69
  }
62
70
  return data;
63
71
  };
@@ -79,31 +87,20 @@ export const structural_data_extractor = (frame) => {
79
87
  }
80
88
  if (frame.metadata) {
81
89
  // Extract other structural properties, avoiding volume duplicate
82
- const structural_fields = [`temperature`];
83
- for (const field of structural_fields) {
84
- if (field in frame.metadata && typeof frame.metadata[field] === `number`)
85
- data[field] = frame.metadata[field];
86
- }
87
- // Handle density separately - prefer metadata, but calculate if not available
88
- if (frame.metadata.density && typeof frame.metadata.density === `number`) {
90
+ copy_numeric_fields(data, frame.metadata, [`temperature`]);
91
+ // Prefer metadata density (fall back to calculating from structure below).
92
+ // Finite-number check (not truthiness) so a legitimate density of 0 is kept.
93
+ if (typeof frame.metadata.density === `number` &&
94
+ Number.isFinite(frame.metadata.density)) {
89
95
  data.density = frame.metadata.density;
90
96
  }
91
- else if (`lattice` in frame.structure) {
92
- try {
93
- data.density = get_density(frame.structure);
94
- }
95
- catch (error) {
96
- console.warn(`Failed to calculate density for frame ${frame.step}:`, error);
97
- }
98
- }
99
97
  // Only use metadata volume if lattice volume is not available
100
98
  if (!data.volume && frame.metadata.volume && typeof frame.metadata.volume === `number`) {
101
99
  data.volume = frame.metadata.volume;
102
100
  }
103
101
  // Note: pressure is handled by force_stress_data_extractor to avoid duplication
104
102
  }
105
- else if (`lattice` in frame.structure) {
106
- // Calculate density even when no metadata is available
103
+ if (data.density === undefined && `lattice` in frame.structure) {
107
104
  try {
108
105
  data.density = get_density(frame.structure);
109
106
  }
@@ -113,50 +110,55 @@ export const structural_data_extractor = (frame) => {
113
110
  }
114
111
  return data;
115
112
  };
116
- // Helper function to check if a property varies across trajectory frames
117
- function property_varies(trajectory, property_key, tolerance = 1e-10) {
118
- if (trajectory.frames.length <= 1)
119
- return false;
120
- const values = [];
113
+ const LATTICE_PARAMS = [`a`, `b`, `c`, `alpha`, `beta`, `gamma`];
114
+ // Cache per trajectory: full_data_extractor runs once per frame, so without this it
115
+ // rescans all frames on every call (O(n²)). WeakMap → GC'd with the trajectory.
116
+ const constant_params_cache = new WeakMap();
117
+ // Lattice params constant across the trajectory, in a single pass (prefer lattice value,
118
+ // else metadata; tol 1e-10). A param must be observed in ≥1 frame to count as constant;
119
+ // params absent from every frame are excluded (not silently treated as "constant").
120
+ function get_constant_lattice_params(trajectory) {
121
+ const cached = constant_params_cache.get(trajectory);
122
+ if (cached)
123
+ return cached;
124
+ const tolerance = 1e-10;
125
+ const first_values = new Map();
126
+ const varies = new Set();
121
127
  for (const frame of trajectory.frames) {
122
- // Check both direct structure properties and metadata
123
- let value;
124
- if (`lattice` in frame.structure) {
125
- const lattice_value = frame.structure.lattice[property_key];
126
- if (typeof lattice_value === `number`)
127
- value = lattice_value;
128
- }
129
- if (value === undefined && frame.metadata && property_key in frame.metadata) {
130
- const metadata_value = frame.metadata[property_key];
131
- if (typeof metadata_value === `number`) {
132
- value = metadata_value;
133
- }
134
- }
135
- if (value !== undefined) {
136
- values.push(value);
128
+ const lattice = `lattice` in frame.structure
129
+ ? frame.structure.lattice
130
+ : null;
131
+ for (const param of LATTICE_PARAMS) {
132
+ if (varies.has(param))
133
+ continue; // already known to vary, skip
134
+ const lattice_value = lattice?.[param];
135
+ const value = typeof lattice_value === `number` ? lattice_value : frame.metadata?.[param];
136
+ // Number.isFinite: NaN is typeof `number` but Math.abs(next-NaN)=NaN → false constant
137
+ if (typeof value !== `number` || !Number.isFinite(value))
138
+ continue;
139
+ const first = first_values.get(param);
140
+ if (first === undefined)
141
+ first_values.set(param, value);
142
+ else if (Math.abs(value - first) > tolerance)
143
+ varies.add(param);
137
144
  }
138
145
  }
139
- if (values.length <= 1)
140
- return false;
141
- const first_value = values[0];
142
- return values.some((value) => Math.abs(value - first_value) > tolerance);
146
+ // only params observed in ≥1 frame; a never-present param is not "constant"
147
+ const constant = new Set([...first_values.keys()].filter((param) => !varies.has(param)));
148
+ constant_params_cache.set(trajectory, constant);
149
+ return constant;
143
150
  }
144
151
  // Combined data extractor that extracts all common properties
145
152
  export const full_data_extractor = (frame, trajectory) => {
146
- const base_data = {
153
+ const result = {
147
154
  ...energy_data_extractor(frame, trajectory),
148
155
  ...force_stress_data_extractor(frame, trajectory),
156
+ ...scf_data_extractor(frame, trajectory),
149
157
  ...structural_data_extractor(frame, trajectory),
150
158
  };
151
- // Check which lattice parameters vary
152
- const lattice_params = [`a`, `b`, `c`, `alpha`, `beta`, `gamma`];
153
- const result = { ...base_data };
154
- // Add metadata to specify which properties don't vary
155
- for (const param of lattice_params) {
156
- if (!property_varies(trajectory, param)) {
157
- // Mark individual lattice parameters as constant
158
- result[`constant_${param}`] = 1;
159
- }
159
+ // Mark individual lattice parameters that don't vary across the trajectory
160
+ for (const param of get_constant_lattice_params(trajectory)) {
161
+ result[`constant_${param}`] = 1;
160
162
  }
161
163
  return result;
162
164
  };
@@ -1,4 +1,3 @@
1
- export declare function strip_compression_extensions(filename: string): string;
2
1
  export declare function ext_hint(filename: string | undefined, ext_regex: RegExp): boolean | null;
3
2
  export declare const FORMAT_PATTERNS: {
4
3
  readonly ase: (data: unknown, filename?: string) => boolean;
@@ -1,16 +1,11 @@
1
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';
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/decompress';
4
+ import { parse_leading_num } from '../utils';
3
5
  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
6
  // Extensions that explicitly identify a format — when present, format detection trusts
12
7
  // the extension instead of sniffing content
13
- 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)$/;
14
9
  // Classify the filename hint for a format whose extensions match ext_regex:
15
10
  // true = filename matches, false = filename names a different known format,
16
11
  // null = no usable hint (missing filename or unrecognized extension, e.g. the UUID
@@ -35,12 +30,12 @@ export const FORMAT_PATTERNS = {
35
30
  return [0x2d, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x6c, 0x6d].every((byte, idx) => view[idx] === byte);
36
31
  },
37
32
  hdf5: (data, filename) => {
38
- if (ext_hint(filename, /\.(h5|hdf5)$/) === false)
33
+ if (ext_hint(filename, /\.(?:h5|hdf5)$/) === false)
39
34
  return false;
40
35
  if (!(data instanceof ArrayBuffer) || data.byteLength < 8)
41
36
  return false;
42
37
  const signature = new Uint8Array(data.slice(0, 8));
43
- return [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a].every((b, idx) => signature[idx] === b);
38
+ return [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a].every((byte, idx) => signature[idx] === byte);
44
39
  },
45
40
  vasp: (data, filename) => {
46
41
  const basename = filename?.toLowerCase().split(`/`).pop() ?? ``;
@@ -49,11 +44,11 @@ export const FORMAT_PATTERNS = {
49
44
  const lines = data.trim().split(/\r?\n/);
50
45
  return (lines.length >= 10 &&
51
46
  lines.some((line) => line.includes(`Direct configuration=`)) &&
52
- !isNaN(parseFloat(lines[1])) &&
47
+ !isNaN(parse_leading_num(lines[1])) &&
53
48
  lines.slice(2, 5).every((line) => line.trim().split(/\s+/).length === 3));
54
49
  },
55
50
  xyz_multi: (data, filename) => {
56
- if (ext_hint(filename, /\.(xyz|extxyz)$/) === false)
51
+ if (ext_hint(filename, /\.(?:xyz|extxyz)$/) === false)
57
52
  return false;
58
53
  return count_xyz_frames(data) >= 2;
59
54
  },
@@ -69,7 +64,7 @@ export function is_trajectory_file(filename, content) {
69
64
  return false;
70
65
  const base_name = strip_compression_extensions(filename);
71
66
  // For xyz/extxyz files, use content-based detection if available
72
- if (/\.(xyz|extxyz)$/i.test(base_name)) {
67
+ if (/\.(?:xyz|extxyz)$/i.test(base_name)) {
73
68
  if (content)
74
69
  return count_xyz_frames(content) >= 2;
75
70
  return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
@@ -80,9 +75,10 @@ export function is_trajectory_file(filename, content) {
80
75
  // Special exclusion for generic md_simulation pattern with certain extensions
81
76
  if (MD_SIM_EXCLUDE_REGEX.test(base_name))
82
77
  return false;
83
- // For .h5/.hdf5 files, require trajectory keywords
84
- if (/\.(h5|hdf5)$/i.test(base_name)) {
85
- return TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
78
+ // For .h5/.hdf5 files, require trajectory keywords. vaspout.h5 (VASP's
79
+ // HDF5 output) is always trajectory-shaped regardless of keywords.
80
+ if (/\.(?:h5|hdf5)$/i.test(base_name)) {
81
+ return /vaspout/i.test(base_name) || TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name);
86
82
  }
87
83
  // For other extensions, require both keywords and specific extensions
88
84
  return (TRAJ_KEYWORDS_SIMPLE_REGEX.test(base_name) &&
@@ -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,8 +11,8 @@ 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
- private parse_xyz_metadata;
16
17
  private parse_ase_metadata;
17
18
  }
@@ -1,12 +1,22 @@
1
1
  // Unified frame loader for XYZ and ASE trajectories (large file indexing)
2
2
  import * as math from '../math';
3
3
  import { MAX_METADATA_SIZE } from './constants';
4
- import { convert_atomic_numbers, count_xyz_frames, create_trajectory_frame, read_ndarray_from_view, validate_3x3_matrix, } from './helpers';
5
- import { strip_compression_extensions } from './format-detect';
6
- import { parse_extxyz_lattice, parse_xyz_atom_lines, parse_xyz_comment_metadata, } from './parse/xyz';
4
+ import { copy_numeric_fields, count_xyz_frames, iter_xyz_frames, validate_3x3_matrix, } from './helpers';
5
+ import { strip_compression_extensions } from '../io/decompress';
6
+ import { decode_ase_frame, read_ase_header } from './parse/ase';
7
+ import { build_xyz_frame, parse_xyz_comment_metadata } from './parse/xyz';
8
+ // Restrict frame metadata to the requested property keys (no-op when unset)
9
+ const filter_properties = (metadata, properties) => {
10
+ if (!properties)
11
+ return;
12
+ metadata.properties = Object.fromEntries(Object.entries(metadata.properties).filter(([key]) => properties.includes(key)));
13
+ };
7
14
  export class TrajFrameReader {
8
15
  format;
9
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;
10
20
  constructor(filename) {
11
21
  const base_filename = strip_compression_extensions(filename);
12
22
  this.format = base_filename.endsWith(`.traj`) ? `ase` : `xyz`;
@@ -19,8 +29,7 @@ export class TrajFrameReader {
19
29
  }
20
30
  if (!(data instanceof ArrayBuffer))
21
31
  throw new Error(`ASE loader requires binary data`);
22
- const view = new DataView(data);
23
- return Number(view.getBigInt64(32, true));
32
+ return read_ase_header(new DataView(data)).n_items;
24
33
  }
25
34
  async build_frame_index(data, sample_rate, on_progress) {
26
35
  const total_frames = await this.get_total_frames(data);
@@ -31,35 +40,25 @@ export class TrajFrameReader {
31
40
  const encoder = new TextEncoder();
32
41
  const newline_sequence = data_str.includes(`\r\n`) ? `\r\n` : `\n`;
33
42
  const newline_byte_len = encoder.encode(newline_sequence).length;
34
- let [current_frame, line_idx, byte_offset] = [0, 0, 0];
35
- while (line_idx < lines.length && current_frame < total_frames) {
36
- if (!lines[line_idx]?.trim()) {
37
- byte_offset += encoder.encode(lines[line_idx]).length + newline_byte_len;
38
- line_idx++;
39
- continue;
40
- }
41
- const num_atoms = parseInt(lines[line_idx].trim(), 10);
42
- if (isNaN(num_atoms) || num_atoms <= 0 || line_idx + num_atoms + 1 >= lines.length) {
43
- byte_offset += encoder.encode(lines[line_idx]).length + newline_byte_len;
44
- line_idx++;
45
- continue;
46
- }
43
+ const line_bytes = (idx) => encoder.encode(lines[idx]).length + newline_byte_len;
44
+ // cursor = next line whose bytes haven't been added to byte_offset yet
45
+ let [current_frame, cursor, byte_offset] = [0, 0, 0];
46
+ for (const { start, num_atoms } of iter_xyz_frames(lines)) {
47
+ if (current_frame >= total_frames)
48
+ break;
49
+ // Accumulate bytes of blank/invalid lines skipped before this frame
50
+ for (; cursor < start; cursor++)
51
+ byte_offset += line_bytes(cursor);
52
+ let frame_size = 0;
53
+ for (; cursor < start + num_atoms + 2; cursor++)
54
+ frame_size += line_bytes(cursor);
47
55
  if (current_frame % sample_rate === 0) {
48
56
  frame_index.push({
49
57
  frame_number: current_frame,
50
58
  byte_offset,
51
- estimated_size: 0,
59
+ estimated_size: frame_size,
52
60
  });
53
61
  }
54
- const frame_start = line_idx;
55
- line_idx += 2 + num_atoms;
56
- let frame_size = 0;
57
- for (let idx = frame_start; idx < line_idx; idx++) {
58
- frame_size += encoder.encode(lines[idx]).length + newline_byte_len;
59
- }
60
- if (current_frame % sample_rate === 0) {
61
- frame_index[frame_index.length - 1].estimated_size = frame_size;
62
- }
63
62
  byte_offset += frame_size;
64
63
  current_frame++;
65
64
  if (on_progress && current_frame % 1000 === 0) {
@@ -73,7 +72,7 @@ export class TrajFrameReader {
73
72
  }
74
73
  else {
75
74
  const view = new DataView(data);
76
- const offsets_pos = Number(view.getBigInt64(40, true));
75
+ const { offsets_pos } = read_ase_header(view);
77
76
  for (let idx = 0; idx < total_frames; idx += sample_rate) {
78
77
  const frame_offset = Number(view.getBigInt64(offsets_pos + idx * 8, true));
79
78
  frame_index.push({
@@ -111,34 +110,21 @@ export class TrajFrameReader {
111
110
  const total_frames = await this.get_total_frames(data);
112
111
  if (this.format === `xyz`) {
113
112
  const lines = data.trim().split(/\r?\n/);
114
- let [current_frame, line_idx] = [0, 0];
115
- while (line_idx < lines.length && current_frame < total_frames) {
116
- if (!lines[line_idx]?.trim()) {
117
- line_idx++;
118
- continue;
119
- }
120
- const num_atoms = parseInt(lines[line_idx].trim(), 10);
121
- if (isNaN(num_atoms) || num_atoms <= 0 || line_idx + num_atoms + 1 >= lines.length) {
122
- line_idx++;
123
- continue;
124
- }
113
+ let current_frame = 0;
114
+ for (const { comment } of iter_xyz_frames(lines)) {
115
+ if (current_frame >= total_frames)
116
+ break;
125
117
  if (current_frame % sample_rate === 0) {
126
- const comment = lines[line_idx + 1] || ``;
127
- let frame_metadata = null;
128
- try {
129
- frame_metadata = this.parse_xyz_metadata(comment, current_frame);
130
- }
131
- catch (error) {
132
- console.warn(`Failed to parse XYZ metadata for frame ${current_frame} at line ${line_idx + 1}:`, error);
133
- }
134
- if (frame_metadata && properties) {
135
- const filtered = Object.fromEntries(Object.entries(frame_metadata.properties).filter(([key]) => properties.includes(key)));
136
- frame_metadata.properties = filtered;
137
- }
138
- if (frame_metadata)
139
- metadata_list.push(frame_metadata);
118
+ // parse_xyz_comment_metadata is pure regex/parseFloat and never throws
119
+ const { step, properties: props } = parse_xyz_comment_metadata(comment);
120
+ const frame_metadata = {
121
+ frame_number: current_frame,
122
+ step: step ?? current_frame,
123
+ properties: props,
124
+ };
125
+ filter_properties(frame_metadata, properties);
126
+ metadata_list.push(frame_metadata);
140
127
  }
141
- line_idx += 2 + num_atoms;
142
128
  current_frame++;
143
129
  if (on_progress && current_frame % 5000 === 0) {
144
130
  on_progress({
@@ -151,8 +137,7 @@ export class TrajFrameReader {
151
137
  }
152
138
  else if (this.format === `ase`) {
153
139
  const view = new DataView(data);
154
- const n_items = Number(view.getBigInt64(32, true));
155
- const offsets_pos = Number(view.getBigInt64(40, true));
140
+ const { n_items, offsets_pos } = read_ase_header(view);
156
141
  for (let idx = 0; idx < n_items; idx += sample_rate) {
157
142
  try {
158
143
  const frame_offset = Number(view.getBigInt64(offsets_pos + idx * 8, true));
@@ -163,10 +148,7 @@ export class TrajFrameReader {
163
148
  }
164
149
  const frame_data = JSON.parse(new TextDecoder().decode(new Uint8Array(data, frame_offset + 8, json_length)));
165
150
  const frame_metadata = this.parse_ase_metadata(frame_data, idx);
166
- if (properties) {
167
- const filtered = Object.fromEntries(Object.entries(frame_metadata.properties).filter(([key]) => properties.includes(key)));
168
- frame_metadata.properties = filtered;
169
- }
151
+ filter_properties(frame_metadata, properties);
170
152
  metadata_list.push(frame_metadata);
171
153
  if (on_progress && idx % 5000 === 0) {
172
154
  on_progress({
@@ -183,107 +165,63 @@ export class TrajFrameReader {
183
165
  }
184
166
  return metadata_list;
185
167
  }
186
- load_xyz_frame(data, frame_number) {
168
+ // Build + cache the line array and per-frame start indices once per payload
169
+ get_xyz_cache(data) {
170
+ if (this.xyz_cache?.data === data)
171
+ return this.xyz_cache;
187
172
  const lines = data.trim().split(/\r?\n/);
188
- let [current_frame, line_idx] = [0, 0];
189
- while (line_idx < lines.length && current_frame < frame_number) {
190
- const skip_atoms = parseInt(lines[line_idx].trim(), 10);
191
- if (isNaN(skip_atoms) || skip_atoms <= 0) {
192
- line_idx++; // skip blank/invalid lines until the next frame's atom-count line
193
- continue;
194
- }
195
- line_idx += 2 + skip_atoms;
196
- current_frame++;
197
- }
198
- if (line_idx >= lines.length)
199
- return null;
200
- const num_atoms = parseInt(lines[line_idx].trim(), 10);
201
- if (isNaN(num_atoms) || line_idx + num_atoms + 1 >= lines.length)
202
- return null;
203
- const comment = lines[line_idx + 1] || ``;
204
- const lattice_matrix = parse_extxyz_lattice(comment);
205
- const { elements, positions, force_stats } = parse_xyz_atom_lines(lines, line_idx + 2, num_atoms, comment, `indexed frame ${frame_number}`);
206
- const { step, properties } = this.parse_xyz_metadata(comment, frame_number);
207
- const metadata = { ...properties, ...force_stats };
208
- // Derive volume from the lattice (parity with the eager parse_xyz_trajectory parser)
209
- if (lattice_matrix)
210
- metadata.volume = math.calc_lattice_params(lattice_matrix).volume;
211
- return create_trajectory_frame(positions, elements, lattice_matrix, lattice_matrix ? [true, true, true] : undefined, step, metadata);
173
+ const frame_starts = Array.from(iter_xyz_frames(lines), ({ start }) => start);
174
+ this.xyz_cache = { data, lines, frame_starts };
175
+ return this.xyz_cache;
176
+ }
177
+ load_xyz_frame(data, frame_number) {
178
+ const { lines, frame_starts } = this.get_xyz_cache(data);
179
+ const start = frame_starts[frame_number];
180
+ if (start === undefined)
181
+ return null; // out-of-range frame
182
+ const num_atoms = Math.trunc(Number(lines[start]?.trim()));
183
+ const comment = lines[start + 1] ?? ``;
184
+ return build_xyz_frame(lines, { start, num_atoms, comment }, {
185
+ frame_label: `indexed frame ${frame_number}`,
186
+ default_step: frame_number,
187
+ });
212
188
  }
213
189
  load_ase_frame(data, frame_number) {
214
190
  try {
215
191
  const view = new DataView(data);
216
- const n_items = Number(view.getBigInt64(32, true));
217
- const offsets_pos = Number(view.getBigInt64(40, true));
192
+ const { n_items, offsets_pos } = read_ase_header(view);
218
193
  if (frame_number >= n_items)
219
194
  return null;
220
195
  const frame_offset = Number(view.getBigInt64(offsets_pos + frame_number * 8, true));
221
- const json_length = Number(view.getBigInt64(frame_offset, true));
222
- const frame_data = JSON.parse(new TextDecoder().decode(new Uint8Array(data, frame_offset + 8, json_length)));
223
- const positions_ref = frame_data[`positions.`] ?? frame_data.positions;
224
- const positions = positions_ref?.ndarray
225
- ? read_ndarray_from_view(view, positions_ref)
226
- : positions_ref;
227
- const numbers_ref = frame_data[`numbers.`] ?? frame_data.numbers ?? this.global_numbers;
228
- const numbers = numbers_ref?.ndarray
229
- ? read_ndarray_from_view(view, numbers_ref).flat()
230
- : numbers_ref;
231
- if (numbers)
232
- this.global_numbers = numbers;
233
- if (!numbers || !positions)
234
- throw new Error(`Missing atomic numbers or positions`);
235
- const cell = frame_data.cell ? validate_3x3_matrix(frame_data.cell) : undefined;
236
- const metadata = {
237
- step: frame_number,
238
- ...frame_data.calculator,
239
- ...frame_data.info,
240
- };
241
- if (cell) {
242
- try {
243
- metadata.volume = Math.abs(math.det_3x3(cell));
244
- }
245
- catch (error) {
246
- console.warn(`Failed to calculate volume for frame ${frame_number}:`, error);
247
- }
248
- }
249
- return create_trajectory_frame(positions, convert_atomic_numbers(numbers), cell, frame_data.pbc ?? [true, true, true], frame_number, metadata);
196
+ const { frame, numbers } = decode_ase_frame(view, data, frame_offset, frame_number, this.global_numbers);
197
+ this.global_numbers = numbers;
198
+ return frame;
250
199
  }
251
200
  catch (error) {
252
201
  console.warn(`Failed to load ASE frame ${frame_number}:`, error);
253
202
  return null;
254
203
  }
255
204
  }
256
- parse_xyz_metadata(comment, frame_number) {
257
- const { step, properties } = parse_xyz_comment_metadata(comment);
258
- return { frame_number, step: step ?? frame_number, properties };
259
- }
260
205
  parse_ase_metadata(frame_data, frame_number) {
261
206
  const properties = {};
262
207
  const step = frame_number;
263
208
  if (frame_data.calculator && typeof frame_data.calculator === `object`) {
264
- const calculator = frame_data.calculator;
265
- const calc_properties = [`energy`, `potential_energy`, `kinetic_energy`, `total_energy`];
266
- for (const prop of calc_properties) {
267
- if (prop in calculator && typeof calculator[prop] === `number`) {
268
- properties[prop] = calculator[prop];
269
- }
270
- }
209
+ copy_numeric_fields(properties, frame_data.calculator, [
210
+ `energy`,
211
+ `potential_energy`,
212
+ `kinetic_energy`,
213
+ `total_energy`,
214
+ ]);
271
215
  }
272
216
  if (frame_data.info && typeof frame_data.info === `object`) {
273
- const info = frame_data.info;
274
- const info_properties = [
217
+ copy_numeric_fields(properties, frame_data.info, [
275
218
  `force_max`,
276
219
  `force_norm`,
277
220
  `stress_max`,
278
221
  `stress_frobenius`,
279
222
  `pressure`,
280
223
  `temperature`,
281
- ];
282
- for (const prop of info_properties) {
283
- if (prop in info && typeof info[prop] === `number`) {
284
- properties[prop] = info[prop];
285
- }
286
- }
224
+ ]);
287
225
  }
288
226
  if (frame_data.cell && Array.isArray(frame_data.cell)) {
289
227
  try {
@@ -3,13 +3,23 @@ import * as math from '../math';
3
3
  import type { AnyStructure } from '../structure/index';
4
4
  import type { Pbc } from '../structure/pbc';
5
5
  import type { TrajectoryFrame } from './index';
6
- export declare const is_valid_element_symbol: (symbol: string) => symbol is ElementSymbol;
7
- export declare const coerce_element_symbol: (symbol: string) => ElementSymbol | undefined;
8
6
  export declare function validate_3x3_matrix(data: unknown): math.Matrix3x3;
9
7
  export declare const convert_atomic_numbers: (numbers: number[]) => ElementSymbol[];
8
+ export declare const count_elements: (elements: readonly string[]) => Record<string, number>;
10
9
  export declare const create_structure: (positions: number[][], elements: ElementSymbol[], lattice_matrix?: math.Matrix3x3, pbc?: Pbc, force_data?: number[][]) => AnyStructure;
11
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;
12
11
  export declare const read_ndarray_from_view: (view: DataView, ref: {
13
12
  ndarray: unknown[];
14
13
  }) => number[][];
14
+ export declare const copy_numeric_fields: (target: Record<string, number>, source: Record<string, unknown>, fields: readonly string[]) => void;
15
+ export declare function calc_force_stats(forces: number[][]): {
16
+ force_max: number;
17
+ force_norm: number;
18
+ } | null;
19
+ export declare const is_xyz_atom_line: (parts: string[] | undefined) => boolean;
20
+ export declare function iter_xyz_frames(lines: string[]): Generator<{
21
+ start: number;
22
+ num_atoms: number;
23
+ comment: string;
24
+ }>;
15
25
  export declare function count_xyz_frames(data: string): number;