matterviz 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +75 -85
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  11. package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  13. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  14. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
  15. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  16. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
  17. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  18. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  19. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  20. package/dist/colors/index.d.ts +0 -4
  21. package/dist/colors/index.js +19 -20
  22. package/dist/composition/BarChart.svelte +37 -31
  23. package/dist/composition/BubbleChart.svelte +17 -17
  24. package/dist/composition/Composition.svelte +7 -11
  25. package/dist/composition/Formula.svelte +18 -25
  26. package/dist/composition/FormulaFilter.svelte +92 -95
  27. package/dist/composition/PieChart.svelte +55 -41
  28. package/dist/composition/format.js +1 -1
  29. package/dist/composition/index.d.ts +2 -0
  30. package/dist/composition/index.js +14 -0
  31. package/dist/composition/parse.d.ts +2 -2
  32. package/dist/composition/parse.js +11 -10
  33. package/dist/constants.js +11 -9
  34. package/dist/convex-hull/ConvexHull.svelte +12 -15
  35. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  36. package/dist/convex-hull/ConvexHull2D.svelte +93 -92
  37. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  38. package/dist/convex-hull/ConvexHull3D.svelte +109 -140
  39. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  40. package/dist/convex-hull/ConvexHull4D.svelte +75 -94
  41. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  42. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  43. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  44. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  45. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  46. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  47. package/dist/convex-hull/StructurePopup.svelte +17 -21
  48. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  49. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  50. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  51. package/dist/convex-hull/helpers.d.ts +8 -10
  52. package/dist/convex-hull/helpers.js +36 -36
  53. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  54. package/dist/convex-hull/thermodynamics.js +18 -17
  55. package/dist/coordination/CoordinationBarPlot.svelte +38 -33
  56. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  57. package/dist/coordination/calc-coordination.d.ts +1 -1
  58. package/dist/coordination/calc-coordination.js +28 -25
  59. package/dist/element/BohrAtom.svelte +5 -8
  60. package/dist/element/ElementHeading.svelte +4 -1
  61. package/dist/element/ElementPhoto.svelte +11 -9
  62. package/dist/element/ElementStats.svelte +12 -10
  63. package/dist/element/ElementTile.svelte +24 -29
  64. package/dist/element/Nucleus.svelte +4 -2
  65. package/dist/element/data.d.ts +1 -2
  66. package/dist/element/helpers.d.ts +4 -0
  67. package/dist/element/helpers.js +18 -0
  68. package/dist/element/index.d.ts +1 -4
  69. package/dist/element/index.js +3 -18
  70. package/dist/feedback/DragOverlay.svelte +5 -5
  71. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  72. package/dist/feedback/StatusMessage.svelte +7 -4
  73. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  74. package/dist/fermi-surface/FermiSurface.svelte +14 -22
  75. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
  76. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  77. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  78. package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
  79. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  80. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  81. package/dist/fermi-surface/compute.js +3 -3
  82. package/dist/fermi-surface/parse.js +22 -24
  83. package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
  84. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  85. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  86. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  87. package/dist/heatmap-matrix/index.d.ts +5 -0
  88. package/dist/icons.d.ts +4 -0
  89. package/dist/icons.js +4 -0
  90. package/dist/io/ExportPane.svelte +10 -6
  91. package/dist/io/decompress.d.ts +2 -1
  92. package/dist/io/decompress.js +22 -35
  93. package/dist/io/export.d.ts +4 -0
  94. package/dist/io/export.js +5 -1
  95. package/dist/io/fetch.d.ts +0 -3
  96. package/dist/io/fetch.js +0 -11
  97. package/dist/io/index.d.ts +0 -1
  98. package/dist/io/index.js +2 -9
  99. package/dist/io/is-binary.d.ts +9 -0
  100. package/dist/io/is-binary.js +45 -1
  101. package/dist/io/url-drop.js +13 -25
  102. package/dist/isosurface/Isosurface.svelte +17 -23
  103. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  104. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  105. package/dist/isosurface/parse-vaspwave.js +138 -0
  106. package/dist/isosurface/parse.js +6 -6
  107. package/dist/labels.d.ts +6 -2
  108. package/dist/labels.js +43 -13
  109. package/dist/layout/FullscreenButton.svelte +2 -1
  110. package/dist/layout/FullscreenToggle.svelte +10 -4
  111. package/dist/layout/InfoCard.svelte +7 -18
  112. package/dist/layout/InfoTag.svelte +1 -3
  113. package/dist/layout/NumberRangeInput.svelte +46 -0
  114. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  115. package/dist/layout/PropertyFilter.svelte +2 -6
  116. package/dist/layout/SettingsSection.svelte +21 -17
  117. package/dist/layout/SubpageGrid.svelte +3 -1
  118. package/dist/layout/ViewerChrome.svelte +9 -10
  119. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  120. package/dist/layout/fullscreen.js +3 -5
  121. package/dist/layout/fullscreen.svelte.js +1 -2
  122. package/dist/layout/index.d.ts +1 -0
  123. package/dist/layout/index.js +1 -0
  124. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  125. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  126. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  127. package/dist/layout/json-tree/utils.js +14 -23
  128. package/dist/math.d.ts +2 -0
  129. package/dist/math.js +19 -0
  130. package/dist/overlays/ContextMenu.svelte +4 -2
  131. package/dist/overlays/CopyButton.svelte +11 -5
  132. package/dist/overlays/DragControlTab.svelte +6 -1
  133. package/dist/overlays/DraggablePane.svelte +81 -26
  134. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  135. package/dist/overlays/GlassChip.svelte +30 -0
  136. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  137. package/dist/overlays/InfoPaneCards.svelte +11 -23
  138. package/dist/overlays/index.d.ts +7 -0
  139. package/dist/overlays/index.js +26 -0
  140. package/dist/overlays/portal.d.ts +2 -0
  141. package/dist/overlays/portal.js +14 -0
  142. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  143. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  144. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  145. package/dist/periodic-table/TableInset.svelte +9 -4
  146. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  147. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  148. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  149. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  150. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  151. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  152. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  153. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  154. package/dist/phase-diagram/build-diagram.js +3 -3
  155. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  156. package/dist/phase-diagram/parse.js +15 -15
  157. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  158. package/dist/phase-diagram/utils.js +2 -3
  159. package/dist/plot/bar/BarPlot.svelte +430 -391
  160. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  161. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  162. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  163. package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
  164. package/dist/plot/bar/data.d.ts +5 -4
  165. package/dist/plot/bar/data.js +2 -1
  166. package/dist/plot/box/BoxPlot.svelte +301 -209
  167. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  168. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  169. package/dist/plot/box/box-plot.js +1 -1
  170. package/dist/plot/core/auto-place.js +1 -1
  171. package/dist/plot/core/axis-utils.d.ts +12 -7
  172. package/dist/plot/core/axis-utils.js +48 -48
  173. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  174. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  175. package/dist/plot/core/components/ColorBar.svelte +101 -106
  176. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  177. package/dist/plot/core/components/FillArea.svelte +10 -17
  178. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  179. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  180. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  181. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  182. package/dist/plot/core/components/Line.svelte +18 -9
  183. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  184. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  185. package/dist/plot/core/components/PlotControls.svelte +65 -41
  186. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  187. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  188. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  189. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  190. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  191. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  192. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  193. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  194. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  195. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  196. package/dist/plot/core/components/index.d.ts +1 -0
  197. package/dist/plot/core/components/index.js +1 -0
  198. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  199. package/dist/plot/core/data-cleaning-signal.js +467 -0
  200. package/dist/plot/core/data-cleaning.d.ts +2 -42
  201. package/dist/plot/core/data-cleaning.js +27 -474
  202. package/dist/plot/core/data-transform.js +9 -5
  203. package/dist/plot/core/fill-utils.d.ts +3 -1
  204. package/dist/plot/core/fill-utils.js +28 -6
  205. package/dist/plot/core/index.d.ts +1 -0
  206. package/dist/plot/core/index.js +1 -0
  207. package/dist/plot/core/interactions.js +0 -2
  208. package/dist/plot/core/layout.d.ts +3 -1
  209. package/dist/plot/core/layout.js +22 -13
  210. package/dist/plot/core/marginals.d.ts +170 -0
  211. package/dist/plot/core/marginals.js +436 -0
  212. package/dist/plot/core/reference-line.js +1 -1
  213. package/dist/plot/core/scales.d.ts +23 -0
  214. package/dist/plot/core/scales.js +39 -13
  215. package/dist/plot/core/types/fills.d.ts +101 -0
  216. package/dist/plot/core/types/fills.js +15 -0
  217. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  218. package/dist/plot/core/types/plot-3d.js +4 -0
  219. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  220. package/dist/plot/core/types/reference-lines.js +9 -0
  221. package/dist/plot/core/types.d.ts +29 -324
  222. package/dist/plot/core/types.js +23 -20
  223. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  224. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  225. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  226. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  227. package/dist/plot/core/utils/label-placement.js +2 -2
  228. package/dist/plot/histogram/Histogram.svelte +304 -325
  229. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  230. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  231. package/dist/plot/histogram/histogram.d.ts +31 -0
  232. package/dist/plot/histogram/histogram.js +70 -0
  233. package/dist/plot/histogram/index.d.ts +1 -0
  234. package/dist/plot/histogram/index.js +1 -0
  235. package/dist/plot/index.d.ts +1 -0
  236. package/dist/plot/index.js +1 -0
  237. package/dist/plot/sankey/Sankey.svelte +78 -69
  238. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  239. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  240. package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
  241. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  242. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  243. package/dist/plot/scatter/ScatterPlot.svelte +477 -385
  244. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  245. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  246. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  247. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  248. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  249. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  250. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  251. package/dist/plot/scatter/scatter-data.js +8 -7
  252. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  253. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  254. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  255. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  256. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  257. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  258. package/dist/plot/sunburst/Sunburst.svelte +251 -329
  259. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  260. package/dist/plot/sunburst/index.d.ts +1 -1
  261. package/dist/plot/sunburst/index.js +2 -1
  262. package/dist/plot/sunburst/render.d.ts +2 -2
  263. package/dist/plot/sunburst/render.js +47 -22
  264. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  265. package/dist/plot/sunburst/sunburst.js +10 -3
  266. package/dist/plot/treemap/Treemap.svelte +907 -0
  267. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  268. package/dist/plot/treemap/index.d.ts +3 -0
  269. package/dist/plot/treemap/index.js +4 -0
  270. package/dist/plot/treemap/treemap.d.ts +26 -0
  271. package/dist/plot/treemap/treemap.js +99 -0
  272. package/dist/rdf/RdfPlot.svelte +22 -26
  273. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  274. package/dist/rdf/calc-rdf.js +4 -8
  275. package/dist/sanitize.js +1 -1
  276. package/dist/scene/bind-renderer.svelte.js +14 -6
  277. package/dist/settings.d.ts +19 -9
  278. package/dist/settings.js +77 -50
  279. package/dist/spectral/Bands.svelte +223 -230
  280. package/dist/spectral/BandsAndDos.svelte +11 -9
  281. package/dist/spectral/BrillouinBandsDos.svelte +19 -27
  282. package/dist/spectral/Dos.svelte +70 -73
  283. package/dist/spectral/helpers.d.ts +3 -3
  284. package/dist/spectral/helpers.js +25 -35
  285. package/dist/state.svelte.js +5 -18
  286. package/dist/structure/Arrow.svelte +5 -18
  287. package/dist/structure/ArrowInstances.svelte +160 -0
  288. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  289. package/dist/structure/AtomLegend.svelte +115 -75
  290. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  291. package/dist/structure/Bond.svelte +31 -23
  292. package/dist/structure/CanvasTooltip.svelte +15 -3
  293. package/dist/structure/CellSelect.svelte +11 -26
  294. package/dist/structure/Cylinder.svelte +24 -40
  295. package/dist/structure/InstancedAtoms.svelte +114 -0
  296. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  297. package/dist/structure/Lattice.svelte +85 -149
  298. package/dist/structure/SiteLabels.svelte +122 -0
  299. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  300. package/dist/structure/Structure.svelte +473 -419
  301. package/dist/structure/Structure.svelte.d.ts +4 -2
  302. package/dist/structure/StructureCarousel.svelte +630 -0
  303. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  304. package/dist/structure/StructureControls.svelte +157 -399
  305. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  306. package/dist/structure/StructureExportPane.svelte +17 -21
  307. package/dist/structure/StructureInfoPane.svelte +72 -66
  308. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  309. package/dist/structure/StructureScene.svelte +467 -476
  310. package/dist/structure/StructureScene.svelte.d.ts +3 -1
  311. package/dist/structure/StructureViewport.svelte +386 -0
  312. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  313. package/dist/structure/atom-label-placement.d.ts +16 -12
  314. package/dist/structure/atom-label-placement.js +70 -37
  315. package/dist/structure/atom-properties.d.ts +2 -0
  316. package/dist/structure/atom-properties.js +104 -38
  317. package/dist/structure/bonding.d.ts +10 -3
  318. package/dist/structure/bonding.js +84 -28
  319. package/dist/structure/edit-history.d.ts +6 -0
  320. package/dist/structure/edit-history.js +27 -0
  321. package/dist/structure/export.d.ts +1 -0
  322. package/dist/structure/export.js +39 -31
  323. package/dist/structure/format-detect.d.ts +1 -0
  324. package/dist/structure/format-detect.js +22 -0
  325. package/dist/structure/geometry.d.ts +9 -0
  326. package/dist/structure/geometry.js +27 -0
  327. package/dist/structure/index.d.ts +16 -1
  328. package/dist/structure/index.js +13 -2
  329. package/dist/structure/measure.d.ts +1 -1
  330. package/dist/structure/measure.js +6 -12
  331. package/dist/structure/parse.d.ts +2 -1
  332. package/dist/structure/parse.js +243 -222
  333. package/dist/structure/partial-occupancy.js +4 -2
  334. package/dist/structure/pbc.js +78 -98
  335. package/dist/structure/polyhedra.d.ts +0 -1
  336. package/dist/structure/polyhedra.js +3 -18
  337. package/dist/structure/supercell.d.ts +1 -2
  338. package/dist/structure/supercell.js +7 -13
  339. package/dist/symmetry/SymmetryElements.svelte +11 -15
  340. package/dist/symmetry/SymmetryStats.svelte +56 -68
  341. package/dist/symmetry/WyckoffTable.svelte +5 -24
  342. package/dist/symmetry/cell-transform.js +1 -0
  343. package/dist/symmetry/index.d.ts +1 -0
  344. package/dist/symmetry/index.js +8 -2
  345. package/dist/symmetry/spacegroups.js +3 -2
  346. package/dist/table/HeatmapTable.svelte +1102 -365
  347. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  348. package/dist/table/ToggleMenu.svelte +5 -12
  349. package/dist/table/index.d.ts +21 -6
  350. package/dist/table/index.js +34 -21
  351. package/dist/theme/ThemeControl.svelte +16 -8
  352. package/dist/theme/index.d.ts +1 -5
  353. package/dist/theme/index.js +4 -10
  354. package/dist/theme/themes.mjs +14 -7
  355. package/dist/tooltip/KCoords.svelte +4 -1
  356. package/dist/tooltip/TooltipContent.svelte +2 -5
  357. package/dist/trajectory/Trajectory.svelte +515 -308
  358. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  359. package/dist/trajectory/TrajectoryError.svelte +11 -8
  360. package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
  361. package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
  362. package/dist/trajectory/extract.js +56 -34
  363. package/dist/trajectory/format-detect.js +11 -9
  364. package/dist/trajectory/frame-reader.d.ts +2 -0
  365. package/dist/trajectory/frame-reader.js +33 -29
  366. package/dist/trajectory/helpers.d.ts +2 -0
  367. package/dist/trajectory/helpers.js +18 -7
  368. package/dist/trajectory/index.d.ts +1 -0
  369. package/dist/trajectory/index.js +3 -0
  370. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  371. package/dist/trajectory/parse/h5-utils.js +109 -0
  372. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  373. package/dist/trajectory/parse/hdf5.js +116 -106
  374. package/dist/trajectory/parse/index.d.ts +2 -3
  375. package/dist/trajectory/parse/index.js +17 -20
  376. package/dist/trajectory/parse/lammps.js +8 -12
  377. package/dist/trajectory/parse/vasp.js +10 -7
  378. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  379. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  380. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  381. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  382. package/dist/trajectory/parse/xyz.js +11 -7
  383. package/dist/trajectory/plotting.d.ts +8 -9
  384. package/dist/trajectory/plotting.js +99 -27
  385. package/dist/utils.d.ts +3 -0
  386. package/dist/utils.js +7 -0
  387. package/dist/xrd/XrdPlot.svelte +47 -61
  388. package/dist/xrd/broadening.js +2 -1
  389. package/dist/xrd/calc-xrd.js +2 -4
  390. package/dist/xrd/parse.d.ts +0 -1
  391. package/dist/xrd/parse.js +56 -73
  392. package/package.json +61 -33
  393. package/dist/api/mp.d.ts +0 -6
  394. package/dist/api/mp.js +0 -22
  395. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
