matterviz 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +154 -96
  3. package/dist/Icon.svelte +20 -14
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -178
  7. package/dist/brillouin/BrillouinZone.svelte +299 -198
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +74 -55
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +277 -165
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
  18. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  19. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +847 -0
  20. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  21. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3194 -0
  22. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  23. package/dist/chempot-diagram/ChemPotScene3D.svelte +11 -0
  24. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  25. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  26. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  27. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  28. package/dist/chempot-diagram/chempot-worker.js +11 -0
  29. package/dist/chempot-diagram/color.d.ts +10 -0
  30. package/dist/chempot-diagram/color.js +32 -0
  31. package/dist/chempot-diagram/compute.d.ts +48 -0
  32. package/dist/chempot-diagram/compute.js +812 -0
  33. package/dist/chempot-diagram/index.d.ts +6 -0
  34. package/dist/chempot-diagram/index.js +6 -0
  35. package/dist/chempot-diagram/pointer.d.ts +16 -0
  36. package/dist/chempot-diagram/pointer.js +40 -0
  37. package/dist/chempot-diagram/temperature.d.ts +15 -0
  38. package/dist/chempot-diagram/temperature.js +36 -0
  39. package/dist/chempot-diagram/types.d.ts +86 -0
  40. package/dist/chempot-diagram/types.js +28 -0
  41. package/dist/colors/index.d.ts +3 -1
  42. package/dist/colors/index.js +9 -3
  43. package/dist/composition/BarChart.svelte +141 -77
  44. package/dist/composition/BubbleChart.svelte +107 -52
  45. package/dist/composition/Composition.svelte +100 -79
  46. package/dist/composition/Formula.svelte +108 -62
  47. package/dist/composition/FormulaFilter.svelte +973 -353
  48. package/dist/composition/FormulaFilter.svelte.d.ts +35 -1
  49. package/dist/composition/PieChart.svelte +199 -99
  50. package/dist/composition/PieChart.svelte.d.ts +1 -1
  51. package/dist/composition/format.d.ts +5 -0
  52. package/dist/composition/format.js +20 -3
  53. package/dist/composition/parse.js +14 -9
  54. package/dist/convex-hull/ConvexHull.svelte +93 -38
  55. package/dist/convex-hull/ConvexHull2D.svelte +551 -393
  56. package/dist/convex-hull/ConvexHull3D.svelte +1303 -825
  57. package/dist/convex-hull/ConvexHull4D.svelte +1012 -686
  58. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  59. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  60. package/dist/convex-hull/ConvexHullStats.svelte +821 -249
  61. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  62. package/dist/convex-hull/ConvexHullTooltip.svelte +41 -16
  63. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  64. package/dist/convex-hull/StructurePopup.svelte +25 -4
  65. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  66. package/dist/convex-hull/barycentric-coords.js +13 -7
  67. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  68. package/dist/convex-hull/demo-temperature.js +40 -0
  69. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  70. package/dist/convex-hull/helpers.d.ts +10 -1
  71. package/dist/convex-hull/helpers.js +79 -38
  72. package/dist/convex-hull/index.d.ts +1 -0
  73. package/dist/convex-hull/index.js +1 -0
  74. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  75. package/dist/convex-hull/thermodynamics.js +163 -69
  76. package/dist/convex-hull/types.d.ts +12 -12
  77. package/dist/convex-hull/types.js +0 -12
  78. package/dist/coordination/CoordinationBarPlot.svelte +232 -176
  79. package/dist/element/BohrAtom.svelte +56 -13
  80. package/dist/element/ElementHeading.svelte +7 -2
  81. package/dist/element/ElementPhoto.svelte +15 -9
  82. package/dist/element/ElementStats.svelte +10 -4
  83. package/dist/element/ElementTile.svelte +137 -73
  84. package/dist/element/Nucleus.svelte +39 -11
  85. package/dist/element/data.js +2 -14
  86. package/dist/element/data.json.gz +0 -0
  87. package/dist/element/types.d.ts +1 -0
  88. package/dist/feedback/ClickFeedback.svelte +16 -5
  89. package/dist/feedback/DragOverlay.svelte +10 -2
  90. package/dist/feedback/Spinner.svelte +4 -2
  91. package/dist/feedback/StatusMessage.svelte +8 -2
  92. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  93. package/dist/fermi-surface/FermiSurface.svelte +336 -239
  94. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  95. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  96. package/dist/fermi-surface/FermiSurfaceScene.svelte +536 -343
  97. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  98. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  99. package/dist/fermi-surface/compute.js +16 -20
  100. package/dist/fermi-surface/parse.js +37 -33
  101. package/dist/fermi-surface/symmetry.js +2 -7
  102. package/dist/fermi-surface/types.d.ts +3 -5
  103. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1527 -0
  104. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  105. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  106. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  107. package/dist/heatmap-matrix/index.d.ts +53 -0
  108. package/dist/heatmap-matrix/index.js +100 -0
  109. package/dist/heatmap-matrix/shared.d.ts +2 -0
  110. package/dist/heatmap-matrix/shared.js +4 -0
  111. package/dist/icons.d.ts +111 -0
  112. package/dist/icons.js +158 -0
  113. package/dist/index.d.ts +5 -2
  114. package/dist/index.js +5 -2
  115. package/dist/io/decompress.js +1 -1
  116. package/dist/io/export.d.ts +3 -0
  117. package/dist/io/export.js +138 -140
  118. package/dist/io/file-drop.d.ts +7 -0
  119. package/dist/io/file-drop.js +43 -0
  120. package/dist/io/index.d.ts +2 -2
  121. package/dist/io/index.js +2 -112
  122. package/dist/io/is-binary.js +2 -3
  123. package/dist/io/types.d.ts +1 -0
  124. package/dist/io/url-drop.d.ts +2 -0
  125. package/dist/io/url-drop.js +117 -0
  126. package/dist/isosurface/Isosurface.svelte +220 -110
  127. package/dist/isosurface/IsosurfaceControls.svelte +65 -28
  128. package/dist/isosurface/parse.js +104 -56
  129. package/dist/isosurface/slice.d.ts +2 -1
  130. package/dist/isosurface/slice.js +8 -13
  131. package/dist/isosurface/types.d.ts +14 -1
  132. package/dist/isosurface/types.js +152 -5
  133. package/dist/labels.d.ts +2 -1
  134. package/dist/labels.js +12 -8
  135. package/dist/layout/FullscreenToggle.svelte +11 -2
  136. package/dist/layout/InfoCard.svelte +38 -6
  137. package/dist/layout/InfoTag.svelte +125 -94
  138. package/dist/layout/PropertyFilter.svelte +82 -37
  139. package/dist/layout/SettingsSection.svelte +85 -55
  140. package/dist/layout/SubpageGrid.svelte +82 -0
  141. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  142. package/dist/layout/index.d.ts +1 -0
  143. package/dist/layout/index.js +1 -0
  144. package/dist/layout/json-tree/JsonNode.svelte +266 -223
  145. package/dist/layout/json-tree/JsonTree.svelte +516 -429
  146. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  147. package/dist/layout/json-tree/JsonValue.svelte +281 -173
  148. package/dist/layout/json-tree/types.d.ts +10 -2
  149. package/dist/layout/json-tree/utils.d.ts +2 -0
  150. package/dist/layout/json-tree/utils.js +37 -2
  151. package/dist/marching-cubes.js +25 -2
  152. package/dist/math.d.ts +20 -17
  153. package/dist/math.js +474 -57
  154. package/dist/overlays/ContextMenu.svelte +66 -40
  155. package/dist/overlays/DraggablePane.svelte +331 -154
  156. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  157. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  158. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  159. package/dist/periodic-table/PropertySelect.svelte +25 -7
  160. package/dist/periodic-table/TableInset.svelte +8 -3
  161. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +559 -267
  162. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  163. package/dist/phase-diagram/PhaseDiagramControls.svelte +131 -51
  164. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  165. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
  166. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  167. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +160 -110
  168. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +8 -1
  169. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +217 -86
  170. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  171. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  172. package/dist/phase-diagram/build-diagram.js +9 -9
  173. package/dist/phase-diagram/colors.js +1 -3
  174. package/dist/phase-diagram/index.d.ts +2 -0
  175. package/dist/phase-diagram/index.js +2 -0
  176. package/dist/phase-diagram/parse.js +10 -9
  177. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  178. package/dist/phase-diagram/svg-to-diagram.js +869 -0
  179. package/dist/phase-diagram/types.d.ts +10 -0
  180. package/dist/phase-diagram/utils.d.ts +8 -4
  181. package/dist/phase-diagram/utils.js +219 -74
  182. package/dist/plot/AxisLabel.svelte +51 -0
  183. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  184. package/dist/plot/BarPlot.svelte +1461 -768
  185. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  186. package/dist/plot/BarPlotControls.svelte +33 -6
  187. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  188. package/dist/plot/ColorBar.svelte +533 -383
  189. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  190. package/dist/plot/ColorScaleSelect.svelte +28 -7
  191. package/dist/plot/ElementScatter.svelte +38 -16
  192. package/dist/plot/FillArea.svelte +152 -92
  193. package/dist/plot/Histogram.svelte +1162 -709
  194. package/dist/plot/Histogram.svelte.d.ts +1 -1
  195. package/dist/plot/HistogramControls.svelte +81 -18
  196. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  197. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  198. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  199. package/dist/plot/Line.svelte +63 -28
  200. package/dist/plot/PlotControls.svelte +221 -96
  201. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  202. package/dist/plot/PlotLegend.svelte +174 -91
  203. package/dist/plot/PlotTooltip.svelte +45 -6
  204. package/dist/plot/PortalSelect.svelte +175 -146
  205. package/dist/plot/ReferenceLine.svelte +77 -22
  206. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  207. package/dist/plot/ReferenceLine3D.svelte +132 -107
  208. package/dist/plot/ReferencePlane.svelte +146 -123
  209. package/dist/plot/ScatterPlot.svelte +1880 -1156
  210. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  211. package/dist/plot/ScatterPlot3D.svelte +256 -131
  212. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  213. package/dist/plot/ScatterPlot3DControls.svelte +300 -297
  214. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  215. package/dist/plot/ScatterPlot3DScene.svelte +608 -406
  216. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  217. package/dist/plot/ScatterPlotControls.svelte +150 -70
  218. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  219. package/dist/plot/ScatterPoint.svelte +98 -26
  220. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  221. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  222. package/dist/plot/Surface3D.svelte +159 -108
  223. package/dist/plot/ZeroLines.svelte +96 -0
  224. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  225. package/dist/plot/ZoomRect.svelte +23 -0
  226. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  227. package/dist/plot/axis-utils.d.ts +1 -1
  228. package/dist/plot/axis-utils.js +1 -3
  229. package/dist/plot/data-cleaning.js +12 -28
  230. package/dist/plot/data-transform.js +2 -1
  231. package/dist/plot/fill-utils.js +2 -0
  232. package/dist/plot/index.d.ts +6 -2
  233. package/dist/plot/index.js +6 -2
  234. package/dist/plot/interactions.d.ts +8 -10
  235. package/dist/plot/interactions.js +2 -3
  236. package/dist/plot/layout.d.ts +11 -2
  237. package/dist/plot/layout.js +44 -17
  238. package/dist/plot/reference-line.d.ts +5 -22
  239. package/dist/plot/reference-line.js +12 -84
  240. package/dist/plot/scales.js +24 -36
  241. package/dist/plot/types.d.ts +53 -40
  242. package/dist/plot/types.js +12 -7
  243. package/dist/plot/utils/label-placement.d.ts +32 -15
  244. package/dist/plot/utils/label-placement.js +227 -63
  245. package/dist/plot/utils/series-visibility.js +2 -3
  246. package/dist/plot/utils.d.ts +1 -0
  247. package/dist/plot/utils.js +14 -0
  248. package/dist/rdf/RdfPlot.svelte +173 -132
  249. package/dist/rdf/calc-rdf.js +4 -5
  250. package/dist/sanitize.d.ts +4 -0
  251. package/dist/sanitize.js +107 -0
  252. package/dist/settings.d.ts +21 -6
  253. package/dist/settings.js +63 -19
  254. package/dist/spectral/Bands.svelte +963 -412
  255. package/dist/spectral/Bands.svelte.d.ts +22 -2
  256. package/dist/spectral/BandsAndDos.svelte +90 -49
  257. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  258. package/dist/spectral/Dos.svelte +389 -258
  259. package/dist/spectral/helpers.d.ts +23 -1
  260. package/dist/spectral/helpers.js +119 -51
  261. package/dist/spectral/types.d.ts +2 -0
  262. package/dist/state.svelte.d.ts +1 -1
  263. package/dist/state.svelte.js +3 -2
  264. package/dist/structure/Arrow.svelte +59 -20
  265. package/dist/structure/AtomLegend.svelte +231 -129
  266. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  267. package/dist/structure/Bond.svelte +73 -47
  268. package/dist/structure/CanvasTooltip.svelte +10 -2
  269. package/dist/structure/CellSelect.svelte +148 -51
  270. package/dist/structure/Cylinder.svelte +33 -17
  271. package/dist/structure/Lattice.svelte +88 -33
  272. package/dist/structure/Structure.svelte +1077 -821
  273. package/dist/structure/Structure.svelte.d.ts +1 -1
  274. package/dist/structure/StructureControls.svelte +373 -139
  275. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  276. package/dist/structure/StructureExportPane.svelte +124 -89
  277. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  278. package/dist/structure/StructureInfoPane.svelte +304 -231
  279. package/dist/structure/StructureScene.svelte +919 -445
  280. package/dist/structure/StructureScene.svelte.d.ts +16 -7
  281. package/dist/structure/atom-properties.d.ts +6 -2
  282. package/dist/structure/atom-properties.js +42 -29
  283. package/dist/structure/bonding.js +6 -7
  284. package/dist/structure/export.js +22 -34
  285. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  286. package/dist/structure/ferrox-wasm-types.js +0 -3
  287. package/dist/structure/ferrox-wasm.d.ts +3 -2
  288. package/dist/structure/ferrox-wasm.js +2 -3
  289. package/dist/structure/index.d.ts +16 -0
  290. package/dist/structure/index.js +88 -6
  291. package/dist/structure/measure.d.ts +2 -2
  292. package/dist/structure/measure.js +4 -44
  293. package/dist/structure/parse.js +130 -155
  294. package/dist/structure/partial-occupancy.d.ts +25 -0
  295. package/dist/structure/partial-occupancy.js +99 -0
  296. package/dist/structure/pbc.d.ts +1 -0
  297. package/dist/structure/pbc.js +16 -6
  298. package/dist/structure/supercell.d.ts +2 -2
  299. package/dist/structure/supercell.js +12 -22
  300. package/dist/structure/validation.js +5 -3
  301. package/dist/symmetry/SymmetryStats.svelte +94 -37
  302. package/dist/symmetry/WyckoffTable.svelte +42 -14
  303. package/dist/symmetry/cell-transform.js +5 -3
  304. package/dist/symmetry/index.d.ts +7 -4
  305. package/dist/symmetry/index.js +87 -21
  306. package/dist/symmetry/spacegroups.js +148 -148
  307. package/dist/table/HeatmapTable.svelte +1112 -516
  308. package/dist/table/HeatmapTable.svelte.d.ts +12 -1
  309. package/dist/table/ToggleMenu.svelte +125 -90
  310. package/dist/table/index.d.ts +2 -0
  311. package/dist/table/index.js +2 -4
  312. package/dist/theme/ThemeControl.svelte +21 -12
  313. package/dist/time.js +4 -1
  314. package/dist/tooltip/TooltipContent.svelte +33 -8
  315. package/dist/trajectory/Trajectory.svelte +889 -687
  316. package/dist/trajectory/TrajectoryError.svelte +14 -3
  317. package/dist/trajectory/TrajectoryExportPane.svelte +148 -90
  318. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  319. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  320. package/dist/trajectory/constants.d.ts +6 -0
  321. package/dist/trajectory/constants.js +7 -0
  322. package/dist/trajectory/extract.js +13 -31
  323. package/dist/trajectory/format-detect.d.ts +9 -0
  324. package/dist/trajectory/format-detect.js +76 -0
  325. package/dist/trajectory/frame-reader.d.ts +17 -0
  326. package/dist/trajectory/frame-reader.js +332 -0
  327. package/dist/trajectory/helpers.d.ts +14 -0
  328. package/dist/trajectory/helpers.js +172 -0
  329. package/dist/trajectory/index.d.ts +1 -0
  330. package/dist/trajectory/index.js +23 -14
  331. package/dist/trajectory/parse/ase.d.ts +2 -0
  332. package/dist/trajectory/parse/ase.js +77 -0
  333. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  334. package/dist/trajectory/parse/hdf5.js +129 -0
  335. package/dist/trajectory/parse/index.d.ts +12 -0
  336. package/dist/trajectory/parse/index.js +299 -0
  337. package/dist/trajectory/parse/lammps.d.ts +5 -0
  338. package/dist/trajectory/parse/lammps.js +179 -0
  339. package/dist/trajectory/parse/vasp.d.ts +2 -0
  340. package/dist/trajectory/parse/vasp.js +68 -0
  341. package/dist/trajectory/parse/xyz.d.ts +2 -0
  342. package/dist/trajectory/parse/xyz.js +110 -0
  343. package/dist/trajectory/plotting.js +13 -8
  344. package/dist/trajectory/types.d.ts +11 -0
  345. package/dist/trajectory/types.js +1 -0
  346. package/dist/utils.d.ts +3 -0
  347. package/dist/utils.js +17 -0
  348. package/dist/xrd/XrdPlot.svelte +337 -245
  349. package/dist/xrd/broadening.js +14 -9
  350. package/dist/xrd/calc-xrd.js +12 -19
  351. package/dist/xrd/parse.d.ts +1 -1
  352. package/dist/xrd/parse.js +17 -17
  353. package/package.json +103 -101
  354. package/readme.md +4 -4
  355. package/dist/trajectory/parse.d.ts +0 -42
  356. package/dist/trajectory/parse.js +0 -1267
  357. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
  358. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,14 +1,14 @@
