matterviz 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +48 -60
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/api/optimade.js +10 -7
  6. package/dist/app.css +68 -0
  7. package/dist/brillouin/BrillouinZone.svelte +90 -91
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  9. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  11. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  12. package/dist/brillouin/BrillouinZoneScene.svelte +46 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  14. package/dist/brillouin/compute.js +10 -16
  15. package/dist/brillouin/geometry.js +2 -2
  16. package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
  17. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
  20. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  21. package/dist/chempot-diagram/async-compute.svelte.js +13 -14
  22. package/dist/chempot-diagram/color.d.ts +21 -1
  23. package/dist/chempot-diagram/color.js +70 -1
  24. package/dist/chempot-diagram/compute.d.ts +7 -0
  25. package/dist/chempot-diagram/compute.js +85 -26
  26. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  27. package/dist/chempot-diagram/export.js +1 -6
  28. package/dist/chempot-diagram/temperature.js +9 -10
  29. package/dist/colors/index.d.ts +0 -4
  30. package/dist/colors/index.js +19 -20
  31. package/dist/composition/BarChart.svelte +30 -26
  32. package/dist/composition/BubbleChart.svelte +17 -17
  33. package/dist/composition/Composition.svelte +10 -19
  34. package/dist/composition/Formula.svelte +20 -27
  35. package/dist/composition/FormulaFilter.svelte +115 -184
  36. package/dist/composition/PieChart.svelte +55 -41
  37. package/dist/composition/format.js +7 -9
  38. package/dist/composition/index.d.ts +2 -0
  39. package/dist/composition/index.js +14 -0
  40. package/dist/composition/parse.d.ts +2 -2
  41. package/dist/composition/parse.js +61 -115
  42. package/dist/constants.d.ts +0 -1
  43. package/dist/constants.js +17 -26
  44. package/dist/convex-hull/ConvexHull.svelte +12 -15
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +93 -94
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +127 -186
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +131 -180
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  53. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  54. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  55. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  56. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  57. package/dist/convex-hull/StructurePopup.svelte +18 -22
  58. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  59. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  60. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  61. package/dist/convex-hull/gas-thermodynamics.js +21 -53
  62. package/dist/convex-hull/helpers.d.ts +8 -10
  63. package/dist/convex-hull/helpers.js +37 -43
  64. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  65. package/dist/convex-hull/thermodynamics.js +37 -44
  66. package/dist/coordination/CoordinationBarPlot.svelte +49 -53
  67. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  68. package/dist/coordination/calc-coordination.d.ts +1 -1
  69. package/dist/coordination/calc-coordination.js +28 -25
  70. package/dist/element/BohrAtom.svelte +5 -9
  71. package/dist/element/ElementHeading.svelte +4 -1
  72. package/dist/element/ElementPhoto.svelte +11 -9
  73. package/dist/element/ElementStats.svelte +12 -10
  74. package/dist/element/ElementTile.svelte +44 -67
  75. package/dist/element/Nucleus.svelte +4 -2
  76. package/dist/element/data.d.ts +3 -2
  77. package/dist/element/data.js +5 -1
  78. package/dist/element/helpers.d.ts +4 -0
  79. package/dist/element/helpers.js +18 -0
  80. package/dist/element/index.d.ts +2 -5
  81. package/dist/element/index.js +4 -19
  82. package/dist/feedback/DragOverlay.svelte +5 -5
  83. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  84. package/dist/feedback/StatusMessage.svelte +7 -4
  85. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  86. package/dist/fermi-surface/FermiSurface.svelte +35 -44
  87. package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
  88. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  89. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  90. package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
  91. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  92. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  93. package/dist/fermi-surface/compute.js +25 -58
  94. package/dist/fermi-surface/parse.js +54 -88
  95. package/dist/file-viewer/JsonBrowser.svelte +1043 -0
  96. package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
  97. package/dist/file-viewer/PlotPanel.svelte +350 -0
  98. package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
  99. package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
  100. package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
  101. package/dist/file-viewer/detect.d.ts +11 -0
  102. package/dist/file-viewer/detect.js +381 -0
  103. package/dist/file-viewer/eligibility.d.ts +4 -0
  104. package/dist/file-viewer/eligibility.js +53 -0
  105. package/dist/file-viewer/host-protocol.d.ts +50 -0
  106. package/dist/file-viewer/host-transfer.d.ts +25 -0
  107. package/dist/file-viewer/host-transfer.js +42 -0
  108. package/dist/file-viewer/index.d.ts +5 -0
  109. package/dist/file-viewer/index.js +5 -0
  110. package/dist/file-viewer/main.d.ts +44 -0
  111. package/dist/file-viewer/main.js +535 -0
  112. package/dist/file-viewer/parse.d.ts +9 -0
  113. package/dist/file-viewer/parse.js +170 -0
  114. package/dist/file-viewer/plot-utils.d.ts +24 -0
  115. package/dist/file-viewer/plot-utils.js +191 -0
  116. package/dist/file-viewer/types.d.ts +4 -0
  117. package/dist/file-viewer/types.js +5 -0
  118. package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
  119. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  120. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  121. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  122. package/dist/heatmap-matrix/index.d.ts +5 -0
  123. package/dist/icons.d.ts +4 -0
  124. package/dist/icons.js +4 -0
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +1 -1
  127. package/dist/io/ExportPane.svelte +11 -7
  128. package/dist/io/decompress.d.ts +4 -1
  129. package/dist/io/decompress.js +24 -36
  130. package/dist/io/export.d.ts +11 -4
  131. package/dist/io/export.js +75 -19
  132. package/dist/io/fetch.d.ts +0 -3
  133. package/dist/io/fetch.js +0 -11
  134. package/dist/io/file-drop.js +60 -35
  135. package/dist/io/index.d.ts +0 -1
  136. package/dist/io/index.js +2 -9
  137. package/dist/io/is-binary.d.ts +9 -0
  138. package/dist/io/is-binary.js +45 -1
  139. package/dist/io/url-drop.d.ts +2 -0
  140. package/dist/io/url-drop.js +40 -40
  141. package/dist/isosurface/Isosurface.svelte +700 -215
  142. package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
  143. package/dist/isosurface/IsosurfaceControls.svelte +590 -116
  144. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
  145. package/dist/isosurface/VolumeSlice.svelte +224 -0
  146. package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
  147. package/dist/isosurface/coloring.d.ts +20 -0
  148. package/dist/isosurface/coloring.js +118 -0
  149. package/dist/isosurface/geometry-worker-types.d.ts +38 -0
  150. package/dist/isosurface/geometry.worker.d.ts +1 -0
  151. package/dist/isosurface/geometry.worker.js +59 -0
  152. package/dist/isosurface/grid.d.ts +10 -0
  153. package/dist/isosurface/grid.js +31 -0
  154. package/dist/isosurface/index.d.ts +4 -0
  155. package/dist/isosurface/index.js +4 -0
  156. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  157. package/dist/isosurface/parse-vaspwave.js +138 -0
  158. package/dist/isosurface/parse.js +6 -6
  159. package/dist/isosurface/profile.d.ts +12 -0
  160. package/dist/isosurface/profile.js +19 -0
  161. package/dist/isosurface/sampling.d.ts +34 -0
  162. package/dist/isosurface/sampling.js +408 -0
  163. package/dist/isosurface/slice-rendering.d.ts +13 -0
  164. package/dist/isosurface/slice-rendering.js +79 -0
  165. package/dist/isosurface/slice.d.ts +22 -2
  166. package/dist/isosurface/slice.js +200 -116
  167. package/dist/isosurface/types.d.ts +24 -1
  168. package/dist/isosurface/types.js +120 -8
  169. package/dist/json-path.d.ts +4 -0
  170. package/dist/json-path.js +89 -0
  171. package/dist/labels.d.ts +6 -2
  172. package/dist/labels.js +44 -14
  173. package/dist/layout/FullscreenButton.svelte +2 -1
  174. package/dist/layout/FullscreenToggle.svelte +10 -4
  175. package/dist/layout/InfoCard.svelte +8 -21
  176. package/dist/layout/InfoTag.svelte +1 -3
  177. package/dist/layout/NumberRangeInput.svelte +46 -0
  178. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  179. package/dist/layout/PropertyFilter.svelte +2 -6
  180. package/dist/layout/SettingsSection.svelte +57 -62
  181. package/dist/layout/SettingsSection.svelte.d.ts +6 -7
  182. package/dist/layout/SubpageGrid.svelte +3 -1
  183. package/dist/layout/ViewerChrome.svelte +16 -11
  184. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  185. package/dist/layout/fullscreen.js +3 -5
  186. package/dist/layout/fullscreen.svelte.js +1 -2
  187. package/dist/layout/index.d.ts +1 -0
  188. package/dist/layout/index.js +1 -0
  189. package/dist/layout/json-tree/JsonNode.svelte +22 -59
  190. package/dist/layout/json-tree/JsonTree.svelte +101 -172
  191. package/dist/layout/json-tree/JsonValue.svelte +9 -32
  192. package/dist/layout/json-tree/utils.d.ts +0 -3
  193. package/dist/layout/json-tree/utils.js +50 -188
  194. package/dist/marching-cubes.d.ts +8 -1
  195. package/dist/marching-cubes.js +115 -48
  196. package/dist/math.d.ts +5 -2
  197. package/dist/math.js +48 -38
  198. package/dist/overlays/ContextMenu.svelte +19 -34
  199. package/dist/overlays/CopyButton.svelte +11 -5
  200. package/dist/overlays/DragControlTab.svelte +6 -1
  201. package/dist/overlays/DraggablePane.svelte +110 -74
  202. package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
  203. package/dist/overlays/GlassChip.svelte +32 -0
  204. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  205. package/dist/overlays/InfoPaneCards.svelte +11 -23
  206. package/dist/overlays/index.d.ts +7 -0
  207. package/dist/overlays/index.js +26 -0
  208. package/dist/overlays/portal.d.ts +2 -0
  209. package/dist/overlays/portal.js +14 -0
  210. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  211. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  212. package/dist/periodic-table/PeriodicTableControls.svelte +37 -115
  213. package/dist/periodic-table/TableInset.svelte +9 -4
  214. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
  215. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  216. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  217. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  218. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  219. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  220. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  221. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  222. package/dist/phase-diagram/build-diagram.js +4 -9
  223. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  224. package/dist/phase-diagram/parse.js +15 -15
  225. package/dist/phase-diagram/svg-to-diagram.js +28 -27
  226. package/dist/phase-diagram/utils.js +2 -3
  227. package/dist/plot/bar/BarPlot.svelte +461 -426
  228. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  229. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  230. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  231. package/dist/plot/bar/SpacegroupBarPlot.svelte +46 -77
  232. package/dist/plot/bar/data.d.ts +5 -4
  233. package/dist/plot/bar/data.js +2 -1
  234. package/dist/plot/box/BoxPlot.svelte +322 -226
  235. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  236. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  237. package/dist/plot/box/box-plot.js +1 -1
  238. package/dist/plot/core/auto-place.d.ts +1 -1
  239. package/dist/plot/core/auto-place.js +2 -2
  240. package/dist/plot/core/axis-utils.d.ts +12 -7
  241. package/dist/plot/core/axis-utils.js +48 -48
  242. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  243. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  244. package/dist/plot/core/components/ColorBar.svelte +101 -106
  245. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  246. package/dist/plot/core/components/FillArea.svelte +10 -17
  247. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  248. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  249. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  250. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  251. package/dist/plot/core/components/Line.svelte +18 -9
  252. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  253. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  254. package/dist/plot/core/components/PlotControls.svelte +65 -41
  255. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  256. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  257. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  258. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  259. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  260. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  261. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  262. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  263. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  264. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  265. package/dist/plot/core/components/index.d.ts +1 -0
  266. package/dist/plot/core/components/index.js +1 -0
  267. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  268. package/dist/plot/core/data-cleaning-signal.js +467 -0
  269. package/dist/plot/core/data-cleaning.d.ts +2 -42
  270. package/dist/plot/core/data-cleaning.js +27 -474
  271. package/dist/plot/core/data-transform.d.ts +1 -2
  272. package/dist/plot/core/data-transform.js +9 -15
  273. package/dist/plot/core/fill-utils.d.ts +3 -1
  274. package/dist/plot/core/fill-utils.js +28 -6
  275. package/dist/plot/core/index.d.ts +1 -0
  276. package/dist/plot/core/index.js +1 -0
  277. package/dist/plot/core/interactions.js +0 -2
  278. package/dist/plot/core/layout.d.ts +15 -6
  279. package/dist/plot/core/layout.js +57 -38
  280. package/dist/plot/core/marginals.d.ts +170 -0
  281. package/dist/plot/core/marginals.js +436 -0
  282. package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
  283. package/dist/plot/core/pan-zoom.svelte.js +34 -17
  284. package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
  285. package/dist/plot/core/placed-tween.svelte.js +68 -21
  286. package/dist/plot/core/reference-line.js +1 -1
  287. package/dist/plot/core/scales.d.ts +23 -0
  288. package/dist/plot/core/scales.js +39 -13
  289. package/dist/plot/core/svg.js +0 -1
  290. package/dist/plot/core/types/fills.d.ts +101 -0
  291. package/dist/plot/core/types/fills.js +15 -0
  292. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  293. package/dist/plot/core/types/plot-3d.js +4 -0
  294. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  295. package/dist/plot/core/types/reference-lines.js +9 -0
  296. package/dist/plot/core/types.d.ts +29 -324
  297. package/dist/plot/core/types.js +23 -20
  298. package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
  299. package/dist/plot/core/utils/hierarchy-chart.js +191 -0
  300. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  301. package/dist/plot/core/utils/hierarchy-labels.js +100 -0
  302. package/dist/plot/core/utils/label-placement.js +2 -2
  303. package/dist/plot/histogram/Histogram.svelte +314 -340
  304. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  305. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  306. package/dist/plot/histogram/histogram.d.ts +31 -0
  307. package/dist/plot/histogram/histogram.js +70 -0
  308. package/dist/plot/histogram/index.d.ts +1 -0
  309. package/dist/plot/histogram/index.js +1 -0
  310. package/dist/plot/index.d.ts +1 -0
  311. package/dist/plot/index.js +1 -0
  312. package/dist/plot/sankey/Sankey.svelte +78 -69
  313. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  314. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  315. package/dist/plot/sankey/sankey.js +13 -9
  316. package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
  317. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  318. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  319. package/dist/plot/scatter/ScatterPlot.svelte +517 -410
  320. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  321. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  322. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  323. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  324. package/dist/plot/scatter/adaptive-density.d.ts +1 -1
  325. package/dist/plot/scatter/adaptive-density.js +36 -20
  326. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  327. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  328. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  329. package/dist/plot/scatter/scatter-data.js +8 -7
  330. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  331. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  332. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  333. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  334. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  335. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  336. package/dist/plot/sunburst/Sunburst.svelte +269 -347
  337. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  338. package/dist/plot/sunburst/index.d.ts +1 -1
  339. package/dist/plot/sunburst/index.js +2 -1
  340. package/dist/plot/sunburst/render.d.ts +2 -2
  341. package/dist/plot/sunburst/render.js +47 -22
  342. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  343. package/dist/plot/sunburst/sunburst.js +10 -3
  344. package/dist/plot/treemap/Treemap.svelte +1022 -0
  345. package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
  346. package/dist/plot/treemap/index.d.ts +4 -0
  347. package/dist/plot/treemap/index.js +4 -0
  348. package/dist/plot/treemap/labels.d.ts +38 -0
  349. package/dist/plot/treemap/labels.js +80 -0
  350. package/dist/plot/treemap/treemap.d.ts +28 -0
  351. package/dist/plot/treemap/treemap.js +102 -0
  352. package/dist/rdf/RdfPlot.svelte +37 -59
  353. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  354. package/dist/rdf/calc-rdf.js +63 -52
  355. package/dist/rdf/index.d.ts +0 -1
  356. package/dist/sanitize.js +85 -27
  357. package/dist/scene/SceneCamera.svelte +1 -1
  358. package/dist/scene/SceneCamera.svelte.d.ts +1 -1
  359. package/dist/scene/bind-renderer.svelte.js +14 -6
  360. package/dist/scene/index.d.ts +1 -2
  361. package/dist/scene/index.js +1 -1
  362. package/dist/scene/{props.js → props.svelte.js} +15 -1
  363. package/dist/settings.d.ts +19 -9
  364. package/dist/settings.js +229 -525
  365. package/dist/spectral/Bands.svelte +207 -221
  366. package/dist/spectral/BandsAndDos.svelte +11 -9
  367. package/dist/spectral/BrillouinBandsDos.svelte +19 -42
  368. package/dist/spectral/Dos.svelte +92 -93
  369. package/dist/spectral/helpers.d.ts +3 -3
  370. package/dist/spectral/helpers.js +65 -140
  371. package/dist/state.svelte.js +5 -18
  372. package/dist/structure/Arrow.svelte +5 -18
  373. package/dist/structure/ArrowInstances.svelte +160 -0
  374. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  375. package/dist/structure/AtomLegend.svelte +120 -85
  376. package/dist/structure/AtomLegend.svelte.d.ts +2 -3
  377. package/dist/structure/Bond.svelte +31 -23
  378. package/dist/structure/CanvasTooltip.svelte +15 -3
  379. package/dist/structure/CellSelect.svelte +45 -35
  380. package/dist/structure/Cylinder.svelte +24 -40
  381. package/dist/structure/InstancedAtoms.svelte +114 -0
  382. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  383. package/dist/structure/Lattice.svelte +85 -149
  384. package/dist/structure/SiteLabels.svelte +122 -0
  385. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  386. package/dist/structure/Structure.svelte +636 -504
  387. package/dist/structure/Structure.svelte.d.ts +4 -2
  388. package/dist/structure/StructureCarousel.svelte +637 -0
  389. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  390. package/dist/structure/StructureControls.svelte +165 -425
  391. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  392. package/dist/structure/StructureExportPane.svelte +17 -21
  393. package/dist/structure/StructureInfoPane.svelte +128 -133
  394. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  395. package/dist/structure/StructureScene.svelte +535 -578
  396. package/dist/structure/StructureScene.svelte.d.ts +6 -2
  397. package/dist/structure/StructureViewport.svelte +451 -0
  398. package/dist/structure/StructureViewport.svelte.d.ts +65 -0
  399. package/dist/structure/atom-label-placement.d.ts +16 -12
  400. package/dist/structure/atom-label-placement.js +70 -37
  401. package/dist/structure/atom-properties.d.ts +2 -0
  402. package/dist/structure/atom-properties.js +105 -38
  403. package/dist/structure/bond-order-perception.js +3 -8
  404. package/dist/structure/bonding.d.ts +9 -3
  405. package/dist/structure/bonding.js +95 -46
  406. package/dist/structure/edit-history.d.ts +6 -0
  407. package/dist/structure/edit-history.js +27 -0
  408. package/dist/structure/export.d.ts +1 -0
  409. package/dist/structure/export.js +89 -105
  410. package/dist/structure/format-detect.d.ts +1 -0
  411. package/dist/structure/format-detect.js +20 -0
  412. package/dist/structure/geometry.d.ts +9 -0
  413. package/dist/structure/geometry.js +27 -0
  414. package/dist/structure/index.d.ts +16 -1
  415. package/dist/structure/index.js +15 -10
  416. package/dist/structure/measure.d.ts +1 -1
  417. package/dist/structure/measure.js +6 -12
  418. package/dist/structure/parse.d.ts +2 -1
  419. package/dist/structure/parse.js +272 -313
  420. package/dist/structure/partial-occupancy.js +10 -5
  421. package/dist/structure/pbc.js +85 -107
  422. package/dist/structure/polyhedra.d.ts +0 -1
  423. package/dist/structure/polyhedra.js +7 -21
  424. package/dist/structure/prop-groups.d.ts +85 -0
  425. package/dist/structure/prop-groups.js +18 -0
  426. package/dist/structure/supercell.d.ts +1 -2
  427. package/dist/structure/supercell.js +7 -13
  428. package/dist/symmetry/SymmetryElements.svelte +11 -15
  429. package/dist/symmetry/SymmetryStats.svelte +55 -71
  430. package/dist/symmetry/WyckoffTable.svelte +10 -28
  431. package/dist/symmetry/cell-transform.js +6 -14
  432. package/dist/symmetry/index.d.ts +1 -0
  433. package/dist/symmetry/index.js +13 -10
  434. package/dist/symmetry/spacegroups.js +3 -2
  435. package/dist/table/HeatmapTable.svelte +1142 -447
  436. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  437. package/dist/table/ToggleMenu.svelte +168 -53
  438. package/dist/table/ToggleMenu.svelte.d.ts +1 -1
  439. package/dist/table/index.d.ts +21 -6
  440. package/dist/table/index.js +34 -21
  441. package/dist/theme/ThemeControl.svelte +16 -8
  442. package/dist/theme/embedded.d.ts +18 -0
  443. package/dist/theme/embedded.js +206 -0
  444. package/dist/theme/index.d.ts +5 -5
  445. package/dist/theme/index.js +5 -12
  446. package/dist/theme/themes.mjs +44 -66
  447. package/dist/tooltip/KCoords.svelte +4 -1
  448. package/dist/tooltip/TooltipContent.svelte +3 -6
  449. package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
  450. package/dist/tooltip/index.d.ts +8 -1
  451. package/dist/trajectory/Trajectory.svelte +613 -386
  452. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  453. package/dist/trajectory/TrajectoryError.svelte +12 -74
  454. package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
  455. package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
  456. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
  457. package/dist/trajectory/extract.js +61 -49
  458. package/dist/trajectory/format-detect.d.ts +2 -0
  459. package/dist/trajectory/format-detect.js +17 -13
  460. package/dist/trajectory/frame-reader.d.ts +2 -0
  461. package/dist/trajectory/frame-reader.js +35 -32
  462. package/dist/trajectory/helpers.d.ts +2 -0
  463. package/dist/trajectory/helpers.js +34 -56
  464. package/dist/trajectory/index.d.ts +1 -0
  465. package/dist/trajectory/index.js +5 -8
  466. package/dist/trajectory/parse/ase.js +1 -1
  467. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  468. package/dist/trajectory/parse/h5-utils.js +109 -0
  469. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  470. package/dist/trajectory/parse/hdf5.js +116 -106
  471. package/dist/trajectory/parse/index.d.ts +6 -6
  472. package/dist/trajectory/parse/index.js +25 -33
  473. package/dist/trajectory/parse/lammps.js +8 -12
  474. package/dist/trajectory/parse/vasp.js +10 -7
  475. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  476. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  477. package/dist/trajectory/parse/vaspout-h5.d.ts +4 -0
  478. package/dist/trajectory/parse/vaspout-h5.js +281 -0
  479. package/dist/trajectory/parse/xyz.js +59 -9
  480. package/dist/trajectory/plotting.d.ts +8 -9
  481. package/dist/trajectory/plotting.js +113 -64
  482. package/dist/utils.d.ts +3 -0
  483. package/dist/utils.js +7 -0
  484. package/dist/xrd/XrdPlot.svelte +79 -118
  485. package/dist/xrd/broadening.js +2 -1
  486. package/dist/xrd/calc-xrd.js +24 -62
  487. package/dist/xrd/parse.d.ts +0 -1
  488. package/dist/xrd/parse.js +69 -95
  489. package/package.json +94 -34
  490. package/readme.md +6 -5
  491. package/dist/api/mp.d.ts +0 -6
  492. package/dist/api/mp.js +0 -22
  493. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
  494. package/dist/scene/types.d.ts +0 -26
  495. package/dist/tooltip/types.d.ts +0 -8
  496. package/dist/trajectory/constants.d.ts +0 -6
  497. package/dist/trajectory/constants.js +0 -11
  498. /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
  499. /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
