Skip to content

Commit

Permalink
Cleaned up the example to show invalid, valid, and other test types. …
Browse files Browse the repository at this point in the history
…Cleaned up documentation. Pointed to the NIBIB repositories.
  • Loading branch information
andymeadows committed Jun 25, 2024
1 parent e131cf2 commit 26109e8
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 82 deletions.
31 changes: 31 additions & 0 deletions MARS_API_OVERVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# RADx MARS API Overview
MARS is Mobile At Home Reporting through Standards. When developing an application/reader under EUA, it is required that the application report results to health departments. MARS works to facilitate this. Under funding by the NIH via the RADx program and facilitated by VentureWell, Meadows Design has developed a TypeScript API capable of interfacing with both current RADx MARS hubs – AIMS (developed by APHL) and ReportStream (developed by the CDC) – in ReactNative mobile applications, NodeJS server applications, or any development environment capable of supporting TypeScript.

Mobile applications developed under the auspices of an EUA are required to follow a specific flow. That flow is defined at https://www.nibib.nih.gov/covid-19/radx-tech-program/mars/mobile-application-guidance. In addition to the flow, this page also defines the requirements for fields that must be requested as well as fields that must be gathered by the application when submitting results to a MARS hub.

Both current MARS hubs receive test results as HL7 ELR 2.5.1 messages. The MARS API developed by Meadows Design not only facilitates the delivery of messages but also the construction of HL7 ELR 2.5.1 messages themselves. This removes the burden of understanding the expansive scope of HL7 from the implementor, allowing them to focus on their detection technology and not the specifications underlying their reporting requirements.

## API Libraries
The API developed by Meadows Design for interfacing with RADx MARS hubs has three distinct libraries: The RADx MARS Library, the AIMS MARS Library, and the ReportStream MARS Library.

