matterviz 0.3.7 → 0.4.1

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 (486) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +76 -148
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
  7. package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
  8. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  11. package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
  13. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  14. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  15. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  16. package/dist/brillouin/compute.d.ts +2 -0
  17. package/dist/brillouin/compute.js +89 -90
  18. package/dist/brillouin/geometry.d.ts +8 -0
  19. package/dist/brillouin/geometry.js +57 -0
  20. package/dist/brillouin/index.d.ts +2 -0
  21. package/dist/brillouin/index.js +2 -0
  22. package/dist/brillouin/types.d.ts +2 -2
  23. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  25. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  27. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  29. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  30. package/dist/chempot-diagram/chempot-worker.js +2 -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 +4 -4
  34. package/dist/chempot-diagram/compute.js +20 -20
  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.js +8 -7
  45. package/dist/composition/FormulaFilter.svelte +18 -11
  46. package/dist/composition/PieChart.svelte +11 -10
  47. package/dist/composition/chem-sys.d.ts +8 -0
  48. package/dist/composition/chem-sys.js +86 -0
  49. package/dist/composition/format.js +7 -4
  50. package/dist/composition/index.d.ts +1 -0
  51. package/dist/composition/index.js +1 -0
  52. package/dist/composition/parse.d.ts +0 -1
  53. package/dist/composition/parse.js +41 -31
  54. package/dist/controls.d.ts +1 -0
  55. package/dist/controls.js +0 -1
  56. package/dist/convex-hull/ConvexHull.svelte +8 -10
  57. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  58. package/dist/convex-hull/ConvexHull2D.svelte +106 -185
  59. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  60. package/dist/convex-hull/ConvexHull3D.svelte +179 -683
  61. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  62. package/dist/convex-hull/ConvexHull4D.svelte +183 -687
  63. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  64. package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
  65. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  66. package/dist/convex-hull/ConvexHullControls.svelte +88 -7
  67. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  68. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  69. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  70. package/dist/convex-hull/ConvexHullStats.svelte +36 -175
  71. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  72. package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
  73. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  74. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  75. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  76. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  77. package/dist/convex-hull/barycentric-coords.js +6 -33
  78. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  79. package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
  80. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  81. package/dist/convex-hull/demo-temperature.js +20 -22
  82. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  83. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  84. package/dist/convex-hull/helpers.d.ts +42 -7
  85. package/dist/convex-hull/helpers.js +171 -78
  86. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  87. package/dist/convex-hull/hull-state.svelte.js +124 -0
  88. package/dist/convex-hull/index.d.ts +10 -8
  89. package/dist/convex-hull/index.js +7 -2
  90. package/dist/convex-hull/thermodynamics.js +136 -960
  91. package/dist/convex-hull/types.d.ts +13 -5
  92. package/dist/convex-hull/types.js +12 -0
  93. package/dist/coordination/CoordinationBarPlot.svelte +27 -34
  94. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  95. package/dist/element/BohrAtom.svelte +2 -1
  96. package/dist/element/index.d.ts +4 -0
  97. package/dist/element/index.js +18 -0
  98. package/dist/feedback/DragOverlay.svelte +3 -1
  99. package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
  100. package/dist/feedback/StatusMessage.svelte +13 -3
  101. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  102. package/dist/fermi-surface/FermiSurface.svelte +78 -151
  103. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
  104. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  105. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  106. package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
  107. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  108. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  109. package/dist/fermi-surface/compute.js +67 -66
  110. package/dist/fermi-surface/export.js +6 -16
  111. package/dist/fermi-surface/index.d.ts +0 -1
  112. package/dist/fermi-surface/index.js +0 -1
  113. package/dist/fermi-surface/parse.d.ts +1 -1
  114. package/dist/fermi-surface/parse.js +71 -79
  115. package/dist/fermi-surface/types.d.ts +3 -2
  116. package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
  117. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
  118. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
  119. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  120. package/dist/heatmap-matrix/index.d.ts +3 -2
  121. package/dist/heatmap-matrix/index.js +1 -1
  122. package/dist/index.d.ts +1 -0
  123. package/dist/index.js +1 -0
  124. package/dist/io/ExportPane.svelte +166 -0
  125. package/dist/io/ExportPane.svelte.d.ts +17 -0
  126. package/dist/io/decompress.js +5 -4
  127. package/dist/io/export.d.ts +9 -5
  128. package/dist/io/export.js +77 -51
  129. package/dist/io/fetch.d.ts +2 -1
  130. package/dist/io/fetch.js +5 -1
  131. package/dist/io/file-drop.d.ts +8 -1
  132. package/dist/io/file-drop.js +48 -36
  133. package/dist/io/index.d.ts +2 -0
  134. package/dist/io/index.js +10 -0
  135. package/dist/io/types.d.ts +13 -0
  136. package/dist/io/url-drop.js +64 -33
  137. package/dist/isosurface/parse.js +52 -51
  138. package/dist/isosurface/slice.js +5 -4
  139. package/dist/isosurface/types.js +1 -1
  140. package/dist/keyboard.d.ts +3 -0
  141. package/dist/keyboard.js +23 -0
  142. package/dist/labels.d.ts +1 -1
  143. package/dist/labels.js +9 -8
  144. package/dist/layout/FullscreenButton.svelte +33 -0
  145. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  146. package/dist/layout/FullscreenToggle.svelte +8 -14
  147. package/dist/layout/PropertyFilter.svelte +3 -2
  148. package/dist/layout/SettingsSection.svelte +1 -1
  149. package/dist/layout/ViewerChrome.svelte +116 -0
  150. package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
  151. package/dist/layout/fullscreen.d.ts +4 -0
  152. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  153. package/dist/layout/fullscreen.svelte.js +37 -0
  154. package/dist/layout/index.d.ts +3 -0
  155. package/dist/layout/index.js +3 -0
  156. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  157. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  158. package/dist/layout/json-tree/utils.js +5 -4
  159. package/dist/marching-cubes.js +8 -13
  160. package/dist/math.d.ts +12 -4
  161. package/dist/math.js +42 -30
  162. package/dist/overlays/DraggablePane.svelte +4 -4
  163. package/dist/overlays/index.d.ts +4 -0
  164. package/dist/periodic-table/PeriodicTable.svelte +27 -15
  165. package/dist/periodic-table/PropertySelect.svelte +1 -0
  166. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  167. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  168. package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
  169. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  170. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  171. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  172. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
  173. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  174. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  175. package/dist/phase-diagram/build-diagram.js +2 -2
  176. package/dist/phase-diagram/colors.js +1 -1
  177. package/dist/phase-diagram/parse.d.ts +2 -1
  178. package/dist/phase-diagram/parse.js +6 -5
  179. package/dist/phase-diagram/types.d.ts +1 -1
  180. package/dist/phase-diagram/utils.d.ts +3 -3
  181. package/dist/phase-diagram/utils.js +8 -12
  182. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
  183. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
  184. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  185. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  186. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
  187. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  188. package/dist/plot/bar/data.d.ts +40 -0
  189. package/dist/plot/bar/data.js +154 -0
  190. package/dist/plot/bar/geometry.d.ts +39 -0
  191. package/dist/plot/bar/geometry.js +60 -0
  192. package/dist/plot/bar/index.d.ts +3 -0
  193. package/dist/plot/bar/index.js +3 -0
  194. package/dist/plot/box/BoxPlot.svelte +1292 -0
  195. package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
  196. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  197. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  198. package/dist/plot/box/Violin.svelte +14 -0
  199. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  200. package/dist/plot/box/box-plot.d.ts +56 -0
  201. package/dist/plot/box/box-plot.js +129 -0
  202. package/dist/plot/box/index.d.ts +5 -0
  203. package/dist/plot/box/index.js +5 -0
  204. package/dist/plot/box/kde.d.ts +17 -0
  205. package/dist/plot/box/kde.js +160 -0
  206. package/dist/plot/box/quantile.d.ts +3 -0
  207. package/dist/plot/box/quantile.js +53 -0
  208. package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
  209. package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
  210. package/dist/plot/core/axis-utils.d.ts +46 -0
  211. package/dist/plot/core/axis-utils.js +110 -0
  212. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  213. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  214. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
  215. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
  216. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  217. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  218. package/dist/plot/core/components/ControlPane.svelte +46 -0
  219. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  220. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  221. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  222. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  223. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  224. package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
  225. package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
  226. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
  227. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
  228. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  229. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  230. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  231. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  232. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  233. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  234. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  235. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  236. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  237. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
  238. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
  239. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
  240. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
  241. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  242. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  243. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  244. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  245. package/dist/plot/core/components/index.d.ts +17 -0
  246. package/dist/plot/core/components/index.js +17 -0
  247. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  248. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
  249. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  250. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  251. package/dist/plot/core/fill-utils.d.ts +34 -0
  252. package/dist/plot/core/fill-utils.js +391 -0
  253. package/dist/plot/core/index.d.ts +10 -0
  254. package/dist/plot/core/index.js +11 -0
  255. package/dist/plot/core/interactions.d.ts +39 -0
  256. package/dist/plot/core/interactions.js +209 -0
  257. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  258. package/dist/plot/{layout.js → core/layout.js} +16 -8
  259. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  260. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  261. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  262. package/dist/plot/core/placed-tween.svelte.js +68 -0
  263. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
  264. package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
  265. package/dist/plot/core/scales.d.ts +40 -0
  266. package/dist/plot/{scales.js → core/scales.js} +94 -93
  267. package/dist/plot/core/svg.d.ts +3 -0
  268. package/dist/plot/core/svg.js +41 -0
  269. package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
  270. package/dist/plot/{types.js → core/types.js} +1 -1
  271. package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
  272. package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
  273. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  274. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  275. package/dist/plot/core/utils.d.ts +12 -0
  276. package/dist/plot/core/utils.js +27 -0
  277. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
  278. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  279. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  280. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  281. package/dist/plot/histogram/index.d.ts +2 -0
  282. package/dist/plot/histogram/index.js +2 -0
  283. package/dist/plot/index.d.ts +8 -41
  284. package/dist/plot/index.js +10 -39
  285. package/dist/plot/sankey/Sankey.svelte +697 -0
  286. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  287. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  288. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  289. package/dist/plot/sankey/index.d.ts +4 -0
  290. package/dist/plot/sankey/index.js +3 -0
  291. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  292. package/dist/plot/sankey/sankey-types.js +4 -0
  293. package/dist/plot/sankey/sankey.d.ts +52 -0
  294. package/dist/plot/sankey/sankey.js +189 -0
  295. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
  296. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
  297. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  298. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  299. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
  300. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
  301. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  302. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
  303. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  304. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  305. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  306. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  307. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
  308. package/dist/plot/scatter/index.d.ts +7 -0
  309. package/dist/plot/scatter/index.js +5 -0
  310. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  311. package/dist/plot/scatter/scatter-data.js +212 -0
  312. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
  313. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
  314. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
  315. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
  316. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
  317. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
  318. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
  319. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
  320. package/dist/plot/scatter-3d/index.d.ts +4 -0
  321. package/dist/plot/scatter-3d/index.js +4 -0
  322. package/dist/plot/sunburst/Sunburst.svelte +1041 -0
  323. package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
  324. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  325. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  326. package/dist/plot/sunburst/index.d.ts +4 -0
  327. package/dist/plot/sunburst/index.js +4 -0
  328. package/dist/plot/sunburst/render.d.ts +34 -0
  329. package/dist/plot/sunburst/render.js +122 -0
  330. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  331. package/dist/plot/sunburst/sunburst.js +269 -0
  332. package/dist/rdf/RdfPlot.svelte +2 -1
  333. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  334. package/dist/rdf/calc-rdf.js +11 -24
  335. package/dist/sanitize.js +14 -3
  336. package/dist/scene/SceneCamera.svelte +62 -0
  337. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  338. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  339. package/dist/scene/bind-renderer.svelte.js +14 -0
  340. package/dist/scene/index.d.ts +4 -0
  341. package/dist/scene/index.js +5 -0
  342. package/dist/scene/props.js +52 -0
  343. package/dist/scene/types.d.ts +26 -0
  344. package/dist/scene/types.js +1 -0
  345. package/dist/settings.d.ts +79 -3
  346. package/dist/settings.js +321 -1
  347. package/dist/spectral/Bands.svelte +47 -36
  348. package/dist/spectral/Bands.svelte.d.ts +6 -6
  349. package/dist/spectral/BandsAndDos.svelte +23 -25
  350. package/dist/spectral/BrillouinBandsDos.svelte +42 -30
  351. package/dist/spectral/Dos.svelte +15 -23
  352. package/dist/spectral/Dos.svelte.d.ts +4 -3
  353. package/dist/spectral/helpers.d.ts +8 -6
  354. package/dist/spectral/helpers.js +137 -65
  355. package/dist/state.svelte.d.ts +0 -7
  356. package/dist/state.svelte.js +0 -6
  357. package/dist/structure/Arrow.svelte +2 -4
  358. package/dist/structure/AtomLegend.svelte +8 -9
  359. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  360. package/dist/structure/CanvasTooltip.svelte +1 -0
  361. package/dist/structure/CellSelect.svelte +12 -5
  362. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  363. package/dist/structure/Cylinder.svelte +12 -8
  364. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  365. package/dist/structure/Lattice.svelte +2 -2
  366. package/dist/structure/Structure.svelte +365 -423
  367. package/dist/structure/Structure.svelte.d.ts +5 -15
  368. package/dist/structure/StructureControls.svelte +217 -2
  369. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  370. package/dist/structure/StructureExportPane.svelte +54 -156
  371. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  372. package/dist/structure/StructureInfoPane.svelte +10 -9
  373. package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
  374. package/dist/structure/StructureScene.svelte +376 -208
  375. package/dist/structure/StructureScene.svelte.d.ts +22 -20
  376. package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
  377. package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
  378. package/dist/structure/atom-properties.d.ts +1 -1
  379. package/dist/structure/atom-properties.js +17 -22
  380. package/dist/structure/bond-order-perception.js +3 -5
  381. package/dist/structure/bonding.d.ts +4 -0
  382. package/dist/structure/bonding.js +134 -63
  383. package/dist/structure/export.d.ts +24 -4
  384. package/dist/structure/export.js +89 -143
  385. package/dist/structure/index.d.ts +4 -4
  386. package/dist/structure/index.js +3 -3
  387. package/dist/structure/measure.d.ts +3 -2
  388. package/dist/structure/measure.js +6 -5
  389. package/dist/structure/parse.d.ts +3 -2
  390. package/dist/structure/parse.js +419 -438
  391. package/dist/structure/partial-occupancy.d.ts +0 -1
  392. package/dist/structure/partial-occupancy.js +1 -1
  393. package/dist/structure/pbc.d.ts +1 -1
  394. package/dist/structure/pbc.js +190 -13
  395. package/dist/structure/polyhedra.d.ts +41 -0
  396. package/dist/structure/polyhedra.js +602 -0
  397. package/dist/structure/site.d.ts +4 -0
  398. package/dist/structure/site.js +1 -0
  399. package/dist/structure/supercell.js +3 -2
  400. package/dist/structure/validation.js +5 -6
  401. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  402. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  403. package/dist/symmetry/SymmetryElements.svelte +354 -0
  404. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  405. package/dist/symmetry/SymmetryStats.svelte +113 -8
  406. package/dist/symmetry/WyckoffTable.svelte +68 -7
  407. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  408. package/dist/symmetry/cell-transform.js +7 -14
  409. package/dist/symmetry/index.d.ts +14 -4
  410. package/dist/symmetry/index.js +291 -72
  411. package/dist/symmetry/spacegroups.d.ts +12 -1
  412. package/dist/symmetry/spacegroups.js +63 -14
  413. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  414. package/dist/symmetry/symmetry-elements.js +521 -0
  415. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  416. package/dist/symmetry/wyckoff-db.js +87 -0
  417. package/dist/table/HeatmapTable.svelte +66 -25
  418. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  419. package/dist/table/index.d.ts +1 -3
  420. package/dist/table/index.js +1 -1
  421. package/dist/theme/index.js +8 -8
  422. package/dist/tooltip/KCoords.svelte +45 -0
  423. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  424. package/dist/tooltip/index.d.ts +1 -0
  425. package/dist/tooltip/index.js +1 -0
  426. package/dist/trajectory/Trajectory.svelte +123 -100
  427. package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
  428. package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
  429. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  430. package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
  431. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  432. package/dist/trajectory/constants.js +6 -2
  433. package/dist/trajectory/extract.js +17 -37
  434. package/dist/trajectory/format-detect.d.ts +1 -1
  435. package/dist/trajectory/format-detect.js +27 -19
  436. package/dist/trajectory/frame-reader.d.ts +0 -1
  437. package/dist/trajectory/frame-reader.js +63 -162
  438. package/dist/trajectory/helpers.d.ts +10 -2
  439. package/dist/trajectory/helpers.js +56 -36
  440. package/dist/trajectory/index.js +1 -1
  441. package/dist/trajectory/parse/ase.d.ts +9 -1
  442. package/dist/trajectory/parse/ase.js +47 -32
  443. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  444. package/dist/trajectory/parse/diagnostics.js +14 -0
  445. package/dist/trajectory/parse/hdf5.js +1 -1
  446. package/dist/trajectory/parse/index.d.ts +1 -1
  447. package/dist/trajectory/parse/index.js +65 -105
  448. package/dist/trajectory/parse/lammps.d.ts +0 -2
  449. package/dist/trajectory/parse/lammps.js +8 -6
  450. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  451. package/dist/trajectory/parse/pymatgen.js +74 -0
  452. package/dist/trajectory/parse/vasp.js +38 -18
  453. package/dist/trajectory/parse/xyz.d.ts +13 -1
  454. package/dist/trajectory/parse/xyz.js +102 -94
  455. package/dist/trajectory/plotting.d.ts +1 -2
  456. package/dist/trajectory/plotting.js +16 -113
  457. package/dist/utils.d.ts +2 -0
  458. package/dist/utils.js +7 -5
  459. package/dist/xrd/XrdPlot.svelte +16 -30
  460. package/dist/xrd/broadening.d.ts +2 -1
  461. package/dist/xrd/calc-xrd.js +18 -20
  462. package/dist/xrd/index.d.ts +2 -2
  463. package/dist/xrd/parse.js +2 -2
  464. package/package.json +43 -26
  465. package/dist/element/data.json +0 -11864
  466. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  467. package/dist/fermi-surface/marching-cubes.js +0 -2
  468. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  469. package/dist/plot/axis-utils.d.ts +0 -19
  470. package/dist/plot/axis-utils.js +0 -78
  471. package/dist/plot/defaults.d.ts +0 -19
  472. package/dist/plot/defaults.js +0 -9
  473. package/dist/plot/fill-utils.d.ts +0 -46
  474. package/dist/plot/fill-utils.js +0 -322
  475. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  476. package/dist/plot/hover-lock.svelte.js +0 -46
  477. package/dist/plot/interactions.d.ts +0 -12
  478. package/dist/plot/interactions.js +0 -101
  479. package/dist/plot/scales.d.ts +0 -48
  480. package/dist/plot/svg.d.ts +0 -1
  481. package/dist/plot/svg.js +0 -11
  482. package/dist/plot/utils/series-visibility.d.ts +0 -15
  483. package/dist/plot/utils.d.ts +0 -1
  484. package/dist/plot/utils.js +0 -14
  485. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  486. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -1,16 +1,14 @@
