matterviz 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/EmptyState.svelte +10 -4
  2. package/dist/FilePicker.svelte +12 -14
  3. package/dist/Icon.svelte +7 -4
  4. package/dist/MillerIndexInput.svelte +2 -2
  5. package/dist/app.css +53 -0
  6. package/dist/brillouin/BrillouinZone.svelte +75 -85
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
  8. package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
  9. package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
  10. package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
  11. package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
  12. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  13. package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
  14. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
  15. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
  16. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
  17. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
  18. package/dist/chempot-diagram/async-compute.svelte.js +1 -1
  19. package/dist/chempot-diagram/controls-state.svelte.js +1 -1
  20. package/dist/colors/index.d.ts +0 -4
  21. package/dist/colors/index.js +19 -20
  22. package/dist/composition/BarChart.svelte +37 -31
  23. package/dist/composition/BubbleChart.svelte +17 -17
  24. package/dist/composition/Composition.svelte +7 -11
  25. package/dist/composition/Formula.svelte +18 -25
  26. package/dist/composition/FormulaFilter.svelte +92 -95
  27. package/dist/composition/PieChart.svelte +55 -41
  28. package/dist/composition/format.js +1 -1
  29. package/dist/composition/index.d.ts +2 -0
  30. package/dist/composition/index.js +14 -0
  31. package/dist/composition/parse.d.ts +2 -2
  32. package/dist/composition/parse.js +11 -10
  33. package/dist/constants.js +11 -9
  34. package/dist/convex-hull/ConvexHull.svelte +12 -15
  35. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  36. package/dist/convex-hull/ConvexHull2D.svelte +93 -92
  37. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  38. package/dist/convex-hull/ConvexHull3D.svelte +109 -140
  39. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  40. package/dist/convex-hull/ConvexHull4D.svelte +75 -94
  41. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  42. package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
  43. package/dist/convex-hull/ConvexHullControls.svelte +46 -48
  44. package/dist/convex-hull/ConvexHullStats.svelte +193 -195
  45. package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
  46. package/dist/convex-hull/GasPressureControls.svelte +5 -12
  47. package/dist/convex-hull/StructurePopup.svelte +17 -21
  48. package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
  49. package/dist/convex-hull/TemperatureSlider.svelte +4 -10
  50. package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
  51. package/dist/convex-hull/helpers.d.ts +8 -10
  52. package/dist/convex-hull/helpers.js +36 -36
  53. package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
  54. package/dist/convex-hull/thermodynamics.js +18 -17
  55. package/dist/coordination/CoordinationBarPlot.svelte +38 -33
  56. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  57. package/dist/coordination/calc-coordination.d.ts +1 -1
  58. package/dist/coordination/calc-coordination.js +28 -25
  59. package/dist/element/BohrAtom.svelte +5 -8
  60. package/dist/element/ElementHeading.svelte +4 -1
  61. package/dist/element/ElementPhoto.svelte +11 -9
  62. package/dist/element/ElementStats.svelte +12 -10
  63. package/dist/element/ElementTile.svelte +24 -29
  64. package/dist/element/Nucleus.svelte +4 -2
  65. package/dist/element/data.d.ts +1 -2
  66. package/dist/element/helpers.d.ts +4 -0
  67. package/dist/element/helpers.js +18 -0
  68. package/dist/element/index.d.ts +1 -4
  69. package/dist/element/index.js +3 -18
  70. package/dist/feedback/DragOverlay.svelte +5 -5
  71. package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
  72. package/dist/feedback/StatusMessage.svelte +7 -4
  73. package/dist/fermi-surface/FermiSlice.svelte +21 -18
  74. package/dist/fermi-surface/FermiSurface.svelte +14 -22
  75. package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
  76. package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
  77. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  78. package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
  79. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  80. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
  81. package/dist/fermi-surface/compute.js +3 -3
  82. package/dist/fermi-surface/parse.js +22 -24
  83. package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
  84. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
  85. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
  86. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
  87. package/dist/heatmap-matrix/index.d.ts +5 -0
  88. package/dist/icons.d.ts +4 -0
  89. package/dist/icons.js +4 -0
  90. package/dist/io/ExportPane.svelte +10 -6
  91. package/dist/io/decompress.d.ts +2 -1
  92. package/dist/io/decompress.js +22 -35
  93. package/dist/io/export.d.ts +4 -0
  94. package/dist/io/export.js +5 -1
  95. package/dist/io/fetch.d.ts +0 -3
  96. package/dist/io/fetch.js +0 -11
  97. package/dist/io/index.d.ts +0 -1
  98. package/dist/io/index.js +2 -9
  99. package/dist/io/is-binary.d.ts +9 -0
  100. package/dist/io/is-binary.js +45 -1
  101. package/dist/io/url-drop.js +13 -25
  102. package/dist/isosurface/Isosurface.svelte +17 -23
  103. package/dist/isosurface/IsosurfaceControls.svelte +37 -42
  104. package/dist/isosurface/parse-vaspwave.d.ts +3 -0
  105. package/dist/isosurface/parse-vaspwave.js +138 -0
  106. package/dist/isosurface/parse.js +6 -6
  107. package/dist/labels.d.ts +6 -2
  108. package/dist/labels.js +43 -13
  109. package/dist/layout/FullscreenButton.svelte +2 -1
  110. package/dist/layout/FullscreenToggle.svelte +10 -4
  111. package/dist/layout/InfoCard.svelte +7 -18
  112. package/dist/layout/InfoTag.svelte +1 -3
  113. package/dist/layout/NumberRangeInput.svelte +46 -0
  114. package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
  115. package/dist/layout/PropertyFilter.svelte +2 -6
  116. package/dist/layout/SettingsSection.svelte +21 -17
  117. package/dist/layout/SubpageGrid.svelte +3 -1
  118. package/dist/layout/ViewerChrome.svelte +9 -10
  119. package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
  120. package/dist/layout/fullscreen.js +3 -5
  121. package/dist/layout/fullscreen.svelte.js +1 -2
  122. package/dist/layout/index.d.ts +1 -0
  123. package/dist/layout/index.js +1 -0
  124. package/dist/layout/json-tree/JsonNode.svelte +8 -11
  125. package/dist/layout/json-tree/JsonTree.svelte +53 -77
  126. package/dist/layout/json-tree/JsonValue.svelte +7 -15
  127. package/dist/layout/json-tree/utils.js +14 -23
  128. package/dist/math.d.ts +2 -0
  129. package/dist/math.js +19 -0
  130. package/dist/overlays/ContextMenu.svelte +4 -2
  131. package/dist/overlays/CopyButton.svelte +11 -5
  132. package/dist/overlays/DragControlTab.svelte +6 -1
  133. package/dist/overlays/DraggablePane.svelte +81 -26
  134. package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
  135. package/dist/overlays/GlassChip.svelte +30 -0
  136. package/dist/overlays/GlassChip.svelte.d.ts +8 -0
  137. package/dist/overlays/InfoPaneCards.svelte +11 -23
  138. package/dist/overlays/index.d.ts +7 -0
  139. package/dist/overlays/index.js +26 -0
  140. package/dist/overlays/portal.d.ts +2 -0
  141. package/dist/overlays/portal.js +14 -0
  142. package/dist/periodic-table/PeriodicTable.svelte +113 -145
  143. package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
  144. package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
  145. package/dist/periodic-table/TableInset.svelte +9 -4
  146. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
  147. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
  148. package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
  149. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  150. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  151. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
  152. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
  153. package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
  154. package/dist/phase-diagram/build-diagram.js +3 -3
  155. package/dist/phase-diagram/diagram-input.d.ts +1 -2
  156. package/dist/phase-diagram/parse.js +15 -15
  157. package/dist/phase-diagram/svg-to-diagram.js +21 -15
  158. package/dist/phase-diagram/utils.js +2 -3
  159. package/dist/plot/bar/BarPlot.svelte +430 -391
  160. package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
  161. package/dist/plot/bar/BarPlotControls.svelte +1 -3
  162. package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
  163. package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
  164. package/dist/plot/bar/data.d.ts +5 -4
  165. package/dist/plot/bar/data.js +2 -1
  166. package/dist/plot/box/BoxPlot.svelte +301 -209
  167. package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
  168. package/dist/plot/box/Violin.svelte.d.ts +1 -0
  169. package/dist/plot/box/box-plot.js +1 -1
  170. package/dist/plot/core/auto-place.js +1 -1
  171. package/dist/plot/core/axis-utils.d.ts +12 -7
  172. package/dist/plot/core/axis-utils.js +48 -48
  173. package/dist/plot/core/components/AxisLabel.svelte +82 -20
  174. package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
  175. package/dist/plot/core/components/ColorBar.svelte +101 -106
  176. package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
  177. package/dist/plot/core/components/FillArea.svelte +10 -17
  178. package/dist/plot/core/components/HierarchyControls.svelte +249 -0
  179. package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
  180. package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
  181. package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
  182. package/dist/plot/core/components/Line.svelte +18 -9
  183. package/dist/plot/core/components/Line.svelte.d.ts +2 -0
  184. package/dist/plot/core/components/PlotAxis.svelte +40 -17
  185. package/dist/plot/core/components/PlotControls.svelte +65 -41
  186. package/dist/plot/core/components/PlotLegend.svelte +31 -35
  187. package/dist/plot/core/components/PlotMarginals.svelte +616 -0
  188. package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
  189. package/dist/plot/core/components/PlotTooltip.svelte +1 -1
  190. package/dist/plot/core/components/PortalSelect.svelte +4 -8
  191. package/dist/plot/core/components/ReferenceLine.svelte +27 -24
  192. package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
  193. package/dist/plot/core/components/ReferencePlane.svelte +7 -8
  194. package/dist/plot/core/components/ZeroLines.svelte +4 -8
  195. package/dist/plot/core/components/ZoomRect.svelte +1 -2
  196. package/dist/plot/core/components/index.d.ts +1 -0
  197. package/dist/plot/core/components/index.js +1 -0
  198. package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
  199. package/dist/plot/core/data-cleaning-signal.js +467 -0
  200. package/dist/plot/core/data-cleaning.d.ts +2 -42
  201. package/dist/plot/core/data-cleaning.js +27 -474
  202. package/dist/plot/core/data-transform.js +9 -5
  203. package/dist/plot/core/fill-utils.d.ts +3 -1
  204. package/dist/plot/core/fill-utils.js +28 -6
  205. package/dist/plot/core/index.d.ts +1 -0
  206. package/dist/plot/core/index.js +1 -0
  207. package/dist/plot/core/interactions.js +0 -2
  208. package/dist/plot/core/layout.d.ts +3 -1
  209. package/dist/plot/core/layout.js +22 -13
  210. package/dist/plot/core/marginals.d.ts +170 -0
  211. package/dist/plot/core/marginals.js +436 -0
  212. package/dist/plot/core/reference-line.js +1 -1
  213. package/dist/plot/core/scales.d.ts +23 -0
  214. package/dist/plot/core/scales.js +39 -13
  215. package/dist/plot/core/types/fills.d.ts +101 -0
  216. package/dist/plot/core/types/fills.js +15 -0
  217. package/dist/plot/core/types/plot-3d.d.ts +87 -0
  218. package/dist/plot/core/types/plot-3d.js +4 -0
  219. package/dist/plot/core/types/reference-lines.d.ts +140 -0
  220. package/dist/plot/core/types/reference-lines.js +9 -0
  221. package/dist/plot/core/types.d.ts +29 -324
  222. package/dist/plot/core/types.js +23 -20
  223. package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
  224. package/dist/plot/core/utils/hierarchy-chart.js +179 -0
  225. package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
  226. package/dist/plot/core/utils/hierarchy-labels.js +99 -0
  227. package/dist/plot/core/utils/label-placement.js +2 -2
  228. package/dist/plot/histogram/Histogram.svelte +304 -325
  229. package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
  230. package/dist/plot/histogram/HistogramControls.svelte +30 -28
  231. package/dist/plot/histogram/histogram.d.ts +31 -0
  232. package/dist/plot/histogram/histogram.js +70 -0
  233. package/dist/plot/histogram/index.d.ts +1 -0
  234. package/dist/plot/histogram/index.js +1 -0
  235. package/dist/plot/index.d.ts +1 -0
  236. package/dist/plot/index.js +1 -0
  237. package/dist/plot/sankey/Sankey.svelte +78 -69
  238. package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
  239. package/dist/plot/sankey/SankeyControls.svelte +22 -16
  240. package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
  241. package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
  242. package/dist/plot/scatter/ElementScatter.svelte +4 -1
  243. package/dist/plot/scatter/ScatterPlot.svelte +477 -385
  244. package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
  245. package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
  246. package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
  247. package/dist/plot/scatter/ScatterPoint.svelte +16 -9
  248. package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
  249. package/dist/plot/scatter/binned-scatter-types.js +6 -1
  250. package/dist/plot/scatter/scatter-data.d.ts +1 -1
  251. package/dist/plot/scatter/scatter-data.js +8 -7
  252. package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
  253. package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
  254. package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
  255. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
  256. package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
  257. package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
  258. package/dist/plot/sunburst/Sunburst.svelte +251 -329
  259. package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
  260. package/dist/plot/sunburst/index.d.ts +1 -1
  261. package/dist/plot/sunburst/index.js +2 -1
  262. package/dist/plot/sunburst/render.d.ts +2 -2
  263. package/dist/plot/sunburst/render.js +47 -22
  264. package/dist/plot/sunburst/sunburst.d.ts +5 -1
  265. package/dist/plot/sunburst/sunburst.js +10 -3
  266. package/dist/plot/treemap/Treemap.svelte +907 -0
  267. package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
  268. package/dist/plot/treemap/index.d.ts +3 -0
  269. package/dist/plot/treemap/index.js +4 -0
  270. package/dist/plot/treemap/treemap.d.ts +26 -0
  271. package/dist/plot/treemap/treemap.js +99 -0
  272. package/dist/rdf/RdfPlot.svelte +22 -26
  273. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  274. package/dist/rdf/calc-rdf.js +4 -8
  275. package/dist/sanitize.js +1 -1
  276. package/dist/scene/bind-renderer.svelte.js +14 -6
  277. package/dist/settings.d.ts +19 -9
  278. package/dist/settings.js +77 -50
  279. package/dist/spectral/Bands.svelte +223 -230
  280. package/dist/spectral/BandsAndDos.svelte +11 -9
  281. package/dist/spectral/BrillouinBandsDos.svelte +19 -27
  282. package/dist/spectral/Dos.svelte +70 -73
  283. package/dist/spectral/helpers.d.ts +3 -3
  284. package/dist/spectral/helpers.js +25 -35
  285. package/dist/state.svelte.js +5 -18
  286. package/dist/structure/Arrow.svelte +5 -18
  287. package/dist/structure/ArrowInstances.svelte +160 -0
  288. package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
  289. package/dist/structure/AtomLegend.svelte +115 -75
  290. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  291. package/dist/structure/Bond.svelte +31 -23
  292. package/dist/structure/CanvasTooltip.svelte +15 -3
  293. package/dist/structure/CellSelect.svelte +11 -26
  294. package/dist/structure/Cylinder.svelte +24 -40
  295. package/dist/structure/InstancedAtoms.svelte +114 -0
  296. package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
  297. package/dist/structure/Lattice.svelte +85 -149
  298. package/dist/structure/SiteLabels.svelte +122 -0
  299. package/dist/structure/SiteLabels.svelte.d.ts +18 -0
  300. package/dist/structure/Structure.svelte +473 -419
  301. package/dist/structure/Structure.svelte.d.ts +4 -2
  302. package/dist/structure/StructureCarousel.svelte +630 -0
  303. package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
  304. package/dist/structure/StructureControls.svelte +157 -399
  305. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  306. package/dist/structure/StructureExportPane.svelte +17 -21
  307. package/dist/structure/StructureInfoPane.svelte +72 -66
  308. package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
  309. package/dist/structure/StructureScene.svelte +467 -476
  310. package/dist/structure/StructureScene.svelte.d.ts +3 -1
  311. package/dist/structure/StructureViewport.svelte +386 -0
  312. package/dist/structure/StructureViewport.svelte.d.ts +63 -0
  313. package/dist/structure/atom-label-placement.d.ts +16 -12
  314. package/dist/structure/atom-label-placement.js +70 -37
  315. package/dist/structure/atom-properties.d.ts +2 -0
  316. package/dist/structure/atom-properties.js +104 -38
  317. package/dist/structure/bonding.d.ts +10 -3
  318. package/dist/structure/bonding.js +84 -28
  319. package/dist/structure/edit-history.d.ts +6 -0
  320. package/dist/structure/edit-history.js +27 -0
  321. package/dist/structure/export.d.ts +1 -0
  322. package/dist/structure/export.js +39 -31
  323. package/dist/structure/format-detect.d.ts +1 -0
  324. package/dist/structure/format-detect.js +22 -0
  325. package/dist/structure/geometry.d.ts +9 -0
  326. package/dist/structure/geometry.js +27 -0
  327. package/dist/structure/index.d.ts +16 -1
  328. package/dist/structure/index.js +13 -2
  329. package/dist/structure/measure.d.ts +1 -1
  330. package/dist/structure/measure.js +6 -12
  331. package/dist/structure/parse.d.ts +2 -1
  332. package/dist/structure/parse.js +243 -222
  333. package/dist/structure/partial-occupancy.js +4 -2
  334. package/dist/structure/pbc.js +78 -98
  335. package/dist/structure/polyhedra.d.ts +0 -1
  336. package/dist/structure/polyhedra.js +3 -18
  337. package/dist/structure/supercell.d.ts +1 -2
  338. package/dist/structure/supercell.js +7 -13
  339. package/dist/symmetry/SymmetryElements.svelte +11 -15
  340. package/dist/symmetry/SymmetryStats.svelte +56 -68
  341. package/dist/symmetry/WyckoffTable.svelte +5 -24
  342. package/dist/symmetry/cell-transform.js +1 -0
  343. package/dist/symmetry/index.d.ts +1 -0
  344. package/dist/symmetry/index.js +8 -2
  345. package/dist/symmetry/spacegroups.js +3 -2
  346. package/dist/table/HeatmapTable.svelte +1102 -365
  347. package/dist/table/HeatmapTable.svelte.d.ts +12 -2
  348. package/dist/table/ToggleMenu.svelte +5 -12
  349. package/dist/table/index.d.ts +21 -6
  350. package/dist/table/index.js +34 -21
  351. package/dist/theme/ThemeControl.svelte +16 -8
  352. package/dist/theme/index.d.ts +1 -5
  353. package/dist/theme/index.js +4 -10
  354. package/dist/theme/themes.mjs +14 -7
  355. package/dist/tooltip/KCoords.svelte +4 -1
  356. package/dist/tooltip/TooltipContent.svelte +2 -5
  357. package/dist/trajectory/Trajectory.svelte +515 -308
  358. package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
  359. package/dist/trajectory/TrajectoryError.svelte +11 -8
  360. package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
  361. package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
  362. package/dist/trajectory/extract.js +56 -34
  363. package/dist/trajectory/format-detect.js +11 -9
  364. package/dist/trajectory/frame-reader.d.ts +2 -0
  365. package/dist/trajectory/frame-reader.js +33 -29
  366. package/dist/trajectory/helpers.d.ts +2 -0
  367. package/dist/trajectory/helpers.js +18 -7
  368. package/dist/trajectory/index.d.ts +1 -0
  369. package/dist/trajectory/index.js +3 -0
  370. package/dist/trajectory/parse/h5-utils.d.ts +13 -0
  371. package/dist/trajectory/parse/h5-utils.js +109 -0
  372. package/dist/trajectory/parse/hdf5.d.ts +1 -1
  373. package/dist/trajectory/parse/hdf5.js +116 -106
  374. package/dist/trajectory/parse/index.d.ts +2 -3
  375. package/dist/trajectory/parse/index.js +17 -20
  376. package/dist/trajectory/parse/lammps.js +8 -12
  377. package/dist/trajectory/parse/vasp.js +10 -7
  378. package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
  379. package/dist/trajectory/parse/vaspout-electronic.js +207 -0
  380. package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
  381. package/dist/trajectory/parse/vaspout-h5.js +284 -0
  382. package/dist/trajectory/parse/xyz.js +11 -7
  383. package/dist/trajectory/plotting.d.ts +8 -9
  384. package/dist/trajectory/plotting.js +99 -27
  385. package/dist/utils.d.ts +3 -0
  386. package/dist/utils.js +7 -0
  387. package/dist/xrd/XrdPlot.svelte +47 -61
  388. package/dist/xrd/broadening.js +2 -1
  389. package/dist/xrd/calc-xrd.js +2 -4
  390. package/dist/xrd/parse.d.ts +0 -1
  391. package/dist/xrd/parse.js +56 -73
  392. package/package.json +61 -33
  393. package/dist/api/mp.d.ts +0 -6
  394. package/dist/api/mp.js +0 -22
  395. package/dist/plot/sunburst/SunburstControls.svelte +0 -200
