matterviz 0.3.6 → 0.4.0

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 (926) hide show
  1. package/dist/EmptyState.svelte.d.ts +9 -0
  2. package/dist/FilePicker.svelte +360 -0
  3. package/dist/FilePicker.svelte.d.ts +17 -0
  4. package/dist/Icon.svelte +44 -0
  5. package/dist/Icon.svelte.d.ts +13 -0
  6. package/dist/MillerIndexInput.svelte +66 -0
  7. package/dist/MillerIndexInput.svelte.d.ts +7 -0
  8. package/dist/api/mp.d.ts +6 -0
  9. package/dist/api/mp.js +22 -0
  10. package/dist/api/optimade.d.ts +45 -0
  11. package/dist/api/optimade.js +141 -0
  12. package/dist/app.css +244 -0
  13. package/dist/brillouin/BrillouinZone.svelte +554 -0
  14. package/dist/brillouin/BrillouinZone.svelte.d.ts +84 -0
  15. package/dist/brillouin/BrillouinZoneControls.svelte +144 -0
  16. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +17 -0
  17. package/dist/brillouin/BrillouinZoneExportPane.svelte +146 -0
  18. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +15 -0
  19. package/dist/brillouin/BrillouinZoneInfoPane.svelte +146 -0
  20. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +13 -0
  21. package/dist/brillouin/BrillouinZoneScene.svelte +522 -0
  22. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +49 -0
  23. package/dist/brillouin/BrillouinZoneTooltip.svelte +83 -0
  24. package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +8 -0
  25. package/dist/brillouin/compute.d.ts +17 -0
  26. package/dist/brillouin/compute.js +422 -0
  27. package/dist/brillouin/index.d.ts +8 -0
  28. package/dist/brillouin/index.js +7 -0
  29. package/dist/brillouin/types.d.ts +43 -0
  30. package/dist/brillouin/types.js +1 -0
  31. package/dist/chempot-diagram/ChemPotDiagram.svelte +328 -0
  32. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  33. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +843 -0
  34. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  35. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3191 -0
  36. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  37. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  38. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  39. package/dist/chempot-diagram/async-compute.svelte.js +80 -0
  40. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  41. package/dist/chempot-diagram/chempot-worker.js +12 -0
  42. package/dist/chempot-diagram/color.d.ts +10 -0
  43. package/dist/chempot-diagram/color.js +32 -0
  44. package/dist/chempot-diagram/compute.d.ts +48 -0
  45. package/dist/chempot-diagram/compute.js +804 -0
  46. package/dist/chempot-diagram/index.d.ts +6 -0
  47. package/dist/chempot-diagram/index.js +6 -0
  48. package/dist/chempot-diagram/pointer.d.ts +16 -0
  49. package/dist/chempot-diagram/pointer.js +40 -0
  50. package/dist/chempot-diagram/temperature.d.ts +15 -0
  51. package/dist/chempot-diagram/temperature.js +34 -0
  52. package/dist/chempot-diagram/types.d.ts +81 -0
  53. package/dist/chempot-diagram/types.js +28 -0
  54. package/dist/colors/index.d.ts +47 -0
  55. package/dist/colors/index.js +204 -0
  56. package/dist/composition/BarChart.svelte +297 -0
  57. package/dist/composition/BarChart.svelte.d.ts +39 -0
  58. package/dist/composition/BubbleChart.svelte +218 -0
  59. package/dist/composition/BubbleChart.svelte.d.ts +28 -0
  60. package/dist/composition/Composition.svelte +165 -0
  61. package/dist/composition/Composition.svelte.d.ts +15 -0
  62. package/dist/composition/Formula.svelte +268 -0
  63. package/dist/composition/Formula.svelte.d.ts +19 -0
  64. package/dist/composition/FormulaFilter.svelte +1263 -0
  65. package/dist/composition/FormulaFilter.svelte.d.ts +51 -0
  66. package/dist/composition/PieChart.svelte +324 -0
  67. package/dist/composition/PieChart.svelte.d.ts +37 -0
  68. package/dist/composition/chem-sys.d.ts +8 -0
  69. package/dist/composition/chem-sys.js +85 -0
  70. package/dist/composition/format.d.ts +15 -0
  71. package/dist/composition/format.js +111 -0
  72. package/dist/composition/index.d.ts +21 -0
  73. package/dist/composition/index.js +15 -0
  74. package/dist/composition/parse.d.ts +56 -0
  75. package/dist/composition/parse.js +486 -0
  76. package/dist/constants.d.ts +29 -0
  77. package/dist/constants.js +99 -0
  78. package/dist/controls.d.ts +14 -0
  79. package/dist/controls.js +30 -0
  80. package/dist/convex-hull/ConvexHull.svelte +157 -0
  81. package/dist/convex-hull/ConvexHull.svelte.d.ts +13 -0
  82. package/dist/convex-hull/ConvexHull2D.svelte +827 -0
  83. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +11 -0
  84. package/dist/convex-hull/ConvexHull3D.svelte +1801 -0
  85. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +8 -0
  86. package/dist/convex-hull/ConvexHull4D.svelte +1394 -0
  87. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +8 -0
  88. package/dist/convex-hull/ConvexHullControls.svelte +535 -0
  89. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +48 -0
  90. package/dist/convex-hull/ConvexHullInfoPane.svelte +125 -0
  91. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +20 -0
  92. package/dist/convex-hull/ConvexHullStats.svelte +929 -0
  93. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +17 -0
  94. package/dist/convex-hull/ConvexHullTooltip.svelte +131 -0
  95. package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +33 -0
  96. package/dist/convex-hull/GasPressureControls.svelte +247 -0
  97. package/dist/convex-hull/GasPressureControls.svelte.d.ts +11 -0
  98. package/dist/convex-hull/StructurePopup.svelte +151 -0
  99. package/dist/convex-hull/StructurePopup.svelte.d.ts +18 -0
  100. package/dist/convex-hull/TemperatureSlider.svelte +140 -0
  101. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +8 -0
  102. package/dist/convex-hull/barycentric-coords.d.ts +18 -0
  103. package/dist/convex-hull/barycentric-coords.js +182 -0
  104. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  105. package/dist/convex-hull/demo-temperature.js +38 -0
  106. package/dist/convex-hull/gas-thermodynamics.d.ts +16 -0
  107. package/dist/convex-hull/gas-thermodynamics.js +306 -0
  108. package/dist/convex-hull/helpers.d.ts +117 -0
  109. package/dist/convex-hull/helpers.js +718 -0
  110. package/dist/convex-hull/index.d.ts +119 -0
  111. package/dist/convex-hull/index.js +58 -0
  112. package/dist/convex-hull/thermodynamics.d.ts +67 -0
  113. package/dist/convex-hull/thermodynamics.js +1757 -0
  114. package/dist/convex-hull/types.d.ts +162 -0
  115. package/dist/convex-hull/types.js +36 -0
  116. package/dist/coordination/CoordinationBarPlot.svelte +311 -0
  117. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +30 -0
  118. package/dist/coordination/calc-coordination.d.ts +15 -0
  119. package/dist/coordination/calc-coordination.js +63 -0
  120. package/dist/coordination/index.d.ts +8 -0
  121. package/dist/coordination/index.js +7 -0
  122. package/dist/effects.svelte.d.ts +12 -0
  123. package/dist/effects.svelte.js +37 -0
  124. package/dist/element/BohrAtom.svelte.d.ts +20 -0
  125. package/dist/element/ElementHeading.svelte +26 -0
  126. package/dist/element/ElementHeading.svelte.d.ts +8 -0
  127. package/dist/element/ElementPhoto.svelte +57 -0
  128. package/dist/element/ElementPhoto.svelte.d.ts +9 -0
  129. package/dist/element/ElementStats.svelte +80 -0
  130. package/dist/element/ElementStats.svelte.d.ts +8 -0
  131. package/dist/element/ElementTile.svelte +484 -0
  132. package/dist/element/ElementTile.svelte.d.ts +29 -0
  133. package/dist/element/Nucleus.svelte.d.ts +17 -0
  134. package/dist/element/data.d.ts +2 -0
  135. package/dist/element/data.js +2 -0
  136. package/dist/element/index.d.ts +8 -0
  137. package/dist/element/index.js +7 -0
  138. package/dist/element/types.d.ts +57 -0
  139. package/dist/element/types.js +1 -0
  140. package/dist/feedback/ClickFeedback.svelte +58 -0
  141. package/dist/feedback/ClickFeedback.svelte.d.ts +12 -0
  142. package/dist/feedback/DragOverlay.svelte +42 -0
  143. package/dist/feedback/DragOverlay.svelte.d.ts +7 -0
  144. package/dist/feedback/Spinner.svelte.d.ts +7 -0
  145. package/dist/feedback/StatusMessage.svelte.d.ts +9 -0
  146. package/dist/feedback/index.d.ts +4 -0
  147. package/dist/feedback/index.js +4 -0
  148. package/dist/fermi-surface/FermiSlice.svelte +197 -0
  149. package/dist/fermi-surface/FermiSlice.svelte.d.ts +24 -0
  150. package/dist/fermi-surface/FermiSurface.svelte +606 -0
  151. package/dist/fermi-surface/FermiSurface.svelte.d.ts +83 -0
  152. package/dist/fermi-surface/FermiSurfaceControls.svelte +448 -0
  153. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +35 -0
  154. package/dist/fermi-surface/FermiSurfaceScene.svelte +797 -0
  155. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +50 -0
  156. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +85 -0
  157. package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +8 -0
  158. package/dist/fermi-surface/compute.d.ts +5 -0
  159. package/dist/fermi-surface/compute.js +538 -0
  160. package/dist/fermi-surface/constants.d.ts +9 -0
  161. package/dist/fermi-surface/constants.js +27 -0
  162. package/dist/fermi-surface/export.d.ts +5 -0
  163. package/dist/fermi-surface/export.js +51 -0
  164. package/dist/fermi-surface/index.d.ts +12 -0
  165. package/dist/fermi-surface/index.js +13 -0
  166. package/dist/fermi-surface/marching-cubes.d.ts +2 -0
  167. package/dist/fermi-surface/marching-cubes.js +2 -0
  168. package/dist/fermi-surface/parse.d.ts +2 -0
  169. package/dist/fermi-surface/parse.js +494 -0
  170. package/dist/fermi-surface/symmetry.d.ts +3 -0
  171. package/dist/fermi-surface/symmetry.js +46 -0
  172. package/dist/fermi-surface/types.d.ts +111 -0
  173. package/dist/fermi-surface/types.js +4 -0
  174. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1547 -0
  175. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  176. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
  177. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
  178. package/dist/heatmap-matrix/index.d.ts +53 -0
  179. package/dist/heatmap-matrix/index.js +100 -0
  180. package/dist/heatmap-matrix/shared.d.ts +2 -0
  181. package/dist/heatmap-matrix/shared.js +4 -0
  182. package/dist/icons.d.ts +569 -0
  183. package/dist/icons.js +648 -0
  184. package/dist/index.d.ts +39 -0
  185. package/dist/index.js +39 -0
  186. package/dist/io/decompress.d.ts +11 -0
  187. package/dist/io/decompress.js +76 -0
  188. package/dist/io/export.d.ts +16 -0
  189. package/dist/io/export.js +338 -0
  190. package/dist/io/fetch.d.ts +5 -0
  191. package/dist/io/fetch.js +43 -0
  192. package/dist/io/file-drop.d.ts +7 -0
  193. package/dist/io/file-drop.js +42 -0
  194. package/dist/io/index.d.ts +7 -0
  195. package/dist/io/index.js +6 -0
  196. package/dist/io/is-binary.d.ts +1 -0
  197. package/dist/io/is-binary.js +20 -0
  198. package/dist/io/types.d.ts +8 -0
  199. package/dist/io/types.js +1 -0
  200. package/dist/io/url-drop.d.ts +2 -0
  201. package/dist/io/url-drop.js +154 -0
  202. package/dist/isosurface/Isosurface.svelte +285 -0
  203. package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
  204. package/dist/isosurface/IsosurfaceControls.svelte +277 -0
  205. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
  206. package/dist/isosurface/index.d.ts +5 -0
  207. package/dist/isosurface/index.js +6 -0
  208. package/dist/isosurface/parse.d.ts +6 -0
  209. package/dist/isosurface/parse.js +552 -0
  210. package/dist/isosurface/slice.d.ts +11 -0
  211. package/dist/isosurface/slice.js +141 -0
  212. package/dist/isosurface/types.d.ts +56 -0
  213. package/dist/isosurface/types.js +227 -0
  214. package/dist/keyboard.d.ts +3 -0
  215. package/dist/keyboard.js +23 -0
  216. package/dist/labels.d.ts +53 -0
  217. package/dist/labels.js +278 -0
  218. package/dist/layout/FullscreenToggle.svelte +50 -0
  219. package/dist/layout/FullscreenToggle.svelte.d.ts +7 -0
  220. package/dist/layout/InfoCard.svelte +120 -0
  221. package/dist/layout/InfoCard.svelte.d.ts +21 -0
  222. package/dist/layout/InfoTag.svelte +185 -0
  223. package/dist/layout/InfoTag.svelte.d.ts +19 -0
  224. package/dist/layout/PropertyFilter.svelte +247 -0
  225. package/dist/layout/PropertyFilter.svelte.d.ts +24 -0
  226. package/dist/layout/SettingsSection.svelte +148 -0
  227. package/dist/layout/SettingsSection.svelte.d.ts +17 -0
  228. package/dist/layout/SubpageGrid.svelte +82 -0
  229. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  230. package/dist/layout/fullscreen.d.ts +9 -0
  231. package/dist/layout/fullscreen.js +53 -0
  232. package/dist/layout/index.d.ts +10 -0
  233. package/dist/layout/index.js +8 -0
  234. package/dist/layout/json-tree/JsonNode.svelte +548 -0
  235. package/dist/layout/json-tree/JsonNode.svelte.d.ts +11 -0
  236. package/dist/layout/json-tree/JsonTree.svelte +1230 -0
  237. package/dist/layout/json-tree/JsonTree.svelte.d.ts +6 -0
  238. package/dist/layout/json-tree/JsonValue.svelte.d.ts +9 -0
  239. package/dist/layout/json-tree/index.d.ts +3 -0
  240. package/dist/layout/json-tree/index.js +3 -0
  241. package/dist/layout/json-tree/types.d.ts +74 -0
  242. package/dist/layout/json-tree/types.js +2 -0
  243. package/dist/layout/json-tree/utils.d.ts +29 -0
  244. package/dist/layout/json-tree/utils.js +642 -0
  245. package/dist/marching-cubes.d.ts +14 -0
  246. package/dist/marching-cubes.js +535 -0
  247. package/dist/math.d.ts +105 -0
  248. package/dist/math.js +920 -0
  249. package/dist/overlays/ContextMenu.svelte +162 -0
  250. package/dist/overlays/ContextMenu.svelte.d.ts +25 -0
  251. package/dist/overlays/CopyButton.svelte +45 -0
  252. package/dist/overlays/CopyButton.svelte.d.ts +8 -0
  253. package/dist/overlays/DragControlTab.svelte +98 -0
  254. package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
  255. package/dist/overlays/DraggablePane.svelte +487 -0
  256. package/dist/overlays/DraggablePane.svelte.d.ts +36 -0
  257. package/dist/overlays/InfoPaneCards.svelte +149 -0
  258. package/dist/overlays/InfoPaneCards.svelte.d.ts +22 -0
  259. package/dist/overlays/index.d.ts +3 -0
  260. package/dist/overlays/index.js +3 -0
  261. package/dist/periodic-table/PeriodicTable.svelte +480 -0
  262. package/dist/periodic-table/PeriodicTable.svelte.d.ts +55 -0
  263. package/dist/periodic-table/PeriodicTableControls.svelte +557 -0
  264. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +24 -0
  265. package/dist/periodic-table/PropertySelect.svelte +38 -0
  266. package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
  267. package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
  268. package/dist/periodic-table/index.d.ts +10 -0
  269. package/dist/periodic-table/index.js +4 -0
  270. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1092 -0
  271. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +44 -0
  272. package/dist/phase-diagram/PhaseDiagramControls.svelte +444 -0
  273. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +30 -0
  274. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +127 -0
  275. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  276. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
  277. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +19 -0
  278. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
  279. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +16 -0
  280. package/dist/phase-diagram/TdbInfoPanel.svelte +203 -0
  281. package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +12 -0
  282. package/dist/phase-diagram/build-diagram.d.ts +11 -0
  283. package/dist/phase-diagram/build-diagram.js +160 -0
  284. package/dist/phase-diagram/colors.d.ts +35 -0
  285. package/dist/phase-diagram/colors.js +51 -0
  286. package/dist/phase-diagram/diagram-input.d.ts +29 -0
  287. package/dist/phase-diagram/diagram-input.js +3 -0
  288. package/dist/phase-diagram/index.d.ts +13 -0
  289. package/dist/phase-diagram/index.js +11 -0
  290. package/dist/phase-diagram/parse.d.ts +55 -0
  291. package/dist/phase-diagram/parse.js +273 -0
  292. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  293. package/dist/phase-diagram/svg-to-diagram.js +867 -0
  294. package/dist/phase-diagram/types.d.ts +93 -0
  295. package/dist/phase-diagram/types.js +1 -0
  296. package/dist/phase-diagram/utils.d.ts +118 -0
  297. package/dist/phase-diagram/utils.js +600 -0
  298. package/dist/plot/bar/BarPlot.svelte +1755 -0
  299. package/dist/plot/bar/BarPlot.svelte.d.ts +84 -0
  300. package/dist/plot/bar/BarPlotControls.svelte +67 -0
  301. package/dist/plot/bar/BarPlotControls.svelte.d.ts +18 -0
  302. package/dist/plot/bar/SpacegroupBarPlot.svelte +293 -0
  303. package/dist/plot/bar/SpacegroupBarPlot.svelte.d.ts +9 -0
  304. package/dist/plot/bar/data.d.ts +40 -0
  305. package/dist/plot/bar/data.js +154 -0
  306. package/dist/plot/bar/geometry.d.ts +39 -0
  307. package/dist/plot/bar/geometry.js +60 -0
  308. package/dist/plot/bar/index.d.ts +3 -0
  309. package/dist/plot/bar/index.js +3 -0
  310. package/dist/plot/box/BoxPlot.svelte +1462 -0
  311. package/dist/plot/box/BoxPlot.svelte.d.ts +94 -0
  312. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  313. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  314. package/dist/plot/box/Violin.svelte +14 -0
  315. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  316. package/dist/plot/box/box-plot.d.ts +55 -0
  317. package/dist/plot/box/box-plot.js +126 -0
  318. package/dist/plot/box/index.d.ts +5 -0
  319. package/dist/plot/box/index.js +5 -0
  320. package/dist/plot/box/kde.d.ts +16 -0
  321. package/dist/plot/box/kde.js +160 -0
  322. package/dist/plot/box/quantile.d.ts +3 -0
  323. package/dist/plot/box/quantile.js +53 -0
  324. package/dist/plot/core/auto-place.d.ts +43 -0
  325. package/dist/plot/core/auto-place.js +122 -0
  326. package/dist/plot/core/axis-utils.d.ts +46 -0
  327. package/dist/plot/core/axis-utils.js +110 -0
  328. package/dist/plot/core/components/AxisLabel.svelte +51 -0
  329. package/dist/plot/core/components/AxisLabel.svelte.d.ts +16 -0
  330. package/dist/plot/core/components/ColorBar.svelte +724 -0
  331. package/dist/plot/core/components/ColorBar.svelte.d.ts +31 -0
  332. package/dist/plot/core/components/ColorScaleSelect.svelte +55 -0
  333. package/dist/plot/core/components/ColorScaleSelect.svelte.d.ts +15 -0
  334. package/dist/plot/core/components/ControlPane.svelte +46 -0
  335. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  336. package/dist/plot/core/components/FillArea.svelte +234 -0
  337. package/dist/plot/core/components/FillArea.svelte.d.ts +21 -0
  338. package/dist/plot/core/components/InteractiveAxisLabel.svelte +96 -0
  339. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +14 -0
  340. package/dist/plot/core/components/Line.svelte +101 -0
  341. package/dist/plot/core/components/Line.svelte.d.ts +15 -0
  342. package/dist/plot/core/components/PlotAxis.svelte +171 -0
  343. package/dist/plot/core/components/PlotAxis.svelte.d.ts +25 -0
  344. package/dist/plot/core/components/PlotControls.svelte +525 -0
  345. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  346. package/dist/plot/core/components/PlotLegend.svelte +580 -0
  347. package/dist/plot/core/components/PlotLegend.svelte.d.ts +30 -0
  348. package/dist/plot/core/components/PlotTooltip.svelte +83 -0
  349. package/dist/plot/core/components/PlotTooltip.svelte.d.ts +25 -0
  350. package/dist/plot/core/components/PortalSelect.svelte +257 -0
  351. package/dist/plot/core/components/PortalSelect.svelte.d.ts +16 -0
  352. package/dist/plot/core/components/ReferenceLine.svelte +204 -0
  353. package/dist/plot/core/components/ReferenceLine.svelte.d.ts +20 -0
  354. package/dist/plot/core/components/ReferenceLine3D.svelte +156 -0
  355. package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +14 -0
  356. package/dist/plot/core/components/ReferencePlane.svelte +175 -0
  357. package/dist/plot/core/components/ReferencePlane.svelte.d.ts +14 -0
  358. package/dist/plot/core/components/ZeroLines.svelte +97 -0
  359. package/dist/plot/core/components/ZeroLines.svelte.d.ts +33 -0
  360. package/dist/plot/core/components/ZoomRect.svelte +23 -0
  361. package/dist/plot/core/components/ZoomRect.svelte.d.ts +8 -0
  362. package/dist/plot/core/components/index.d.ts +17 -0
  363. package/dist/plot/core/components/index.js +17 -0
  364. package/dist/plot/core/data-cleaning.d.ts +107 -0
  365. package/dist/plot/core/data-cleaning.js +853 -0
  366. package/dist/plot/core/data-transform.d.ts +16 -0
  367. package/dist/plot/core/data-transform.js +45 -0
  368. package/dist/plot/core/fill-utils.d.ts +33 -0
  369. package/dist/plot/core/fill-utils.js +388 -0
  370. package/dist/plot/core/hover-lock.svelte.d.ts +14 -0
  371. package/dist/plot/core/hover-lock.svelte.js +45 -0
  372. package/dist/plot/core/index.d.ts +10 -0
  373. package/dist/plot/core/index.js +11 -0
  374. package/dist/plot/core/interactions.d.ts +35 -0
  375. package/dist/plot/core/interactions.js +195 -0
  376. package/dist/plot/core/layout.d.ts +79 -0
  377. package/dist/plot/core/layout.js +281 -0
  378. package/dist/plot/core/reference-line.d.ts +60 -0
  379. package/dist/plot/core/reference-line.js +301 -0
  380. package/dist/plot/core/scales.d.ts +48 -0
  381. package/dist/plot/core/scales.js +480 -0
  382. package/dist/plot/core/svg.d.ts +2 -0
  383. package/dist/plot/core/svg.js +41 -0
  384. package/dist/plot/core/types.d.ts +771 -0
  385. package/dist/plot/core/types.js +99 -0
  386. package/dist/plot/core/utils/label-placement.d.ts +68 -0
  387. package/dist/plot/core/utils/label-placement.js +326 -0
  388. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  389. package/dist/plot/core/utils/series-visibility.js +112 -0
  390. package/dist/plot/core/utils.d.ts +11 -0
  391. package/dist/plot/core/utils.js +27 -0
  392. package/dist/plot/histogram/Histogram.svelte +1418 -0
  393. package/dist/plot/histogram/Histogram.svelte.d.ts +50 -0
  394. package/dist/plot/histogram/HistogramControls.svelte +212 -0
  395. package/dist/plot/histogram/HistogramControls.svelte.d.ts +22 -0
  396. package/dist/plot/histogram/index.d.ts +2 -0
  397. package/dist/plot/histogram/index.js +2 -0
  398. package/dist/plot/index.d.ts +8 -0
  399. package/dist/plot/index.js +10 -0
  400. package/dist/plot/sankey/Sankey.svelte +700 -0
  401. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  402. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  403. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  404. package/dist/plot/sankey/index.d.ts +4 -0
  405. package/dist/plot/sankey/index.js +3 -0
  406. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  407. package/dist/plot/sankey/sankey-types.js +4 -0
  408. package/dist/plot/sankey/sankey.d.ts +52 -0
  409. package/dist/plot/sankey/sankey.js +187 -0
  410. package/dist/plot/scatter/BinnedScatterPlot.svelte +1116 -0
  411. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +66 -0
  412. package/dist/plot/scatter/ElementScatter.svelte +63 -0
  413. package/dist/plot/scatter/ElementScatter.svelte.d.ts +14 -0
  414. package/dist/plot/scatter/ScatterPlot.svelte +2357 -0
  415. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +96 -0
  416. package/dist/plot/scatter/ScatterPlotControls.svelte +307 -0
  417. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +17 -0
  418. package/dist/plot/scatter/ScatterPoint.svelte +182 -0
  419. package/dist/plot/scatter/ScatterPoint.svelte.d.ts +22 -0
  420. package/dist/plot/scatter/adaptive-density.d.ts +79 -0
  421. package/dist/plot/scatter/adaptive-density.js +217 -0
  422. package/dist/plot/scatter/binned-scatter-types.d.ts +59 -0
  423. package/dist/plot/scatter/binned-scatter-types.js +1 -0
  424. package/dist/plot/scatter/index.d.ts +7 -0
  425. package/dist/plot/scatter/index.js +5 -0
  426. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  427. package/dist/plot/scatter/scatter-data.js +212 -0
  428. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +531 -0
  429. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +95 -0
  430. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +438 -0
  431. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +20 -0
  432. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +912 -0
  433. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +74 -0
  434. package/dist/plot/scatter-3d/Surface3D.svelte +197 -0
  435. package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +13 -0
  436. package/dist/plot/scatter-3d/index.d.ts +4 -0
  437. package/dist/plot/scatter-3d/index.js +4 -0
  438. package/dist/plot/sunburst/Sunburst.svelte +1045 -0
  439. package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -0
  440. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  441. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  442. package/dist/plot/sunburst/index.d.ts +4 -0
  443. package/dist/plot/sunburst/index.js +4 -0
  444. package/dist/plot/sunburst/render.d.ts +34 -0
  445. package/dist/plot/sunburst/render.js +122 -0
  446. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  447. package/dist/plot/sunburst/sunburst.js +266 -0
  448. package/dist/rdf/RdfPlot.svelte +248 -0
  449. package/dist/rdf/RdfPlot.svelte.d.ts +27 -0
  450. package/dist/rdf/calc-rdf.d.ts +4 -0
  451. package/dist/rdf/calc-rdf.js +98 -0
  452. package/dist/rdf/index.d.ts +23 -0
  453. package/dist/rdf/index.js +2 -0
  454. package/dist/sanitize.d.ts +6 -0
  455. package/dist/sanitize.js +116 -0
  456. package/dist/settings.d.ts +319 -0
  457. package/dist/settings.js +1394 -0
  458. package/dist/spectral/Bands.svelte +1050 -0
  459. package/dist/spectral/Bands.svelte.d.ts +39 -0
  460. package/dist/spectral/BandsAndDos.svelte +134 -0
  461. package/dist/spectral/BandsAndDos.svelte.d.ts +18 -0
  462. package/dist/spectral/BrillouinBandsDos.svelte +264 -0
  463. package/dist/spectral/BrillouinBandsDos.svelte.d.ts +20 -0
  464. package/dist/spectral/Dos.svelte +688 -0
  465. package/dist/spectral/Dos.svelte.d.ts +29 -0
  466. package/dist/spectral/helpers.d.ts +121 -0
  467. package/dist/spectral/helpers.js +1098 -0
  468. package/dist/spectral/index.d.ts +6 -0
  469. package/dist/spectral/index.js +6 -0
  470. package/dist/spectral/types.d.ts +84 -0
  471. package/dist/spectral/types.js +2 -0
  472. package/dist/state.svelte.d.ts +25 -0
  473. package/dist/state.svelte.js +45 -0
  474. package/dist/structure/Arrow.svelte +72 -0
  475. package/dist/structure/Arrow.svelte.d.ts +15 -0
  476. package/dist/structure/AtomLegend.svelte +814 -0
  477. package/dist/structure/AtomLegend.svelte.d.ts +35 -0
  478. package/dist/structure/Bond.svelte +140 -0
  479. package/dist/structure/Bond.svelte.d.ts +9 -0
  480. package/dist/structure/CanvasTooltip.svelte +33 -0
  481. package/dist/structure/CanvasTooltip.svelte.d.ts +12 -0
  482. package/dist/structure/CellSelect.svelte +348 -0
  483. package/dist/structure/CellSelect.svelte.d.ts +13 -0
  484. package/dist/structure/Cylinder.svelte +49 -0
  485. package/dist/structure/Cylinder.svelte.d.ts +13 -0
  486. package/dist/structure/Lattice.svelte +196 -0
  487. package/dist/structure/Lattice.svelte.d.ts +17 -0
  488. package/dist/structure/Structure.svelte +2254 -0
  489. package/dist/structure/Structure.svelte.d.ts +89 -0
  490. package/dist/structure/StructureControls.svelte +1273 -0
  491. package/dist/structure/StructureControls.svelte.d.ts +31 -0
  492. package/dist/structure/StructureExportPane.svelte +252 -0
  493. package/dist/structure/StructureExportPane.svelte.d.ts +17 -0
  494. package/dist/structure/StructureInfoPane.svelte +736 -0
  495. package/dist/structure/StructureInfoPane.svelte.d.ts +19 -0
  496. package/dist/structure/StructureScene.svelte +2256 -0
  497. package/dist/structure/StructureScene.svelte.d.ts +111 -0
  498. package/dist/structure/atom-properties.d.ts +37 -0
  499. package/dist/structure/atom-properties.js +200 -0
  500. package/dist/structure/bond-order-perception.d.ts +13 -0
  501. package/dist/structure/bond-order-perception.js +384 -0
  502. package/dist/structure/bonding.d.ts +69 -0
  503. package/dist/structure/bonding.js +724 -0
  504. package/dist/structure/export.d.ts +20 -0
  505. package/dist/structure/export.js +731 -0
  506. package/dist/structure/index.d.ts +124 -0
  507. package/dist/structure/index.js +167 -0
  508. package/dist/structure/label-placement.d.ts +14 -0
  509. package/dist/structure/label-placement.js +72 -0
  510. package/dist/structure/measure.d.ts +7 -0
  511. package/dist/structure/measure.js +30 -0
  512. package/dist/structure/parse.d.ts +66 -0
  513. package/dist/structure/parse.js +1410 -0
  514. package/dist/structure/partial-occupancy.d.ts +25 -0
  515. package/dist/structure/partial-occupancy.js +99 -0
  516. package/dist/structure/pbc.d.ts +9 -0
  517. package/dist/structure/pbc.js +127 -0
  518. package/dist/structure/supercell.d.ts +8 -0
  519. package/dist/structure/supercell.js +170 -0
  520. package/dist/structure/validation.d.ts +2 -0
  521. package/dist/structure/validation.js +10 -0
  522. package/dist/symmetry/SymmetryStats.svelte +226 -0
  523. package/dist/symmetry/SymmetryStats.svelte.d.ts +21 -0
  524. package/dist/symmetry/WyckoffTable.svelte +120 -0
  525. package/dist/symmetry/WyckoffTable.svelte.d.ts +11 -0
  526. package/dist/symmetry/cell-transform.d.ts +12 -0
  527. package/dist/symmetry/cell-transform.js +91 -0
  528. package/dist/symmetry/index.d.ts +43 -0
  529. package/dist/symmetry/index.js +226 -0
  530. package/dist/symmetry/spacegroups.d.ts +16 -0
  531. package/dist/symmetry/spacegroups.js +429 -0
  532. package/dist/table/HeatmapTable.svelte +1885 -0
  533. package/dist/table/HeatmapTable.svelte.d.ts +49 -0
  534. package/dist/table/ToggleMenu.svelte +385 -0
  535. package/dist/table/ToggleMenu.svelte.d.ts +11 -0
  536. package/dist/table/index.d.ts +72 -0
  537. package/dist/table/index.js +38 -0
  538. package/dist/theme/ThemeControl.svelte +53 -0
  539. package/dist/theme/ThemeControl.svelte.d.ts +9 -0
  540. package/dist/theme/index.d.ts +29 -0
  541. package/dist/theme/index.js +79 -0
  542. package/dist/time.d.ts +4 -0
  543. package/dist/time.js +70 -0
  544. package/dist/tooltip/KCoords.svelte +45 -0
  545. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  546. package/dist/tooltip/TooltipContent.svelte +58 -0
  547. package/dist/tooltip/TooltipContent.svelte.d.ts +31 -0
  548. package/dist/tooltip/index.d.ts +3 -0
  549. package/dist/tooltip/index.js +2 -0
  550. package/dist/tooltip/types.d.ts +8 -0
  551. package/dist/tooltip/types.js +1 -0
  552. package/dist/trajectory/Trajectory.svelte +1571 -0
  553. package/dist/trajectory/Trajectory.svelte.d.ts +78 -0
  554. package/dist/trajectory/TrajectoryError.svelte +128 -0
  555. package/dist/trajectory/TrajectoryError.svelte.d.ts +13 -0
  556. package/dist/trajectory/TrajectoryExportPane.svelte +358 -0
  557. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +17 -0
  558. package/dist/trajectory/TrajectoryInfoPane.svelte +314 -0
  559. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +17 -0
  560. package/dist/trajectory/constants.d.ts +6 -0
  561. package/dist/trajectory/constants.js +7 -0
  562. package/dist/trajectory/extract.d.ts +5 -0
  563. package/dist/trajectory/extract.js +162 -0
  564. package/dist/trajectory/format-detect.d.ts +10 -0
  565. package/dist/trajectory/format-detect.js +90 -0
  566. package/dist/trajectory/frame-reader.d.ts +17 -0
  567. package/dist/trajectory/frame-reader.js +299 -0
  568. package/dist/trajectory/helpers.d.ts +15 -0
  569. package/dist/trajectory/helpers.js +164 -0
  570. package/dist/trajectory/index.d.ts +63 -0
  571. package/dist/trajectory/index.js +126 -0
  572. package/dist/trajectory/parse/ase.d.ts +2 -0
  573. package/dist/trajectory/parse/ase.js +73 -0
  574. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  575. package/dist/trajectory/parse/hdf5.js +127 -0
  576. package/dist/trajectory/parse/index.d.ts +12 -0
  577. package/dist/trajectory/parse/index.js +306 -0
  578. package/dist/trajectory/parse/lammps.d.ts +5 -0
  579. package/dist/trajectory/parse/lammps.js +179 -0
  580. package/dist/trajectory/parse/vasp.d.ts +2 -0
  581. package/dist/trajectory/parse/vasp.js +87 -0
  582. package/dist/trajectory/parse/xyz.d.ts +26 -0
  583. package/dist/trajectory/parse/xyz.js +123 -0
  584. package/dist/trajectory/plotting.d.ts +28 -0
  585. package/dist/trajectory/plotting.js +423 -0
  586. package/dist/trajectory/types.d.ts +11 -0
  587. package/dist/trajectory/types.js +1 -0
  588. package/dist/utils.d.ts +7 -0
  589. package/dist/utils.js +47 -0
  590. package/dist/xrd/XrdPlot.svelte +616 -0
  591. package/dist/xrd/XrdPlot.svelte.d.ts +28 -0
  592. package/dist/xrd/broadening.d.ts +20 -0
  593. package/dist/xrd/broadening.js +97 -0
  594. package/dist/xrd/calc-xrd.d.ts +37 -0
  595. package/dist/xrd/calc-xrd.js +339 -0
  596. package/dist/xrd/index.d.ts +37 -0
  597. package/dist/xrd/index.js +4 -0
  598. package/dist/xrd/parse.d.ts +13 -0
  599. package/dist/xrd/parse.js +749 -0
  600. package/license +1 -1
  601. package/package.json +237 -1458
  602. package/readme.md +98 -171
  603. package/.vscode/launch.json +0 -13
  604. package/.vscodeignore +0 -7
  605. package/dist/assets/STLExporter-BpTH3YHE.js +0 -8
  606. package/dist/assets/browser-DdDecX_W.js +0 -1
  607. package/dist/assets/export-qgn-H9y6.js +0 -2
  608. package/dist/assets/main-DiKYzti2.css +0 -1
  609. package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
  610. package/dist/extension.js +0 -31293
  611. package/dist/src/lib/FilePicker.svelte +0 -360
  612. package/dist/src/lib/Icon.svelte +0 -41
  613. package/dist/src/lib/MillerIndexInput.svelte +0 -66
  614. package/dist/src/lib/api/mp.ts +0 -26
  615. package/dist/src/lib/api/optimade.ts +0 -204
  616. package/dist/src/lib/app.css +0 -247
  617. package/dist/src/lib/brillouin/BrillouinZone.svelte +0 -549
  618. package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +0 -144
  619. package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +0 -146
  620. package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +0 -146
  621. package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +0 -476
  622. package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +0 -92
  623. package/dist/src/lib/brillouin/compute.ts +0 -529
  624. package/dist/src/lib/brillouin/index.ts +0 -8
  625. package/dist/src/lib/brillouin/types.ts +0 -51
  626. package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +0 -327
  627. package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +0 -846
  628. package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +0 -3193
  629. package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +0 -94
  630. package/dist/src/lib/chempot-diagram/chempot-worker.ts +0 -11
  631. package/dist/src/lib/chempot-diagram/color.ts +0 -42
  632. package/dist/src/lib/chempot-diagram/compute.ts +0 -1014
  633. package/dist/src/lib/chempot-diagram/index.ts +0 -6
  634. package/dist/src/lib/chempot-diagram/pointer.ts +0 -56
  635. package/dist/src/lib/chempot-diagram/temperature.ts +0 -77
  636. package/dist/src/lib/chempot-diagram/types.ts +0 -130
  637. package/dist/src/lib/colors/index.ts +0 -249
  638. package/dist/src/lib/composition/BarChart.svelte +0 -297
  639. package/dist/src/lib/composition/BubbleChart.svelte +0 -218
  640. package/dist/src/lib/composition/Composition.svelte +0 -165
  641. package/dist/src/lib/composition/Formula.svelte +0 -268
  642. package/dist/src/lib/composition/FormulaFilter.svelte +0 -1257
  643. package/dist/src/lib/composition/PieChart.svelte +0 -323
  644. package/dist/src/lib/composition/format.ts +0 -155
  645. package/dist/src/lib/composition/index.ts +0 -37
  646. package/dist/src/lib/composition/parse.ts +0 -605
  647. package/dist/src/lib/constants.ts +0 -134
  648. package/dist/src/lib/controls.ts +0 -42
  649. package/dist/src/lib/convex-hull/ConvexHull.svelte +0 -157
  650. package/dist/src/lib/convex-hull/ConvexHull2D.svelte +0 -825
  651. package/dist/src/lib/convex-hull/ConvexHull3D.svelte +0 -1801
  652. package/dist/src/lib/convex-hull/ConvexHull4D.svelte +0 -1398
  653. package/dist/src/lib/convex-hull/ConvexHullControls.svelte +0 -535
  654. package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +0 -125
  655. package/dist/src/lib/convex-hull/ConvexHullStats.svelte +0 -929
  656. package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +0 -131
  657. package/dist/src/lib/convex-hull/GasPressureControls.svelte +0 -247
  658. package/dist/src/lib/convex-hull/StructurePopup.svelte +0 -151
  659. package/dist/src/lib/convex-hull/TemperatureSlider.svelte +0 -140
  660. package/dist/src/lib/convex-hull/barycentric-coords.ts +0 -246
  661. package/dist/src/lib/convex-hull/demo-temperature.ts +0 -63
  662. package/dist/src/lib/convex-hull/gas-thermodynamics.ts +0 -405
  663. package/dist/src/lib/convex-hull/helpers.ts +0 -932
  664. package/dist/src/lib/convex-hull/index.ts +0 -202
  665. package/dist/src/lib/convex-hull/thermodynamics.ts +0 -2192
  666. package/dist/src/lib/convex-hull/types.ts +0 -267
  667. package/dist/src/lib/coordination/CoordinationBarPlot.svelte +0 -311
  668. package/dist/src/lib/coordination/calc-coordination.ts +0 -93
  669. package/dist/src/lib/coordination/index.ts +0 -9
  670. package/dist/src/lib/effects.svelte.ts +0 -48
  671. package/dist/src/lib/element/ElementHeading.svelte +0 -26
  672. package/dist/src/lib/element/ElementPhoto.svelte +0 -57
  673. package/dist/src/lib/element/ElementStats.svelte +0 -80
  674. package/dist/src/lib/element/ElementTile.svelte +0 -484
  675. package/dist/src/lib/element/data.ts +0 -14
  676. package/dist/src/lib/element/index.ts +0 -8
  677. package/dist/src/lib/element/types.ts +0 -62
  678. package/dist/src/lib/feedback/ClickFeedback.svelte +0 -58
  679. package/dist/src/lib/feedback/DragOverlay.svelte +0 -42
  680. package/dist/src/lib/feedback/index.ts +0 -4
  681. package/dist/src/lib/fermi-surface/FermiSlice.svelte +0 -189
  682. package/dist/src/lib/fermi-surface/FermiSurface.svelte +0 -600
  683. package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +0 -448
  684. package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +0 -794
  685. package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
  686. package/dist/src/lib/fermi-surface/compute.ts +0 -728
  687. package/dist/src/lib/fermi-surface/constants.ts +0 -32
  688. package/dist/src/lib/fermi-surface/export.ts +0 -64
  689. package/dist/src/lib/fermi-surface/index.ts +0 -14
  690. package/dist/src/lib/fermi-surface/marching-cubes.ts +0 -3
  691. package/dist/src/lib/fermi-surface/parse.ts +0 -574
  692. package/dist/src/lib/fermi-surface/symmetry.ts +0 -56
  693. package/dist/src/lib/fermi-surface/types.ts +0 -159
  694. package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +0 -1545
  695. package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
  696. package/dist/src/lib/heatmap-matrix/index.ts +0 -167
  697. package/dist/src/lib/heatmap-matrix/shared.ts +0 -7
  698. package/dist/src/lib/icons.ts +0 -650
  699. package/dist/src/lib/index.ts +0 -61
  700. package/dist/src/lib/io/decompress.ts +0 -92
  701. package/dist/src/lib/io/export.ts +0 -385
  702. package/dist/src/lib/io/fetch.ts +0 -46
  703. package/dist/src/lib/io/file-drop.ts +0 -51
  704. package/dist/src/lib/io/index.ts +0 -7
  705. package/dist/src/lib/io/is-binary.ts +0 -24
  706. package/dist/src/lib/io/types.ts +0 -8
  707. package/dist/src/lib/io/url-drop.ts +0 -141
  708. package/dist/src/lib/isosurface/Isosurface.svelte +0 -285
  709. package/dist/src/lib/isosurface/IsosurfaceControls.svelte +0 -277
  710. package/dist/src/lib/isosurface/index.ts +0 -7
  711. package/dist/src/lib/isosurface/parse.ts +0 -656
  712. package/dist/src/lib/isosurface/slice.ts +0 -175
  713. package/dist/src/lib/isosurface/types.ts +0 -309
  714. package/dist/src/lib/labels.ts +0 -320
  715. package/dist/src/lib/layout/FullscreenToggle.svelte +0 -50
  716. package/dist/src/lib/layout/InfoCard.svelte +0 -120
  717. package/dist/src/lib/layout/InfoTag.svelte +0 -185
  718. package/dist/src/lib/layout/PropertyFilter.svelte +0 -246
  719. package/dist/src/lib/layout/SettingsSection.svelte +0 -148
  720. package/dist/src/lib/layout/SubpageGrid.svelte +0 -82
  721. package/dist/src/lib/layout/fullscreen.ts +0 -65
  722. package/dist/src/lib/layout/index.ts +0 -11
  723. package/dist/src/lib/layout/json-tree/JsonNode.svelte +0 -548
  724. package/dist/src/lib/layout/json-tree/JsonTree.svelte +0 -1230
  725. package/dist/src/lib/layout/json-tree/index.ts +0 -3
  726. package/dist/src/lib/layout/json-tree/types.ts +0 -126
  727. package/dist/src/lib/layout/json-tree/utils.ts +0 -682
  728. package/dist/src/lib/marching-cubes.ts +0 -614
  729. package/dist/src/lib/math.ts +0 -1081
  730. package/dist/src/lib/overlays/ContextMenu.svelte +0 -162
  731. package/dist/src/lib/overlays/CopyButton.svelte +0 -45
  732. package/dist/src/lib/overlays/DragControlTab.svelte +0 -98
  733. package/dist/src/lib/overlays/DraggablePane.svelte +0 -487
  734. package/dist/src/lib/overlays/InfoPaneCards.svelte +0 -149
  735. package/dist/src/lib/overlays/index.ts +0 -3
  736. package/dist/src/lib/periodic-table/PeriodicTable.svelte +0 -469
  737. package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +0 -557
  738. package/dist/src/lib/periodic-table/PropertySelect.svelte +0 -37
  739. package/dist/src/lib/periodic-table/index.ts +0 -12
  740. package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1086
  741. package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +0 -444
  742. package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
  743. package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +0 -184
  744. package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +0 -391
  745. package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +0 -203
  746. package/dist/src/lib/phase-diagram/build-diagram.ts +0 -186
  747. package/dist/src/lib/phase-diagram/colors.ts +0 -58
  748. package/dist/src/lib/phase-diagram/diagram-input.ts +0 -40
  749. package/dist/src/lib/phase-diagram/index.ts +0 -13
  750. package/dist/src/lib/phase-diagram/parse.ts +0 -348
  751. package/dist/src/lib/phase-diagram/svg-to-diagram.ts +0 -1023
  752. package/dist/src/lib/phase-diagram/types.ts +0 -144
  753. package/dist/src/lib/phase-diagram/utils.ts +0 -775
  754. package/dist/src/lib/plot/AxisLabel.svelte +0 -51
  755. package/dist/src/lib/plot/BarPlot.svelte +0 -2113
  756. package/dist/src/lib/plot/BarPlotControls.svelte +0 -66
  757. package/dist/src/lib/plot/BinnedScatterPlot.svelte +0 -1114
  758. package/dist/src/lib/plot/ColorBar.svelte +0 -721
  759. package/dist/src/lib/plot/ColorScaleSelect.svelte +0 -54
  760. package/dist/src/lib/plot/ElementScatter.svelte +0 -63
  761. package/dist/src/lib/plot/FillArea.svelte +0 -223
  762. package/dist/src/lib/plot/Histogram.svelte +0 -1558
  763. package/dist/src/lib/plot/HistogramControls.svelte +0 -212
  764. package/dist/src/lib/plot/InteractiveAxisLabel.svelte +0 -96
  765. package/dist/src/lib/plot/Line.svelte +0 -84
  766. package/dist/src/lib/plot/PlotAxis.svelte +0 -169
  767. package/dist/src/lib/plot/PlotControls.svelte +0 -537
  768. package/dist/src/lib/plot/PlotLegend.svelte +0 -569
  769. package/dist/src/lib/plot/PlotTooltip.svelte +0 -67
  770. package/dist/src/lib/plot/PortalSelect.svelte +0 -253
  771. package/dist/src/lib/plot/ReferenceLine.svelte +0 -204
  772. package/dist/src/lib/plot/ReferenceLine3D.svelte +0 -156
  773. package/dist/src/lib/plot/ReferencePlane.svelte +0 -175
  774. package/dist/src/lib/plot/ScatterPlot.svelte +0 -2778
  775. package/dist/src/lib/plot/ScatterPlot3D.svelte +0 -529
  776. package/dist/src/lib/plot/ScatterPlot3DControls.svelte +0 -437
  777. package/dist/src/lib/plot/ScatterPlot3DScene.svelte +0 -912
  778. package/dist/src/lib/plot/ScatterPlotControls.svelte +0 -306
  779. package/dist/src/lib/plot/ScatterPoint.svelte +0 -182
  780. package/dist/src/lib/plot/SpacegroupBarPlot.svelte +0 -293
  781. package/dist/src/lib/plot/Surface3D.svelte +0 -197
  782. package/dist/src/lib/plot/ZeroLines.svelte +0 -97
  783. package/dist/src/lib/plot/ZoomRect.svelte +0 -23
  784. package/dist/src/lib/plot/adaptive-density.ts +0 -316
  785. package/dist/src/lib/plot/auto-place.ts +0 -184
  786. package/dist/src/lib/plot/axis-utils.ts +0 -122
  787. package/dist/src/lib/plot/binned-scatter-types.ts +0 -83
  788. package/dist/src/lib/plot/data-cleaning.ts +0 -1069
  789. package/dist/src/lib/plot/data-transform.ts +0 -69
  790. package/dist/src/lib/plot/defaults.ts +0 -9
  791. package/dist/src/lib/plot/fill-utils.ts +0 -494
  792. package/dist/src/lib/plot/hover-lock.svelte.ts +0 -60
  793. package/dist/src/lib/plot/index.ts +0 -53
  794. package/dist/src/lib/plot/interactions.ts +0 -119
  795. package/dist/src/lib/plot/layout.ts +0 -425
  796. package/dist/src/lib/plot/reference-line.ts +0 -426
  797. package/dist/src/lib/plot/scales.ts +0 -654
  798. package/dist/src/lib/plot/svg.ts +0 -23
  799. package/dist/src/lib/plot/types.ts +0 -1144
  800. package/dist/src/lib/plot/utils/label-placement.ts +0 -541
  801. package/dist/src/lib/plot/utils/series-visibility.ts +0 -140
  802. package/dist/src/lib/plot/utils.ts +0 -11
  803. package/dist/src/lib/rdf/RdfPlot.svelte +0 -247
  804. package/dist/src/lib/rdf/calc-rdf.ts +0 -167
  805. package/dist/src/lib/rdf/index.ts +0 -27
  806. package/dist/src/lib/sanitize.ts +0 -126
  807. package/dist/src/lib/settings.ts +0 -1479
  808. package/dist/src/lib/spectral/Bands.svelte +0 -1040
  809. package/dist/src/lib/spectral/BandsAndDos.svelte +0 -134
  810. package/dist/src/lib/spectral/BrillouinBandsDos.svelte +0 -252
  811. package/dist/src/lib/spectral/Dos.svelte +0 -697
  812. package/dist/src/lib/spectral/helpers.ts +0 -1381
  813. package/dist/src/lib/spectral/index.ts +0 -8
  814. package/dist/src/lib/spectral/types.ts +0 -112
  815. package/dist/src/lib/state.svelte.ts +0 -64
  816. package/dist/src/lib/structure/Arrow.svelte +0 -72
  817. package/dist/src/lib/structure/AtomLegend.svelte +0 -815
  818. package/dist/src/lib/structure/Bond.svelte +0 -140
  819. package/dist/src/lib/structure/CanvasTooltip.svelte +0 -33
  820. package/dist/src/lib/structure/CellSelect.svelte +0 -349
  821. package/dist/src/lib/structure/Cylinder.svelte +0 -45
  822. package/dist/src/lib/structure/Lattice.svelte +0 -196
  823. package/dist/src/lib/structure/Structure.svelte +0 -2248
  824. package/dist/src/lib/structure/StructureControls.svelte +0 -1273
  825. package/dist/src/lib/structure/StructureExportPane.svelte +0 -252
  826. package/dist/src/lib/structure/StructureInfoPane.svelte +0 -737
  827. package/dist/src/lib/structure/StructureScene.svelte +0 -2255
  828. package/dist/src/lib/structure/atom-properties.ts +0 -316
  829. package/dist/src/lib/structure/bond-order-perception.ts +0 -447
  830. package/dist/src/lib/structure/bonding.ts +0 -944
  831. package/dist/src/lib/structure/export.ts +0 -861
  832. package/dist/src/lib/structure/index.ts +0 -291
  833. package/dist/src/lib/structure/label-placement.ts +0 -130
  834. package/dist/src/lib/structure/measure.ts +0 -45
  835. package/dist/src/lib/structure/parse.ts +0 -1705
  836. package/dist/src/lib/structure/partial-occupancy.ts +0 -183
  837. package/dist/src/lib/structure/pbc.ts +0 -164
  838. package/dist/src/lib/structure/supercell.ts +0 -226
  839. package/dist/src/lib/structure/validation.ts +0 -11
  840. package/dist/src/lib/symmetry/SymmetryStats.svelte +0 -226
  841. package/dist/src/lib/symmetry/WyckoffTable.svelte +0 -120
  842. package/dist/src/lib/symmetry/cell-transform.ts +0 -118
  843. package/dist/src/lib/symmetry/index.ts +0 -348
  844. package/dist/src/lib/symmetry/spacegroups.ts +0 -404
  845. package/dist/src/lib/table/HeatmapTable.svelte +0 -1833
  846. package/dist/src/lib/table/ToggleMenu.svelte +0 -385
  847. package/dist/src/lib/table/index.ts +0 -139
  848. package/dist/src/lib/theme/ThemeControl.svelte +0 -53
  849. package/dist/src/lib/theme/index.ts +0 -107
  850. package/dist/src/lib/time.ts +0 -71
  851. package/dist/src/lib/tooltip/TooltipContent.svelte +0 -58
  852. package/dist/src/lib/tooltip/index.ts +0 -2
  853. package/dist/src/lib/tooltip/types.ts +0 -13
  854. package/dist/src/lib/trajectory/Trajectory.svelte +0 -1545
  855. package/dist/src/lib/trajectory/TrajectoryError.svelte +0 -128
  856. package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +0 -357
  857. package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +0 -313
  858. package/dist/src/lib/trajectory/constants.ts +0 -7
  859. package/dist/src/lib/trajectory/extract.ts +0 -196
  860. package/dist/src/lib/trajectory/format-detect.ts +0 -96
  861. package/dist/src/lib/trajectory/frame-reader.ts +0 -456
  862. package/dist/src/lib/trajectory/helpers.ts +0 -217
  863. package/dist/src/lib/trajectory/index.ts +0 -218
  864. package/dist/src/lib/trajectory/parse/ase.ts +0 -109
  865. package/dist/src/lib/trajectory/parse/hdf5.ts +0 -173
  866. package/dist/src/lib/trajectory/parse/index.ts +0 -411
  867. package/dist/src/lib/trajectory/parse/lammps.ts +0 -215
  868. package/dist/src/lib/trajectory/parse/vasp.ts +0 -102
  869. package/dist/src/lib/trajectory/parse/xyz.ts +0 -143
  870. package/dist/src/lib/trajectory/plotting.ts +0 -599
  871. package/dist/src/lib/trajectory/types.ts +0 -13
  872. package/dist/src/lib/utils.ts +0 -56
  873. package/dist/src/lib/xrd/XrdPlot.svelte +0 -615
  874. package/dist/src/lib/xrd/broadening.ts +0 -130
  875. package/dist/src/lib/xrd/calc-xrd.ts +0 -397
  876. package/dist/src/lib/xrd/index.ts +0 -38
  877. package/dist/src/lib/xrd/parse.ts +0 -858
  878. package/dist/webview.js +0 -29421
  879. package/icon.png +0 -0
  880. package/matterviz-0.3.2.vsix +0 -0
  881. package/matterviz-0.3.4.vsix +0 -0
  882. package/matterviz-0.3.5.vsix +0 -0
  883. package/scripts/sync-config.ts +0 -101
  884. package/src/declarations.d.ts +0 -2
  885. package/src/extension.ts +0 -972
  886. package/src/node-io.ts +0 -65
  887. package/src/types.ts +0 -17
  888. package/src/webview/JsonBrowser.svelte +0 -1079
  889. package/src/webview/PlotPanel.svelte +0 -346
  890. package/src/webview/detect.ts +0 -444
  891. package/src/webview/main.ts +0 -764
  892. package/src/webview/plot-utils.ts +0 -250
  893. package/test-fixtures/all-viz-types.json.gz +0 -0
  894. package/test-fixtures/plot-demo-data.json.gz +0 -0
  895. package/tests/detect.test.ts +0 -604
  896. package/tests/extension.test.ts +0 -2041
  897. package/tests/node-io.test.ts +0 -39
  898. package/tests/plot-utils.test.ts +0 -302
  899. package/tests/vite-plugin-json-gz.test.ts +0 -114
  900. package/tests/vscode-mock.ts +0 -18
  901. package/tests/webview.test.ts +0 -231
  902. package/tsconfig.json +0 -20
  903. package/vite-plugin-json-gz.ts +0 -29
  904. package/vite.config.ts +0 -34
  905. package/vite.extension.config.ts +0 -34
  906. /package/dist/{src/lib/EmptyState.svelte → EmptyState.svelte} +0 -0
  907. /package/dist/{src/lib/chempot-diagram → chempot-diagram}/ChemPotScene3D.svelte +0 -0
  908. /package/dist/{src/lib/colors → colors}/alloy-colors.json +0 -0
  909. /package/dist/{src/lib/colors → colors}/dark-mode-colors.json +0 -0
  910. /package/dist/{src/lib/colors → colors}/jmol-colors.json +0 -0
  911. /package/dist/{src/lib/colors → colors}/muted-colors.json +0 -0
  912. /package/dist/{src/lib/colors → colors}/pastel-colors.json +0 -0
  913. /package/dist/{src/lib/colors → colors}/vesta-colors.json +0 -0
  914. /package/dist/{src/lib/element → element}/BohrAtom.svelte +0 -0
  915. /package/dist/{src/lib/element → element}/Nucleus.svelte +0 -0
  916. /package/dist/{src/lib/element → element}/data.json +0 -0
  917. /package/dist/{src/lib/element → element}/data.json.gz +0 -0
  918. /package/dist/{src/lib/element → element}/data.json.gz.d.ts +0 -0
  919. /package/dist/{src/lib/element → element}/data.schema.json +0 -0
  920. /package/dist/{src/lib/element-image-urls.json → element-image-urls.json} +0 -0
  921. /package/dist/{src/lib/feedback → feedback}/Spinner.svelte +0 -0
  922. /package/dist/{src/lib/feedback → feedback}/StatusMessage.svelte +0 -0
  923. /package/dist/{src/lib/layout → layout}/json-tree/JsonValue.svelte +0 -0
  924. /package/dist/{src/lib/periodic-table → periodic-table}/TableInset.svelte +0 -0
  925. /package/dist/{src/lib/theme → theme}/themes.mjs +0 -0
  926. /package/dist/{src/lib/xrd → xrd}/atomic_scattering_params.json +0 -0
