matterviz 0.3.7 → 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 (324) hide show
  1. package/dist/Icon.svelte +7 -4
  2. package/dist/MillerIndexInput.svelte +1 -1
  3. package/dist/api/optimade.js +32 -26
  4. package/dist/app.css +0 -3
  5. package/dist/brillouin/BrillouinZone.svelte +8 -3
  6. package/dist/brillouin/BrillouinZone.svelte.d.ts +2 -1
  7. package/dist/brillouin/BrillouinZoneScene.svelte +52 -6
  8. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -0
  9. package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
  10. package/dist/brillouin/compute.js +10 -14
  11. package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
  12. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +12 -15
  13. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +8 -10
  14. package/dist/chempot-diagram/async-compute.svelte.js +3 -1
  15. package/dist/chempot-diagram/chempot-worker.js +2 -1
  16. package/dist/chempot-diagram/compute.d.ts +1 -1
  17. package/dist/chempot-diagram/compute.js +17 -19
  18. package/dist/colors/index.js +6 -5
  19. package/dist/composition/FormulaFilter.svelte +12 -6
  20. package/dist/composition/PieChart.svelte +6 -5
  21. package/dist/composition/chem-sys.d.ts +8 -0
  22. package/dist/composition/chem-sys.js +85 -0
  23. package/dist/composition/format.js +4 -2
  24. package/dist/composition/index.d.ts +1 -0
  25. package/dist/composition/index.js +1 -0
  26. package/dist/composition/parse.js +25 -13
  27. package/dist/convex-hull/ConvexHull2D.svelte +12 -10
  28. package/dist/convex-hull/ConvexHull3D.svelte +5 -5
  29. package/dist/convex-hull/ConvexHull4D.svelte +5 -9
  30. package/dist/convex-hull/ConvexHullStats.svelte +12 -12
  31. package/dist/convex-hull/GasPressureControls.svelte +4 -4
  32. package/dist/convex-hull/TemperatureSlider.svelte +2 -2
  33. package/dist/convex-hull/demo-temperature.d.ts +1 -1
  34. package/dist/convex-hull/demo-temperature.js +20 -22
  35. package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
  36. package/dist/convex-hull/gas-thermodynamics.js +22 -30
  37. package/dist/convex-hull/helpers.d.ts +3 -0
  38. package/dist/convex-hull/helpers.js +17 -9
  39. package/dist/convex-hull/index.d.ts +1 -1
  40. package/dist/convex-hull/thermodynamics.js +83 -78
  41. package/dist/convex-hull/types.d.ts +1 -1
  42. package/dist/coordination/CoordinationBarPlot.svelte +23 -23
  43. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
  44. package/dist/element/ElementTile.svelte.d.ts +1 -1
  45. package/dist/fermi-surface/FermiSlice.svelte +13 -5
  46. package/dist/fermi-surface/FermiSurface.svelte +11 -5
  47. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  48. package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
  49. package/dist/fermi-surface/FermiSurfaceScene.svelte +3 -0
  50. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
  51. package/dist/fermi-surface/compute.js +59 -59
  52. package/dist/fermi-surface/export.js +3 -2
  53. package/dist/fermi-surface/parse.js +7 -4
  54. package/dist/fermi-surface/types.d.ts +1 -0
  55. package/dist/heatmap-matrix/HeatmapMatrix.svelte +23 -21
  56. package/dist/heatmap-matrix/index.js +1 -1
  57. package/dist/io/decompress.js +4 -2
  58. package/dist/io/export.d.ts +4 -4
  59. package/dist/io/export.js +47 -25
  60. package/dist/io/fetch.js +5 -1
  61. package/dist/io/file-drop.d.ts +1 -1
  62. package/dist/io/file-drop.js +35 -36
  63. package/dist/io/url-drop.js +64 -33
  64. package/dist/isosurface/parse.js +6 -7
  65. package/dist/isosurface/slice.js +5 -4
  66. package/dist/isosurface/types.js +1 -1
  67. package/dist/keyboard.d.ts +3 -0
  68. package/dist/keyboard.js +23 -0
  69. package/dist/labels.d.ts +1 -1
  70. package/dist/labels.js +8 -7
  71. package/dist/layout/PropertyFilter.svelte +3 -2
  72. package/dist/layout/SettingsSection.svelte +1 -1
  73. package/dist/layout/json-tree/JsonNode.svelte +1 -1
  74. package/dist/layout/json-tree/JsonTree.svelte +2 -2
  75. package/dist/layout/json-tree/utils.js +5 -4
  76. package/dist/marching-cubes.js +8 -13
  77. package/dist/math.d.ts +5 -1
  78. package/dist/math.js +24 -9
  79. package/dist/overlays/DraggablePane.svelte +4 -4
  80. package/dist/periodic-table/PeriodicTable.svelte +20 -9
  81. package/dist/periodic-table/PropertySelect.svelte +1 -0
  82. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
  83. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  84. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  85. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
  86. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
  87. package/dist/phase-diagram/build-diagram.js +2 -2
  88. package/dist/phase-diagram/parse.js +6 -5
  89. package/dist/phase-diagram/types.d.ts +1 -1
  90. package/dist/phase-diagram/utils.d.ts +3 -3
  91. package/dist/phase-diagram/utils.js +8 -12
  92. package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +229 -587
  93. package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +5 -5
  94. package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
  95. package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
  96. package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +6 -6
  97. package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
  98. package/dist/plot/bar/data.d.ts +40 -0
  99. package/dist/plot/bar/data.js +154 -0
  100. package/dist/plot/bar/geometry.d.ts +39 -0
  101. package/dist/plot/bar/geometry.js +60 -0
  102. package/dist/plot/bar/index.d.ts +3 -0
  103. package/dist/plot/bar/index.js +3 -0
  104. package/dist/plot/box/BoxPlot.svelte +1462 -0
  105. package/dist/plot/box/BoxPlot.svelte.d.ts +94 -0
  106. package/dist/plot/box/BoxPlotControls.svelte +109 -0
  107. package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
  108. package/dist/plot/box/Violin.svelte +14 -0
  109. package/dist/plot/box/Violin.svelte.d.ts +70 -0
  110. package/dist/plot/box/box-plot.d.ts +55 -0
  111. package/dist/plot/box/box-plot.js +126 -0
  112. package/dist/plot/box/index.d.ts +5 -0
  113. package/dist/plot/box/index.js +5 -0
  114. package/dist/plot/box/kde.d.ts +16 -0
  115. package/dist/plot/box/kde.js +160 -0
  116. package/dist/plot/box/quantile.d.ts +3 -0
  117. package/dist/plot/box/quantile.js +53 -0
  118. package/dist/plot/{auto-place.js → core/auto-place.js} +2 -2
  119. package/dist/plot/core/axis-utils.d.ts +46 -0
  120. package/dist/plot/core/axis-utils.js +110 -0
  121. package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
  122. package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
  123. package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +36 -33
  124. package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +2 -2
  125. package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
  126. package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
  127. package/dist/plot/core/components/ControlPane.svelte +46 -0
  128. package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
  129. package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
  130. package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
  131. package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
  132. package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
  133. package/dist/plot/{Line.svelte → core/components/Line.svelte} +30 -13
  134. package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +7 -5
  135. package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +3 -2
  136. package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
  137. package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
  138. package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
  139. package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
  140. package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
  141. package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
  142. package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
  143. package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
  144. package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
  145. package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +4 -4
  146. package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +2 -2
  147. package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +7 -7
  148. package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +2 -2
  149. package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
  150. package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
  151. package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
  152. package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
  153. package/dist/plot/core/components/index.d.ts +17 -0
  154. package/dist/plot/core/components/index.js +17 -0
  155. package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
  156. package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +3 -5
  157. package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
  158. package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
  159. package/dist/plot/core/fill-utils.d.ts +33 -0
  160. package/dist/plot/core/fill-utils.js +388 -0
  161. package/dist/plot/{hover-lock.svelte.js → core/hover-lock.svelte.js} +5 -6
  162. package/dist/plot/core/index.d.ts +10 -0
  163. package/dist/plot/core/index.js +11 -0
  164. package/dist/plot/core/interactions.d.ts +35 -0
  165. package/dist/plot/core/interactions.js +195 -0
  166. package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
  167. package/dist/plot/{layout.js → core/layout.js} +16 -8
  168. package/dist/plot/{reference-line.d.ts → core/reference-line.d.ts} +1 -1
  169. package/dist/plot/{reference-line.js → core/reference-line.js} +23 -36
  170. package/dist/plot/{scales.d.ts → core/scales.d.ts} +2 -2
  171. package/dist/plot/{scales.js → core/scales.js} +84 -85
  172. package/dist/plot/core/svg.d.ts +2 -0
  173. package/dist/plot/core/svg.js +41 -0
  174. package/dist/plot/{types.d.ts → core/types.d.ts} +19 -79
  175. package/dist/plot/{types.js → core/types.js} +1 -1
  176. package/dist/plot/{utils → core/utils}/label-placement.d.ts +2 -2
  177. package/dist/plot/core/utils/series-visibility.d.ts +26 -0
  178. package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
  179. package/dist/plot/core/utils.d.ts +11 -0
  180. package/dist/plot/core/utils.js +27 -0
  181. package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +154 -294
  182. package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
  183. package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
  184. package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
  185. package/dist/plot/histogram/index.d.ts +2 -0
  186. package/dist/plot/histogram/index.js +2 -0
  187. package/dist/plot/index.d.ts +8 -41
  188. package/dist/plot/index.js +10 -39
  189. package/dist/plot/sankey/Sankey.svelte +700 -0
  190. package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
  191. package/dist/plot/sankey/SankeyControls.svelte +98 -0
  192. package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
  193. package/dist/plot/sankey/index.d.ts +4 -0
  194. package/dist/plot/sankey/index.js +3 -0
  195. package/dist/plot/sankey/sankey-types.d.ts +42 -0
  196. package/dist/plot/sankey/sankey-types.js +4 -0
  197. package/dist/plot/sankey/sankey.d.ts +52 -0
  198. package/dist/plot/sankey/sankey.js +187 -0
  199. package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +61 -59
  200. package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +4 -4
  201. package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
  202. package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
  203. package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +221 -642
  204. package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +7 -7
  205. package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
  206. package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +1 -1
  207. package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
  208. package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
  209. package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
  210. package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
  211. package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +3 -3
  212. package/dist/plot/scatter/index.d.ts +7 -0
  213. package/dist/plot/scatter/index.js +5 -0
  214. package/dist/plot/scatter/scatter-data.d.ts +19 -0
  215. package/dist/plot/scatter/scatter-data.js +212 -0
  216. package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +12 -10
  217. package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +7 -7
  218. package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +5 -4
  219. package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +2 -2
  220. package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +11 -11
  221. package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +3 -3
  222. package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +1 -1
  223. package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +1 -1
  224. package/dist/plot/scatter-3d/index.d.ts +4 -0
  225. package/dist/plot/scatter-3d/index.js +4 -0
  226. package/dist/plot/sunburst/Sunburst.svelte +1045 -0
  227. package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -0
  228. package/dist/plot/sunburst/SunburstControls.svelte +200 -0
  229. package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
  230. package/dist/plot/sunburst/index.d.ts +4 -0
  231. package/dist/plot/sunburst/index.js +4 -0
  232. package/dist/plot/sunburst/render.d.ts +34 -0
  233. package/dist/plot/sunburst/render.js +122 -0
  234. package/dist/plot/sunburst/sunburst.d.ts +62 -0
  235. package/dist/plot/sunburst/sunburst.js +266 -0
  236. package/dist/rdf/RdfPlot.svelte +2 -1
  237. package/dist/rdf/calc-rdf.js +11 -24
  238. package/dist/sanitize.js +1 -1
  239. package/dist/settings.d.ts +65 -1
  240. package/dist/settings.js +262 -0
  241. package/dist/spectral/Bands.svelte +39 -29
  242. package/dist/spectral/Bands.svelte.d.ts +3 -4
  243. package/dist/spectral/BandsAndDos.svelte +1 -1
  244. package/dist/spectral/BrillouinBandsDos.svelte +39 -27
  245. package/dist/spectral/Dos.svelte +10 -19
  246. package/dist/spectral/Dos.svelte.d.ts +2 -2
  247. package/dist/spectral/helpers.d.ts +3 -1
  248. package/dist/spectral/helpers.js +95 -29
  249. package/dist/structure/AtomLegend.svelte +8 -9
  250. package/dist/structure/CellSelect.svelte +1 -2
  251. package/dist/structure/Cylinder.svelte +12 -8
  252. package/dist/structure/Cylinder.svelte.d.ts +4 -1
  253. package/dist/structure/Structure.svelte +78 -72
  254. package/dist/structure/Structure.svelte.d.ts +1 -1
  255. package/dist/structure/StructureInfoPane.svelte +5 -6
  256. package/dist/structure/StructureScene.svelte +11 -10
  257. package/dist/structure/atom-properties.js +6 -6
  258. package/dist/structure/bond-order-perception.js +1 -1
  259. package/dist/structure/bonding.d.ts +1 -0
  260. package/dist/structure/bonding.js +43 -15
  261. package/dist/structure/export.js +27 -23
  262. package/dist/structure/index.d.ts +2 -4
  263. package/dist/structure/index.js +1 -3
  264. package/dist/structure/label-placement.js +4 -4
  265. package/dist/structure/measure.d.ts +3 -2
  266. package/dist/structure/measure.js +6 -5
  267. package/dist/structure/parse.js +121 -103
  268. package/dist/structure/pbc.js +4 -0
  269. package/dist/symmetry/SymmetryStats.svelte +2 -2
  270. package/dist/symmetry/index.d.ts +1 -1
  271. package/dist/symmetry/index.js +22 -24
  272. package/dist/symmetry/spacegroups.d.ts +7 -0
  273. package/dist/symmetry/spacegroups.js +48 -13
  274. package/dist/table/HeatmapTable.svelte +63 -11
  275. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  276. package/dist/table/index.d.ts +1 -3
  277. package/dist/table/index.js +1 -1
  278. package/dist/theme/index.js +8 -8
  279. package/dist/tooltip/KCoords.svelte +45 -0
  280. package/dist/tooltip/KCoords.svelte.d.ts +8 -0
  281. package/dist/tooltip/index.d.ts +1 -0
  282. package/dist/tooltip/index.js +1 -0
  283. package/dist/trajectory/Trajectory.svelte +66 -40
  284. package/dist/trajectory/Trajectory.svelte.d.ts +2 -1
  285. package/dist/trajectory/TrajectoryExportPane.svelte +2 -1
  286. package/dist/trajectory/TrajectoryInfoPane.svelte +2 -1
  287. package/dist/trajectory/format-detect.d.ts +1 -0
  288. package/dist/trajectory/format-detect.js +25 -11
  289. package/dist/trajectory/frame-reader.js +17 -50
  290. package/dist/trajectory/helpers.js +1 -1
  291. package/dist/trajectory/index.js +1 -1
  292. package/dist/trajectory/parse/hdf5.js +1 -1
  293. package/dist/trajectory/parse/index.js +14 -6
  294. package/dist/trajectory/parse/vasp.js +36 -17
  295. package/dist/trajectory/parse/xyz.d.ts +24 -0
  296. package/dist/trajectory/parse/xyz.js +102 -89
  297. package/dist/trajectory/plotting.d.ts +1 -1
  298. package/dist/trajectory/plotting.js +15 -15
  299. package/dist/utils.d.ts +1 -0
  300. package/dist/utils.js +6 -4
  301. package/dist/xrd/XrdPlot.svelte +2 -1
  302. package/dist/xrd/calc-xrd.js +15 -12
  303. package/dist/xrd/parse.js +2 -2
  304. package/package.json +22 -18
  305. package/dist/plot/PlotControls.svelte.d.ts +0 -4
  306. package/dist/plot/axis-utils.d.ts +0 -19
  307. package/dist/plot/axis-utils.js +0 -78
  308. package/dist/plot/defaults.d.ts +0 -19
  309. package/dist/plot/defaults.js +0 -9
  310. package/dist/plot/fill-utils.d.ts +0 -46
  311. package/dist/plot/fill-utils.js +0 -322
  312. package/dist/plot/interactions.d.ts +0 -12
  313. package/dist/plot/interactions.js +0 -101
  314. package/dist/plot/svg.d.ts +0 -1
  315. package/dist/plot/svg.js +0 -11
  316. package/dist/plot/utils/series-visibility.d.ts +0 -15
  317. package/dist/plot/utils.d.ts +0 -1
  318. package/dist/plot/utils.js +0 -14
  319. /package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +0 -0
  320. /package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +0 -0
  321. /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
  322. /package/dist/plot/{hover-lock.svelte.d.ts → core/hover-lock.svelte.d.ts} +0 -0
  323. /package/dist/plot/{utils → core/utils}/label-placement.js +0 -0
  324. /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