@@ -1,402 +1,25 @@
1
1
  // Data cleaning utilities for plot data
2
- // Detects oscillations, enforces physical bounds, and handles multi-dimensional datasets
2
+ // Enforces physical bounds, handles invalid values, and cleans multi-dimensional datasets.
3
+ // Signal-processing primitives (variance, instability detection, smoothing, outlier removal)
4
+ // live in ./data-cleaning-signal and are re-exported here so the public API is unchanged.
3
5
  import { apply_gaussian_smearing } from '../../spectral/helpers';
4
- // Default configuration values
5
- const DEFAULT_WINDOW_SIZE = 5;
6
- const DEFAULT_OSCILLATION_THRESHOLD = 3.0;
7
- const DEFAULT_POLYNOMIAL_ORDER = 2;
8
- // --- Core Detection Functions ---
9
- // Compute rolling variance using Welford's online algorithm - O(n)
10
- // Returns variance for each point based on surrounding window
11
- export function compute_local_variance(values, window_size) {
12
- const len = values.length;
13
- if (len === 0)
14
- return [];
15
- if (len === 1)
16
- return [0];
17
- const half_window = Math.floor(window_size / 2);
18
- const result = Array(len);
19
- // Single pass for each index, no slice allocation (avoids O(n × window) allocations)
20
- for (let idx = 0; idx < len; idx++) {
21
- const start = Math.max(0, idx - half_window);
22
- const end = Math.min(len, idx + half_window + 1);
23
- // Welford's online variance calculation
24
- let [mean, m2, count] = [0, 0, 0];
25
- for (let jdx = start; jdx < end; jdx++) {
26
- const val = values[jdx];
27
- if (!Number.isFinite(val))
28
- continue;
29
- count++;
30
- const delta = val - mean;
31
- mean += delta / count;
32
- const delta2 = val - mean;
33
- m2 += delta * delta2;
34
- }
35
- result[idx] = count > 1 ? m2 / (count - 1) : 0;
36
- }
37
- return result;
38
- }
39
- // Compute first-order finite differences (discrete derivative)
40
- function compute_derivatives(values) {
41
- if (values.length < 2)
42
- return [];
43
- const derivs = Array(values.length - 1);
44
- for (let idx = 0; idx < values.length - 1; idx++) {
45
- derivs[idx] = values[idx + 1] - values[idx];
46
- }
47
- return derivs;
48
- }
49
- // Detect derivative variance spikes (method 1)
50
- // Returns onset index where derivative variance exceeds threshold
51
- function detect_derivative_variance(values, window_size, threshold_multiplier) {
52
- const derivs = compute_derivatives(values);
53
- if (derivs.length < window_size) {
54
- return { onset_index: -1, score: 0 };
55
- }
56
- const local_var = compute_local_variance(derivs, window_size);
57
- // Compute baseline variance from first stable portion
58
- const baseline_end = Math.min(Math.floor(derivs.length / 4), 50);
59
- const baseline_vars = local_var.slice(0, Math.max(baseline_end, window_size));
60
- const baseline_median = median(baseline_vars.filter((val) => val > 0));
61
- if (baseline_median === 0) {
62
- return { onset_index: -1, score: 0 };
63
- }
64
- // Find first point where variance exceeds threshold
65
- let max_score = 0;
66
- for (let idx = baseline_end; idx < local_var.length; idx++) {
67
- const ratio = local_var[idx] / baseline_median;
68
- if (ratio > max_score)
69
- max_score = ratio;
70
- if (ratio > threshold_multiplier) {
71
- return { onset_index: idx + 1, score: ratio }; // +1 to convert from deriv index to value index
72
- }
73
- }
74
- return { onset_index: -1, score: max_score };
75
- }
76
- // Detect exponential amplitude growth (method 2)
77
- // Looks for values growing exponentially from their mean
78
- function detect_amplitude_growth(values, window_size) {
79
- if (values.length < window_size * 3) {
80
- return { onset_index: -1, score: 0 };
81
- }
82
- // Compute running amplitude (deviation from local mean)
83
- const amplitudes = [];
84
- const half_window = Math.floor(window_size / 2);
85
- for (let idx = half_window; idx < values.length - half_window; idx++) {
86
- const start = idx - half_window;
87
- const end = idx + half_window + 1;
88
- const window_len = end - start;
89
- // Compute local mean without slice allocation
90
- let sum = 0;
91
- for (let jdx = start; jdx < end; jdx++)
92
- sum += values[jdx];
93
- const local_mean = sum / window_len;
94
- // Find max deviation without slice allocation
95
- let max_deviation = 0;
96
- for (let jdx = start; jdx < end; jdx++) {
97
- const deviation = Math.abs(values[jdx] - local_mean);
98
- if (deviation > max_deviation)
99
- max_deviation = deviation;
100
- }
101
- amplitudes.push(max_deviation);
102
- }
103
- if (amplitudes.length < 10) {
104
- return { onset_index: -1, score: 0 };
105
- }
106
- // Detect exponential growth by checking if amplitude ratio increases
107
- const baseline_amp = median(amplitudes.slice(0, Math.floor(amplitudes.length / 4)));
108
- if (baseline_amp === 0) {
109
- return { onset_index: -1, score: 0 };
110
- }
111
- let max_score = 0;
112
- for (let idx = Math.floor(amplitudes.length / 4); idx < amplitudes.length; idx++) {
113
- const ratio = amplitudes[idx] / baseline_amp;
114
- if (ratio > max_score)
115
- max_score = ratio;
116
- // Exponential growth threshold: amplitude 10x baseline
117
- if (ratio > 10) {
118
- return { onset_index: idx + half_window, score: ratio / 10 };
119
- }
120
- }
121
- return { onset_index: -1, score: max_score / 10 };
122
- }
123
- // Count derivative sign changes per window (method 3)
124
- // Detects high-frequency oscillations
125
- function detect_sign_change_frequency(values, window_size, max_changes_per_window = 3) {
126
- const derivs = compute_derivatives(values);
127
- if (derivs.length < window_size * 2) {
128
- return { onset_index: -1, score: 0 };
129
- }
130
- // Count sign changes in sliding windows
131
- const half_window = Math.floor(window_size / 2);
132
- let max_score = 0;
133
- for (let idx = half_window; idx < derivs.length - half_window; idx++) {
134
- const start = idx - half_window;
135
- const end = idx + half_window + 1;
136
- let sign_changes = 0;
137
- // Count sign changes without slice allocation
138
- for (let jdx = start + 1; jdx < end; jdx++) {
139
- if (derivs[jdx] * derivs[jdx - 1] < 0) {
140
- sign_changes++;
141
- }
142
- }
143
- const normalized_score = sign_changes / max_changes_per_window;
144
- if (normalized_score > max_score)
145
- max_score = normalized_score;
146
- if (sign_changes > max_changes_per_window) {
147
- return { onset_index: idx + 1, score: normalized_score };
148
- }
149
- }
150
- return { onset_index: -1, score: max_score };
151
- }
152
- // Combined detection with configurable weights
153
- export function detect_instability(x_values, y_values, config = {}) {
154
- const window_size = config.window_size ?? DEFAULT_WINDOW_SIZE;
155
- const threshold = config.oscillation_threshold ?? DEFAULT_OSCILLATION_THRESHOLD;
156
- const weights = {
157
- derivative_variance: config.oscillation_weights?.derivative_variance ?? 1.0,
158
- amplitude_growth: config.oscillation_weights?.amplitude_growth ?? 1.0,
159
- sign_changes: config.oscillation_weights?.sign_changes ?? 1.0,
160
- };
161
- // Filter out invalid values for detection
162
- const valid_indices = [];
163
- const valid_y = [];
164
- for (let idx = 0; idx < y_values.length; idx++) {
165
- if (Number.isFinite(y_values[idx])) {
166
- valid_indices.push(idx);
167
- valid_y.push(y_values[idx]);
168
- }
169
- }
170
- if (valid_y.length < window_size * 2) {
171
- const method_scores = { derivative_variance: 0, amplitude_growth: 0, sign_changes: 0 };
172
- const detected = false;
173
- return { detected, onset_index: -1, onset_x: NaN, combined_score: 0, method_scores };
174
- }
175
- // Run all three detection methods
176
- const deriv_result = detect_derivative_variance(valid_y, window_size, threshold);
177
- const amp_result = detect_amplitude_growth(valid_y, window_size);
178
- const sign_result = detect_sign_change_frequency(valid_y, window_size);
179
- const method_scores = {
180
- derivative_variance: deriv_result.score,
181
- amplitude_growth: amp_result.score,
182
- sign_changes: sign_result.score,
183
- };
184
- // Compute weighted combined score
185
- const total_weight = weights.derivative_variance + weights.amplitude_growth + weights.sign_changes;
186
- const combined_score = total_weight > 0
187
- ? (weights.derivative_variance * deriv_result.score +
188
- weights.amplitude_growth * amp_result.score +
189
- weights.sign_changes * sign_result.score) /
190
- total_weight
191
- : 0;
192
- // Find earliest onset across all methods that exceeded threshold
193
- const onset_candidates = [
194
- {
195
- idx: deriv_result.onset_index,
196
- score: deriv_result.score * weights.derivative_variance,
197
- },
198
- { idx: amp_result.onset_index, score: amp_result.score * weights.amplitude_growth },
199
- { idx: sign_result.onset_index, score: sign_result.score * weights.sign_changes },
200
- ].filter((candidate) => candidate.idx >= 0);
201
- let onset_index = -1;
202
- if (onset_candidates.length > 0) {
203
- // Take earliest detected onset
204
- onset_index = Math.min(...onset_candidates.map((candidate) => candidate.idx));
205
- // Map back to original index if we filtered values
206
- if (onset_index >= 0 && onset_index < valid_indices.length) {
207
- onset_index = valid_indices[onset_index];
208
- }
209
- }
210
- const detected = combined_score >= threshold || onset_index >= 0;
211
- const onset_x = onset_index >= 0 && onset_index < x_values.length ? x_values[onset_index] : NaN;
212
- return { detected, onset_index, onset_x, combined_score, method_scores };
213
- }
214
- // --- Smoothing Functions ---
215
- // Moving average - O(n)
216
- export function smooth_moving_average(values, window) {
217
- if (values.length === 0 || window <= 1)
218
- return [...values];
219
- const result = Array(values.length);
220
- const half_window = Math.floor(window / 2);
221
- for (let idx = 0; idx < values.length; idx++) {
222
- const start = Math.max(0, idx - half_window);
223
- const end = Math.min(values.length, idx + half_window + 1);
224
- let [sum, count] = [0, 0];
225
- for (let jdx = start; jdx < end; jdx++) {
226
- if (Number.isFinite(values[jdx])) {
227
- sum += values[jdx];
228
- count++;
229
- }
230
- }
231
- result[idx] = count > 0 ? sum / count : values[idx];
232
- }
233
- return result;
234
- }
235
- // Savitzky-Golay filter coefficients for polynomial smoothing
236
- // Uses least-squares polynomial fitting in each window
237
- function compute_savgol_coefficients(window, order) {
238
- // Ensure window is odd
239
- const half = Math.floor(window / 2);
240
- const size = 2 * half + 1;
241
- // Build Vandermonde matrix for polynomial fitting
242
- const vandermonde = [];
243
- for (let idx = -half; idx <= half; idx++) {
244
- const row = [];
245
- for (let power = 0; power <= order; power++) {
246
- row.push(idx ** power);
247
- }
248
- vandermonde.push(row);
249
- }
250
- // Compute (V^T V)^-1 V^T using simple pseudoinverse
251
- // For smoothing, we only need the first row (constant term coefficients)
252
- const vtv = multiply_matrices(transpose(vandermonde), vandermonde);
253
- const vtv_inv = invert_matrix(vtv);
254
- if (!vtv_inv) {
255
- // Fallback to uniform weights
256
- return Array(size).fill(1 / size);
257
- }
258
- const vt = transpose(vandermonde);
259
- const coeffs_matrix = multiply_matrices(vtv_inv, vt);
260
- // First row gives smoothing coefficients
261
- return coeffs_matrix[0];
262
- }
263
- // Savitzky-Golay filter (derivative-preserving) - O(n * window)
264
- export function smooth_savitzky_golay(values, window, polynomial_order = DEFAULT_POLYNOMIAL_ORDER) {
265
- if (values.length === 0)
266
- return [];
267
- // Ensure window is odd and >= polynomial_order + 1
268
- let actual_window = window % 2 === 0 ? window + 1 : window;
269
- actual_window = Math.max(actual_window, polynomial_order + 2);
270
- actual_window = Math.min(actual_window, values.length);
271
- if (actual_window < 3)
272
- return [...values];
273
- const coeffs = compute_savgol_coefficients(actual_window, polynomial_order);
274
- const half = Math.floor(actual_window / 2);
275
- const result = Array(values.length);
276
- // Cache coefficient sum to avoid O(n × window) redundant reductions in loop
277
- const coeffs_sum = coeffs.reduce((sum, coeff) => sum + coeff, 0);
278
- for (let idx = 0; idx < values.length; idx++) {
279
- let [sum, weight_sum] = [0, 0];
280
- for (let jdx = 0; jdx < actual_window; jdx++) {
281
- const data_idx = idx - half + jdx;
282
- if (data_idx >= 0 && data_idx < values.length && Number.isFinite(values[data_idx])) {
283
- sum += coeffs[jdx] * values[data_idx];
284
- weight_sum += coeffs[jdx];
285
- }
286
- }
287
- result[idx] = weight_sum !== 0 ? (sum / weight_sum) * coeffs_sum : values[idx];
288
- }
289
- return result;
290
- }
6
+ import { detect_instability, remove_local_outliers, smooth_moving_average, smooth_savitzky_golay, } from './data-cleaning-signal';
7
+ export * from './data-cleaning-signal';
291
8
  // Apply smoothing based on config
