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.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +12 -14
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/app.css +53 -0
- package/dist/brillouin/BrillouinZone.svelte +75 -85
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
- package/dist/brillouin/BrillouinZoneScene.svelte +26 -39
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +62 -74
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +511 -547
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +37 -31
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +7 -11
- package/dist/composition/Formula.svelte +18 -25
- package/dist/composition/FormulaFilter.svelte +92 -95
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +1 -1
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -2
- package/dist/composition/parse.js +11 -10
- package/dist/constants.js +11 -9
- package/dist/convex-hull/ConvexHull.svelte +12 -15
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +93 -92
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +109 -140
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +75 -94
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
- package/dist/convex-hull/ConvexHullControls.svelte +46 -48
- package/dist/convex-hull/ConvexHullStats.svelte +193 -195
- package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +17 -21
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +36 -36
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +18 -17
- package/dist/coordination/CoordinationBarPlot.svelte +38 -33
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +5 -8
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +24 -29
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +1 -2
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +1 -4
- package/dist/element/index.js +3 -18
- package/dist/feedback/DragOverlay.svelte +5 -5
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
- package/dist/feedback/StatusMessage.svelte +7 -4
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +14 -22
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -7
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +37 -64
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +3 -3
- package/dist/fermi-surface/parse.js +22 -24
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +109 -148
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/index.d.ts +5 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/io/ExportPane.svelte +10 -6
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -35
- package/dist/io/export.d.ts +4 -0
- package/dist/io/export.js +5 -1
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/index.d.ts +0 -1
- package/dist/io/index.js +2 -9
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/url-drop.js +13 -25
- package/dist/isosurface/Isosurface.svelte +17 -23
- package/dist/isosurface/IsosurfaceControls.svelte +37 -42
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +6 -6
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +43 -13
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +7 -18
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +21 -17
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +9 -10
- package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.js +1 -2
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +8 -11
- package/dist/layout/json-tree/JsonTree.svelte +53 -77
- package/dist/layout/json-tree/JsonValue.svelte +7 -15
- package/dist/layout/json-tree/utils.js +14 -23
- package/dist/math.d.ts +2 -0
- package/dist/math.js +19 -0
- package/dist/overlays/ContextMenu.svelte +4 -2
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +81 -26
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
- package/dist/overlays/GlassChip.svelte +30 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +7 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +113 -145
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +3 -3
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +21 -15
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +430 -391
- package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
- package/dist/plot/bar/SpacegroupBarPlot.svelte +29 -36
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +301 -209
- package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
- package/dist/plot/box/Violin.svelte.d.ts +1 -0
- package/dist/plot/box/box-plot.js +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +101 -106
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +18 -9
- package/dist/plot/core/components/Line.svelte.d.ts +2 -0
- package/dist/plot/core/components/PlotAxis.svelte +40 -17
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
- package/dist/plot/core/components/ReferencePlane.svelte +7 -8
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +27 -474
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +3 -1
- package/dist/plot/core/fill-utils.js +28 -6
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.js +0 -2
- package/dist/plot/core/layout.d.ts +3 -1
- package/dist/plot/core/layout.js +22 -13
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/reference-line.js +1 -1
- package/dist/plot/core/scales.d.ts +23 -0
- package/dist/plot/core/scales.js +39 -13
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
- package/dist/plot/core/utils/hierarchy-chart.js +179 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +99 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +304 -325
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +78 -69
- package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/scatter/BinnedScatterPlot.svelte +263 -109
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +477 -385
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
- package/dist/plot/sunburst/Sunburst.svelte +251 -329
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +10 -3
- package/dist/plot/treemap/Treemap.svelte +907 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
- package/dist/plot/treemap/index.d.ts +3 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/treemap.d.ts +26 -0
- package/dist/plot/treemap/treemap.js +99 -0
- package/dist/rdf/RdfPlot.svelte +22 -26
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +4 -8
- package/dist/sanitize.js +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +77 -50
- package/dist/spectral/Bands.svelte +223 -230
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -27
- package/dist/spectral/Dos.svelte +70 -73
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +25 -35
- package/dist/state.svelte.js +5 -18
- package/dist/structure/Arrow.svelte +5 -18
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +115 -75
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +11 -26
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +473 -419
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +157 -399
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +72 -66
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +467 -476
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +16 -12
- package/dist/structure/atom-label-placement.js +70 -37
- package/dist/structure/atom-properties.d.ts +2 -0
- package/dist/structure/atom-properties.js +104 -38
- package/dist/structure/bonding.d.ts +10 -3
- package/dist/structure/bonding.js +84 -28
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +1 -0
- package/dist/structure/export.js +39 -31
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +22 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +16 -1
- package/dist/structure/index.js +13 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +2 -1
- package/dist/structure/parse.js +243 -222
- package/dist/structure/partial-occupancy.js +4 -2
- package/dist/structure/pbc.js +78 -98
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +3 -18
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +7 -13
- package/dist/symmetry/SymmetryElements.svelte +11 -15
- package/dist/symmetry/SymmetryStats.svelte +56 -68
- package/dist/symmetry/WyckoffTable.svelte +5 -24
- package/dist/symmetry/cell-transform.js +1 -0
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +8 -2
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1102 -365
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +5 -12
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/index.d.ts +1 -5
- package/dist/theme/index.js +4 -10
- package/dist/theme/themes.mjs +14 -7
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +2 -5
- package/dist/trajectory/Trajectory.svelte +515 -308
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -31
- package/dist/trajectory/TrajectoryInfoPane.svelte +85 -97
- package/dist/trajectory/extract.js +56 -34
- package/dist/trajectory/format-detect.js +11 -9
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +33 -29
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +18 -7
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +2 -3
- package/dist/trajectory/parse/index.js +17 -20
- package/dist/trajectory/parse/lammps.js +8 -12
- package/dist/trajectory/parse/vasp.js +10 -7
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
- package/dist/trajectory/parse/vaspout-h5.js +284 -0
- package/dist/trajectory/parse/xyz.js +11 -7
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +99 -27
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +47 -61
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +2 -4
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +61 -33
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- 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.
|
|
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?: {
|
package/dist/plot/core/scales.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as math from '../../math';
|
|
2
|
-
import {
|
|
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
|
-
//
|
|
267
|
-
//
|
|
268
|
-
|
|
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
|
-
:
|
|
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
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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(
|
|
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 ??
|
|
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];
|