1
+ import type { D3InterpolateName } from '../colors';
1
2
  import type { ElementSymbol } from '../element';
2
3
  import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types';
3
4
  import type { Vec3 } from '../math';
4
- import { type CameraProjection, type ShowBonds } from '../settings';
5
+ import type { CameraProjection, ShowBonds, VectorColorMode, VectorLayerConfig } from '../settings';
5
6
  import type { AnyStructure, MeasureMode, Site } from './';
6
7
  import { Lattice } from './';
7
8
  import type { AtomColorConfig } from './atom-properties';
8
9
  import type { MoyoDataset } from '@spglib/moyo-wasm';
9
10
  import * as extras from '@threlte/extras';
10
- import type { ComponentProps } from 'svelte';
11
- import { type Snippet } from 'svelte';
11
+ import { type ComponentProps, type Snippet } from 'svelte';
12
12
  import { SvelteMap } from 'svelte/reactivity';
13
13
  import { type Camera, type Scene } from 'three';
14
14
  import type { BondingStrategy } from './bonding';
@@ -18,6 +18,7 @@ type $$ComponentProps = {
18
18
  atom_radius?: number;
19
19
  same_size_atoms?: boolean;
20
20
  camera_position?: [x: number, y: number, z: number];
21
+ camera_target?: Vec3;
21
22
  camera_projection?: CameraProjection;
22
23
  rotation_damping?: number;
23
24
  max_zoom?: number;
@@ -30,9 +31,17 @@ type $$ComponentProps = {
30
31
  show_bonds?: ShowBonds;
31
32
  show_site_labels?: boolean;
32
33
  show_site_indices?: boolean;
33
- show_force_vectors?: boolean;
34
- force_scale?: number;
35
- force_color?: string;
34
+ vector_configs?: Record<string, VectorLayerConfig>;
35
+ vector_scale?: number;
36
+ vector_color?: string;
37
+ vector_color_mode?: VectorColorMode;
38
+ vector_color_scale?: D3InterpolateName;
39
+ vector_normalize?: boolean;
40
+ vector_uniform_thickness?: boolean;
41
+ vector_origin_gap?: number;
42
+ vector_shaft_radius?: number;
43
+ vector_arrow_head_radius?: number;
44
+ vector_arrow_head_length?: number;
36
45
  gizmo?: boolean | ComponentProps<typeof extras.Gizmo>;
37
46
  hovered_idx?: number | null;
38
47
  hovered_site?: Site | null;
@@ -90,6 +99,6 @@ type $$ComponentProps = {
90
99
  volumetric_data?: VolumetricData;
91
100
  isosurface_settings?: IsosurfaceSettings;
92
101
  };
93
- declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "site_label_offset" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "hovered_idx" | "hovered_site" | "camera_is_moving" | "measured_sites" | "added_bonds" | "removed_bonds" | "active_sites" | "scene" | "camera" | "orbit_controls" | "rotation_target_ref" | "initial_computed_zoom" | "add_atom_mode" | "add_element" | "dragging_atoms">;
102
+ declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "site_label_offset" | "vector_configs" | "camera" | "scene" | "orbit_controls" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "selected_sites" | "hovered_idx" | "hovered_site" | "camera_is_moving" | "measured_sites" | "added_bonds" | "removed_bonds" | "active_sites" | "rotation_target_ref" | "initial_computed_zoom" | "add_atom_mode" | "add_element" | "dragging_atoms">;
94
103
  type StructureScene = ReturnType<typeof StructureScene>;
95
104
  export default StructureScene;
@@ -1,6 +1,6 @@
1
- import type { AnyStructure, Site } from './';
2
1
  import type { ColorScaleType, D3InterpolateName } from '../colors';
3
2
  import type { AtomColorMode } from '../settings';
3
+ import type { AnyStructure, Site } from './';
4
4
  import type { BondingStrategy } from './bonding';
5
5
  import type { MoyoDataset } from '@spglib/moyo-wasm';
6
6
  export interface AtomColorConfig {
@@ -16,6 +16,9 @@ export interface AtomPropertyColors {
16
16
  max_value?: number;
17
17
  unique_values?: (number | string)[];
18
18
  }
19
+ type SymmetryDataWithOrigMap = MoyoDataset & {
20
+ orig_site_indices_by_std_idx?: number[][];
21
+ };
19
22
  export declare const get_d3_color_scales: () => string[];
20
23
  export declare function apply_color_scale(vals: number[], scale?: string, type?: ColorScaleType): {
21
24
  colors: string[];
@@ -27,7 +30,8 @@ export declare const apply_categorical_color_scale: (vals: string[], scale?: str
27
30
  };
28
31
  export declare const get_orig_site_idx: (site: Site | undefined, site_idx: number) => number;
29
32
  export declare function get_coordination_colors(structure: AnyStructure, strategy?: BondingStrategy, scale?: string, type?: ColorScaleType): AtomPropertyColors;
30
- export declare function get_wyckoff_colors(structure: AnyStructure, sym_data: MoyoDataset | null, scale?: string): AtomPropertyColors;
33
+ export declare function get_wyckoff_colors(structure: AnyStructure, sym_data: SymmetryDataWithOrigMap | null, scale?: string): AtomPropertyColors;
31
34
  export declare function get_custom_colors(structure: AnyStructure, fn: (site: Site, idx: number) => number | string, scale?: string, type?: ColorScaleType): AtomPropertyColors;
32
35
  export declare function get_atom_colors(structure: AnyStructure, config: Partial<AtomColorConfig>, bonding_strategy?: BondingStrategy, sym_data?: MoyoDataset | null): AtomPropertyColors;
33
36
  export declare function get_property_colors(structure: AnyStructure | undefined, config: Partial<AtomColorConfig>, bonding_strategy: BondingStrategy, sym_data: MoyoDataset | null): AtomPropertyColors | null;
37
+ export {};
@@ -1,6 +1,7 @@
1
1
  // Utility functions for computing atom properties and applying color scales
2
2
  import { calc_coordination_nums } from '../coordination';
3
3
  import * as math from '../math';
4
+ import { wrap_to_unit_cell } from './pbc';
4
5
  import { rgb } from 'd3-color';
5
6
  import * as d3_sc from 'd3-scale-chromatic';
6
7
  const GRAY = `#808080`;
@@ -15,6 +16,25 @@ const get_interpolator = (scale) => {
15
16
  return interp_fn;
16
17
  };
17
18
  const to_hex = (interp_fn, t) => rgb(interp_fn(t)).formatHex();
19
+ const build_image_site = (site, frac_to_cart, offset, orig_idx) => {
20
+ const img_abc = [
21
+ site.abc[0] + offset[0],
22
+ site.abc[1] + offset[1],
23
+ site.abc[2] + offset[2],
24
+ ];
25
+ return {
26
+ ...site,
27
+ abc: img_abc,
28
+ xyz: frac_to_cart(img_abc),
29
+ properties: { ...site.properties, orig_site_idx: orig_idx },
30
+ };
31
+ };
32
+ const get_all_offsets = (pbc) => [-1, 0, 1]
33
+ .flatMap((dx) => [-1, 0, 1].flatMap((dy) => [-1, 0, 1].map((dz) => [dx, dy, dz])))
34
+ .filter(([dx, dy, dz]) => !(dx === 0 && dy === 0 && dz === 0) &&
35
+ (pbc[0] || dx === 0) &&
36
+ (pbc[1] || dy === 0) &&
37
+ (pbc[2] || dz === 0));
18
38
  const make_categorical = (vals, scale, sort_fn) => {
19
39
  const interp_fn = get_interpolator(scale);
20
40
  const uniq = sort_fn ? [...new Set(vals)].sort(sort_fn) : [...new Set(vals)].sort();
@@ -66,45 +86,23 @@ function expand_structure_for_pbc(structure) {
66
86
  return structure;
67
87
  }
68
88
  const { sites, lattice } = structure;
69
- const lattice_T = math.transpose_3x3_matrix(lattice.matrix);
89
+ const frac_to_cart = math.create_frac_to_cart(lattice.matrix);
70
90
  const pbc = lattice.pbc ?? [true, true, true];
71
- // All valid image offsets respecting PBC
72
- const all_offsets = [-1, 0, 1]
73
- .flatMap((dx) => [-1, 0, 1].flatMap((dy) => [-1, 0, 1].map((dz) => [dx, dy, dz])))
74
- .filter(([dx, dy, dz]) => !(dx === 0 && dy === 0 && dz === 0) &&
75
- (pbc[0] || dx === 0) &&
76
- (pbc[1] || dy === 0) &&
77
- (pbc[2] || dz === 0));
91
+ const all_offsets = get_all_offsets(pbc);
78
92
  // Small structures: expand all atoms
79
93
  if (sites.length < 20 || !pbc.some((periodic) => periodic)) {
80
- const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map(([dx, dy, dz]) => {
81
- const img_abc = [site.abc[0] + dx, site.abc[1] + dy, site.abc[2] + dz];
82
- return {
83
- ...site,
84
- abc: img_abc,
85
- xyz: math.mat3x3_vec3_multiply(lattice_T, img_abc),
86
- properties: { ...site.properties, orig_site_idx: orig_idx },
87
- };
88
- }));
94
+ const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx)));
89
95
  return { ...structure, sites: [...sites, ...image_sites] };
90
96
  }
91
97
  // Large structures: only expand atoms near boundaries (within 5Å bond distance)
92
98
  const cutoff = [5.0 / lattice.a, 5.0 / lattice.b, 5.0 / lattice.c];
93
99
  const image_sites = sites.flatMap((site, orig_idx) => {
94
- const norm = site.abc.map((coord) => coord - Math.floor(coord));
100
+ const norm = wrap_to_unit_cell(site.abc);
95
101
  return all_offsets
96
102
  .filter(([dx, dy, dz]) => (dx === 0 || (dx === -1 ? norm[0] <= cutoff[0] : norm[0] >= 1 - cutoff[0])) &&
97
103
  (dy === 0 || (dy === -1 ? norm[1] <= cutoff[1] : norm[1] >= 1 - cutoff[1])) &&
98
104
  (dz === 0 || (dz === -1 ? norm[2] <= cutoff[2] : norm[2] >= 1 - cutoff[2])))
99
- .map(([dx, dy, dz]) => {
100
- const img_abc = [site.abc[0] + dx, site.abc[1] + dy, site.abc[2] + dz];
101
- return {
102
- ...site,
103
- abc: img_abc,
104
- xyz: math.mat3x3_vec3_multiply(lattice_T, img_abc),
105
- properties: { ...site.properties, orig_site_idx: orig_idx },
106
- };
107
- });
105
+ .map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx));
108
106
  });