292
9
  function apply_smoothing(x_values, y_values, config) {
293
10
  if (config.type === `moving_avg`) {
294
11
  return smooth_moving_average(y_values, config.window);
295
12
  }
296
13
  else if (config.type === `savgol`) {
297
- return smooth_savitzky_golay(y_values, config.window, config.polynomial_order ?? DEFAULT_POLYNOMIAL_ORDER);
14
+ // pass polynomial_order through: when it's undefined, smooth_savitzky_golay's
15
+ // default parameter applies (JS defaults also kick in for an explicit undefined)
16
+ return smooth_savitzky_golay(y_values, config.window, config.polynomial_order);
298
17
  }
299
18
  else if (config.type === `gaussian`) {
300
19
  return apply_gaussian_smearing(x_values, y_values, config.sigma);
301
20
  }
302
21
  return y_values;
303
22
  }
304
- // --- Local Outlier Detection ---
305
- // Default values for local outlier detection
306
- const DEFAULT_LOCAL_WINDOW_HALF = 7;
307
- const DEFAULT_LOCAL_MAD_THRESHOLD = 2.0;
308
- const DEFAULT_LOCAL_MAX_ITERATIONS = 5;
309
- // Compute local median within a window, excluding the center point
310
- // This allows detecting if the center point is an outlier relative to its neighbors
311
- function compute_local_median_excluding_center(values, center_idx, window_half) {
312
- const window_values = [];
313
- const start = Math.max(0, center_idx - window_half);
314
- const end = Math.min(values.length - 1, center_idx + window_half);
315
- for (let idx = start; idx <= end; idx++) {
316
- if (idx !== center_idx && Number.isFinite(values[idx])) {
317
- window_values.push(values[idx]);
318
- }
319
- }
320
- if (window_values.length === 0)
321
- return values[center_idx];
322
- return median(window_values);
323
- }
324
- // Compute local MAD (median absolute deviation) within a window, excluding center
325
- function compute_local_mad_excluding_center(values, center_idx, window_half, local_median) {
326
- const abs_devs = [];
327
- const start = Math.max(0, center_idx - window_half);
328
- const end = Math.min(values.length - 1, center_idx + window_half);
329
- for (let idx = start; idx <= end; idx++) {
330
- if (idx !== center_idx && Number.isFinite(values[idx])) {
331
- abs_devs.push(Math.abs(values[idx] - local_median));
332
- }
333
- }
334
- if (abs_devs.length === 0)
335
- return 0;
336
- return median(abs_devs);
337
- }
338
- // Remove local outliers using iterative sliding window MAD-based detection
339
- // Detects points that deviate significantly from their local neighborhood
340
- // Returns only the indices to keep, preserving good data before AND after bad regions
341
- export function remove_local_outliers(y_values, config = {}) {
342
- const window_half = config.window_half ?? DEFAULT_LOCAL_WINDOW_HALF;
343
- const mad_threshold = config.mad_threshold ?? DEFAULT_LOCAL_MAD_THRESHOLD;
344
- const max_iterations = config.max_iterations ?? DEFAULT_LOCAL_MAX_ITERATIONS;
345
- const len = y_values.length;
346
- if (len === 0) {
347
- return { kept_indices: [], removed_indices: [], iterations_used: 0 };
348
- }
349
- // Need enough neighbors for meaningful local statistics
350
- const min_points_needed = window_half * 2 + 1;
351
- if (len < min_points_needed) {
352
- return {
353
- kept_indices: Array.from({ length: len }, (_, idx) => idx),
354
- removed_indices: [],
355
- iterations_used: 0,
356
- };
357
- }
358
- let kept_mask = Array(len).fill(true);
359
- let iterations_used = 0;
360
- for (let iter = 0; iter < max_iterations; iter++) {
361
- let removed_any = false;
362
- const new_kept_mask = [...kept_mask];
363
- // Note: Local statistics are computed from original values, not filtered values.
364
- // This prevents cascading removals where one outlier's removal dramatically
365
- // shifts statistics and causes false positives on neighboring points.
366
- for (let idx = 0; idx < len; idx++) {
367
- if (!kept_mask[idx])
368
- continue; // Already removed
369
- if (!Number.isFinite(y_values[idx]))
370
- continue; // Skip invalid values
371
- const local_median = compute_local_median_excluding_center(y_values, idx, window_half);
372
- const local_mad = compute_local_mad_excluding_center(y_values, idx, window_half, local_median);
373
- // Cannot compute robust threshold if MAD is zero (all neighbors identical)
374
- if (local_mad === 0)
375
- continue;
376
- const threshold = local_mad * mad_threshold;
377
- const deviation = Math.abs(y_values[idx] - local_median);
378
- if (deviation > threshold) {
379
- new_kept_mask[idx] = false;
380
- removed_any = true;
381
- }
382
- }
383
- kept_mask = new_kept_mask;
384
- iterations_used = iter + 1;
385
- if (!removed_any)
386
- break;
387
- }
388
- const kept_indices = [];
389
- const removed_indices = [];
390
- for (let idx = 0; idx < len; idx++) {
391
- if (kept_mask[idx]) {
392
- kept_indices.push(idx);
393
- }
394
- else {
395
- removed_indices.push(idx);
396
- }
397
- }
398
- return { kept_indices, removed_indices, iterations_used };
399
- }
400
23
  // --- Helper Functions ---