@@ -60,7 +60,8 @@ export const PARTIAL_OCCUPANCY_CAP_ARC = {
60
60
  };
61
61
  export const merge_split_partial_sites = (sites, hidden_elements = new Set()) => {
62
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);
63
+ const { non_grouped_site_indices, grouped_site_indices } = grouped_indices;
64
+ return build_render_sites(sites, non_grouped_site_indices, grouped_site_indices);
64
65
  };
65
66
  export const compute_slice_geometry = (visible_species, slice_gap_rad = PARTIAL_OCCUPANCY_SLICE_GAP_RAD) => {
66
67
  if (visible_species.length === 0)
@@ -72,7 +73,8 @@ export const compute_slice_geometry = (visible_species, slice_gap_rad = PARTIAL_
72
73
  element,
73
74
  occu: occu * occupancy_scale_factor,
74
75
  }));
75
- const normalized_total_occupancy = normalized_species.reduce((occupancy_sum, { occu }) => occupancy_sum + occu, 0);
76
+ // Sum of scaled occupancies equals total * scale (avoids a second O(n) pass)
77
+ const normalized_total_occupancy = total_visible_occupancy * occupancy_scale_factor;
76
78
  const has_vacancy_gap = normalized_total_occupancy < 1 - OCCUPANCY_EPS;
