feat: state sync service and hanging protocol updates to preserve state (#3131)
* feat: Add state sync and use it to remember viewport grid info fix: Version updates Fixes for toggling MPR mode Fix the display when the interleaved load module fails Fix the memory of the state to restore correctly PR fixes for the state sync service PR fixes PR fixes PR fixes Added a hack warning to remove volumeDeactivate Fixes for TMTV colormap setting Fix the casing Missed renames fix: tests not running due to variance in ordering Reverting some fixes to change case PR changes - mostly comments and minor improvements fix: All display sets were being updated on drag and drop PR fixes - mostly renames PR fixes Test support for OHIF, for HP branch test: Add at least a minimal set of automated tests for hanging protocols Docs PR fixes Merge fixes DOCS updates Add an example of the mn hanging protocol PR fixes PR fixes PR fixes * Fix the drag and drop PR fixes * PR changes - update default keys for next/previous stage * fix: Was storing the custom viewport grid too aggressively Caused by a PR change misspelling a variable
This commit is contained in:
1 parent
b7fff77e17
commit
803f638401
87 files changed
+3413
-1919
No files matched your search
@@ -0,0 +1 @@
|
||||
export default (study, extraData) => Math.max(...(extraData?.displaySets?.map?.(ds => (ds.numImageFrames ?? 0))) || [0]);
|
||||
@@ -0,0 +1 @@
|
||||
export default (study, extraData) => extraData?.displaySets?.length;
|
||||
@@ -0,0 +1,5 @@
|
||||
export default (study, extraData) => {
|
||||
const ret = extraData?.displaySets?.filter(ds => ds.numImageFrames>0)?.length;
|
||||
console.log("number of display sets with images", ret);
|
||||
return ret;
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* This function extracts an attribute from the already matched display sets, and
|
||||
* compares it to the attribute in the current display set, and indicates if they match.
|
||||
* From 'this', it uses:
|
||||
* `sameAttribute` as the attribute name to look for
|
||||
* `sameDisplaySetId` as the display set id to look for
|
||||
* From `options`, it looks for
|
||||
*/
|
||||
export default function (displaySet, options) {
|
||||
const { sameAttribute, sameDisplaySetId } = this;
|
||||
if( !sameAttribute ) {
|
||||
console.log("sameAttribute not defined in", this);
|
||||
return `sameAttribute not defined in ${this.id}`;
|
||||
}
|
||||
if( !sameDisplaySetId ) {
|
||||
console.log("sameDisplaySetId not defined in", this);
|
||||
return `sameDisplaySetId not defined in ${this.id}`;
|
||||
}
|
||||
const { displaySetMatchDetails, displaySets } = options;
|
||||
const match = displaySetMatchDetails.get(sameDisplaySetId);
|
||||
if( !match ) {
|
||||
console.log("No match for display set", sameDisplaySetId);
|
||||
return false;
|
||||
}
|
||||
const { displaySetInstanceUID } = match;
|
||||
const altDisplaySet = displaySets.find(it => it.displaySetInstanceUID==displaySetInstanceUID);
|
||||
if( !altDisplaySet ) {
|
||||
console.log("No display set found with", displaySetInstanceUID, "in", displaySets);
|
||||
return false;
|
||||
}
|
||||
const testValue = altDisplaySet[sameAttribute];
|
||||
return testValue===displaySet[sameAttribute];
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export default (study, extraData) => extraData?.displaySets?.map(ds => ds.SeriesDescription);
|
||||
@@ -0,0 +1,259 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
/**
|
||||
* This hanging protocol has multiple stages, which are enabled when
|
||||
* there are enough display sets with images to fill the stage, and
|
||||
* are passive when there is at least one display set.
|
||||
* Enabled display sets are navigated to by default, while passive ones
|
||||
* are navigated to manually using the ctrl+end keyboard shortcut.
|
||||
*/
|
||||
const hpMN: Types.HangingProtocol.Protocol = {
|
||||
hasUpdatedPriorsInformation: false,
|
||||
id: '@ohif/hp-extension.mn',
|
||||
description: 'Has various hanging protocol layouts for use in testing',
|
||||
name: '2x2',
|
||||
protocolMatchingRules: [
|
||||
{
|
||||
id: 'OneOrMoreSeries',
|
||||
weight: 1,
|
||||
attribute: 'numberOfDisplaySetsWithImages',
|
||||
constraint: {
|
||||
greaterThan: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
toolGroupIds: ['default'],
|
||||
displaySetSelectors: {
|
||||
defaultDisplaySetId: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
attribute: 'numImageFrames',
|
||||
constraint: {
|
||||
greaterThan: { value: 0 },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
defaultViewport: {
|
||||
viewportOptions: {
|
||||
viewportType: 'stack',
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'defaultDisplaySetId',
|
||||
matchedDisplaySetsIndex: -1,
|
||||
},
|
||||
],
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: '2x2',
|
||||
stageActivation: {
|
||||
enabled: {
|
||||
minViewportsMatched: 4,
|
||||
},
|
||||
},
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 2,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 1,
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 2,
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 3,
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// 3x1 stage
|
||||
{
|
||||
id: '3x1',
|
||||
// Obsolete settings:
|
||||
requiredViewports: 1,
|
||||
preferredViewports: 3,
|
||||
// New equivalent:
|
||||
stageActivation: {
|
||||
enabled: {
|
||||
minViewportsMatched: 3,
|
||||
},
|
||||
},
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 3,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'defaultDisplaySetId',
|
||||
reuseId: '0-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 1,
|
||||
id: 'defaultDisplaySetId',
|
||||
reuseId: '1-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 2,
|
||||
id: 'defaultDisplaySetId',
|
||||
reuseId: '0-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// A 2x1 stage
|
||||
{
|
||||
id: '2x1',
|
||||
requiredViewports: 1,
|
||||
preferredViewports: 2,
|
||||
stageActivation: {
|
||||
enabled: {
|
||||
minViewportsMatched: 2,
|
||||
},
|
||||
},
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 2,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 1,
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// A 1x1 stage - should be automatically activated if there is only 1 viewable instance
|
||||
{
|
||||
id: '1x1',
|
||||
requiredViewports: 1,
|
||||
preferredViewports: 1,
|
||||
stageActivation: {
|
||||
enabled: {
|
||||
minViewportsMatched: 1,
|
||||
},
|
||||
},
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 1,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'default',
|
||||
allowUnmatchedView: true,
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
matchedDisplaySetsIndex: 1,
|
||||
id: 'defaultDisplaySetId',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
numberOfPriorsReferenced: -1,
|
||||
};
|
||||
|
||||
export default hpMN;
|
||||
@@ -0,0 +1,17 @@
|
||||
import hpMN from './hpMN';
|
||||
|
||||
const hangingProtocols = [
|
||||
{
|
||||
id: '@ohif/hp-extension.mn',
|
||||
protocol: hpMN,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Registers a single study hanging protocol which can be referenced as
|
||||
* `@ohif/hp-exgtension.mn`, that has initial layouts which show images
|
||||
* only display sets, up to a 2x2 view.
|
||||
*/
|
||||
export default function getHangingProtocolModule() {
|
||||
return hangingProtocols;
|
||||
}
|
||||
@@ -1,17 +1,64 @@
|
||||
import { id } from './id';
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
import { id } from './id';
|
||||
|
||||
import getHangingProtocolModule from './hp';
|
||||
// import {setViewportZoomPan, storeViewportZoomPan } from './custom-viewport/setViewportZoomPan';
|
||||
import sameAs from './custom-attribute/sameAs';
|
||||
import numberOfDisplaySets from './custom-attribute/numberOfDisplaySets';
|
||||
import numberOfDisplaySetsWithImages from './custom-attribute/numberOfDisplaySetsWithImages';
|
||||
import maxNumImageFrames from './custom-attribute/maxNumImageFrames';
|
||||
import seriesDescriptionsFromDisplaySets from './custom-attribute/seriesDescriptionsFromDisplaySets';
|
||||
|
||||
/**
|
||||
*
|
||||
* The test extension provides additional behaviour for testing various
|
||||
* customizations and settings for OHIF.
|
||||
*/
|
||||
const testExtension: Types.Extensions.Extension = {
|
||||
/**
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id,
|
||||
preRegistration() {
|
||||
console.debug('hello from test-extension init.js');
|
||||
|
||||
/** Register additional behaviour:
|
||||
* * HP custom attribute seriesDescriptions to retrieve an array of all series descriptions
|
||||
* * HP custom attribute numberOfDisplaySets to retrieve the number of display sets
|
||||
* * HP custom attribute numberOfDisplaySetsWithImages to retrieve the number of display sets containing images
|
||||
* * HP custom attribute to return a boolean true, when the attribute sameAttribute has the same
|
||||
* value as another series description in an already matched display set selector named with the value
|
||||
* in `sameDisplaySetId`
|
||||
*/
|
||||
preRegistration: ({ servicesManager }: Types.Extensions.ExtensionParams) => {
|
||||
const { hangingProtocolService } = servicesManager.services;
|
||||
hangingProtocolService.addCustomAttribute(
|
||||
'seriesDescriptions',
|
||||
'Series Descriptions',
|
||||
seriesDescriptionsFromDisplaySets
|
||||
);
|
||||
hangingProtocolService.addCustomAttribute(
|
||||
'numberOfDisplaySets',
|
||||
'Number of displays sets',
|
||||
numberOfDisplaySets
|
||||
);
|
||||
hangingProtocolService.addCustomAttribute(
|
||||
'numberOfDisplaySetsWithImages',
|
||||
'Number of displays sets with images',
|
||||
numberOfDisplaySetsWithImages
|
||||
);
|
||||
hangingProtocolService.addCustomAttribute(
|
||||
'maxNumImageFrames',
|
||||
'Maximum of number of image frames',
|
||||
maxNumImageFrames
|
||||
);
|
||||
hangingProtocolService.addCustomAttribute(
|
||||
'sameAs',
|
||||
'Match an attribute in an existing display set',
|
||||
sameAs
|
||||
);
|
||||
},
|
||||
|
||||
/** Registers some additional hanging protocols. See hp/index.tsx for more details */
|
||||
getHangingProtocolModule,
|
||||
};
|
||||
|
||||
export default testExtension;
|
||||
Reference in new issue
Block a user