401
24
  // Handle NaN/Infinity based on mode
402
25
  export function handle_invalid_values(values, mode) {
@@ -461,20 +84,19 @@ export function apply_bounds(x_values, y_values, bounds) {
461
84
  for (let idx = 0; idx < result.length; idx++) {
462
85
  const x_val = x_values[idx];
463
86
  const y_val = result[idx];
464
- const min_bound = typeof bounds.min === `function` ? bounds.min(x_val) : bounds.min;
465
- const max_bound = typeof bounds.max === `function` ? bounds.max(x_val) : bounds.max;
466
- let violated = false;
467
- if (min_bound !== undefined && y_val < min_bound)
468
- violated = true;
469
- if (max_bound !== undefined && y_val > max_bound)
470
- violated = true;
471
- if (violated) {
87
+ // Resolve bounds once per point; is_in_bounds would redundantly re-resolve them
88
+ // (costly when min/max are functions of x). NaN compares false on both checks
89
+ // and thus counts as in-bounds, matching is_in_bounds semantics.
90
+ const { min: min_bound, max: max_bound } = resolve_physical_bounds(x_val, bounds);
91
+ const below_min = min_bound !== undefined && y_val < min_bound;
92
+ const above_max = max_bound !== undefined && y_val > max_bound;
93
+ if (below_min || above_max) {
472
94
  violations++;
473
95
  const mode = bounds.mode ?? `clamp`;
474
96
  if (mode === `clamp`) {
475
- if (min_bound !== undefined && y_val < min_bound)
97
+ if (below_min)
476
98
  result[idx] = min_bound;
477
- if (max_bound !== undefined && y_val > max_bound)
99
+ if (above_max)
478
100
  result[idx] = max_bound;
479
101
  }
480
102
  else if (mode === `filter`) {
@@ -497,10 +119,17 @@ export function sync_metadata(metadata, kept_indices) {
497
119
  }
498
120
  // Filter arrays by kept indices
499
121
  const filter_by_indices = (arr, kept_indices) => kept_indices.map((idx) => arr[idx]);
500
- // Check if value is within bounds (static or x-dependent)
122
+ // Resolve static or x-dependent min/max bounds at a given x value
123
+ function resolve_physical_bounds(x_val, bounds) {
124
+ return {
125
+ min: typeof bounds.min === `function` ? bounds.min(x_val) : bounds.min,
126
+ max: typeof bounds.max === `function` ? bounds.max(x_val) : bounds.max,
127
+ };
128
+ }
129
+ // Check if value is within bounds (static or x-dependent).
130
+ // NB: NaN values compare false on both checks and therefore count as in-bounds.
501
131
  function is_in_bounds(val, x_val, bounds) {
502
- const min = typeof bounds.min === `function` ? bounds.min(x_val) : bounds.min;
503
- const max = typeof bounds.max === `function` ? bounds.max(x_val) : bounds.max;
132
+ const { min, max } = resolve_physical_bounds(x_val, bounds);
504
133
  if (min !== undefined && val < min)
505
134
  return false;
506
135
  if (max !== undefined && val > max)
@@ -775,79 +404,3 @@ export function clean_trajectory_props(props, config = {}) {
775
404
  }
776
405
  return { props: result_props, quality: quality_reports };
777
406
  }
778
- // --- Utility Functions ---
779
- function median(values) {
780
- if (values.length === 0)
781
- return 0;
782
- const sorted = [...values].sort((a, b) => a - b);
783
- const mid = Math.floor(sorted.length / 2);
784
- return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
785
- }
786
- // Simple matrix operations for Savitzky-Golay
787
- function transpose(matrix) {
788
- if (matrix.length === 0)
789
- return [];
790
- const rows = matrix.length;
791
- const cols = matrix[0].length;
792
- const result = Array.from({ length: cols }, () => Array(rows).fill(0));
793
- for (let row = 0; row < rows; row++) {
794
- for (let col = 0; col < cols; col++) {
795
- result[col][row] = matrix[row][col];
796
- }
797
- }
798
- return result;
799
- }
800
- function multiply_matrices(matrix_a, matrix_b) {
801
- const rows_a = matrix_a.length;
802
- const cols_a = matrix_a[0]?.length ?? 0;
803
- const cols_b = matrix_b[0]?.length ?? 0;
804
- const result = Array.from({ length: rows_a }, () => Array(cols_b).fill(0));
805
- for (let row = 0; row < rows_a; row++) {
806
- for (let col = 0; col < cols_b; col++) {
807
- for (let idx_k = 0; idx_k < cols_a; idx_k++) {
808
- result[row][col] += matrix_a[row][idx_k] * matrix_b[idx_k][col];
809
- }
810
- }
811
- }
812
- return result;
813
- }
814
- function invert_matrix(matrix) {
815
- const size = matrix.length;
816
- if (size === 0 || matrix[0].length !== size)
817
- return null;
818
- // Create augmented matrix [A | I]
819
- const aug = matrix.map((row, idx) => [
820
- ...row,
821
- ...Array.from({ length: size }, (_, jdx) => (idx === jdx ? 1 : 0)),
822
- ]);
823
- // Gaussian elimination with partial pivoting
824
- for (let col = 0; col < size; col++) {
825
- // Find pivot
826
- let max_row = col;
827
- for (let row = col + 1; row < size; row++) {
828
- if (Math.abs(aug[row][col]) > Math.abs(aug[max_row][col])) {
829
- max_row = row;
830
- }
831
- }
832
- if (Math.abs(aug[max_row][col]) < 1e-10) {
833
- return null; // Singular
834
- } // Swap rows
835
- ;
836
- [aug[col], aug[max_row]] = [aug[max_row], aug[col]];
837
- // Eliminate column
838
- const pivot = aug[col][col];
839
- for (let jdx = 0; jdx < 2 * size; jdx++) {
840
- aug[col][jdx] /= pivot;
841
- }
842
- for (let row = 0; row < size; row++) {
843
- if (row !== col) {
844
- const factor = aug[row][col];
845
- for (let jdx = 0; jdx < 2 * size; jdx++) {
846
- aug[row][jdx] -= factor * aug[col][jdx];
847
- }
848
- }
849
- }
850
- }
851
- // Extract inverse
852
- return aug.map((row) => row.slice(size));
853
- }
@@ -6,11 +6,15 @@ export const get_series_color = (series_idx) => DEFAULT_SERIES_COLORS[series_idx
6
6
  export const get_series_symbol = (series_idx) => DEFAULT_SERIES_SYMBOLS[series_idx % DEFAULT_SERIES_SYMBOLS.length];
7
7
  // Extract the primary color from a series data object.
8
8
  // Checks line stroke, then point fill (handling arrays), with fallback to default blue.
9
- export const extract_series_color = (series_data) => (series_data.line_style?.stroke ??
10
- (Array.isArray(series_data.point_style)
11
- ? series_data.point_style[0]?.fill
12
- : series_data.point_style?.fill)) || // oxlint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty fill should use default color
13
- `#4A9EFF`;
9
+ export const extract_series_color = (series_data) => {
10
+ const color = series_data.line_style?.stroke ??
11
+ (Array.isArray(series_data.point_style)
12
+ ? series_data.point_style[0]?.fill
13
+ : series_data.point_style?.fill);
14
+ if (color)
15
+ return color;
16
+ return DEFAULTS.scatter.point.color;
17
+ };
14
18
  // Prepare legend data from series array
15
19
  export const prepare_legend_data = (series) => series.map((series_data, series_idx) => ({
16
20
  series_idx,
@@ -1,5 +1,6 @@
1
1
  import type { Vec2 } from '../../math';
2
- import type { DataSeries, ErrorBand, FillBoundary, FillCurveType, FillGradient, FillRegion } from './types';
2
+ import type { CurveFactory } from 'd3-shape';
3
+ import type { DataSeries, ErrorBand, FillBoundary, FillCurveType, FillGradient, FillRegion, LineCurve } from './types';
3
4
  export declare const LOG_EPSILON = 1e-10;
4
5
  export interface Pt {
5
6
  x: number;
@@ -28,6 +29,7 @@ interface DomainContext {
28
29
  }
29
30
  export declare function resolve_boundary_points(boundary: FillBoundary, series: readonly DataSeries[], domains: DomainContext, companion?: Pt[] | null): ResolvedBoundary | null;
30
31
  export declare function compute_fill_segments(region: FillRegion, series: readonly DataSeries[], domains: DomainContext): FillSegment[];
32
+ export declare const line_curve_factory: (curve: LineCurve | undefined) => CurveFactory;
31
33
  export declare function generate_fill_path(upper: readonly Pt[], lower: readonly Pt[], upper_curve?: FillCurveType, lower_curve?: FillCurveType): string;
32
34
  export declare function convert_error_band_to_fill_region(error_band: ErrorBand, series: readonly DataSeries[], default_color?: string): FillRegion | null;
33
35
  export declare const is_fill_gradient: (fill: string | FillGradient | undefined) => fill is FillGradient;
@@ -1,8 +1,9 @@
1
1
  // Fill-between utility functions for ScatterPlot fill regions
2
2
  // Each fill edge is traced through its boundary's own points with the same curve the series line
3
- // uses (curveMonotoneX), so an unclipped fill edge coincides with the line it borders. When an
4
- // edge is clipped (x_range / partial overlap), the inserted endpoint shifts the neighboring
5
- // monotone tangent, so the clipped edge can deviate sub-pixel from the full series line.
3
+ // uses (a series edge inherits the series' `line_style.curve`, default monotoneX), so an unclipped
4
+ // fill edge coincides with the line it borders. When an edge is clipped (x_range / partial
5
+ // overlap), inserted endpoints are evaluated on a monotone-cubic approximation: sub-pixel for
6
+ // monotoneX/linear/step, but natural/basis/catmullRom edges can deviate more at the clip points.
6
7
  import { curveBasis, curveCardinal, curveCatmullRom, curveLinear, curveMonotoneX, curveMonotoneY, curveNatural, curveStep, curveStepAfter, curveStepBefore, line, } from 'd3-shape';
7
8
  // Epsilon value for log scale clamping (to avoid log(0) = -Infinity)
8
9
  export const LOG_EPSILON = 1e-10;
@@ -145,6 +146,19 @@ const finite_points = (xs, ys) => clean_pts(Array.from({ length: Math.min(xs.len
145
146
  x: xs[idx],
146
147
  y: ys[idx],
147
148
  })));
149
+ // Bridge the public LineCurve vocabulary (series `line_style.curve`) to FillCurveType names so
150
+ // a series fill edge traces with the same curve as its rendered line. Default: monotoneX.
151
+ const LINE_CURVE_TO_FILL = {
152
+ linear: `linear`,
153
+ monotone: `monotoneX`,
154
+ natural: `natural`,
155
+ step: `step`,
156
+ basis: `basis`,
157
+ 'catmull-rom': `catmullRom`,
158
+ };
159
+ const line_curve_to_fill = (curve) =>
160
+ // ?? monotoneX guards an unknown string from an untyped (Python/JSON) caller
161
+ (curve ? LINE_CURVE_TO_FILL[curve] : undefined) ?? `monotoneX`;
148
162
  // Resolve a boundary to native points + curve in data coordinates. `companion` supplies x
149
163
  // positions for boundaries that don't define their own (constant/axis/function/data-without-x).
150
164
  export function resolve_boundary_points(boundary, series, domains, companion) {
@@ -157,15 +171,16 @@ export function resolve_boundary_points(boundary, series, domains, companion) {
157
171
  points: horizontal(span_xs, y),
158
172
  curve: `linear`,
159
173
  });
160
- // series / function / data edges are traced with monotoneX (matches the series line)
161
- const curved_edge = (points) => points.length > 0 ? { points, curve: `monotoneX` } : null;
174
+ // function / data edges trace with monotoneX by default; a series edge inherits the
175
+ // series' own line curve so the fill border coincides with the rendered line
176
+ const curved_edge = (points, curve = `monotoneX`) => (points.length > 0 ? { points, curve } : null);
162
177
  if (typeof boundary === `number`)
163
178
  return flat_edge(boundary);
164
179
  if (boundary.type === `series`) {
165
180
  const resolved = resolve_series_ref(boundary, series);
166
181
  if (!resolved)
167
182
  return null;
168
- return curved_edge(finite_points(resolved.x, resolved.y));
183
+ return curved_edge(finite_points(resolved.x, resolved.y), line_curve_to_fill(resolved.line_style?.curve));
169
184
  }
170
185
  if (boundary.type === `constant`)
171
186
  return flat_edge(boundary.value);
@@ -345,6 +360,10 @@ const CURVE_MAP = {
345
360
  natural: curveNatural,
346
361
  };
347
362
  const get_curve = (curve_type) => CURVE_MAP[curve_type] ?? curveMonotoneX;
363
+ // Resolve a public LineCurve (a series' `line_style.curve`) to its d3 CurveFactory. Single source
364
+ // of truth shared by Line.svelte and PlotMarginals.svelte (composes the LineCurve -> FillCurveType
365
+ // -> CurveFactory maps); unknown/undefined falls back to curveMonotoneX.
366
+ export const line_curve_factory = (curve) => get_curve(line_curve_to_fill(curve));
348
367
  const trace = (points, curve_type) => line()
349
368
  .x((pt) => pt.x)
350
369
  .y((pt) => pt.y)
@@ -378,6 +397,9 @@ export function convert_error_band_to_fill_region(error_band, series, default_co
378
397
  return {
379
398
  id: error_band.id,
380
399
  label: error_band.label,
400
+ // band edges are data boundaries (default monotoneX); inherit the central series' line
401
+ // curve so the band traces with the same curve as the line it brackets
402
+ curve: line_curve_to_fill(resolved.line_style?.curve),
381
403
  upper: { type: `data`, x, values: y.map((val, idx) => val + upper_err[idx]) },
382
404
  lower: { type: `data`, x, values: y.map((val, idx) => val - lower_err[idx]) },
383
405
  fill: error_band.fill ?? default_color ?? `#4e79a7`,
@@ -3,6 +3,7 @@ export * from './data-cleaning';
3
3
  export * from './fill-utils';
4
4
  export * from './interactions';
5
5
  export * from './layout';
6
+ export * from './marginals';
6
7
  export * from './reference-line';
7
8
  export * from './scales';
8
9
  export * from './svg';
@@ -4,6 +4,7 @@ export * from './data-cleaning';
4
4
  export * from './fill-utils';
5
5
  export * from './interactions';
6
6
  export * from './layout';
7
+ export * from './marginals';
7
8
  export * from './reference-line';
8
9
  export * from './scales';
9
10
  export * from './svg';