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
@@ -0,0 +1,436 @@
1
+ // Shared marginal-distribution model for all 2D plots. Pure and unit-tested: types,
2
+ // shorthand resolution, pad reservation, strip geometry, and the curve math (histogram /
3
+ // kde / cdf / rug). The PlotMarginals.svelte renderer consumes these; each plot only adapts
4
+ // its data to MarginalSeriesInput and folds reserve_marginal_pad into its `pad`.
5
+ import { sorted_range } from './interactions';
6
+ import { get_scale_type_name } from './types';
7
+ import { gaussian_kde } from '../box/kde';
8
+ import { bin } from 'd3-array';
9
+ export const MARGINAL_SIDES = [`top`, `bottom`, `left`, `right`];
10
+ // Top/bottom strips run along the x (horizontal) positional axis; left/right run along y
11
+ const is_x_side = (side) => side === `top` || side === `bottom`;
12
+ // Build a MarginalAxis from a host plot's scale fn + current range, reading scale_type/format/label
13
+ // off the plot's AxisConfig (DRYs the per-axis object every host plot passes to PlotMarginals; the
14
+ // renderer defaults a missing scale_type to `linear`). `tick_label` maps a position to a label.
15
+ export const marginal_axis = (scale, range, axis, tick_label) => ({
16
+ scale,
17
+ range,
18
+ scale_type: axis.scale_type,
19
+ format: axis.format,
20
+ label: axis.label,
21
+ tick_label,
22
+ });
23
+ // Pixel tolerance for rug-tick hit-testing (a tick farther than this from the pointer is a miss)
24
+ export const MARGINAL_HIT_TOLERANCE_PX = 10;
25
+ // Pure hit-test: given a strip's render context and a pointer position in wrapper px, return the
26
+ // nearest datum as a MarginalHover (or null for a miss). ctx.curves is kind-homogeneous, so we
27
+ // branch once on the first curve's kind, matching only along the shared positional axis. Non-finite
28
+ // data is skipped (consistent with the renderer) so custom reduce/data curves can't yield ghost hits.
29
+ export function marginal_hit(ctx, px, py) {
30
+ const { side, curves, positional_scale, value_scale, baseline, config, scale_type } = ctx;
31
+ const is_x = is_x_side(side);
32
+ const pointer_pos = is_x ? px : py; // along the shared positional axis
33
+ const pointer_cross = is_x ? py : px; // across the strip thickness (the value direction)
34
+ const kind = curves[0]?.curve.kind;
35
+ if (!kind)
36
+ return null;
37
+ const contains_cross = (value_px) => Number.isFinite(value_px) &&
38
+ pointer_cross >= Math.min(baseline, value_px) &&
39
+ pointer_cross <= Math.max(baseline, value_px);
40
+ const hover = (curve, extra) => ({
41
+ side,
42
+ x: px,
43
+ y: py,
44
+ color: config.color ?? curve.color,
45
+ label: curve.label,
46
+ kind,
47
+ config,
48
+ scale_type,
49
+ format: ctx.format,
50
+ pos_label: ctx.tick_label?.(extra.pos),
51
+ axis_title: ctx.axis_title,
52
+ ...extra,
53
+ });
54
+ if (kind === `bars`) {
55
+ // Among bins whose rendered rect contains the pointer, pick the largest-value (tallest) bar.
56
+ // Baseline-anchored bars nest, so the tallest containing bar wins render-order independently.
57
+ let best = null;
58
+ for (const series_curve of curves) {
59
+ if (series_curve.curve.kind !== `bars`)
60
+ continue;
61
+ for (const bar of series_curve.curve.bins) {
62
+ if (!Number.isFinite(bar.value) || bar.value <= 0)
63
+ continue; // finite positive only (matches renderer)
64
+ const edge_a = positional_scale(bar.pos0);
65
+ const edge_b = positional_scale(bar.pos1);
66
+ if (!Number.isFinite(edge_a) || !Number.isFinite(edge_b))
67
+ continue;
68
+ if (pointer_pos < Math.min(edge_a, edge_b) || pointer_pos > Math.max(edge_a, edge_b)) {
69
+ continue;
70
+ }
71
+ if (!contains_cross(value_scale(bar.value)))
72
+ continue;
73
+ if (!best || bar.value > best.bar.value)
74
+ best = { curve: series_curve, bar };
75
+ }
76
+ }
77
+ if (!best)
78
+ return null;
79
+ const { bar } = best;
80
+ return hover(best.curve, {
81
+ pos: (bar.pos0 + bar.pos1) / 2,
82
+ pos0: bar.pos0,
83
+ pos1: bar.pos1,
84
+ value: bar.value,
85
+ });
86
+ }
87
+ if (kind === `line`) {
88
+ let chosen = null;
89
+ let best_extent = -1;
90
+ for (const series_curve of curves) {
91
+ if (series_curve.curve.kind !== `line`)
92
+ continue;
93
+ const pts = [];
94
+ let min_pos = Infinity;
95
+ let max_pos = -Infinity;
96
+ for (const pt of series_curve.curve.points) {
97
+ const px_pos = positional_scale(pt.pos);
98
+ const px_val = value_scale(pt.value);
99
+ if (!Number.isFinite(px_pos) || !Number.isFinite(px_val))
100
+ continue;
101
+ pts.push({ curve: series_curve, pos: pt.pos, value: pt.value, px_pos, px_val });
102
+ min_pos = Math.min(min_pos, px_pos);
103
+ max_pos = Math.max(max_pos, px_pos);
104
+ }
105
+ if (pts.length < 2)
106
+ continue; // renderer skips line/area paths without two finite points
107
+ if (pointer_pos < min_pos || pointer_pos > max_pos)
108
+ continue;
109
+ let near = null;
110
+ let near_dist = Infinity;
111
+ for (const pt of pts) {
112
+ const pos_dist = Math.abs(pt.px_pos - pointer_pos);
113
+ if (pos_dist < near_dist) {
114
+ near_dist = pos_dist;
115
+ near = pt;
116
+ }
117
+ }
118
+ if (!near || !contains_cross(near.px_val))
119
+ continue;
120
+ const extent = Math.abs(near.px_val - baseline);
121
+ if (extent > best_extent)
122
+ [best_extent, chosen] = [extent, near];
123
+ }
124
+ return chosen ? hover(chosen.curve, { pos: chosen.pos, value: chosen.value }) : null;
125
+ }
126
+ // rug: nearest tick along the positional axis, within a pixel tolerance (no value/cross axis)
127
+ let best = null;
128
+ for (const series_curve of curves) {
129
+ if (series_curve.curve.kind !== `rug`)
130
+ continue;
131
+ for (const pos of series_curve.curve.positions) {
132
+ const px_pos = positional_scale(pos);
133
+ if (!Number.isFinite(px_pos))
134
+ continue;
135
+ const dist = Math.abs(px_pos - pointer_pos);
136
+ if (dist < (best?.dist ?? Infinity))
137
+ best = { curve: series_curve, pos, dist };
138
+ }
139
+ }
140
+ if (!best || best.dist > MARGINAL_HIT_TOLERANCE_PX)
141
+ return null;
142
+ return hover(best.curve, { pos: best.pos });
143
+ }
144
+ // Co-located defaults (mirrors REF_LINE_STYLE_DEFAULTS in types.ts). Deliberately NOT part of
145
+ // settings.ts DEFAULTS to avoid pulling marginals into the settings-UI JSON schema.
146
+ export const MARGINAL_DEFAULTS = {
147
+ type: `histogram`,
148
+ size: 64,
149
+ gap: 6,
150
+ placement: `auto`,
151
+ per_series: true,
152
+ bins: 60,
153
+ bandwidth: `silverman`,
154
+ stroke_width: 1.5,
155
+ opacity: 1,
156
+ value_axis: true,
157
+ };
158
+ // Normalize a single side's shorthand to a MarginalConfig, `false` (explicit disable), or
159
+ // undefined (not specified -> fall back to default)
160
+ const to_config = (input) => {
161
+ if (input === undefined)
162
+ return undefined;
163
+ if (input === false)
164
+ return false;
165
+ if (input === true)
166
+ return {};
167
+ if (typeof input === `string`)
168
+ return { type: input };
169
+ return input;
170
+ };
171
+ // Merge a user side-input over the plot's default side-input into a resolved config (or null)
172
+ const resolve_side = (user_input, default_input) => {
173
+ const user = to_config(user_input);
174
+ if (user === false)
175
+ return null; // explicit disable wins over any default
176
+ const base = to_config(default_input);
177
+ const base_cfg = base === false ? undefined : base;
178
+ if (user === undefined && base_cfg === undefined)
179
+ return null; // side inactive
180
+ return { ...MARGINAL_DEFAULTS, ...base_cfg, ...user };
181
+ };
182
+ // Expand the `marginals` prop into a per-side resolved config, merging with the plot's
183
+ // `default_sides` (the sensible defaults a given plot enables when `marginals` is `true`).
184
+ // - `true`: enable exactly the plot's default sides
185
+ // - a type string: that type on the plot's default sides (or top+right if none), inheriting
186
+ // each default side's config (e.g. shared bins)
187
+ // - a per-side map: enable ONLY the sides the user lists (default sides do not auto-activate),
188
+ // merging the plot's per-side default config under the user's
189
+ export function normalize_marginals(prop, default_sides = {}) {
190
+ const result = { top: null, bottom: null, left: null, right: null };
191
+ if (prop == null || prop === false)
192
+ return result;
193
+ if (prop === true) {
194
+ for (const side of MARGINAL_SIDES)
195
+ result[side] = resolve_side(undefined, default_sides[side]);
196
+ return result;
197
+ }
198
+ if (typeof prop === `string`) {
199
+ const sides = Object.keys(default_sides).length > 0 ? default_sides : { top: true, right: true };
200
+ for (const side of MARGINAL_SIDES) {
201
+ if (!(side in sides))
202
+ continue;
203
+ result[side] = resolve_side(prop, default_sides[side]);
204
+ }
205
+ return result;
206
+ }
207
+ // Explicit per-side map: only sides the user names become active
208
+ for (const side of MARGINAL_SIDES) {
209
+ if (prop[side] === undefined)
210
+ continue;
211
+ result[side] = resolve_side(prop[side], default_sides[side]);
212
+ }
213
+ return result;
214
+ }
215
+ // Padding (px) each plot must add to its `pad` to make room for active marginal strips
216
+ export function reserve_marginal_pad(resolved) {
217
+ const reserve = (cfg) => (cfg ? cfg.size + cfg.gap : 0);
218
+ return {
219
+ t: reserve(resolved.top),
220
+ b: reserve(resolved.bottom),
221
+ l: reserve(resolved.left),
222
+ r: reserve(resolved.right),
223
+ };
224
+ }
225
+ // Sum two padding objects (used to fold marginal reservation into the decoration pad)
226
+ export const add_sides = (a, b) => ({
227
+ t: a.t + b.t,
228
+ b: a.b + b.b,
229
+ l: a.l + b.l,
230
+ r: a.r + b.r,
231
+ });
232
+ // Default axis a side binds to when `config.axis` is unset
233
+ export const default_axis_for_side = (side) => is_x_side(side) ? `x1` : `y1`;
234
+ // Which sides carry an axis (drives `auto` placement). Bottom/left hold the primary x/y axes and
235
+ // are always present; top/right only when the plot shows a secondary axis there.
236
+ export const marginal_axis_presence = (top, right) => ({ top, bottom: true, left: true, right });
237
+ // Whether the strip should hug the plot edge (`flush`) vs sit beyond the ticks (`outer`)
238
+ const is_flush = (placement, has_axis) => placement === `flush` || (placement === `auto` && !has_axis);
239
+ // Pixel rect of a marginal strip. The cross dimension spans the plot area (so it aligns with
240
+ // the shared positional scale); the thickness is `config.size`, positioned per placement.
241
+ export function marginal_strip_rect(side, pad, width, height, config, has_axis) {
242
+ const { size, gap } = config;
243
+ const flush = is_flush(config.placement, has_axis);
244
+ const is_x = is_x_side(side);
245
+ const grows_negative = side === `top` || side === `left`;
246
+ // thickness-axis position of the strip's near edge: flush sits a gap from the plot, outer at
247
+ // the container edge (top/left strips go before the plot, bottom/right strips after it)
248
+ const plot_near = is_x ? pad.t : pad.l;
249
+ const plot_far = is_x ? height - pad.b : width - pad.r;
250
+ const container_far = is_x ? height : width;
251
+ const thick = flush
252
+ ? grows_negative
253
+ ? plot_near - gap - size
254
+ : plot_far + gap
255
+ : grows_negative
256
+ ? 0
257
+ : container_far - size;
258
+ // cross axis spans the plot area so the strip aligns with the shared positional scale
259
+ const cross_min = is_x ? pad.l : pad.t;
260
+ const cross = Math.max(0, (is_x ? width - pad.r : height - pad.b) - cross_min);
261
+ return is_x
262
+ ? { x: cross_min, y: thick, width: cross, height: size }
263
+ : { x: thick, y: cross_min, width: size, height: cross };
264
+ }
265
+ // Linear value scale across a strip's thickness, growing away from the plot. `domain` is the
266
+ // marginal value range (typically [0, max]); `baseline` is the plot-facing value=domain[0] edge.
267
+ export function marginal_value_scale(side, rect, domain) {
268
+ const [lo, hi] = domain;
269
+ const span = hi - lo || 1;
270
+ const is_x = is_x_side(side);
271
+ const thickness = is_x ? rect.height : rect.width;
272
+ const near = is_x ? rect.y : rect.x; // strip edge at the smaller pixel coordinate
273
+ // top/left strips grow toward smaller pixel coords; their baseline (value=lo, plot-facing) sits
274
+ // at the far edge, and value increases in the negative pixel direction
275
+ const grows_negative = side === `top` || side === `left`;
276
+ const baseline = grows_negative ? near + thickness : near;
277
+ const sign = grows_negative ? -1 : 1;
278
+ return { scale: (val) => baseline + sign * ((val - lo) / span) * thickness, baseline };
279
+ }
280
+ // Drop non-finite positions (and matching weights), restrict to the current positional range
281
+ // so every marginal type tracks zoom/pan consistently (histogram already clips via bin domain),
282
+ // and drop non-positive positions on a log axis.
283
+ const clean_pairs = (positions, weights, positional_range, scale_type) => {
284
+ const [lo, hi] = positional_range; // ascending (canonicalized by compute_marginal_curve)
285
+ const require_positive = get_scale_type_name(scale_type) === `log`;
286
+ const out_pos = [];
287
+ const out_wts = weights ? [] : undefined;
288
+ for (let idx = 0; idx < positions.length; idx++) {
289
+ const pos = positions[idx];
290
+ if (!Number.isFinite(pos) || pos < lo || pos > hi)
291
+ continue;
292
+ if (require_positive && pos <= 0)
293
+ continue;
294
+ if (weights && out_wts) {
295
+ const weight = weights[idx];
296
+ // skip non-finite and negative weights: a negative makes a weighted CDF non-monotone and
297
+ // skews histogram normalization. zero is kept (it contributes nothing and the renderer
298
+ // already drops zero-value bars, so skipping it would only needlessly drop rug/kde positions)
299
+ if (!Number.isFinite(weight) || weight < 0)
300
+ continue;
301
+ out_wts.push(weight);
302
+ }
303
+ out_pos.push(pos);
304
+ }
305
+ return { positions: out_pos, weights: out_wts };
306
+ };
307
+ function compute_histogram(positions, weights, config, positional_range) {
308
+ const indices = positions.map((_, idx) => idx);
309
+ const binner = bin()
310
+ .domain(positional_range)
311
+ .thresholds(config.bins)
312
+ .value((idx) => positions[idx]);
313
+ const binned = binner(indices);
314
+ let max = 0;
315
+ const bins = binned.map((items) => {
316
+ const value = weights ? items.reduce((sum, idx) => sum + weights[idx], 0) : items.length;
317
+ if (value > max)
318
+ max = value;
319
+ return { pos0: items.x0 ?? 0, pos1: items.x1 ?? 0, value };
320
+ });
321
+ // count: raw; probability: value/total; density: value/(total*bin_width)
322
+ if (config.normalize && config.normalize !== `count`) {
323
+ const grand = bins.reduce((sum, item) => sum + item.value, 0) || 1;
324
+ max = 0;
325
+ for (const item of bins) {
326
+ const width = item.pos1 - item.pos0;
327
+ item.value =
328
+ config.normalize === `density`
329
+ ? item.value / (grand * (width || 1))
330
+ : item.value / grand;
331
+ if (item.value > max)
332
+ max = item.value;
333
+ }
334
+ }
335
+ return { kind: `bars`, bins, max };
336
+ }
337
+ function compute_cdf(positions, weights) {
338
+ const order = positions.map((_, idx) => idx).sort((a, b) => positions[a] - positions[b]);
339
+ const total = weights ? weights.reduce((sum, weight) => sum + weight, 0) : positions.length;
340
+ const points = [];
341
+ let cum = 0;
342
+ for (const idx of order) {
343
+ cum += weights ? weights[idx] : 1;
344
+ const pos = positions[idx];
345
+ const value = total > 0 ? cum / total : 0;
346
+ // collapse ties so positions stay strictly increasing (keeps monotone curves well-behaved)
347
+ const last = points[points.length - 1];
348
+ if (last?.pos === pos)
349
+ last.value = value;
350
+ else
351
+ points.push({ pos, value });
352
+ }
353
+ return { kind: `line`, points, max: 1 };
354
+ }
355
+ // Smallest strictly-positive value (Infinity if none): repairs a degenerate log lower bound (<= 0)
356
+ // so kde grids / histogram bins don't dip to non-renderable positions
357
+ const smallest_positive = (vals) => vals.reduce((min, val) => (val > 0 && val < min ? val : min), Infinity);
358
+ function compute_kde(positions, config, positional_range, scale_type) {
359
+ // The grid spans the current positional range, so on a normal log axis (range[0] > 0) no
360
+ // clamping is needed. Only repair a degenerate log range whose lower bound is <= 0 (would
361
+ // otherwise emit grid points at <= 0 -> NaN pixels) by clamping to the smallest positive sample.
362
+ let clip;
363
+ if (get_scale_type_name(scale_type) === `log` && positional_range[0] <= 0) {
364
+ const min_pos = smallest_positive(positions);
365
+ if (Number.isFinite(min_pos))
366
+ clip = [min_pos, null];
367
+ }
368
+ const kde = gaussian_kde(positions, {
369
+ bandwidth: config.bandwidth,
370
+ n_points: 100,
371
+ range: positional_range,
372
+ clip,
373
+ max_samples: 5000,
374
+ });
375
+ let max = 0;
376
+ for (const density of kde.density)
377
+ if (density > max)
378
+ max = density;
379
+ const points = kde.grid.map((pos, idx) => ({ pos, value: kde.density[idx] }));
380
+ return { kind: `line`, points, max };
381
+ }
382
+ // Summarize 1-D values into a renderable curve per the marginal type. Filters non-finite
383
+ // inputs and returns an empty curve for empty input (so nothing renders).
384
+ export function compute_marginal_curve(positions, weights, config, positional_range, scale_type) {
385
+ // Canonicalize to an ascending range so a reversed (inverted-axis) range doesn't crash
386
+ // d3.bin (negative-length bin array) or empty the kde grid
387
+ const range = sorted_range(positional_range[0], positional_range[1]);
388
+ const { positions: pos, weights: wts } = clean_pairs(positions, weights, range, scale_type);
389
+ // rug returns the raw positions (empty or not); other types short-circuit on empty input
390
+ if (config.type === `rug`)
391
+ return { kind: `rug`, positions: pos };
392
+ if (pos.length === 0) {
393
+ return config.type === `histogram`
394
+ ? { kind: `bars`, bins: [], max: 0 }
395
+ : { kind: `line`, points: [], max: 0 };
396
+ }
397
+ if (config.type === `histogram`) {
398
+ // on a degenerate log axis (lower bound <= 0) bin over the smallest positive sample instead, so
399
+ // bins aren't spread below the smallest renderable position (mirrors compute_kde's clip)
400
+ const hist_range = get_scale_type_name(scale_type) === `log` && range[0] <= 0
401
+ ? [smallest_positive(pos), range[1]]
402
+ : range;
403
+ return compute_histogram(pos, wts, config, hist_range);
404
+ }
405
+ if (config.type === `cdf`)
406
+ return compute_cdf(pos, wts);
407
+ return compute_kde(pos, config, range, scale_type);
408
+ }
409
+ // Max value across a set of curves (for a shared per-side value scale)
410
+ export const curves_max = (curves) => curves.reduce((max, curve) => (curve.kind === `rug` ? max : Math.max(max, curve.max)), 0);
411
+ // Value-axis title for a strip: explicit `config.label` wins, else auto per type (histogram uses
412
+ // its normalization). `rug` has no value axis so returns an empty string.
413
+ export const default_marginal_label = (config) => {
414
+ if (config.label != null)
415
+ return config.label;
416
+ if (config.type === `cdf`)
417
+ return `CDF`;
418
+ if (config.type === `kde`)
419
+ return `density`;
420
+ if (config.type === `histogram`)
421
+ return config.normalize ?? `count`;
422
+ return ``;
423
+ };
424
+ // d3-format spec for the strip's value-axis tick labels, picked to suit each type's value units
425
+ export const marginal_value_format = (config) => {
426
+ if (config.type === `cdf`)
427
+ return `.0%`;
428
+ if (config.type === `histogram`) {
429
+ if (config.normalize === `probability`)
430
+ return `.0%`;
431
+ if (config.normalize === `density`)
432
+ return `.2~g`;
433
+ return `.3~s`;
434
+ }
435
+ return `.2~g`; // kde density
436
+ };
@@ -210,7 +210,7 @@ export function calculate_annotation_position(x1, y1, x2, y2, annotation) {
210
210
  // Calculate base position with edge padding applied along line direction
211
211
  const dx = x2 - x1;
212
212
  const dy = y2 - y1;
213
- const len = Math.sqrt(dx * dx + dy * dy);
213
+ const len = Math.hypot(dx, dy);
214
214
  let base_x = x1 + frac * dx;
215
215
  let base_y = y1 + frac * dy;
216
216
  // Apply edge padding to pull text slightly inward from plot boundaries
@@ -17,6 +17,29 @@ export type PlotScaleFn = ScaleContinuousNumeric<number, number> | ScaleTime<num
17
17
  export declare function scale_arcsinh(threshold?: number): ArcsinhScale;
18
18
  export declare function generate_arcsinh_ticks(min: number, max: number, threshold?: number, count?: number): number[];
19
19
  export declare function create_scale(scale_type: ScaleType, domain: Vec2, output_range: Vec2): ScaleContinuousNumeric<number, number> | ArcsinhScale;
20
+ export declare function create_axis_scales<A extends {
21
+ scale_type?: ScaleType;
22
+ }>(axes: {
23
+ x: A;
24
+ x2: A;
25
+ y: A;
26
+ y2: A;
27
+ }, ranges: {
28
+ x: Vec2;
29
+ x2: Vec2;
30
+ y: Vec2;
31
+ y2: Vec2;
32
+ }, pad: {
33
+ l: number;
34
+ r: number;
35
+ t: number;
36
+ b: number;
37
+ }, width: number, height: number): {
38
+ x: ArcsinhScale | ScaleContinuousNumeric<number, number, never>;
39
+ x2: ArcsinhScale | ScaleContinuousNumeric<number, number, never>;
40
+ y: ArcsinhScale | ScaleContinuousNumeric<number, number, never>;
41
+ y2: ArcsinhScale | ScaleContinuousNumeric<number, number, never>;
42
+ };
20
43
  export declare const create_time_scale: (domain: Vec2, output_range: Vec2) => ScaleTime<number, number, never>;
21
44
  export declare function generate_ticks(domain: Vec2, scale_type: ScaleType, ticks_option: TicksOption | undefined, scale_fn: PlotScaleFn, // D3 scale function with .ticks() method
22
45
  options?: {
@@ -1,5 +1,7 @@
1
1
  import * as math from '../../math';
2
- import { get_arcsinh_threshold, get_scale_type_name, is_time_scale, } from './types';
2
+ import { get_d3_interpolator } from '../../colors';
3
+ import { clamp01 } from '../../utils';
4
+ import { get_arcsinh_threshold, get_scale_type_name, is_time_scale, SCALE_DEFAULTS, } from './types';
3
5
  import { extent, range } from 'd3-array';
4
6
  import { scaleLinear, scaleLog, scaleSequential, scaleSequentialLog, scaleTime, } from 'd3-scale';
5
7
  import * as d3_sc from 'd3-scale-chromatic';
@@ -188,6 +190,19 @@ export function create_scale(scale_type, domain, output_range) {
188
190
  // For 'time' or 'linear', return linear scale (time scales need create_time_scale())
189
191
  return scaleLinear().domain(domain).range(output_range);
190
192
  }
193
+ // Build the four axis scales for a 2D plot in one call: x/x2 share the horizontal pixel span,
194
+ // y/y2 the inverted vertical one. Shared by BarPlot/BoxPlot/Histogram (identical layout math).
195
+ export function create_axis_scales(axes, ranges, pad, width, height) {
196
+ const x_px = [pad.l, width - pad.r];
197
+ const y_px = [height - pad.b, pad.t];
198
+ const scale = (axis, domain, px) => create_scale(axis.scale_type ?? `linear`, domain, px);
199
+ return {
200
+ x: scale(axes.x, ranges.x, x_px),
201
+ x2: scale(axes.x2, ranges.x2, x_px),
202
+ y: scale(axes.y, ranges.y, y_px),
203
+ y2: scale(axes.y2, ranges.y2, y_px),
204
+ };
205
+ }
191
206
  // Create a time scale for time-based data
192
207
  export const create_time_scale = (domain, output_range) => scaleTime()
193
208
  .domain([new Date(domain[0]), new Date(domain[1])])
@@ -263,9 +278,13 @@ export function calculate_domain(values, scale_type = `linear`) {
263
278
  if (min_val === undefined || max_val === undefined)
264
279
  return [0, 1];
265
280
  const type_name = get_scale_type_name(scale_type);
266
- // Only log scale needs domain clamping to positive values
267
- // Arcsinh and linear can handle any values
268
- return type_name === `log` ? [Math.max(min_val, math.LOG_EPS), max_val] : [min_val, max_val];
281
+ // log clamps to positive (arcsinh/linear take any value); clamp BOTH ends so all-negative
282
+ // data can't leave max <= the clamped min and invert/collapse the scale
283
+ if (type_name === `log`) {
284
+ const lo = Math.max(min_val, math.LOG_EPS);
285
+ return [lo, Math.max(max_val, lo)];
286
+ }
287
+ return [min_val, max_val];
269
288
  }
270
289
  // Advanced domain calculation with padding and nice boundaries (from ScatterPlot)
271
290
  export function get_nice_data_range(points, get_value, limits, scale_type, padding_factor, is_time = false) {
@@ -274,6 +293,13 @@ export function get_nice_data_range(points, get_value, limits, scale_type, paddi
274
293
  let data_min = min ?? min_ext ?? 0;
275
294
  let data_max = max ?? max_ext ?? 1;
276
295
  const type_name = get_scale_type_name(scale_type);
296
+ const can_snap_zero = min_ext !== undefined &&
297
+ max_ext !== undefined &&
298
+ min_ext < max_ext &&
299
+ !is_time &&
300
+ type_name !== `log`;
301
+ const snap_zero_min = can_snap_zero && min === null && min_ext === 0;
302
+ const snap_zero_max = can_snap_zero && max === null && max_ext === 0;
277
303
  // Apply padding *only if* limits were NOT provided
278
304
  if (min === null && max === null && points.length > 0) {
279
305
  if (data_min !== data_max) {
@@ -339,7 +365,7 @@ export function get_nice_data_range(points, get_value, limits, scale_type, paddi
339
365
  // Use D3's nice() to create pretty boundaries
340
366
  // For arcsinh, we don't use D3's nice() - just return padded domain
341
367
  if (type_name === `arcsinh`) {
342
- return [data_min, data_max];
368
+ return [snap_zero_min ? 0 : data_min, snap_zero_max ? 0 : data_max];
343
369
  }
344
370
  // Create the scale with the *padded* data domain
345
371
  const scale = type_name === `log`
@@ -350,7 +376,7 @@ export function get_nice_data_range(points, get_value, limits, scale_type, paddi
350
376
  : scaleLinear().domain([data_min, data_max]);
351
377
  scale.nice();
352
378
  const [nice_min = data_min, nice_max = data_max] = scale.domain();
353
- return [nice_min, nice_max];
379
+ return [snap_zero_min ? 0 : nice_min, snap_zero_max ? 0 : nice_max];
354
380
  }
355
381
  // Generate logarithmic ticks (from ScatterPlot)
356
382
  export function generate_log_ticks(min, max, ticks_option) {
@@ -400,16 +426,16 @@ export function create_color_scale(color_scale_config, auto_color_range) {
400
426
  const candidate_interpolator = Object.entries(d3_sc).find(([key]) => key === scheme)?.[1];
401
427
  const interpolator = typeof candidate_interpolator === `function`
402
428
  ? candidate_interpolator
403
- : d3_sc.interpolateViridis;
429
+ : get_d3_interpolator(SCALE_DEFAULTS.scheme);
404
430
  const [min_val, max_val] = (typeof color_scale_config === `string` ? undefined : color_scale_config.value_range) ??
405
431
  auto_color_range;
406
432
  const scale_type = typeof color_scale_config === `string` ? undefined : color_scale_config.type;
407
433
  const type_name = get_scale_type_name(scale_type);
408
434
  if (type_name === `log`) {
409
- return scaleSequentialLog(interpolator).domain([
410
- Math.max(min_val, math.LOG_EPS),
411
- Math.max(max_val, min_val * 1.1),
412
- ]);
435
+ // clamp both ends (like create_scale): all-negative data otherwise yields an inverted
436
+ // [LOG_EPS, max<0] domain that maps every input to undefined
437
+ const lo = Math.max(min_val, math.LOG_EPS);
438
+ return scaleSequentialLog(interpolator).domain([lo, Math.max(max_val, lo * 1.1)]);
413
439
  }
414
440
  if (type_name === `arcsinh`) {
415
441
  // For arcsinh color scale, we create a custom scale that wraps the interpolator
@@ -436,7 +462,7 @@ function create_arcsinh_color_scale(interpolator, initial_domain, threshold) {
436
462
  const t_val = Math.asinh(value / safe_threshold);
437
463
  // Normalize to [0, 1]
438
464
  const normalized = t_max === t_min ? 0.5 : (t_val - t_min) / (t_max - t_min);
439
- return interpolator(Math.max(0, Math.min(1, normalized)));
465
+ return interpolator(clamp01(normalized));
440
466
  });
441
467
  // Domain getter/setter for D3 compatibility - returns same scale instance
442
468
  scale.domain = function (new_domain) {
@@ -449,7 +475,7 @@ function create_arcsinh_color_scale(interpolator, initial_domain, threshold) {
449
475
  }
450
476
  // Create a size scale function from configuration
451
477
  export function create_size_scale(config, all_size_values) {
452
- const [min_radius, max_radius] = config.radius_range ?? [2, 10];
478
+ const [min_radius, max_radius] = config.radius_range ?? SCALE_DEFAULTS.radius;
453
479
  const auto_range = all_size_values.length > 0
454
480
  ? extent(all_size_values.filter((val) => val !== null))
455
481
  : [0, 1];