matterviz 0.3.7 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +76 -148
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
  7. package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
  8. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
  11. package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
  13. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  14. package/dist/brillouin/ReciprocalVectors.svelte +39 -0
  15. package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
  16. package/dist/brillouin/compute.d.ts +2 -0
  17. package/dist/brillouin/compute.js +89 -90
  18. package/dist/brillouin/geometry.d.ts +8 -0
  19. package/dist/brillouin/geometry.js +57 -0
  20. package/dist/brillouin/index.d.ts +2 -0
  21. package/dist/brillouin/index.js +2 -0
  22. package/dist/brillouin/types.d.ts +2 -2
  23. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  24. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
  25. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
  26. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
  27. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
  28. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
  29. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  30. package/dist/chempot-diagram/chempot-worker.js +2 -1
  31. package/dist/chempot-diagram/color.d.ts +3 -6
  32. package/dist/chempot-diagram/color.js +5 -5
  33. package/dist/chempot-diagram/compute.d.ts +4 -4
  34. package/dist/chempot-diagram/compute.js +20 -20
  35. package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
  36. package/dist/chempot-diagram/controls-state.svelte.js +42 -0
  37. package/dist/chempot-diagram/export.d.ts +47 -0
  38. package/dist/chempot-diagram/export.js +133 -0
  39. package/dist/chempot-diagram/index.d.ts +1 -0
  40. package/dist/chempot-diagram/index.js +1 -0
  41. package/dist/chempot-diagram/pointer.d.ts +0 -10
  42. package/dist/chempot-diagram/pointer.js +4 -4
  43. package/dist/chempot-diagram/types.d.ts +3 -3
  44. package/dist/colors/index.js +8 -7
  45. package/dist/composition/FormulaFilter.svelte +18 -11
  46. package/dist/composition/PieChart.svelte +11 -10
  47. package/dist/composition/chem-sys.d.ts +8 -0
  48. package/dist/composition/chem-sys.js +86 -0
  49. package/dist/composition/format.js +7 -4
  50. package/dist/composition/index.d.ts +1 -0
  51. package/dist/composition/index.js +1 -0
  52. package/dist/composition/parse.d.ts +0 -1
  53. package/dist/composition/parse.js +41 -31
  54. package/dist/controls.d.ts +1 -0
  55. package/dist/controls.js +0 -1
  56. package/dist/convex-hull/ConvexHull.svelte +8 -10
  57. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
  58. package/dist/convex-hull/ConvexHull2D.svelte +106 -185
  59. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  60. package/dist/convex-hull/ConvexHull3D.svelte +179 -683
  61. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  62. package/dist/convex-hull/ConvexHull4D.svelte +183 -687
  63. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  64. package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
  65. package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
  66. package/dist/convex-hull/ConvexHullControls.svelte +88 -7
  67. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
  68. package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
  69. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
  70. package/dist/convex-hull/ConvexHullStats.svelte +36 -175
  71. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
  72. package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
  73. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
  74. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  75. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  76. package/dist/convex-hull/barycentric-coords.d.ts +2 -4
  77. package/dist/convex-hull/barycentric-coords.js +6 -33
  78. package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
  79. package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
  80. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  81. package/dist/convex-hull/demo-temperature.js +20 -22
  82. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  83. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  84. package/dist/convex-hull/helpers.d.ts +42 -7
  85. package/dist/convex-hull/helpers.js +171 -78
  86. package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
  87. package/dist/convex-hull/hull-state.svelte.js +124 -0
  88. package/dist/convex-hull/index.d.ts +10 -8
  89. package/dist/convex-hull/index.js +7 -2
  90. package/dist/convex-hull/thermodynamics.js +136 -960
  91. package/dist/convex-hull/types.d.ts +13 -5
  92. package/dist/convex-hull/types.js +12 -0
  93. package/dist/coordination/CoordinationBarPlot.svelte +27 -34
  94. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  95. package/dist/element/BohrAtom.svelte +2 -1
  96. package/dist/element/index.d.ts +4 -0
  97. package/dist/element/index.js +18 -0
  98. package/dist/feedback/DragOverlay.svelte +3 -1
  99. package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
  100. package/dist/feedback/StatusMessage.svelte +13 -3
  101. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  102. package/dist/fermi-surface/FermiSurface.svelte +78 -151
  103. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
  104. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  105. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  106. package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
  107. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
  108. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  109. package/dist/fermi-surface/compute.js +67 -66
  110. package/dist/fermi-surface/export.js +6 -16
  111. package/dist/fermi-surface/index.d.ts +0 -1
  112. package/dist/fermi-surface/index.js +0 -1
  113. package/dist/fermi-surface/parse.d.ts +1 -1
  114. package/dist/fermi-surface/parse.js +71 -79
  115. package/dist/fermi-surface/types.d.ts +3 -2
  116. package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
  117. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
  118. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
  119. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
  120. package/dist/heatmap-matrix/index.d.ts +3 -2
  121. package/dist/heatmap-matrix/index.js +1 -1
  122. package/dist/index.d.ts +1 -0
  123. package/dist/index.js +1 -0
  124. package/dist/io/ExportPane.svelte +166 -0
  125. package/dist/io/ExportPane.svelte.d.ts +17 -0
  126. package/dist/io/decompress.js +5 -4
  127. package/dist/io/export.d.ts +9 -5
  128. package/dist/io/export.js +77 -51
  129. package/dist/io/fetch.d.ts +2 -1
  130. package/dist/io/fetch.js +5 -1
  131. package/dist/io/file-drop.d.ts +8 -1
  132. package/dist/io/file-drop.js +48 -36
  133. package/dist/io/index.d.ts +2 -0
  134. package/dist/io/index.js +10 -0
  135. package/dist/io/types.d.ts +13 -0
  136. package/dist/io/url-drop.js +64 -33
  137. package/dist/isosurface/parse.js +52 -51
  138. package/dist/isosurface/slice.js +5 -4
  139. package/dist/isosurface/types.js +1 -1
  140. package/dist/keyboard.d.ts +3 -0
  141. package/dist/keyboard.js +23 -0
  142. package/dist/labels.d.ts +1 -1
  143. package/dist/labels.js +9 -8
  144. package/dist/layout/FullscreenButton.svelte +33 -0
  145. package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
  146. package/dist/layout/FullscreenToggle.svelte +8 -14
  147. package/dist/layout/PropertyFilter.svelte +3 -2
  148. package/dist/layout/SettingsSection.svelte +1 -1
  149. package/dist/layout/ViewerChrome.svelte +116 -0
  150. package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
  151. package/dist/layout/fullscreen.d.ts +4 -0
  152. package/dist/layout/fullscreen.svelte.d.ts +8 -0
  153. package/dist/layout/fullscreen.svelte.js +37 -0
  154. package/dist/layout/index.d.ts +3 -0
  155. package/dist/layout/index.js +3 -0
  156. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  157. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  158. package/dist/layout/json-tree/utils.js +5 -4
  159. package/dist/marching-cubes.js +8 -13
  160. package/dist/math.d.ts +12 -4
  161. package/dist/math.js +42 -30
  162. package/dist/overlays/DraggablePane.svelte +4 -4
  163. package/dist/overlays/index.d.ts +4 -0
  164. package/dist/periodic-table/PeriodicTable.svelte +27 -15
  165. package/dist/periodic-table/PropertySelect.svelte +1 -0
  166. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  167. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  168. package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
  169. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
  170. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
  171. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
  172. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
  173. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
  174. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  175. package/dist/phase-diagram/build-diagram.js +2 -2
  176. package/dist/phase-diagram/colors.js +1 -1
  177. package/dist/phase-diagram/parse.d.ts +2 -1
  178. package/dist/phase-diagram/parse.js +6 -5
  179. package/dist/phase-diagram/types.d.ts +1 -1
  180. package/dist/phase-diagram/utils.d.ts +3 -3
  181. package/dist/phase-diagram/utils.js +8 -12
  182. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
  183. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
  184. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  185. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  186. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
  187. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  188. package/dist/plot/bar/data.d.ts +40 -0
  189. package/dist/plot/bar/data.js +154 -0
  190. package/dist/plot/bar/geometry.d.ts +39 -0
  191. package/dist/plot/bar/geometry.js +60 -0
  192. package/dist/plot/bar/index.d.ts +3 -0
  193. package/dist/plot/bar/index.js +3 -0
  194. package/dist/plot/box/BoxPlot.svelte +1292 -0
  195. package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
  196. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  197. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  198. package/dist/plot/box/Violin.svelte +14 -0
  199. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  200. package/dist/plot/box/box-plot.d.ts +56 -0
  201. package/dist/plot/box/box-plot.js +129 -0
  202. package/dist/plot/box/index.d.ts +5 -0
  203. package/dist/plot/box/index.js +5 -0
  204. package/dist/plot/box/kde.d.ts +17 -0
  205. package/dist/plot/box/kde.js +160 -0
  206. package/dist/plot/box/quantile.d.ts +3 -0
  207. package/dist/plot/box/quantile.js +53 -0
  208. package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
  209. package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
  210. package/dist/plot/core/axis-utils.d.ts +46 -0
  211. package/dist/plot/core/axis-utils.js +110 -0
  212. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  213. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  214. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
  215. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
  216. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  217. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  218. package/dist/plot/core/components/ControlPane.svelte +46 -0
  219. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  220. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  221. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  222. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  223. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  224. package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
  225. package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
  226. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
  227. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
  228. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  229. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  230. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  231. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  232. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  233. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  234. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  235. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  236. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  237. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
  238. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
  239. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
  240. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
  241. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  242. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  243. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  244. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  245. package/dist/plot/core/components/index.d.ts +17 -0
  246. package/dist/plot/core/components/index.js +17 -0
  247. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  248. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
  249. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  250. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  251. package/dist/plot/core/fill-utils.d.ts +34 -0
  252. package/dist/plot/core/fill-utils.js +391 -0
  253. package/dist/plot/core/index.d.ts +10 -0
  254. package/dist/plot/core/index.js +11 -0
  255. package/dist/plot/core/interactions.d.ts +39 -0
  256. package/dist/plot/core/interactions.js +209 -0
  257. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  258. package/dist/plot/{layout.js → core/layout.js} +16 -8
  259. package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
  260. package/dist/plot/core/pan-zoom.svelte.js +221 -0
  261. package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
  262. package/dist/plot/core/placed-tween.svelte.js +68 -0
  263. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
  264. package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
  265. package/dist/plot/core/scales.d.ts +40 -0
  266. package/dist/plot/{scales.js → core/scales.js} +94 -93
  267. package/dist/plot/core/svg.d.ts +3 -0
  268. package/dist/plot/core/svg.js +41 -0
  269. package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
  270. package/dist/plot/{types.js → core/types.js} +1 -1
  271. package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
  272. package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
  273. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  274. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  275. package/dist/plot/core/utils.d.ts +12 -0
  276. package/dist/plot/core/utils.js +27 -0
  277. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
  278. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  279. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  280. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  281. package/dist/plot/histogram/index.d.ts +2 -0
  282. package/dist/plot/histogram/index.js +2 -0
  283. package/dist/plot/index.d.ts +8 -41
  284. package/dist/plot/index.js +10 -39
  285. package/dist/plot/sankey/Sankey.svelte +697 -0
  286. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  287. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  288. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  289. package/dist/plot/sankey/index.d.ts +4 -0
  290. package/dist/plot/sankey/index.js +3 -0
  291. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  292. package/dist/plot/sankey/sankey-types.js +4 -0
  293. package/dist/plot/sankey/sankey.d.ts +52 -0
  294. package/dist/plot/sankey/sankey.js +189 -0
  295. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
  296. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
  297. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  298. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  299. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
  300. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
  301. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  302. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
  303. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  304. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  305. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  306. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  307. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
  308. package/dist/plot/scatter/index.d.ts +7 -0
  309. package/dist/plot/scatter/index.js +5 -0
  310. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  311. package/dist/plot/scatter/scatter-data.js +212 -0
  312. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
  313. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
  314. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
  315. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
  316. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
  317. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
  318. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
  319. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
  320. package/dist/plot/scatter-3d/index.d.ts +4 -0
  321. package/dist/plot/scatter-3d/index.js +4 -0
  322. package/dist/plot/sunburst/Sunburst.svelte +1041 -0
  323. package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
  324. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  325. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  326. package/dist/plot/sunburst/index.d.ts +4 -0
  327. package/dist/plot/sunburst/index.js +4 -0
  328. package/dist/plot/sunburst/render.d.ts +34 -0
  329. package/dist/plot/sunburst/render.js +122 -0
  330. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  331. package/dist/plot/sunburst/sunburst.js +269 -0
  332. package/dist/rdf/RdfPlot.svelte +2 -1
  333. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  334. package/dist/rdf/calc-rdf.js +11 -24
  335. package/dist/sanitize.js +14 -3
  336. package/dist/scene/SceneCamera.svelte +62 -0
  337. package/dist/scene/SceneCamera.svelte.d.ts +19 -0
  338. package/dist/scene/bind-renderer.svelte.d.ts +2 -0
  339. package/dist/scene/bind-renderer.svelte.js +14 -0
  340. package/dist/scene/index.d.ts +4 -0
  341. package/dist/scene/index.js +5 -0
  342. package/dist/scene/props.js +52 -0
  343. package/dist/scene/types.d.ts +26 -0
  344. package/dist/scene/types.js +1 -0
  345. package/dist/settings.d.ts +79 -3
  346. package/dist/settings.js +321 -1
  347. package/dist/spectral/Bands.svelte +47 -36
  348. package/dist/spectral/Bands.svelte.d.ts +6 -6
  349. package/dist/spectral/BandsAndDos.svelte +23 -25
  350. package/dist/spectral/BrillouinBandsDos.svelte +42 -30
  351. package/dist/spectral/Dos.svelte +15 -23
  352. package/dist/spectral/Dos.svelte.d.ts +4 -3
  353. package/dist/spectral/helpers.d.ts +8 -6
  354. package/dist/spectral/helpers.js +137 -65
  355. package/dist/state.svelte.d.ts +0 -7
  356. package/dist/state.svelte.js +0 -6
  357. package/dist/structure/Arrow.svelte +2 -4
  358. package/dist/structure/AtomLegend.svelte +8 -9
  359. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  360. package/dist/structure/CanvasTooltip.svelte +1 -0
  361. package/dist/structure/CellSelect.svelte +12 -5
  362. package/dist/structure/CellSelect.svelte.d.ts +2 -1
  363. package/dist/structure/Cylinder.svelte +12 -8
  364. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  365. package/dist/structure/Lattice.svelte +2 -2
  366. package/dist/structure/Structure.svelte +365 -423
  367. package/dist/structure/Structure.svelte.d.ts +5 -15
  368. package/dist/structure/StructureControls.svelte +217 -2
  369. package/dist/structure/StructureControls.svelte.d.ts +5 -3
  370. package/dist/structure/StructureExportPane.svelte +54 -156
  371. package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
  372. package/dist/structure/StructureInfoPane.svelte +10 -9
  373. package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
  374. package/dist/structure/StructureScene.svelte +376 -208
  375. package/dist/structure/StructureScene.svelte.d.ts +22 -20
  376. package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
  377. package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
  378. package/dist/structure/atom-properties.d.ts +1 -1
  379. package/dist/structure/atom-properties.js +17 -22
  380. package/dist/structure/bond-order-perception.js +3 -5
  381. package/dist/structure/bonding.d.ts +4 -0
  382. package/dist/structure/bonding.js +134 -63
  383. package/dist/structure/export.d.ts +24 -4
  384. package/dist/structure/export.js +89 -143
  385. package/dist/structure/index.d.ts +4 -4
  386. package/dist/structure/index.js +3 -3
  387. package/dist/structure/measure.d.ts +3 -2
  388. package/dist/structure/measure.js +6 -5
  389. package/dist/structure/parse.d.ts +3 -2
  390. package/dist/structure/parse.js +419 -438
  391. package/dist/structure/partial-occupancy.d.ts +0 -1
  392. package/dist/structure/partial-occupancy.js +1 -1
  393. package/dist/structure/pbc.d.ts +1 -1
  394. package/dist/structure/pbc.js +190 -13
  395. package/dist/structure/polyhedra.d.ts +41 -0
  396. package/dist/structure/polyhedra.js +602 -0
  397. package/dist/structure/site.d.ts +4 -0
  398. package/dist/structure/site.js +1 -0
  399. package/dist/structure/supercell.js +3 -2
  400. package/dist/structure/validation.js +5 -6
  401. package/dist/symmetry/SymmetryElementControls.svelte +69 -0
  402. package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
  403. package/dist/symmetry/SymmetryElements.svelte +354 -0
  404. package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
  405. package/dist/symmetry/SymmetryStats.svelte +113 -8
  406. package/dist/symmetry/WyckoffTable.svelte +68 -7
  407. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
  408. package/dist/symmetry/cell-transform.js +7 -14
  409. package/dist/symmetry/index.d.ts +14 -4
  410. package/dist/symmetry/index.js +291 -72
  411. package/dist/symmetry/spacegroups.d.ts +12 -1
  412. package/dist/symmetry/spacegroups.js +63 -14
  413. package/dist/symmetry/symmetry-elements.d.ts +33 -0
  414. package/dist/symmetry/symmetry-elements.js +521 -0
  415. package/dist/symmetry/wyckoff-db.d.ts +9 -0
  416. package/dist/symmetry/wyckoff-db.js +87 -0
  417. package/dist/table/HeatmapTable.svelte +66 -25
  418. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  419. package/dist/table/index.d.ts +1 -3
  420. package/dist/table/index.js +1 -1
  421. package/dist/theme/index.js +8 -8
  422. package/dist/tooltip/KCoords.svelte +45 -0
  423. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  424. package/dist/tooltip/index.d.ts +1 -0
  425. package/dist/tooltip/index.js +1 -0
  426. package/dist/trajectory/Trajectory.svelte +123 -100
  427. package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
  428. package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
  429. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
  430. package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
  431. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
  432. package/dist/trajectory/constants.js +6 -2
  433. package/dist/trajectory/extract.js +17 -37
  434. package/dist/trajectory/format-detect.d.ts +1 -1
  435. package/dist/trajectory/format-detect.js +27 -19
  436. package/dist/trajectory/frame-reader.d.ts +0 -1
  437. package/dist/trajectory/frame-reader.js +63 -162
  438. package/dist/trajectory/helpers.d.ts +10 -2
  439. package/dist/trajectory/helpers.js +56 -36
  440. package/dist/trajectory/index.js +1 -1
  441. package/dist/trajectory/parse/ase.d.ts +9 -1
  442. package/dist/trajectory/parse/ase.js +47 -32
  443. package/dist/trajectory/parse/diagnostics.d.ts +3 -0
  444. package/dist/trajectory/parse/diagnostics.js +14 -0
  445. package/dist/trajectory/parse/hdf5.js +1 -1
  446. package/dist/trajectory/parse/index.d.ts +1 -1
  447. package/dist/trajectory/parse/index.js +65 -105
  448. package/dist/trajectory/parse/lammps.d.ts +0 -2
  449. package/dist/trajectory/parse/lammps.js +8 -6
  450. package/dist/trajectory/parse/pymatgen.d.ts +2 -0
  451. package/dist/trajectory/parse/pymatgen.js +74 -0
  452. package/dist/trajectory/parse/vasp.js +38 -18
  453. package/dist/trajectory/parse/xyz.d.ts +13 -1
  454. package/dist/trajectory/parse/xyz.js +102 -94
  455. package/dist/trajectory/plotting.d.ts +1 -2
  456. package/dist/trajectory/plotting.js +16 -113
  457. package/dist/utils.d.ts +2 -0
  458. package/dist/utils.js +7 -5
  459. package/dist/xrd/XrdPlot.svelte +16 -30
  460. package/dist/xrd/broadening.d.ts +2 -1
  461. package/dist/xrd/calc-xrd.js +18 -20
  462. package/dist/xrd/index.d.ts +2 -2
  463. package/dist/xrd/parse.js +2 -2
  464. package/package.json +43 -26
  465. package/dist/element/data.json +0 -11864
  466. package/dist/fermi-surface/marching-cubes.d.ts +0 -2
  467. package/dist/fermi-surface/marching-cubes.js +0 -2
  468. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  469. package/dist/plot/axis-utils.d.ts +0 -19
  470. package/dist/plot/axis-utils.js +0 -78
  471. package/dist/plot/defaults.d.ts +0 -19
  472. package/dist/plot/defaults.js +0 -9
  473. package/dist/plot/fill-utils.d.ts +0 -46
  474. package/dist/plot/fill-utils.js +0 -322
  475. package/dist/plot/hover-lock.svelte.d.ts +0 -14
  476. package/dist/plot/hover-lock.svelte.js +0 -46
  477. package/dist/plot/interactions.d.ts +0 -12
  478. package/dist/plot/interactions.js +0 -101
  479. package/dist/plot/scales.d.ts +0 -48
  480. package/dist/plot/svg.d.ts +0 -1
  481. package/dist/plot/svg.js +0 -11
  482. package/dist/plot/utils/series-visibility.d.ts +0 -15
  483. package/dist/plot/utils.d.ts +0 -1
  484. package/dist/plot/utils.js +0 -14
  485. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  486. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -1,10 +1,17 @@
