QIDO/WADO endpoints handling in OHIF v3

Hello everyone!

Congrats to the team for the new website and this shiny forum! :clap:

To give a bit of context, I am working for the Greater Paris University Hospitals (APHP), and we’re using OHIF v2 for a few months now with some of our research projects.
We are pluging OHIF to our own PACS solution (opensource, soon to be published) based on Python (pydicom, pynetdicom, on top of Django Rest Framework for handling DICOMweb).

I am in the process of installing OHIF v3 in our dev environment, so we can test it and get back to you with some feedback.

I have a strange issue that I did not encountered with OHIF v2 ; it seems that the qidoRoot param is not taken into account :

Here is my Datasource :

dataSources: [
    {
        friendlyName: "SPHERE DICOMWeb Server",
        namespace: "org.ohif.default.dataSourcesModule.dicomweb",
        sourceName: "dicomweb",
        configuration: {
            name: "SPHERE",
            wadoUriRoot: "https://sphere.docker.local:443/wadors",
            qidoRoot: "https://sphere.docker.local:443/qidors",
            wadoRoot: "https://sphere.docker.local:443/wadors",
            qidoSupportsIncludeField: true,
            imageRendering: "wadors",
            thumbnailRendering: "wadors",
            enableStudyLazyLoad: true,
            supportsFuzzyMatching: false,
            supportsWildcard: false,
        },
    },
];

It seems that the query to the PACS for displaying the study list is using the wadors endpoint :


image.png

Looking into the code, it seems that these config params are not well known :

/**
 *
 * @param {string} name - Data source name
 * @param {string} wadoUriRoot - Legacy? (potentially unused/replaced)
 * @param {string} qidoRoot - Base URL to use for QIDO requests
 * @param {string} wadoRoot - Base URL to use for WADO requests
 * @param {boolean} qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
 * @param {string} imageRengering - wadors | ? (unsure of where/how this is used)
 * @param {string} thumbnailRendering - wadors | ? (unsure of where/how this is used)
 * @param {bool} supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
 * @param {bool} lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
 */

I cant find the root of the issue by quickly looking at it, does that ring any bells to anyone?

Thank you :bowing_man:

