Reader SDK Documents
Breadcrumbs

IFU007(02) v1.0.1

Novarum DX Ltd
Instructions for Use / Guides

Document ID: IFU007
Revision: 02
Released: Dec 19, 2025

1. Overview

Reader SDK v1.0.1 is the initial release of the Reader component, enabling mobile devices to analyze lateral flow tests using the device camera.
This version provides core functionality for capturing, processing, and interpreting test strips via the Reader API.

2. Core Features

  • Camera-based analysis of lateral flow tests

    • Captures live camera input and performs on-device image analysis.

  • Real-time guidance overlay

    • Guides the user to correctly align the test strip for optimal capture.

  • Automated line detection and analysis

    • Detects and evaluates test and control lines from the camera feed.

  • Cross-platform parity

    • Shared analysis logic between Android and iOS with platform-appropriate camera and rendering layers.

3. Supported Platforms

Platform

Minimum Version

Notes

Android

API Level 26 (Android 8.0)

Requires OpenCV 4.8.0

iOS

iOS 13+

Requires OpenCV 4.8.0

Expo

Expo 51.0+

Requires OpenCV 4.8.0, inherits platform requirements form iOS and Android version 1.0.1

4. Public APIs

The SDK exposes a single entry point for initiating the analysis session.

4.1. Example (Android)

Kotlin
// Provide the analyser configuration
val readerParams = PMFLoader.loadReaderParams(readerParamsJson)

val analyserConfiguration =
    AnalyserConfiguration(
        pointModel = readerParams.pointModel,
        classifier = readerParams.classifier,
        testType = readerParams.testConfig
    )
Kotlin
NovarumAnalyzerPreview(ctx).apply {
    analyzerConfig = analyserConfiguration
    onScanningComplete = { result ->
        /* Handle results */
    },
    onProgression =  { progress ->
        /* Handle progress */
    },
    onFrameCaptured = { result ->
        /* Handle current frame status */
    }
}

4.2. Android Compose Example

Kotlin
@Composable
fun NovarumAnalyzerPreview(
    analyzerConfig: AnalyserConfiguration,
    onFrameCaptured: (ResultPMF) -> Unit = {},
    onScanningComplete: (ResultModel) -> Unit = {},
    onProgression: (Float) -> Unit = {},
) {
    val lifecycleOwner = LocalLifecycleOwner.current

    AndroidView(
        factory = { ctx ->
            val preview =
                org.novarumdx.camerax.NovarumAnalyzerPreview(ctx, scaleToFitVertical = true)
            preview.analyzerConfig = analyzerConfig
            preview.onFrameCaptured = onFrameCaptured
            preview.onScanningComplete = onScanningComplete
            preview.onProgression = onProgression
            lifecycleOwner.lifecycle.addObserver(preview)
            preview
        },
        modifier =
            Modifier
                .fillMaxWidth(),
    )
}

4.3. Example (iOS Swift UI)

Swift
let data = try Data(contentsOf: URL(fileURLWithPath: assetPath))
let readerParam = PmfService.shared.loadReaderParams(jsonData: Data)
Swift
    var readerParams: ReaderParams?

    var body: some View {
        VStack {
            ReaderViewWrapper(
                readerParams: readerParams,
                onFrameCaptured: { readerStatus in
                     /* Handle current frame status */
                },
                onComplete: { analysisModel in
                   /* Handle results */
                },
                onProgressChanged: {progress in
                    /* Handle progress */
                }
            )

4.4. Example Expo (React Native)

4.4.1. NdxImagingExpoView

In order to configure the reader the json configuration must be loaded and provided to the view as a string.

This can be achieved using the react assets folder.

TypeScript
import testInfoJson from './assets/unified-phoenix-test-config.json'

const configurationJson = JSON.stringify(testInfoJson);
TypeScript
import { NdxImagingExpoView } from '@novarumdx/ndx-imaging-expo';

    ...
    
    <NdxImagingExpoView
        style={styles.container}
        testInfoJson={configurationJson}
        hfactor={1.0}
        onComplete={({ nativeEvent: { resultModel } }) => {
          console.log(resultModel.testStrips[0].lines)
          
          let message = `TC Ratio: ${resultModel.testStrips[0].lines[0].tcRatio}\n`
          message += `Hash: ${resultModel.integrityHash}\n`
          message += `Hfactor Override: ${resultModel.hFactorOverride}`
        }}
        onFrameCaptured={({ nativeEvent: { resultPMF } }) => {
          if (resultPMF == 'Fit') {
            console.log('😀')
          }
        }}
        onProgress={({ nativeEvent: { progress } }) => {
          if (progress < 0.8 && progress > 0.5) {
            console.log('🟠')
          } else if (progress > 0.8) {
            console.log('🟢')
          }
        }}
    />

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'black',
  }
})

5. Output Models

  • ResultModel

    • Contains final test results and associated strip data.

  • TestStrip

    • Includes baseline, profile, and control/test line data.

(PMF Story, abort, and per-frame callbacks are introduced later in v2.1.1.)

  • Progress

    • Float between 0 and 1 denotes scan progress

  • OnFramCaptured

    • Enum/String value, (None, Fit, MarginalFit, NoFit) denotes the status of the current frame


6. Notes

This version establishes the baseline Reader SDK functionality and data models upon which all subsequent versions build.

7. Document History

Revision

Summary

Date

01

Initial document revision

Nov 13, 2025

02

Added expo component and corrected ios and android 1.0.1 examples

Dec 19, 2025