77
79
  const last_visible_species_idx = normalized_species.length - 1;
78
80
  let start_angle = 0;
@@ -1,5 +1,5 @@
1
1
  import * as math from '../math';
2
- import { element_lookup, get_majority_element } from './bonding';
2
+ import { element_lookup, get_majority_element, has_framework_potential, is_spectator_center, pack_cell_key, } from './bonding';
3
3
  // Distance slack added to the covalent-radii sum when deciding whether a
4
4
  // candidate image atom bonds to a base atom (VESTA-like bond search criterion)
5
5
  const BOND_SLACK = 0.4; // Å
@@ -34,42 +34,30 @@ const is_scattered_trajectory = (sites) => {
34
34
  const atoms_outside_cell = sites.filter(({ abc }) => abc.some((coord) => coord < -0.1 || coord > 1.1));
35
35
  return atoms_outside_cell.length > sites.length * 0.1;
36
36
  };
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
37
  export function find_image_atoms(structure, { tolerance } = {}) {
40
38
  // 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.
39
+ // tuples; is_completion marks phase-2 images that only complete bonds / coordination
40
+ // polyhedra at cell faces (renderers may hide them). Skips scattered trajectories.
44
41
  if (!structure.lattice || !structure.sites || structure.sites.length === 0)
45
42
  return [];
46
43
  if (is_scattered_trajectory(structure.sites))
47
44
  return [];
48
- // Check if this is a supercell to correctly identify external boundaries correctly
49
45
  const image_sites = [];
50
46
  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
47
+ const frac_to_cart = math.create_frac_to_cart(lattice_vecs);
48
+ const vec_lens = lattice_vecs.map((vec) => Math.hypot(...vec));
49
+ // Scale zero-displacement threshold by lattice length scale to avoid magic numbers
50
+ const lattice_norm = Math.max(...vec_lens);
54
51
  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];