1
1
  // Shared utilities for trajectory parsing
2
2
  import { ATOMIC_NUMBER_TO_SYMBOL } from '../composition/parse';
3
- import { ELEM_SYMBOLS } from '../labels';
3
+ import { is_elem_symbol } from '../element';
4
4
  import * as math from '../math';
5
- const element_symbol_set = new Set(ELEM_SYMBOLS);
5
+ import { make_site } from '../structure/site';
6
6
  const is_valid_row = (row) => {
7
7
  if (!(Array.isArray(row) || (ArrayBuffer.isView(row) && `length` in row)))
8
8
  return false;
9
9
  return math.is_finite_vec3_like(row);
10
10
  };
11
11
  const is_valid_vec3 = (coords) => Array.isArray(coords) && math.is_finite_vec3_like(coords);
12
- export const is_valid_element_symbol = (symbol) => element_symbol_set.has(symbol);
13
- export const coerce_element_symbol = (symbol) => is_valid_element_symbol(symbol) ? symbol : undefined;
14
12
  // Validate that data is a proper 3x3 matrix
15
13
  // Accepts both regular arrays and typed arrays (Float32Array, Float64Array, etc.)
16
14
  export function validate_3x3_matrix(data) {
@@ -24,7 +22,7 @@ export function validate_3x3_matrix(data) {
24
22
  }
25
23
  export const convert_atomic_numbers = (numbers) => numbers.map((num) => {
26
24
  const symbol = ATOMIC_NUMBER_TO_SYMBOL[num];
27
- if (!symbol || !is_valid_element_symbol(symbol)) {
25
+ if (!symbol || !is_elem_symbol(symbol)) {
28
26
  throw new Error(`Unknown atomic number in trajectory data: ${num}`);
29
27
  }
30
28
  return symbol;
@@ -42,13 +40,7 @@ export const create_structure = (positions, elements, lattice_matrix, pbc, force
42
40
  const abc = cart_to_frac ? cart_to_frac(xyz) : [0, 0, 0];
43
41
  const force = force_data?.[idx];
44
42
  const properties = is_valid_vec3(force) ? { force } : {};
45
- return {
46
- species: [{ element: elements[idx], occu: 1, oxidation_state: 0 }],
47
- abc,
48
- xyz,
49
- label: `${elements[idx]}${idx + 1}`,
50
- properties,
51
- };
43
+ return make_site(elements[idx], abc, xyz, `${elements[idx]}${idx + 1}`, properties);
52
44
  });
53
45
  return lattice_matrix
54
46
  ? {
@@ -126,39 +118,67 @@ export const read_ndarray_from_view = (view, ref) => {
126
118
  throw new Error(`Unsupported shape`);
127
119
  })();
128
120
  };
129
- // Unified frame counting for XYZ
130
- export function count_xyz_frames(data) {
131
- if (!data || typeof data !== `string`)
132
- return 0;
133
- const lines = data.trim().split(/\r?\n/);
134
- let frame_count = 0;
121
+ // Copy listed fields from source to target when they hold numbers
122
+ export const copy_numeric_fields = (target, source, fields) => {
123
+ for (const field of fields) {
124
+ if (field in source && typeof source[field] === `number`)
125
+ target[field] = source[field];
126
+ }
127
+ };
128
+ // Max and RMS of per-atom force magnitudes, or null when no forces present. Loop-based
129
+ // rather than Math.max(...spread) to avoid call-stack overflow on very large frames.
130
+ export function calc_force_stats(forces) {
131
+ if (forces.length === 0)
132
+ return null;
133
+ let force_max = -Infinity;
134
+ let sum_sq = 0;
135
+ for (const force of forces) {
136
+ const magnitude = Math.hypot(...force);
137
+ if (magnitude > force_max)
138
+ force_max = magnitude;
139
+ sum_sq += magnitude ** 2;
140
+ }
141
+ return { force_max, force_norm: Math.sqrt(sum_sq / forces.length) };
142
+ }
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
145
+ // first few atom lines look like "<element> <x> <y> <z>"; otherwise we advance one line and
146
+ // rescan. That validation doubles as content sniffing so numeric-leading non-XYZ formats
147
+ // (e.g. VASP XDATCAR) aren't misread as frames, and keeps count_xyz_frames consistent with
148
+ // the actual parse/index walk (both go through this single source of truth).
149
+ export function* iter_xyz_frames(lines) {
135
150
  let line_idx = 0;
136
151
  while (line_idx < lines.length) {
137
- if (!lines[line_idx]?.trim()) {
138
- line_idx++;
139
- continue;
140
- }
141
- const num_atoms = parseInt(lines[line_idx].trim(), 10);
152
+ const num_atoms = parseInt(lines[line_idx]?.trim(), 10);
142
153
  if (isNaN(num_atoms) || num_atoms <= 0 || line_idx + num_atoms + 2 > lines.length) {
143
- line_idx++;
154
+ line_idx++; // skip blank/invalid lines until the next frame's atom-count line
144
155
  continue;
145
156
  }
146
- // Quick validation of first few atom lines
147
157
  let valid_coords = 0;
148
- for (let idx = 0; idx < Math.min(num_atoms, 3); idx++) {
158
+ const sample = Math.min(num_atoms, 3);
159
+ for (let idx = 0; idx < sample; idx++) {
149
160
  const parts = lines[line_idx + 2 + idx]?.trim().split(/\s+/);
150
- if (parts?.length >= 4 && isNaN(parseInt(parts[0])) && parts[0].length <= 3) {
151
- if (parts.slice(1, 4).every((coord) => !isNaN(parseFloat(coord))))
152
- valid_coords++;
153
- }
154
- }
155
- if (valid_coords >= Math.min(num_atoms, 3)) {
156
- frame_count++;
157
- line_idx += 2 + num_atoms;
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))))
165
+ valid_coords++;
158
166
  }
159
- else {
160
- line_idx++;
167
+ if (valid_coords < sample) {
168
+ line_idx++; // count line looks valid but atom lines don't — likely non-XYZ content
169
+ continue;
161
170
  }
171
+ yield { start: line_idx, num_atoms, comment: lines[line_idx + 1] || `` };
172
+ line_idx += num_atoms + 2;
162
173
  }
174
+ }
175
+ // Count XYZ frames via iter_xyz_frames so total_frames matches what gets indexed/loaded
176
+ export function count_xyz_frames(data) {
177
+ if (!data || typeof data !== `string`)
178
+ return 0;
179
+ const frames = iter_xyz_frames(data.trim().split(/\r?\n/));
180
+ let frame_count = 0;
181
+ while (!frames.next().done)
182
+ frame_count += 1;
163
183
  return frame_count;
164
184
  }
@@ -77,7 +77,7 @@ export function validate_trajectory(trajectory) {
77
77
  }
78
78
  export function get_trajectory_stats(trajectory) {
79
79
  const { frames, total_frames, indexed_frames, plot_metadata } = trajectory;
80
- const frame_count = total_frames || frames.length;
80
+ const frame_count = total_frames ?? frames.length;
81
81
  const stats = {
82
82
  frame_count,
83
83
  is_indexed: trajectory.is_indexed ?? false,
@@ -1,2 +1,10 @@
1
- import type { TrajectoryType } from '../index';
1
+ import type { TrajectoryFrame, TrajectoryType } from '../index';
2
+ export declare const read_ase_header: (view: DataView) => {
3
+ n_items: number;
4
+ offsets_pos: number;
5
+ };
6
+ export declare function decode_ase_frame(view: DataView, buffer: ArrayBuffer, frame_offset: number, step: number, fallback_numbers?: number[], max_json_length?: number): {
7
+ frame: TrajectoryFrame;
8
+ numbers: number[];
9
+ };
2
10
  export declare function parse_ase_trajectory(buffer: ArrayBuffer, filename?: string): TrajectoryType;
@@ -1,18 +1,55 @@
1
1
  // ASE trajectory (.traj) parsing - binary format
2
+ import * as math from '../../math';
2
3
  import { MAX_SAFE_STRING_LENGTH } from '../constants';
3
4
  import { convert_atomic_numbers, create_trajectory_frame, read_ndarray_from_view, validate_3x3_matrix, } from '../helpers';
5
+ // ULM header: frame count lives at byte 32, frame-offsets table position at byte 40
6
+ export const read_ase_header = (view) => ({
7
+ n_items: Number(view.getBigInt64(32, true)),
8
+ offsets_pos: Number(view.getBigInt64(40, true)),
9
+ });
10
+ // Decode a single ASE/ULM frame (JSON header + optional ndarray payloads) into a
11
+ // TrajectoryFrame. Returns the atomic numbers actually used so callers can cache them
12
+ // as fallback for later frames that omit `numbers` (ASE stores them only once).
13
+ export function decode_ase_frame(view, buffer, frame_offset, step, fallback_numbers, max_json_length) {
14
+ const json_length = Number(view.getBigInt64(frame_offset, true));
15
+ if (max_json_length !== undefined && json_length > max_json_length) {
16
+ throw new Error(`frame JSON too large: ${json_length} bytes`);
17
+ }
18
+ const frame_data = JSON.parse(new TextDecoder().decode(new Uint8Array(buffer, frame_offset + 8, json_length)));
19
+ const positions_ref = frame_data[`positions.`] ?? frame_data.positions;
20
+ const positions = positions_ref?.ndarray
21
+ ? read_ndarray_from_view(view, positions_ref)
22
+ : positions_ref;
23
+ const numbers_ref = frame_data[`numbers.`] ?? frame_data.numbers ?? fallback_numbers;
24
+ const numbers = numbers_ref?.ndarray
25
+ ? read_ndarray_from_view(view, numbers_ref).flat()
26
+ : numbers_ref;
27
+ if (!numbers || !positions) {
28
+ throw new Error(`missing ${!numbers ? `numbers` : `positions`}`);
29
+ }
30
+ const cell = frame_data.cell ? validate_3x3_matrix(frame_data.cell) : undefined;
31
+ const metadata = {
32
+ step,
33
+ ...frame_data.calculator,
34
+ ...frame_data.info,
35
+ };
36
+ if (cell) {
37
+ try {
38
+ metadata.volume = Math.abs(math.det_3x3(cell));
39
+ }
40
+ catch (error) {
41
+ console.warn(`Failed to calculate volume for frame ${step}:`, error);
42
+ }
43
+ }
44
+ const frame = create_trajectory_frame(positions, convert_atomic_numbers(numbers), cell, frame_data.pbc ?? [true, true, true], step, metadata);
45
+ return { frame, numbers };
46
+ }
4
47
  export function parse_ase_trajectory(buffer, filename) {
5
48
  const view = new DataView(buffer);
6
- let offset = 0;
7
49
  const signature = new TextDecoder().decode(new Uint8Array(buffer, 0, 8));
8
50
  if (signature !== `- of Ulm`)
9
51
  throw new Error(`Invalid ASE trajectory`);
10
- offset += 24;
11
- // Skip ASE/Ulm version field; current parsing logic is version-independent.
12
- offset += 8;
13
- const n_items = Number(view.getBigInt64(offset, true));
14
- offset += 8;
15
- const offsets_pos = Number(view.getBigInt64(offset, true));
52
+ const { n_items, offsets_pos } = read_ase_header(view);
16
53
  if (n_items <= 0)
17
54
  throw new Error(`Invalid frame count`);
18
55
  if (offsets_pos < 0 || offsets_pos + n_items * 8 > buffer.byteLength) {
@@ -23,31 +60,9 @@ export function parse_ase_trajectory(buffer, filename) {
23
60
  let global_numbers;
24
61
  for (let idx = 0; idx < n_items; idx++) {
25
62
  try {
26
- offset = frame_offsets[idx];
27
- const json_length = Number(view.getBigInt64(offset, true));
28
- offset += 8;
29
- if (json_length > MAX_SAFE_STRING_LENGTH) {
30
- console.warn(`Skipping frame ${idx + 1}/${n_items}: too large`);
31
- continue;
32
- }
33
- const frame_data = JSON.parse(new TextDecoder().decode(new Uint8Array(buffer, offset, json_length)));
34
- const positions_ref = frame_data[`positions.`] ?? frame_data.positions;
35
- const positions = positions_ref?.ndarray
36
- ? read_ndarray_from_view(view, positions_ref)
37
- : positions_ref;
38
- const numbers_ref = frame_data[`numbers.`] ?? frame_data.numbers ?? global_numbers;
39
- const numbers = numbers_ref?.ndarray
40
- ? read_ndarray_from_view(view, numbers_ref).flat()
41
- : numbers_ref;
42
- if (numbers)
43
- global_numbers = numbers;
44
- if (!numbers || !positions) {
45
- console.warn(`Skipping ASE frame ${idx + 1}/${n_items}: missing ${!numbers ? `numbers` : `positions`}`);
46
- continue;
47
- }
48
- const elements = convert_atomic_numbers(numbers);
49
- const metadata = { step: idx, ...frame_data.calculator, ...frame_data.info };
50
- frames.push(create_trajectory_frame(positions, elements, frame_data.cell ? validate_3x3_matrix(frame_data.cell) : undefined, frame_data.pbc ?? [true, true, true], idx, metadata));
63
+ const { frame, numbers } = decode_ase_frame(view, buffer, frame_offsets[idx], idx, global_numbers, MAX_SAFE_STRING_LENGTH);
64
+ global_numbers = numbers;
65
+ frames.push(frame);
51
66
  }
52
67
  catch (error) {
53
68
  console.warn(`Error processing frame ${idx + 1}/${n_items}:`, error);
@@ -0,0 +1,3 @@
1
+ export declare const get_traj_parse_warnings: () => string[];
2
+ export declare const reset_traj_parse_warnings: () => void;
3
+ export declare const traj_warn: (message: string, error?: unknown) => void;
@@ -0,0 +1,14 @@
1
+ import { to_error } from '../../utils';
2
+ // Collector for non-fatal trajectory parse warnings (skipped atoms, dropped frames, plot-metadata extraction failures, ...) so they reach the UI not just the console. Reset at the start of each top-level parse call; format parsers append via traj_warn (mirrored to console.warn). Fatal failures throw — see parse_trajectory_data.
3
+ let traj_parse_warnings = [];
4
+ // Read-only snapshot of warnings since the last top-level parse (attached to trajectory metadata by parse/index.ts for UI surfacing)
5
+ export const get_traj_parse_warnings = () => [...traj_parse_warnings];
6
+ export const reset_traj_parse_warnings = () => void (traj_parse_warnings = []);
7
+ export const traj_warn = (message, error) => {
8
+ const detail = error === undefined ? `` : `: ${to_error(error).message}`;
9
+ traj_parse_warnings.push(`${message}${detail}`);
10
+ if (error === undefined)
11
+ console.warn(message);
12
+ else
13
+ console.warn(`${message}:`, error);
14
+ };
@@ -9,7 +9,7 @@ export async function parse_torch_sim_hdf5(buffer, filename) {
9
9
  const file_basename = filename
10
10
  ?.split(`/`)
11
11
  .at(-1)
12
- ?.replace(/[^\w.-]/g, `_`) || `temp`;
12
+ ?.replaceAll(/[^\w.-]/g, `_`) ?? `temp`;
13
13
  const unique_suffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
14
14
  const temp_filename = `${file_basename}-${unique_suffix}.h5`;
15
15
  FS.writeFile(temp_filename, new Uint8Array(buffer));
@@ -2,7 +2,7 @@ import { is_trajectory_file } from '../format-detect';
2
2
  import { TrajFrameReader } from '../frame-reader';
3
3
  import type { FrameLoader, ParseProgress, TrajectoryType } from '../index';
4
4
  import type { AtomTypeMapping, LoadingOptions } from '../types';
5
- export { INDEX_SAMPLE_RATE, LARGE_FILE_THRESHOLD, MAX_BIN_FILE_SIZE, MAX_METADATA_SIZE, MAX_SAFE_STRING_LENGTH, MAX_TEXT_FILE_SIZE, } from '../constants';
5
+ export { LARGE_FILE_THRESHOLD, MAX_BIN_FILE_SIZE, MAX_TEXT_FILE_SIZE, } from '../constants';
6
6
  export type { AtomTypeMapping, LoadingOptions } from '../types';
7
7
  export { is_trajectory_file, TrajFrameReader };
8
8
  export declare function parse_trajectory_data(data: unknown, filename?: string, atom_type_mapping?: AtomTypeMapping): Promise<TrajectoryType>;
@@ -1,21 +1,31 @@
1
+ // Parsing functions for trajectory data from various formats
1
2
  import { is_binary } from '../../io/is-binary';
2
- import * as math from '../../math';
3
- import { parse_xyz } from '../../structure/parse';
3
+ import { is_plain_object } from '../../utils';
4
+ import { is_parsed_structure, parse_xyz } from '../../structure/parse';
4
5
  import { INDEX_SAMPLE_RATE, LARGE_FILE_THRESHOLD } from '../constants';
5
- import { FORMAT_PATTERNS, is_trajectory_file, strip_compression_extensions, } from '../format-detect';
6
+ import { strip_compression_extensions } from '../../io';
7
+ import { ext_hint, FORMAT_PATTERNS, is_trajectory_file } from '../format-detect';
6
8
  import { TrajFrameReader } from '../frame-reader';
7
- import { create_trajectory_frame, validate_3x3_matrix } from '../helpers';
9
+ import { count_xyz_frames } from '../helpers';
8
10
  import { parse_ase_trajectory } from './ase';
11
+ import { get_traj_parse_warnings, reset_traj_parse_warnings, traj_warn } from './diagnostics';
9
12
  import { parse_torch_sim_hdf5 } from './hdf5';
10
13
  import { parse_lammps_trajectory } from './lammps';
14
+ import { parse_pymatgen_trajectory } from './pymatgen';
11
15
  import { parse_vasp_xdatcar } from './vasp';
12
16
  import { parse_xyz_trajectory } from './xyz';
13
- // Silently swallow expected parse fallbacks the caller throws if ALL formats fail
14
- const log_parse_debug = (_message, _error) => { };
17
+ // Throw on a trajectory frame whose structure isn't a valid parsed structure (non-empty sites with species + coords)
18
+ const assert_frame_structure = (structure, label) => {
19
+ if (!is_parsed_structure(structure)) {
20
+ const context = typeof label === `number` ? `trajectory frame ${label}` : label;
21
+ throw new Error(`Invalid structure in ${context}: expected non-empty 'sites' array with species and coordinates`);
22
+ }
23
+ };
15
24
  // Re-export constants and types for consumers
16
- export { INDEX_SAMPLE_RATE, LARGE_FILE_THRESHOLD, MAX_BIN_FILE_SIZE, MAX_METADATA_SIZE, MAX_SAFE_STRING_LENGTH, MAX_TEXT_FILE_SIZE, } from '../constants';
25
+ export { LARGE_FILE_THRESHOLD, MAX_BIN_FILE_SIZE, MAX_TEXT_FILE_SIZE, } from '../constants';
17
26
  export { is_trajectory_file, TrajFrameReader };
18
27
  export async function parse_trajectory_data(data, filename, atom_type_mapping) {
28
+ reset_traj_parse_warnings();
19
29
  if (data instanceof ArrayBuffer) {
20
30
  if (FORMAT_PATTERNS.ase(data, filename))
21
31
  return parse_ase_trajectory(data, filename);
@@ -33,8 +43,10 @@ export async function parse_trajectory_data(data, filename, atom_type_mapping) {
33
43
  if (FORMAT_PATTERNS.lammpstrj(content, filename)) {
34
44
  return parse_lammps_trajectory(content, filename, atom_type_mapping);
35
45
  }
36
- // Single XYZ fallback
37
- if (filename?.toLowerCase().match(/\.(?:xyz|extxyz)$/)) {
46
+ // Single XYZ fallback (content-sniffed when the filename gives no format hint,
47
+ // e.g. blob: object URLs whose basenames are UUIDs)
48
+ const xyz_hint = ext_hint(filename, /\.(xyz|extxyz)$/);
49
+ if (xyz_hint || (xyz_hint === null && count_xyz_frames(content) === 1)) {
38
50
  try {
39
51
  const structure = parse_xyz(content);
40
52
  if (structure) {
@@ -44,127 +56,62 @@ export async function parse_trajectory_data(data, filename, atom_type_mapping) {
44
56
  };
45
57
  }
46
58
  }
47
- catch (error) {
59
+ catch {
48
60
  // Single-frame XYZ parsing failed, continue to JSON parsing.
49
- log_parse_debug(`Single XYZ parse fallback failed for ${filename ?? `unknown file`}:`, error);
50
61
  }
51
62
  }
52
63
  try {
53
64
  data = JSON.parse(content);
54
65
  }
55
66
  catch (error) {
56
- log_parse_debug(`JSON parse failed for ${filename ?? `unknown file`}:`, error);
57
67
  throw new Error(`Unsupported text format`, { cause: error });
58
68
  }
59
69
  }
60
- if (!data || typeof data !== `object`)
61
- throw new Error(`Invalid data format`);
62
70
  // Handle JSON formats
63
71
  if (Array.isArray(data)) {
64
72
  const frames = data.map((frame_data, idx) => {
65
73
  const frame_obj = frame_data;
66
74
  const frame_step = frame_obj.step;
75
+ const structure = frame_obj.structure ?? frame_obj;
76
+ assert_frame_structure(structure, idx);
67
77
  return {
68
- structure: (frame_obj.structure || frame_obj),
78
+ structure: structure,
69
79
  step: typeof frame_step === `number` ? frame_step : idx,
70
80
  metadata: frame_obj.metadata || {},
71
81
  };
72
82
  });
73
83
  return { frames, metadata: { source_format: `array`, frame_count: frames.length } };
74
84
  }
75
- const obj = data;
85
+ if (!is_plain_object(data))
86
+ throw new Error(`Invalid data format`);
76
87
  // Pymatgen format
77
- if (obj[`@class`] === `Trajectory` && obj.species && obj.coords && obj.lattice) {
78
- const species = obj.species;
79
- const frame_elements = species.map((specie) => specie.element);
80
- const coords = obj.coords;
81
- const matrix = validate_3x3_matrix(obj.lattice);
82
- const frame_properties = obj.frame_properties || [];
83
- const frac_to_cart = math.create_frac_to_cart(matrix);
84
- const frames = coords.map((frame_coords, idx) => {
85
- const positions = frame_coords.map((abc) => frac_to_cart(abc));
86
- // Process frame properties to extract numpy arrays
87
- const raw_properties = frame_properties[idx] || {};
88
- const processed_properties = {};
89
- Object.entries(raw_properties).forEach(([key, value]) => {
90
- if (value &&
91
- typeof value === `object` &&
92
- value[`@class`] === `array`) {
93
- // Extract numpy array data
94
- const array_obj = value;
95
- processed_properties[key] = array_obj.data;
96
- // Calculate force statistics for forces
97
- if (key === `forces` && Array.isArray(array_obj.data)) {
98
- const forces = array_obj.data;
99
- const force_magnitudes = forces.map((force) => Math.hypot(...force));
100
- if (force_magnitudes.length > 0) {
101
- processed_properties.force_max = force_magnitudes.reduce((max_val, magnitude) => (magnitude > max_val ? magnitude : max_val), force_magnitudes[0]);
102
- processed_properties.force_norm = Math.sqrt(force_magnitudes.reduce((sum, f) => sum + f ** 2, 0) / force_magnitudes.length);
103
- }
104
- }
105
- // Calculate stress statistics for stress tensor
106
- if (key === `stress` && Array.isArray(array_obj.data)) {
107
- const stress_tensor = array_obj.data;
108
- if (!math.is_square_matrix(stress_tensor, 3)) {
109
- console.warn(`Invalid stress tensor structure in frame ${idx}`);
110
- }
111
- else {
112
- // Calculate stress components (diagonal elements represent normal stresses)
113
- const normal_stresses = [
114
- stress_tensor[0][0],
115
- stress_tensor[1][1],
116
- stress_tensor[2][2],
117
- ];
118
- processed_properties.stress_max = Math.max(...normal_stresses.map(Math.abs));
119
- // Calculate hydrostatic pressure (negative of mean normal stress)
120
- processed_properties.pressure =
121
- -(normal_stresses[0] + normal_stresses[1] + normal_stresses[2]) / 3;
122
- }
123
- }
124
- }
125
- else {
126
- processed_properties[key] = value;
127
- }
128
- });
129
- return create_trajectory_frame(positions, frame_elements, matrix, [true, true, true], idx, processed_properties);
130
- });
131
- return {
132
- frames,
133
- metadata: {
134
- filename,
135
- source_format: `pymatgen_trajectory`,
136
- frame_count: frames.length,
137
- species_list: [...new Set(species.map((specie) => specie.element))],
138
- periodic_boundary_conditions: [true, true, true],
139
- },
140
- };
88
+ if (data[`@class`] === `Trajectory` && data.species && data.coords && data.lattice) {
89
+ return parse_pymatgen_trajectory(data, filename);
141
90
  }
142
91
  // Object with frames
143
- if (Array.isArray(obj.frames)) {
144
- const metadata = (obj.metadata ?? {});
145
- return {
146
- frames: obj.frames,
147
- metadata: { ...metadata, source_format: `object_with_frames` },
148
- };
92
+ if (Array.isArray(data.frames)) {
93
+ const metadata = (data.metadata ?? {});
94
+ const frames = data.frames;
95
+ frames.forEach((frame, idx) => assert_frame_structure(frame?.structure, idx));
96
+ return { frames, metadata: { ...metadata, source_format: `object_with_frames` } };
149
97
  }
150
- // Single structure
151
- if (obj.sites) {
152
- return {
153
- frames: [{ structure: obj, step: 0, metadata: {} }],
154
- metadata: { source_format: `single_structure`, frame_count: 1 },
155
- };
98
+ // Single structure (treated as a 1-frame trajectory)
99
+ if (data.sites) {
100
+ assert_frame_structure(data, `single structure`);
101
+ const frames = [{ structure: data, step: 0, metadata: {} }];
102
+ const metadata = { source_format: `single_structure`, frame_count: 1 };
103
+ return { frames, metadata };
156
104
  }
157
105
  throw new Error(`Unrecognized trajectory format`);
158
106
  }
159
107
  export function get_unsupported_format_message(filename, content) {
160
108
  const lower = filename.toLowerCase();
161
109
  // Check for unsupported compression formats first
162
- const unsupported_compression = [
163
- { ext: `.bz2`, name: `BZ2` },
164
- { ext: `.xz`, name: `XZ` },
165
- { ext: `.zip`, name: `ZIP` },
166
- ];
167
- for (const { ext, name } of unsupported_compression) {
110
+ for (const [ext, name] of [
111
+ [`.bz2`, `BZ2`],
112
+ [`.xz`, `XZ`],
113
+ [`.zip`, `ZIP`],
114
+ ]) {
168
115
  if (lower.endsWith(ext)) {
169
116
  return `🚫 ${name} compression not supported in browser\nPlease decompress the file first`;
170
117
  }
@@ -185,10 +132,20 @@ export function get_unsupported_format_message(filename, content) {
185
132
  ? `🚫 Binary format not supported${filename ? `: ${filename}` : ``}`
186
133
  : null;
187
134
  }
135
+ // Attach non-fatal parse warnings (skipped atoms, dropped frames, plot-metadata
136
+ // extraction failures, ...) collected during parsing to the trajectory metadata so
137
+ // the UI can surface them instead of leaving them in the console only.
138
+ function attach_parse_warnings(trajectory) {
139
+ const parse_warnings = get_traj_parse_warnings();
140
+ if (parse_warnings.length === 0)
141
+ return trajectory;
142
+ return { ...trajectory, metadata: { ...trajectory.metadata, parse_warnings } };
143
+ }
188
144
  // Unified async parser with streaming support
189
145
  export async function parse_trajectory_async(data, filename, on_progress, options = {}) {
190
146
  const { use_indexing, index_sample_rate = INDEX_SAMPLE_RATE, extract_plot_metadata = true, atom_type_mapping, } = options;
191
147
  const update_progress = (current, stage) => on_progress?.({ current, total: 100, stage });
148
+ reset_traj_parse_warnings();
192
149
  try {
193
150
  update_progress(0, `Detecting format...`);
194
151
  const data_size = data instanceof ArrayBuffer ? data.byteLength : new TextEncoder().encode(data).byteLength;
@@ -198,18 +155,21 @@ export async function parse_trajectory_async(data, filename, on_progress, option
198
155
  update_progress(5, `Large file detected (${Math.round(data_size / 1024 / 1024)}MB)`);
199
156
  }
200
157
  // Use indexed loading for supported large files (including compressed names).
158
+ // When the filename gives no format hint (e.g. blob: URLs), sniff a content
159
+ // prefix for XYZ frames so large extensionless files still get indexed.
201
160
  const base_filename = strip_compression_extensions(filename);
202
- if (should_use_indexing && /\.(xyz|extxyz|traj)$/.test(base_filename)) {
203
- return await parse_with_unified_loader(data, filename, {
204
- index_sample_rate,
205
- extract_plot_metadata,
206
- }, on_progress);
161
+ const can_index = /\.(xyz|extxyz|traj)$/.test(base_filename) ||
162
+ (typeof data === `string` &&
163
+ ext_hint(filename, /\.(xyz|extxyz)$/) === null &&
164
+ count_xyz_frames(data.slice(0, 2 ** 20)) >= 1);
165
+ if (should_use_indexing && can_index) {
166
+ return attach_parse_warnings(await parse_with_unified_loader(data, filename, { index_sample_rate, extract_plot_metadata }, on_progress));
207
167
  }
208
168
  // Fallback to direct parsing
209
169
  update_progress(10, `Parsing trajectory...`);
210
170
  const result = await parse_trajectory_data(data, filename, atom_type_mapping);
211
171
  update_progress(100, `Complete`);
212
- return result;
172
+ return attach_parse_warnings(result);
213
173
  }
214
174
  catch (error) {
215
175
  const error_message = error instanceof Error ? error.message : `Unknown error`;
@@ -251,7 +211,7 @@ async function parse_with_unified_loader(data, filename, options, on_progress) {
251
211
  });
252
212
  }
253
213
  catch (error) {
254
- console.warn(`Failed to extract plot metadata:`, error);
214
+ traj_warn(`Failed to extract plot metadata`, error);
255
215
  }
256
216
  }
257
217
  const stage = `Ready: ${total_frames} frames indexed`;
@@ -1,5 +1,3 @@
1
- import * as math from '../../math';
2
1
  import type { TrajectoryType } from '../index';
3
2
  import type { AtomTypeMapping } from '../types';
4
- export declare function parse_lammps_box(box_lines: string[], is_triclinic: boolean): math.Matrix3x3 | null;
5
3
  export declare function parse_lammps_trajectory(content: string, filename?: string, atom_type_mapping?: AtomTypeMapping): TrajectoryType;
@@ -1,11 +1,13 @@
1
1
  import { ELEM_SYMBOLS } from '../../labels';
2
2
  import * as math from '../../math';
3
- import { coerce_element_symbol, create_trajectory_frame } from '../helpers';
3
+ import { coerce_elem_symbol } from '../../element';
4
+ import { create_trajectory_frame } from '../helpers';
5
+ import { traj_warn } from './diagnostics';
4
6
  const is_periodic = (token) => token.toLowerCase().startsWith(`p`);
5
7
  // Parse LAMMPS box bounds → lattice matrix. Handles orthogonal and triclinic boxes.
6
8
  // Triclinic: converts bounding box to actual dims per https://docs.lammps.org/Howto_triclinic.html
7
9
  // Lattice vectors: a=(lx,0,0), b=(xy,ly,0), c=(xz,yz,lz)
8
- export function parse_lammps_box(box_lines, is_triclinic) {
10
+ function parse_lammps_box(box_lines, is_triclinic) {
9
11
  if (box_lines.length !== 3)
10
12
  return null;
11
13
  const bounds = box_lines.map((line) => line.split(/\s+/).map(Number));
@@ -100,7 +102,7 @@ export function parse_lammps_trajectory(content, filename, atom_type_mapping) {
100
102
  if (pos_cols.some((col_idx) => col_idx === undefined))
101
103
  continue;
102
104
  if (type_col === undefined && element_col === undefined && id_col === undefined) {
103
- console.warn(`Skipping LAMMPS frame at timestep ${timestep}: missing type/element/id column`);
105
+ traj_warn(`Skipping LAMMPS frame at timestep ${timestep}: missing type/element/id column`);
104
106
  continue;
105
107
  }
106
108
  // Parse atom data
@@ -125,9 +127,9 @@ export function parse_lammps_trajectory(content, filename, atom_type_mapping) {
125
127
  const raw_symbol = parts[element_col];
126
128
  if (!raw_symbol)
127
129
  continue;
128
- element_symbol = coerce_element_symbol(raw_symbol);
130
+ element_symbol = coerce_elem_symbol(raw_symbol);
129
131
  if (!element_symbol) {
130
- console.warn(`Skipping LAMMPS atom with unknown element symbol "${raw_symbol}" at timestep ${timestep}`);
132
+ traj_warn(`Skipping LAMMPS atom with unknown element symbol "${raw_symbol}" at timestep ${timestep}`);
131
133
  continue;
132
134
  }
133
135
  }
@@ -135,7 +137,7 @@ export function parse_lammps_trajectory(content, filename, atom_type_mapping) {
135
137
  const atom_id = parseInt(parts[id_col], 10) || 1;
136
138
  atom_types_found.add(atom_id);
137
139
  if (!id_fallback_warning_emitted) {
138
- console.warn(`LAMMPS parser fallback: mapping atom IDs to elements from ID column; this may be incorrect for large or sequential IDs. Prefer a TYPE column when available.`);
140
+ traj_warn(`LAMMPS parser fallback: mapping atom IDs to elements from ID column; this may be incorrect for large or sequential IDs. Prefer a TYPE column when available.`);
139
141
  id_fallback_warning_emitted = true;
140
142
  }
141
143
  element_symbol = get_element(atom_id);
@@ -0,0 +1,2 @@
1
+ import type { TrajectoryType } from '../index';
2
+ export declare function parse_pymatgen_trajectory(obj: Record<string, unknown>, filename?: string): TrajectoryType;