react-cheminfo 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -25
- package/lib/chart/core/axisLabels.d.ts +82 -0
- package/lib/chart/core/axisLabels.d.ts.map +1 -0
- package/lib/chart/core/axisLabels.js +111 -0
- package/lib/chart/core/axisLabels.js.map +1 -0
- package/lib/chart/core/boxLayout.d.ts +53 -0
- package/lib/chart/core/boxLayout.d.ts.map +1 -0
- package/lib/chart/core/boxLayout.js +112 -0
- package/lib/chart/core/boxLayout.js.map +1 -0
- package/lib/chart/core/chartAxisScale.d.ts +23 -2
- package/lib/chart/core/chartAxisScale.d.ts.map +1 -1
- package/lib/chart/core/chartAxisScale.js +64 -13
- package/lib/chart/core/chartAxisScale.js.map +1 -1
- package/lib/chart/core/chartDomain.d.ts +160 -0
- package/lib/chart/core/chartDomain.d.ts.map +1 -0
- package/lib/chart/core/chartDomain.js +46 -0
- package/lib/chart/core/chartDomain.js.map +1 -0
- package/lib/chart/core/chartGeometry.d.ts +131 -0
- package/lib/chart/core/chartGeometry.d.ts.map +1 -0
- package/lib/chart/core/chartGeometry.js +101 -0
- package/lib/chart/core/chartGeometry.js.map +1 -0
- package/lib/chart/core/chartPane.d.ts +11 -0
- package/lib/chart/core/chartPane.d.ts.map +1 -0
- package/lib/chart/core/chartPane.js +11 -0
- package/lib/chart/core/chartPane.js.map +1 -0
- package/lib/chart/core/chartScale.d.ts +4 -1
- package/lib/chart/core/chartScale.d.ts.map +1 -1
- package/lib/chart/core/chartScale.js +8 -4
- package/lib/chart/core/chartScale.js.map +1 -1
- package/lib/chart/core/chartTheme.d.ts +156 -0
- package/lib/chart/core/chartTheme.d.ts.map +1 -0
- package/lib/chart/core/chartTheme.js +156 -0
- package/lib/chart/core/chartTheme.js.map +1 -0
- package/lib/chart/core/chartViewport.d.ts +32 -5
- package/lib/chart/core/chartViewport.d.ts.map +1 -1
- package/lib/chart/core/chartViewport.js +40 -11
- package/lib/chart/core/chartViewport.js.map +1 -1
- package/lib/chart/core/guidePlacement.d.ts +52 -0
- package/lib/chart/core/guidePlacement.d.ts.map +1 -0
- package/lib/chart/core/guidePlacement.js +52 -0
- package/lib/chart/core/guidePlacement.js.map +1 -0
- package/lib/chart/core/index.d.ts +29 -2
- package/lib/chart/core/index.d.ts.map +1 -1
- package/lib/chart/core/index.js +19 -2
- package/lib/chart/core/index.js.map +1 -1
- package/lib/chart/core/labelStack.d.ts +27 -0
- package/lib/chart/core/labelStack.d.ts.map +1 -0
- package/lib/chart/core/labelStack.js +62 -0
- package/lib/chart/core/labelStack.js.map +1 -0
- package/lib/chart/core/legendBox.d.ts +152 -0
- package/lib/chart/core/legendBox.d.ts.map +1 -0
- package/lib/chart/core/legendBox.js +169 -0
- package/lib/chart/core/legendBox.js.map +1 -0
- package/lib/chart/core/selectionGeometry.d.ts +45 -0
- package/lib/chart/core/selectionGeometry.d.ts.map +1 -0
- package/lib/chart/core/selectionGeometry.js +49 -0
- package/lib/chart/core/selectionGeometry.js.map +1 -0
- package/lib/chart/core/spectrumColor.d.ts +80 -0
- package/lib/chart/core/spectrumColor.d.ts.map +1 -0
- package/lib/chart/core/spectrumColor.js +120 -0
- package/lib/chart/core/spectrumColor.js.map +1 -0
- package/lib/chart/core/stackCapacity.d.ts +136 -0
- package/lib/chart/core/stackCapacity.d.ts.map +1 -0
- package/lib/chart/core/stackCapacity.js +153 -0
- package/lib/chart/core/stackCapacity.js.map +1 -0
- package/lib/chart/core/svgPoint.d.ts +62 -0
- package/lib/chart/core/svgPoint.d.ts.map +1 -0
- package/lib/chart/core/svgPoint.js +43 -0
- package/lib/chart/core/svgPoint.js.map +1 -0
- package/lib/chart/core/tracePath.d.ts +94 -0
- package/lib/chart/core/tracePath.d.ts.map +1 -0
- package/lib/chart/core/tracePath.js +191 -0
- package/lib/chart/core/tracePath.js.map +1 -0
- package/lib/chart/core/trackerReadout.d.ts +55 -0
- package/lib/chart/core/trackerReadout.d.ts.map +1 -0
- package/lib/chart/core/trackerReadout.js +53 -0
- package/lib/chart/core/trackerReadout.js.map +1 -0
- package/lib/chart/core/viewTransform.d.ts +167 -0
- package/lib/chart/core/viewTransform.d.ts.map +1 -0
- package/lib/chart/core/viewTransform.js +188 -0
- package/lib/chart/core/viewTransform.js.map +1 -0
- package/lib/chart/core/zoomDomain.d.ts +127 -0
- package/lib/chart/core/zoomDomain.d.ts.map +1 -0
- package/lib/chart/core/zoomDomain.js +175 -0
- package/lib/chart/core/zoomDomain.js.map +1 -0
- package/lib/chart/ui/Axes.d.ts +104 -0
- package/lib/chart/ui/Axes.d.ts.map +1 -0
- package/lib/chart/ui/Axes.js +155 -0
- package/lib/chart/ui/Axes.js.map +1 -0
- package/lib/chart/ui/AxisGuide.d.ts +60 -0
- package/lib/chart/ui/AxisGuide.d.ts.map +1 -0
- package/lib/chart/ui/AxisGuide.js +111 -0
- package/lib/chart/ui/AxisGuide.js.map +1 -0
- package/lib/chart/ui/ChartStack.d.ts +81 -0
- package/lib/chart/ui/ChartStack.d.ts.map +1 -0
- package/lib/chart/ui/ChartStack.js +42 -0
- package/lib/chart/ui/ChartStack.js.map +1 -0
- package/lib/chart/ui/ChartTracker.d.ts +36 -0
- package/lib/chart/ui/ChartTracker.d.ts.map +1 -0
- package/lib/chart/ui/ChartTracker.js +27 -0
- package/lib/chart/ui/ChartTracker.js.map +1 -0
- package/lib/chart/ui/PlotCaption.d.ts +44 -0
- package/lib/chart/ui/PlotCaption.d.ts.map +1 -0
- package/lib/chart/ui/PlotCaption.js +68 -0
- package/lib/chart/ui/PlotCaption.js.map +1 -0
- package/lib/chart/ui/SelectionRect.d.ts +27 -0
- package/lib/chart/ui/SelectionRect.d.ts.map +1 -0
- package/lib/chart/ui/SelectionRect.js +31 -0
- package/lib/chart/ui/SelectionRect.js.map +1 -0
- package/lib/chart/ui/TraceLegend.d.ts +99 -0
- package/lib/chart/ui/TraceLegend.d.ts.map +1 -0
- package/lib/chart/ui/TraceLegend.js +45 -0
- package/lib/chart/ui/TraceLegend.js.map +1 -0
- package/lib/chart/ui/chartGestures.d.ts +158 -0
- package/lib/chart/ui/chartGestures.d.ts.map +1 -0
- package/lib/chart/ui/chartGestures.js +145 -0
- package/lib/chart/ui/chartGestures.js.map +1 -0
- package/lib/chart/ui/chartStackLevel.d.ts +115 -0
- package/lib/chart/ui/chartStackLevel.d.ts.map +1 -0
- package/lib/chart/ui/chartStackLevel.js +96 -0
- package/lib/chart/ui/chartStackLevel.js.map +1 -0
- package/lib/chart/ui/chartSurface.d.ts +35 -0
- package/lib/chart/ui/chartSurface.d.ts.map +1 -0
- package/lib/chart/ui/chartSurface.js +58 -0
- package/lib/chart/ui/chartSurface.js.map +1 -0
- package/lib/chart/ui/index.d.ts +24 -0
- package/lib/chart/ui/index.d.ts.map +1 -1
- package/lib/chart/ui/index.js +13 -0
- package/lib/chart/ui/index.js.map +1 -1
- package/lib/chart/ui/useChartPointer.d.ts +124 -0
- package/lib/chart/ui/useChartPointer.d.ts.map +1 -0
- package/lib/chart/ui/useChartPointer.js +152 -0
- package/lib/chart/ui/useChartPointer.js.map +1 -0
- package/lib/chart/ui/useChartSize.d.ts +49 -0
- package/lib/chart/ui/useChartSize.d.ts.map +1 -0
- package/lib/chart/ui/useChartSize.js +91 -0
- package/lib/chart/ui/useChartSize.js.map +1 -0
- package/lib/chart/ui/useChartWindow.d.ts +147 -0
- package/lib/chart/ui/useChartWindow.d.ts.map +1 -0
- package/lib/chart/ui/useChartWindow.js +135 -0
- package/lib/chart/ui/useChartWindow.js.map +1 -0
- package/lib/chart/ui/useChartZoom.d.ts +88 -0
- package/lib/chart/ui/useChartZoom.d.ts.map +1 -0
- package/lib/chart/ui/useChartZoom.js +142 -0
- package/lib/chart/ui/useChartZoom.js.map +1 -0
- package/lib/chart/ui/useWheelListener.d.ts +30 -0
- package/lib/chart/ui/useWheelListener.d.ts.map +1 -0
- package/lib/chart/ui/useWheelListener.js +57 -0
- package/lib/chart/ui/useWheelListener.js.map +1 -0
- package/lib/clipboard/core/copyPng.d.ts +13 -0
- package/lib/clipboard/core/copyPng.d.ts.map +1 -0
- package/lib/clipboard/core/copyPng.js +19 -0
- package/lib/clipboard/core/copyPng.js.map +1 -0
- package/lib/clipboard/core/index.d.ts +1 -0
- package/lib/clipboard/core/index.d.ts.map +1 -1
- package/lib/clipboard/core/index.js +1 -0
- package/lib/clipboard/core/index.js.map +1 -1
- package/lib/clipboard/ui/CopyableValue.d.ts +12 -9
- package/lib/clipboard/ui/CopyableValue.d.ts.map +1 -1
- package/lib/clipboard/ui/CopyableValue.js +11 -15
- package/lib/clipboard/ui/CopyableValue.js.map +1 -1
- package/lib/core.d.ts +1 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +1 -0
- package/lib/core.js.map +1 -1
- package/lib/download/core/exportStyles.d.ts +22 -0
- package/lib/download/core/exportStyles.d.ts.map +1 -0
- package/lib/download/core/exportStyles.js +19 -0
- package/lib/download/core/exportStyles.js.map +1 -0
- package/lib/download/core/imageResolution.d.ts +88 -0
- package/lib/download/core/imageResolution.d.ts.map +1 -0
- package/lib/download/core/imageResolution.js +77 -0
- package/lib/download/core/imageResolution.js.map +1 -0
- package/lib/download/core/index.d.ts +13 -0
- package/lib/download/core/index.d.ts.map +1 -1
- package/lib/download/core/index.js +8 -0
- package/lib/download/core/index.js.map +1 -1
- package/lib/download/core/pictureExport.d.ts +93 -0
- package/lib/download/core/pictureExport.d.ts.map +1 -0
- package/lib/download/core/pictureExport.js +116 -0
- package/lib/download/core/pictureExport.js.map +1 -0
- package/lib/download/core/stackedDrawing.d.ts +36 -0
- package/lib/download/core/stackedDrawing.d.ts.map +1 -0
- package/lib/download/core/stackedDrawing.js +98 -0
- package/lib/download/core/stackedDrawing.js.map +1 -0
- package/lib/download/core/svgBounds.d.ts +44 -0
- package/lib/download/core/svgBounds.d.ts.map +1 -0
- package/lib/download/core/svgBounds.js +69 -0
- package/lib/download/core/svgBounds.js.map +1 -0
- package/lib/download/core/svgNamespace.d.ts +9 -0
- package/lib/download/core/svgNamespace.d.ts.map +1 -0
- package/lib/download/core/svgNamespace.js +10 -0
- package/lib/download/core/svgNamespace.js.map +1 -0
- package/lib/download/core/svgToPng.d.ts +43 -0
- package/lib/download/core/svgToPng.d.ts.map +1 -0
- package/lib/download/core/svgToPng.js +79 -0
- package/lib/download/core/svgToPng.js.map +1 -0
- package/lib/download/core/svgToString.d.ts +45 -0
- package/lib/download/core/svgToString.d.ts.map +1 -0
- package/lib/download/core/svgToString.js +58 -0
- package/lib/download/core/svgToString.js.map +1 -0
- package/lib/download/ui/ExportDialogFrame.d.ts +46 -0
- package/lib/download/ui/ExportDialogFrame.d.ts.map +1 -0
- package/lib/download/ui/ExportDialogFrame.js +24 -0
- package/lib/download/ui/ExportDialogFrame.js.map +1 -0
- package/lib/download/ui/ExportImageDialog.d.ts +47 -0
- package/lib/download/ui/ExportImageDialog.d.ts.map +1 -0
- package/lib/download/ui/ExportImageDialog.js +25 -0
- package/lib/download/ui/ExportImageDialog.js.map +1 -0
- package/lib/download/ui/ExportNameField.d.ts +29 -0
- package/lib/download/ui/ExportNameField.d.ts.map +1 -0
- package/lib/download/ui/ExportNameField.js +99 -0
- package/lib/download/ui/ExportNameField.js.map +1 -0
- package/lib/download/ui/ExportPictureSection.d.ts +38 -0
- package/lib/download/ui/ExportPictureSection.d.ts.map +1 -0
- package/lib/download/ui/ExportPictureSection.js +48 -0
- package/lib/download/ui/ExportPictureSection.js.map +1 -0
- package/lib/download/ui/index.d.ts +10 -0
- package/lib/download/ui/index.d.ts.map +1 -1
- package/lib/download/ui/index.js +5 -0
- package/lib/download/ui/index.js.map +1 -1
- package/lib/download/ui/useDrawingBox.d.ts +23 -0
- package/lib/download/ui/useDrawingBox.d.ts.map +1 -0
- package/lib/download/ui/useDrawingBox.js +21 -0
- package/lib/download/ui/useDrawingBox.js.map +1 -0
- package/lib/error/core/describeSource.d.ts +17 -0
- package/lib/error/core/describeSource.d.ts.map +1 -0
- package/lib/error/core/describeSource.js +19 -0
- package/lib/error/core/describeSource.js.map +1 -0
- package/lib/error/core/index.d.ts +1 -0
- package/lib/error/core/index.d.ts.map +1 -1
- package/lib/error/core/index.js +1 -0
- package/lib/error/core/index.js.map +1 -1
- package/lib/help/ui/HelpBody.d.ts +10 -1
- package/lib/help/ui/HelpBody.d.ts.map +1 -1
- package/lib/help/ui/HelpBody.js +24 -1
- package/lib/help/ui/HelpBody.js.map +1 -1
- package/lib/help/ui/index.d.ts +1 -1
- package/lib/help/ui/index.d.ts.map +1 -1
- package/lib/help/ui/index.js.map +1 -1
- package/lib/ir/core/analysisSpectra.d.ts +46 -0
- package/lib/ir/core/analysisSpectra.d.ts.map +1 -0
- package/lib/ir/core/analysisSpectra.js +187 -0
- package/lib/ir/core/analysisSpectra.js.map +1 -0
- package/lib/ir/core/assignBands.d.ts +83 -0
- package/lib/ir/core/assignBands.d.ts.map +1 -0
- package/lib/ir/core/assignBands.js +83 -0
- package/lib/ir/core/assignBands.js.map +1 -0
- package/lib/ir/core/bandAssignments.d.ts +47 -0
- package/lib/ir/core/bandAssignments.d.ts.map +1 -0
- package/lib/ir/core/bandAssignments.js +305 -0
- package/lib/ir/core/bandAssignments.js.map +1 -0
- package/lib/ir/core/bandLabelPlan.d.ts +93 -0
- package/lib/ir/core/bandLabelPlan.d.ts.map +1 -0
- package/lib/ir/core/bandLabelPlan.js +104 -0
- package/lib/ir/core/bandLabelPlan.js.map +1 -0
- package/lib/ir/core/detectIrFormat.d.ts +23 -0
- package/lib/ir/core/detectIrFormat.d.ts.map +1 -0
- package/lib/ir/core/detectIrFormat.js +133 -0
- package/lib/ir/core/detectIrFormat.js.map +1 -0
- package/lib/ir/core/downloadSpectra.d.ts +26 -0
- package/lib/ir/core/downloadSpectra.d.ts.map +1 -0
- package/lib/ir/core/downloadSpectra.js +37 -0
- package/lib/ir/core/downloadSpectra.js.map +1 -0
- package/lib/ir/core/fromJcamp.d.ts +35 -0
- package/lib/ir/core/fromJcamp.d.ts.map +1 -0
- package/lib/ir/core/fromJcamp.js +48 -0
- package/lib/ir/core/fromJcamp.js.map +1 -0
- package/lib/ir/core/fromSpc.d.ts +30 -0
- package/lib/ir/core/fromSpc.d.ts.map +1 -0
- package/lib/ir/core/fromSpc.js +40 -0
- package/lib/ir/core/fromSpc.js.map +1 -0
- package/lib/ir/core/index.d.ts +51 -0
- package/lib/ir/core/index.d.ts.map +1 -0
- package/lib/ir/core/index.js +35 -0
- package/lib/ir/core/index.js.map +1 -0
- package/lib/ir/core/irBand.d.ts +45 -0
- package/lib/ir/core/irBand.d.ts.map +1 -0
- package/lib/ir/core/irBand.js +30 -0
- package/lib/ir/core/irBand.js.map +1 -0
- package/lib/ir/core/irCommands.d.ts +168 -0
- package/lib/ir/core/irCommands.d.ts.map +1 -0
- package/lib/ir/core/irCommands.js +94 -0
- package/lib/ir/core/irCommands.js.map +1 -0
- package/lib/ir/core/irDomain.d.ts +63 -0
- package/lib/ir/core/irDomain.d.ts.map +1 -0
- package/lib/ir/core/irDomain.js +136 -0
- package/lib/ir/core/irDomain.js.map +1 -0
- package/lib/ir/core/irEditorApi.d.ts +42 -0
- package/lib/ir/core/irEditorApi.d.ts.map +1 -0
- package/lib/ir/core/irEditorApi.js +10 -0
- package/lib/ir/core/irEditorApi.js.map +1 -0
- package/lib/ir/core/irFormat.d.ts +42 -0
- package/lib/ir/core/irFormat.d.ts.map +1 -0
- package/lib/ir/core/irFormat.js +51 -0
- package/lib/ir/core/irFormat.js.map +1 -0
- package/lib/ir/core/irMode.d.ts +160 -0
- package/lib/ir/core/irMode.d.ts.map +1 -0
- package/lib/ir/core/irMode.js +175 -0
- package/lib/ir/core/irMode.js.map +1 -0
- package/lib/ir/core/irReducer.d.ts +101 -0
- package/lib/ir/core/irReducer.d.ts.map +1 -0
- package/lib/ir/core/irReducer.js +207 -0
- package/lib/ir/core/irReducer.js.map +1 -0
- package/lib/ir/core/irSidePanels.d.ts +22 -0
- package/lib/ir/core/irSidePanels.d.ts.map +1 -0
- package/lib/ir/core/irSidePanels.js +12 -0
- package/lib/ir/core/irSidePanels.js.map +1 -0
- package/lib/ir/core/irSpectrum.d.ts +140 -0
- package/lib/ir/core/irSpectrum.d.ts.map +1 -0
- package/lib/ir/core/irSpectrum.js +34 -0
- package/lib/ir/core/irSpectrum.js.map +1 -0
- package/lib/ir/core/irState.d.ts +119 -0
- package/lib/ir/core/irState.d.ts.map +1 -0
- package/lib/ir/core/irState.js +92 -0
- package/lib/ir/core/irState.js.map +1 -0
- package/lib/ir/core/loadIrSpectra.d.ts +36 -0
- package/lib/ir/core/loadIrSpectra.d.ts.map +1 -0
- package/lib/ir/core/loadIrSpectra.js +44 -0
- package/lib/ir/core/loadIrSpectra.js.map +1 -0
- package/lib/ir/core/nearestBand.d.ts +35 -0
- package/lib/ir/core/nearestBand.d.ts.map +1 -0
- package/lib/ir/core/nearestBand.js +47 -0
- package/lib/ir/core/nearestBand.js.map +1 -0
- package/lib/ir/core/pickBands.d.ts +70 -0
- package/lib/ir/core/pickBands.d.ts.map +1 -0
- package/lib/ir/core/pickBands.js +125 -0
- package/lib/ir/core/pickBands.js.map +1 -0
- package/lib/ir/core/spectrumJcamp.d.ts +58 -0
- package/lib/ir/core/spectrumJcamp.d.ts.map +1 -0
- package/lib/ir/core/spectrumJcamp.js +156 -0
- package/lib/ir/core/spectrumJcamp.js.map +1 -0
- package/lib/ir/core/toIrSpectrum.d.ts +59 -0
- package/lib/ir/core/toIrSpectrum.d.ts.map +1 -0
- package/lib/ir/core/toIrSpectrum.js +56 -0
- package/lib/ir/core/toIrSpectrum.js.map +1 -0
- package/lib/ir/ui/BandMarks.d.ts +52 -0
- package/lib/ir/ui/BandMarks.d.ts.map +1 -0
- package/lib/ir/ui/BandMarks.js +71 -0
- package/lib/ir/ui/BandMarks.js.map +1 -0
- package/lib/ir/ui/BandsPanel.d.ts +31 -0
- package/lib/ir/ui/BandsPanel.d.ts.map +1 -0
- package/lib/ir/ui/BandsPanel.js +94 -0
- package/lib/ir/ui/BandsPanel.js.map +1 -0
- package/lib/ir/ui/IrAboutDialog.d.ts +18 -0
- package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -0
- package/lib/ir/ui/IrAboutDialog.js +32 -0
- package/lib/ir/ui/IrAboutDialog.js.map +1 -0
- package/lib/ir/ui/IrCanvas.d.ts +38 -0
- package/lib/ir/ui/IrCanvas.d.ts.map +1 -0
- package/lib/ir/ui/IrCanvas.js +41 -0
- package/lib/ir/ui/IrCanvas.js.map +1 -0
- package/lib/ir/ui/IrChart.d.ts +28 -0
- package/lib/ir/ui/IrChart.d.ts.map +1 -0
- package/lib/ir/ui/IrChart.js +114 -0
- package/lib/ir/ui/IrChart.js.map +1 -0
- package/lib/ir/ui/IrCommandProvider.d.ts +15 -0
- package/lib/ir/ui/IrCommandProvider.d.ts.map +1 -0
- package/lib/ir/ui/IrCommandProvider.js +14 -0
- package/lib/ir/ui/IrCommandProvider.js.map +1 -0
- package/lib/ir/ui/IrCommandTooltip.d.ts +16 -0
- package/lib/ir/ui/IrCommandTooltip.d.ts.map +1 -0
- package/lib/ir/ui/IrCommandTooltip.js +22 -0
- package/lib/ir/ui/IrCommandTooltip.js.map +1 -0
- package/lib/ir/ui/IrDocumentationDialog.d.ts +18 -0
- package/lib/ir/ui/IrDocumentationDialog.d.ts.map +1 -0
- package/lib/ir/ui/IrDocumentationDialog.js +68 -0
- package/lib/ir/ui/IrDocumentationDialog.js.map +1 -0
- package/lib/ir/ui/IrEditor.d.ts +60 -0
- package/lib/ir/ui/IrEditor.d.ts.map +1 -0
- package/lib/ir/ui/IrEditor.js +42 -0
- package/lib/ir/ui/IrEditor.js.map +1 -0
- package/lib/ir/ui/IrHeader.d.ts +13 -0
- package/lib/ir/ui/IrHeader.d.ts.map +1 -0
- package/lib/ir/ui/IrHeader.js +21 -0
- package/lib/ir/ui/IrHeader.js.map +1 -0
- package/lib/ir/ui/IrLogo.d.ts +20 -0
- package/lib/ir/ui/IrLogo.d.ts.map +1 -0
- package/lib/ir/ui/IrLogo.js +17 -0
- package/lib/ir/ui/IrLogo.js.map +1 -0
- package/lib/ir/ui/IrPointerTracker.d.ts +29 -0
- package/lib/ir/ui/IrPointerTracker.d.ts.map +1 -0
- package/lib/ir/ui/IrPointerTracker.js +47 -0
- package/lib/ir/ui/IrPointerTracker.js.map +1 -0
- package/lib/ir/ui/IrShell.d.ts +25 -0
- package/lib/ir/ui/IrShell.d.ts.map +1 -0
- package/lib/ir/ui/IrShell.js +178 -0
- package/lib/ir/ui/IrShell.js.map +1 -0
- package/lib/ir/ui/IrSidePanel.d.ts +26 -0
- package/lib/ir/ui/IrSidePanel.d.ts.map +1 -0
- package/lib/ir/ui/IrSidePanel.js +39 -0
- package/lib/ir/ui/IrSidePanel.js.map +1 -0
- package/lib/ir/ui/IrStateProvider.d.ts +19 -0
- package/lib/ir/ui/IrStateProvider.d.ts.map +1 -0
- package/lib/ir/ui/IrStateProvider.js +16 -0
- package/lib/ir/ui/IrStateProvider.js.map +1 -0
- package/lib/ir/ui/IrStatusBar.d.ts +14 -0
- package/lib/ir/ui/IrStatusBar.d.ts.map +1 -0
- package/lib/ir/ui/IrStatusBar.js +48 -0
- package/lib/ir/ui/IrStatusBar.js.map +1 -0
- package/lib/ir/ui/IrToolbar.d.ts +18 -0
- package/lib/ir/ui/IrToolbar.d.ts.map +1 -0
- package/lib/ir/ui/IrToolbar.js +32 -0
- package/lib/ir/ui/IrToolbar.js.map +1 -0
- package/lib/ir/ui/IrTraces.d.ts +63 -0
- package/lib/ir/ui/IrTraces.d.ts.map +1 -0
- package/lib/ir/ui/IrTraces.js +72 -0
- package/lib/ir/ui/IrTraces.js.map +1 -0
- package/lib/ir/ui/MetadataPanel.d.ts +15 -0
- package/lib/ir/ui/MetadataPanel.d.ts.map +1 -0
- package/lib/ir/ui/MetadataPanel.js +49 -0
- package/lib/ir/ui/MetadataPanel.js.map +1 -0
- package/lib/ir/ui/SpectraPanel.d.ts +20 -0
- package/lib/ir/ui/SpectraPanel.d.ts.map +1 -0
- package/lib/ir/ui/SpectraPanel.js +42 -0
- package/lib/ir/ui/SpectraPanel.js.map +1 -0
- package/lib/ir/ui/SpectrumRow.d.ts +26 -0
- package/lib/ir/ui/SpectrumRow.d.ts.map +1 -0
- package/lib/ir/ui/SpectrumRow.js +41 -0
- package/lib/ir/ui/SpectrumRow.js.map +1 -0
- package/lib/ir/ui/index.d.ts +56 -0
- package/lib/ir/ui/index.d.ts.map +1 -0
- package/lib/ir/ui/index.js +36 -0
- package/lib/ir/ui/index.js.map +1 -0
- package/lib/ir/ui/irActions.d.ts +52 -0
- package/lib/ir/ui/irActions.d.ts.map +1 -0
- package/lib/ir/ui/irActions.js +62 -0
- package/lib/ir/ui/irActions.js.map +1 -0
- package/lib/ir/ui/irChartProps.d.ts +116 -0
- package/lib/ir/ui/irChartProps.d.ts.map +1 -0
- package/lib/ir/ui/irChartProps.js +14 -0
- package/lib/ir/ui/irChartProps.js.map +1 -0
- package/lib/ir/ui/irCommandContext.d.ts +35 -0
- package/lib/ir/ui/irCommandContext.d.ts.map +1 -0
- package/lib/ir/ui/irCommandContext.js +44 -0
- package/lib/ir/ui/irCommandContext.js.map +1 -0
- package/lib/ir/ui/irStateContext.d.ts +26 -0
- package/lib/ir/ui/irStateContext.d.ts.map +1 -0
- package/lib/ir/ui/irStateContext.js +37 -0
- package/lib/ir/ui/irStateContext.js.map +1 -0
- package/lib/ir/ui/useIrEditor.d.ts +51 -0
- package/lib/ir/ui/useIrEditor.d.ts.map +1 -0
- package/lib/ir/ui/useIrEditor.js +88 -0
- package/lib/ir/ui/useIrEditor.js.map +1 -0
- package/lib/ir/ui/useIrPointer.d.ts +66 -0
- package/lib/ir/ui/useIrPointer.d.ts.map +1 -0
- package/lib/ir/ui/useIrPointer.js +53 -0
- package/lib/ir/ui/useIrPointer.js.map +1 -0
- package/lib/ir/ui/useIrShortcuts.d.ts +24 -0
- package/lib/ir/ui/useIrShortcuts.d.ts.map +1 -0
- package/lib/ir/ui/useIrShortcuts.js +73 -0
- package/lib/ir/ui/useIrShortcuts.js.map +1 -0
- package/lib/ir/ui/useIrZoom.d.ts +51 -0
- package/lib/ir/ui/useIrZoom.d.ts.map +1 -0
- package/lib/ir/ui/useIrZoom.js +46 -0
- package/lib/ir/ui/useIrZoom.js.map +1 -0
- package/lib/ir.d.ts +13 -0
- package/lib/ir.d.ts.map +1 -0
- package/lib/ir.js +13 -0
- package/lib/ir.js.map +1 -0
- package/lib/panel/core/dialogStyles.d.ts +13 -0
- package/lib/panel/core/dialogStyles.d.ts.map +1 -0
- package/lib/panel/core/dialogStyles.js +11 -0
- package/lib/panel/core/dialogStyles.js.map +1 -0
- package/lib/panel/core/index.d.ts +19 -0
- package/lib/panel/core/index.d.ts.map +1 -0
- package/lib/panel/core/index.js +18 -0
- package/lib/panel/core/index.js.map +1 -0
- package/lib/panel/core/isEditingField.d.ts +17 -0
- package/lib/panel/core/isEditingField.d.ts.map +1 -0
- package/lib/panel/core/isEditingField.js +25 -0
- package/lib/panel/core/isEditingField.js.map +1 -0
- package/lib/panel/core/panelStyles.d.ts +242 -0
- package/lib/panel/core/panelStyles.d.ts.map +1 -0
- package/lib/panel/core/panelStyles.js +228 -0
- package/lib/panel/core/panelStyles.js.map +1 -0
- package/lib/panel/core/rowSpacers.d.ts +38 -0
- package/lib/panel/core/rowSpacers.d.ts.map +1 -0
- package/lib/panel/core/rowSpacers.js +31 -0
- package/lib/panel/core/rowSpacers.js.map +1 -0
- package/lib/panel/core/statusBar.d.ts +44 -0
- package/lib/panel/core/statusBar.d.ts.map +1 -0
- package/lib/panel/core/statusBar.js +40 -0
- package/lib/panel/core/statusBar.js.map +1 -0
- package/lib/panel/core/textFilter.d.ts +22 -0
- package/lib/panel/core/textFilter.d.ts.map +1 -0
- package/lib/panel/core/textFilter.js +32 -0
- package/lib/panel/core/textFilter.js.map +1 -0
- package/lib/panel/core/yieldToPainting.d.ts +17 -0
- package/lib/panel/core/yieldToPainting.d.ts.map +1 -0
- package/lib/panel/core/yieldToPainting.js +21 -0
- package/lib/panel/core/yieldToPainting.js.map +1 -0
- package/lib/panel/ui/AboutDialogFrame.d.ts +36 -0
- package/lib/panel/ui/AboutDialogFrame.d.ts.map +1 -0
- package/lib/panel/ui/AboutDialogFrame.js +43 -0
- package/lib/panel/ui/AboutDialogFrame.js.map +1 -0
- package/lib/panel/ui/ClearButton.d.ts +28 -0
- package/lib/panel/ui/ClearButton.d.ts.map +1 -0
- package/lib/panel/ui/ClearButton.js +23 -0
- package/lib/panel/ui/ClearButton.js.map +1 -0
- package/lib/panel/ui/DocumentationDialogFrame.d.ts +39 -0
- package/lib/panel/ui/DocumentationDialogFrame.d.ts.map +1 -0
- package/lib/panel/ui/DocumentationDialogFrame.js +29 -0
- package/lib/panel/ui/DocumentationDialogFrame.js.map +1 -0
- package/lib/panel/ui/FilterInput.d.ts +31 -0
- package/lib/panel/ui/FilterInput.d.ts.map +1 -0
- package/lib/panel/ui/FilterInput.js +23 -0
- package/lib/panel/ui/FilterInput.js.map +1 -0
- package/lib/panel/ui/HelpLabel.d.ts +24 -0
- package/lib/panel/ui/HelpLabel.d.ts.map +1 -0
- package/lib/panel/ui/HelpLabel.js +23 -0
- package/lib/panel/ui/HelpLabel.js.map +1 -0
- package/lib/panel/ui/PanelMessage.d.ts +41 -0
- package/lib/panel/ui/PanelMessage.d.ts.map +1 -0
- package/lib/panel/ui/PanelMessage.js +30 -0
- package/lib/panel/ui/PanelMessage.js.map +1 -0
- package/lib/panel/ui/PanelRail.d.ts +41 -0
- package/lib/panel/ui/PanelRail.d.ts.map +1 -0
- package/lib/panel/ui/PanelRail.js +12 -0
- package/lib/panel/ui/PanelRail.js.map +1 -0
- package/lib/panel/ui/Section.d.ts +25 -0
- package/lib/panel/ui/Section.d.ts.map +1 -0
- package/lib/panel/ui/Section.js +41 -0
- package/lib/panel/ui/Section.js.map +1 -0
- package/lib/panel/ui/SidePanelStack.d.ts +62 -0
- package/lib/panel/ui/SidePanelStack.d.ts.map +1 -0
- package/lib/panel/ui/SidePanelStack.js +40 -0
- package/lib/panel/ui/SidePanelStack.js.map +1 -0
- package/lib/panel/ui/SpectrumColorSwatch.d.ts +33 -0
- package/lib/panel/ui/SpectrumColorSwatch.d.ts.map +1 -0
- package/lib/panel/ui/SpectrumColorSwatch.js +76 -0
- package/lib/panel/ui/SpectrumColorSwatch.js.map +1 -0
- package/lib/panel/ui/index.d.ts +37 -0
- package/lib/panel/ui/index.d.ts.map +1 -0
- package/lib/panel/ui/index.js +24 -0
- package/lib/panel/ui/index.js.map +1 -0
- package/lib/panel/ui/useConfirmOnEnter.d.ts +19 -0
- package/lib/panel/ui/useConfirmOnEnter.d.ts.map +1 -0
- package/lib/panel/ui/useConfirmOnEnter.js +64 -0
- package/lib/panel/ui/useConfirmOnEnter.js.map +1 -0
- package/lib/panel/ui/useFilterBox.d.ts +23 -0
- package/lib/panel/ui/useFilterBox.d.ts.map +1 -0
- package/lib/panel/ui/useFilterBox.js +22 -0
- package/lib/panel/ui/useFilterBox.js.map +1 -0
- package/lib/panel/ui/useVirtualRows.d.ts +46 -0
- package/lib/panel/ui/useVirtualRows.d.ts.map +1 -0
- package/lib/panel/ui/useVirtualRows.js +56 -0
- package/lib/panel/ui/useVirtualRows.js.map +1 -0
- package/lib/panel/ui/useVirtualWindowRows.d.ts +40 -0
- package/lib/panel/ui/useVirtualWindowRows.d.ts.map +1 -0
- package/lib/panel/ui/useVirtualWindowRows.js +65 -0
- package/lib/panel/ui/useVirtualWindowRows.js.map +1 -0
- package/lib/ui.d.ts +1 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +1 -0
- package/lib/ui.js.map +1 -1
- package/package.json +8 -1
- package/src/chart/core/axisLabels.ts +117 -0
- package/src/chart/core/boxLayout.ts +126 -0
- package/src/chart/core/chartAxisScale.ts +92 -10
- package/src/chart/core/chartDomain.ts +185 -0
- package/src/chart/core/chartGeometry.ts +159 -0
- package/src/chart/core/chartPane.ts +10 -0
- package/src/chart/core/chartScale.ts +7 -4
- package/src/chart/core/chartTheme.ts +161 -0
- package/src/chart/core/chartViewport.ts +40 -13
- package/src/chart/core/guidePlacement.ts +66 -0
- package/src/chart/core/index.ts +121 -2
- package/src/chart/core/labelStack.ts +72 -0
- package/src/chart/core/legendBox.ts +263 -0
- package/src/chart/core/selectionGeometry.ts +68 -0
- package/src/chart/core/spectrumColor.ts +129 -0
- package/src/chart/core/stackCapacity.ts +162 -0
- package/src/chart/core/svgPoint.ts +77 -0
- package/src/chart/core/tracePath.ts +228 -0
- package/src/chart/core/trackerReadout.ts +78 -0
- package/src/chart/core/viewTransform.ts +287 -0
- package/src/chart/core/zoomDomain.ts +235 -0
- package/src/chart/ui/Axes.tsx +361 -0
- package/src/chart/ui/AxisGuide.tsx +187 -0
- package/src/chart/ui/ChartStack.tsx +130 -0
- package/src/chart/ui/ChartTracker.tsx +101 -0
- package/src/chart/ui/PlotCaption.tsx +108 -0
- package/src/chart/ui/SelectionRect.tsx +52 -0
- package/src/chart/ui/TraceLegend.tsx +193 -0
- package/src/chart/ui/chartGestures.ts +270 -0
- package/src/chart/ui/chartStackLevel.tsx +210 -0
- package/src/chart/ui/chartSurface.ts +66 -0
- package/src/chart/ui/index.ts +35 -0
- package/src/chart/ui/useChartPointer.ts +223 -0
- package/src/chart/ui/useChartSize.ts +115 -0
- package/src/chart/ui/useChartWindow.ts +240 -0
- package/src/chart/ui/useChartZoom.ts +255 -0
- package/src/chart/ui/useWheelListener.ts +62 -0
- package/src/clipboard/core/copyPng.ts +20 -0
- package/src/clipboard/core/index.ts +1 -0
- package/src/clipboard/ui/CopyableValue.tsx +22 -35
- package/src/core.ts +1 -0
- package/src/download/core/exportStyles.ts +20 -0
- package/src/download/core/imageResolution.ts +118 -0
- package/src/download/core/index.ts +34 -0
- package/src/download/core/pictureExport.ts +207 -0
- package/src/download/core/stackedDrawing.ts +108 -0
- package/src/download/core/svgBounds.ts +80 -0
- package/src/download/core/svgNamespace.ts +9 -0
- package/src/download/core/svgToPng.ts +121 -0
- package/src/download/core/svgToString.ts +95 -0
- package/src/download/ui/ExportDialogFrame.tsx +86 -0
- package/src/download/ui/ExportImageDialog.tsx +91 -0
- package/src/download/ui/ExportNameField.tsx +148 -0
- package/src/download/ui/ExportPictureSection.tsx +142 -0
- package/src/download/ui/index.ts +11 -0
- package/src/download/ui/useDrawingBox.ts +37 -0
- package/src/error/core/describeSource.ts +18 -0
- package/src/error/core/index.ts +1 -0
- package/src/help/ui/HelpBody.tsx +41 -2
- package/src/help/ui/index.ts +6 -1
- package/src/ir/core/analysisSpectra.ts +231 -0
- package/src/ir/core/assignBands.ts +144 -0
- package/src/ir/core/bandAssignments.ts +329 -0
- package/src/ir/core/bandLabelPlan.ts +194 -0
- package/src/ir/core/detectIrFormat.ts +139 -0
- package/src/ir/core/downloadSpectra.ts +57 -0
- package/src/ir/core/fromJcamp.ts +70 -0
- package/src/ir/core/fromSpc.ts +61 -0
- package/src/ir/core/index.ts +113 -0
- package/src/ir/core/irBand.ts +57 -0
- package/src/ir/core/irCommands.ts +154 -0
- package/src/ir/core/irDomain.ts +163 -0
- package/src/ir/core/irEditorApi.ts +44 -0
- package/src/ir/core/irFormat.ts +57 -0
- package/src/ir/core/irMode.ts +203 -0
- package/src/ir/core/irReducer.ts +273 -0
- package/src/ir/core/irSidePanels.ts +20 -0
- package/src/ir/core/irSpectrum.ts +155 -0
- package/src/ir/core/irState.ts +173 -0
- package/src/ir/core/loadIrSpectra.ts +79 -0
- package/src/ir/core/nearestBand.ts +57 -0
- package/src/ir/core/pickBands.ts +181 -0
- package/src/ir/core/spectrumJcamp.ts +178 -0
- package/src/ir/core/toIrSpectrum.ts +102 -0
- package/src/ir/ui/BandMarks.tsx +166 -0
- package/src/ir/ui/BandsPanel.tsx +271 -0
- package/src/ir/ui/IrAboutDialog.tsx +121 -0
- package/src/ir/ui/IrCanvas.tsx +91 -0
- package/src/ir/ui/IrChart.tsx +215 -0
- package/src/ir/ui/IrCommandProvider.tsx +32 -0
- package/src/ir/ui/IrCommandTooltip.tsx +36 -0
- package/src/ir/ui/IrDocumentationDialog.tsx +174 -0
- package/src/ir/ui/IrEditor.tsx +99 -0
- package/src/ir/ui/IrHeader.tsx +39 -0
- package/src/ir/ui/IrLogo.tsx +49 -0
- package/src/ir/ui/IrPointerTracker.tsx +102 -0
- package/src/ir/ui/IrShell.tsx +285 -0
- package/src/ir/ui/IrSidePanel.tsx +78 -0
- package/src/ir/ui/IrStateProvider.tsx +32 -0
- package/src/ir/ui/IrStatusBar.tsx +97 -0
- package/src/ir/ui/IrToolbar.tsx +102 -0
- package/src/ir/ui/IrTraces.tsx +134 -0
- package/src/ir/ui/MetadataPanel.tsx +88 -0
- package/src/ir/ui/SpectraPanel.tsx +114 -0
- package/src/ir/ui/SpectrumRow.tsx +127 -0
- package/src/ir/ui/index.ts +56 -0
- package/src/ir/ui/irActions.ts +103 -0
- package/src/ir/ui/irChartProps.ts +118 -0
- package/src/ir/ui/irCommandContext.tsx +62 -0
- package/src/ir/ui/irStateContext.ts +48 -0
- package/src/ir/ui/useIrEditor.ts +139 -0
- package/src/ir/ui/useIrPointer.ts +109 -0
- package/src/ir/ui/useIrShortcuts.ts +95 -0
- package/src/ir/ui/useIrZoom.ts +86 -0
- package/src/ir.ts +13 -0
- package/src/panel/core/dialogStyles.ts +11 -0
- package/src/panel/core/index.ts +47 -0
- package/src/panel/core/isEditingField.ts +23 -0
- package/src/panel/core/panelStyles.ts +248 -0
- package/src/panel/core/rowSpacers.ts +50 -0
- package/src/panel/core/statusBar.ts +48 -0
- package/src/panel/core/textFilter.ts +33 -0
- package/src/panel/core/yieldToPainting.ts +20 -0
- package/src/panel/ui/AboutDialogFrame.tsx +100 -0
- package/src/panel/ui/ClearButton.tsx +42 -0
- package/src/panel/ui/DocumentationDialogFrame.tsx +86 -0
- package/src/panel/ui/FilterInput.tsx +60 -0
- package/src/panel/ui/HelpLabel.tsx +43 -0
- package/src/panel/ui/PanelMessage.tsx +64 -0
- package/src/panel/ui/PanelRail.tsx +64 -0
- package/src/panel/ui/Section.tsx +66 -0
- package/src/panel/ui/SidePanelStack.tsx +109 -0
- package/src/panel/ui/SpectrumColorSwatch.tsx +119 -0
- package/src/panel/ui/index.ts +47 -0
- package/src/panel/ui/useConfirmOnEnter.ts +68 -0
- package/src/panel/ui/useFilterBox.ts +35 -0
- package/src/panel/ui/useVirtualRows.ts +82 -0
- package/src/panel/ui/useVirtualWindowRows.ts +86 -0
- package/src/ui.ts +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which band the pointer is asking about.
|
|
3
|
+
*
|
|
4
|
+
* Found in pixels rather than in wavenumbers, because what a user means by
|
|
5
|
+
* "that band" is what is under the pointer on screen: at a full-scan zoom two
|
|
6
|
+
* bands thirty wavenumbers apart are three pixels apart and either will do,
|
|
7
|
+
* while at a deep zoom the same thirty wavenumbers is half the plot and only one
|
|
8
|
+
* of them is being pointed at.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ChartScale } from '../../chart/core/chartScale.ts';
|
|
12
|
+
import { chartPixel } from '../../chart/core/chartScale.ts';
|
|
13
|
+
|
|
14
|
+
import type { IrBand } from './irBand.ts';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* How close the pointer has to be to a band, in pixels.
|
|
18
|
+
*
|
|
19
|
+
* Eight is about a fingertip's worth of aim on a trackpad. Wider and the readout
|
|
20
|
+
* claims a band while the pointer is plainly on the baseline beside it; narrower
|
|
21
|
+
* and a band has to be hit exactly, which on a dense fingerprint region is not
|
|
22
|
+
* a gesture anyone can make.
|
|
23
|
+
*/
|
|
24
|
+
export const BAND_HIT_RADIUS = 8;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The band nearest a place on the axis, when one is within reach.
|
|
28
|
+
*
|
|
29
|
+
* A plain scan rather than a binary search: a spectrum is picked down to a few
|
|
30
|
+
* dozen bands, so the whole list is shorter than the setup a search would need,
|
|
31
|
+
* and it stays correct if the bands ever arrive in another order.
|
|
32
|
+
* @param bands - The bands of every spectrum currently drawn.
|
|
33
|
+
* @param xScale - The wavenumber axis as it is currently zoomed, which may run
|
|
34
|
+
* either way round.
|
|
35
|
+
* @param pixelX - Where the pointer is, in user units of the SVG.
|
|
36
|
+
* @param radius - How close it has to be. Defaults to `BAND_HIT_RADIUS`.
|
|
37
|
+
* @returns The band, or `null` when none is within reach.
|
|
38
|
+
*/
|
|
39
|
+
export function nearestBandAt(
|
|
40
|
+
bands: readonly IrBand[],
|
|
41
|
+
xScale: ChartScale,
|
|
42
|
+
pixelX: number,
|
|
43
|
+
radius = BAND_HIT_RADIUS,
|
|
44
|
+
): IrBand | null {
|
|
45
|
+
let found: IrBand | null = null;
|
|
46
|
+
let bestDistance = radius;
|
|
47
|
+
for (const band of bands) {
|
|
48
|
+
const distance = Math.abs(chartPixel(xScale, band.wavenumber) - pixelX);
|
|
49
|
+
// Strictly nearer, so the first of two bands at one wavenumber wins and the
|
|
50
|
+
// answer does not flicker between them as the pointer rests still.
|
|
51
|
+
if (distance < bestDistance) {
|
|
52
|
+
bestDistance = distance;
|
|
53
|
+
found = band;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding the bands in a spectrum, which `ir-spectrum` does.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is the two things that call needs and does not have: a
|
|
5
|
+
* `MeasurementXY` built out of the arrays the viewer holds, and the decision to
|
|
6
|
+
* pick on **absorbance** rather than on transmittance. That second one is the
|
|
7
|
+
* only judgement in the file and it is not a preference — peak picking finds
|
|
8
|
+
* maxima, and a band is a maximum in absorbance but a *minimum* in transmittance,
|
|
9
|
+
* so picking on transmittance would return the flat baseline between the bands
|
|
10
|
+
* and miss every band there is.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { MeasurementXY } from 'cheminfo-types';
|
|
14
|
+
import { autoPeakPicking } from 'ir-spectrum';
|
|
15
|
+
import { xMaxValue, xMinValue } from 'ml-spectra-processing';
|
|
16
|
+
|
|
17
|
+
import type { IrBand, IrBandStrength } from './irBand.ts';
|
|
18
|
+
import type { IrSpectrum } from './irSpectrum.ts';
|
|
19
|
+
|
|
20
|
+
/** How the bands are picked. */
|
|
21
|
+
export interface PickBandsOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Lowest wavenumber to pick in, in cm⁻¹.
|
|
24
|
+
* @default the start of the spectrum
|
|
25
|
+
*/
|
|
26
|
+
from?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Highest wavenumber to pick in, in cm⁻¹.
|
|
29
|
+
* @default the end of the spectrum
|
|
30
|
+
*/
|
|
31
|
+
to?: number;
|
|
32
|
+
/**
|
|
33
|
+
* How tall a band must be against the tallest one to count, as a fraction.
|
|
34
|
+
*
|
|
35
|
+
* Two percent by default, which on a real ATR spectrum is a little above the
|
|
36
|
+
* noise and a long way below any band worth naming. Lowered, the fingerprint
|
|
37
|
+
* region fills with shoulders that have no assignment; raised past about a
|
|
38
|
+
* tenth, weak but diagnostic bands — a nitrile, an alkyne — stop being found.
|
|
39
|
+
* @default 0.02
|
|
40
|
+
*/
|
|
41
|
+
minRelativeHeight?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Narrowest band to keep, in cm⁻¹.
|
|
44
|
+
*
|
|
45
|
+
* A spike one point wide is a detector glitch rather than a vibration: real
|
|
46
|
+
* infrared bands are several wavenumbers across even at their sharpest.
|
|
47
|
+
* @default 4
|
|
48
|
+
*/
|
|
49
|
+
minPeakWidth?: number;
|
|
50
|
+
/**
|
|
51
|
+
* At most how many bands to keep, the strongest first.
|
|
52
|
+
* @default every band found
|
|
53
|
+
*/
|
|
54
|
+
limit?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Pick the bands of one spectrum.
|
|
59
|
+
*
|
|
60
|
+
* The bands come back in ascending wavenumber, which is the order a spectrum is
|
|
61
|
+
* read in rather than the order they were found — `limit` cuts by height, and
|
|
62
|
+
* then what survives is put back in axis order, so a table of them reads like
|
|
63
|
+
* the chart.
|
|
64
|
+
*
|
|
65
|
+
* **A band centre is a sampled point, not an interpolated one.** `ir-spectrum`
|
|
66
|
+
* reports each picked band at the wavenumber of the sample it peaked on, so on a
|
|
67
|
+
* bench instrument's 4 cm⁻¹ grid a carbonyl centred at 1710 is reported at 1708
|
|
68
|
+
* or 1712. That is within the tolerance the assignment table is matched with, and
|
|
69
|
+
* refining it here would mean re-deriving a peak position this package has
|
|
70
|
+
* deliberately delegated — but it is why a band should never be quoted as though
|
|
71
|
+
* it were measured to the wavenumber.
|
|
72
|
+
* @param spectrum - The spectrum to pick from.
|
|
73
|
+
* @param options - Where to pick, and what to keep.
|
|
74
|
+
* @returns The bands, ascending by wavenumber.
|
|
75
|
+
*/
|
|
76
|
+
export function pickBands(
|
|
77
|
+
spectrum: IrSpectrum,
|
|
78
|
+
options: PickBandsOptions = {},
|
|
79
|
+
): IrBand[] {
|
|
80
|
+
const {
|
|
81
|
+
from,
|
|
82
|
+
to,
|
|
83
|
+
minRelativeHeight = 0.02,
|
|
84
|
+
minPeakWidth = 4,
|
|
85
|
+
limit,
|
|
86
|
+
} = options;
|
|
87
|
+
if (spectrum.wavenumber.length < 2) return [];
|
|
88
|
+
|
|
89
|
+
const picked = autoPeakPicking(measurementOf(spectrum), {
|
|
90
|
+
// Absorbance, because a band is a maximum there and a minimum in the other.
|
|
91
|
+
yVariable: 'a',
|
|
92
|
+
minMaxRatio: minRelativeHeight,
|
|
93
|
+
minPeakWidth,
|
|
94
|
+
...(from === undefined ? {} : { from }),
|
|
95
|
+
...(to === undefined ? {} : { to }),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const bands: IrBand[] = [];
|
|
99
|
+
for (const peak of picked) {
|
|
100
|
+
if (!Number.isFinite(peak.wavenumber)) continue;
|
|
101
|
+
bands.push({
|
|
102
|
+
spectrumId: spectrum.id,
|
|
103
|
+
wavenumber: peak.wavenumber,
|
|
104
|
+
absorbance: peak.absorbance,
|
|
105
|
+
// `ConvertedPeak.transmittance` is a fraction where the spectrum's own
|
|
106
|
+
// transmittance is a percentage; brought onto the one scale here so that
|
|
107
|
+
// nothing downstream has to remember which of the two it is holding.
|
|
108
|
+
transmittance: peak.transmittance * 100,
|
|
109
|
+
strength: peak.kind as IrBandStrength,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const kept =
|
|
114
|
+
limit === undefined || bands.length <= limit
|
|
115
|
+
? bands
|
|
116
|
+
: bands.toSorted(byDescendingAbsorbance).slice(0, limit);
|
|
117
|
+
return kept.toSorted(byAscendingWavenumber);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The spectrum as `ir-spectrum` wants it.
|
|
122
|
+
*
|
|
123
|
+
* The `t` variable is given its extremes, because that is what the strength
|
|
124
|
+
* letter is worked out from: without them the conversion assumes a spectrum
|
|
125
|
+
* running the full 0 to 100 percent, and every band of a shallow ATR trace that
|
|
126
|
+
* never leaves the eighties comes back weak.
|
|
127
|
+
* @param spectrum - The spectrum the viewer holds.
|
|
128
|
+
* @returns A measurement carrying all three variables.
|
|
129
|
+
*/
|
|
130
|
+
function measurementOf(spectrum: IrSpectrum): MeasurementXY {
|
|
131
|
+
const transmittance = {
|
|
132
|
+
label: 'Transmittance (%)',
|
|
133
|
+
units: '%',
|
|
134
|
+
symbol: 't' as const,
|
|
135
|
+
data: spectrum.transmittance,
|
|
136
|
+
min: xMinValue(spectrum.transmittance),
|
|
137
|
+
max: xMaxValue(spectrum.transmittance),
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
variables: {
|
|
141
|
+
x: {
|
|
142
|
+
label: 'Wavenumber',
|
|
143
|
+
units: '1/cm',
|
|
144
|
+
symbol: 'x',
|
|
145
|
+
data: spectrum.wavenumber,
|
|
146
|
+
},
|
|
147
|
+
// `y` is required of every measurement, and stands for whichever axis was
|
|
148
|
+
// recorded. Nothing here reads it — the picking is told to use `a` and the
|
|
149
|
+
// strength letter is read off `t` — so it carries the transmittance rather
|
|
150
|
+
// than a third copy of anything.
|
|
151
|
+
y: transmittance,
|
|
152
|
+
a: {
|
|
153
|
+
label: 'Absorbance',
|
|
154
|
+
units: '',
|
|
155
|
+
symbol: 'a',
|
|
156
|
+
data: spectrum.absorbance,
|
|
157
|
+
},
|
|
158
|
+
t: transmittance,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Order two bands by height, tallest first.
|
|
165
|
+
* @param first - One band.
|
|
166
|
+
* @param second - The other.
|
|
167
|
+
* @returns The comparison.
|
|
168
|
+
*/
|
|
169
|
+
function byDescendingAbsorbance(first: IrBand, second: IrBand): number {
|
|
170
|
+
return second.absorbance - first.absorbance;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Order two bands along the axis, lowest wavenumber first.
|
|
175
|
+
* @param first - One band.
|
|
176
|
+
* @param second - The other.
|
|
177
|
+
* @returns The comparison.
|
|
178
|
+
*/
|
|
179
|
+
function byAscendingWavenumber(first: IrBand, second: IrBand): number {
|
|
180
|
+
return first.wavenumber - second.wavenumber;
|
|
181
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writing spectra back out as JCAMP-DX, so what was loaded can be taken away.
|
|
3
|
+
*
|
|
4
|
+
* JCAMP is the format to write rather than two columns of text because it says
|
|
5
|
+
* what its second column means: an infrared spectrum is read either as
|
|
6
|
+
* absorbance or as percent transmittance, the two are the same measurement
|
|
7
|
+
* turned inside out, and a bare column of numbers leaves whoever opens it next
|
|
8
|
+
* to guess which. `##YUNITS=` states it, and `ir-spectrum` reads it back and
|
|
9
|
+
* derives the other axis from it, so a spectrum written here returns carrying
|
|
10
|
+
* both.
|
|
11
|
+
*
|
|
12
|
+
* The points are written as an `##PEAK TABLE=` of explicit `x y` pairs rather
|
|
13
|
+
* than as a compressed `##XYDATA=` record. An XYDATA record states a first
|
|
14
|
+
* wavenumber and an increment and lets the reader rebuild the axis, which is
|
|
15
|
+
* exact only for an evenly sampled trace — and an interferogram transformed onto
|
|
16
|
+
* a wavenumber grid is evenly sampled only until somebody trims or splices it.
|
|
17
|
+
* Explicit pairs round trip whatever the spacing.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { fromJSON } from 'convert-to-jcamp';
|
|
21
|
+
|
|
22
|
+
import type { IrMode, IrSpectrum } from './irSpectrum.ts';
|
|
23
|
+
|
|
24
|
+
/** The extension a written spectrum is saved under. */
|
|
25
|
+
export const JCAMP_EXTENSION = '.jdx';
|
|
26
|
+
|
|
27
|
+
/** What a JCAMP-DX file is served as. */
|
|
28
|
+
export const JCAMP_MIME_TYPE = 'chemical/x-jcamp-dx';
|
|
29
|
+
|
|
30
|
+
/** How the technique is named when the file that was read named nothing. */
|
|
31
|
+
export const DEFAULT_DATA_TYPE = 'INFRARED SPECTRUM';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Write one spectrum as a JCAMP-DX block.
|
|
35
|
+
*
|
|
36
|
+
* The axis written is the one the instrument recorded wherever the file said
|
|
37
|
+
* which that was, and only otherwise the one being read. Writing what is on
|
|
38
|
+
* screen instead would export a spectrum that had been through a logarithm it
|
|
39
|
+
* was never measured with — and, where a band bottoms out at zero transmittance,
|
|
40
|
+
* an absorbance of infinity that no reader can take back.
|
|
41
|
+
* @param spectrum - The spectrum.
|
|
42
|
+
* @param mode - The axis being read, used when the file named none.
|
|
43
|
+
* @returns The block, `##TITLE=` through `##END=`.
|
|
44
|
+
*/
|
|
45
|
+
export function irSpectrumToJcamp(spectrum: IrSpectrum, mode: IrMode): string {
|
|
46
|
+
const written = spectrum.origin.recorded ?? mode;
|
|
47
|
+
const values =
|
|
48
|
+
written === 'absorbance' ? spectrum.absorbance : spectrum.transmittance;
|
|
49
|
+
return fromJSON(
|
|
50
|
+
{ x: spectrum.wavenumber, y: values },
|
|
51
|
+
{ info: infoRecords(spectrum, written), meta: metaRecords(spectrum) },
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Write every spectrum of a list as one JCAMP-DX file.
|
|
57
|
+
*
|
|
58
|
+
* One file rather than one download per spectrum: a browser asked for six files
|
|
59
|
+
* in a row blocks all but the first, and a sample and its background are wanted
|
|
60
|
+
* back as the pair they were compared as. The blocks go inside a `LINK` block,
|
|
61
|
+
* which is what JCAMP has for a container and what the instruments that write a
|
|
62
|
+
* pair already use, so dropping the file back on the chart brings the whole list
|
|
63
|
+
* back.
|
|
64
|
+
*
|
|
65
|
+
* A list of one is written as that block alone: wrapping a single spectrum in a
|
|
66
|
+
* container gains nothing, and the file is then exactly what asking for that one
|
|
67
|
+
* spectrum would have written.
|
|
68
|
+
* @param spectra - The spectra, in the order the list holds them.
|
|
69
|
+
* @param mode - The axis being read, used for a spectrum whose file named none.
|
|
70
|
+
* @param title - What to call the file's own outer block.
|
|
71
|
+
* @returns The file.
|
|
72
|
+
*/
|
|
73
|
+
export function irSpectraToJcamp(
|
|
74
|
+
spectra: readonly IrSpectrum[],
|
|
75
|
+
mode: IrMode,
|
|
76
|
+
title = `${spectra.length} infrared spectra`,
|
|
77
|
+
): string {
|
|
78
|
+
const only = spectra.length === 1 ? spectra[0] : undefined;
|
|
79
|
+
if (only !== undefined) return irSpectrumToJcamp(only, mode);
|
|
80
|
+
|
|
81
|
+
const blocks: string[] = [];
|
|
82
|
+
for (const spectrum of spectra) {
|
|
83
|
+
blocks.push(irSpectrumToJcamp(spectrum, mode));
|
|
84
|
+
}
|
|
85
|
+
return `##TITLE=${recordValue(title)}
|
|
86
|
+
##JCAMP-DX=4.24
|
|
87
|
+
##DATA TYPE=LINK
|
|
88
|
+
##BLOCKS=${blocks.length}
|
|
89
|
+
${blocks.join('\n')}
|
|
90
|
+
##END=
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The standard records of a block: what it is called, and what its axes are.
|
|
96
|
+
* @param spectrum - The spectrum.
|
|
97
|
+
* @param written - The axis being written.
|
|
98
|
+
* @returns The records, as `convert-to-jcamp` takes them.
|
|
99
|
+
*/
|
|
100
|
+
function infoRecords(
|
|
101
|
+
spectrum: IrSpectrum,
|
|
102
|
+
written: IrMode,
|
|
103
|
+
): Record<string, string> {
|
|
104
|
+
return {
|
|
105
|
+
title: recordValue(spectrum.name),
|
|
106
|
+
// The technique as the file stated it, so a Raman spectrum that was opened
|
|
107
|
+
// here is not written back out claiming to be infrared.
|
|
108
|
+
dataType: technique(spectrum) ?? DEFAULT_DATA_TYPE,
|
|
109
|
+
xUnits: '1/CM',
|
|
110
|
+
// Spelled the way `ir-spectrum` reads it: it takes the axis to be
|
|
111
|
+
// transmittance when the label says `trans`, and to be a percentage rather
|
|
112
|
+
// than a fraction when it carries a `%`.
|
|
113
|
+
yUnits: written === 'absorbance' ? 'ABSORBANCE' : 'Transmittance (%)',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The `$`-prefixed records of a block: the acquisition, as the file stated it.
|
|
119
|
+
*
|
|
120
|
+
* The table's labels are the record names themselves — the reader lists whatever
|
|
121
|
+
* `##$` records a block carried, under their own names — so writing it back is a
|
|
122
|
+
* matter of putting the `$` in front again. `Technique` is the one row that is
|
|
123
|
+
* not a record of that bag: it is the block's `##DATA TYPE=`, and it goes back
|
|
124
|
+
* there rather than becoming a user-defined record of its own.
|
|
125
|
+
* @param spectrum - The spectrum.
|
|
126
|
+
* @returns The records, keyed without their `##$`.
|
|
127
|
+
*/
|
|
128
|
+
function metaRecords(spectrum: IrSpectrum): Record<string, string> {
|
|
129
|
+
const records: Record<string, string> = {};
|
|
130
|
+
const fields = spectrum.meta?.fields ?? [];
|
|
131
|
+
for (const field of fields) {
|
|
132
|
+
if (field.label === TECHNIQUE) continue;
|
|
133
|
+
records[recordKey(field.label)] = recordValue(field.value);
|
|
134
|
+
}
|
|
135
|
+
return records;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** The row of the table that holds the block's own data type. */
|
|
139
|
+
const TECHNIQUE = 'Technique';
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* What the file said the spectrum was, if it said.
|
|
143
|
+
* @param spectrum - The spectrum.
|
|
144
|
+
* @returns The technique, or `undefined` when the file stated none.
|
|
145
|
+
*/
|
|
146
|
+
function technique(spectrum: IrSpectrum): string | undefined {
|
|
147
|
+
for (const field of spectrum.meta?.fields ?? []) {
|
|
148
|
+
if (field.label === TECHNIQUE) return recordValue(field.value);
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* A label put where a JCAMP record's name goes.
|
|
155
|
+
*
|
|
156
|
+
* A record name runs to the `=` and holds no whitespace, so a label that picked
|
|
157
|
+
* up a space on its way through some other tool would otherwise write a record
|
|
158
|
+
* whose name is its first word and whose value starts with the rest of it.
|
|
159
|
+
* @param label - The row's label.
|
|
160
|
+
* @returns It as a record name.
|
|
161
|
+
*/
|
|
162
|
+
function recordKey(label: string): string {
|
|
163
|
+
return label.replaceAll(/[\s=]+/g, '_');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* A value put where a JCAMP record's value goes.
|
|
168
|
+
*
|
|
169
|
+
* A record is one line and `$$` opens a comment that runs to the end of it, so a
|
|
170
|
+
* value with a newline in it would otherwise either break the file in two or
|
|
171
|
+
* lose its tail. Both failures are silent on the way back in, which is why this
|
|
172
|
+
* is done to every value rather than to the ones known to be long.
|
|
173
|
+
* @param value - The value as it is held.
|
|
174
|
+
* @returns The value as one line, with no comment marker in it.
|
|
175
|
+
*/
|
|
176
|
+
function recordValue(value: string): string {
|
|
177
|
+
return value.replaceAll(/\s+/g, ' ').replaceAll('$$', '$').trim();
|
|
178
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning what a reader produced into what the viewer holds.
|
|
3
|
+
*
|
|
4
|
+
* A reader answers about a file and knows nothing about the session it is being
|
|
5
|
+
* read into — which spectra are already open, what colours they took, what this
|
|
6
|
+
* one should be called. That is the gap this closes, and it is the only place an
|
|
7
|
+
* identity or a colour is invented.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { nextSpectrumColor } from '../../chart/core/spectrumColor.ts';
|
|
11
|
+
|
|
12
|
+
import type { LoadedIrSpectrum } from './analysisSpectra.ts';
|
|
13
|
+
import type { IrSpectrum } from './irSpectrum.ts';
|
|
14
|
+
|
|
15
|
+
/** What has to be decided for a loaded spectrum to become a held one. */
|
|
16
|
+
export interface ToIrSpectrumOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Identity, which every later edit and selection is keyed on.
|
|
19
|
+
* @default a fresh UUID
|
|
20
|
+
*/
|
|
21
|
+
id?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The colour to draw it in.
|
|
24
|
+
* @default the lowest hue not in `taken`
|
|
25
|
+
*/
|
|
26
|
+
color?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The colours the spectra already open have taken, so a new one is told apart
|
|
29
|
+
* from them. Ignored when `color` says outright.
|
|
30
|
+
* @default no colours taken
|
|
31
|
+
*/
|
|
32
|
+
taken?: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* What to call it, overriding the file's own title.
|
|
35
|
+
* @default the file's title, then its name, then `spectrum`
|
|
36
|
+
*/
|
|
37
|
+
name?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Whether it is drawn as soon as it is added.
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
visible?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Make a held spectrum out of a read one.
|
|
47
|
+
* @param loaded - What the reader produced.
|
|
48
|
+
* @param options - The identity, colour and name to give it.
|
|
49
|
+
* @returns The spectrum as the viewer holds it.
|
|
50
|
+
*/
|
|
51
|
+
export function toIrSpectrum(
|
|
52
|
+
loaded: LoadedIrSpectrum,
|
|
53
|
+
options: ToIrSpectrumOptions = {},
|
|
54
|
+
): IrSpectrum {
|
|
55
|
+
const {
|
|
56
|
+
id = crypto.randomUUID(),
|
|
57
|
+
taken = [],
|
|
58
|
+
name,
|
|
59
|
+
visible = true,
|
|
60
|
+
} = options;
|
|
61
|
+
const color = options.color ?? nextSpectrumColor(taken);
|
|
62
|
+
return {
|
|
63
|
+
id,
|
|
64
|
+
name: name ?? loaded.name ?? loaded.origin.fileName ?? 'spectrum',
|
|
65
|
+
color,
|
|
66
|
+
wavenumber: loaded.wavenumber,
|
|
67
|
+
absorbance: loaded.absorbance,
|
|
68
|
+
transmittance: loaded.transmittance,
|
|
69
|
+
meta: loaded.meta,
|
|
70
|
+
origin: loaded.origin,
|
|
71
|
+
visible,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Make held spectra out of everything one file held.
|
|
77
|
+
*
|
|
78
|
+
* The colours are handed out one at a time against a growing list, so a file
|
|
79
|
+
* carrying a sample and its background gives two spectra of two colours rather
|
|
80
|
+
* than two of the same — `nextSpectrumColor` can only answer that if it is told
|
|
81
|
+
* what the previous call took.
|
|
82
|
+
* @param loaded - What the reader produced, in file order.
|
|
83
|
+
* @param options - The colours already taken, and whether the spectra are drawn.
|
|
84
|
+
* @returns The spectra, in the same order.
|
|
85
|
+
*/
|
|
86
|
+
export function toIrSpectra(
|
|
87
|
+
loaded: readonly LoadedIrSpectrum[],
|
|
88
|
+
options: Pick<ToIrSpectrumOptions, 'taken' | 'visible'> = {},
|
|
89
|
+
): IrSpectrum[] {
|
|
90
|
+
const { taken = [], visible } = options;
|
|
91
|
+
const colors = [...taken];
|
|
92
|
+
const spectra: IrSpectrum[] = [];
|
|
93
|
+
for (const entry of loaded) {
|
|
94
|
+
const spectrum = toIrSpectrum(entry, {
|
|
95
|
+
taken: colors,
|
|
96
|
+
...(visible === undefined ? {} : { visible }),
|
|
97
|
+
});
|
|
98
|
+
colors.push(spectrum.color);
|
|
99
|
+
spectra.push(spectrum);
|
|
100
|
+
}
|
|
101
|
+
return spectra;
|
|
102
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { PlotRect } from '../../chart/core/chartGeometry.ts';
|
|
5
|
+
import type { ChartScale } from '../../chart/core/chartScale.ts';
|
|
6
|
+
import {
|
|
7
|
+
CHART_COLORS,
|
|
8
|
+
CHART_FONT,
|
|
9
|
+
LABEL_HALO,
|
|
10
|
+
} from '../../chart/core/chartTheme.ts';
|
|
11
|
+
import type { AssignedBand } from '../core/assignBands.ts';
|
|
12
|
+
import { BAND_MARK, planBandLabels } from '../core/bandLabelPlan.ts';
|
|
13
|
+
import type { IrBand } from '../core/irBand.ts';
|
|
14
|
+
import { sameIrBand } from '../core/irBand.ts';
|
|
15
|
+
import { bandsPointDown } from '../core/irMode.ts';
|
|
16
|
+
import type { IrMode } from '../core/irSpectrum.ts';
|
|
17
|
+
|
|
18
|
+
export interface BandMarksProps {
|
|
19
|
+
/** The bands to mark, with whatever the table said about them. */
|
|
20
|
+
assigned: readonly AssignedBand[];
|
|
21
|
+
/** Where the plot sits inside the SVG. */
|
|
22
|
+
plot: PlotRect;
|
|
23
|
+
/** The wavenumber axis as it is currently zoomed. */
|
|
24
|
+
xScale: ChartScale;
|
|
25
|
+
/** The value axis as it is currently zoomed. */
|
|
26
|
+
yScale: ChartScale;
|
|
27
|
+
/** Which value axis is being drawn. */
|
|
28
|
+
mode: IrMode;
|
|
29
|
+
/**
|
|
30
|
+
* Whether each label names the assignment as well as the wavenumber.
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
showAssignments?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* At most how many bands are named. Marks are drawn on all of them.
|
|
36
|
+
* @default 12
|
|
37
|
+
*/
|
|
38
|
+
limit?: number;
|
|
39
|
+
/**
|
|
40
|
+
* The band the pointer has come to rest on, drawn larger, `null` for none.
|
|
41
|
+
* @default null
|
|
42
|
+
*/
|
|
43
|
+
highlight?: IrBand | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A mark on every band, and a label on the ones there is room for.
|
|
48
|
+
*
|
|
49
|
+
* The mark reaches *away* from the label, into the band, because the clear space
|
|
50
|
+
* on the label's side is where the numbers are written and the mark is there to
|
|
51
|
+
* say which band they are about. So in transmittance both hang downwards from a
|
|
52
|
+
* dip and in absorbance both rise from a maximum, and the pair reads the same way
|
|
53
|
+
* up in either.
|
|
54
|
+
*
|
|
55
|
+
* A leader line is drawn only when a label had to be slid off its band to clear
|
|
56
|
+
* its neighbours — a leader from a label that is already directly above its band
|
|
57
|
+
* is a line saying what the position already said. A label slid too far is not
|
|
58
|
+
* drawn at all; the mark still says the band is there, which is the honest
|
|
59
|
+
* outcome, where a label hanging over a band it says nothing about is not.
|
|
60
|
+
* @param props - Component props.
|
|
61
|
+
* @returns The marks and labels, as SVG.
|
|
62
|
+
*/
|
|
63
|
+
export function BandMarks(props: BandMarksProps): ReactElement {
|
|
64
|
+
const {
|
|
65
|
+
assigned,
|
|
66
|
+
plot,
|
|
67
|
+
xScale,
|
|
68
|
+
yScale,
|
|
69
|
+
mode,
|
|
70
|
+
showAssignments = false,
|
|
71
|
+
limit = 12,
|
|
72
|
+
highlight = null,
|
|
73
|
+
} = props;
|
|
74
|
+
|
|
75
|
+
const plans = useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
planBandLabels({
|
|
78
|
+
assigned,
|
|
79
|
+
plot,
|
|
80
|
+
xScale,
|
|
81
|
+
yScale,
|
|
82
|
+
mode,
|
|
83
|
+
showAssignments,
|
|
84
|
+
limit,
|
|
85
|
+
}),
|
|
86
|
+
[assigned, plot, xScale, yScale, mode, showAssignments, limit],
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const down = bandsPointDown(mode);
|
|
90
|
+
const reach = down ? BAND_MARK : -BAND_MARK;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<g pointerEvents="none">
|
|
94
|
+
{plans.map((plan) => {
|
|
95
|
+
const highlighted = sameIrBand(plan.band, highlight);
|
|
96
|
+
const dropped = !Number.isFinite(plan.labelX);
|
|
97
|
+
const firstBaseline = plan.baselines[0];
|
|
98
|
+
const slid = !dropped && Math.abs(plan.labelX - plan.tipX) > LEADER_AT;
|
|
99
|
+
return (
|
|
100
|
+
<g key={`${plan.band.spectrumId} ${plan.band.wavenumber}`}>
|
|
101
|
+
<line
|
|
102
|
+
x1={plan.tipX}
|
|
103
|
+
y1={plan.tipY}
|
|
104
|
+
x2={plan.tipX}
|
|
105
|
+
y2={plan.tipY + reach}
|
|
106
|
+
style={highlighted ? highlightMarkStyle : markStyle}
|
|
107
|
+
strokeWidth={highlighted ? 2 : 1}
|
|
108
|
+
/>
|
|
109
|
+
{slid && firstBaseline !== undefined ? (
|
|
110
|
+
<line
|
|
111
|
+
x1={plan.tipX}
|
|
112
|
+
y1={plan.tipY + reach}
|
|
113
|
+
x2={plan.labelX}
|
|
114
|
+
y2={firstBaseline}
|
|
115
|
+
style={leaderStyle}
|
|
116
|
+
/>
|
|
117
|
+
) : null}
|
|
118
|
+
{dropped
|
|
119
|
+
? null
|
|
120
|
+
: plan.lines.map((line, index) => (
|
|
121
|
+
<text
|
|
122
|
+
key={line}
|
|
123
|
+
x={plan.labelX}
|
|
124
|
+
y={plan.baselines[index]}
|
|
125
|
+
textAnchor="middle"
|
|
126
|
+
style={highlighted ? highlightTextStyle : textStyle}
|
|
127
|
+
>
|
|
128
|
+
{line}
|
|
129
|
+
</text>
|
|
130
|
+
))}
|
|
131
|
+
</g>
|
|
132
|
+
);
|
|
133
|
+
})}
|
|
134
|
+
</g>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* How far a label may sit from its band before a leader is drawn to it.
|
|
140
|
+
*
|
|
141
|
+
* Two pixels: below that the label is over its band and a leader would be a
|
|
142
|
+
* line nobody needs, and the declutter sweep leaves most labels within a pixel
|
|
143
|
+
* of where they wanted to be.
|
|
144
|
+
*/
|
|
145
|
+
const LEADER_AT = 2;
|
|
146
|
+
|
|
147
|
+
const markStyle = { stroke: CHART_COLORS.annotation } as const;
|
|
148
|
+
|
|
149
|
+
const highlightMarkStyle = { stroke: CHART_COLORS.highlight } as const;
|
|
150
|
+
|
|
151
|
+
const leaderStyle = { stroke: CHART_COLORS.leader } as const;
|
|
152
|
+
|
|
153
|
+
// Haloed: an infrared label is written over the trace as often as beside it,
|
|
154
|
+
// since a band is named where it dips and the neighbouring bands dip too.
|
|
155
|
+
const textStyle = {
|
|
156
|
+
fill: CHART_COLORS.labelText,
|
|
157
|
+
fontSize: CHART_FONT.label,
|
|
158
|
+
...LABEL_HALO,
|
|
159
|
+
} as const;
|
|
160
|
+
|
|
161
|
+
const highlightTextStyle = {
|
|
162
|
+
fill: CHART_COLORS.highlight,
|
|
163
|
+
fontSize: CHART_FONT.label,
|
|
164
|
+
fontWeight: 600,
|
|
165
|
+
...LABEL_HALO,
|
|
166
|
+
} as const;
|