@@ -0,0 +1,94 @@
1
+ import type { BandwidthOption, BasePlotProps, BoxHandlerProps, BoxPlotSeries, LegendConfig, Orientation, PanConfig, PlotConfig, RefLine, RefLineEvent, UserContentProps, ViolinKind, ViolinSide, WhiskerMode } from '..';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ declare function $$render<Metadata extends Record<string, unknown> = Record<string, unknown>>(): {
5
+ props: HTMLAttributes<HTMLDivElement> & BasePlotProps & PlotConfig & {
6
+ series?: BoxPlotSeries<Metadata>[];
7
+ orientation?: Orientation;
8
+ legend?: LegendConfig | null;
9
+ show_legend?: boolean;
10
+ box?: {
11
+ color?: string;
12
+ opacity?: number;
13
+ stroke_width?: number;
14
+ stroke_color?: string;
15
+ border_radius?: number;
16
+ };
17
+ whisker?: {
18
+ width?: number;
19
+ color?: string;
20
+ cap_fraction?: number;
21
+ };
22
+ median_style?: {
23
+ width?: number;
24
+ color?: string;
25
+ };
26
+ outlier_style?: {
27
+ radius?: number;
28
+ opacity?: number;
29
+ stroke_width?: number;
30
+ };
31
+ whisker_mode?: WhiskerMode;
32
+ whisker_range?: number;
33
+ whisker_percentiles?: [number, number];
34
+ show_outliers?: boolean;
35
+ show_mean?: boolean;
36
+ show_value_labels?: boolean;
37
+ value_label_stat?: `median` | `mean`;
38
+ value_label_format?: string;
39
+ kind?: ViolinKind;
40
+ side?: ViolinSide;
41
+ bandwidth?: BandwidthOption;
42
+ violin_width?: number;
43
+ violin_style?: {
44
+ opacity?: number;
45
+ stroke_width?: number;
46
+ };
47
+ kde_points?: number;
48
+ kde_cut?: number;
49
+ kde_max_samples?: number;
50
+ kde_clip?: [number | null, number | null];
51
+ tooltip?: Snippet<[BoxHandlerProps<Metadata>]>;
52
+ user_content?: Snippet<[UserContentProps]>;
53
+ header_controls?: Snippet<[{
54
+ height: number;
55
+ width: number;
56
+ fullscreen: boolean;
57
+ }]>;
58
+ controls_extra?: Snippet<[{
59
+ orientation: Orientation;
60
+ } & Required<PlotConfig>]>;
61
+ change?: (data: BoxHandlerProps<Metadata> | null) => void;
62
+ on_box_click?: (data: BoxHandlerProps<Metadata> & {
63
+ event: MouseEvent | KeyboardEvent;
64
+ }) => void;
65
+ on_box_hover?: (data: (BoxHandlerProps<Metadata> & {
66
+ event: MouseEvent | FocusEvent | KeyboardEvent;
67
+ }) | null) => void;
68
+ ref_lines?: RefLine[];
69
+ on_ref_line_click?: (event: RefLineEvent) => void;
70
+ on_ref_line_hover?: (event: RefLineEvent | null) => void;
71
+ pan?: PanConfig;
72
+ };
73
+ exports: {};
74
+ bindings: "orientation" | "display" | "show_controls" | "fullscreen" | "series" | "hovered" | "ref_lines" | "controls_open" | "x_axis" | "y_axis" | "whisker_mode" | "x2_axis" | "y2_axis" | "show_outliers" | "show_mean" | "kind" | "side";
75
+ slots: {};
76
+ events: {};
77
+ };
78
+ declare class __sveltets_Render<Metadata extends Record<string, unknown> = Record<string, unknown>> {
79
+ props(): ReturnType<typeof $$render<Metadata>>['props'];
80
+ events(): ReturnType<typeof $$render<Metadata>>['events'];
81
+ slots(): ReturnType<typeof $$render<Metadata>>['slots'];
82
+ bindings(): "orientation" | "display" | "show_controls" | "fullscreen" | "series" | "hovered" | "ref_lines" | "controls_open" | "x_axis" | "y_axis" | "whisker_mode" | "x2_axis" | "y2_axis" | "show_outliers" | "show_mean" | "kind" | "side";
83
+ exports(): {};
84
+ }
85
+ interface $$IsomorphicComponent {
86
+ new <Metadata extends Record<string, unknown> = Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Metadata>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Metadata>['props']>, ReturnType<__sveltets_Render<Metadata>['events']>, ReturnType<__sveltets_Render<Metadata>['slots']>> & {
87
+ $$bindings?: ReturnType<__sveltets_Render<Metadata>['bindings']>;
88
+ } & ReturnType<__sveltets_Render<Metadata>['exports']>;
89
+ <Metadata extends Record<string, unknown> = Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<Metadata>['props']> & {}): ReturnType<__sveltets_Render<Metadata>['exports']>;
90
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
91
+ }
92
+ declare const BoxPlot: $$IsomorphicComponent;
93
+ type BoxPlot<Metadata extends Record<string, unknown> = Record<string, unknown>> = InstanceType<typeof BoxPlot<Metadata>>;
94
+ export default BoxPlot;
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ import { SettingsSection } from '../../layout'
3
+ import type { Orientation, PlotConfig, ViolinKind, ViolinSide, WhiskerMode } from '..'
4
+ import { PlotControls } from '..'
5
+ import type { PlotControlsProps } from '../core/types'
6
+ import { unique_id } from '../core/utils'
7
+ import { DEFAULTS } from '../../settings'
8
+ import type { Snippet } from 'svelte'
9
+
10
+ // Unique ID prefix to avoid conflicts when multiple instances on same page
11
+ const uid = unique_id(`box-ctrl`)
12
+
13
+ let {
14
+ orientation = $bindable(`vertical`),
15
+ whisker_mode = $bindable(`tukey`),
16
+ show_outliers = $bindable(true),
17
+ show_mean = $bindable(false),
18
+ kind = $bindable(`box`),
19
+ side = $bindable(`both`),
20
+ x_axis = $bindable({}),
21
+ x2_axis = $bindable({}),
22
+ y_axis = $bindable({}),
23
+ y2_axis = $bindable({}),
24
+ display = $bindable({}),
25
+ show_controls = $bindable(false),
26
+ controls_open = $bindable(false),
27
+ children,
28
+ ...rest
29
+ }: Omit<PlotControlsProps, `children` | `post_children`> & {
30
+ orientation?: Orientation
31
+ whisker_mode?: WhiskerMode
32
+ show_outliers?: boolean
33
+ show_mean?: boolean
34
+ kind?: ViolinKind
35
+ side?: ViolinSide
36
+ show_controls?: boolean
37
+ controls_open?: boolean
38
+ children?: Snippet<[{ orientation: Orientation } & Required<PlotConfig>]>
39
+ } = $props()
40
+ </script>
41
+
42
+ <PlotControls
43
+ bind:show_controls
44
+ bind:controls_open
45
+ bind:x_axis
46
+ bind:x2_axis
47
+ bind:y_axis
48
+ bind:y2_axis
49
+ bind:display
50
+ {...rest}
51
+ >
52
+ {@render children?.({ orientation, x_axis, x2_axis, y_axis, y2_axis, display })}
53
+ <SettingsSection
54
+ title="Box / Violin"
55
+ current_values={{ orientation, kind, side, whisker_mode, show_outliers, show_mean }}
56
+ on_reset={() => {
57
+ orientation = `vertical`
58
+ kind = DEFAULTS.box.kind
59
+ side = DEFAULTS.box.side
60
+ whisker_mode = DEFAULTS.box.whisker_mode
61
+ show_outliers = DEFAULTS.box.show_outliers
62
+ show_mean = DEFAULTS.box.show_mean
63
+ }}
64
+ style="display: flex; flex-wrap: wrap; gap: 2ex"
65
+ >
66
+ <label style="flex: 1">
67
+ Orientation:
68
+ <select bind:value={orientation} id="{uid}-orientation">
69
+ <option value="vertical">Vertical</option>
70
+ <option value="horizontal">Horizontal</option>
71
+ </select>
72
+ </label>
73
+ <label style="flex: 1">
74
+ Glyph:
75
+ <select bind:value={kind} id="{uid}-kind">
76
+ <option value="box">Box</option>
77
+ <option value="violin">Violin</option>
78
+ <option value="violin+box">Violin + Box</option>
79
+ </select>
80
+ </label>
81
+ {#if kind !== `box`}
82
+ <label style="flex: 1">
83
+ Violin side:
84
+ <select bind:value={side} id="{uid}-side">
85
+ <option value="both">Both</option>
86
+ <option value="positive">Positive</option>
87
+ <option value="negative">Negative</option>
88
+ </select>
89
+ </label>
90
+ {/if}
91
+ <label style="flex: 1">
92
+ Whiskers:
93
+ <select bind:value={whisker_mode} id="{uid}-whisker-mode">
94
+ <option value="tukey">Tukey (1.5·IQR)</option>
95
+ <option value="minmax">Min/Max</option>
96
+ <option value="percentile">Percentile</option>
97
+ <option value="std">Std Dev</option>
98
+ </select>
99
+ </label>
100
+ <label style="flex: 1 1 100%">
101
+ <input type="checkbox" bind:checked={show_outliers} />
102
+ Show outliers
103
+ </label>
104
+ <label style="flex: 1 1 100%">
105
+ <input type="checkbox" bind:checked={show_mean} />
106
+ Show mean
107
+ </label>
108
+ </SettingsSection>
109
+ </PlotControls>
@@ -0,0 +1,19 @@
1
+ import type { Orientation, PlotConfig, ViolinKind, ViolinSide, WhiskerMode } from '..';
2
+ import type { PlotControlsProps } from '../core/types';
3
+ import type { Snippet } from 'svelte';
4
+ type $$ComponentProps = Omit<PlotControlsProps, `children` | `post_children`> & {
5
+ orientation?: Orientation;
6
+ whisker_mode?: WhiskerMode;
7
+ show_outliers?: boolean;
8
+ show_mean?: boolean;
9
+ kind?: ViolinKind;
10
+ side?: ViolinSide;
11
+ show_controls?: boolean;
12
+ controls_open?: boolean;
13
+ children?: Snippet<[{
14
+ orientation: Orientation;
15
+ } & Required<PlotConfig>]>;
16
+ };
17
+ declare const BoxPlotControls: import("svelte").Component<$$ComponentProps, {}, "orientation" | "display" | "show_controls" | "controls_open" | "x_axis" | "y_axis" | "whisker_mode" | "x2_axis" | "y2_axis" | "show_outliers" | "show_mean" | "kind" | "side">;
18
+ type BoxPlotControls = ReturnType<typeof BoxPlotControls>;
19
+ export default BoxPlotControls;
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ // Thin wrapper around BoxPlot with violin defaults. A violin is the same chart as a box
3
+ // plot (per-series raw distribution on a categorical axis), so all the scaffolding is shared.
4
+ import type { ComponentProps } from 'svelte'
5
+ import BoxPlot from './BoxPlot.svelte'
6
+
7
+ let {
8
+ series = $bindable([]),
9
+ kind = $bindable(`violin`),
10
+ ...rest
11
+ }: ComponentProps<typeof BoxPlot> = $props()
12
+ </script>
13
+
14
+ <BoxPlot bind:series bind:kind {...rest} />
@@ -0,0 +1,70 @@
1
+ declare const Violin: import("svelte").Component<import("svelte/elements").HTMLAttributes<HTMLDivElement> & import("..").BasePlotProps & import("..").PlotConfig & {
2
+ series?: import("./box-plot").BoxPlotSeries<Record<string, unknown>>[] | undefined;
3
+ orientation?: import("..").Orientation;
4
+ legend?: import("..").LegendConfig | null;
5
+ show_legend?: boolean;
6
+ box?: {
7
+ color?: string;
8
+ opacity?: number;
9
+ stroke_width?: number;
10
+ stroke_color?: string;
11
+ border_radius?: number;
12
+ } | undefined;
13
+ whisker?: {
14
+ width?: number;
15
+ color?: string;
16
+ cap_fraction?: number;
17
+ } | undefined;
18
+ median_style?: {
19
+ width?: number;
20
+ color?: string;
21
+ } | undefined;
22
+ outlier_style?: {
23
+ radius?: number;
24
+ opacity?: number;
25
+ stroke_width?: number;
26
+ } | undefined;
27
+ whisker_mode?: import("./box-plot").WhiskerMode;
28
+ whisker_range?: number;
29
+ whisker_percentiles?: [number, number];
30
+ show_outliers?: boolean;
31
+ show_mean?: boolean;
32
+ show_value_labels?: boolean;
33
+ value_label_stat?: `median` | `mean`;
34
+ value_label_format?: string;
35
+ kind?: import("./box-plot").ViolinKind;
36
+ side?: import("./box-plot").ViolinSide;
37
+ bandwidth?: import("./box-plot").BandwidthOption;
38
+ violin_width?: number;
39
+ violin_style?: {
40
+ opacity?: number;
41
+ stroke_width?: number;
42
+ } | undefined;
43
+ kde_points?: number;
44
+ kde_cut?: number;
45
+ kde_max_samples?: number;
46
+ kde_clip?: [number | null, number | null];
47
+ tooltip?: import("svelte").Snippet<[import("./box-plot").BoxHandlerProps<Record<string, unknown>>]> | undefined;
48
+ user_content?: import("svelte").Snippet<[import("..").UserContentProps]>;
49
+ header_controls?: import("svelte").Snippet<[{
50
+ height: number;
51
+ width: number;
52
+ fullscreen: boolean;
53
+ }]> | undefined;
54
+ controls_extra?: import("svelte").Snippet<[{
55
+ orientation: import("..").Orientation;
56
+ } & Required<import("..").PlotConfig>]> | undefined;
57
+ change?: ((data: import("./box-plot").BoxHandlerProps<Record<string, unknown>> | null) => void) | undefined;
58
+ on_box_click?: ((data: import("./box-plot").BoxHandlerProps<Record<string, unknown>> & {
59
+ event: MouseEvent | KeyboardEvent;
60
+ }) => void) | undefined;
61
+ on_box_hover?: ((data: (import("./box-plot").BoxHandlerProps<Record<string, unknown>> & {
62
+ event: MouseEvent | FocusEvent | KeyboardEvent;
63
+ }) | null) => void) | undefined;
64
+ ref_lines?: import("..").RefLine[];
65
+ on_ref_line_click?: ((event: import("..").RefLineEvent) => void) | undefined;
66
+ on_ref_line_hover?: ((event: import("..").RefLineEvent | null) => void) | undefined;
67
+ pan?: import("..").PanConfig;
68
+ }, {}, "series" | "kind">;
69
+ type Violin = ReturnType<typeof Violin>;
70
+ export default Violin;
@@ -0,0 +1,55 @@
1
+ import type { HandlerProps } from '../core/types';
2
+ export type WhiskerMode = `tukey` | `minmax` | `percentile` | `std`;
3
+ export type ViolinKind = `box` | `violin` | `violin+box`;
4
+ export type ViolinSide = `both` | `positive` | `negative`;
5
+ export type BandwidthOption = number | `silverman` | `scott`;
6
+ export interface BoxPlotSeries<Metadata = Record<string, unknown>> {
7
+ id?: string | number;
8
+ y: readonly number[];
9
+ label?: string;
10
+ color?: string;
11
+ box_width?: number;
12
+ visible?: boolean;
13
+ legend_group?: string;
14
+ metadata?: Metadata;
15
+ x_axis?: `x1` | `x2`;
16
+ y_axis?: `y1` | `y2`;
17
+ whisker_mode?: WhiskerMode;
18
+ whisker_range?: number;
19
+ whisker_percentiles?: [number, number];
20
+ kind?: ViolinKind;
21
+ side?: ViolinSide;
22
+ bandwidth?: BandwidthOption;
23
+ violin_width?: number;
24
+ clip?: [number | null, number | null];
25
+ category?: string;
26
+ }
27
+ export interface BoxHandlerProps<Metadata = Record<string, unknown>> extends HandlerProps<Metadata> {
28
+ box_idx: number;
29
+ stats: BoxStats;
30
+ color: string;
31
+ category_label?: string;
32
+ active_y_axis: `y1` | `y2`;
33
+ active_x_axis: `x1` | `x2`;
34
+ }
35
+ export interface BoxStats {
36
+ min: number;
37
+ max: number;
38
+ q1: number;
39
+ median: number;
40
+ q3: number;
41
+ mean: number;
42
+ whisker_low: number;
43
+ whisker_high: number;
44
+ outliers: number[];
45
+ n: number;
46
+ }
47
+ export interface BoxStatsOptions {
48
+ whisker_mode?: WhiskerMode;
49
+ whisker_range?: number;
50
+ whisker_percentiles?: [number, number];
51
+ collect_outliers?: boolean;
52
+ }
53
+ export declare const WHISKER_MODES: readonly ["tukey", "minmax", "percentile", "std"];
54
+ export declare const is_whisker_mode: (val: string) => val is WhiskerMode;
55
+ export declare function compute_box_stats(values: readonly number[], opts?: BoxStatsOptions): BoxStats;
@@ -0,0 +1,126 @@
1
+ // Box plot statistics: compute quartiles, whiskers and outliers from a raw distribution.
2
+ // Single source of truth for the quantile math used by BoxPlot.svelte.
3
+ import { ascending } from 'd3-array';
4
+ import { quantile_unordered } from './quantile';
5
+ export const WHISKER_MODES = [`tukey`, `minmax`, `percentile`, `std`];
6
+ const WHISKER_MODE_SET = new Set(WHISKER_MODES);
7
+ export const is_whisker_mode = (val) => WHISKER_MODE_SET.has(val);
8
+ const EMPTY_STATS = {
9
+ min: NaN,
10
+ max: NaN,
11
+ q1: NaN,
12
+ median: NaN,
13
+ q3: NaN,
14
+ mean: NaN,
15
+ whisker_low: NaN,
16
+ whisker_high: NaN,
17
+ outliers: [],
18
+ n: 0,
19
+ };
20
+ const clamp01 = (val) => Math.max(0, Math.min(1, val));
21
+ function collect_outliers_by_scan(values, low_bound, high_bound, collect) {
22
+ if (!collect)
23
+ return [];
24
+ const outliers = [];
25
+ for (const val of values)
26
+ if (val < low_bound || val > high_bound)
27
+ outliers.push(val);
28
+ outliers.sort(ascending);
29
+ return outliers;
30
+ }
31
+ function tukey_scan(values, low_bound, high_bound, collect, data_min, data_max) {
32
+ let whisker_low = Infinity;
33
+ let whisker_high = -Infinity;
34
+ const outliers = [];
35
+ for (const val of values) {
36
+ if (val < low_bound || val > high_bound) {
37
+ if (collect)
38
+ outliers.push(val);
39
+ }
40
+ else {
41
+ if (val < whisker_low)
42
+ whisker_low = val;
43
+ if (val > whisker_high)
44
+ whisker_high = val;
45
+ }
46
+ }
47
+ if (collect)
48
+ outliers.sort(ascending);
49
+ return {
50
+ whisker_low: whisker_low === Infinity ? data_min : whisker_low,
51
+ whisker_high: whisker_high === -Infinity ? data_max : whisker_high,
52
+ outliers,
53
+ };
54
+ }
55
+ // Compute box plot statistics for a raw numeric distribution.
56
+ // Quartiles use type-7 linear interpolation, matching d3/numpy/pandas defaults.
57
+ // Non-finite values are filtered out; the input array is never mutated.
58
+ export function compute_box_stats(values, opts = {}) {
59
+ const { whisker_mode = `tukey`, whisker_range = 1.5, whisker_percentiles = [5, 95], collect_outliers = true, } = opts;
60
+ const vals = values.filter((val) => Number.isFinite(val));
61
+ const n_vals = vals.length;
62
+ if (n_vals === 0)
63
+ return { ...EMPTY_STATS, outliers: [] };
64
+ let sum = 0;
65
+ let data_min = Infinity;
66
+ let data_max = -Infinity;
67
+ for (const val of vals) {
68
+ sum += val;
69
+ if (val < data_min)
70
+ data_min = val;
71
+ if (val > data_max)
72
+ data_max = val;
73
+ }
74
+ const mean = sum / n_vals;
75
+ const qtl = (p) => quantile_unordered(vals, p);
76
+ const collect_beyond = (lo, hi) => collect_outliers_by_scan(vals, lo, hi, collect_outliers);
77
+ const q1 = qtl(0.25);
78
+ const median = qtl(0.5);
79
+ const q3 = qtl(0.75);
80
+ let whisker_low;
81
+ let whisker_high;
82
+ let outliers = [];
83
+ if (whisker_mode === `minmax`) {
84
+ whisker_low = data_min;
85
+ whisker_high = data_max;
86
+ }
87
+ else if (whisker_mode === `percentile`) {
88
+ // Order-defensively so reversed input like [95, 5] still yields low <= high
89
+ const pct_low = Math.min(...whisker_percentiles);
90
+ const pct_high = Math.max(...whisker_percentiles);
91
+ whisker_low = qtl(clamp01(pct_low / 100));
92
+ whisker_high = qtl(clamp01(pct_high / 100));
93
+ outliers = collect_beyond(whisker_low, whisker_high);
94
+ }
95
+ else if (whisker_mode === `std`) {
96
+ let variance_sum = 0;
97
+ for (const val of vals) {
98
+ const delta = val - mean;
99
+ variance_sum += delta * delta;
100
+ }
101
+ const std = n_vals > 1 ? Math.sqrt(variance_sum / (n_vals - 1)) : 0;
102
+ const low_bound = mean - whisker_range * std;
103
+ const high_bound = mean + whisker_range * std;
104
+ // Clamp whisker ends to the data extent so they never extend past real values
105
+ whisker_low = Math.max(data_min, low_bound);
106
+ whisker_high = Math.min(data_max, high_bound);
107
+ outliers = collect_beyond(low_bound, high_bound);
108
+ }
109
+ else {
110
+ // tukey (default): whiskers extend to the most extreme datum within range*IQR of the quartiles
111
+ const iqr = q3 - q1;
112
+ ({ whisker_low, whisker_high, outliers } = tukey_scan(vals, q1 - whisker_range * iqr, q3 + whisker_range * iqr, collect_outliers, data_min, data_max));
113
+ }
114
+ return {
115
+ min: data_min,
116
+ max: data_max,
117
+ q1,
118
+ median,
119
+ q3,
120
+ mean,
121
+ whisker_low,
122
+ whisker_high,
123
+ outliers,
124
+ n: n_vals,
125
+ };
126
+ }
@@ -0,0 +1,5 @@
1
+ export * from './box-plot';
2
+ export * from './kde';
3
+ export { default as BoxPlot } from './BoxPlot.svelte';
4
+ export { default as BoxPlotControls } from './BoxPlotControls.svelte';
5
+ export { default as Violin } from './Violin.svelte';
@@ -0,0 +1,5 @@
1
+ export * from './box-plot';
2
+ export * from './kde';
3
+ export { default as BoxPlot } from './BoxPlot.svelte';
4
+ export { default as BoxPlotControls } from './BoxPlotControls.svelte';
5
+ export { default as Violin } from './Violin.svelte';
@@ -0,0 +1,16 @@
1
+ export interface KdeResult {
2
+ grid: number[];
3
+ density: number[];
4
+ bandwidth: number;
5
+ }
6
+ export interface KdeOptions {
7
+ bandwidth?: number | `silverman` | `scott`;
8
+ n_points?: number;
9
+ cut?: number;
10
+ clip?: [number | null, number | null];
11
+ range?: [number, number];
12
+ max_samples?: number;
13
+ }
14
+ export declare function silverman_bandwidth(sorted: readonly number[]): number;
15
+ export declare function scott_bandwidth(samples: readonly number[]): number;
16
+ export declare function gaussian_kde(samples: readonly number[], opts?: KdeOptions): KdeResult;
@@ -0,0 +1,160 @@
1
+ // 1-D Gaussian kernel density estimation for violin plots.
2
+ // Pure and unit-tested; mirrors the style of box-plot.ts. Never mutates inputs.
3
+ import { quantile_sorted, quantile_unordered } from './quantile';
4
+ const KDE_EXACT_SAMPLE_LIMIT = 1024;
5
+ const KDE_TAIL_SIGMA = 6;
6
+ function sample_deviation(sorted) {
7
+ const n_vals = sorted.length;
8
+ if (n_vals < 2)
9
+ return 0;
10
+ let sum = 0;
11
+ for (const val of sorted)
12
+ sum += val;
13
+ const mean = sum / n_vals;
14
+ let variance_sum = 0;
15
+ for (const val of sorted) {
16
+ const delta = val - mean;
17
+ variance_sum += delta * delta;
18
+ }
19
+ return Math.sqrt(variance_sum / (n_vals - 1));
20
+ }
21
+ // Silverman's rule of thumb: 0.9 * min(std, IQR/1.34) * n^(-1/5). Matches scipy/seaborn.
22
+ // (`sigma` floors to std then 1 to avoid a zero bandwidth.)
23
+ const silverman_from_stats = (n_vals, std, iqr) => {
24
+ const spread = iqr > 0 ? Math.min(std, iqr / 1.34) : std;
25
+ const sigma = spread > 0 ? spread : std > 0 ? std : 1;
26
+ return 0.9 * sigma * n_vals ** (-1 / 5);
27
+ };
28
+ export function silverman_bandwidth(sorted) {
29
+ if (sorted.length < 2)
30
+ return 1;
31
+ const iqr = quantile_sorted(sorted, 0.75) - quantile_sorted(sorted, 0.25);
32
+ return silverman_from_stats(sorted.length, sample_deviation(sorted), iqr);
33
+ }
34
+ function silverman_bandwidth_unordered(samples) {
35
+ if (samples.length < 2)
36
+ return 1;
37
+ const q1 = quantile_unordered(samples, 0.25);
38
+ const q3 = quantile_unordered(samples, 0.75);
39
+ return silverman_from_stats(samples.length, sample_deviation(samples), q3 - q1);
40
+ }
41
+ // Scott's rule: std * n^(-1/5) for 1-D data.
42
+ // `samples` need not be sorted (only uses sample_deviation, unlike silverman_bandwidth)
43
+ export function scott_bandwidth(samples) {
44
+ const n_vals = samples.length;
45
+ if (n_vals < 2)
46
+ return 1;
47
+ const std = sample_deviation(samples) || 1;
48
+ return std * n_vals ** (-1 / 5);
49
+ }
50
+ function exact_density(eval_samples, grid, band) {
51
+ const n_eval = eval_samples.length;
52
+ const norm = 1 / (n_eval * band * Math.sqrt(2 * Math.PI));
53
+ const density = Array.from({ length: grid.length }, () => 0);
54
+ for (let grid_idx = 0; grid_idx < grid.length; grid_idx++) {
55
+ const g_val = grid[grid_idx];
56
+ let sum = 0;
57
+ for (const sample of eval_samples) {
58
+ const u = (g_val - sample) / band;
59
+ sum += Math.exp(-0.5 * u * u);
60
+ }
61
+ density[grid_idx] = sum * norm;
62
+ }
63
+ return density;
64
+ }
65
+ function binned_density(eval_samples, grid, band) {
66
+ const n_eval = eval_samples.length;
67
+ let sample_min = Infinity;
68
+ let sample_max = -Infinity;
69
+ for (const sample of eval_samples) {
70
+ if (sample < sample_min)
71
+ sample_min = sample;
72
+ if (sample > sample_max)
73
+ sample_max = sample;
74
+ }
75
+ if (sample_max <= sample_min)
76
+ return exact_density(eval_samples, grid, band);
77
+ const bin_count = Math.min(1024, Math.max(128, grid.length * 4));
78
+ const counts = new Float64Array(bin_count);
79
+ const span = sample_max - sample_min;
80
+ const inv_bin_width = bin_count / span;
81
+ for (const sample of eval_samples) {
82
+ const idx = Math.min(bin_count - 1, Math.floor((sample - sample_min) * inv_bin_width));
83
+ counts[idx] += 1;
84
+ }
85
+ const centers = new Float64Array(bin_count);
86
+ const bin_width = span / bin_count;
87
+ for (let idx = 0; idx < bin_count; idx++)
88
+ centers[idx] = sample_min + (idx + 0.5) * bin_width;
89
+ const density = Array.from({ length: grid.length }, () => 0);
90
+ const norm = 1 / (n_eval * band * Math.sqrt(2 * Math.PI));
91
+ const radius = KDE_TAIL_SIGMA * band;
92
+ for (let grid_idx = 0; grid_idx < grid.length; grid_idx++) {
93
+ const g_val = grid[grid_idx];
94
+ const start = Math.max(0, Math.floor((g_val - radius - sample_min) * inv_bin_width));
95
+ const stop = Math.min(bin_count - 1, Math.floor((g_val + radius - sample_min) * inv_bin_width));
96
+ let sum = 0;
97
+ for (let bin_idx = start; bin_idx <= stop; bin_idx++) {
98
+ const count = counts[bin_idx];
99
+ if (count === 0)
100
+ continue;
101
+ const u = (g_val - centers[bin_idx]) / band;
102
+ sum += count * Math.exp(-0.5 * u * u);
103
+ }
104
+ density[grid_idx] = sum * norm;
105
+ }
106
+ return density;
107
+ }
108
+ // Estimate a smooth density from raw samples via a Gaussian kernel.
109
+ export function gaussian_kde(samples, opts = {}) {
110
+ const { bandwidth = `silverman`, n_points = 100, cut = 2, clip, range, max_samples } = opts;
111
+ const finite = samples.filter((val) => Number.isFinite(val));
112
+ const n_vals = finite.length;
113
+ if (n_vals === 0)
114
+ return { grid: [], density: [], bandwidth: 0 };
115
+ let data_min = Infinity;
116
+ let data_max = -Infinity;
117
+ for (const sample of finite) {
118
+ if (sample < data_min)
119
+ data_min = sample;
120
+ if (sample > data_max)
121
+ data_max = sample;
122
+ }
123
+ // Deterministic stride subsample for the density sum on large inputs.
124
+ // Do this before unordered quantile selection mutates `finite`.
125
+ let eval_samples = finite;
126
+ if (max_samples && n_vals > max_samples) {
127
+ const step = n_vals / max_samples;
128
+ const sampled = Array.from({ length: max_samples }, () => 0);
129
+ for (let idx = 0; idx < max_samples; idx++)
130
+ sampled[idx] = finite[Math.floor(idx * step)];
131
+ eval_samples = sampled;
132
+ }
133
+ let band = typeof bandwidth === `number`
134
+ ? bandwidth
135
+ : bandwidth === `scott`
136
+ ? scott_bandwidth(finite)
137
+ : silverman_bandwidth_unordered(finite);
138
+ band = Math.max(band, 1e-12); // guard against zero/negative bandwidth
139
+ const n_eval = eval_samples.length;
140
+ let lo = range ? range[0] : data_min - cut * band;
141
+ let hi = range ? range[1] : data_max + cut * band;
142
+ if (clip) {
143
+ if (clip[0] != null)
144
+ lo = Math.max(lo, clip[0]);
145
+ if (clip[1] != null)
146
+ hi = Math.min(hi, clip[1]);
147
+ }
148
+ // An inverted/collapsed range (e.g. clip [10, 5], or a clip bound outside the data) leaves
149
+ // no valid grid -> degrade to an empty density rather than a corrupted descending grid.
150
+ if (hi <= lo)
151
+ return { grid: [], density: [], bandwidth: band };
152
+ const points = Math.max(2, Math.floor(n_points));
153
+ const grid = Array.from({ length: points }, () => 0);
154
+ for (let idx = 0; idx < points; idx++)
155
+ grid[idx] = lo + ((hi - lo) * idx) / (points - 1);
156
+ const density = max_samples && n_eval > KDE_EXACT_SAMPLE_LIMIT
157
+ ? binned_density(eval_samples, grid, band)
158
+ : exact_density(eval_samples, grid, band);
159
+ return { grid, density, bandwidth: band };
160
+ }