### RADx MARS Library
The RADx MARS Library will be identified as `radx-mars-lib`` in NPM and is currently hosted on [Bitbucket](https://bitbucket.org/meadowsdesign/radx-mars-lib/). It contains base class libraries representing several of the segments defined in HL7 ELR 2.5.1 messages as well as interfaces to implement by hubs in order to facßßilitate message construction and delivery to a RADx MARS hub.

Defined in this library is the `MarsHubProvider` interface – a key component in the RADx MARS library ecosystem. It enables RADx MARS Hubs to integrate with the RADx MARS Library by implementing this interface in their own libraries. This design allows the RADx MARS Library to remain agnostic to the specific communication methods used by individual hubs. The primary role of the `MarsHubProvider` interface is to standardize the message delivery mechanism, allowing the RADx MARS Library to focus on message construction while abstracting away the details of the delivery process.

Both the AIMS and ReportStream libraries depend on the RADx MARS Library and both implement their own versions of the `MarsHubProvider` interface. The AIMS and ReportStream libraries can be used interchangeably allowing the developer to change the RADx MARS Hub targeted by their application.

### AIMS MARS Library
The AIMS MARS Library will be identified as `aims-mars-lib` in NPM and is currently hosted at [Bitbucket](https://bitbucket.org/meadowsdesign/aims-mars-lib/). It contains a `MarsHubProvider` implementation for communicating with APHL’s AIMS MARS Hub and any supporting classes needed to fulfill the implementation.

**Note**: Inclusion of this library within an application does not grant the implementor access to the AIMS MARS Hub itself. The implementor’s organization must still follow the onboarding certifications and processes mandated by APHL AIMS to enable their application to report results through the APHL AIMS MARS Hub.

### ReportStream MARS Library
The ReportStream MARS Library will be identified as `reportstream-mars-lib` in NPM and is currently hosted at [Bitbucket](https://bitbucket.org/meadowsdesign/reportstream-mars-lib/). It contains a `MarsHubProvider` implementation for communicating with the CDC’s ReportStream MARS Hub as well any necessary supporting classes.

**Note**: As with the APHL AIMS Mars Hub, inclusion of this library within an application does not grant the implementor access to the ReportStream MARS Hub itself. The implementor’s organization must still follow the onboarding certifications and processes mandated by the CDC to enable their application to report results through the CDC ReportStream MARS Hub.

## Sample Applications
There are two sample applications illustrating the usage of these APIs. The first sample application is this repository: `radx-mars-demo`. In this repository you will find code capable of submitting a test to AIMS or Report Stream as well as a sample `MarsHubProvider` implementation used to support debugging of messages.

A separate repository, `react-native-mars-demo`, to be hosted at [Bitbucket](https://bitbucket.org/meadowsdesign/react-native-mars-demo/), shows how one might use the API inside of a React Native application to deliver
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Walkthrough of `radx-mars-demo`

## Overview
The `radx-mars-demo` is a TypeScript project demonstrating the use of the `radx-mars-lib` and its extensions for constructing and submitting HL7 messages to MARS Hubs. The demo includes setting up the necessary configurations, creating patient and test data, and demonstrating the submission process. In this demo we construct an HL7 message submitting the result of an Abbott Labs' BinaxNow test to a MARS hub.

### Before We Begin
This demo relies on a set of three libraries briefly enumerated as follows:

* `radx-mars-lib` - A library containing a set of base classes, interfaces, models, and classes upon which additional libraries can and have been built. This library contains all of the core classes responsible for constructing an HL7 ELR 2.5.1 with all content required by MARS Hubs as defined by the NIH and validated by the NIST HL7 ELR 2.5.1 validator. The construction of the HL7 message is abstracted into a set of friendly model classes. The delivery of the HL7 message is coorrdinated internally through a set of internal classes and an implementation of a `MarsHubProvider`.
* `aims-mars-lib` - This library contains an implementation of a `MarsHubProvider` capable of delivering an HL7 message generated from within `radx-mars-lib` to the APHL AIMS MARS Hub. You will leverage this library if you want to deliver your HL7 messages through AIMS. This library requires the `radx-mars-lib` library as a dependency.
* `reportstream-mars-lib` - This library contains an implementation of a `MarsHubProvider` capable of delivering an HL7 message generated from within `radx-mars-lib` to the CDC Report Stream MARS Hub. You will leverage this library if you want to deliver your HL7 messages through Report Stream. This library requires the `radx-mars-lib` library as a dependency.

During the demo we will construct a `MarsClient`. The `MarsClient` class is defined in `radx-mars-lib` and serves as the coordinator of all activity. It is responsible for initating the construction of the HL7 message and constructing a `LabResultSubmitter` class used to submit HL7 messages specific to a particular test to a MARS Hub implemented as a `MarsHubProvider`. This should become clearer as we walk through the construction of this demo.

**Important**: These packages are NOT currently hosted in NPM. As such, the dependencies for this package are pulled from bitbucket as dependencies. You may need to build each of the packages individually as the dist/ directories are not part of the git repository commits.

## Step-by-Step Implementation

### Setting Up Hub Providers
The demo begins by initializing two hub providers, `AimsHubProvider` from `aims-mars-lib` and `ReportStreamHubProvider` from `reportstream-mars-lib`. These are configured with necessary details for connecting to their respective MARS Hubs. You will need to retrieve credentials for your chosen provider from the provider maintainer. You will typically only use a single provider in your solution. We have included in this demo a simple `DebugHubProvider` class you can use to view the message you would otherwise send to a MARS provider.

```typescript
const aimsHubProvider = new AimsHubProvider('RADx', { bucketPath: '...' }, false);
const reportStreamHubProvider = new ReportStreamHubProvider({ ...credentials... }, false);
```

### The MarsClient
The `MarsClient` class is the starting point for all implementations. The `MarsClient` class orchestrates the generation of HL7 messages and their submission to a RADx MARS Hub.

### Initializing the MarsClient
In this demo, a `MarsClient` instance is created with the `ReportStreamHubProvider` (you can modify it to use the `AimsHubProvider` -- `MarsHubProvider`s are interchangeable) and an instance of `AbbottLabInfo`. `AbbottLabInfo` is an extension of the base `MarsLabInfo` class contained in `radx-mars-lib`. You will want provide an instance of `MarsLabInfo` during construction of your `MarsClient` or extend `MarsLabInfo` as we have done here.

The generated `MarsClient` client is responsible for handling HL7 message generation and submission.

```typescript
const client = new MarsClient(reportStreamHubProvider, new AbbottLabInfo());
```

### Creating a Result Submitter
The demo sets up a result submitter (an instance of `LabResultSubmitter` using the `MarsClient`. A `LabResultSubmitter` is capable of sending results for a specific test type (in this case, `BinaxNowCovidTest`, an extension of the `Test` class in `radx-mars-lib`) to facilitate the submission of test results.

```typescript
const resultSubmitter = client.createResultSubmitter(new BinaxNowCovidTest());
```

### Gathering Patient Information
Patient data is then collected and a `Patient` object is created. This object captures essential information such as the patient's ID, age, and address.

```typescript
const patientAge = 28;
const patient = new Patient('YOUR_PATIENT_ID', patientAge, ExtendedAddress.MinExtendedAddress('00000'), ...);
```

A couple of things to note about the construction of a `Patient`. There are a couple of required fields regarding the test subject you must capture prior to submission of a test. The first is the patient age. You can either get the patient age by acquiring the patient birthdate or by asking them for it directly. The second piece of required information is the patient's zipcode. You can see we've supplied both of them in the code from the demo above.

### Preparing the Test Kit and Test Result
We can now prepare information about the test kit and the test result. A `TestKit` instance and a `BinaxNowCovidTestResult` instance are created with necessary details like test kit ID, test dates, and result codes. The `BinaxNowCovidTestResult` is an extension of the `TestResult` class defined in the `radx-mars-lib` library and simply serves as a way to construct a new `TestResult` without entering all of the information every time. The creation of a class that extends `TestResult` is a design choice and is not required.

```typescript
const testKit = new TestKit('Test Kit ID', new Date(), new Date());
const testResult = new BinaxNowCovidTestResult(new Date(), BinaxNowCovidDetectedTestResultCodes.Detected, TestResultAbnormalFlagsCode.Detected);
```

### Submitting the Test Result
Finally, the test result is submitted using the result submitter. This step demonstrates how the assembled

data is sent to the MARS Hub, showcasing the end-to-end functionality of the `radx-mars-lib` and its extensions.

```typescript
resultSubmitter.submitResult(patient, testKit, testResult);
```

In this step, the `submitResult` method of the result submitter is called with the patient information, test kit details, and test result. This method manages the creation of the HL7 message and its submission to the specified MARS Hub.

---

This walkthrough covers the key steps implemented in the `radx-mars-demo` project. It demonstrates how the `radx-mars-lib` and its extensions can be utilized to construct HL7 messages and interact with different MARS Hubs. The demo provides a practical example of setting up necessary configurations, preparing patient and test data, and submitting this data as an HL7 message.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
"test": "jest",
"prepublishOnly": "npm run build",
"lint": "eslint .",
"run": "npm run build && node dist/index.js"
"start": "npm run build && node dist/index.js"
},
"keywords": [],
"author": "Meadows Design, Andy Meadows",
"license": "ISC",
"dependencies": {
"@aws-sdk/client-s3": "^3.440.0",
"react-native-fetch-blob": "^0.10.8",
"radx-mars-lib": "bitbucket:meadowsdesign/radx-mars-lib#bug/integration-fixes",
"reportstream-mars-lib": "bitbucket:meadowsdesign/reportstream-typescript#bug/integration-fixes",
"aims-mars-lib": "bitbucket:meadowsdesign/aims-mars-lib#bug/integration-fixes"
"radx-mars-lib": "git+https://github.com/NIBIB/radx-mars-lib.git#main",
"reportstream-mars-lib": git+https://github.com/NIBIB/reportstream-mars-lib.git#main",
"aims-mars-lib": "git+https://github.com/NIBIB/aims-mars-lib.git#main"
},
"devDependencies": {
"@types/jest": "^29.5.2",
Expand All @@ -36,4 +36,4 @@
"ts-node": "^10.4.0",
"typescript": "^5.2.2"
}
}
}
9 changes: 5 additions & 4 deletions src/AbbottLabInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
MarsLabInfo
} from 'radx-mars-lib'

// Setup our lab information. Lab information is specific to the sender and
// is provided by a governing authority. It identifies the ISO and CLIA
// designation of the Lab authorized to collect and report test results.

/**
* Setup our lab information. Lab information is specific to the sender and
* is provided by a governing authority. It identifies the ISO and CLIA
* designation of the Lab authorized to collect and report test results.
*/
export default class AbbottLabInfo extends MarsLabInfo {
constructor () {
super(
Expand Down
8 changes: 5 additions & 3 deletions src/BinaxNowCovidTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
Test
} from 'radx-mars-lib'

// Define our test. The test information may be gathered from the NIH
// PowerBI dashboard. For us, this test information represents the
// Abbott BinaxNow COVID test.
/**
* Define our test. The test information may be gathered from the NIH
* PowerBI dashboard. For us, this test information represents the
* Abbott BinaxNow COVID test.
*/
export default class BinaxNowCovidTest extends Test {
constructor () {
super('94558-4',
Expand Down
8 changes: 7 additions & 1 deletion src/BinaxNowCovidTestResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import {
type TestResultCode
} from 'radx-mars-lib'

/**
* This class extends TestResult and serves to simply the construction of a
* test result by hiding the passing of the immutable parameters to the base
* TestResult class. This is simply a design decision and is unnecessary in
* any implementation -- you may simply construct a TestResult.
*/
export default class BinaxNowCovidTestResult extends TestResult {
constructor (
determinationDate: Date,
Expand All @@ -17,7 +23,7 @@ export default class BinaxNowCovidTestResult extends TestResult {
'10811877011337_DIT',
determinationDate,
testResultCode,
testResultAbnormalFlagsCode, // TODO: Move this so the user doens't have to supply it. How?
testResultAbnormalFlagsCode,
CodingSystem.LOINC_271
)
}
Expand Down
26 changes: 26 additions & 0 deletions src/DebugHubProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {
IsoHierarchicDesignator,
type HierarchicDesignator,
type MarsHubProvider
} from 'radx-mars-lib'

/**
* This is a sample hub provider illustrating how you can extend the base class
* to do simple debugging.
*/
export default class DebugHubProvider implements MarsHubProvider {
get receivingApplicationIdentifier (): HierarchicDesignator {
return new IsoHierarchicDesignator('AIMS.INTEGRATION.STG', '2.16.840.1.114222.4.3.15.2')
}

get receivingFacilityIdentifier (): HierarchicDesignator {
return new IsoHierarchicDesignator('AIMS.PLATFORM', '2.16.840.1.114222.4.1.217446')
}

readonly isUsingProduction = false

public async submitTest (hl7Message: any): Promise<boolean> {
console.log(hl7Message)
return true
}
}
Loading

0 comments on commit 26109e8

Please sign in to comment.