OHIF-20 Moving multi-frame related functionality to metaDataProvider / Created new library with parsing utilities.
This commit is contained in:
parent
952f4d1a60
commit
1122594d2b
@ -213,15 +213,15 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
|||||||
cornerstoneTools.addToolState(element, 'stack', stack);
|
cornerstoneTools.addToolState(element, 'stack', stack);
|
||||||
|
|
||||||
// Set the default CINE settings
|
// Set the default CINE settings
|
||||||
var frameRate = 1000 / displaySet.images[0].frameTime;
|
var multiframeMetadata = instance.multiframeMetadata;
|
||||||
var cineToolData = {
|
var cineToolData = {
|
||||||
loop: OHIF.viewer.cine.loop,
|
loop: OHIF.viewer.cine.loop,
|
||||||
framesPerSecond: frameRate || OHIF.viewer.cine.framesPerSecond
|
framesPerSecond: multiframeMetadata.averageFrameRate || OHIF.viewer.cine.framesPerSecond
|
||||||
};
|
};
|
||||||
cornerstoneTools.addToolState(element, 'playClip', cineToolData);
|
cornerstoneTools.addToolState(element, 'playClip', cineToolData);
|
||||||
|
|
||||||
// Autoplay datasets that have framerates set
|
// Autoplay datasets that have framerates set
|
||||||
if (frameRate) {
|
if (multiframeMetadata.isMultiframeImage && multiframeMetadata.averageFrameRate > 0) {
|
||||||
cornerstoneTools.playClip(element);
|
cornerstoneTools.playClip(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +386,6 @@ function setDisplaySet(data, displaySetInstanceUid, templateData) {
|
|||||||
var study = data.study;
|
var study = data.study;
|
||||||
if (!study || !study.displaySets) {
|
if (!study || !study.displaySets) {
|
||||||
throw 'Study does not exist or has no display sets';
|
throw 'Study does not exist or has no display sets';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
study.displaySets.every(displaySet => {
|
study.displaySets.every(displaySet => {
|
||||||
@ -401,7 +400,6 @@ function setDisplaySet(data, displaySetInstanceUid, templateData) {
|
|||||||
// If we didn't find anything, stop here
|
// If we didn't find anything, stop here
|
||||||
if (!data.displaySet) {
|
if (!data.displaySet) {
|
||||||
throw 'Display set not found in specified study!';
|
throw 'Display set not found in specified study!';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, load pass the data object into loadSeriesIntoViewport
|
// Otherwise, load pass the data object into loadSeriesIntoViewport
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import {parsingUtils} from './parsingUtils'
|
||||||
|
|
||||||
var metaDataLookup = {};
|
var metaDataLookup = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,6 +104,7 @@ updateMetaData = function(image) {
|
|||||||
imageMetaData.instance.frameIncrementPointer = imageMetaData.instance.frameIncrementPointer || image.data.string('x00280009');
|
imageMetaData.instance.frameIncrementPointer = imageMetaData.instance.frameIncrementPointer || image.data.string('x00280009');
|
||||||
imageMetaData.instance.frameTime = imageMetaData.instance.frameTime || image.data.string('x00181063');
|
imageMetaData.instance.frameTime = imageMetaData.instance.frameTime || image.data.string('x00181063');
|
||||||
imageMetaData.instance.frameTimeVector = imageMetaData.instance.frameTimeVector || image.data.string('x00181065');
|
imageMetaData.instance.frameTimeVector = imageMetaData.instance.frameTimeVector || image.data.string('x00181065');
|
||||||
|
imageMetaData.instance.multiframeMetadata = getMultiframeModuleMetaData(image.data);
|
||||||
|
|
||||||
imageMetaData.imagePlane = imageMetaData.imagePlane || getImagePlane(imageMetaData.instance);
|
imageMetaData.imagePlane = imageMetaData.imagePlane || getImagePlane(imageMetaData.instance);
|
||||||
};
|
};
|
||||||
@ -150,6 +153,69 @@ function getImagePlane(instance) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function extracts miltiframe information from a dicomParser.DataSet object.
|
||||||
|
*
|
||||||
|
* @param dataSet {Object} An instance of dicomParser.DataSet object where multiframe information can be found.
|
||||||
|
* @return {Object} An object containing multiframe image metadata (frameIncrementPointer, frameTime, frameTimeVector, etc).
|
||||||
|
*/
|
||||||
|
getMultiframeModuleMetaData = function(dataSet) {
|
||||||
|
|
||||||
|
var numberOfFrames,
|
||||||
|
frameIncrementPointer,
|
||||||
|
frameTime,
|
||||||
|
frameTimeVector,
|
||||||
|
imageInfo = {
|
||||||
|
isMultiframeImage: false,
|
||||||
|
frameIncrementPointer: null,
|
||||||
|
numberOfFrames: 0,
|
||||||
|
frameTime: 0,
|
||||||
|
frameTimeVector: null,
|
||||||
|
averageFrameRate: 0 // backwards compatibility only... it might be useless in the future
|
||||||
|
};
|
||||||
|
|
||||||
|
if (parsingUtils.isValidDataSet(dataSet)) {
|
||||||
|
|
||||||
|
// (0028,0008) = Number of Frames
|
||||||
|
numberOfFrames = dataSet.intString('x00280008', -1);
|
||||||
|
if (numberOfFrames > 0) {
|
||||||
|
|
||||||
|
// set multi-frame image indicator
|
||||||
|
imageInfo.isMultiframeImage = true;
|
||||||
|
imageInfo.numberOfFrames = numberOfFrames;
|
||||||
|
|
||||||
|
// (0028,0009) = Frame Increment Pointer
|
||||||
|
frameIncrementPointer = parsingUtils.attributeTag(dataSet, 'x00280009') || '';
|
||||||
|
|
||||||
|
if (frameIncrementPointer === 'x00181065') {
|
||||||
|
// Frame Increment Pointer points to Frame Time Vector (0018,1065) field
|
||||||
|
frameTimeVector = parsingUtils.floatArray(dataSet, 'x00181065');
|
||||||
|
if (frameTimeVector instanceof Array && frameTimeVector.length > 0) {
|
||||||
|
imageInfo.frameIncrementPointer = 'frameTimeVector';
|
||||||
|
imageInfo.frameTimeVector = frameTimeVector;
|
||||||
|
frameTime = frameTimeVector.reduce((a, b) => a + b) / frameTimeVector.length;
|
||||||
|
imageInfo.averageFrameRate = 1000 / frameTime;
|
||||||
|
}
|
||||||
|
} else if (frameIncrementPointer === 'x00181063' || frameIncrementPointer === '') {
|
||||||
|
// Frame Increment Pointer points to Frame Time (0018,1063) field or is not defined (for addtional flexibility).
|
||||||
|
// Yet another value is possible for this field (5200,9230 for Multi-frame Functional Groups)
|
||||||
|
// but that case is currently not supported.
|
||||||
|
frameTime = dataSet.floatString('x00181063', -1);
|
||||||
|
if (frameTime > 0) {
|
||||||
|
imageInfo.frameIncrementPointer = 'frameTime';
|
||||||
|
imageInfo.frameTime = frameTime;
|
||||||
|
imageInfo.averageFrameRate = 1000 / frameTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageInfo;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up metaData for Cornerstone Tools given a specified type and imageId
|
* Looks up metaData for Cornerstone Tools given a specified type and imageId
|
||||||
* A type may be, e.g. 'study', or 'patient', or 'imagePlane'. These types
|
* A type may be, e.g. 'study', or 'patient', or 'imagePlane'. These types
|
||||||
|
|||||||
41
Packages/viewerbase/lib/parsingUtils.js
Normal file
41
Packages/viewerbase/lib/parsingUtils.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
import {dicomParser} from 'meteor/cornerstone';
|
||||||
|
|
||||||
|
export const parsingUtils = {
|
||||||
|
isValidDataSet: function(data) {
|
||||||
|
return (data instanceof dicomParser.DataSet);
|
||||||
|
},
|
||||||
|
attributeTag: function(data, tag) {
|
||||||
|
if (this.isValidDataSet(data) && tag in data.elements) {
|
||||||
|
let element = data.elements[tag];
|
||||||
|
if (element && element.length === 4) {
|
||||||
|
let parser = data.byteArrayParser.readUint16,
|
||||||
|
bytes = data.byteArray,
|
||||||
|
offset = element.dataOffset;
|
||||||
|
return 'x' + ('00000000' + (parser(bytes, offset) * 256 * 256 + parser(bytes, offset + 2)).toString(16)).substr(-8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
multiValue: function(data, tag, parser) {
|
||||||
|
if (this.isValidDataSet(data) && tag in data.elements) {
|
||||||
|
let element = data.elements[tag];
|
||||||
|
if (element && element.length > 0) {
|
||||||
|
let string = dicomParser.readFixedString(data.byteArray, element.dataOffset, element.length);
|
||||||
|
if (typeof string === 'string' && string.length > 0) {
|
||||||
|
if (typeof parser !== 'function') {
|
||||||
|
parser = null;
|
||||||
|
}
|
||||||
|
return string.split('\\').map(function(value) {
|
||||||
|
value = value.trim();
|
||||||
|
return parser !== null ? parser(value) : value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
floatArray: function(data, tag) {
|
||||||
|
return this.multiValue(data, tag, parseFloat);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user