95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import type {NativePPGProcessingResult} from 'react-native-haptika-ppg';
|
|
|
|
import {mapNativeProcessingResult} from '../measurement/measurementCoordinator';
|
|
|
|
const nativeResult = (): NativePPGProcessingResult => ({
|
|
valid: false,
|
|
invalidReason: 'Signal exploitable insuffisant',
|
|
bpm: {
|
|
bpm: 72,
|
|
temporalBpm: Number.NaN,
|
|
frequencyBpm: 72.4,
|
|
methodAgreementBpm: 0.4,
|
|
validPeakCount: 19.7,
|
|
rejectedPeakCount: 8.2,
|
|
confidence: 0.51,
|
|
selectedChannel: 'red-inverted',
|
|
},
|
|
prv: {
|
|
estimatedRmssdMs: Number.POSITIVE_INFINITY,
|
|
estimatedSdnnMs: 31,
|
|
meanIpiMs: 833,
|
|
medianIpiMs: 829,
|
|
pnn50Percent: 7,
|
|
rangeIpiMs: 118,
|
|
modeIpiMs: 825,
|
|
amo50Percent: 42,
|
|
coefficientOfVariation: 0.05,
|
|
validIntervalCount: 18.8,
|
|
rejectedIntervalCount: 7.4,
|
|
rejectedIntervalRatio: 0.28,
|
|
reliable: false,
|
|
},
|
|
quality: {
|
|
score: 0.43,
|
|
level: 'invalid',
|
|
usableDurationSeconds: 21.5,
|
|
droppedFrameRatio: 0.08,
|
|
saturationRatio: 0.12,
|
|
rejectedIntervalRatio: 0.28,
|
|
signalToNoiseRatio: 3.2,
|
|
motionArtifactRatio: 0.31,
|
|
methodAgreementScore: 0.6,
|
|
timestampJitterRatio: 0.04,
|
|
longestGapSeconds: 0.38,
|
|
issues: ['motionArtifacts', 'futureNativeDiagnostic'],
|
|
},
|
|
startedAtMonotonicSeconds: 100,
|
|
endedAtMonotonicSeconds: 160,
|
|
rawSampleCount: 1_642.4,
|
|
resampledSampleCount: 5_501.7,
|
|
});
|
|
|
|
describe('measurementCoordinator diagnostics', () => {
|
|
test('preserves acquisition diagnostics used to explain an invalid result', () => {
|
|
const result = mapNativeProcessingResult(nativeResult());
|
|
|
|
expect(result).toMatchObject({
|
|
valid: false,
|
|
invalidReason: 'Signal exploitable insuffisant',
|
|
rawSampleCount: 1_642,
|
|
resampledSampleCount: 5_502,
|
|
quality: {
|
|
usableDurationSeconds: 21.5,
|
|
droppedFrameRatio: 0.08,
|
|
saturationRatio: 0.12,
|
|
rejectedIntervalRatio: 0.28,
|
|
signalToNoiseRatio: 3.2,
|
|
motionArtifactRatio: 0.31,
|
|
timestampJitterRatio: 0.04,
|
|
longestGapSeconds: 0.38,
|
|
},
|
|
bpm: {
|
|
selectedChannel: 'red-inverted',
|
|
validPeakCount: 20,
|
|
rejectedPeakCount: 8,
|
|
},
|
|
prv: {
|
|
validIntervalCount: 19,
|
|
rejectedIntervalCount: 7,
|
|
},
|
|
});
|
|
});
|
|
|
|
test('normalizes non-finite values and unknown native issues safely', () => {
|
|
const result = mapNativeProcessingResult(nativeResult());
|
|
|
|
expect(result.bpm.temporalBpm).toBeNull();
|
|
expect(result.prv.estimatedRmssdMs).toBeNull();
|
|
expect(result.quality.issues).toEqual([
|
|
'motionArtifacts',
|
|
'nonFiniteProcessingResult',
|
|
]);
|
|
});
|
|
});
|