Real-time Medical Image Collaboration POC Made Easy with OHIF and Nun-db

Remotely controlling medical imaging visualization enables many use cases; for example, in education, the professor can ask all students to open the same study and manipulate the image from their computers at the lab, and all students can see it reflected immediately on their screens. Or, for example, in collaboration between two doctors while analyzing a patient case.

OHIF and Nun-db

OHIF (Open Health Imaging Foundation) is a widely used open-source platform for medical imaging visualization tools, and it has mature extension and event capabilities, making it simple to enable such use cases. Using Nun-db and its real-time data synchronization, we can easily implement such use cases using fully open-source solutions (both are licensed under MIT).

How it works?

Let’s make it happen

This tutorial is based on OHIF master version 3.7.0-beta.86, but it should work with any recent version since it does not rely on special new features.

Cloning OHIF

git clone git@github.com:OHIF/Viewers.git
cd Viewers&&yarn install
yarn start

Link the lib using the OHIF cli tool.

yarn cli add-extension ohif-nun-db

Diff of the change

diff --git a/platform/app/pluginConfig.json b/platform/app/pluginConfig.json
index 08a42deb0..47ce44fd4 100644
--- a/platform/app/pluginConfig.json
+++ b/platform/app/pluginConfig.json
@@ -51,6 +51,10 @@
       "packageName": "@ohif/extension-cornerstone-dicom-rt",
       "default": false,
       "version": "3.0.0"
+    },
+    {
+      "packageName": "ohif-nun-db",
+      "version": "1.2.4"
     }
   ],
   "modes": [

Amazing, we are almost there. Let’s configure OHIF to access the correct instance of Nun-db. in this first part, we will use the cloud-hosted Nun-db, and in the last part of the tutorial, we will show how to connect to a local running version.

For that you have to change the file platform/app/public/config/default.js and add the Nun-db configuration to the end of the file.

Configuring OHIF to access Nun-db

window.config = {
  //.. Omitted for simplicity
  dataSources: [
  //... Omitted for simplicity
  ],
  hotkeys: [
  //... Omitted for simplicity
  ],
  nunDb: {
    url: 'wss://ws-staging.nundb.org', // Nun-db server address
    db: 'features-of-db',// Nun-db Db instance
    user: 'client', // Nun-db db user
    token: 'client-pwd',// Nun-db user token
    key: 'client-YOUR_NAME_HERE', // Replace this key to a unique one
  },
};


Diff of the config change

diff --git a/platform/app/public/config/default.js b/platform/app/public/config/default.js
index 0001352..c98de30 100644
--- a/platform/app/public/config/default.js
+++ b/platform/app/public/config/default.js
@@ -230,4 +230,11 @@ window.config = {
       keys: ['9'],
     },
   ],
+  nunDb: {
+    url: 'wss://ws-staging.nundb.org',
+    db: 'features-of-db',
+    user: 'client',
+    token: 'client-pwd',
+    key: 'client-YOUR_NAME_HERE',
+  },
 };

Stop and restart your yarn start process.

# Kill old yarn start process
yarn start

Change the YOUR_NAME_HERE to a unique value (maybe use your GitHub name).

At this point, you should be able to see it working as expected; let’s test it. Open http://localhost:3000 at your machine browser and see it in action.

If you want to see an repo configured up to this point here it is, and here is the commit, with all changes you must have up to this point (You can ignore yarn.lock changes).

From this point ahead is optional only if you want to run Nun-db locally or understand how this work and the limitation of this POC implementation.

Advance topics

Running your own Nun-db instance with docker

To execute this POC fully in your computer or infra, you will need to run your own Nun-db instance for that, the simplest form is using docker, Next I am showing the command to get it running.

docker run --env NUN_USER=user-name --env NUN_PWD=user-pwd --env NUN_DBS_DIR="/data" --mount type=bind,source="/tmp",target=/data -it --rm -p 3013:3013 -p 3012:3012 -p 3014:3014 --name nun-test mateusfreira/nun-db

Next, we need to create the database and the user and set the proper permissions for this tutorial to work. This may sound complex, so if you want to understand deeper how to manipulate users in Nun-db, read this tutorial.

docker exec -it nun-test  /bin/sh -c 'nun-db -u user-name -p user-pwd create-db -d features-ohif-db -t features-ohif-db-pwd&&nun-db -u user-name -p user-pwd exec "use features-of-db features-of-db-pwd; create-user client client-pwd;set-permissions client r *|rwx client-*;"'

You should see the following response if the command works as expected.

[2023-09-24T21:32:22.005972013Z nun_db] nundb starting!
Response "valid auth\n;create-db success\n"
[2023-09-24T21:32:22.328383888Z nun_db] nundb starting!
Response "valid auth\n;empty;empty;empty"

Now, to connect to your local Nun-db instead of the Cloud Nun-db, you just have to change the URL to point to local. This change will be in the file platform/app/public/config/default.js and the parameter nunDb.url must be changed from wss://ws-staging.nundb.org to ws://localhost:3012 (port 3012 is the default websocket port for Nun-db). If you are testing this in your internal network, make sure to change the localhost to the machine’s network IP.

How does it work internally ? (If you want to replicate with different backends)

The main mechanism to enable this implementation are 2 cornerstone APIs.

  1. First one is the event CAMERA_MODIFIED Documentation here, that triggers on the HTML element when the viewport camera changes. We leverage that event to propagate in the network the same camera state using Nun-Dbs watch capabilities, in the code Here Here you can find we binding the event from the viewport and applying the value to Nun-db here. That will ensure that any change made in one client will be stored and therefore replicated to other connected clients. This process is shown in the Next image.

  1. On the other side, every time the key ${window.config.nunDb.key}-camera changes we want to use the API setCamera to apply the same state in the other clients. We do that by watching the changes coming from Nun-db here, and apply it on the other side here after that you have to render the viewport again we do that here.

There are other smaller details in the implementation to avoid infinite loops of change and also to sync currentImageIdIndex, setting here and watching there.

Limitations

This was a proof of concept and by no means ready for production usage. Nevertheless, it shows the capabilities of Nun-db to quickly enable such use cases. Please email me if you need help replicating this; next, I am adding a few current implementation limitations.

  • Works with a single viewport.
  • Does not sync the series opening.

Update 1

  • We also implemented tools to enable and disable the live sync and here you can find an example of how to add that to your hotkey bindings.

Future Work ideas

  • Enable remote replication of Hanging Protocol.
  • Remote replicate tool enabling (add a button to enable and disable the sync).
  • Show the other actor’s mouse position.
  • Add some visual indication that the sync is enabled.

Conclusion

In this tutorial, we aim to demonstrate how to connect OHIF to Nun-db to enable live sync use cases. Though simple to do, we also tried to show the means we used to create the POC and also make sure that if someone wants to replicate with different backends, they can use this as an example.

Written on September 24, 2023