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);
|
||||
|
||||
// Set the default CINE settings
|
||||
var frameRate = 1000 / displaySet.images[0].frameTime;
|
||||
var multiframeMetadata = instance.multiframeMetadata;
|
||||
var cineToolData = {
|
||||
loop: OHIF.viewer.cine.loop,
|
||||
framesPerSecond: frameRate || OHIF.viewer.cine.framesPerSecond
|
||||
framesPerSecond: multiframeMetadata.averageFrameRate || OHIF.viewer.cine.framesPerSecond
|
||||
};
|
||||
cornerstoneTools.addToolState(element, 'playClip', cineToolData);
|
||||
|
||||
// Autoplay datasets that have framerates set
|
||||
if (frameRate) {
|
||||
if (multiframeMetadata.isMultiframeImage && multiframeMetadata.averageFrameRate > 0) {
|
||||
cornerstoneTools.playClip(element);
|
||||
}
|
||||
|
||||
@ -386,7 +386,6 @@ function setDisplaySet(data, displaySetInstanceUid, templateData) {
|
||||
var study = data.study;
|
||||
if (!study || !study.displaySets) {
|
||||
throw 'Study does not exist or has no display sets';
|
||||
return;
|
||||
}
|
||||
|
||||
study.displaySets.every(displaySet => {
|
||||
@ -401,7 +400,6 @@ function setDisplaySet(data, displaySetInstanceUid, templateData) {
|
||||
// If we didn't find anything, stop here
|
||||
if (!data.displaySet) {
|
||||
throw 'Display set not found in specified study!';
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, load pass the data object into loadSeriesIntoViewport
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import {parsingUtils} from './parsingUtils'
|
||||
|
||||
var metaDataLookup = {};
|
||||
|
||||
/**
|
||||
@ -102,6 +104,7 @@ updateMetaData = function(image) {
|
||||
imageMetaData.instance.frameIncrementPointer = imageMetaData.instance.frameIncrementPointer || image.data.string('x00280009');
|
||||
imageMetaData.instance.frameTime = imageMetaData.instance.frameTime || image.data.string('x00181063');
|
||||
imageMetaData.instance.frameTimeVector = imageMetaData.instance.frameTimeVector || image.data.string('x00181065');
|
||||
imageMetaData.instance.multiframeMetadata = getMultiframeModuleMetaData(image.data);
|
||||
|
||||
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
|
||||
* 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