52
+ // Boundary tolerance: physical 0.5 Å as fractional per-axis, so large cells (MOFs)
53
+ // don't over-generate (a flat 0.05 fractional would be huge there)
54
+ const PHYSICAL_TOLERANCE = 0.5; // Å
55
+ const tolerances = vec_lens.map((vec_len) => tolerance ?? (vec_len > 0 ? PHYSICAL_TOLERANCE / vec_len : 0.05));
56
+ const pbc = structure.lattice.pbc ?? [true, true, true]; // no images across vacuum
57
+ // Phase 1: true periodic copies of atoms within `tolerance` of a cell face (bond
58
+ // lengths preserved, rather than clamping the copy to the cell face)
69
59
  for (const [idx, site] of structure.sites.entries()) {
70
- // Find edge dimensions and translation directions
71
60
  const edge_dims = [];
72
- // Find boundary dimensions
73
61
  for (let dim = 0; dim < 3; dim++) {
74
62
  if (!pbc[dim])
75
63
  continue;
@@ -80,10 +68,9 @@ export function find_image_atoms(structure, { tolerance } = {}) {
80
68
  if (Math.abs(coord - 1) < dim_tolerance)
81
69
  edge_dims.push({ dim, direction: -1 });
82
70
  }
83
- // Generate all translation combinations
71
+ // Generate all translation combinations; if both +1 and -1 are selected for a dim the
72
+ // net shift is zero and we skip (yields no image).
84
73
  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
74
  const selected_shift = [0, 0, 0];
88
75
  for (let bit = 0; bit < edge_dims.length; bit++) {
89
76
  if (mask & (1 << bit)) {
@@ -91,25 +78,18 @@ export function find_image_atoms(structure, { tolerance } = {}) {
91
78
  selected_shift[dim] += direction;
92
79
  }
93
80
  }
94
- // Early skip if no net shift across any dimension
95
81
  if (selected_shift.every((val) => val === 0))
96
82
  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.
83
+ const [s_a, s_b, s_c] = site.abc;
100
84
  const img_abc = [
101
- site.abc[0] + selected_shift[0],
102
- site.abc[1] + selected_shift[1],
103
- site.abc[2] + selected_shift[2],
85
+ s_a + selected_shift[0],
86
+ s_b + selected_shift[1],
87
+ s_c + selected_shift[2],
104
88
  ];
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])
89
+ if (img_abc[0] === s_a && img_abc[1] === s_b && img_abc[2] === s_c)
109
90
  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)