@@ -10,7 +10,6 @@ const make_render_site = (sites, site_idx, source_site_indices, site_override) =
10
10
  is_image_atom: source_site_indices.some((source_site_idx) => is_image_atom(sites[source_site_idx])),
11
11
  source_site_indices,
12
12
  });
13
- const sq_dist = (xyz_1, xyz_2) => (xyz_1[0] - xyz_2[0]) ** 2 + (xyz_1[1] - xyz_2[1]) ** 2 + (xyz_1[2] - xyz_2[2]) ** 2;
14
13
  const is_split_partial_site = (site, hidden_elements) => {
15
14
  const visible_species = site.species.filter(({ element }) => !hidden_elements.has(element));
16
15
  const total_visible_occupancy = visible_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
@@ -25,7 +24,12 @@ const group_split_partial_indices = (sites, hidden_elements) => {
25
24
  non_grouped_site_indices.push(site_idx);
26
25
  continue;
27
26
  }
28
- const matched_group_idx = grouped_centers.findIndex((center_xyz) => sq_dist(center_xyz, site.xyz) <= MERGE_DISTANCE_TOLERANCE ** 2);
27
+ const matched_group_idx = grouped_centers.findIndex((center_xyz) => {
28
+ const dx = center_xyz[0] - site.xyz[0];
29
+ const dy = center_xyz[1] - site.xyz[1];
30
+ const dz = center_xyz[2] - site.xyz[2];
31
+ return dx * dx + dy * dy + dz * dz <= MERGE_DISTANCE_TOLERANCE ** 2;
32
+ });
29
33
  if (matched_group_idx === -1) {
30
34
  grouped_centers.push(site.xyz);
31
35
  grouped_site_indices.push([site_idx]);
@@ -59,8 +63,8 @@ export const PARTIAL_OCCUPANCY_CAP_ARC = {
59
63
  arc_length: Math.PI,
60
64
  };
61
65
  export const merge_split_partial_sites = (sites, hidden_elements = new Set()) => {
62
- const grouped_indices = group_split_partial_indices(sites, hidden_elements);
63
- return build_render_sites(sites, grouped_indices.non_grouped_site_indices, grouped_indices.grouped_site_indices);
66
+ const { non_grouped_site_indices, grouped_site_indices } = group_split_partial_indices(sites, hidden_elements);
67
+ return build_render_sites(sites, non_grouped_site_indices, grouped_site_indices);
64
68
  };
65
69
  export const compute_slice_geometry = (visible_species, slice_gap_rad = PARTIAL_OCCUPANCY_SLICE_GAP_RAD) => {
66
70
  if (visible_species.length === 0)
@@ -72,7 +76,8 @@ export const compute_slice_geometry = (visible_species, slice_gap_rad = PARTIAL_
72
76
  element,
73
77
  occu: occu * occupancy_scale_factor,
74
78
  }));
75
- const normalized_total_occupancy = normalized_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
79
+ // Sum of scaled occupancies equals total * scale (avoids a second O(n) pass)
80
+ const normalized_total_occupancy = total_visible_occupancy * occupancy_scale_factor;
76
81
  const has_vacancy_gap = normalized_total_occupancy < 1 - OCCUPANCY_EPS;
77
82
  const last_visible_species_idx = normalized_species.length - 1;
78
83
  let start_angle = 0;
@@ -1,5 +1,7 @@
1
+ // Periodic boundary conditions utilities
2
+ import { element_by_symbol } from '../element/data';
1
3
  import * as math from '../math';
2
- import { element_lookup, get_majority_element } from './bonding';
4
+ import { get_majority_element, has_framework_potential, is_spectator_center, pack_cell_key, } from './bonding';
3
5
  // Distance slack added to the covalent-radii sum when deciding whether a
4
6
  // candidate image atom bonds to a base atom (VESTA-like bond search criterion)
5
7
  const BOND_SLACK = 0.4; // Å
@@ -34,42 +36,30 @@ const is_scattered_trajectory = (sites) => {
34
36
  const atoms_outside_cell = sites.filter(({ abc }) => abc.some((coord) => coord < -0.1 || coord > 1.1));
35
37
  return atoms_outside_cell.length > sites.length * 0.1;
36
38
  };
37
- // Cartesian position of fractional coords abc in the given lattice (rows = lattice vectors)
38
- const frac_to_cart_pos = (abc, lattice_vecs) => math.add(math.scale(lattice_vecs[0], abc[0]), math.scale(lattice_vecs[1], abc[1]), math.scale(lattice_vecs[2], abc[2]));
39
39
  export function find_image_atoms(structure, { tolerance } = {}) {
40
40
  // Find image atoms for PBC. Returns [atom_idx, image_xyz, image_abc, is_completion?]
41
- // tuples; is_completion marks phase-2 images that exist only to complete bonds /
42
- // coordination polyhedra at cell faces (renderers may hide them when neither shows).
43
- // Skips image generation for trajectory data with scattered atoms.
41
+ // tuples; is_completion marks phase-2 images that only complete bonds / coordination
42
+ // polyhedra at cell faces (renderers may hide them). Skips scattered trajectories.
44
43
  if (!structure.lattice || !structure.sites || structure.sites.length === 0)
45
44
  return [];
46
45
  if (is_scattered_trajectory(structure.sites))
47
46
  return [];
48
- // Check if this is a supercell to correctly identify external boundaries correctly
49
47
  const image_sites = [];
50
48
  const lattice_vecs = structure.lattice.matrix;
51
- // Scale zero-displacement threshold by lattice length scale to avoid hard-coded magic numbers
52
- const lattice_norm = Math.max(Math.hypot(...lattice_vecs[0]), Math.hypot(...lattice_vecs[1]), Math.hypot(...lattice_vecs[2]));
53
- // Threshold to filter out floating-point-identical (zero-displacement) images; rarely triggers but guards against edge cases
49
+ const frac_to_cart = math.create_frac_to_cart(lattice_vecs);
50
+ const vec_lens = lattice_vecs.map((vec) => Math.hypot(...vec));
51
+ // Scale zero-displacement threshold by lattice length scale to avoid magic numbers
52
+ const lattice_norm = Math.max(...vec_lens);
54
53
  const displacement_eps_sq = (1e-10 * lattice_norm) ** 2;
55
- // Tolerances determine which atoms are near cell boundaries and need image generation
56
- // Use provided tolerance or default to physical tolerance of 0.5 Angstroms converted to fractional
57
- // This prevents excessive image generation for large unit cells (e.g. MOFs) where 0.05 fractional is huge
58
- const PHYSICAL_TOLERANCE = 0.5; // Angstroms
59
- const tolerances = [0, 1, 2].map((dim) => {
60
- if (tolerance !== undefined)
61
- return tolerance;
62
- const vec_len = Math.hypot(...lattice_vecs[dim]);
63
- // zero-length lattice vector should not occur in valid structures,
64
- // but fall back to 0.05 fractional tolerance if it does
65
- return vec_len > 0 ? PHYSICAL_TOLERANCE / vec_len : 0.05;
66
- });
67
- // Respect per-axis periodicity: no images across non-periodic (vacuum) directions
68
- const pbc = structure.lattice.pbc ?? [true, true, true];
54
+ // Boundary tolerance: physical 0.5 Å as fractional per-axis, so large cells (MOFs)
55
+ // don't over-generate (a flat 0.05 fractional would be huge there)
56
+ const PHYSICAL_TOLERANCE = 0.5; // Å
57
+ const tolerances = vec_lens.map((vec_len) => tolerance ?? (vec_len > 0 ? PHYSICAL_TOLERANCE / vec_len : 0.05));
58
+ const pbc = structure.lattice.pbc ?? [true, true, true]; // no images across vacuum
59
+ // Phase 1: true periodic copies of atoms within `tolerance` of a cell face (bond
60
+ // lengths preserved, rather than clamping the copy to the cell face)
69
61
  for (const [idx, site] of structure.sites.entries()) {
70
- // Find edge dimensions and translation directions
71
62
  const edge_dims = [];
72
- // Find boundary dimensions
73
63
  for (let dim = 0; dim < 3; dim++) {
74
64
  if (!pbc[dim])
75
65
  continue;
@@ -80,10 +70,9 @@ export function find_image_atoms(structure, { tolerance } = {}) {
80
70
  if (Math.abs(coord - 1) < dim_tolerance)
81
71
  edge_dims.push({ dim, direction: -1 });
82
72
  }
83
- // Generate all translation combinations
73
+ // Generate all translation combinations; if both +1 and -1 are selected for a dim the
74
+ // net shift is zero and we skip (yields no image).
84
75
  for (let mask = 1; mask < 1 << edge_dims.length; mask++) {
85
- // Track selected translation per dimension. If both +1 and -1 are selected for a dim,
86
- // the net shift is zero and we skip because it yields no image.
87
76
  const selected_shift = [0, 0, 0];
88
77
  for (let bit = 0; bit < edge_dims.length; bit++) {
89
78
  if (mask & (1 << bit)) {
@@ -91,25 +80,18 @@ export function find_image_atoms(structure, { tolerance } = {}) {
91
80
  selected_shift[dim] += direction;
92
81
  }
93
82
  }
94
- // Early skip if no net shift across any dimension
95
83
  if (selected_shift.every((val) => val === 0))
96
84
  continue;
97
- // Build fractional coordinates by applying the integer translation
98
- // This ensures the image is a true periodic copy (preserving bond lengths)
99
- // rather than clamping it to the cell face.
85
+ const [s_a, s_b, s_c] = site.abc;
100
86
  const img_abc = [
101
- site.abc[0] + selected_shift[0],
102
- site.abc[1] + selected_shift[1],
103
- site.abc[2] + selected_shift[2],
87
+ s_a + selected_shift[0],
88
+ s_b + selected_shift[1],
89
+ s_c + selected_shift[2],
104
90
  ];
105
- // If no dimension actually shifted, continue
106
- if (img_abc[0] === site.abc[0] &&
107
- img_abc[1] === site.abc[1] &&
108
- img_abc[2] === site.abc[2])
91
+ if (img_abc[0] === s_a && img_abc[1] === s_b && img_abc[2] === s_c)
109
92
  continue;
110
- // Compute xyz from img_abc to ensure consistency
111
- const img_xyz = frac_to_cart_pos(img_abc, lattice_vecs);
112
- // Skip zero-displacement images (should not happen, guards against FP edge cases)
93
+ const img_xyz = frac_to_cart(img_abc);
94
+ // Skip zero-displacement images (guards against FP edge cases)
113
95
  const displacement = math.subtract(img_xyz, site.xyz);
114
96
  const displacement_len_sq = displacement.reduce((sum, val) => sum + val * val, 0);
115
97
  if (displacement_len_sq < displacement_eps_sq)
@@ -117,87 +99,91 @@ export function find_image_atoms(structure, { tolerance } = {}) {
117
99
  image_sites.push([idx, img_xyz, img_abc]);
118
100
  }
119
101
  }
120
- // Phase 2: polyhedra-completing images (VESTA boundary-mode-like). The face
121
- // tolerance above only catches atoms within ~0.5 Å of a boundary, but bonds
122
- // reach a covalent-radii sum further: an anion just beyond a cell face may be
123
- // needed to complete the coordination shell of a cation near that face, so
124
- // bonds and coordination polyhedra at cell edges come out truncated without it.
125
- // Phase 2 adds ONLY such anion images: a candidate must qualify as a polyhedron
126
- // vertex (a non-metal/metalloid - same condition as is_anion_vertex in
127
- // polyhedra.ts) and be strictly more electronegative than the anchor atom it
128
- // bonds to. Everything else - elemental metals, intermetallics (incl. multi
129
- // metal ones like Al-Fe-Ni where EN differs but no polyhedra exist), equal-EN
130
- // covalent networks, cation copies - gets no phase-2 images, so the default
131
- // render stays minimal and grows uniformly from all cell surfaces (the phase-1
132
- // boundary copies above are the only non-anion atoms outside the cell).
102
+ // Per-site element data for the phase-2 completion pass. present_elements is the tiny
103
+ // composition (so has_framework_potential doesn't re-scan every site in big supercells).
104
+ const site_elements = [];
133
105
  const site_radii = [];
134
106
  const site_en = [];
135
107
  const site_is_metal = [];
108
+ const present_elements = new Set();
136
109
  let max_radius = 0;
137
- // Minimum electronegativity among potential anchors: a candidate can only ever
138
- // complete some cation's shell if it's strictly more electronegative than this
139
- let min_anchor_en = Infinity;
140
110
  for (const site of structure.sites) {
141
111
  const elem = get_majority_element(site);
142
- const data = elem === null ? undefined : element_lookup.get(elem);
112
+ const data = elem === null ? undefined : element_by_symbol.get(elem);
143
113
  const radius = data?.covalent_radius ?? null;
144
- const en = data?.electronegativity ?? null;
114
+ site_elements.push(elem);
115
+ if (elem !== null)
116
+ present_elements.add(elem);
145
117
  site_radii.push(radius);
146
- site_en.push(en);
118
+ site_en.push(data?.electronegativity ?? null);
147
119
  site_is_metal.push(data?.metal === true);
148
120
  if (radius !== null && radius > max_radius)
149
121
  max_radius = radius;
150
- if (radius !== null && en !== null && en < min_anchor_en)
122
+ }
123
+ // Skip spectator A-site cations (Li/Na, heavy alkaline earths) when a framework cation
124
+ // is present: they render no polyhedron, so completing their shells floats coordination
125
+ // groups (e.g. a PO4 around a corner Li) beyond the cell. Purely ionic binaries (NaCl)
126
+ // keep theirs. Note: a spectator force-included as a polyhedra center (compute_polyhedra's
127
+ // included_center_elements) is still skipped here, so its boundary polyhedra truncate at
128
+ // cell faces - accepted to keep image generation independent of render-only settings.
129
+ const skip_spectators = has_framework_potential(present_elements);
130
+ const site_skipped = site_elements.map((elem) => skip_spectators && elem !== null && is_spectator_center(elem));
131
+ // Phase 2: anion images that complete coordination polyhedra / bonds at cell faces.
132
+ // Phase 1's ~0.5 Å face tolerance misses anions just beyond a face that still bond a
133
+ // cation near it, truncating boundary polyhedra. We add ONLY such images: a candidate
134
+ // must be a polyhedron vertex (non-metal/metalloid, like is_anion_vertex in polyhedra.ts)
135
+ // AND strictly more electronegative than the anchor it bonds. Metals, intermetallics,
136
+ // equal-EN networks and cation copies get none, keeping renders minimal.
137
+ // Min anchor EN: a candidate only completes a cation's shell if more electronegative
138
+ // than it. Over non-skipped anchors only, so skipped spectators can't loosen the filter.
139
+ let min_anchor_en = Infinity;
140
+ for (let idx = 0; idx < structure.sites.length; idx++) {
141
+ if (site_skipped[idx])
142
+ continue;
143
+ const en = site_en[idx];
144
+ if (site_radii[idx] !== null && en !== null && en < min_anchor_en)
151
145
  min_anchor_en = en;
152
146
  }
153
147
  const max_bond_dist = 2 * max_radius + BOND_SLACK;
154
148
  if (max_bond_dist > BOND_SLACK && min_anchor_en < Infinity) {
155
- // Perpendicular cell heights: |frac| * height lower-bounds the Cartesian
156
- // distance along each axis (valid for oblique cells)
157
- const volume = Math.abs(math.dot(lattice_vecs[0], math.cross_3d(lattice_vecs[1], lattice_vecs[2])));
158
- // height = volume / opposite-face area. A zero-volume (degenerate) cell has two
159
- // parallel lattice vectors and ill-defined heights; treat every axis as
160
- // infinitely tall so the pad logic below adds no images (pad -> 0) instead of
161
- // dividing by zero. When volume > 0 the vectors are linearly independent, so no
162
- // pairwise cross product can be zero.
163
- const heights = volume === 0
164
- ? [Infinity, Infinity, Infinity]
165
- : [
166
- volume / Math.hypot(...math.cross_3d(lattice_vecs[1], lattice_vecs[2])),
167
- volume / Math.hypot(...math.cross_3d(lattice_vecs[0], lattice_vecs[2])),
168
- volume / Math.hypot(...math.cross_3d(lattice_vecs[0], lattice_vecs[1])),
169
- ];
170
- // Anchor set for the bond test: base atoms plus the phase-1 boundary images
171
- // (corner/edge/face copies). Anchoring on those too matches VESTA - every
172
- // displayed boundary cation gets its shell completed (e.g. all 8 corner
173
- // octahedra in rutile, not just the one at the origin).
149
+ // Per-axis fractional bond reach via perpendicular cell heights (correct for oblique
150
+ // cells; 0 for degenerate cells no images). The + face tolerance covers phase-1
151
+ // anchors sitting slightly outside the cell.
152
+ const pad_per_axis = math.frac_cutoff_per_axis(lattice_vecs, max_bond_dist + PHYSICAL_TOLERANCE);
153
+ // Bond-test anchors = base atoms + phase-1 boundary images, so every displayed
154
+ // boundary cation gets its shell completed (VESTA-like; e.g. all 8 rutile corners).
174
155
  const anchor_positions = structure.sites.map((site) => site.xyz);
175
156
  const anchor_radii = [...site_radii];
176
157
  const anchor_en = [...site_en];
158
+ const anchor_skipped = [...site_skipped];
177
159
  for (const [src_idx, img_xyz] of image_sites) {
178
160
  anchor_positions.push(img_xyz);
179
161
  anchor_radii.push(site_radii[src_idx]);
180
162
  anchor_en.push(site_en[src_idx]);
163
+ anchor_skipped.push(site_skipped[src_idx]);
181
164
  }
182
- // Spatial grid over anchors for the bond check
165
+ // Spatial grid over anchors for the bond check (integer-packed keys: this
166
+ // grid is probed 27x per candidate image in the loop below)
183
167
  const grid = new Map();
184
- const grid_key = (pos) => pos.map((coord) => Math.floor(coord / max_bond_dist)).join(`,`);
185
168
  for (const [idx, pos] of anchor_positions.entries()) {
186
- const key = grid_key(pos);
169
+ const key = pack_cell_key(Math.floor(pos[0] / max_bond_dist), Math.floor(pos[1] / max_bond_dist), Math.floor(pos[2] / max_bond_dist));
187
170
  const cell = grid.get(key);
188
171
  if (cell)
189
172
  cell.push(idx);
190
173
  else
191
174
  grid.set(key, [idx]);
192
175
  }
193
- // True when the candidate (an anion image) bonds a strictly less
194
- // electronegative anchor, i.e. completes some cation's coordination shell
176
+ // True when the candidate (an anion image) bonds a strictly less electronegative
177
+ // anchor, i.e. completes some cation's coordination shell
195
178
  const completes_cation_shell = (pos, radius, en) => {
196
179
  const [cx, cy, cz] = pos.map((coord) => Math.floor(coord / max_bond_dist));
197
180
  for (let dx = -1; dx <= 1; dx++) {
198
181
  for (let dy = -1; dy <= 1; dy++) {
199
182
  for (let dz = -1; dz <= 1; dz++) {
200
- for (const anchor_idx of grid.get(`${cx + dx},${cy + dy},${cz + dz}`) ?? []) {
183
+ for (const anchor_idx of grid.get(pack_cell_key(cx + dx, cy + dy, cz + dz)) ??
184
+ []) {
185
+ if (anchor_skipped[anchor_idx])
186
+ continue;
201
187
  const anchor_radius = anchor_radii[anchor_idx];
202
188
  const anchor_electroneg = anchor_en[anchor_idx];
203
189
  if (anchor_radius === null)
@@ -221,22 +207,19 @@ export function find_image_atoms(structure, { tolerance } = {}) {
221
207
  for (const [idx, site] of structure.sites.entries()) {
222
208
  const radius = site_radii[idx];
223
209
  const en = site_en[idx];
224
- // Skip candidates that could never be a polyhedron vertex: metals (e.g.
225
- // Fe/Ni in Al-Fe-Ni intermetallics, despite their higher EN) and anything
226
- // not strictly more electronegative than at least one anchor (covers all
227
- // sites of elemental/equal-EN structures and all cations)
210
+ // Skip candidates that could never be a polyhedron vertex: metals (e.g. Fe/Ni in
211
+ // Al-Fe-Ni intermetallics) and anything not strictly more electronegative than at
212
+ // least one anchor (covers elemental/equal-EN structures and all cations)
228
213
  if (radius === null || en === null || en <= min_anchor_en)
229
214
  continue;
230
215
  if (site_is_metal[idx])
231
216
  continue;
232
- // Per-axis shifts that could land a copy of this atom within bonding reach
233
- // of the cell: {0} plus +1/-1 when the atom is within max_bond_dist of the
234
- // respective boundary
217
+ // Per-axis shifts that could land a copy of this atom within bonding reach of the
218
+ // cell: {0} plus +1/-1 when the atom is within max_bond_dist of the boundary
235
219
  const axis_shifts = [0, 1, 2].map((axis) => {
236
220
  if (!pbc[axis])
237
221
  return [0];
238
- // + face tolerance: anchors (phase-1 images) can sit slightly outside the cell
239
- const pad = (max_bond_dist + PHYSICAL_TOLERANCE) / heights[axis];
222
+ const pad = pad_per_axis[axis];
240
223
  const shifts = [0];
241
224
  if (site.abc[axis] < pad)
242
225
  shifts.push(1);
@@ -257,7 +240,7 @@ export function find_image_atoms(structure, { tolerance } = {}) {
257
240
  site.abc[1] + shift_b,
258
241
  site.abc[2] + shift_c,
259
242
  ];
260
- const img_xyz = frac_to_cart_pos(img_abc, lattice_vecs);
243
+ const img_xyz = frac_to_cart(img_abc);
261
244
  if (!completes_cation_shell(img_xyz, radius, en))
262
245
  continue;
263
246
  seen_images.add(key);
@@ -269,19 +252,14 @@ export function find_image_atoms(structure, { tolerance } = {}) {
269
252
  }
270
253
  return image_sites;
271
254
  }
272
- // Return structure with image atoms added
255
+ // Return structure with image atoms added (unchanged when none are generated,
256
+ // e.g. for scattered trajectory-like data)
273
257
  export function get_pbc_image_sites(...args) {
274
258
  const structure = args[0];
275
- if (!structure || !structure.sites || structure.sites.length === 0) {
276
- return structure;
277
- }
278
- // Return trajectory data unchanged
279
- if (is_scattered_trajectory(structure.sites))
280
- return structure;
281
- // Add image atoms to regular crystal structures
282
259
  const image_sites = find_image_atoms(...args);
260
+ if (image_sites.length === 0)
261
+ return structure;
283
262
  const imaged_struct = { ...structure, sites: [...structure.sites] };
284
- // Add image atoms as new sites using provided (xyz, abc) from find_image_atoms
285
263
  for (const [site_idx, img_xyz, img_abc, is_completion] of image_sites) {
286
264
  const orig_site = structure.sites[site_idx];
287
265
  imaged_struct.sites.push({
@@ -36,6 +36,5 @@ export interface MergedPolyhedraBuffers {
36
36
  }
37
37
  export declare function convex_hull_3d(points: readonly Vec3[], eps_scale?: number): ConvexHullResult;
38
38
  export declare function build_adjacency(bonds: readonly BondPair[]): Map<number, Set<number>>;
39
- export declare const is_spectator_center: (element: string) => boolean;
40
39
  export declare function compute_polyhedra(structure: AnyStructure, bonds: readonly BondPair[], options?: PolyhedraOptions): Polyhedron[];
41
40
  export declare function merge_polyhedra_buffers(polyhedra: readonly Polyhedron[], get_vertex_color: (poly: Polyhedron, vertex_idx: number) => string, coplanar_tol?: number): MergedPolyhedraBuffers;
@@ -4,9 +4,10 @@
4
4
  // so the whole scene renders in 1-2 draw calls regardless of supercell size.
5
5
  // Hot paths use scalar math and per-element caches to scale to large structures.
6
6
  import { rgb as parse_rgb } from 'd3-color';
7
+ import { element_by_symbol } from '../element/data';
7
8
  import { DEFAULTS } from '../settings';
8
9
  import { get_orig_site_idx } from './atom-properties';
9
- import { element_lookup, get_majority_element } from './bonding';
10
+ import { get_majority_element, has_framework_potential, is_spectator_center } from './bonding';
10
11
  const face_of = (points, vert_a, vert_b, vert_c) => {
11
12
  const [ax, ay, az] = points[vert_a];
12
13
  const abx = points[vert_b][0] - ax;
@@ -294,15 +295,6 @@ export function build_adjacency(bonds) {
294
295
  return adjacency;
295
296
  }
296
297
  // --- Center selection ---
297
- // Large low-valent A-site cations whose coordination polyhedra (CN 8-12) tend to
298
- // obscure the structural framework. VESTA-style figures draw the framework
299
- // (e.g. TiO6 in BaTiO3, FeO6/PO4 in LiFePO4) and leave these as plain spheres.
300
- // They still get polyhedra when they are the only qualifying cations (e.g. NaCl)
301
- // or when force-included via `included_center_elements`.
302
- const SPECTATOR_CATEGORIES = new Set([`alkali metal`]);
303
- const HEAVY_ALKALINE_EARTHS = new Set([`Ca`, `Sr`, `Ba`, `Ra`]);
304
- export const is_spectator_center = (element) => SPECTATOR_CATEGORIES.has(element_lookup.get(element)?.category ?? ``) ||
305
- HEAVY_ALKALINE_EARTHS.has(element);
306
298
  // A bonded neighbor counts as a polyhedron vertex only if it's an anion-former:
307
299
  // a nonmetal or metalloid that is more electronegative than the center. This keeps
308
300
  // spurious cation-cation bonds (e.g. Ti-Ba in perovskites, Li-P in thiophosphates)
@@ -310,7 +302,7 @@ export const is_spectator_center = (element) => SPECTATOR_CATEGORIES.has(element
310
302
  function is_anion_vertex(center_en, center_is_metal, neighbor_element, electronegativity_margin) {
311
303
  if (!neighbor_element)
312
304
  return false;
313
- const n_data = element_lookup.get(neighbor_element);
305
+ const n_data = element_by_symbol.get(neighbor_element);
314
306
  if (n_data?.metal)
315
307
  return false;
316
308
  const n_en = n_data?.electronegativity ?? null;
@@ -350,12 +342,12 @@ export function compute_polyhedra(structure, bonds, options = {}) {
350
342
  const center_info = (element) => {
351
343
  let info = center_info_cache.get(element);
352
344
  if (!info) {
353
- const data = element_lookup.get(element);
345
+ const data = element_by_symbol.get(element);
354
346
  const center_en = data?.electronegativity ?? null;
355
347
  const r_center = data?.covalent_radius ?? null;
356
348
  const accepts = new Set(unique_elements.filter((n_elem) => is_anion_vertex(center_en, data?.metal === true, n_elem, electronegativity_margin)));
357
349
  const radii_sums = new Map(unique_elements.map((n_elem) => {
358
- const r_n = element_lookup.get(n_elem)?.covalent_radius ?? null;
350
+ const r_n = element_by_symbol.get(n_elem)?.covalent_radius ?? null;
359
351
  return [n_elem, r_center !== null && r_n !== null ? r_center + r_n : null];
360
352
  }));
361
353
  info = { accepts, radii_sums };
@@ -426,13 +418,7 @@ export function compute_polyhedra(structure, bonds, options = {}) {
426
418
  // the anions). Composition-based rather than candidate-based so boundary
427
419
  // truncation of framework polyhedra doesn't promote Li/Na/Ba clutter; purely
428
420
  // ionic binaries like NaCl or CaF2 still draw their spectator polyhedra.
429
- const max_en = Math.max(...unique_elements.map((el) => element_lookup.get(el)?.electronegativity ?? -Infinity));
430
- const has_framework_potential = unique_elements.some((el) => {
431
- if (is_spectator_center(el))
432
- return false;
433
- const en = element_lookup.get(el)?.electronegativity;
434
- return en !== null && en !== undefined && en < max_en;
435
- });
421
+ const has_framework = has_framework_potential(unique_elements);
436
422
  // Weakly-bound center species (mean bond length well beyond the covalent-radii
437
423
  // sum, e.g. lone-pair Bi3+ with 8 long Bi-O bonds) are hidden when a
438
424
  // strongly-bound framework species exists - mirrors how pyrochlore-type figures
@@ -455,7 +441,7 @@ export function compute_polyhedra(structure, bonds, options = {}) {
455
441
  const visible = candidates.filter(({ element }) => {
456
442
  if (included.has(element))
457
443
  return true;
458
- if (is_spectator_center(element) && has_framework_potential)
444
+ if (is_spectator_center(element) && has_framework)
459
445
  return false;
460
446
  return !is_weak_species(element);
461
447
  });
@@ -0,0 +1,85 @@
1
+ import type { DefaultSettings } from '../settings';
2
+ export declare const build_structure_props_from_settings: (defaults: DefaultSettings) => {
3
+ scene_props: {
4
+ gizmo: boolean;
5
+ atom_radius: number;
6
+ same_size_atoms: boolean;
7
+ show_atoms: boolean;
8
+ show_image_atoms: boolean;
9
+ sphere_segments: number;
10
+ bond_thickness: number;
11
+ auto_bond_order: boolean;
12
+ aromatic_display: "aromatic" | "kekule";
13
+ show_bonds: "always" | "never" | "crystals" | "molecules";
14
+ bond_color: string;
15
+ bonding_strategy: "electroneg_ratio" | "solid_angle";
16
+ show_polyhedra: "always" | "never" | "crystals" | "molecules";
17
+ polyhedra_opacity: number;
18
+ polyhedra_show_edges: boolean;
19
+ polyhedra_edge_color: string;
20
+ polyhedra_color_mode: import("./polyhedra").PolyhedraColorMode;
21
+ polyhedra_color: string;
22
+ polyhedra_hide_center_atoms: boolean;
23
+ polyhedra_min_neighbors: number;
24
+ polyhedra_max_neighbors: number;
25
+ polyhedra_excluded_elements: readonly string[];
26
+ polyhedra_included_elements: readonly string[];
27
+ atom_color_mode: "element" | "coordination" | "wyckoff" | "custom";
28
+ atom_color_scale: import("..").D3InterpolateName;
29
+ atom_color_scale_type: "continuous" | "categorical";
30
+ show_gizmo: boolean;
31
+ camera_position: import("..").Vec3;
32
+ camera_projection: import("../settings").CameraProjection;
33
+ initial_zoom: number;
34
+ fov: number;
35
+ rotation_damping: number;
36
+ rotate_speed: number;
37
+ zoom_speed: number;
38
+ pan_speed: number;
39
+ zoom_to_cursor: boolean;
40
+ max_zoom: number | undefined;
41
+ min_zoom: number | undefined;
42
+ auto_rotate: number;
43
+ rotation: import("..").Vec3;
44
+ show_site_labels: boolean;
45
+ show_site_indices: boolean;
46
+ site_label_size: number;
47
+ site_label_color: string;
48
+ site_label_bg_color: string;
49
+ site_label_padding: number;
50
+ site_label_offset: import("..").Vec3;
51
+ ambient_light: number;
52
+ directional_light: number;
53
+ vector_configs: Record<string, import("../settings").VectorLayerConfig>;
54
+ vector_scale: number;
55
+ vector_color: string;
56
+ vector_color_mode: "auto" | "element" | "uniform" | "spin_direction" | "magnitude";
57
+ vector_color_scale: import("..").D3InterpolateName;
58
+ vector_normalize: boolean;
59
+ vector_uniform_thickness: boolean;
60
+ vector_origin_gap: number;
61
+ vector_shaft_radius: number;
62
+ vector_arrow_head_radius: number;
63
+ vector_arrow_head_length: number;
64
+ show_cell: boolean;
65
+ show_cell_vectors: boolean;
66
+ cell_edge_opacity: number;
67
+ cell_surface_opacity: number;
68
+ cell_edge_color: string;
69
+ cell_surface_color: string;
70
+ cell_edge_width: number;
71
+ fullscreen_toggle: boolean;
72
+ };
73
+ lattice_props: {
74
+ cell_edge_opacity: number;
75
+ cell_surface_opacity: number;
76
+ cell_edge_color: string;
77
+ cell_surface_color: string;
78
+ cell_edge_width: number;
79
+ show_cell_vectors: boolean;
80
+ };
81
+ color_scheme: string;
82
+ background_color: string;
83
+ background_opacity: number;
84
+ show_image_atoms: boolean;
85
+ };
@@ -0,0 +1,18 @@
1
+ export const build_structure_props_from_settings = (defaults) => {
2
+ const { structure } = defaults;
3
+ return {
4
+ scene_props: { ...structure, gizmo: structure.show_gizmo },
5
+ lattice_props: {
6
+ cell_edge_opacity: structure.cell_edge_opacity,
7
+ cell_surface_opacity: structure.cell_surface_opacity,
8
+ cell_edge_color: structure.cell_edge_color,
9
+ cell_surface_color: structure.cell_surface_color,
10
+ cell_edge_width: structure.cell_edge_width,
11
+ show_cell_vectors: structure.show_cell_vectors,
12
+ },
13
+ color_scheme: defaults.color_scheme,
14
+ background_color: defaults.background_color,
15
+ background_opacity: defaults.background_opacity,
16
+ show_image_atoms: structure.show_image_atoms,
17
+ };
18
+ };
@@ -1,8 +1,7 @@
1
1
  import type { Vec3 } from '../math';
2
- import { scale_lattice_matrix } from '../math';
3
2
  import type { Crystal } from './index';
4
3
  export declare function parse_supercell_scaling(scaling: string | number | Vec3): Vec3;
5
4
  export declare function generate_lattice_points(scaling_factors: Vec3): Vec3[];
6
- export { scale_lattice_matrix };
5
+ export { scale_lattice_matrix } from '../math';
7
6
  export declare function make_supercell(structure: Crystal, scaling: string | number | Vec3, to_unit_cell?: boolean): Crystal;
8
7
  export declare function is_valid_supercell_input(input: string): boolean;
@@ -1,5 +1,4 @@
1
1
  import * as math from '../math';
2
- import { scale_lattice_matrix } from '../math';
3
2
  import { wrap_frac_coord } from './pbc';
4
3
  import { normalize_structure_bond } from './bonding';
5
4
  const mod = (value, divisor) => ((value % divisor) + divisor) % divisor;
@@ -79,7 +78,7 @@ export function generate_lattice_points(scaling_factors) {
79
78
  return points;
80
79
  }
81
80
  // Re-export from $lib/math for backward compatibility
82
- export { scale_lattice_matrix };
81
+ export { scale_lattice_matrix } from '../math';
83
82
  // Create a supercell from a Crystal
84
83
  // Takes original structure, scaling factors, and whether to fold coordinates back to unit cell (default: true)
85
84
  // Returns new supercell structure
@@ -96,19 +95,14 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
96
95
  }
97
96
  const orig_matrix = structure.lattice.matrix;
98
97
  // Create new scaled lattice
99
- const new_lattice_matrix = scale_lattice_matrix(orig_matrix, supercell_scaling);
100
- const lattice_params = math.calc_lattice_params(new_lattice_matrix);
101
- const new_lattice = {
102
- ...structure.lattice,
103
- matrix: new_lattice_matrix,
104
- ...lattice_params,
105
- };
98
+ const new_matrix = math.scale_lattice_matrix(orig_matrix, supercell_scaling);
99
+ const lattice_params = math.calc_lattice_params(new_matrix);
100
+ const new_lattice = { ...structure.lattice, matrix: new_matrix, ...lattice_params };
106
101
  // Pre-allocate sites array
107
102
  const n_sites = structure.sites.length;
108
103
  const new_sites = Array(n_sites * total_cells);
109
104
  // Destructure lattice vectors for fast inline arithmetic (avoid function calls in hot loop)
110
105
  const [[ax, ay, az], [bx, by, bz], [cx, cy, cz]] = orig_matrix;
111
- const [sx, sy, sz] = supercell_scaling;
112
106
  let write_idx = 0;
113
107
  const sites = structure.sites;
114
108
  // Loop order: k, j, i to match typical pymatgen/standard ordering
@@ -124,9 +118,9 @@ export function make_supercell(structure, scaling, to_unit_cell = true) {
124
118
  for (let site_idx = 0; site_idx < n_sites; site_idx++) {
125
119
  const site = sites[site_idx];
126
120
  // new_abc = (old_abc + [ii, jj, kk]) / supercell_scaling
127
- let new_a = (site.abc[0] + ii) / sx;
128
- let new_b = (site.abc[1] + jj) / sy;
129
- let new_c = (site.abc[2] + kk) / sz;
121
+ let new_a = (site.abc[0] + ii) / scale_x;
122
+ let new_b = (site.abc[1] + jj) / scale_y;
123
+ let new_c = (site.abc[2] + kk) / scale_z;
130
124
  if (to_unit_cell) {
131
125
  new_a = wrap_frac_coord(new_a);
132
126
  new_b = wrap_frac_coord(new_b);