1
1
  import { ATOMIC_NUMBER_TO_SYMBOL, SYMBOL_TO_ATOMIC_NUMBER } from '../composition/parse';
2
+ import * as math from '../math';
2
3
  import { DEFAULTS } from '../settings';
3
4
  import { merge_split_partial_sites } from '../structure/partial-occupancy';
4
5
  import init, { analyze_cell } from '@spglib/moyo-wasm';
5
6
  import moyo_wasm_url from '@spglib/moyo-wasm/moyo_wasm_bg.wasm?url';
7
+ import { mat3_from_flat_col_major } from './symmetry-elements';
8
+ import { wyckoff_letter } from './wyckoff-db';
6
9
  export * from './cell-transform';
7
10
  export * from './spacegroups';
11
+ export * from './symmetry-elements';
12
+ export * from './wyckoff-db';
13
+ export { default as SymmetryElementControls } from './SymmetryElementControls.svelte';
14
+ export { default as SymmetryElements } from './SymmetryElements.svelte';
8
15
  export { default as SymmetryStats } from './SymmetryStats.svelte';
9
16
  export { default as WyckoffTable } from './WyckoffTable.svelte';
10
17
  // Keys are standard crystallographic symbols (P, I, F, A, B, C, R)
@@ -27,13 +34,37 @@ const to_unit = (value) => value - Math.floor(value);
27
34
  const near_zero = (value) => Math.min(value, 1 - value);