@@ -0,0 +1,1098 @@
1
+ // Helper utilities for band structure and DOS data processing
2
+ import { SUBSCRIPT_MAP } from '../labels';
3
+ import { euclidean_dist } from '../math';
4
+ const is_subscript_key = (key) => key in SUBSCRIPT_MAP;
5
+ // Check if range is a valid [min, max] tuple (strict 2-element array of finite numbers)
6
+ export const is_valid_range = (range) => Array.isArray(range) &&
7
+ range.length === 2 &&
8
+ Number.isFinite(range[0]) &&
9
+ Number.isFinite(range[1]);
10
+ // Check if two ranges are approximately equal (within tolerance)
11
+ // Returns false if either range is invalid (null, undefined, or fails is_valid_range)
12
+ // Negative tol is clamped to 0; tol=0 checks exact equality
13
+ export const ranges_equal = (a, b, tol = 0.001) => {
14
+ const safe_tol = Math.max(0, tol);
15
+ return (is_valid_range(a) &&
16
+ is_valid_range(b) &&
17
+ Math.abs(a[0] - b[0]) <= safe_tol &&
18
+ Math.abs(a[1] - b[1]) <= safe_tol);
19
+ };
20
+ export const axis_with_range = (axis, range, label) => ({
21
+ ...axis,
22
+ ...(label !== undefined && { label }),
23
+ ...(is_valid_range(range) && { range }),
24
+ });
25
+ // Sync a ScatterPlot's internal y-axis range back onto a parent bindable axis.
26
+ // Returns a new axis when the range changed (or became invalid and must be
27
+ // cleared), otherwise the same reference so callers can skip reassignment and
28
+ // avoid reactive churn (assign only when `result !== axis`).
29
+ export function sync_axis_range(axis, range) {
30
+ if (is_valid_range(range)) {
31
+ if (axis.range?.[0] === range[0] && axis.range?.[1] === range[1])
32
+ return axis;
33
+ return { ...axis, range };
34
+ }
35
+ if (`range` in axis) {
36
+ const { range: _omit, ...rest } = axis;
37
+ return rest;
38
+ }
39
+ return axis;
40
+ }
41
+ // Detect which plot triggered a zoom change and return the new synced range.
42
+ // Returns null to reset to shared range, undefined for no change, or Vec2 for new zoom.
43
+ export function detect_zoom_change(bands_range, dos_range, shared_range, current_synced, dos_enabled = true) {
44
+ const bands_valid = is_valid_range(bands_range);
45
+ const dos_valid = dos_enabled && is_valid_range(dos_range);
46
+ // Reset if either becomes invalid (auto-range reset) or returns to shared range
47
+ if (current_synced !== null) {
48
+ const bands_at_shared = bands_valid && ranges_equal(bands_range, shared_range);
49
+ const dos_at_shared = dos_valid && ranges_equal(dos_range, shared_range);
50
+ if (bands_at_shared || dos_at_shared || !bands_valid || (dos_enabled && !dos_valid)) {
51
+ return null;
52
+ }
53
+ }
54
+ // Check for new zoom from either plot
55
+ const bands_is_new = bands_valid &&
56
+ !ranges_equal(bands_range, shared_range) &&
57
+ !ranges_equal(bands_range, current_synced);
58
+ const dos_is_new = dos_valid &&
59
+ !ranges_equal(dos_range, shared_range) &&
60
+ !ranges_equal(dos_range, current_synced);
61
+ if (bands_is_new && !dos_is_new)
62
+ return bands_range;
63
+ if (dos_is_new && !bands_is_new)
64
+ return dos_range;
65
+ return undefined; // no change
66
+ }
67
+ // Physical constants for unit conversions (SI units)
68
+ const PLANCK = 6.62607015e-34; // J⋅s
69
+ const EV_TO_J = 1.602176634e-19; // J
70
+ const C_LIGHT = 299792458; // m/s
71
+ const THz_TO_HZ = 1e12;
72
+ const THz_TO_EV = (PLANCK * THz_TO_HZ) / EV_TO_J;
73
+ const THz_TO_MEV = THz_TO_EV * 1000;
74
+ const THz_TO_HA = THz_TO_EV / 27.211386245988; // Hartree
75
+ const THz_TO_CM = THz_TO_HZ / (C_LIGHT * 100); // cm^-1 (c in cm/s)
76
+ // Band structure constants
77
+ export const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005; // Clamp negatives < 0.5% as noise
78
+ // Convert symmetry point symbols to pretty-printed versions.
79
+ // Handles Greek letters (both plain and LaTeX backslash-prefixed) and subscripts.
80
+ export function pretty_sym_point(symbol) {
81
+ if (!symbol)
82
+ return ``;
83
+ // Remove underscores (htmlify maps S0 → S<sub>0</sub> but leaves S_0 as is)
84
+ // Replace common symmetry point names with Greek letters
85
+ // Handle both plain names (GAMMA) and LaTeX notation (\Gamma) from pymatgen
86
+ // Handle subscripts: convert S0 to S₀, K1 to K₁, Γ1 to Γ₁, etc.
87
+ // Use \p{L} to match any Unicode letter (not just ASCII A-Z)
88
+ return symbol
89
+ .replaceAll('_', ``)
90
+ .replaceAll(/\\?GAMMA/gi, `Γ`)
91
+ .replaceAll(/\\?DELTA/gi, `Δ`)
92
+ .replaceAll(/\\?SIGMA/gi, `Σ`)
93
+ .replaceAll(/\\?LAMBDA/gi, `Λ`)
94
+ .replaceAll(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
95
+ num
96
+ .split(``)
97
+ .map((digit) => (is_subscript_key(digit) ? SUBSCRIPT_MAP[digit] : digit))
98
+ .join(``));
99
+ }
100
+ // Create segment key from start and end labels
101
+ export const get_segment_key = (start_label, end_label) => `${start_label ?? `null`}_${end_label ?? `null`}`;
102
+ // Get ordered segment keys from a band structure, preserving physical path order.
103
+ export const get_ordered_segments = (band_struct, segments) => {
104
+ if (!band_struct)
105
+ return Array.from(segments);
106
+ const ordered = band_struct.branches.map((branch) => get_segment_key(band_struct.qpoints[branch.start_index]?.label ?? undefined, band_struct.qpoints[branch.end_index]?.label ?? undefined));
107
+ const remaining = Array.from(segments).filter((seg) => !ordered.includes(seg));
108
+ return [...ordered, ...remaining];
109
+ };
110
+ // Scale segment distances to a target x-axis range [x_start, x_end].
111
+ // Used by both band line series and fat band ribbons for consistent x-axis positioning.
112
+ export function scale_segment_distances(segment_distances, x_start, x_end) {
113
+ if (segment_distances.length === 0)
114
+ return [];
115
+ const dist_min = segment_distances[0];
116
+ const dist_range = (segment_distances.at(-1) ?? dist_min) - dist_min;
117
+ if (dist_range === 0) {
118
+ // All points at same distance - place at midpoint
119
+ return segment_distances.map(() => (x_start + x_end) / 2);
120
+ }
121
+ return segment_distances.map((dist) => x_start + ((dist - dist_min) / dist_range) * (x_end - x_start));
122
+ }
123
+ // Get ribbon config for a specific band structure label.
124
+ // Supports both single global config (with primitive keys like opacity, max_width, scale, color)
125
+ // and per-structure config (keyed by structure label).
126
+ // Distinguishes between a global config and a per-structure config by checking if any
127
+ // primitive-typed keys (opacity, max_width, scale, color) exist at the top level.
128
+ export function get_ribbon_config(ribbon_config, label) {
129
+ const defaults = { opacity: 0.3, max_width: 6, scale: 1 };
130
+ const config_record = ribbon_config;
131
+ // Check for primitive config values (not objects) to distinguish single vs per-structure config
132
+ const has_primitive = [`opacity`, `max_width`, `scale`, `color`].some((key) => {
133
+ const value = config_record[key];
134
+ return value !== undefined && typeof value !== `object`;
135
+ });
136
+ if (has_primitive) {
137
+ // Single global config with primitive values - apply to all structures
138
+ return { ...defaults, ...ribbon_config };
139
+ }
140
+ // Otherwise, treat as Record<string, RibbonConfig> and look up by label
141
+ // Empty label skips lookup and uses defaults only
142
+ const label_config = label ? config_record[label] : undefined;
143
+ return {
144
+ ...defaults,
145
+ ...(label_config && typeof label_config === `object` ? label_config : {}),
146
+ };
147
+ }
148
+ // Extract tick positions and labels for a band structure plot.
149
+ export function get_band_xaxis_ticks(band_struct, branches = []) {
150
+ const ticks_x_pos = [];
151
+ const tick_labels = [];
152
+ let prev_label = band_struct.qpoints[0]?.label ?? null;
153
+ let prev_branch = band_struct.branches[0]?.name || null;
154
+ // Convert branches to Set for consistent handling
155
+ const branches_set = Array.isArray(branches) ? new Set(branches) : branches;
156
+ for (let idx = 0; idx < band_struct.qpoints.length; idx++) {
157
+ const point = band_struct.qpoints[idx];
158
+ if (point.label === null)
159
+ continue;
160
+ // Find which branch this point belongs to
161
+ const branch_names = band_struct.branches
162
+ .filter((branch) => branch.start_index <= idx && idx <= branch.end_index)
163
+ .map((branch) => branch.name);
164
+ const this_branch = branch_names[0] || null;
165
+ if (point.label !== prev_label && prev_branch !== this_branch) {
166
+ // Branch transition - combine labels
167
+ tick_labels[tick_labels.length - 1] = `${prev_label ?? ``}|${point.label}`;
168
+ ticks_x_pos[ticks_x_pos.length - 1] = band_struct.distance[idx];
169
+ }
170
+ else if (branches_set.size === 0 || (this_branch && branches_set.has(this_branch))) {
171
+ tick_labels.push(point.label);
172
+ ticks_x_pos.push(band_struct.distance[idx]);
173
+ }
174
+ prev_label = point.label;
175
+ prev_branch = this_branch;
176
+ }
177
+ return [ticks_x_pos, tick_labels.map(pretty_sym_point)];
178
+ }
179
+ // Convert frequencies from THz to specified units.
180
+ export function convert_frequencies(frequencies, unit = `THz`) {
181
+ const conversion_factors = {
182
+ THz: 1,
183
+ eV: THz_TO_EV,
184
+ meV: THz_TO_MEV,
185
+ Ha: THz_TO_HA,
186
+ 'cm-1': THz_TO_CM,
187
+ };
188
+ const factor = conversion_factors[unit];
189
+ if (!factor) {
190
+ const valid_units = Object.keys(conversion_factors).join(`, `);
191
+ throw new Error(`Invalid unit: ${unit}. Must be one of ${valid_units}`);
192
+ }
193
+ return frequencies.map((freq) => freq * factor);
194
+ }
195
+ // Normalize DOS densities according to specified mode.
196
+ export function normalize_densities(densities, freqs_or_energies, mode) {
197
+ if (!mode)
198
+ return densities;
199
+ const normalized = [...densities];
200
+ if (mode === `max`) {
201
+ const max_val = Math.max(...normalized);
202
+ if (max_val === 0)
203
+ return normalized;
204
+ return normalized.map((dens) => dens / max_val);
205
+ }
206
+ else if (mode === `sum`) {
207
+ const sum = normalized.reduce((acc, d) => acc + d, 0);
208
+ if (sum === 0)
209
+ return normalized;
210
+ return normalized.map((dens) => dens / sum);
211
+ }
212
+ else if (mode === `integral`) {
213
+ if (freqs_or_energies.length < 2)
214
+ return normalized;
215
+ const bin_width = freqs_or_energies[1] - freqs_or_energies[0];
216
+ if (bin_width === 0)
217
+ return normalized;
218
+ const sum = normalized.reduce((acc, d) => acc + d, 0);
219
+ if (sum === 0)
220
+ return normalized;
221
+ return normalized.map((dens) => dens / (sum * bin_width));
222
+ }
223
+ return normalized;
224
+ }
225
+ // Simple LRU cache for Gaussian smearing results
226
+ // Key: hash of (frequencies, densities, sigma), Value: smeared densities
227
+ const SMEARING_CACHE_MAX_SIZE = 10;
228
+ const smearing_cache = new Map();
229
+ // FNV-1a hash for number arrays (fast, good distribution, O(n))
230
+ function fnv1a_hash(arr) {
231
+ let hash = 2166136261; // FNV offset basis
232
+ for (const val of arr) {
233
+ // Convert float to int32 bits for consistent hashing
234
+ const bits = new Float64Array([val]);
235
+ const int_view = new Uint32Array(bits.buffer);
236
+ hash ^= int_view[0];
237
+ hash = Math.imul(hash, 16777619); // FNV prime
238
+ hash ^= int_view[1];
239
+ hash = Math.imul(hash, 16777619);
240
+ }
241
+ // oxlint-disable-next-line eslint-plugin-unicorn/prefer-math-trunc -- `>>> 0` is unsigned 32-bit coercion, not truncation
242
+ return hash >>> 0; // Ensure unsigned
243
+ }
244
+ // Generate cache key using FNV-1a hash over full arrays (O(n), low collision risk)
245
+ function generate_smearing_cache_key(freqs_or_energies, densities, sigma) {
246
+ const len = freqs_or_energies.length;
247
+ if (len === 0)
248
+ return `0:${sigma.toFixed(6)}:0:0`;
249
+ return `${len}:${sigma.toFixed(6)}:${fnv1a_hash(freqs_or_energies).toString(16)}:${fnv1a_hash(densities).toString(16)}`;
250
+ }
251
+ // Core Gaussian smearing computation (unmemoized)
252
+ function apply_gaussian_smearing_core(freqs_or_energies, densities, sigma) {
253
+ const orig_sum = densities.reduce((acc, d) => acc + d, 0);
254
+ if (sigma <= 0 || orig_sum === 0)
255
+ return densities;
256
+ const smeared = Array(densities.length).fill(0);
257
+ const truncation_width = 4; // Truncate Gaussian at ±4σ (contribution < 0.01%)
258
+ for (let idx = 0; idx < freqs_or_energies.length; idx++) {
259
+ const energy = freqs_or_energies[idx];
260
+ const cutoff = truncation_width * sigma;
261
+ for (let jdx = 0; jdx < freqs_or_energies.length; jdx++) {
262
+ const e_j = freqs_or_energies[jdx];
263
+ const delta = Math.abs(energy - e_j);
264
+ // Skip points beyond truncation width
265
+ if (delta > cutoff)
266
+ continue;
267
+ const gaussian = Math.exp(-((energy - e_j) ** 2) / (2 * sigma ** 2));
268
+ smeared[idx] += densities[jdx] * gaussian;
269
+ }
270
+ }
271
+ // Normalize to preserve integral
272
+ const smeared_sum = smeared.reduce((acc, d) => acc + d, 0);
273
+ if (smeared_sum === 0)
274
+ return densities;
275
+ const normalization = orig_sum / smeared_sum;
276
+ return smeared.map((dens) => dens * normalization);
277
+ }
278
+ // Apply Gaussian smearing to DOS densities with memoization.
279
+ // Uses truncated Gaussian (±4σ) for O(n·w) complexity instead of O(n²).
280
+ // Results are cached using an LRU cache to avoid recomputation on reactive updates.
281
+ export function apply_gaussian_smearing(freqs_or_energies, densities, sigma) {
282
+ // Fast path: no smearing needed
283
+ if (sigma <= 0)
284
+ return densities;
285
+ const cache_key = generate_smearing_cache_key(freqs_or_energies, densities, sigma);
286
+ // Check cache
287
+ const cached = smearing_cache.get(cache_key);
288
+ if (cached) {
289
+ // Move to end (LRU behavior: most recently used last)
290
+ smearing_cache.delete(cache_key);
291
+ smearing_cache.set(cache_key, cached);
292
+ return cached;
293
+ }
294
+ // Compute and cache
295
+ const result = apply_gaussian_smearing_core(freqs_or_energies, densities, sigma);
296
+ // Evict oldest entry if cache is full (LRU: first entry is oldest)
297
+ if (smearing_cache.size >= SMEARING_CACHE_MAX_SIZE) {
298
+ const oldest_key = smearing_cache.keys().next().value;
299
+ if (oldest_key !== undefined)
300
+ smearing_cache.delete(oldest_key);
301
+ }
302
+ smearing_cache.set(cache_key, result);
303
+ return result;
304
+ }
305
+ // Clear the smearing cache (useful for testing or memory management)
306
+ export function clear_smearing_cache() {
307
+ smearing_cache.clear();
308
+ }
309
+ // Type guards for pymatgen qpoint formats
310
+ const is_vec3 = (val) => Array.isArray(val) && val.length >= 3 && val.slice(0, 3).every(Number.isFinite);
311
+ const is_kpoint = (val) => val !== null && typeof val === `object` && `frac_coords` in val && is_vec3(val.frac_coords);
312
+ const is_pymatgen_format = (obj) => {
313
+ // Check for explicit pymatgen markers
314
+ if (typeof obj[`@class`] === `string` || typeof obj[`@module`] === `string`) {
315
+ return true;
316
+ }
317
+ // Check for pymatgen-style qpoints (phonon) or kpoints (electronic) without branches
318
+ const points = obj.qpoints ?? obj.kpoints;
319
+ if (Array.isArray(points) && points.length > 0 && !Array.isArray(obj.branches)) {
320
+ return is_vec3(points[0]) || is_kpoint(points[0]);
321
+ }
322
+ return false;
323
+ };
324
+ // Extract frac_coords/label from pymatgen qpoint, matching label from labels_dict if needed
325
+ const parse_qpoint = (qpt, labels_dict) => {
326
+ const frac_coords = is_vec3(qpt)
327
+ ? [qpt[0], qpt[1], qpt[2]]
328
+ : is_kpoint(qpt)
329
+ ? qpt.frac_coords
330
+ : null;
331
+ if (!frac_coords)
332
+ return null;
333
+ const label = ((is_kpoint(qpt) && typeof qpt.label === `string` && qpt.label) ||
334
+ Object.entries(labels_dict ?? {}).find(([, c]) => euclidean_dist(frac_coords, c) < 1e-4)?.[0]) ??
335
+ null;
336
+ return { label, frac_coords };
337
+ };
338
+ // Inverse conversion factors (derived from THz_TO_* for consistency)
339
+ const EV_TO_THZ = 1 / THz_TO_EV;
340
+ const CM_TO_THZ = 1 / THz_TO_CM;
341
+ // Spin key constants for pymatgen spin-polarized data
342
+ const SPIN_UP_KEYS = [`1`, `Spin.up`];
343
+ const SPIN_DOWN_KEYS = [`-1`, `Spin.down`];
344
+ // Extract both spin channels from pymatgen spin-keyed data.
345
+ // Returns { up: T, down: T | null } where down is null for non-spin-polarized data.
346
+ export function extract_spin_channels(data) {
347
+ if (Array.isArray(data))
348
+ return { up: data, down: null };
349
+ if (data && typeof data === `object`) {
350
+ const record = data;
351
+ let spin_up = null;
352
+ let spin_down = null;
353
+ // Extract spin-up channel
354
+ for (const key of SPIN_UP_KEYS) {
355
+ if (key in record) {
356
+ spin_up = record[key];
357
+ break;
358
+ }
359
+ }
360
+ // Extract spin-down channel
361
+ for (const key of SPIN_DOWN_KEYS) {
362
+ if (key in record) {
363
+ spin_down = record[key];
364
+ break;
365
+ }
366
+ }
367
+ // Fall back to first key if no spin-up key found
368
+ if (spin_up === null) {
369
+ const keys = Object.keys(record);
370
+ if (keys.length > 0)
371
+ spin_up = record[keys[0]];
372
+ }
373
+ if (spin_up === null)
374
+ return null;
375
+ return { up: spin_up, down: spin_down };
376
+ }
377
+ return null;
378
+ }
379
+ // Convert pymatgen PhononBandStructureSymmLine or BandStructure to matterviz format
380
+ function convert_pymatgen_band_structure(pmg) {
381
+ // Support both qpoints (phonon) and kpoints (electronic)
382
+ const raw_qpts = (pmg.qpoints ?? pmg.kpoints);
383
+ // Handle bands in multiple formats:
384
+ // 1. Standard pymatgen: bands as dict with spin keys {1: [[...], ...]}
385
+ // 2. Custom phonon format: frequencies_cm as 2D array [[...], ...]
386
+ // 3. Already normalized: bands as 2D array [[...], ...]
387
+ const spin_channels = extract_spin_channels(pmg.bands);
388
+ let raw_bands = spin_channels?.up ?? null;
389
+ let raw_spin_down_bands = spin_channels?.down ?? null;
390
+ const has_frequencies_cm = Array.isArray(pmg.frequencies_cm);
391
+ if (!raw_bands && has_frequencies_cm) {
392
+ // Phonon format: frequencies_cm is [n_qpoints x n_branches] - needs transpose
393
+ const freqs = pmg.frequencies_cm;
394
+ if (freqs.length > 0 && Array.isArray(freqs[0])) {
395
+ // Transpose: [n_qpoints x n_branches] -> [n_branches x n_qpoints]
396
+ raw_bands = Array.from({ length: freqs[0].length }, (_, band_idx) => freqs.map((qpt_freqs) => qpt_freqs[band_idx]));
397
+ raw_spin_down_bands = null;
398
+ }
399
+ }
400
+ const labels_dict = pmg.labels_dict;
401
+ const lattice_rec = pmg.lattice_rec;
402
+ // Determine unit: cm-1 if frequencies_cm present, else check explicit unit or default to THz
403
+ const unit = pmg.unit?.toLowerCase() ?? (has_frequencies_cm ? `cm-1` : `thz`);
404
+ if (!Array.isArray(raw_qpts) ||
405
+ !Array.isArray(raw_bands) ||
406
+ raw_qpts.length === 0 ||
407
+ raw_bands.length === 0)
408
+ return null;
409
+ const qpoints = raw_qpts
410
+ .map((qpoint) => parse_qpoint(qpoint, labels_dict))
411
+ .filter((qpoint) => qpoint !== null);
412
+ if (qpoints.length === 0)
413
+ return null;
414
+ // Step distances and discontinuity detection (5x median threshold)
415
+ const steps = qpoints
416
+ .slice(1)
417
+ .map((qpoint, idx) => euclidean_dist(qpoints[idx].frac_coords, qpoint.frac_coords));
418
+ const sorted = steps.slice().sort((a, b) => a - b);
419
+ const threshold = (sorted[Math.floor(sorted.length / 2)] ?? 0) * 5;
420
+ const disc_set = new Set(steps
421
+ .map((step, idx) => (step > threshold ? idx + 1 : -1))
422
+ .filter((disc_idx) => disc_idx >= 0));
423
+ // Cumulative distance (skip discontinuities)
424
+ const distance = steps.reduce((acc, step, idx) => [...acc, disc_set.has(idx + 1) ? acc[idx] : acc[idx] + step], [0]);
425
+ // Use pymatgen's branches if available - they correctly handle discontinuities
426
+ // Otherwise, infer branches from discontinuities (robust fallback covering all qpoints)
427
+ const pmg_branches = pmg.branches;
428
+ let branches = [];
429
+ if (Array.isArray(pmg_branches) && pmg_branches.length > 0) {
430
+ // Validate and use pymatgen branches directly
431
+ branches = pmg_branches.filter((branch) => typeof branch.start_index === `number` &&
432
+ typeof branch.end_index === `number` &&
433
+ branch.start_index >= 0 &&
434
+ branch.end_index < qpoints.length &&
435
+ branch.start_index <= branch.end_index);
436
+ }
437
+ // Fallback: infer branches from discontinuities when none provided or all invalid
438
+ if (branches.length === 0) {
439
+ console.warn(`Band structure missing 'branches' field - inferring from path discontinuities`);
440
+ // Discontinuity indices mark points where the path jumps (disc before that index)
441
+ // Create continuous segments between discontinuities
442
+ const disc_indices = [...disc_set].sort((a, b) => a - b);
443
+ // Segment boundaries: [0, first_disc), [first_disc, second_disc), ..., [last_disc, end]
444
+ const segment_starts = [0, ...disc_indices];
445
+ const segment_ends = [...disc_indices.map((idx) => idx - 1), qpoints.length - 1];
446
+ branches = segment_starts
447
+ .map((start, idx) => {
448
+ const end = segment_ends[idx];
449
+ const start_label = qpoints[start]?.label ?? `?`;
450
+ const end_label = qpoints[end]?.label ?? `?`;
451
+ return {
452
+ start_index: start,
453
+ end_index: end,
454
+ name: `${start_label}-${end_label}`,
455
+ };
456
+ })
457
+ .filter((branch) => branch.start_index <= branch.end_index);
458
+ }
459
+ if (branches.length === 0) {
460
+ branches.push({ start_index: 0, end_index: qpoints.length - 1, name: `path` });
461
+ }
462
+ // Convert bands to THz based on input unit
463
+ const convert_to_thz = (val) => {
464
+ if (unit === `ev`)
465
+ return val * EV_TO_THZ;
466
+ if (unit === `cm-1`)
467
+ return val * CM_TO_THZ;
468
+ return val; // THz (default) - no conversion
469
+ };
470
+ const converted_bands = raw_bands.map((band) => band.map(convert_to_thz));
471
+ const valid_spin_down_bands = Array.isArray(raw_spin_down_bands) &&
472
+ raw_spin_down_bands.length === raw_bands.length &&
473
+ raw_spin_down_bands.every((band, band_idx) => Array.isArray(band) && band.length === raw_bands[band_idx]?.length)
474
+ ? raw_spin_down_bands
475
+ : null;
476
+ const converted_spin_down_bands = valid_spin_down_bands?.map((band) => band.map(convert_to_thz));
477
+ return {
478
+ qpoints,
479
+ branches,
480
+ distance,
481
+ bands: converted_bands,
482
+ spin_down_bands: converted_spin_down_bands,
483
+ nb_bands: raw_bands.length,
484
+ labels_dict: labels_dict ?? {},
485
+ recip_lattice: {
486
+ matrix: lattice_rec?.matrix ?? [
487
+ [1, 0, 0],
488
+ [0, 1, 0],
489
+ [0, 0, 1],
490
+ ],
491
+ },
492
+ };
493
+ }
494
+ export function normalize_band_structure(bs) {
495
+ if (!bs || typeof bs !== `object`)
496
+ return null;
497
+ const band_struct = bs;
498
+ // Check if this is pymatgen format and convert if so
499
+ if (is_pymatgen_format(band_struct)) {
500
+ return convert_pymatgen_band_structure(band_struct);
501
+ }
502
+ // Standard matterviz format validation
503
+ const { qpoints, branches, bands, distance } = band_struct;
504
+ if (!Array.isArray(qpoints) ||
505
+ !Array.isArray(branches) ||
506
+ !Array.isArray(bands) ||
507
+ !Array.isArray(distance))
508
+ return null;
509
+ // Validate array lengths and branch indices
510
+ const n_qpts = qpoints.length;
511
+ if (distance.length !== n_qpts ||
512
+ bands.some((band) => !Array.isArray(band) || band.length !== n_qpts) ||
513
+ branches.some((branch) => typeof branch.start_index !== `number` ||
514
+ typeof branch.end_index !== `number` ||
515
+ branch.start_index < 0 ||
516
+ branch.end_index >= n_qpts ||
517
+ branch.start_index > branch.end_index))
518
+ return null;
519
+ return band_struct;
520
+ }
521
+ // Validate and normalize a DOS object.
522
+ // Supports both matterviz and pymatgen formats.
523
+ // Also auto-detects and converts cm⁻¹ to THz for legacy data (disable with auto_convert_units: false).
524
+ export function normalize_dos(dos, options = {}) {
525
+ const { auto_convert_units = true } = options;
526
+ if (!dos || typeof dos !== `object`)
527
+ return null;
528
+ const dos_obj = dos;
529
+ // Check for pymatgen format (has @class or @module)
530
+ const is_pymatgen = typeof dos_obj[`@class`] === `string` || typeof dos_obj[`@module`] === `string`;
531
+ const { frequencies, energies, spin_polarized } = dos_obj;
532
+ // Handle densities as either array or dict with spin keys (pymatgen format)
533
+ // Pymatgen stores densities as {1: [...], -1: [...]} or {"Spin.up": [...], ...}
534
+ const spin_channels = extract_spin_channels(dos_obj.densities);
535
+ if (!spin_channels)
536
+ return null;
537
+ const densities = spin_channels.up;
538
+ // Use extracted spin-down or fallback to explicit field (for already-normalized DosData)
539
+ const spin_down_densities = spin_channels.down ?? dos_obj.spin_down_densities ?? null;
540
+ if (!Array.isArray(densities))
541
+ return null;
542
+ // Phonon DOS: has frequencies
543
+ if (Array.isArray(frequencies)) {
544
+ if (frequencies.length !== densities.length)
545
+ return null;
546
+ // Auto-detect if frequencies are in cm⁻¹ instead of THz (unless disabled)
547
+ // Typical phonon frequencies are < 50 THz for most materials
548
+ // If max frequency > 100, it's almost certainly in cm⁻¹
549
+ const max_freq = Math.max(...frequencies);
550
+ let final_frequencies = frequencies;
551
+ if (auto_convert_units && max_freq > 100) {
552
+ // Likely in cm⁻¹, convert to THz
553
+ final_frequencies = frequencies.map((frequency) => frequency * CM_TO_THZ);
554
+ console.warn(`Phonon DOS frequencies appear to be in cm⁻¹ (max: ${max_freq.toFixed(1)}). ` +
555
+ `Converting to THz (max: ${(max_freq * CM_TO_THZ).toFixed(1)} THz).`);
556
+ }
557
+ return { type: `phonon`, frequencies: final_frequencies, densities };
558
+ }
559
+ // Electronic DOS: has energies
560
+ if (Array.isArray(energies)) {
561
+ if (energies.length !== densities.length)
562
+ return null;
563
+ // Detect spin-polarized from data if not explicitly set
564
+ const is_spin_polarized = spin_polarized ??
565
+ (spin_down_densities !== null && spin_down_densities.length === densities.length);
566
+ return {
567
+ type: `electronic`,
568
+ energies,
569
+ densities,
570
+ spin_down_densities: is_spin_polarized ? (spin_down_densities ?? undefined) : undefined,
571
+ spin_polarized: is_spin_polarized,
572
+ };
573
+ }
574
+ // For pymatgen format, log a helpful message if format wasn't recognized
575
+ if (is_pymatgen) {
576
+ console.warn(`Pymatgen DOS format detected but missing required fields. ` +
577
+ `Expected 'frequencies' (phonon) or 'energies' (electronic) arrays.`);
578
+ }
579
+ return null;
580
+ }
581
+ // Extract k-path points from band structure and convert to reciprocal space coordinates
582
+ // Accepts a reciprocal lattice matrix (should include 2π factor for consistency with BZ)
583
+ // Handles both matterviz format (qpoints as objects) and normalized pymatgen format
584
+ // Optionally wraps fractional coordinates to first BZ (default: true)
585
+ export function extract_k_path_points(band_struct, recip_lattice_matrix, options = {}) {
586
+ const { wrap_to_bz = true } = options;
587
+ if (!band_struct?.qpoints || !recip_lattice_matrix)
588
+ return [];
589
+ if (recip_lattice_matrix.length !== 3 ||
590
+ recip_lattice_matrix.some((row) => row?.length !== 3))
591
+ throw new Error(`reciprocal_lattice_matrix must be a 3×3 matrix`);
592
+ const [[m00, m01, m02], [m10, m11, m12], [m20, m21, m22]] = recip_lattice_matrix;
593
+ return band_struct.qpoints.map((qpoint) => {
594
+ const [x, y, z] = qpoint.frac_coords;
595
+ const cart = [
596
+ x * m00 + y * m10 + z * m20,
597
+ x * m01 + y * m11 + z * m21,
598
+ x * m02 + y * m12 + z * m22,
599
+ ];
600
+ // Fold into the first (Wigner-Seitz) BZ so points stay inside the rendered zone.
601
+ // Folding in Cartesian space (vs per-axis on fractional coords, which only yields
602
+ // the parallelepiped cell) handles non-orthogonal lattices and preserves path
603
+ // continuity: points already inside the zone are left untouched.
604
+ return wrap_to_bz ? fold_to_first_bz(cart, recip_lattice_matrix) : cart;
605
+ });
606
+ }
607
+ // Fold a Cartesian reciprocal-space point into the first (Wigner-Seitz) Brillouin zone
608
+ // by choosing the periodic image with the smallest norm (minimum-image convention).
609
+ // The ±1 search (27 images) suffices for typical reciprocal lattices; extremely skewed
610
+ // cells could in principle need a wider search.
611
+ function fold_to_first_bz(cart, recip) {
612
+ let best = cart;
613
+ let best_norm = cart[0] ** 2 + cart[1] ** 2 + cart[2] ** 2;
614
+ for (let n1 = -1; n1 <= 1; n1++) {
615
+ for (let n2 = -1; n2 <= 1; n2++) {
616
+ for (let n3 = -1; n3 <= 1; n3++) {
617
+ if (n1 === 0 && n2 === 0 && n3 === 0)
618
+ continue;
619
+ const cand = [
620
+ cart[0] + n1 * recip[0][0] + n2 * recip[1][0] + n3 * recip[2][0],
621
+ cart[1] + n1 * recip[0][1] + n2 * recip[1][1] + n3 * recip[2][1],
622
+ cart[2] + n1 * recip[0][2] + n2 * recip[1][2] + n3 * recip[2][2],
623
+ ];
624
+ const norm = cand[0] ** 2 + cand[1] ** 2 + cand[2] ** 2;
625
+ if (norm < best_norm - 1e-9)
626
+ [best, best_norm] = [cand, norm];
627
+ }
628
+ }
629
+ }
630
+ return best;
631
+ }
632
+ // Find the q-point index closest to a given distance along the band structure path
633
+ export function find_qpoint_at_distance(band_struct, target) {
634
+ const { distance } = band_struct;
635
+ if (!distance?.length)
636
+ return null;
637
+ return distance.reduce((closest, dist, idx) => Math.abs(dist - target) < Math.abs(distance[closest] - target) ? idx : closest, 0);
638
+ }
639
+ // Rescaled x-position of a q-point index along the band plot path. Inverse of
640
+ // find_qpoint_at_rescaled_x, used to highlight a q-point hovered in the Brillouin zone.
641
+ // Returns null if the index doesn't fall on a plotted (non-discontinuity) branch.
642
+ export function qpoint_x_position(band_struct, qpoint_index, x_positions) {
643
+ if (!band_struct?.branches?.length || !x_positions)
644
+ return null;
645
+ for (const branch of band_struct.branches) {
646
+ if (qpoint_index < branch.start_index || qpoint_index > branch.end_index)
647
+ continue;
648
+ const start_label = band_struct.qpoints[branch.start_index]?.label ?? undefined;
649
+ const end_label = band_struct.qpoints[branch.end_index]?.label ?? undefined;
650
+ const range = x_positions[get_segment_key(start_label, end_label)];
651
+ if (!range)
652
+ continue;
653
+ const [x_start, x_end] = range;
654
+ const d_start = band_struct.distance[branch.start_index];
655
+ const d_end = band_struct.distance[branch.end_index];
656
+ if (d_end === d_start)
657
+ return x_start; // discontinuity / zero-length segment
658
+ const ratio = (band_struct.distance[qpoint_index] - d_start) / (d_end - d_start);
659
+ return x_start + ratio * (x_end - x_start);
660
+ }
661
+ return null;
662
+ }
663
+ // Find q-point index from rescaled x-coordinate (used in band structure plots)
664
+ // This handles the case where the plot uses custom x-axis scaling per segment
665
+ export function find_qpoint_at_rescaled_x(band_struct, rescaled_x, x_positions) {
666
+ if (!band_struct?.branches?.length || !x_positions)
667
+ return null;
668
+ // Find which segment contains this x coordinate
669
+ for (const branch of band_struct.branches) {
670
+ const start_idx = branch.start_index;
671
+ const end_idx = branch.end_index;
672
+ const start_label = band_struct.qpoints[start_idx]?.label ?? undefined;
673
+ const end_label = band_struct.qpoints[end_idx]?.label ?? undefined;
674
+ const segment_key = get_segment_key(start_label, end_label);
675
+ const segment_range = x_positions[segment_key];
676
+ if (!segment_range)
677
+ continue;
678
+ const [x_start, x_end] = segment_range;
679
+ // Check if discontinuity (zero-length segment)
680
+ const is_discontinuity = Math.abs(x_end - x_start) < 1e-6;
681
+ if (is_discontinuity) {
682
+ // For discontinuities, check if x is exactly at this point
683
+ if (Math.abs(rescaled_x - x_start) < 1e-6) {
684
+ return start_idx;
685
+ }
686
+ continue;
687
+ }
688
+ // Check if x is within this segment (with small tolerance for edges)
689
+ if (rescaled_x >= x_start - 1e-6 && rescaled_x <= x_end + 1e-6) {
690
+ // Map from rescaled x back to original distance
691
+ const segment_distances = band_struct.distance.slice(start_idx, end_idx + 1);
692
+ const dist_min = segment_distances[0];
693
+ const dist_max = segment_distances.at(-1) ?? dist_min;
694
+ const dist_range = dist_max - dist_min;
695
+ // Handle zero-length segments
696
+ if (dist_range === 0) {
697
+ return start_idx;
698
+ }
699
+ // Inverse of the scaling: x = x_start + ((dist - dist_min) / dist_range) * (x_end - x_start)
700
+ // Solving for dist: dist = dist_min + ((x - x_start) / (x_end - x_start)) * dist_range
701
+ const normalized_x = (rescaled_x - x_start) / (x_end - x_start);
702
+ const target_dist = dist_min + normalized_x * dist_range;
703
+ // Find closest qpoint in this branch to the target distance
704
+ let closest_idx = start_idx;
705
+ let min_diff = Math.abs(band_struct.distance[start_idx] - target_dist);
706
+ for (let idx = start_idx; idx <= end_idx; idx++) {
707
+ const diff = Math.abs(band_struct.distance[idx] - target_dist);
708
+ if (diff < min_diff) {
709
+ min_diff = diff;
710
+ closest_idx = idx;
711
+ }
712
+ }
713
+ return closest_idx;
714
+ }
715
+ }
716
+ // Fallback: find closest labeled point
717
+ let closest_idx = 0;
718
+ let min_dist = Infinity;
719
+ for (const branch of band_struct.branches) {
720
+ const start_idx = branch.start_index;
721
+ const end_idx = branch.end_index;
722
+ const start_label = band_struct.qpoints[start_idx]?.label ?? undefined;
723
+ const end_label = band_struct.qpoints[end_idx]?.label ?? undefined;
724
+ const segment_key = get_segment_key(start_label, end_label);
725
+ const segment_range = x_positions[segment_key];
726
+ if (!segment_range)
727
+ continue;
728
+ const [x_start, x_end] = segment_range;
729
+ for (const [x_pos, idx] of [
730
+ [x_start, start_idx],
731
+ [x_end, end_idx],
732
+ ]) {
733
+ const dist = Math.abs(rescaled_x - x_pos);
734
+ if (dist < min_dist) {
735
+ min_dist = dist;
736
+ closest_idx = idx;
737
+ }
738
+ }
739
+ }
740
+ return closest_idx;
741
+ }
742
+ // Extract projected DOS from pymatgen CompleteDos format.
743
+ // Returns a dict of label → DosData for each atom or orbital.
744
+ // filter_keys: optional list of keys to include (e.g., ["Fe", "O"] for atoms or ["s", "p", "d"] for orbitals)
745
+ export function extract_pdos(dos, pdos_type, filter_keys) {
746
+ if (!dos || typeof dos !== `object`)
747
+ return null;
748
+ const dos_obj = dos;
749
+ // Get the appropriate projected DOS dict
750
+ const pdos_dict = pdos_type === `atom`
751
+ ? dos_obj.atom_dos
752
+ : dos_obj.spd_dos;
753
+ if (!pdos_dict || typeof pdos_dict !== `object`)
754
+ return null;
755
+ const result = {};
756
+ for (const [key, nested_dos] of Object.entries(pdos_dict)) {
757
+ // Apply filter if provided
758
+ if (filter_keys && filter_keys.length > 0 && !filter_keys.includes(key))
759
+ continue;
760
+ if (!nested_dos || typeof nested_dos !== `object`)
761
+ continue;
762
+ const energies = nested_dos.energies;
763
+ const spin_channels = extract_spin_channels(nested_dos.densities);
764
+ if (!Array.isArray(energies) || !spin_channels)
765
+ continue;
766
+ const densities = spin_channels.up;
767
+ if (!Array.isArray(densities) || energies.length !== densities.length)
768
+ continue;
769
+ const is_spin_polarized = spin_channels.down !== null && spin_channels.down.length === densities.length;
770
+ result[key] = {
771
+ type: `electronic`,
772
+ energies,
773
+ densities,
774
+ spin_down_densities: is_spin_polarized ? (spin_channels.down ?? undefined) : undefined,
775
+ spin_polarized: is_spin_polarized,
776
+ efermi: nested_dos.efermi,
777
+ };
778
+ }
779
+ return Object.keys(result).length > 0 ? result : null;
780
+ }
781
+ // Shift a single DOS object's energies by the given amount
782
+ const shift_dos_energies = (dos, shift) => ({
783
+ ...dos,
784
+ efermi: dos.efermi - shift,
785
+ energies: dos.energies.map((energy) => energy - shift),
786
+ });
787
+ // Shift DOS energies relative to Fermi energy so E_F = 0
788
+ // Recursively shifts nested DOS in atom_dos and spd_dos for consistency
789
+ export function shift_to_fermi(dos) {
790
+ const shift = dos.efermi;
791
+ // Shift root DOS energies using the shared helper
792
+ const shifted_root = shift_dos_energies(dos, shift);
793
+ // Shift nested atom_dos if present
794
+ const atom_dos = dos.atom_dos
795
+ ? Object.fromEntries(Object.entries(dos.atom_dos).map(([key, nested_dos]) => [
796
+ key,
797
+ shift_dos_energies(nested_dos, shift),
798
+ ]))
799
+ : undefined;
800
+ // Shift nested spd_dos if present
801
+ const spd_dos = dos.spd_dos
802
+ ? Object.fromEntries(Object.entries(dos.spd_dos).map(([key, nested_dos]) => [
803
+ key,
804
+ shift_dos_energies(nested_dos, shift),
805
+ ]))
806
+ : undefined;
807
+ return {
808
+ ...shifted_root,
809
+ efermi: 0, // Explicitly set to 0 (shift_dos_energies would give efermi - shift)
810
+ ...(atom_dos && { atom_dos }),
811
+ ...(spd_dos && { spd_dos }),
812
+ };
813
+ }
814
+ // Generate an SVG path for a fat band ribbon.
815
+ // Creates a closed polygon by tracing the upper edge (y - half_width) forward,
816
+ // then tracing the lower edge (y + half_width) backward.
817
+ // Non-finite or non-positive widths are clamped to 0.
818
+ export function generate_ribbon_path(x_values, y_values, width_values, x_scale_fn, y_scale_fn, max_width_px, scale = 1) {
819
+ const len = x_values.length;
820
+ if (len < 2 || len !== y_values.length || len !== width_values.length)
821
+ return ``;
822
+ // Normalize width values to [0, 1] range based on the max positive finite value
823
+ const finite_positive_widths = width_values.filter((width) => Number.isFinite(width) && width > 0);
824
+ if (finite_positive_widths.length === 0)
825
+ return ``;
826
+ const max_width_val = Math.max(...finite_positive_widths);
827
+ // Build upper edge path (forward direction)
828
+ const upper_points = [];
829
+ const lower_points = [];
830
+ for (let idx = 0; idx < x_values.length; idx++) {
831
+ const x_px = x_scale_fn(x_values[idx]);
832
+ const y_data = y_values[idx];
833
+ const raw_width = width_values[idx] ?? 0;
834
+ const width_normalized = Number.isFinite(raw_width) && raw_width > 0 ? raw_width / max_width_val : 0;
835
+ const half_width_px = width_normalized * max_width_px * scale;
836
+ // In SVG, y increases downward, so upper edge has smaller y value
837
+ const y_upper_px = y_scale_fn(y_data) - half_width_px;
838
+ const y_lower_px = y_scale_fn(y_data) + half_width_px;
839
+ upper_points.push(`${x_px.toFixed(2)},${y_upper_px.toFixed(2)}`);
840
+ lower_points.push(`${x_px.toFixed(2)},${y_lower_px.toFixed(2)}`);
841
+ }
842
+ // Combine: upper edge forward, lower edge backward, close path
843
+ const path_parts = [
844
+ `M${upper_points[0]}`,
845
+ ...upper_points.slice(1).map((pt) => `L${pt}`),
846
+ ...lower_points.toReversed().map((pt) => `L${pt}`),
847
+ `Z`,
848
+ ];
849
+ return path_parts.join(` `);
850
+ }
851
+ // Extract efermi from a data source (band structure or DOS).
852
+ // Handles both single objects with an efermi field and dicts of objects.
853
+ // Returns undefined if no valid efermi is found or if the source is empty.
854
+ export function extract_efermi(data) {
855
+ if (!data || typeof data !== `object`)
856
+ return undefined;
857
+ const obj = data;
858
+ // Direct efermi field on the object
859
+ if (`efermi` in obj && typeof obj.efermi === `number`)
860
+ return obj.efermi;
861
+ // Dict of objects - try to get efermi from first value
862
+ const values = Object.values(obj);
863
+ if (values.length === 0)
864
+ return undefined;
865
+ const first_val = values[0];
866
+ if (first_val && typeof first_val === `object`) {
867
+ const efermi = first_val.efermi;
868
+ if (typeof efermi === `number`)
869
+ return efermi;
870
+ }
871
+ return undefined;
872
+ }
873
+ // Calculate fraction of |values| that are negative. Used to detect imaginary phonon modes.
874
+ export function negative_fraction(values) {
875
+ let [neg, total] = [0, 0];
876
+ for (const val of values) {
877
+ if (!Number.isFinite(val))
878
+ continue;
879
+ const abs_val = Math.abs(val);
880
+ total += abs_val;
881
+ if (val < 0)
882
+ neg += abs_val;
883
+ }
884
+ return total > 0 ? neg / total : 0;
885
+ }
886
+ // Check if raw band structure input has electronic markers (efermi, kpoints, or electronic @class).
887
+ // Must be called on raw input before normalization since these fields aren't preserved.
888
+ function is_electronic_band_struct(bs) {
889
+ if (!bs || typeof bs !== `object`)
890
+ return false;
891
+ const obj = bs;
892
+ // Electronic band structures have efermi field
893
+ if (`efermi` in obj && typeof obj.efermi === `number`)
894
+ return true;
895
+ // Pymatgen electronic format uses kpoints (not qpoints)
896
+ if (`kpoints` in obj && Array.isArray(obj.kpoints) && obj.kpoints.length > 0) {
897
+ return true;
898
+ }
899
+ // Pymatgen @class: BandStructure* but not Phonon*
900
+ const raw_class = obj[`@class`];
901
+ const py_class_name = typeof raw_class === `string` ? raw_class : ``;
902
+ if (py_class_name.startsWith(`BandStructure`) && !py_class_name.includes(`Phonon`)) {
903
+ return true;
904
+ }
905
+ return false;
906
+ }
907
+ // Compute frequency/energy range from bands and DOS. Clamps phonon min to 0 if noise < 0.5%.
908
+ export function compute_frequency_range(band_structs, doses, padding_factor = 0.02) {
909
+ let [min_val, max_val, is_phonon] = [Infinity, -Infinity, false];
910
+ const all_freqs = [];
911
+ // Check raw band_structs for electronic markers before normalization
912
+ // (normalized structures always have qpoints, so we can't detect from them)
913
+ let has_electronic_bs = false;
914
+ // Support both qpoints (phonon) and kpoints (electronic) to detect single vs dict
915
+ const is_single_bs = band_structs &&
916
+ typeof band_structs === `object` &&
917
+ (`qpoints` in band_structs || `kpoints` in band_structs);
918
+ if (band_structs && typeof band_structs === `object`) {
919
+ // Single structure check
920
+ if (is_electronic_band_struct(band_structs)) {
921
+ has_electronic_bs = true;
922
+ }
923
+ else if (!is_single_bs) {
924
+ // Dict of band structures - check each value
925
+ for (const bs_val of Object.values(band_structs)) {
926
+ if (is_electronic_band_struct(bs_val)) {
927
+ has_electronic_bs = true;
928
+ break;
929
+ }
930
+ }
931
+ }
932
+ }
933
+ const bs_list = band_structs
934
+ ? is_single_bs
935
+ ? [normalize_band_structure(band_structs)]
936
+ : Object.values(band_structs).map(normalize_band_structure)
937
+ : [];
938
+ // If band structures exist and aren't electronic, mark as phonon
939
+ const has_band_structs = bs_list.some(Boolean);
940
+ if (has_band_structs && !has_electronic_bs)
941
+ is_phonon = true;
942
+ for (const bs of bs_list) {
943
+ if (!bs)
944
+ continue;
945
+ for (const band of bs.bands) {
946
+ for (const val of band) {
947
+ if (!Number.isFinite(val))
948
+ continue;
949
+ all_freqs.push(val);
950
+ min_val = Math.min(min_val, val);
951
+ max_val = Math.max(max_val, val);
952
+ }
953
+ }
954
+ }
955
+ const dos_list = doses
956
+ ? `densities` in doses
957
+ ? [normalize_dos(doses)]
958
+ : Object.values(doses).map((dos) => normalize_dos(dos))
959
+ : [];
960
+ for (const dos of dos_list) {
961
+ if (!dos)
962
+ continue;
963
+ // DOS type detection: explicit type field is authoritative
964
+ if (dos.type === `phonon`)
965
+ is_phonon = true;
966
+ if (dos.type === `electronic`)
967
+ is_phonon = false;
968
+ for (const val of dos.type === `phonon` ? dos.frequencies : dos.energies) {
969
+ if (!Number.isFinite(val))
970
+ continue;
971
+ all_freqs.push(val);
972
+ min_val = Math.min(min_val, val);
973
+ max_val = Math.max(max_val, val);
974
+ }
975
+ }
976
+ if (!Number.isFinite(min_val) || !Number.isFinite(max_val))
977
+ return undefined;
978
+ const clamp_min = is_phonon &&
979
+ min_val < 0 && // clamp phonon noise to 0
980
+ negative_fraction(all_freqs) < IMAGINARY_MODE_NOISE_THRESHOLD;
981
+ if (clamp_min)
982
+ min_val = 0;
983
+ // Calculate padding from (possibly clamped) range for consistency with Bands.svelte
984
+ const padding = (max_val - min_val) * padding_factor;
985
+ return [min_val === 0 ? 0 : min_val - padding, max_val + padding];
986
+ }
987
+ // Parse axis label: "Frequency (THz)" → { name: "Frequency", unit: "THz" }
988
+ function parse_axis_label(label) {
989
+ const match = /^(.+?)\s*\(([^)]+)\)$/.exec(label);
990
+ return match ? { name: match[1], unit: match[2] } : { name: label };
991
+ }
992
+ const format_tooltip_line = (name, value, unit) => `${name}: ${value}${unit ? ` ${unit}` : ``}`;
993
+ // Format DOS tooltip content from axis labels and values
994
+ export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizontal, is_phonon, units, x_axis_label, y_axis_label, num_series) {
995
+ const x_parsed = parse_axis_label(x_axis_label);
996
+ const y_parsed = parse_axis_label(y_axis_label);
997
+ const freq_defaults = {
998
+ name: is_phonon ? `Frequency` : `Energy`,
999
+ unit: is_phonon ? units : `eV`,
1000
+ };
1001
+ const lines = is_horizontal
1002
+ ? [
1003
+ format_tooltip_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit ?? freq_defaults.unit),
1004
+ format_tooltip_line(x_parsed.name || `Density`, x_formatted),
1005
+ ]
1006
+ : [
1007
+ format_tooltip_line(y_parsed.name || `Density`, y_formatted),
1008
+ format_tooltip_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit ?? freq_defaults.unit),
1009
+ ];
1010
+ return { title: num_series > 1 && label ? label : undefined, lines };
1011
+ }
1012
+ // Spin mode options for DOS visualization
1013
+ export const SPIN_MODES = [
1014
+ { value: `mirror`, label: `↕`, title: `Mirror: spin-up above, spin-down below zero` },
1015
+ { value: `overlay`, label: `≡`, title: `Overlay: both spins on same axis` },
1016
+ { value: `up_only`, label: `↑`, title: `Show spin-up only` },
1017
+ { value: `down_only`, label: `↓`, title: `Show spin-down only` },
1018
+ ];
1019
+ // Normalization mode options
1020
+ export const NORMALIZATION_MODES = [
1021
+ { value: null, label: `None` },
1022
+ { value: `max`, label: `Max=1` },
1023
+ { value: `sum`, label: `Sum=1` },
1024
+ { value: `integral`, label: `∫=1` },
1025
+ ];
1026
+ // Available frequency units for phonon DOS
1027
+ export const FREQUENCY_UNITS = [`THz`, `eV`, `meV`, `cm-1`, `Ha`];
1028
+ // Default values for DOS controls
1029
+ export const DEFAULT_SPIN_MODE = `mirror`;
1030
+ export const DEFAULT_SIGMA = 0;
1031
+ export const DEFAULT_NORMALIZE = null;
1032
+ export const DEFAULT_UNITS = `THz`;
1033
+ // Format sigma with adaptive precision: 0→"0", <0.01→exp, <1→3dp, else→2dp
1034
+ export function format_sigma(val) {
1035
+ if (val === 0)
1036
+ return `0`;
1037
+ if (val < 0.01)
1038
+ return val.toExponential(1);
1039
+ return val.toFixed(val < 1 ? 3 : 2);
1040
+ }
1041
+ // Validate sigma_range: ensures min < max, returns [0, 1] if invalid
1042
+ export const validate_sigma_range = ([min, max]) => Number.isFinite(min) && Number.isFinite(max) && min < max ? [min, max] : [0, 1];
1043
+ // Calculate slider step: 1/100th of range, or 0.01 fallback
1044
+ export function calculate_sigma_step(range) {
1045
+ const [min, max] = validate_sigma_range(range);
1046
+ return (max - min) / 100 || 0.01;
1047
+ }
1048
+ // Central difference for local slope (dω/dk or dE/dk).
1049
+ // Uses forward/backward difference at endpoints, central difference for interior points.
1050
+ export function compute_slope(x_vals, y_vals, idx) {
1051
+ const len = Math.min(x_vals.length, y_vals.length);
1052
+ if (len < 2 || idx < 0 || idx >= len)
1053
+ return null;
1054
+ const lo = idx === 0 ? 0 : idx - 1;
1055
+ const hi = idx >= len - 1 ? len - 1 : idx + 1;
1056
+ const dx = x_vals[hi] - x_vals[lo];
1057
+ return dx ? (y_vals[hi] - y_vals[lo]) / dx : null;
1058
+ }
1059
+ // Find Gamma-point indices (q ≈ integer lattice point) in a band structure.
1060
+ // Returns indices of q-points whose fractional coordinates are all within 0.01 of integers.
1061
+ export function find_gamma_indices(bs) {
1062
+ const indices = [];
1063
+ for (let q_idx = 0; q_idx < bs.qpoints.length; q_idx++) {
1064
+ const coords = bs.qpoints[q_idx]?.frac_coords;
1065
+ if (coords?.every((coord) => Math.abs(coord - Math.round(coord)) < 0.01)) {
1066
+ indices.push(q_idx);
1067
+ }
1068
+ }
1069
+ return indices;
1070
+ }
1071
+ // Threshold below which a band's frequency at Gamma is considered acoustic (THz).
1072
+ // Assumes bands are stored in THz (normalize_band_structure converts to THz).
1073
+ export const ACOUSTIC_FREQ_THRESHOLD = 0.5;
1074
+ // Classify a band as acoustic based on near-zero frequency at Gamma points.
1075
+ // Returns true (acoustic), false (optical), or null (no Gamma points → can't determine).
1076
+ export function classify_acoustic(bs, band_idx, gamma_indices, threshold = ACOUSTIC_FREQ_THRESHOLD) {
1077
+ if (gamma_indices.length === 0)
1078
+ return null;
1079
+ return gamma_indices.some((gamma_idx) => Math.abs(bs.bands[band_idx]?.[gamma_idx] ?? Infinity) < threshold);
1080
+ }
1081
+ // Build per-point metadata array for a band series in the tooltip.
1082
+ export function build_point_metadata(opts) {
1083
+ const { x_vals, y_vals, band_idx, spin, is_acoustic, bs, start_idx } = opts;
1084
+ return x_vals.map((_, pt_idx) => {
1085
+ const global_idx = start_idx + pt_idx;
1086
+ const qpoint = bs.qpoints[global_idx];
1087
+ return {
1088
+ band_idx,
1089
+ spin,
1090
+ is_acoustic,
1091
+ nb_bands: bs.nb_bands,
1092
+ frac_coords: qpoint?.frac_coords ?? null,
1093
+ qpoint_label: qpoint?.label ?? null,
1094
+ band_width: bs.band_widths?.[band_idx]?.[global_idx] ?? null,
1095
+ slope: compute_slope(x_vals, y_vals, pt_idx),
1096
+ };
1097
+ });
1098
+ }