feat: explicit layout apply via HangingProtocolService (#2936)
* feat: add more types to HP service * change hp to have apply protocol * feat: mpr initial work * apply protocol by id * feat: mode should be able to apply protocol directly * fix: wrong inheritance for viewports drag and drop * apply review comments
This commit is contained in:
1 parent
fb9744a817
commit
5f480ff746
28 files changed
+705
-226
No files matched your search
@@ -28,7 +28,7 @@ const deafultProtocol = {
|
||||
id: 'hYbmMy3b7pz7GLiaT',
|
||||
name: 'default',
|
||||
viewportStructure: {
|
||||
type: 'grid',
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 2,
|
||||
@@ -64,8 +64,8 @@ const deafultProtocol = {
|
||||
function getHangingProtocolModule() {
|
||||
return [
|
||||
{
|
||||
name: hangingProtocolName,
|
||||
protocols: [defaultProtocol],
|
||||
id: 'default',
|
||||
protocol: deafultProtocol,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ async function defaultRouteInit({
|
||||
});
|
||||
|
||||
DicomMetadataStore.subscribe('seriesAdded', ({ StudyInstanceUID }) => {
|
||||
const studyMetadata = DicomMetadataStore.getStudy(StudyInstanceUID);
|
||||
HangingProtocolService.run(studyMetadata);
|
||||
const studyMetadata = // get study metadata and displaySets
|
||||
HangingProtocolService.run({studies, displaySets, activeStudy});
|
||||
});
|
||||
|
||||
return unsubscriptions;
|
||||
|
||||
@@ -8,20 +8,32 @@ sidebar_label: Hanging Protocol Service
|
||||
## Overview
|
||||
|
||||
`HangingProtocolService` is a migration of the `OHIF-v1` hanging protocol
|
||||
engine. This service handles the arrangement of the images in the viewport. In
|
||||
short, the registered protocols will get matched with the Series that are
|
||||
available for the series. Each protocol gets a point, and they are ranked. The
|
||||
engine along with various improvements and fixes.
|
||||
This service handles the arrangement of the images in the viewport. In
|
||||
short, the registered protocols will get matched with the DisplaySets that are
|
||||
available. Each protocol gets a score, and they are ranked. The
|
||||
winning protocol gets applied and its settings run for the viewports.
|
||||
|
||||
You can read more about hanging protocols
|
||||
[here](http://dicom.nema.org/dicom/Conf-2005/Day-2_Selected_Papers/B305_Morgan_HangProto_v1.pdf).
|
||||
In short with `OHIF-v3` hanging protocols you can:
|
||||
In `OHIF-v3` hanging protocols you can:
|
||||
|
||||
- Define what layout of the viewport should the viewer starts with (2x2 layout)
|
||||
- Define which series gets displayed in which position of the layout
|
||||
- Apply certain initial viewport settings; e.g., inverting the contrast
|
||||
- Enable certain tools based on what series are displayed: link prostate T2 and
|
||||
ADC MRI.
|
||||
- Specify the type of the viewport and its orientation
|
||||
- Define which displaySets gets displayed in which viewport of the layout
|
||||
- Apply certain initial viewport settings; e.g., inverting the contrast, jumping to a specific slice, etc.
|
||||
- Add specific synchronization rules for the viewports
|
||||
|
||||
## Protocols
|
||||
|
||||
A protocol can be an object or a function that returns an object (protocol generator).
|
||||
Each protocol can get added to the `HangingProtocolService` by using the `addProtocol` method given
|
||||
an `id` and the protocol itself. As an example, the `default` protocol is an object, while
|
||||
the 'mpr' protocol is a function that returns the protocol (the reason for this is that the
|
||||
`mpr` protocol needs to be generated based on the active viewport).
|
||||
|
||||
All protocols are stored in the `HangingProtocolService` using their `id` as the key, and
|
||||
the protocol itself as the value.
|
||||
|
||||
## Events
|
||||
|
||||
@@ -31,20 +43,21 @@ There are two events that get publish in `HangingProtocolService`:
|
||||
| ------------ | -------------------------------------------------------------------- |
|
||||
| NEW_LAYOUT | Fires when a new layout is requested by the `HangingProtocolService` |
|
||||
| STAGE_CHANGE | Fires when the the stage is changed in the hanging protocols |
|
||||
| PROTOCOL_CHANGED | Fires when the the protocol is changed in the hanging protocols |
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
- `getState`: returns an array: `[matchDetails, hpAlreadyApplied]`:
|
||||
- `getMatchDetails`: returns an object which contains the details of the
|
||||
matching for the viewports, displaysets and whether the protocol is
|
||||
applied to the viewport or not
|
||||
|
||||
- `matchDetails`: matching details for the series
|
||||
- `hpAlreadyApplied`: An array which tracks whether HPServices has been
|
||||
applied on each viewport.
|
||||
|
||||
- `addProtocols`: adds provided protocols to the list of registered protocols
|
||||
- `addProtocol`: adds provided protocol to the list of registered protocols
|
||||
for matching
|
||||
|
||||
- `run(studyMetaData, protocol)`: runs the HPService with the provided
|
||||
studyMetaData and optional protocol. If protocol is not given, HP Matching
|
||||
- `run({studies, activeStudy, displaySets }, protocolId)`: runs the HPService with the provided
|
||||
studyMetaData and optional protocolId. If protocol is not given, HP Matching
|
||||
engine will search all the registered protocols for the best matching one
|
||||
based on the constraints.
|
||||
|
||||
@@ -52,6 +65,8 @@ There are two events that get publish in `HangingProtocolService`:
|
||||
|
||||
Default initialization of the modes handles running the `HangingProtocolService`
|
||||
|
||||
|
||||
|
||||
## Custom Attribute
|
||||
In some situations, you might want to match based on a custom attribute and not the DICOM tags. For instance,
|
||||
if you have assigned a `timepointId` to each study, and you want to match based on it.
|
||||
@@ -129,50 +144,3 @@ function modeFactory() {
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Viewport Settings
|
||||
|
||||
You can define custom settings to be applied to each viewport. There are two
|
||||
types of settings:
|
||||
|
||||
- `viewport settings`: Currently we support two viewport settings
|
||||
|
||||
- `voi`: applying an initial `voi` by setting the windowWidth and windowCenter
|
||||
- `inverted`: inverting the viewport color (e.g., for PET images)
|
||||
|
||||
- `props settings`: Running commands after the first render; e.g., enabling the
|
||||
link tool
|
||||
|
||||
Examples of each settings are :
|
||||
|
||||
```js
|
||||
viewportSettings: [
|
||||
{
|
||||
options: {
|
||||
itemId: 'SyncScroll',
|
||||
interactionType: 'toggle',
|
||||
commandName: 'toggleSynchronizer',
|
||||
commandOptions: { toggledState: true },
|
||||
},
|
||||
commandName: 'setToolActive',
|
||||
type: 'props',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```js
|
||||
viewportSettings: [
|
||||
{
|
||||
options: {
|
||||
voi: {
|
||||
windowWidth: 400,
|
||||
windowCenter: 40,
|
||||
},
|
||||
},
|
||||
commandName: '',
|
||||
type: 'viewport',
|
||||
},
|
||||
];
|
||||
```
|
||||
@@ -58,8 +58,7 @@ async function defaultRouteInit({
|
||||
const { unsubscribe: seriesAddedUnsubscribe } = DicomMetadataStore.subscribe(
|
||||
DicomMetadataStore.EVENTS.SERIES_ADDED,
|
||||
({ StudyInstanceUID }) => {
|
||||
const studyMetadata = DicomMetadataStore.getStudy(StudyInstanceUID);
|
||||
HangingProtocolService.run(studyMetadata);
|
||||
HangingProtocolService.run({studies, displaySets, activeStudy});
|
||||
}
|
||||
);
|
||||
unsubscriptions.push(seriesAddedUnsubscribe);
|
||||
@@ -89,11 +88,6 @@ export default function ModeRoute(/**..**/) {
|
||||
extensionManager.onModeEnter();
|
||||
mode?.onModeEnter({ servicesManager, extensionManager });
|
||||
|
||||
hangingProtocols.forEach(extentionProtocols => {
|
||||
const { protocols } = extensionManager.getModuleEntry(extentionProtocols);
|
||||
HangingProtocolService.addProtocols(protocols);
|
||||
});
|
||||
|
||||
const setupRouteInit = async () => {
|
||||
if (route.init) {
|
||||
return await route.init(/**...**/);
|
||||
|
||||
Reference in new issue
Block a user