91
+ const img_xyz = frac_to_cart(img_abc);
92
+ // Skip zero-displacement images (guards against FP edge cases)
113
93
  const displacement = math.subtract(img_xyz, site.xyz);
114
94
  const displacement_len_sq = displacement.reduce((sum, val) => sum + val * val, 0);
115
95
  if (displacement_len_sq < displacement_eps_sq)
@@ -117,87 +97,91 @@ export function find_image_atoms(structure, { tolerance } = {}) {
117
97
  image_sites.push([idx, img_xyz, img_abc]);
118
98
  }
119
99
  }
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).
100
+ // Per-site element data for the phase-2 completion pass. present_elements is the tiny
101
+ // composition (so has_framework_potential doesn't re-scan every site in big supercells).
102
+ const site_elements = [];
133
103
  const site_radii = [];
134
104
  const site_en = [];
135
105
  const site_is_metal = [];
106
+ const present_elements = new Set();
136
107
  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
108
  for (const site of structure.sites) {
141
109
  const elem = get_majority_element(site);
142
110
  const data = elem === null ? undefined : element_lookup.get(elem);
143
111
  const radius = data?.covalent_radius ?? null;
144
- const en = data?.electronegativity ?? null;
112
+ site_elements.push(elem);
113
+ if (elem !== null)
114
+ present_elements.add(elem);
145
115
  site_radii.push(radius);
146
- site_en.push(en);
116
+ site_en.push(data?.electronegativity ?? null);
147
117
  site_is_metal.push(data?.metal === true);
148
118
  if (radius !== null && radius > max_radius)
149
119
  max_radius = radius;
150
- if (radius !== null && en !== null && en < min_anchor_en)
120
+ }
121
+ // Skip spectator A-site cations (Li/Na, heavy alkaline earths) when a framework cation
122
+ // is present: they render no polyhedron, so completing their shells floats coordination
123
+ // groups (e.g. a PO4 around a corner Li) beyond the cell. Purely ionic binaries (NaCl)
124
+ // keep theirs. Note: a spectator force-included as a polyhedra center (compute_polyhedra's
125
+ // included_center_elements) is still skipped here, so its boundary polyhedra truncate at
126
+ // cell faces - accepted to keep image generation independent of render-only settings.
127
+ const skip_spectators = has_framework_potential(present_elements);
128
+ const site_skipped = site_elements.map((elem) => skip_spectators && elem !== null && is_spectator_center(elem));
129
+ // Phase 2: anion images that complete coordination polyhedra / bonds at cell faces.
130
+ // Phase 1's ~0.5 Å face tolerance misses anions just beyond a face that still bond a
131
+ // cation near it, truncating boundary polyhedra. We add ONLY such images: a candidate
132
+ // must be a polyhedron vertex (non-metal/metalloid, like is_anion_vertex in polyhedra.ts)
133
+ // AND strictly more electronegative than the anchor it bonds. Metals, intermetallics,
134
+ // equal-EN networks and cation copies get none, keeping renders minimal.
135
+ // Min anchor EN: a candidate only completes a cation's shell if more electronegative
136
+ // than it. Over non-skipped anchors only, so skipped spectators can't loosen the filter.
137
+ let min_anchor_en = Infinity;
138
+ for (let idx = 0; idx < structure.sites.length; idx++) {
139
+ if (site_skipped[idx])
140
+ continue;
141
+ const en = site_en[idx];
142
+ if (site_radii[idx] !== null && en !== null && en < min_anchor_en)
151
143
  min_anchor_en = en;
152
144
  }