Thanks for reporting this.
I lookd at the code, and I confirm this is bug introduced here (feat: Add Static WADO display (#2499) · OHIF/Viewers@2327b4a · GitHub)

The fix will get merged soon

Awesome, thank you! :muscle:

Hello again :wink:

It seems that I now have the same issue a bit further in the workflow.

Indeed, I can now access the studies list view, but every time I click on a study, OHIF is querying the WADO-RS endpoint instead of the QIDO-RS one) to query series metadata (or at least that is what it seems to happen) :

image

The consequence is that I cannot display any series content since OHIF cannot retrieve the series metadata it needs to query the WADO-RS endpoint for data frames.

I precise that I am working on the last version of the v3-stable branch.

Here is the last version of my DataSource configuration, if this can be of any help :

window.config = {
  routerBasename: '/',
  // whiteLabelling: {},
  extensions: [],
  modes: [],
  showStudyList: true,
  filterQueryParam: false,
  dataSources: [
    {
      friendlyName: 'SPHERE',
      namespace: 'org.ohif.default.dataSourcesModule.dicomweb',
      sourceName: 'dicomweb',
      configuration: {
        name: 'SPHERE',
        wadoUriRoot: 'https://sphere.docker.local:443/wadors',
        qidoRoot: 'https://sphere.docker.local:443/qidors',
        wadoRoot: 'https://sphere.docker.local:443/wadors',
        qidoSupportsIncludeField: true,
        supportsReject: false,
        imageRendering: 'wadors',
        thumbnailRendering: 'thumbnail',
        enableStudyLazyLoad: true,
        supportsFuzzyMatching: false,
        supportsWildcard: false,
        staticWado: false,
      },
    },
  ],
  defaultDataSourceName: 'dicomweb',
};

Do you know what could cause the issue?

Thank you :slightly_smiling_face:

What is the last commit hash you have on your OHIF? (having said that we need a better way to communicate which version you are using …)

This one →

commit 1d0b310d9235aa29b7834a12e3c0a725496ddbb5 (HEAD -> v3-stable, origin/v3-stable)
Author: Daryl.Xu <ziqiang_xu@qq.com>
Date:   Mon Oct 25 16:55:13 2021 +0800

    fix: typo (#2592)

It is very weird, we are using the qidoRoot for querying here.

Where exactly (which file) is querying using the wado (instead of qido)?

EDIT : Here is a GIF of the issue, with public data from the TCIA :

StudyLoading

OHIF v3 shows one empty series, but when switching to OHIF v2, I can see several series with instances inside.


I took some time to dig through the code today despite my very limited React skills, but here is what I found (and I hope it also answers your question) :

The issue seems to be with the way OHIF v3 is calling the searchForSeries function inside the dicomweb-client dependency :

Indeed, this function seems to be called with the wadoDicomWebClient object, instead of the qidoDicomWebClient one (and this function clearly wants a QIDO URL).

In the DicomWebDataSource module, we can see inside the retrieve series implementation a declaration of a studyPromise, which is calling the retrieveStudyMetadata with a wadoDicomWebClient object`:

If we take a closer look to the retrieveStudyMetadata function inside the RetrieveMetadata module, we can see a new promise which is using the RetrieveMetadata function :

This function is using the RetrieveMetadataLoaderAsync :

Finally, this async loader is calling the searchForSeries function of the dicomweb-client dependency with the wadoDicomWebClient it has been called with :

Now this is pure supposition of my part, but I think that this AsyncLoader is triggrered when we are displaying a Study in order to crawl through the series, for performance reasons I guess, and that could explain why this error arises at this moment in the workflow.

This is the best lead I have, but do not hesitate to correct me if I am wrong

Sorry for the spam, but I figured my latest investigations could help you out :smiley:

I found that the dicomweb-client dependency have four interesting parameters in our case :

  • url : base URL of the DICOMWeb server
  • qidoURLPrefix : the qido base URL extension
  • wadoURLPrefix : the wado base URL extension
  • stowURLPrefix : the stow base URL extension

In the OHIFv3 code you showed me, we are using two different DICOMWeb clients ; one for WADO-RS and one for QIDO-RS, and in each case we are cheating a bit by replacing the url parameter in the options by a complete WADO-RS or QIDO-RS URL.
I wonder why we are doing that since one client can perfectly handle both endpoints, and also adding a proper support for STOW queries (I know there is support for such queries in OHIF v2 and v3, but I wonder how there are implemented and which client they use :thinking:).

Anyway, I tweaked the code a bit, by simply :

  • Creating one client instead of two
  • Adding support in the DicomWebDataSource module and in the DataSource config file for the url, wadoUrlPrefix, qidoUrlPrefix and stowUrlPrefix parameters :
function createDicomWebApi(dicomWebConfig, UserAuthenticationService) {
  const {
    qidoRoot,
    wadoRoot,
    baseUrl,
    wadoUrlPrefix,
    qidoUrlPrefix,
    stowUrlPrefix,
    enableStudyLazyLoad,
    supportsFuzzyMatching,
    supportsWildcard,
    supportsReject,
    staticWado,
  } = dicomWebConfig;

  const dicomWebClientConfig = {
    url: baseUrl,
    wadoURLPrefix: wadoUrlPrefix,
    qidoURLPrefix: qidoUrlPrefix,
    stowURLPrefix: stowUrlPrefix,
    headers: UserAuthenticationService.getAuthorizationHeader(),
    errorInterceptor: errorHandler.getHTTPErrorHandler(),
  };

  const dicomWebClient = new api.DICOMwebClient(dicomWebClientConfig);

And I just replaced all the calls to the former WADO-RS and QIDO-RS clients to my new generic dicomWebClient.

I also updated the dicomweb-client dependency to the latest available version.

And, for the first time, I am now able to visualize my DICOMs with OHIF v3! :tada:

Now, I am sure that this naive modification have more implications and would probably break some things, but at least now we know that there is still an issue with the DICOMWeb clients as there are implemented now.

It would be great if we could manage to use just one client, but I guess we are using two of them for a reason :thinking:

1 Like