OHIF / Viewers

OHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages
https://docs.ohif.org/
MIT License
3.02k stars 3.19k forks source link

How to make the viewer load a specific Dicom Study #1400

Closed EduardoSantanaSeverino closed 4 years ago

EduardoSantanaSeverino commented 4 years ago

How to make the viewer load a specific Dicom Study

Is there any internal function or method where I can indicate or set the DICOM Image parameters (Instance ID, Study ID) for the viewer loads this image.

I have been able to embed the viewer into the application but instead of the study list, I want to load a specific study.

dannyrb commented 4 years ago

@EduardoSantanaSeverino, you can specify the study to load using the route/url.

See: https://viewer.ohif.org/viewer/{studyInstanceUid}

@kokokenada, you can ViewerRouting.js allows for seriesInstanceUids to be specified as query parameters. Whether their presence "promotes" or "filters" depends on if the configuration property filterQueryParam is true or false.

The logic there could be cleaner, and we are open to accepting PRs that refactor and/or add support for specifying an initial instance to display. We have discussed hanging protocol support, but likely won't address them until they're on the critical path for "workflow extensions"

EduardoSantanaSeverino commented 4 years ago

@dannyrb, thanks for the quick replay,

I am embedding the viewer into an already existed react application using the following example: https://docs.ohif.org/deployment/recipes/embedded-viewer.html

and this other example: https://codesandbox.io/s/viewer-script-tag-tprch

I don't have a specific URL for loading the study.

But for instance, I would end up with some URL like the following:

http://myappname.com/component/{studyInstanceId}

dannyrb commented 4 years ago

If you are embedding the app with an iframe, you can control the URL of the iFrame. If you are using the exposed App component directly, we can discuss exposing props that give you similar control.

matthiasg commented 4 years ago

I would definitely be interested in this too. The URL to study mapping could simply be a configurable callback function. The general concept stays as would the resulting mapping to the DICOM retrieval urls.

EduardoSantanaSeverino commented 4 years ago

@matthiasg thank you very much, I will definitely take a look at the previous issue that you posted.

In the meantime I just got it working in the following way:

Step 1: Change the default route: modified the following file: Viewers/platform/viewer/src/routes/routesUtil.js line number 35 from: ['/viewer/:studyInstanceUids'], to: path: ['/viewer/:studyInstanceUids', '/'], line number 34 from: path: ['/studylist', '/'], to: path: ['/studylist'],

Step 2: Get the study id from config file: modifed the following file: Viewers/platform/viewer/src/routes/ViewerRouting.js line number 32 from: const studyUids = UrlUtil.paramString.parseParam(studyInstanceUids); to: const studyUids = server.studyInstanceUids ? [server.studyInstanceUids] : UrlUtil.paramString.parseParam(studyInstanceUids);

Step 3: Set the study id on the config file: For the configuration file you set it as the following:

window.config = {
  routerBasename: '/',
  showStudyList: true,
  servers: {
    dicomWeb: [
      {
        name: 'DCM4CHEE',
        ....
        studyInstanceUids: 'MY-DICOM-STUDY-ID',
        ....
      },
    ],
  },
};

Please Note: I find this approach useful only if you need to embed the viewer into an already existed web application using the below example approach. The viewer will load the study id instead of loading the study list. https://codesandbox.io/s/viewer-script-tag-tprch

For example:

<script src="myserver.com/mybundle-ohif-viewer-pkg/index.umd.js" crossorigin></script>
<script>
    var containerId = "root";
    var componentRenderedOrUpdatedCallback = function(){
      console.log('OHIF Viewer rendered/updated');
    }
    window.OHIFViewer.installViewer(
      {
      // routerBasename: '/',
      servers: {
        dicomWeb: [
          {
            name: 'DCM4CHEE',
            wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
            qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
            wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
            studyInstanceUids: 'MY-DICOM-STUDY-ID',
            qidoSupportsIncludeField: true,
            imageRendering: 'wadors',
            thumbnailRendering: 'wadors',
          },
        ],
      },
    }, containerId, componentRenderedOrUpdatedCallback);
</script>
matthiasg commented 4 years ago

@EduardoSantanaSeverino thanks for looking into this. As an ad-hoc change adding via config can be helpful.

When using the viewer in more complex environments it should be possible to directly commandeer the viewer data model to handle incoming events from e.g a connected system.

While staying in the 1 Study per Viewer Model it should at least be the following flow:

  1. Start viewer with configuration. Configuration has pluggable studyInstanceUid lookup function or string. When empty, a default function is used which reads the studyInstanceUid from the URL as before. Otherwise the function gets called and returns the studyInstanceUid.

  2. An external call should be possible to react to external change events. This could be a route change or some other event (websocket,user click etc).

NOTE: I have NOT yet looked at the code internals. Only at the obvious APIs made available (see above). As such I am sure the system being modeled with React only have a design that is applicable.

As there would be two different ways of interacting the question is on whether to integrate or what the external function actually should do. In order to stay consistent and debuggable it would not be a great idea to just have a function called 'showStudy' if it can override the config key or the aforementioned function if that existed. Also a showStudy function would basically only update the internal view model anyway and trigger a re-rendering. The very next thing might be some other features like addSeries, setLayoutetc. This would open up a pretty large API.

In order to stay manageable it would be best to expose a ViewModel (could be the react state?) to users of the component. The plugins, the main viewer and any embedding apps would have access to the same state model. It might only be a subset of the main react store of course.

I am looking forward at reading the code as I expect something like this will already be there.

EduardoSantanaSeverino commented 4 years ago

https://github.com/OHIF/Viewers/issues/1448

EduardoSantanaSeverino commented 4 years ago

@dannyrb Thanks for your time. I am looking to add a feature request. but I am facing this error. https://github.com/OHIF/Viewers/issues/1448

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

dannyrb commented 4 years ago

This is currently labeled as a question. If we would like this to shift to a feature request, let's create a new issue with formalized "acceptance criteria". Issue may be a blocker, but it's unrelated to this request. I am more than happy to accept a PR to resolve that issue, or guidance on troubleshooting as the next steps are unclear.

nicoesiea commented 1 year ago

Sorry to come back, but it there a solution now for this question?