153
145
  const max_bond_dist = 2 * max_radius + BOND_SLACK;
154
146
  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).
147
+ // Per-axis fractional bond reach via perpendicular cell heights (correct for oblique
148
+ // cells; 0 for degenerate cells no images). The + face tolerance covers phase-1
149
+ // anchors sitting slightly outside the cell.
150
+ const pad_per_axis = math.frac_cutoff_per_axis(lattice_vecs, max_bond_dist + PHYSICAL_TOLERANCE);
151
+ // Bond-test anchors = base atoms + phase-1 boundary images, so every displayed
152
+ // boundary cation gets its shell completed (VESTA-like; e.g. all 8 rutile corners).
174
153
  const anchor_positions = structure.sites.map((site) => site.xyz);
175
154
  const anchor_radii = [...site_radii];
176
155
  const anchor_en = [...site_en];
156
+ const anchor_skipped = [...site_skipped];
177
157
  for (const [src_idx, img_xyz] of image_sites) {
178
158
  anchor_positions.push(img_xyz);
179
159
  anchor_radii.push(site_radii[src_idx]);
180
160
  anchor_en.push(site_en[src_idx]);
161
+ anchor_skipped.push(site_skipped[src_idx]);
181
162
  }
182
- // Spatial grid over anchors for the bond check
163
+ // Spatial grid over anchors for the bond check (integer-packed keys: this
164
+ // grid is probed 27x per candidate image in the loop below)
183
165
  const grid = new Map();