28
35
  const near_half = (value) => Math.abs(value - 0.5);
29
36
  const symmetry_position_key = (pos) => pos.map((coord) => to_unit(coord).toFixed(8)).join(`,`);
30
- const periodic_distance = (pos1, pos2) => Math.sqrt(pos1.reduce((sum, coord, idx) => {
31
- // Wrap delta into [-0.5, 0.5) using safe modulo
32
- const delta = coord - pos2[idx];
33
- const wrapped = ((((delta + 0.5) % 1) + 1) % 1) - 0.5;
34
- const distance = Math.abs(wrapped);
35
- return sum + distance * distance;
36
- }, 0));
37
+ const is_near_integer_vec = (vec, tol) => vec.every((coord) => Math.abs(coord - Math.round(coord)) < tol);
38
+ // Wrap fractional coordinates into [0, 1), snapping values within 1e-9 of 1 back to 0.
39
+ // NOTE on epsilon: 1e-9 is deliberately looser than wrap_frac_coord @1e-10
40
+ // [[src/lib/structure/pbc.ts:26]] because inputs here passed through moyo
41
+ // standardization plus a P⁻¹(x − p) matrix transform (make_frac_coord_mapper),
42
+ // accumulating more float error than freshly parsed coords. It is tighter than
43
+ // wrap_point @1e-8 [[src/lib/symmetry/symmetry-elements.ts:214]], which must
44
+ // keep dedup keys stable for fixed points solved from linear systems. Do not
45
+ // unify: each epsilon matches the noise level of its inputs.
46
+ const wrap_frac = (pos) => pos.map((coord) => {
47
+ const wrapped = coord - Math.floor(coord);
48
+ return wrapped > 1 - 1e-9 ? 0 : wrapped;
49
+ });
50
+ // Build a mapper from input-cell to standardized-cell fractional coordinates.
51
+ // moyo's (std_linear P, std_origin_shift p) follow the ITA convention for the
52
+ // transformation from the input cell to the standardized cell: x_std = P⁻¹ (x_input − p).
53
+ // Returns null if std_linear is absent or singular.
54
+ function make_frac_coord_mapper(linear_flat, origin_shift) {
55
+ if (linear_flat?.length !== 9)
56
+ return null;
57
+ try {
58
+ const linear = mat3_from_flat_col_major(linear_flat);
59
+ const linear_inv = math.matrix_inverse_3x3(linear);
60
+ const shift = (origin_shift ?? [0, 0, 0]);
61
+ const to_std = (pos) => math.mat3x3_vec3_multiply(linear_inv, math.subtract(pos, shift));
62
+ return { to_std, linear, linear_inv, shift };
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
37
68
  export async function ensure_moyo_wasm_ready(wasm_url) {
38
69
  if (initialized)
39
70
  return;
@@ -93,15 +124,32 @@ export function to_cell_json(structure) {
93
124
  const fractional_sq_dist = (pos_1, pos_2) => (pos_1[0] - pos_2[0] - Math.round(pos_1[0] - pos_2[0])) ** 2 +
94
125
  (pos_1[1] - pos_2[1] - Math.round(pos_1[1] - pos_2[1])) ** 2 +
95
126
  (pos_1[2] - pos_2[2] - Math.round(pos_1[2] - pos_2[2])) ** 2;
96
- export function map_std_to_orig_site_indices(std_positions, std_numbers, input_positions, input_numbers, orig_site_indices_by_input_idx) {
127
+ // Map each standardized-cell site to the input-cell site it descends from, then to
128
+ // original structure indices. When moyo's (std_linear, std_origin_shift) transform is
129
+ // provided, std positions are first mapped into the input frame via x_in = P·x_std + p
130
+ // (the std and input cells use DIFFERENT bases in general, so comparing raw fractional
131
+ // coordinates across them is meaningless). Matches account for crystal translations of
132
+ // both lattices: a difference d is a translation if d ∈ ℤ³ (input lattice) or P⁻¹d ∈ ℤ³
133
+ // (standardized lattice expressed in the input frame).
134
+ export const map_std_to_orig_site_indices = (std_positions, std_numbers, input_positions, input_numbers, orig_site_indices_by_input_idx, transform, tol = 1e-4) => {
135
+ const mapper = make_frac_coord_mapper(transform?.std_linear, transform?.std_origin_shift);
97
136
  return std_positions.map((std_pos, std_idx) => {
137
+ // Predicted input-frame position of this std site: x_in = P·x_std + p
138
+ const pred = mapper
139
+ ? math.add(math.mat3x3_vec3_multiply(mapper.linear, std_pos), mapper.shift)
140
+ : std_pos;
98
141
  const std_number = std_numbers[std_idx];
99
142
  let nearest_input_idx = -1;
100
143
  let nearest_sq_dist = Infinity;
101
144
  for (let input_idx = 0; input_idx < input_positions.length; input_idx += 1) {
102
145
  if (input_numbers[input_idx] !== std_number)
103
146
  continue;
104
- const sq_dist = fractional_sq_dist(std_pos, input_positions[input_idx]);
147
+ const delta = math.subtract(pred, input_positions[input_idx]);
148
+ // Exact match modulo a translation of the standardized lattice
149
+ const is_std_translation = mapper && is_near_integer_vec(math.mat3x3_vec3_multiply(mapper.linear_inv, delta), tol);
150
+ const sq_dist = is_std_translation
151
+ ? 0
152
+ : fractional_sq_dist(pred, input_positions[input_idx]);
105
153
  if (sq_dist < nearest_sq_dist) {
106
154
  nearest_sq_dist = sq_dist;
107
155
  nearest_input_idx = input_idx;
@@ -111,7 +159,7 @@ export function map_std_to_orig_site_indices(std_positions, std_numbers, input_p
111
159
  return [];
112
160
  return orig_site_indices_by_input_idx[nearest_input_idx] ?? [];
113
161
  });
114
- }
162
+ };
115
163
  export async function analyze_structure_symmetry(struct_or_mol, settings) {
116
164
  await ensure_moyo_wasm_ready();
117
165
  if (!(`lattice` in struct_or_mol)) {
@@ -123,8 +171,16 @@ export async function analyze_structure_symmetry(struct_or_mol, settings) {
123
171
  // Map "Moyo" to "Standard" for moyo-wasm
124
172
  const moyo_algo = algo === `Moyo` ? `Standard` : algo;
125
173
  const sym_data = analyze_cell(cell_json, symprec, moyo_algo);
126
- const orig_site_indices_by_std_idx = map_std_to_orig_site_indices(sym_data.std_cell.positions, sym_data.std_cell.numbers, moyo_input_cell.positions, moyo_input_cell.numbers, moyo_input_cell.orig_site_indices_by_input_idx);
127
- return { ...sym_data, orig_site_indices_by_std_idx };
174
+ const orig_site_indices_by_std_idx = map_std_to_orig_site_indices(sym_data.std_cell.positions, sym_data.std_cell.numbers, moyo_input_cell.positions, moyo_input_cell.numbers, moyo_input_cell.orig_site_indices_by_input_idx, { std_linear: sym_data.std_linear, std_origin_shift: sym_data.std_origin_shift }, Math.max(1e-5, symprec * 10));
175
+ return {
176
+ ...sym_data,
177
+ orig_site_indices_by_std_idx,
178
+ input_cell: {
179
+ positions: moyo_input_cell.positions,
180
+ numbers: moyo_input_cell.numbers,
181
+ },
182
+ orig_site_indices_by_input_idx: moyo_input_cell.orig_site_indices_by_input_idx,
183
+ };
128
184
  }
129
185
  // Helper function to score coordinate simplicity for Wyckoff table
130
186
  export function simplicity_score(vec) {
@@ -134,66 +190,74 @@ export function simplicity_score(vec) {
134
190
  near_zero(az) +
135
191
  0.5 * (near_half(ax) + near_half(ay) + near_half(az)));
136
192
  }
137
- // Generate Wyckoff table rows from symmetry data
138
- export function wyckoff_positions_from_moyo(sym_data) {
139
- if (!sym_data)
140
- return [];
141
- const { positions, numbers } = sym_data.std_cell;
142
- const { wyckoffs, orig_indices, orig_site_indices_by_std_idx } = sym_data;
143
- // Group sites by letter-element combination and track all indices
144
- const groups = new Map();
145
- // Process all atoms in the standardized cell
146
- // Note: wyckoffs array may be shorter than std_cell when moyo combines symmetry-equivalent sites
147
- for (let idx = 0; idx < numbers.length; idx++) {
148
- // Use wyckoff letter if available, otherwise mark as non-symmetric
149
- const full = idx < wyckoffs.length ? wyckoffs[idx] : null;
150
- const letter = full?.match(/[a-z]+$/)?.[0] ?? full ?? ``;
151
- const atomic_num = numbers[idx];
152
- const elem = ATOMIC_NUMBER_TO_SYMBOL[atomic_num] ?? `?`;
153
- const position = positions[idx];
154
- const key = letter ? `${letter}|${elem}` : `nosym|${elem}|${idx}`;
155
- const group = groups.get(key) ?? { letter, elem, indices: [], positions: [] };
156
- group.indices.push(idx);
157
- group.positions.push(position);
158
- groups.set(key, group);
159
- }
160
- const rows = Array.from(groups.values()).map(({ letter, elem, indices, positions: group_positions }) => {
161
- // Find the position with the best simplicity score to display
162
- const best_pos = group_positions.reduce((best, pos) => {
163
- const score = simplicity_score(pos);
164
- return score < best.score ? { pos, score } : best;
165
- }, { pos: group_positions[0], score: simplicity_score(group_positions[0]) }).pos;
166
- // Map standardized cell indices back to original structure indices
167
- const orig_site_indices = orig_site_indices_by_std_idx
168
- ? indices.flatMap((std_idx) => orig_site_indices_by_std_idx[std_idx] ?? [])
169
- : orig_indices
170
- ? indices.map((std_idx) => orig_indices[std_idx]).filter((idx) => idx !== undefined)
171
- : indices;
172
- const wyckoff = letter ? `${indices.length}${letter}` : `1`;
193
+ // Pick the representative coordinate with the lowest simplicity score (ties keep first)
194
+ const simplest_position = (positions) => positions.reduce((best, pos) => simplicity_score(pos) < simplicity_score(best) ? pos : best);
195
+ // Build Wyckoff rows from moyo's input-cell orbits. moyo's per-site arrays (wyckoffs,
196
+ // orbits, site_symmetry_symbols) are indexed by INPUT cell sites — NOT std_cell sites —
197
+ // so rows must be derived by grouping input sites into crystallographic orbits.
198
+ // Multiplicity in the conventional cell is the orbit size scaled by the std/input cell
199
+ // size ratio (e.g. a 1-atom primitive FCC input has orbit size 1 but multiplicity 4).
200
+ function wyckoff_rows_from_input_orbits(sym_data) {
201
+ const { input_cell, orbits, wyckoffs, site_symmetry_symbols, std_cell, orig_site_indices_by_input_idx, } = sym_data;
202
+ const n_input = input_cell?.positions.length ?? 0;
203
+ if (!input_cell || n_input === 0)
204
+ return null;
205
+ if (orbits?.length !== n_input || wyckoffs?.length !== n_input)
206
+ return null;
207
+ const mapper = make_frac_coord_mapper(sym_data.std_linear, sym_data.std_origin_shift);
208
+ if (!mapper)
209
+ return null;
210
+ // Group input-cell sites by crystallographic orbit (keyed by orbit representative).
211
+ // Distinct orbits sharing the same Wyckoff letter and element stay separate rows.
212
+ const orbit_members = new Map();
213
+ orbits.forEach((rep, idx) => {
214
+ const members = orbit_members.get(rep) ?? [];
215
+ members.push(idx);
216
+ orbit_members.set(rep, members);
217
+ });
218
+ const n_std = std_cell?.positions.length ?? n_input;
219
+ return [...orbit_members.entries()].map(([rep, members]) => {
220
+ const letter = wyckoff_letter(wyckoffs[rep] ?? ``);
221
+ const elem = ATOMIC_NUMBER_TO_SYMBOL[input_cell.numbers[rep]] ?? `?`;
222
+ const multiplicity = Math.round((members.length * n_std) / n_input);
223
+ // Representative coordinate in the standardized frame, simplest first
224
+ const best_pos = simplest_position(members.map((idx) => wrap_frac(mapper.to_std(input_cell.positions[idx]))));
225
+ const orig_site_indices = members.flatMap((idx) => orig_site_indices_by_input_idx?.[idx] ?? [idx]);
226
+ const site_symmetry = site_symmetry_symbols?.[rep];
173
227
  return {
174
- wyckoff,
228
+ wyckoff: letter ? `${multiplicity}${letter}` : `${multiplicity}`,
175
229
  elem,
176
230
  abc: best_pos,
177
231
  site_indices: [...new Set(orig_site_indices)].sort((idx_a, idx_b) => idx_a - idx_b),
232
+ ...(site_symmetry ? { site_symmetry } : {}),
178
233
  };
179
234
  });
180
- rows.sort((w1, w2) => {
181
- const [w1_mult, w2_mult] = [parseInt(w1.wyckoff), parseInt(w2.wyckoff)];
235
+ }
236
+ // Generate Wyckoff table rows from symmetry data by grouping moyo's input-cell sites into
237
+ // crystallographic orbits. moyo's per-site arrays (wyckoffs, orbits, site_symmetry_symbols)
238
+ // always index the input cell and analyze_structure_symmetry always attaches input_cell, so
239
+ // the orbit grouping is the single source of truth for any input cell setting.
240
+ // Rows sort by ascending multiplicity, then Wyckoff label.
241
+ export function wyckoff_positions_from_moyo(sym_data) {
242
+ if (!sym_data)
243
+ return [];
244
+ const orbit_rows = wyckoff_rows_from_input_orbits(sym_data);
245
+ return (orbit_rows ?? []).sort((w1, w2) => {
246
+ const [w1_mult, w2_mult] = [parseInt(w1.wyckoff, 10), parseInt(w2.wyckoff, 10)];
182
247
  if (w1_mult !== w2_mult)
183
248
  return w1_mult - w2_mult;
184
249
  return w1.wyckoff.localeCompare(w2.wyckoff);
185
250
  });
186
- return rows;
187
251
  }
188
252
  // Apply symmetry operations to find all equivalent positions for a given fractional coordinate
189
- export function apply_symmetry_operations(position, operations, _tolerance = 1e-6) {
253
+ export function apply_symmetry_operations(position, operations) {
190
254
  const seen = new Set();
191
255
  return operations
192
256
  .map(({ rotation, translation }) => {
193
- // Apply 3x3 rotation matrix and translation: new_pos = R * position + t
194
- const new_pos = [0, 1, 2].map((dim) => rotation[dim * 3] * position[0] +
195
- rotation[dim * 3 + 1] * position[1] +
196
- rotation[dim * 3 + 2] * position[2] +
257
+ // new_pos = W·position + t; moyo serializes W COLUMN-major: W[dim][j] = rotation[dim + 3j]
258
+ const new_pos = [0, 1, 2].map((dim) => rotation[dim] * position[0] +
259
+ rotation[dim + 3] * position[1] +
260
+ rotation[dim + 6] * position[2] +
197
261
  translation[dim]);
198
262
  return new_pos.map(to_unit);
199
263
  })
@@ -205,24 +269,179 @@ export function apply_symmetry_operations(position, operations, _tolerance = 1e-
205
269
  return true;
206
270
  });
207
271
  }
208
- // Map Wyckoff positions to all equivalent atoms in the displayed structure (including image atoms)
272
+ // Build candidate frames for the displayed structure: original, conventional (moyo
273
+ // std_cell), and primitive (moyo prim_std_cell). The displayed structure's fractional
274
+ // coordinates only match symmetry-equivalent positions when expressed in the same frame.
275
+ function candidate_display_frames(orig_structure, sym_data) {
276
+ const frames = [
277
+ {
278
+ lattice: orig_structure.lattice.matrix,
279
+ map_equiv: (pos) => pos,
280
+ input_translation_check: null,
281
+ },
282
+ ];
283
+ const cells = [
284
+ { cell: sym_data.std_cell, linear: sym_data.std_linear, shift: sym_data.std_origin_shift },
285
+ {
286
+ cell: sym_data.prim_std_cell,
287
+ linear: sym_data.prim_std_linear,
288
+ shift: sym_data.prim_std_origin_shift,
289
+ },
290
+ ];
291
+ for (const { cell, linear, shift } of cells) {
292
+ const basis = cell?.lattice?.basis;
293
+ const mapper = make_frac_coord_mapper(linear, shift);
294
+ if (basis?.length !== 9 || !mapper)
295
+ continue;
296
+ // basis is row-major (each row a lattice vector); same reshape as moyo_cell_to_structure
297
+ frames.push({
298
+ lattice: math.vec9_to_mat3x3([...basis]),
299
+ map_equiv: mapper.to_std,
300
+ input_translation_check: mapper.linear,
301
+ });
302
+ }
303
+ return frames;
304
+ }
305
+ // Spatial hash over wrapped fractional coordinates for tolerance-based, mod-1 position
306
+ // lookups. Cell size is chosen ≥ tolerance so probing the ±1 neighbor cells (with
307
+ // wraparound) covers every point within tolerance of the query.
308
+ class WrappedPositionIndex {
309
+ tolerance;
310
+ buckets = new Map();
311
+ coords;
312
+ n_cells;
313
+ constructor(positions, tolerance) {
314
+ this.tolerance = tolerance;
315
+ this.n_cells = Math.min(64, Math.max(1, Math.floor(1 / Math.max(tolerance, 1e-9))));
316
+ this.coords = positions;
317
+ positions.forEach((pos, idx) => {
318
+ const key = this.cell_key(pos, 0, 0, 0);
319
+ const bucket = this.buckets.get(key);
320
+ if (bucket)
321
+ bucket.push(idx);
322
+ else
323
+ this.buckets.set(key, [idx]);
324
+ });
325
+ }
326
+ cell_key(pos, dx, dy, dz) {
327
+ const n_cells = this.n_cells;
328
+ const cell = (coord, offset) => {
329
+ const wrapped = coord - Math.floor(coord);
330
+ return (((Math.floor(wrapped * n_cells) + offset) % n_cells) + n_cells) % n_cells;
331
+ };
332
+ return `${cell(pos[0], dx)},${cell(pos[1], dy)},${cell(pos[2], dz)}`;
333
+ }
334
+ // Indices of stored positions within `tolerance` of `query` modulo ℤ³
335
+ query(query, out) {
336
+ const tol = this.tolerance;
337
+ for (let dx = -1; dx <= 1; dx++) {
338
+ for (let dy = -1; dy <= 1; dy++) {
339
+ for (let dz = -1; dz <= 1; dz++) {
340
+ const bucket = this.buckets.get(this.cell_key(query, dx, dy, dz));
341
+ if (!bucket)
342
+ continue;
343
+ for (const idx of bucket) {
344
+ const pos = this.coords[idx];
345
+ const d0 = pos[0] - query[0];
346
+ const d1 = pos[1] - query[1];
347
+ const d2 = pos[2] - query[2];
348
+ if (Math.abs(d0 - Math.round(d0)) < tol &&
349
+ Math.abs(d1 - Math.round(d1)) < tol &&
350
+ Math.abs(d2 - Math.round(d2)) < tol)
351
+ out.add(idx);
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+ // Map Wyckoff positions to all equivalent atoms in the displayed structure (including
359
+ // image atoms). Handles displayed structures in the original frame as well as
360
+ // conventional/primitive cell transforms and integer supercells of any of those: the
361
+ // displayed lattice L_disp is matched against each candidate frame's lattice L_F via
362
+ // S = L_disp·L_F⁻¹ (S must be near-integer), displayed coords are converted into the
363
+ // frame via x_F = x_disp·S, and matches allow crystal translations of both the frame
364
+ // lattice (d ∈ ℤ³) and the input lattice (P·d ∈ ℤ³). Matching uses spatial hashing:
365
+ // O(N_disp + N_orig·N_ops) instead of O(N_orig·N_disp·N_ops).
209
366
  export function map_wyckoff_to_all_atoms(wyckoff_positions, displayed_structure, orig_structure, sym_data, tolerance = 1e-5) {
210
367
  if (!sym_data?.operations || !displayed_structure.sites || !orig_structure.sites) {
211
368
  return wyckoff_positions;
212
369
  }
213
- return wyckoff_positions.map((wyckoff_pos) => {
214
- const indices = (wyckoff_pos.site_indices || [])
215
- .filter((idx) => idx < orig_structure.sites.length)
216
- .flatMap((orig_idx) => {
217
- const { abc: orig_abc, species } = orig_structure.sites[orig_idx];
218
- const element = species[0]?.element;
219
- const equivalent_positions = apply_symmetry_operations(orig_abc, sym_data.operations, tolerance);
220
- return displayed_structure.sites
221
- .map((site, display_idx) => ({ site, display_idx }))
222
- .filter(({ site }) => site.species[0]?.element === element)
223
- .filter(({ site }) => equivalent_positions.some((equiv_pos) => periodic_distance(equiv_pos, site.abc) < tolerance))
224
- .map(({ display_idx }) => display_idx);
370
+ const map_in_frame = (frame) => {
371
+ // Supercell factor S = L_disp·L_F⁻¹ must be a near-integer matrix with |det| ≥ 1
372
+ let scaling;
373
+ try {
374
+ scaling = math.dot(displayed_structure.lattice.matrix, math.matrix_inverse_3x3(frame.lattice));
375
+ }
376
+ catch {
377
+ return null;
378
+ }
379
+ const is_integer_scaling = scaling.every((row) => row.every((val) => Math.abs(val - Math.round(val)) < tolerance));
380
+ if (!is_integer_scaling || Math.abs(math.det_3x3(scaling)) < 0.99)
381
+ return null;
382
+ // Displayed site coords expressed in frame-F fractional coordinates: x_F = x_disp·S
383
+ const scaling_transpose = math.transpose_3x3_matrix(scaling);
384
+ const displayed_frame_coords = displayed_structure.sites.map((site) => math.mat3x3_vec3_multiply(scaling_transpose, site.abc));
385
+ const displayed_elements = displayed_structure.sites.map((site) => site.species[0]?.element);
386
+ // Spatial hashes: one over the frame coords directly (matches d ∈ ℤ³), and one over
387
+ // P·x_F (matches input-lattice translations: d ∈ P⁻¹ℤ³ ⟺ P·d ∈ ℤ³)
388
+ const direct_index = new WrappedPositionIndex(displayed_frame_coords, tolerance);
389
+ const check = frame.input_translation_check;
390
+ const check_index = check
391
+ ? new WrappedPositionIndex(displayed_frame_coords.map((pos) => math.mat3x3_vec3_multiply(check, pos)), tolerance)
392
+ : null;
393
+ let any_matched = false;
394
+ const rows = wyckoff_positions.map((wyckoff_pos) => {
395
+ // Union the symmetry orbits of all original sites in this row, grouped by element.
396
+ // Sites whose (wrapped) position already appears in the accumulated orbit are
397
+ // skipped — orbit members generate identical orbits, so rows with many sites of
398
+ // one orbit (e.g. supercells) only pay for one full operation sweep
399
+ const equiv_by_element = new Map();
400
+ for (const orig_idx of wyckoff_pos.site_indices ?? []) {
401
+ if (orig_idx >= orig_structure.sites.length)
402
+ continue;
403
+ const { abc: orig_abc, species } = orig_structure.sites[orig_idx];
404
+ const element = species[0]?.element;
405
+ const equivalents = equiv_by_element.get(element) ?? new Map();
406
+ equiv_by_element.set(element, equivalents);
407
+ const member_key = symmetry_position_key(frame.map_equiv(orig_abc.map(to_unit)));
408
+ if (equivalents.has(member_key))
409
+ continue;
410
+ for (const equiv_pos of apply_symmetry_operations(orig_abc, sym_data.operations)) {
411
+ const frame_pos = frame.map_equiv(equiv_pos);
412
+ const key = symmetry_position_key(frame_pos);
413
+ if (!equivalents.has(key))
414
+ equivalents.set(key, frame_pos);
415
+ }
416
+ }
417
+ const matched = new Set();
418
+ for (const [element, equivalents] of equiv_by_element) {
419
+ const candidates = new Set();
420
+ for (const equiv_pos of equivalents.values()) {
421
+ direct_index.query(equiv_pos, candidates);
422
+ if (check && check_index) {
423
+ check_index.query(math.mat3x3_vec3_multiply(check, equiv_pos), candidates);
424
+ }
425
+ }
426
+ for (const display_idx of candidates) {
427
+ if (displayed_elements[display_idx] === element)
428
+ matched.add(display_idx);
429
+ }
430
+ }
431
+ if (matched.size > 0)
432
+ any_matched = true;
433
+ return { ...wyckoff_pos, site_indices: [...matched].sort((a, b) => a - b) };
225
434
  });
226
- return { ...wyckoff_pos, site_indices: [...new Set(indices)].sort((a, b) => a - b) };
227
- });
435
+ return any_matched || displayed_structure.sites.length === 0 ? rows : null;
436
+ };
437
+ // Try frames in order; accept the first whose lattice fits AND that matches any site
438
+ // (lattices can coincide across frames while origins differ, so a lattice match alone
439
+ // is not conclusive)
440
+ for (const frame of candidate_display_frames(orig_structure, sym_data)) {
441
+ const rows = map_in_frame(frame);
442
+ if (rows)
443
+ return rows;
444
+ }
445
+ // No frame fits — site indices into the displayed structure cannot be determined
446
+ return wyckoff_positions.map((pos) => ({ ...pos, site_indices: [] }));
228
447
  }
@@ -1,9 +1,20 @@
1
- export declare const CRYSTAL_SYSTEM_RANGES: Record<CrystalSystem, [number, number]>;
1
+ import type { Vec2 } from '../math';
2
+ import type { SunburstNode } from '../plot/core/types';
3
+ export declare const CRYSTAL_SYSTEM_RANGES: Record<CrystalSystem, Vec2>;
2
4
  export declare const CRYSTAL_SYSTEM_COLORS: Record<CrystalSystem, string>;
3
5
  export declare const CRYSTAL_SYSTEMS: readonly ["triclinic", "monoclinic", "orthorhombic", "tetragonal", "trigonal", "hexagonal", "cubic"];
4
6
  export type CrystalSystem = (typeof CRYSTAL_SYSTEMS)[number];
5
7
  export declare function spacegroup_num_to_crystal_sys(spacegroup: number): CrystalSystem | null;
6
8
  export declare function spacegroup_to_crystal_sys(spacegroup: number | string): CrystalSystem | null;
9
+ export declare const RHOMBOHEDRAL_SPACEGROUPS: readonly number[];
10
+ export type LatticeSystem = Exclude<CrystalSystem, `trigonal`> | `rhombohedral`;
11
+ export declare function spacegroup_num_to_lattice_system(spacegroup: number): LatticeSystem | null;
7
12
  export declare function normalize_spacegroup(spacegroup: number | string): number | null;
8
13
  export declare const SPACEGROUP_SYMBOL_TO_NUM: Record<string, number>;
9
14
  export declare const SPACEGROUP_NUM_TO_SYMBOL: Record<number, string>;
15
+ export interface SpacegroupSunburstMetadata {
16
+ spacegroup: number;
17
+ crystal_system: CrystalSystem;
18
+ [key: string]: unknown;
19
+ }
20
+ export declare function spacegroup_sunburst_data(spacegroups: readonly (number | string)[]): SunburstNode<SpacegroupSunburstMetadata>[];
@@ -40,24 +40,34 @@ export function spacegroup_num_to_crystal_sys(spacegroup) {
40
40
  }
41
41
  // Convert space group (number or symbol) to crystal system
42
42
  export function spacegroup_to_crystal_sys(spacegroup) {
43
- if (typeof spacegroup === `number`)
44
- return spacegroup_num_to_crystal_sys(spacegroup);
45
- // Try to parse as symbol
46
- const number = SPACEGROUP_SYMBOL_TO_NUM[spacegroup];
47
- if (number !== undefined)
48
- return spacegroup_num_to_crystal_sys(number);
49
- // Try to parse string as number
50
- const parsed = parseInt(spacegroup, 10);
51
- if (!isNaN(parsed))
52
- return spacegroup_num_to_crystal_sys(parsed);
53
- return null;
43
+ const num = normalize_spacegroup(spacegroup);
44
+ return num == null ? null : spacegroup_num_to_crystal_sys(num);
45
+ }
46
+ // Trigonal space groups with rhombohedral (R-centered) Bravais lattices. All other
47
+ // trigonal groups have primitive hexagonal lattices.
48
+ export const RHOMBOHEDRAL_SPACEGROUPS = [146, 148, 155, 160, 161, 166, 167];
49
+ // Convert space group number to lattice system (classification of the Bravais lattice).
50
+ // Differs from the crystal system only for trigonal groups: R-centered ones (R3, R-3m, …)
51
+ // have rhombohedral lattices while P-trigonal ones (P3, P-3m1, …) have hexagonal lattices.
52
+ export function spacegroup_num_to_lattice_system(spacegroup) {
53
+ const crystal_sys = spacegroup_num_to_crystal_sys(spacegroup);
54
+ if (crystal_sys === null)
55
+ return null;
56
+ if (crystal_sys !== `trigonal`)
57
+ return crystal_sys;
58
+ return RHOMBOHEDRAL_SPACEGROUPS.includes(spacegroup) ? `rhombohedral` : `hexagonal`;
54
59
  }
55
- // Normalize space group input to number
60
+ // Normalize space group input (number, Hermann-Mauguin symbol, or numeric string
61
+ // like "225") to a space group number in [1, 230], or null if invalid
56
62
  export function normalize_spacegroup(spacegroup) {
57
63
  if (typeof spacegroup === `number`) {
58
64
  return spacegroup >= 1 && spacegroup <= 230 ? spacegroup : null;
59
65
  }
60
- return SPACEGROUP_SYMBOL_TO_NUM[spacegroup] ?? null;
66
+ const from_symbol = SPACEGROUP_SYMBOL_TO_NUM[spacegroup];
67
+ if (from_symbol !== undefined)
68
+ return from_symbol;
69
+ const parsed = parseInt(spacegroup, 10);
70
+ return isNaN(parsed) ? null : normalize_spacegroup(parsed);
61
71
  }
62
72
  export const SPACEGROUP_SYMBOL_TO_NUM = {
63
73
  // Triclinic
@@ -206,13 +216,13 @@ export const SPACEGROUP_SYMBOL_TO_NUM = {
206
216
  'I4/mcm': 140,
207
217
  'I4_1/amd': 141,
208
218
  'I4_1/acd': 142,
219
+ // Trigonal
209
220
  P3: 143,
210
221
  P3_1: 144,
211
222
  P3_2: 145,
212
223
  R3: 146,
213
224
  'P-3': 147,
214
225
  'R-3': 148,
215
- // Trigonal
216
226
  P312: 149,
217
227
  P321: 150,
218
228
  P3_112: 151,
@@ -392,3 +402,42 @@ export const SPACEGROUP_NUM_TO_SYMBOL = Object.entries(SPACEGROUP_SYMBOL_TO_NUM)
392
402
  acc[num] = symbol;
393
403
  return acc;
394
404
  }, {});
405
+ // Build crystal-system -> spacegroup hierarchy data for the Sunburst component from a
406
+ // list of spacegroup numbers or symbols (one entry per occurrence; counts become leaf
407
+ // values). Leaf ids follow the pymatviz spacegroup_sunburst scheme, e.g. "cubic/225".
408
+ export function spacegroup_sunburst_data(spacegroups) {
409
+ const counts = new Map();
410
+ let n_invalid = 0;
411
+ for (const spacegroup of spacegroups) {
412
+ const num = normalize_spacegroup(spacegroup); // numbers, symbols, numeric strings
413
+ if (num == null) {
414
+ n_invalid += 1;
415
+ continue;
416
+ }
417
+ counts.set(num, (counts.get(num) ?? 0) + 1);
418
+ }
419
+ if (n_invalid > 0) {
420
+ console.warn(`spacegroup_sunburst_data: skipped ${n_invalid} invalid spacegroup(s) (expected numbers 1-230 or Hermann-Mauguin symbols)`);
421
+ }
422
+ // Emit crystal systems in canonical (space group number) order, only those present
423
+ return CRYSTAL_SYSTEMS.flatMap((system) => {
424
+ const nums = [...counts.keys()]
425
+ .filter((num) => spacegroup_num_to_crystal_sys(num) === system)
426
+ .sort((num_a, num_b) => num_a - num_b);
427
+ if (nums.length === 0)
428
+ return [];
429
+ return [
430
+ {
431
+ id: system,
432
+ label: system,
433
+ color: CRYSTAL_SYSTEM_COLORS[system],
434
+ children: nums.map((num) => ({
435
+ id: `${system}/${num}`,
436
+ label: SPACEGROUP_NUM_TO_SYMBOL[num] ?? `${num}`,
437
+ value: counts.get(num),
438
+ metadata: { spacegroup: num, crystal_system: system },
439
+ })),
440
+ },
441
+ ];
442
+ });
443
+ }
@@ -0,0 +1,33 @@
1
+ import type { Matrix3x3, Vec3 } from '../math';
2
+ import type { MoyoDataset } from '@spglib/moyo-wasm';
3
+ export type SymmetryElementKind = `rotation` | `screw` | `mirror` | `glide` | `inversion` | `rotoinversion`;
4
+ export type SymmetryElement = {
5
+ kind: SymmetryElementKind;
6
+ order: number;
7
+ label: string;
8
+ axis: Vec3 | null;
9
+ point: Vec3;
10
+ translation: Vec3 | null;
11
+ };
12
+ export declare const SYM_ELEM_KINDS: readonly ["rotation", "screw", "rotoinversion", "mirror", "glide", "inversion"];
13
+ export type ShowSymmetryKinds = Partial<Record<SymmetryElementKind, boolean>>;
14
+ export declare const DEFAULT_SHOW_SYM_KINDS: ShowSymmetryKinds;
15
+ export declare const SYM_ELEM_KIND_INFO: Record<SymmetryElementKind, {
16
+ label: string;
17
+ color: string;
18
+ }>;
19
+ export declare function count_symmetry_elements(elements: readonly SymmetryElement[]): Partial<Record<SymmetryElementKind, number>>;
20
+ export declare const has_visible_symmetry_overlay: (elements: readonly SymmetryElement[], show_kinds?: ShowSymmetryKinds) => boolean;
21
+ export declare const mat3_from_flat_col_major: (flat: readonly number[]) => Matrix3x3;
22
+ export type ClassifiedOperation = Omit<SymmetryElement, `point`> & {
23
+ point: Vec3;
24
+ };
25
+ export declare function classify_symmetry_op(rotation: readonly number[], translation: readonly number[], centerings?: readonly Vec3[]): ClassifiedOperation | null;
26
+ export declare function symmetry_elements_from_ops(operations: MoyoDataset[`operations`]): SymmetryElement[];
27
+ export declare function dash_segments(length: number, dash: number, gap: number): {
28
+ center: number;
29
+ length: number;
30
+ }[];
31
+ export declare const frac_to_cart_direction: (frac: Vec3, lattice: Matrix3x3) => Vec3;
32
+ export declare function clip_line_to_cell(point: Vec3, direction: Vec3, lattice: Matrix3x3, eps?: number): [Vec3, Vec3] | null;
33
+ export declare function clip_plane_to_cell(point: Vec3, normal_frac: Vec3, lattice: Matrix3x3): Vec3[];