109
107
  return { ...structure, sites: [...sites, ...image_sites] };
110
108
  }
@@ -113,8 +111,7 @@ export function get_coordination_colors(structure, strategy = `electroneg_ratio`
113
111
  // Check if structure has periodic boundary conditions
114
112
  const has_lattice = `lattice` in structure && structure.lattice !== undefined;
115
113
  const pbc = has_lattice ? structure.lattice.pbc : undefined;
116
- const has_pbc = has_lattice &&
117
- (pbc === undefined || pbc.some((is_periodic) => is_periodic));
114
+ const has_pbc = has_lattice && (pbc === undefined || pbc.some((is_periodic) => is_periodic));
118
115
  // For PBC structures, expand with images from neighboring cells for accurate coordination
119
116
  const coord_structure = has_pbc ? expand_structure_for_pbc(structure) : structure;
120
117
  // Calculate coordination numbers on the (potentially expanded) structure
@@ -135,9 +132,25 @@ export function get_wyckoff_colors(structure, sym_data, scale = DEFAULT_COLOR_SC
135
132
  unique_values: [`unknown`],
136
133
  };
137
134
  }
135
+ const wyckoff_by_orig_idx = new Map();
136
+ const mapping_by_std_idx = sym_data.orig_site_indices_by_std_idx;
137
+ if (mapping_by_std_idx) {
138
+ for (let std_idx = 0; std_idx < sym_data.wyckoffs.length; std_idx += 1) {
139
+ const wyckoff = sym_data.wyckoffs[std_idx];
140
+ for (const orig_idx of mapping_by_std_idx[std_idx] ?? []) {
141
+ if (!wyckoff_by_orig_idx.has(orig_idx))
142
+ wyckoff_by_orig_idx.set(orig_idx, wyckoff);
143
+ }
144
+ }
145
+ }
138
146
  // Create unique orbit identifiers: Wyckoff position + element symbol