184
- const grid_key = (pos) => pos.map((coord) => Math.floor(coord / max_bond_dist)).join(`,`);
185
166
  for (const [idx, pos] of anchor_positions.entries()) {
186
- const key = grid_key(pos);
167
+ 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
168
  const cell = grid.get(key);
188
169
  if (cell)
189
170
  cell.push(idx);
190
171
  else
191
172
  grid.set(key, [idx]);
192
173
  }
193
- // True when the candidate (an anion image) bonds a strictly less
194
- // electronegative anchor, i.e. completes some cation's coordination shell
174
+ // True when the candidate (an anion image) bonds a strictly less electronegative
175
+ // anchor, i.e. completes some cation's coordination shell
195
176
  const completes_cation_shell = (pos, radius, en) => {
196
177
  const [cx, cy, cz] = pos.map((coord) => Math.floor(coord / max_bond_dist));
197
178
  for (let dx = -1; dx <= 1; dx++) {
198
179
  for (let dy = -1; dy <= 1; dy++) {
199
180
  for (let dz = -1; dz <= 1; dz++) {
200
- for (const anchor_idx of grid.get(`${cx + dx},${cy + dy},${cz + dz}`) ?? []) {
181
+ for (const anchor_idx of grid.get(pack_cell_key(cx + dx, cy + dy, cz + dz)) ??
182
+ []) {
183
+ if (anchor_skipped[anchor_idx])
184
+ continue;
201
185
  const anchor_radius = anchor_radii[anchor_idx];
202
186
  const anchor_electroneg = anchor_en[anchor_idx];
203
187
  if (anchor_radius === null)
@@ -221,22 +205,19 @@ export function find_image_atoms(structure, { tolerance } = {}) {
221
205
  for (const [idx, site] of structure.sites.entries()) {
222
206
  const radius = site_radii[idx];
223
207
  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)
208
+ // Skip candidates that could never be a polyhedron vertex: metals (e.g. Fe/Ni in
209
+ // Al-Fe-Ni intermetallics) and anything not strictly more electronegative than at
210
+ // least one anchor (covers elemental/equal-EN structures and all cations)
228
211
  if (radius === null || en === null || en <= min_anchor_en)
229
212
  continue;
230
213
  if (site_is_metal[idx])
231
214
  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
215
+ // Per-axis shifts that could land a copy of this atom within bonding reach of the
216
+ // cell: {0} plus +1/-1 when the atom is within max_bond_dist of the boundary
235
217
  const axis_shifts = [0, 1, 2].map((axis) => {
236
218
  if (!pbc[axis])
237
219
  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];
220
+ const pad = pad_per_axis[axis];
240
221
  const shifts = [0];
241
222
  if (site.abc[axis] < pad)
242
223
  shifts.push(1);
@@ -257,7 +238,7 @@ export function find_image_atoms(structure, { tolerance } = {}) {
257
238
  site.abc[1] + shift_b,
258
239
  site.abc[2] + shift_c,
259
240
  ];
260
- const img_xyz = frac_to_cart_pos(img_abc, lattice_vecs);
241
+ const img_xyz = frac_to_cart(img_abc);
261
242
  if (!completes_cation_shell(img_xyz, radius, en))
262
243
  continue;
263
244
  seen_images.add(key);
@@ -281,7 +262,6 @@ export function get_pbc_image_sites(...args) {
281
262
  // Add image atoms to regular crystal structures
282
263
  const image_sites = find_image_atoms(...args);
283
264
  const imaged_struct = { ...structure, sites: [...structure.sites] };
284
- // Add image atoms as new sites using provided (xyz, abc) from find_image_atoms
285
265
  for (const [site_idx, img_xyz, img_abc, is_completion] of image_sites) {
286
266
  const orig_site = structure.sites[site_idx];
287
267
  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;
@@ -6,7 +6,7 @@
6
6
  import { rgb as parse_rgb } from 'd3-color';
7
7
  import { DEFAULTS } from '../settings';
8
8
  import { get_orig_site_idx } from './atom-properties';
9
- import { element_lookup, get_majority_element } from './bonding';
9
+ import { element_lookup, get_majority_element, has_framework_potential, is_spectator_center, } from './bonding';
10
10
  const face_of = (points, vert_a, vert_b, vert_c) => {
11
11
  const [ax, ay, az] = points[vert_a];
12
12
  const abx = points[vert_b][0] - ax;
@@ -294,15 +294,6 @@ export function build_adjacency(bonds) {
294
294
  return adjacency;
295
295
  }
296
296
  // --- 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
297
  // A bonded neighbor counts as a polyhedron vertex only if it's an anion-former:
307
298
  // a nonmetal or metalloid that is more electronegative than the center. This keeps
308
299
  // spurious cation-cation bonds (e.g. Ti-Ba in perovskites, Li-P in thiophosphates)
@@ -426,13 +417,7 @@ export function compute_polyhedra(structure, bonds, options = {}) {
426
417
  // the anions). Composition-based rather than candidate-based so boundary
427
418
  // truncation of framework polyhedra doesn't promote Li/Na/Ba clutter; purely
428
419
  // 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
- });
420
+ const has_framework = has_framework_potential(unique_elements);
436
421
  // Weakly-bound center species (mean bond length well beyond the covalent-radii
437
422
  // sum, e.g. lone-pair Bi3+ with 8 long Bi-O bonds) are hidden when a
438
423
  // strongly-bound framework species exists - mirrors how pyrochlore-type figures
@@ -455,7 +440,7 @@ export function compute_polyhedra(structure, bonds, options = {}) {
455
440
  const visible = candidates.filter(({ element }) => {
456
441
  if (included.has(element))
457
442
  return true;
458
- if (is_spectator_center(element) && has_framework_potential)
443
+ if (is_spectator_center(element) && has_framework)
459
444
  return false;
460
445
  return !is_weak_species(element);
461
446
  });
@@ -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);
@@ -20,6 +20,7 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
20
20
  <script lang="ts">
21
21
  import type { Matrix3x3, Vec2, Vec3 } from '../math'
22
22
  import * as math from '../math'
23
+ import { quaternion_from_direction } from '../structure/geometry'
23
24
  import type { ShowSymmetryKinds, SymmetryElement } from './symmetry-elements'
24
25
  import {
25
26
  clip_line_to_cell,
@@ -39,7 +40,6 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
39
40
  LinearFilter,
40
41
  Matrix4,
41
42
  OctahedronGeometry,
42
- Quaternion,
43
43
  RepeatWrapping,
44
44
  RGBAFormat,
45
45
  Vector3,
@@ -92,7 +92,6 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
92
92
  inversion_color?: string
93
93
  } = $props()
94
94
 
95
- const UP = new Vector3(0, 1, 0)
96
95
  const UNIT_SCALE = new Vector3(1, 1, 1)
97
96
 
98
97
  // 1D stripe alpha texture for glide fills (three.js alphaMap samples the GREEN
@@ -136,14 +135,12 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
136
135
  dir_unit: Vector3,
137
136
  radius: number,
138
137
  length: number,
139
- ): CylinderGeometry =>
140
- new CylinderGeometry(radius, radius, length, 12).applyMatrix4(
141
- new Matrix4().compose(
142
- center,
143
- new Quaternion().setFromUnitVectors(UP, dir_unit),
144
- UNIT_SCALE,
145
- ),
138
+ ): CylinderGeometry => {
139
+ const orientation = quaternion_from_direction(dir_unit.toArray() as Vec3)
140
+ return new CylinderGeometry(radius, radius, length, 12).applyMatrix4(
141
+ new Matrix4().compose(center, orientation, UNIT_SCALE),
146
142
  )
143
+ }
147
144
 
148
145
  // Axes (cylinders) + rotoinversion center markers (spheres), merged per color/radius.
149
146
  // Pure rotations render solid; screw axes render DASHED so the two are
@@ -152,9 +149,9 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
152
149
  const axis_groups: MaterialGroup[] = $derived.by(() => {
153
150
  const axis_elements = elements.filter(
154
151
  (elem) =>
155
- (elem.kind === `rotation` || elem.kind === `screw` ||
156
- elem.kind === `rotoinversion`) &&
157
- show_kinds[elem.kind] && elem.axis,
152
+ (elem.kind === `rotation` || elem.kind === `screw` || elem.kind === `rotoinversion`) &&
153
+ show_kinds[elem.kind] &&
154
+ elem.axis,
158
155
  )
159
156
  // Drop 2-fold axes coincident with a higher-order axis (4 contains 2, 6 contains
160
157
  // 2 and 3, -4 contains 2, …) to reduce visual clutter. Computed over the VISIBLE
@@ -168,9 +165,8 @@ color/opacity instead of one mesh per element) and disposed on change/unmount. -
168
165
 
169
166
  const parts_by_group = new Map<string, BufferGeometry[]>()
170
167
  for (const elem of axis_elements) {
171
- if (
172
- hide_redundant_axes && elem.order < (max_order_by_line.get(line_key(elem)) ?? 0)
173
- ) continue
168
+ if (hide_redundant_axes && elem.order < (max_order_by_line.get(line_key(elem)) ?? 0))
169
+ continue
174
170
  const clipped = clip_line_to_cell(elem.point, elem.axis as Vec3, lattice)
175
171
  if (!clipped) continue
176
172
  const [start, end] = clipped