import { Popover } from '@blueprintjs/core'; import styled from '@emotion/styled'; import { IdcodeSvgRenderer } from 'react-ocl'; import { isSpectrum1D } from '../../data/data1d/Spectrum1D/isSpectrum1D.js'; import type { AssignmentsData } from '../assignment/AssignmentsContext.js'; import { useAssignment } from '../assignment/AssignmentsContext.js'; import { useScaleChecked } from '../context/ScaleContext.js'; import { useHighlight } from '../highlight/index.js'; import useCheckExperimentalFeature from '../hooks/useCheckExperimentalFeature.js'; import useSpectrum from '../hooks/useSpectrum.js'; const boxHeight = 10; const boxPadding = 4; const Rect = styled.rect<{ isHighlighted: boolean }>` fill: ${({ isHighlighted }) => (isHighlighted ? '#ff6f0057' : 'transparent')}; :hover { fill: #ff6f0057; } `; const Container = styled.div` display: flex; flex-direction: column; `; const InfoHeader = styled.div` display: flex; flex-direction: row; `; const BaseText = styled.span` flex: 1; font-size: 12px; text-align: center; `; const Text = styled(BaseText)` background-color: darkgray; color: white; `; const Value = styled(BaseText)` border-bottom: 1px solid darkgray; font-weight: bold; `; interface Statistics { min: number; q1: number; median: number; q3: number; max: number; mean: number; lowerWhisker: number; upperWhisker: number; nb: number; } interface Metadata { sphere: number; hose: string; } interface SignalStatistics { statistics: Statistics; metadata: Metadata; id: string; } function useStatistics() { const spectrum = useSpectrum(); if (!isSpectrum1D(spectrum)) return; const ranges = spectrum?.ranges?.values; if (!Array.isArray(ranges) || ranges?.length === 0) { return []; } const result: SignalStatistics[] = []; for (const range of ranges) { const { signals = [] } = range; for (const signal of signals) { const { statistics, id, metadata } = signal as any; if (!statistics) continue; result.push({ id, statistics, metadata }); } } return result; } export function PredictionErrorsNotations() { const data = useStatistics(); if (!data || data?.length === 0) return null; return ( {data.map((datum, index) => ( ))} ); } function PredictionError(props: SignalStatistics) { const { statistics, metadata, id } = props; const isExperimental = useCheckExperimentalFeature(); const assignment = useAssignment(id); const highlight = useHighlight(extractID(id, assignment), { type: 'SIGNAL', }); const isAssignmentActive = assignment.isActive; const isHighlighted = highlight.isActive || isAssignmentActive; const { scaleX } = useScaleChecked(); const { min, max, median, q1, q3, nb } = statistics; const yCenter = boxHeight / 2; const yTop = 0; const yBottom = boxHeight; const xQ1 = scaleX()(q1); const xQ3 = scaleX()(q3); const xMin = scaleX()(min); const xMax = scaleX()(max); const xMedian = scaleX()(median); const boxPath = ` M ${xMin} ${yCenter} L ${xQ1} ${yCenter} M ${xQ1} ${yTop} L ${xQ3} ${yTop} L ${xQ3} ${yBottom} L ${xQ1} ${yBottom} Z M ${xQ3} ${yCenter} L ${xMax} ${yCenter} `; const medianLine = `M ${xMedian} ${yTop} L ${xMedian} ${yBottom}`; const rectWidth = Math.abs(xMax - xMin) + boxPadding * 2; const rectHeight = boxHeight + boxPadding * 2; const x = xMax - boxPadding; const y = -boxPadding; const { hose, sphere } = metadata; return ( ) : undefined } > { assignment.highlight('x'); highlight.show(); }} onMouseLeave={() => { assignment.clearHighlight(); highlight.hide(); }} > ); } interface InfoBlockProps { sphere: number; nb: number; hose: string; } function InfoBlock(props: InfoBlockProps) { const { sphere, nb, hose } = props; return ( Sphere {sphere} Nb {nb} {hose && } ); } function extractID(id: string, assignment: AssignmentsData) { return [id].concat(assignment.assignedDiaIds?.x || []); }