139
147
  const orbit_ids = structure.sites.map((site, idx) => {
140
148
  const sym_idx = get_orig_site_idx(site, idx);
149
+ const mapped_wyckoff = wyckoff_by_orig_idx.get(sym_idx);
150
+ if (mapped_wyckoff !== undefined) {
151
+ const element = site.species[0]?.element ?? `?`;
152
+ return mapped_wyckoff ? `${mapped_wyckoff}|${element}` : `unknown`;
153
+ }
141
154
  if (sym_idx >= sym_data.wyckoffs.length) {
142
155
  console.error(`[get_wyckoff_colors] Site ${idx} (maps to ${sym_idx}) has no Wyckoff data. ` +
143
156
  `Structure has ${n} sites but symmetry data only has ${sym_data.wyckoffs.length}.`);
@@ -2,7 +2,9 @@
2
2
  import { element_data } from '../element';
3
3
  import * as math from '../math';
4
4
  const element_lookup = new Map(element_data.map((el) => [el.symbol, el]));
5
- const covalent_radii = new Map(element_data.filter((el) => el.covalent_radius !== null).map((el) => [el.symbol, el.covalent_radius]));
5
+ const covalent_radii = new Map(element_data
6
+ .filter((el) => el.covalent_radius !== null)
7
+ .map((el) => [el.symbol, el.covalent_radius]));
6
8
  // Get the species with highest occupancy from a site.
7
9
  const get_majority_species = (site) => (site.species ?? []).reduce((max_species, species) => (species.occu > max_species.occu ? species : max_species), site.species?.[0] ?? { element: ``, occu: -1 });
8
10
  // Helper to extract numeric index from site properties
@@ -67,6 +69,7 @@ export function compute_bond_transform(pos_1, pos_2) {
67
69
  (pos_1[2] + pos_2[2]) / 2,
68
70
  ];
69
71
  return new Float32Array([
72
+ // Return flattened column-major 4x4 matrix for Three.js
70
73
  ...[m00, m10, m20, 0],
71
74
  ...[m01 * height, m11 * height, m21 * height, 0],
72
75
  ...[m02, m12, m22, 0],
@@ -263,17 +266,13 @@ export function solid_angle(structure, { min_solid_angle = 0.01, min_face_area =
263
266
  for (let idx_a = 0; idx_a < sites.length - 1; idx_a++) {
264
267
  const [x1, y1, z1] = sites[idx_a].xyz;
265
268
  const majority_a = get_majority_species(sites[idx_a]);
266
- const radius_a = majority_a.element
267
- ? covalent_radii.get(majority_a.element)
268
- : undefined;
269
+ const radius_a = majority_a.element ? covalent_radii.get(majority_a.element) : undefined;
269
270
  for (const idx_b of get_candidates(sites[idx_a].xyz, sites, spatial)) {
270
271
  if (idx_b <= idx_a)
271
272
  continue;
272
273
  const [x2, y2, z2] = sites[idx_b].xyz;
273
274
  const majority_b = get_majority_species(sites[idx_b]);
274
- const radius_b = majority_b.element
275
- ? covalent_radii.get(majority_b.element)
276
- : undefined;
275
+ const radius_b = majority_b.element ? covalent_radii.get(majority_b.element) : undefined;
277
276
  const [dx, dy, dz] = [x2 - x1, y2 - y1, z2 - z1];
278
277
  const dist_sq = dx * dx + dy * dy + dz * dz;
279
278
  const dist = Math.sqrt(dist_sq);
@@ -10,13 +10,16 @@ export function has_color_property(mat) {
10
10
  if (!(`color` in mat))
11
11
  return false;
12
12
  const color = mat.color;
13
- // Check for Color-like object with r, g, b properties (duck typing)
14
- return (color !== null &&
15
- typeof color === `object` &&
16
- `r` in color &&
17
- `g` in color &&
18
- `b` in color &&
19
- typeof color.r === `number`);
13
+ if (!color || typeof color !== `object`)
14
+ return false;
15
+ // Check for Color-like object with numeric r/g/b channels (duck typing)
16
+ const color_obj = color;
17
+ const red_channel = color_obj.r;
18
+ const green_channel = color_obj.g;
19
+ const blue_channel = color_obj.b;
20
+ return (typeof red_channel === `number` &&
21
+ typeof green_channel === `number` &&
22
+ typeof blue_channel === `number`);
20
23
  }
21
24
  // Extract color from a ShaderMaterial by checking common color uniform patterns
22
25
  function extract_shader_color(shader_mat) {
@@ -126,9 +129,7 @@ export function generate_mtl_content(scene) {
126
129
  lines.push(`Ks 0.500000 0.500000 0.500000`);
127
130
  lines.push(`Ns 96.078431`); // Specular exponent
128
131
  // Transparency (d = 1.0 is fully opaque)
129
- const opacity = `opacity` in mat && typeof mat.opacity === `number`
130
- ? mat.opacity
131
- : 1.0;
132
+ const opacity = `opacity` in mat && typeof mat.opacity === `number` ? mat.opacity : 1.0;
132
133
  lines.push(`d ${opacity.toFixed(6)}`);
133
134
  // Illumination model (2 = highlight on)
134
135
  lines.push(`illum 2`);
@@ -148,7 +149,7 @@ function extract_material_color(mat) {
148
149
  // This is necessary because GLB/OBJ exporters don't handle InstancedMesh properly
149
150
  // Note: Threlte's InstancedMesh sets isInstancedMesh=true but type remains "Mesh"
150
151
  // Type guard for InstancedMesh (Three.js uses isInstancedMesh property, not exposed in Object3D type)
151
- const is_instanced_mesh = (obj) => obj.isInstancedMesh === true || obj.type === `InstancedMesh`;
152
+ const is_instanced_mesh = (obj) => obj.isInstancedMesh || obj.type === `InstancedMesh`;
152
153
  function convert_instanced_meshes_to_regular(scene) {
153
154
  // STEP 1: Collect material colors from ORIGINAL scene BEFORE cloning
154
155
  // This is crucial because scene.clone() may not properly preserve Threlte's material colors
@@ -354,16 +355,14 @@ export function structure_to_xyz_str(structure) {
354
355
  if (formula && formula !== `Unknown`)
355
356
  comment_parts.push(formula);
356
357
  // Include extended XYZ lattice information when available so round-trips preserve lattice
357
- if ((`lattice` in structure) && structure.lattice?.matrix?.length === 3) {
358
+ if (`lattice` in structure && structure.lattice?.matrix?.length === 3) {
358
359
  const lattice_values = structure.lattice.matrix
359
360
  .flat()
360
361
  .map((value) => (Number.isFinite(value) ? value : 0).toFixed(8))
361
362
  .join(` `);
362
363
  comment_parts.push(`Lattice="${lattice_values}"`);
363
364
  }
364
- const comment = comment_parts.length > 0
365
- ? comment_parts.join(` `)
366
- : `Generated from structure`;
365
+ const comment = comment_parts.length > 0 ? comment_parts.join(` `) : `Generated from structure`;
367
366
  lines.push(comment);
368
367
  // Cache converter for fractional→Cartesian (if lattice available)
369
368
  const frac_to_cart = `lattice` in structure && structure.lattice?.matrix?.length === 3
@@ -373,9 +372,7 @@ export function structure_to_xyz_str(structure) {
373
372
  for (const site of structure.sites) {
374
373
  // Extract element symbol from species
375
374
  let element_symbol = `X`; // default fallback
376
- if (site.species &&
377
- Array.isArray(site.species) &&
378
- site.species.length > 0) {
375
+ if (site.species && Array.isArray(site.species) && site.species.length > 0) {
379
376
  // species is an array of Species objects with element property
380
377
  const first_species = site.species[0];
381
378
  if (first_species && `element` in first_species && first_species.element)
@@ -466,7 +463,8 @@ export function structure_to_cif_str(structure) {
466
463
  lines.push(`_cell_angle_gamma ${lattice.gamma.toFixed(6)}`);
467
464
  }
468
465
  // Space group information
469
- if (`symmetry` in structure && structure.symmetry &&
466
+ if (`symmetry` in structure &&
467
+ structure.symmetry &&
470
468
  typeof structure.symmetry === `object`) {
471
469
  const symmetry = structure.symmetry;
472
470
  if (`space_group_symbol` in symmetry && symmetry.space_group_symbol) {
@@ -486,9 +484,7 @@ export function structure_to_cif_str(structure) {
486
484
  lines.push(`_atom_site_fract_z`);
487
485
  lines.push(`_atom_site_occupancy`);
488
486
  // Cache inverse transpose for Cartesian→fractional conversion (avoids recomputing per site)
489
- const cart_to_frac = lattice.matrix?.length === 3
490
- ? math.create_cart_to_frac(lattice.matrix)
491
- : null;
487
+ const cart_to_frac = lattice.matrix?.length === 3 ? math.create_cart_to_frac(lattice.matrix) : null;
492
488
  // Atom sites
493
489
  for (let idx = 0; idx < structure.sites.length; idx++) {
494
490
  const site = structure.sites[idx];
@@ -497,9 +493,7 @@ export function structure_to_cif_str(structure) {
497
493
  // Extract element symbol from species
498
494
  let element_symbol = `X`; // default fallback
499
495
  let occupancy = 1;
500
- if (site.species &&
501
- Array.isArray(site.species) &&
502
- site.species.length > 0) {
496
+ if (site.species && Array.isArray(site.species) && site.species.length > 0) {
503
497
  const first_species = site.species[0];
504
498
  if (first_species && `element` in first_species && first_species.element) {
505
499
  element_symbol = first_species.element;
@@ -553,9 +547,7 @@ export function structure_to_poscar_str(structure) {
553
547
  const element_symbols = [];
554
548
  for (const site of structure.sites) {
555
549
  let element_symbol = `X`; // default fallback
556
- if (site.species &&
557
- Array.isArray(site.species) &&
558
- site.species.length > 0) {
550
+ if (site.species && Array.isArray(site.species) && site.species.length > 0) {
559
551
  const first_species = site.species[0];
560
552
  if (first_species && `element` in first_species && first_species.element) {
561
553
  element_symbol = first_species.element;
@@ -579,16 +571,12 @@ export function structure_to_poscar_str(structure) {
579
571
  // Coordinate mode (Direct = fractional coordinates)
580
572
  lines.push(`Direct`);
581
573
  // Cache inverse transpose for Cartesian→fractional conversion (avoids recomputing per site)
582
- const cart_to_frac = lattice.matrix?.length === 3
583
- ? math.create_cart_to_frac(lattice.matrix)
584
- : null;
574
+ const cart_to_frac = lattice.matrix?.length === 3 ? math.create_cart_to_frac(lattice.matrix) : null;
585
575
  // Atom coordinates grouped by element
586
576
  for (const element_symbol of element_symbols) {
587
577
  for (const site of structure.sites) {
588
578
  let site_element = `X`;
589
- if (site.species &&
590
- Array.isArray(site.species) &&
591
- site.species.length > 0) {
579
+ if (site.species && Array.isArray(site.species) && site.species.length > 0) {
592
580
  const first_species = site.species[0];
593
581
  if (first_species && `element` in first_species && first_species.element) {
594
582
  site_element = first_species.element;
@@ -1,3 +1,4 @@
1
+ import type { Vec3 } from '../math';
1
2
  export type WasmResult<T> = {
2
3
  ok: T;
3
4
  } | {
@@ -14,7 +15,7 @@ export declare function unwrap_or<T>(result: WasmResult<T>, default_value: T): T
14
15
  export interface NeighborListResult {
15
16
  center_indices: number[];
16
17
  neighbor_indices: number[];
17
- image_offsets: [number, number, number][];
18
+ image_offsets: Vec3[];
18
19
  distances: number[];
19
20
  }
20
21
  export interface MatcherOptions {
@@ -28,7 +29,7 @@ export interface MatcherOptions {
28
29
  export type StructureFormat = `cif` | `poscar` | `json`;
29
30
  export type ReductionAlgorithm = `niggli` | `lll`;
30
31
  export interface HklInfo {
31
- hkl: [number, number, number];
32
+ hkl: Vec3;
32
33
  multiplicity: number;
33
34
  }
34
35
  export interface XrdPattern {
@@ -1,6 +1,3 @@
1
- // Pure type definitions and utility functions for ferrox-wasm results.
2
- // This module has no WASM side effects, making it safe to import in tests
3
- // without triggering WASM resolution.
4
1
  // Type guard to check if result is successful
5
2
  export function is_ok(result) {
6
3
  return `ok` in result;
@@ -1,3 +1,4 @@
1
+ import type { Vec3 } from '../math';
1
2
  import type { Crystal } from './';
2
3
  import type { MatcherOptions, NeighborListResult, ReductionAlgorithm, StructureFormat, WasmResult, XrdOptions, XrdPattern } from './ferrox-wasm-types';
3
4
  export * from './ferrox-wasm-types';
@@ -81,8 +82,8 @@ export declare function interpolate_structures(start: Crystal, end: Crystal, n_i
81
82
  }): Promise<WasmResult<Crystal[]>>;
82
83
  export declare function copy_structure(structure: Crystal, sanitize?: boolean): Promise<WasmResult<Crystal>>;
83
84
  export declare function wrap_to_unit_cell(structure: Crystal): Promise<WasmResult<Crystal>>;
84
- export declare function create_supercell_matrix(structure: Crystal, matrix: [[number, number, number], [number, number, number], [number, number, number]]): Promise<WasmResult<Crystal>>;
85
- export declare function translate_sites(structure: Crystal, indices: number[], vector: [number, number, number], frac_coords?: boolean): Promise<WasmResult<Crystal>>;
85
+ export declare function create_supercell_matrix(structure: Crystal, matrix: [Vec3, Vec3, Vec3]): Promise<WasmResult<Crystal>>;
86
+ export declare function translate_sites(structure: Crystal, indices: number[], vector: Vec3, frac_coords?: boolean): Promise<WasmResult<Crystal>>;
86
87
  export declare function perturb_structure(structure: Crystal, distance: number, options?: {
87
88
  min_distance?: number;
88
89
  seed?: number;
@@ -25,8 +25,7 @@ export function ensure_ferrox_wasm_ready() {
25
25
  init_promise = (async () => {
26
26
  try {
27
27
  // Dynamic import to avoid loading WASM until needed
28
- const { default: init } = (await import(
29
- /* @vite-ignore */ `matterviz-wasm`));
28
+ const { default: init } = (await import(`matterviz-wasm`));
30
29
  // Initialize WASM module (the package handles WASM loading internally)
31
30
  wasm_module = await init();
32
31
  return wasm_module;
@@ -34,7 +33,7 @@ export function ensure_ferrox_wasm_ready() {
34
33
  catch (err) {
35
34
  // Clear the promise on failure so retry is possible
36
35
  init_promise = null;
37
- throw new Error(`Failed to load matterviz-wasm. Install with: pnpm add matterviz-wasm. Original error: ${err}`);
36
+ throw new Error(`Failed to load matterviz-wasm. Install with: npm add matterviz-wasm. Original error: ${err}`, { cause: err });
38
37
  }
39
38
  })();
40
39
  }
@@ -67,6 +67,21 @@ export declare function format_formula_by_electronegativity(structure: AnyStruct
67
67
  export declare const atomic_radii: CompositionType;
68
68
  export declare function get_density(structure: Crystal): number;
69
69
  export declare function get_center_of_mass(structure: AnyStructure): Vec3;
70
+ export declare const VECTOR_KEY_PREFIXES: readonly ["force", "forces", "magmom", "magmoms", "spin", "spins"];
71
+ export declare function is_vector_key(key: string): boolean;
72
+ export declare const VECTOR_PALETTE: readonly ["#e74c3c", "#3498db", "#2ecc71", "#f39c12", "#9b59b6", "#1abc9c"];
73
+ export declare const default_vector_configs: (keys: string[]) => {
74
+ [k: string]: {
75
+ visible: boolean;
76
+ color: "#e74c3c" | "#3498db" | "#2ecc71" | "#f39c12" | "#9b59b6" | "#1abc9c" | null;
77
+ scale: null;
78
+ };
79
+ };
80
+ export declare function get_all_site_vectors(site: Site): {
81
+ vec: Vec3;
82
+ key: string;
83
+ }[];
84
+ export declare function get_structure_vector_keys(structure: AnyStructure): string[];
70
85
  export interface StructureHandlerData {
71
86
  structure?: AnyStructure;
72
87
  filename?: string;
@@ -75,6 +90,7 @@ export interface StructureHandlerData {
75
90
  error_msg?: string;
76
91
  fullscreen?: boolean;
77
92
  camera_position?: Vec3;
93
+ camera_target?: Vec3;
78
94
  camera_has_moved?: boolean;
79
95
  color_scheme?: string;
80
96
  performance_mode?: `quality` | `speed`;
@@ -42,16 +42,14 @@ export function format_chemical_formula(structure, sort_fn) {
42
42
  }
43
43
  export function format_formula_by_electronegativity(structure) {
44
44
  // concatenate elements in a structure followed by their amount sorted by electronegativity
45
- return format_chemical_formula(structure, (symbols) => (symbols.sort((el1, el2) => {
46
- const elec_neg1 = element_data.find((el) => el.symbol === el1)?.electronegativity ??
47
- 0;
48
- const elec_neg2 = element_data.find((el) => el.symbol === el2)?.electronegativity ??
49
- 0;
45
+ return format_chemical_formula(structure, (symbols) => symbols.sort((el1, el2) => {
46
+ const elec_neg1 = element_data.find((el) => el.symbol === el1)?.electronegativity ?? 0;
47
+ const elec_neg2 = element_data.find((el) => el.symbol === el2)?.electronegativity ?? 0;
50
48
  // Sort by electronegativity (ascending), then alphabetically for ties
51
49
  if (elec_neg1 !== elec_neg2)
52
50
  return elec_neg1 - elec_neg2;
53
51
  return el1.localeCompare(el2);
54
- })));
52
+ }));
55
53
  }
56
54
  // Atomic radii in Angstroms (used for relative sizing, not absolute rendering scale)
57
55
  export const atomic_radii = Object.fromEntries(element_data.map((el) => [el.symbol, el.atomic_radius ?? 1]));
@@ -84,3 +82,87 @@ export function get_center_of_mass(structure) {
84
82
  }
85
83
  return math.scale(center, 1 / total_weight);
86
84
  }
85
+ // Recognized prefixes for per-site vector data (force, magnetic moment, spin).
86
+ // Both singular and plural forms are accepted. Keys matching exactly or starting
87
+ // with one of these followed by `_` (e.g. `force_DFT`) are treated as vectors.
88
+ export const VECTOR_KEY_PREFIXES = [
89
+ `force`,
90
+ `forces`,
91
+ `magmom`,
92
+ `magmoms`,
93
+ `spin`,
94
+ `spins`,
95
+ ];
96
+ export function is_vector_key(key) {
97
+ return VECTOR_KEY_PREFIXES.some((prefix) => key === prefix || key.startsWith(`${prefix}_`));
98
+ }
99
+ // Default color palette for distinguishing multiple vector layers
100
+ export const VECTOR_PALETTE = [
101
+ `#e74c3c`,
102
+ `#3498db`,
103
+ `#2ecc71`,
104
+ `#f39c12`,
105
+ `#9b59b6`,
106
+ `#1abc9c`,
107
+ ];
108
+ // Single key → null color (semantic coloring); multiple keys → palette colors.
109
+ export const default_vector_configs = (keys) => Object.fromEntries(keys.map((key, idx) => [
110
+ key,
111
+ {
112
+ visible: true,
113
+ color: keys.length > 1 ? VECTOR_PALETTE[idx % VECTOR_PALETTE.length] : null,
114
+ scale: null,
115
+ },
116
+ ]));
117
+ function try_parse_vec3(val) {
118
+ if (Array.isArray(val) &&
119
+ val.length === 3 &&
120
+ val.every((elem) => typeof elem === `number` && isFinite(elem)))
121
+ return val;
122
+ if (typeof val === `number` && isFinite(val))
123
+ return [0, 0, val];
124
+ return null;
125
+ }
126
+ // Priority index for ordering: bare names first in VECTOR_KEY_PREFIXES order,
127
+ // then prefixed keys in the same prefix order, alphabetically within each prefix group.
128
+ function vector_key_sort_order(key) {
129
+ for (const [prefix_idx, prefix] of VECTOR_KEY_PREFIXES.entries()) {
130
+ if (key === prefix)
131
+ return [prefix_idx, 0, ``];
132
+ if (key.startsWith(`${prefix}_`))
133
+ return [prefix_idx, 1, key];
134
+ }
135
+ return [VECTOR_KEY_PREFIXES.length, 0, key];
136
+ }
137
+ function compare_vector_keys(left, right) {
138
+ const ord_l = vector_key_sort_order(left);
139
+ const ord_r = vector_key_sort_order(right);
140
+ return ord_l[0] - ord_r[0] || ord_l[1] - ord_r[1] || ord_l[2].localeCompare(ord_r[2]);
141
+ }
142
+ // Extract ALL vector properties from a site (not just the first match).
143
+ // Returns entries for every key that is_vector_key() and has a valid 3D vector value.
144
+ // Ordered by VECTOR_KEY_PREFIXES priority, then alphabetically for prefixed keys.
145
+ export function get_all_site_vectors(site) {
146
+ const props = site.properties;
147
+ if (!props)
148
+ return [];
149
+ const results = [];
150
+ for (const key of Object.keys(props)) {
151
+ if (!is_vector_key(key))
152
+ continue;
153
+ const vec = try_parse_vec3(props[key]);
154
+ if (vec)
155
+ results.push({ vec, key });
156
+ }
157
+ return results.sort((left, right) => compare_vector_keys(left.key, right.key));
158
+ }
159
+ // Collect the union of all vector property keys across all sites in a structure,
160
+ // preserving VECTOR_KEY_PREFIXES priority order.
161
+ export function get_structure_vector_keys(structure) {
162
+ const seen = new Set();
163
+ for (const site of structure.sites) {
164
+ for (const { key } of get_all_site_vectors(site))
165
+ seen.add(key);
166
+ }
167
+ return [...seen].sort(compare_vector_keys);
168
+ }
@@ -1,6 +1,6 @@
1
- import type { Matrix3x3, Vec3 } from '../math';
1
+ import type { LatticeConverters, Matrix3x3, Vec3 } from '../math';
2
2
  export type AngleMode = `degrees` | `radians`;
3
3
  export declare const MAX_SELECTED_SITES = 8;
4
- export declare function displacement_pbc(from: Vec3, to: Vec3, lattice_matrix: Matrix3x3 | null | undefined, lattice_inv?: Matrix3x3): Vec3;
4
+ export declare function displacement_pbc(from: Vec3, to: Vec3, lattice_matrix: Matrix3x3 | null | undefined, converters?: LatticeConverters): Vec3;
5
5
  export declare function distance_pbc(a: Vec3, b: Vec3, lattice_matrix: Matrix3x3): number;
6
6
  export declare function angle_between_vectors(v1: Vec3, v2: Vec3, mode?: AngleMode): number;
@@ -1,55 +1,15 @@
1
1
  // functions for measuring distances and angles between structure sites
2
- import { mat3x3_vec3_multiply, matrix_inverse_3x3, subtract } from '../math';
2
+ import { min_image_displacement, subtract } from '../math';
3
3
  export const MAX_SELECTED_SITES = 8;
4
4
  // Calculate minimum image displacement between two points under PBC
5
5
  // If lattice_matrix is null/undefined, returns Euclidean displacement
6
- export function displacement_pbc(from, to, lattice_matrix, lattice_inv) {
7
- // For non-periodic structures, return direct displacement
6
+ export function displacement_pbc(from, to, lattice_matrix, converters) {
8
7
  if (!lattice_matrix)
9
8
  return subtract(to, from);
10
- const inv_mat = lattice_inv ?? matrix_inverse_3x3(lattice_matrix);
11
- const frac_from = mat3x3_vec3_multiply(inv_mat, from);
12
- const frac_to = mat3x3_vec3_multiply(inv_mat, to);
13
- // Wrap fractional coordinates to [0,1) for easier boundary checking
14
- const frac_from_wrapped = [
15
- frac_from[0] - Math.floor(frac_from[0]),
16
- frac_from[1] - Math.floor(frac_from[1]),
17
- frac_from[2] - Math.floor(frac_from[2]),
18
- ];
19
- const frac_to_wrapped = [
20
- frac_to[0] - Math.floor(frac_to[0]),
21
- frac_to[1] - Math.floor(frac_to[1]),
22
- frac_to[2] - Math.floor(frac_to[2]),
23
- ];
24
- // Find minimum image by testing all nearby lattice translations
25
- let min_dist_sq = Infinity;
26
- let best_displacement = [0, 0, 0];
27
- // Test lattice images in a 3x3x3 neighborhood (sufficient for minimum image)
28
- for (let ii = -1; ii <= 1; ii++) {
29
- for (let jj = -1; jj <= 1; jj++) {
30
- for (let kk = -1; kk <= 1; kk++) {
31
- // Fractional displacement with lattice translation
32
- const frac_diff = [
33
- frac_to_wrapped[0] - frac_from_wrapped[0] + ii,
34
- frac_to_wrapped[1] - frac_from_wrapped[1] + jj,
35
- frac_to_wrapped[2] - frac_from_wrapped[2] + kk,
36
- ];
37
- // Convert to cartesian
38
- const cart_diff = mat3x3_vec3_multiply(lattice_matrix, frac_diff);
39
- const dist_sq = cart_diff[0] ** 2 + cart_diff[1] ** 2 + cart_diff[2] ** 2;
40
- // Keep the shortest displacement
41
- if (dist_sq < min_dist_sq) {
42
- min_dist_sq = dist_sq;
43
- best_displacement = cart_diff;
44
- }
45
- }
46
- }
47
- }
48
- return best_displacement;
9
+ return min_image_displacement(from, to, lattice_matrix, converters);
49
10
  }
50
11
  export function distance_pbc(a, b, lattice_matrix) {
51
- const inv_mat = matrix_inverse_3x3(lattice_matrix);
52
- const [dx, dy, dz] = displacement_pbc(a, b, lattice_matrix, inv_mat);
12
+ const [dx, dy, dz] = displacement_pbc(a, b, lattice_matrix);
53
13
  return Math.hypot(dx, dy, dz);
54
14
  }
55
15
  export function angle_between_vectors(v1, v2, mode = `degrees`) {