Updating OHIF private hanging-protocol branch with Nucleus rebased version
This commit is contained in:
parent
5346f20329
commit
b9a3cf9da3
@ -1,5 +1,4 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { $ } from 'meteor/jquery';
|
|
||||||
import { _ } from 'meteor/underscore';
|
import { _ } from 'meteor/underscore';
|
||||||
// OHIF Modules
|
// OHIF Modules
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
@ -173,6 +172,8 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
* @param {Object} studyMedadataSource Instance of StudyMetadataSource (ohif-viewerbase) Object to get study metadata
|
* @param {Object} studyMedadataSource Instance of StudyMetadataSource (ohif-viewerbase) Object to get study metadata
|
||||||
*/
|
*/
|
||||||
constructor(LayoutManager, studies, relatedStudies, studyMetadataSource) {
|
constructor(LayoutManager, studies, relatedStudies, studyMetadataSource) {
|
||||||
|
OHIF.log.info('ProtocolEngine::constructor');
|
||||||
|
|
||||||
if (!(studyMetadataSource instanceof OHIF.viewerbase.StudyMetadataSource)) {
|
if (!(studyMetadataSource instanceof OHIF.viewerbase.StudyMetadataSource)) {
|
||||||
throw new OHIF.viewerbase.OHIFError('ProtocolEngine::constructor studyMetadataSource is not an instance of StudyMetadataSource');
|
throw new OHIF.viewerbase.OHIFError('ProtocolEngine::constructor studyMetadataSource is not an instance of StudyMetadataSource');
|
||||||
}
|
}
|
||||||
@ -207,19 +208,21 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
findMatchByStudy(study) {
|
findMatchByStudy(study) {
|
||||||
var matched = [];
|
OHIF.log.info('ProtocolEngine::findMatchByStudy');
|
||||||
|
|
||||||
|
const matched = [];
|
||||||
|
|
||||||
HP.ProtocolStore.getProtocol().forEach(protocol => {
|
HP.ProtocolStore.getProtocol().forEach(protocol => {
|
||||||
// Clone the protocol's protocolMatchingRules array
|
// Clone the protocol's protocolMatchingRules array
|
||||||
// We clone it so that we don't accidentally add the
|
// We clone it so that we don't accidentally add the
|
||||||
// numberOfPriorsReferenced rule to the Protocol itself.
|
// numberOfPriorsReferenced rule to the Protocol itself.
|
||||||
var rules = protocol.protocolMatchingRules.slice(0);
|
const rules = protocol.protocolMatchingRules.slice(0);
|
||||||
if (!rules) {
|
if (!rules) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
study.numberOfPriorsReferenced = this.getNumberOfAvailablePriors(study);
|
study.numberOfPriorsReferenced = this.getNumberOfAvailablePriors(study);
|
||||||
var rule = new HP.ProtocolMatchingRule('numberOfPriorsReferenced', {
|
const rule = new HP.ProtocolMatchingRule('numberOfPriorsReferenced', {
|
||||||
numericality: {
|
numericality: {
|
||||||
greaterThanOrEqualTo: protocol.numberOfPriorsReferenced
|
greaterThanOrEqualTo: protocol.numberOfPriorsReferenced
|
||||||
}
|
}
|
||||||
@ -227,7 +230,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
rules.push(rule);
|
rules.push(rule);
|
||||||
|
|
||||||
var matchedDetails = HP.match(study, rules);
|
const matchedDetails = HP.match(study, rules);
|
||||||
|
|
||||||
if (matchedDetails.score > 0) {
|
if (matchedDetails.score > 0) {
|
||||||
matched.push({
|
matched.push({
|
||||||
@ -238,7 +241,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!matched.length) {
|
if (!matched.length) {
|
||||||
var defaultProtocol = HP.ProtocolStore.getProtocol('defaultProtocol');
|
const defaultProtocol = HP.ProtocolStore.getProtocol('defaultProtocol');
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
score: 1,
|
score: 1,
|
||||||
@ -247,6 +250,9 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sortByScore(matched);
|
sortByScore(matched);
|
||||||
|
|
||||||
|
OHIF.log.info('ProtocolEngine::findMatchByStudy matched', matched);
|
||||||
|
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,21 +260,23 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
* Populates the MatchedProtocols Collection by running the matching procedure
|
* Populates the MatchedProtocols Collection by running the matching procedure
|
||||||
*/
|
*/
|
||||||
updateMatches() {
|
updateMatches() {
|
||||||
|
OHIF.log.info('ProtocolEngine::updateMatches');
|
||||||
|
|
||||||
// Clear all data from the MatchedProtocols Collection
|
// Clear all data from the MatchedProtocols Collection
|
||||||
MatchedProtocols.remove({});
|
MatchedProtocols.remove({});
|
||||||
|
|
||||||
// For each study, find the matching protocols
|
// For each study, find the matching protocols
|
||||||
this.studies.forEach(study => {
|
this.studies.forEach(study => {
|
||||||
var matched = this.findMatchByStudy(study);
|
const matched = this.findMatchByStudy(study);
|
||||||
|
|
||||||
// For each matched protocol, check if it is already in MatchedProtocols
|
// For each matched protocol, check if it is already in MatchedProtocols
|
||||||
matched.forEach(function(matchedDetail) {
|
matched.forEach(matchedDetail => {
|
||||||
var protocol = matchedDetail.protocol;
|
const protocol = matchedDetail.protocol;
|
||||||
if (!protocol) {
|
if (!protocol) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var protocolInCollection = MatchedProtocols.findOne({
|
const protocolInCollection = MatchedProtocols.findOne({
|
||||||
id: protocol.id
|
id: protocol.id
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -289,15 +297,18 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
this.updateMatches();
|
this.updateMatches();
|
||||||
|
|
||||||
// Retrieve the highest scoring Protocol
|
// Retrieve the highest scoring Protocol
|
||||||
var sorted = MatchedProtocols.find({}, {
|
const sorted = MatchedProtocols.find({}, {
|
||||||
sort: {
|
sort: {
|
||||||
score: -1
|
score: -1
|
||||||
},
|
},
|
||||||
limit: 1
|
limit: 1
|
||||||
}).fetch();
|
}).fetch();
|
||||||
|
|
||||||
// Return the highest scoring Protocol
|
// Highest scoring Protocol
|
||||||
return sorted[0].protocol;
|
const bestMatch = sorted[0].protocol;
|
||||||
|
|
||||||
|
OHIF.log.info('ProtocolEngine::getBestMatch bestMatch', bestMatch);
|
||||||
|
return bestMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -366,36 +377,34 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getRelatedStudies(options, sorting) {
|
|
||||||
HP.setGetRelatedStudies = getNucleusRelatedStudies();
|
|
||||||
HP.getRelatedStudies(options, sorting);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match images given a list of Studies and a Viewport's image matching reqs
|
// Match images given a list of Studies and a Viewport's image matching reqs
|
||||||
matchImages(viewport) {
|
matchImages(viewport) {
|
||||||
var studyMatchingRules = viewport.studyMatchingRules;
|
OHIF.log.info('ProtocolEngine::matchImages');
|
||||||
var seriesMatchingRules = viewport.seriesMatchingRules;
|
|
||||||
var instanceMatchingRules = viewport.imageMatchingRules;
|
|
||||||
|
|
||||||
var highestStudyMatchingScore = 0;
|
const studyMatchingRules = viewport.studyMatchingRules;
|
||||||
var highestSeriesMatchingScore = 0;
|
const seriesMatchingRules = viewport.seriesMatchingRules;
|
||||||
var highestImageMatchingScore = 0;
|
const instanceMatchingRules = viewport.imageMatchingRules;
|
||||||
var matchingScores = [];
|
const matchingScores = [];
|
||||||
var bestMatch;
|
const currentStudy = this.studies[0];
|
||||||
|
|
||||||
|
let highestStudyMatchingScore = 0;
|
||||||
|
let highestSeriesMatchingScore = 0;
|
||||||
|
let highestImageMatchingScore = 0;
|
||||||
|
let bestMatch;
|
||||||
|
|
||||||
var currentStudy = this.studies[0];
|
|
||||||
currentStudy.abstractPriorValue = 0;
|
currentStudy.abstractPriorValue = 0;
|
||||||
|
|
||||||
studyMatchingRules.forEach(rule => {
|
studyMatchingRules.forEach(rule => {
|
||||||
if (rule.attribute === 'abstractPriorValue') {
|
if (rule.attribute === 'abstractPriorValue') {
|
||||||
var validatorType = Object.keys(rule.constraint)[0];
|
const validatorType = Object.keys(rule.constraint)[0];
|
||||||
var validator = Object.keys(rule.constraint[validatorType])[0];
|
const validator = Object.keys(rule.constraint[validatorType])[0];
|
||||||
var abstractPriorValue = rule.constraint[validatorType][validator];
|
|
||||||
|
let abstractPriorValue = rule.constraint[validatorType][validator];
|
||||||
abstractPriorValue = parseInt(abstractPriorValue, 10);
|
abstractPriorValue = parseInt(abstractPriorValue, 10);
|
||||||
// TODO: Restrict or clarify validators for abstractPriorValue?
|
// TODO: Restrict or clarify validators for abstractPriorValue?
|
||||||
|
|
||||||
// @TODO replace for this.relatedStudies (TypeSafeCollection of StudyMetadatas)
|
// @TODO replace for this.relatedStudies (TypeSafeCollection of StudyMetadatas)
|
||||||
var studies = StudyListStudies.find({
|
const studies = StudyListStudies.find({
|
||||||
patientId: currentStudy.patientId,
|
patientId: currentStudy.patientId,
|
||||||
studyDate: {
|
studyDate: {
|
||||||
$lt: currentStudy.studyDate
|
$lt: currentStudy.studyDate
|
||||||
@ -409,11 +418,11 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
// TODO: Revisit this later: What about two studies with the same
|
// TODO: Revisit this later: What about two studies with the same
|
||||||
// study date?
|
// study date?
|
||||||
|
|
||||||
var priorStudy;
|
let priorStudy;
|
||||||
if (abstractPriorValue === -1) {
|
if (abstractPriorValue === -1) {
|
||||||
priorStudy = studies[studies.length - 1];
|
priorStudy = studies[studies.length - 1];
|
||||||
} else {
|
} else {
|
||||||
var studyIndex = Math.max(abstractPriorValue - 1, 0);
|
const studyIndex = Math.max(abstractPriorValue - 1, 0);
|
||||||
priorStudy = studies[studyIndex];
|
priorStudy = studies[studyIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +431,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @TypeSafeStudies
|
// @TypeSafeStudies
|
||||||
var alreadyLoaded = OHIF.viewer.Studies.findBy({
|
const alreadyLoaded = OHIF.viewer.Studies.findBy({
|
||||||
studyInstanceUid: priorStudy.studyInstanceUid
|
studyInstanceUid: priorStudy.studyInstanceUid
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -441,7 +450,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
// TODO: Add relative Date / time
|
// TODO: Add relative Date / time
|
||||||
});
|
});
|
||||||
|
|
||||||
this.studies.forEach(function(study) {
|
this.studies.forEach(study => {
|
||||||
const studyMatchDetails = HP.match(study, studyMatchingRules);
|
const studyMatchDetails = HP.match(study, studyMatchingRules);
|
||||||
if ((studyMatchingRules.length && !studyMatchDetails.score) ||
|
if ((studyMatchingRules.length && !studyMatchDetails.score) ||
|
||||||
studyMatchDetails.score < highestStudyMatchingScore) {
|
studyMatchDetails.score < highestStudyMatchingScore) {
|
||||||
@ -450,7 +459,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
highestStudyMatchingScore = studyMatchDetails.score;
|
highestStudyMatchingScore = studyMatchDetails.score;
|
||||||
|
|
||||||
study.forEachSeries(function(series) {
|
study.forEachSeries(series => {
|
||||||
const seriesMatchDetails = HP.match(series, seriesMatchingRules);
|
const seriesMatchDetails = HP.match(series, seriesMatchingRules);
|
||||||
if ((seriesMatchingRules.length && !seriesMatchDetails.score) ||
|
if ((seriesMatchingRules.length && !seriesMatchDetails.score) ||
|
||||||
seriesMatchDetails.score < highestSeriesMatchingScore) {
|
seriesMatchDetails.score < highestSeriesMatchingScore) {
|
||||||
@ -459,7 +468,7 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
highestSeriesMatchingScore = seriesMatchDetails.score;
|
highestSeriesMatchingScore = seriesMatchDetails.score;
|
||||||
|
|
||||||
series.forEachInstance(function(instance, index) {
|
series.forEachInstance((instance, index) => {
|
||||||
// This tests to make sure there is actually image data in this instance
|
// This tests to make sure there is actually image data in this instance
|
||||||
// TODO: Change this when we add PDF and MPEG support
|
// TODO: Change this when we add PDF and MPEG support
|
||||||
// See https://ohiforg.atlassian.net/browse/LT-227
|
// See https://ohiforg.atlassian.net/browse/LT-227
|
||||||
@ -485,11 +494,12 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
matchDetails.failed = matchDetails.failed.concat(studyMatchDetails.details.failed);
|
matchDetails.failed = matchDetails.failed.concat(studyMatchDetails.details.failed);
|
||||||
|
|
||||||
const totalMatchScore = instanceMatchDetails.score + seriesMatchDetails.score + studyMatchDetails.score;
|
const totalMatchScore = instanceMatchDetails.score + seriesMatchDetails.score + studyMatchDetails.score;
|
||||||
|
const currentSOPInstanceUID = instance.getSOPInstanceUID();
|
||||||
|
|
||||||
const imageDetails = {
|
const imageDetails = {
|
||||||
studyInstanceUid: study.getStudyInstanceUID(),
|
studyInstanceUid: study.getStudyInstanceUID(),
|
||||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
sopInstanceUid: currentSOPInstanceUID,
|
||||||
currentImageIdIndex: index,
|
currentImageIdIndex: index,
|
||||||
matchingScore: totalMatchScore,
|
matchingScore: totalMatchScore,
|
||||||
matchDetails: matchDetails,
|
matchDetails: matchDetails,
|
||||||
@ -502,7 +512,6 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Find the displaySet
|
// Find the displaySet
|
||||||
const currentSOPInstanceUID = instance.getSOPInstanceUID();
|
|
||||||
const displaySet = study.findDisplaySet(displaySet => displaySet.images.find(image => image.getSOPInstanceUID() === currentSOPInstanceUID));
|
const displaySet = study.findDisplaySet(displaySet => displaySet.images.find(image => image.getSOPInstanceUID() === currentSOPInstanceUID));
|
||||||
|
|
||||||
// If the instance was found, set the displaySet ID
|
// If the instance was found, set the displaySet ID
|
||||||
@ -535,6 +544,8 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
});
|
});
|
||||||
matchingScores.sort((a, b) => sortingFunction(a.sortingInfo, b.sortingInfo));
|
matchingScores.sort((a, b) => sortingFunction(a.sortingInfo, b.sortingInfo));
|
||||||
|
|
||||||
|
OHIF.log.info('ProtocolEngine::matchImages bestMatch', bestMatch);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bestMatch: bestMatch,
|
bestMatch: bestMatch,
|
||||||
matchingScores: matchingScores
|
matchingScores: matchingScores
|
||||||
@ -551,13 +562,15 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
* @param viewportIndex
|
* @param viewportIndex
|
||||||
*/
|
*/
|
||||||
updateViewports(viewportIndex) {
|
updateViewports(viewportIndex) {
|
||||||
|
OHIF.log.info(`ProtocolEngine::updateViewports viewportIndex: ${viewportIndex}`);
|
||||||
|
|
||||||
// Make sure we have an active protocol with a non-empty array of display sets
|
// Make sure we have an active protocol with a non-empty array of display sets
|
||||||
if (!this.protocol || !this.protocol.stages || !this.protocol.stages.length) {
|
if (!this.protocol || !this.protocol.stages || !this.protocol.stages.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current display set in the display set sequence
|
// Retrieve the current display set in the display set sequence
|
||||||
var stageModel = this.getCurrentStageModel();
|
const stageModel = this.getCurrentStageModel();
|
||||||
|
|
||||||
// If the current display set does not fulfill the requirements to be displayed,
|
// If the current display set does not fulfill the requirements to be displayed,
|
||||||
// stop here.
|
// stop here.
|
||||||
@ -570,20 +583,20 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
// Retrieve the layoutTemplate associated with the current display set's viewport structure
|
// Retrieve the layoutTemplate associated with the current display set's viewport structure
|
||||||
// If no such template name exists, stop here.
|
// If no such template name exists, stop here.
|
||||||
var layoutTemplateName = stageModel.viewportStructure.getLayoutTemplateName();
|
const layoutTemplateName = stageModel.viewportStructure.getLayoutTemplateName();
|
||||||
if (!layoutTemplateName) {
|
if (!layoutTemplateName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the properties associated with the current display set's viewport structure template
|
// Retrieve the properties associated with the current display set's viewport structure template
|
||||||
// If no such layout properties exist, stop here.
|
// If no such layout properties exist, stop here.
|
||||||
var layoutProps = stageModel.viewportStructure.properties;
|
const layoutProps = stageModel.viewportStructure.properties;
|
||||||
if (!layoutProps) {
|
if (!layoutProps) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an empty array to store the output viewportData
|
// Create an empty array to store the output viewportData
|
||||||
var viewportData = [];
|
const viewportData = [];
|
||||||
|
|
||||||
// Empty the matchDetails associated with the ProtocolEngine.
|
// Empty the matchDetails associated with the ProtocolEngine.
|
||||||
// This will be used to store the pass/fail details and score
|
// This will be used to store the pass/fail details and score
|
||||||
@ -592,14 +605,18 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
// Loop through each viewport
|
// Loop through each viewport
|
||||||
stageModel.viewports.forEach((viewport, viewportIndex) => {
|
stageModel.viewports.forEach((viewport, viewportIndex) => {
|
||||||
var details = this.matchImages(viewport);
|
const details = this.matchImages(viewport);
|
||||||
|
|
||||||
this.matchDetails[viewportIndex] = details;
|
this.matchDetails[viewportIndex] = details;
|
||||||
|
|
||||||
// Convert any YES/NO values into true/false for Cornerstone
|
// Convert any YES/NO values into true/false for Cornerstone
|
||||||
var cornerstoneViewportParams = {};
|
const cornerstoneViewportParams = {};
|
||||||
Object.keys(viewport.viewportSettings).forEach(function(key) {
|
|
||||||
var value = viewport.viewportSettings[key];
|
// Cache viewportSettings keys
|
||||||
|
const viewportSettingsKeys = Object.keys(viewport.viewportSettings);
|
||||||
|
|
||||||
|
viewportSettingsKeys.forEach(key => {
|
||||||
|
let value = viewport.viewportSettings[key];
|
||||||
if (value === 'YES') {
|
if (value === 'YES') {
|
||||||
value = true;
|
value = true;
|
||||||
} else if (value === 'NO') {
|
} else if (value === 'NO') {
|
||||||
@ -611,14 +628,15 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
|
|
||||||
// imageViewerViewports occasionally needs relevant layout data in order to set
|
// imageViewerViewports occasionally needs relevant layout data in order to set
|
||||||
// the element style of the viewport in question
|
// the element style of the viewport in question
|
||||||
var currentViewportData = $.extend({
|
const currentViewportData = {
|
||||||
viewportIndex: viewportIndex,
|
viewportIndex,
|
||||||
viewport: cornerstoneViewportParams
|
viewport: cornerstoneViewportParams,
|
||||||
}, layoutProps);
|
...layoutProps
|
||||||
|
};
|
||||||
|
|
||||||
var customSettings = [];
|
const customSettings = [];
|
||||||
Object.keys(viewport.viewportSettings).forEach(id => {
|
viewportSettingsKeys.forEach(id => {
|
||||||
var setting = HP.CustomViewportSettings[id];
|
const setting = HP.CustomViewportSettings[id];
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -629,13 +647,13 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
currentViewportData.renderedCallback = function(element) {
|
currentViewportData.renderedCallback = element => {
|
||||||
//console.log('renderedCallback for ' + element.id);
|
//console.log('renderedCallback for ' + element.id);
|
||||||
customSettings.forEach(function(customSetting) {
|
customSettings.forEach(customSetting => {
|
||||||
console.log('Applying custom setting: ' + customSetting.id);
|
OHIF.log.info(`ProtocolEngine::currentViewportData.renderedCallback Applying custom setting: ${customSetting.id}`);
|
||||||
console.log('with value: ' + customSetting.value);
|
OHIF.log.info(`ProtocolEngine::currentViewportData.renderedCallback with value: ${customSetting.value}`);
|
||||||
|
|
||||||
var setting = HP.CustomViewportSettings[customSetting.id];
|
const setting = HP.CustomViewportSettings[customSetting.id];
|
||||||
setting.callback(element, customSetting.value);
|
setting.callback(element, customSetting.value);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -686,6 +704,9 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
* @param updateViewports
|
* @param updateViewports
|
||||||
*/
|
*/
|
||||||
setHangingProtocol(newProtocol, updateViewports=true) {
|
setHangingProtocol(newProtocol, updateViewports=true) {
|
||||||
|
OHIF.log.info('ProtocolEngine::setHangingProtocol newProtocol', newProtocol);
|
||||||
|
OHIF.log.info(`ProtocolEngine::setHangingProtocol updateViewports = ${updateViewports}`);
|
||||||
|
|
||||||
// Reset the array of newStageIds
|
// Reset the array of newStageIds
|
||||||
this.newStageIds = [];
|
this.newStageIds = [];
|
||||||
|
|
||||||
@ -726,6 +747,8 @@ HP.ProtocolEngine = class ProtocolEngine {
|
|||||||
* @param stage An integer value specifying the index of the desired Stage
|
* @param stage An integer value specifying the index of the desired Stage
|
||||||
*/
|
*/
|
||||||
setCurrentProtocolStage(stage) {
|
setCurrentProtocolStage(stage) {
|
||||||
|
OHIF.log.info(`ProtocolEngine::setCurrentProtocolStage stage = ${stage}`);
|
||||||
|
|
||||||
if (!this.protocol || !this.protocol.stages || !this.protocol.stages.length) {
|
if (!this.protocol || !this.protocol.stages || !this.protocol.stages.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export class ImageSet {
|
|||||||
constructor(images) {
|
constructor(images) {
|
||||||
|
|
||||||
if (Array.isArray(images) !== true) {
|
if (Array.isArray(images) !== true) {
|
||||||
throw new OHIFError('ImageSet expects an array of images...');
|
throw new OHIFError('ImageSet expects an array of images');
|
||||||
}
|
}
|
||||||
|
|
||||||
// @property "images"
|
// @property "images"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Metadata } from './Metadata';
|
import { Metadata } from './Metadata';
|
||||||
import { SeriesMetadata } from './SeriesMetadata';
|
import { SeriesMetadata } from './SeriesMetadata';
|
||||||
import { ImageSet } from '../ImageSet';
|
import { ImageSet } from '../ImageSet';
|
||||||
|
import { OHIFError } from '../OHIFError';
|
||||||
|
|
||||||
export class StudyMetadata extends Metadata {
|
export class StudyMetadata extends Metadata {
|
||||||
|
|
||||||
@ -122,6 +123,14 @@ export class StudyMetadata extends Metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the number of display sets within the current study.
|
||||||
|
* @returns {number} The number of display sets in the current study.
|
||||||
|
*/
|
||||||
|
getDisplaySetCount() {
|
||||||
|
return this._displaySets.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the StudyInstanceUID of the current study.
|
* Returns the StudyInstanceUID of the current study.
|
||||||
*/
|
*/
|
||||||
@ -129,6 +138,14 @@ export class StudyMetadata extends Metadata {
|
|||||||
return this._studyInstanceUID;
|
return this._studyInstanceUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for series
|
||||||
|
* @return {Array} Array of SeriesMetadata object
|
||||||
|
*/
|
||||||
|
getSeries() {
|
||||||
|
return this._series.slice();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a series to the current study.
|
* Append a series to the current study.
|
||||||
* @param {SeriesMetadata} series The series to be added to the current study.
|
* @param {SeriesMetadata} series The series to be added to the current study.
|
||||||
@ -213,6 +230,58 @@ export class StudyMetadata extends Metadata {
|
|||||||
return this._series.indexOf(series);
|
return this._series.indexOf(series);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It sorts the series based on display sets order. Each series must be an instance
|
||||||
|
* of SeriesMetadata and each display sets must be an instance of ImageSet.
|
||||||
|
* Both array must have the same length, otherwise it throws an error.
|
||||||
|
* Useful example of usage:
|
||||||
|
* Study data provided by backend does not sort series at all and client-side
|
||||||
|
* needs series sorted by the same criteria used for sorting display sets.
|
||||||
|
*/
|
||||||
|
sortSeriesByDisplaySets() {
|
||||||
|
// Check if the study is multiframe. If it is,
|
||||||
|
const firstInstance = this.getFirstInstance();
|
||||||
|
const isMultiframe = firstInstance.getRawValue('x00280008') > 1;
|
||||||
|
|
||||||
|
// @TODO: Check if is necessary to do a similar check for multiframe studies
|
||||||
|
// Check if both arrays have same length in case of non-multiframe studies
|
||||||
|
if (!isMultiframe && this.getSeriesCount() !== this.getDisplaySetCount()) {
|
||||||
|
throw new OHIFError('StudyMetadata::sortSeriesByDisplaySets series count and display set count does not match');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object for mapping display sets' index by seriesInstanceUid
|
||||||
|
const displaySetsMapping = {};
|
||||||
|
|
||||||
|
// Loop through each display set to create the mapping
|
||||||
|
this.forEachDisplaySet( (displaySet, index) => {
|
||||||
|
|
||||||
|
if (!(displaySet instanceof ImageSet)) {
|
||||||
|
throw new OHIFError(`StudyMetadata::sortSeriesByDisplaySets display set at index ${index} is not an instance of ImageSet`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case of multiframe studies, just get the first index occurence
|
||||||
|
if (displaySetsMapping[displaySet.seriesInstanceUid] === void 0) {
|
||||||
|
displaySetsMapping[displaySet.seriesInstanceUid] = index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clone of actual series
|
||||||
|
const actualSeries = this.getSeries();
|
||||||
|
|
||||||
|
actualSeries.forEach( (series, index) => {
|
||||||
|
|
||||||
|
if (!(series instanceof SeriesMetadata)) {
|
||||||
|
throw new OHIFError(`StudyMetadata::sortSeriesByDisplaySets series at index ${index} is not an instance of SeriesMetadata`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the new series index
|
||||||
|
const seriesIndex = displaySetsMapping[series.getSeriesInstanceUID()];
|
||||||
|
|
||||||
|
// Update the series object with the new series position
|
||||||
|
this._series[seriesIndex] = series;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares the current study instance with another one.
|
* Compares the current study instance with another one.
|
||||||
* @param {StudyMetadata} study An instance of the StudyMetadata class.
|
* @param {StudyMetadata} study An instance of the StudyMetadata class.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user