Moving Hanging Protocols updates back to the viewers

This commit is contained in:
Eloízio Salgado committed 2017-03-02 10:18:11 -03:00
1 parent e10453b919
commit bec8f21c0a
19 files changed
+1626 -183

No files matched your search

@@ -1,14 +1,21 @@
import { Metadata } from './Metadata';
import { OHIFError } from '../OHIFError';
/**
* ATTENTION! This class should never depend on StudyMetadata or SeriesMetadata classes as this could
* possibly cause circular dependency issues.
*/
const UNDEFINED = 'undefined';
const NUMBER = 'number';
const STRING = 'string';
const STUDY_INSTANCE_UID = 'x0020000d';
const SERIES_INSTANCE_UID = 'x0020000e';
export class InstanceMetadata extends Metadata {
constructor(data) {
super(data);
constructor(data, uid) {
super(data, uid);
// Initialize Private Properties
Object.defineProperties(this, {
_sopInstanceUID: {
@@ -60,6 +67,20 @@ export class InstanceMetadata extends Metadata {
* Public Methods
*/
/**
* Returns the StudyInstanceUID of the current instance. This method is basically a shorthand the full "getTagValue" method call.
*/
getStudyInstanceUID() {
return this.getTagValue(STUDY_INSTANCE_UID, null);
}
/**
* Returns the SeriesInstanceUID of the current instance. This method is basically a shorthand the full "getTagValue" method call.
*/
getSeriesInstanceUID() {
return this.getTagValue(SERIES_INSTANCE_UID, null);
}
/**
* Returns the SOPInstanceUID of the current instance.
*/
@@ -69,7 +90,7 @@ export class InstanceMetadata extends Metadata {
// @TODO: Improve this... (E.g.: blob data)
getStringValue(tagOrProperty, index, defaultValue) {
let value = this.getRawValue(tagOrProperty, defaultValue);
let value = this.getTagValue(tagOrProperty, defaultValue);
if (typeof value !== STRING && typeof value !== UNDEFINED) {
value = value.toString();
@@ -80,7 +101,7 @@ export class InstanceMetadata extends Metadata {
// @TODO: Improve this... (E.g.: blob data)
getFloatValue(tagOrProperty, index, defaultValue) {
let value = this.getRawValue(tagOrProperty, defaultValue);
let value = this.getTagValue(tagOrProperty, defaultValue);
value = InstanceMetadata.getIndexedValue(value, index, defaultValue);
if(value instanceof Array) {
@@ -96,7 +117,7 @@ export class InstanceMetadata extends Metadata {
// @TODO: Improve this... (E.g.: blob data)
getIntValue(tagOrProperty, index, defaultValue) {
let value = this.getRawValue(tagOrProperty, defaultValue);
let value = this.getTagValue(tagOrProperty, defaultValue);
value = InstanceMetadata.getIndexedValue(value, index, defaultValue);
if(value instanceof Array) {
@@ -111,13 +132,20 @@ export class InstanceMetadata extends Metadata {
}
/**
*
* @deprecated Please use getTagValue instead.
*/
getRawValue(tagOrProperty, defaultValue) {
return this.getTagValue(tagOrProperty, defaultValue);
}
/**
* This function should be overriden by specialized classes in order to allow client libraries or viewers to take advantage of the Study Metadata API.
*/
getTagValue(tagOrProperty, defaultValue) {
/**
* Please override this method on a specialized class.
*/
throw new OHIFError('InstanceMetadata::getRawValue is not overriden. Please, override it in a specialized class. See OHIFInstanceMetadata for example');
throw new OHIFError('InstanceMetadata::getTagValue is not overriden. Please, override it in a specialized class. See OHIFInstanceMetadata for example');
}
/**
@@ -8,13 +8,17 @@ const NUMBER = 'number';
const FUNCTION = 'function';
const OBJECT = 'object';
/**
* Class Definition
*/
export class Metadata {
/**
* Constructor and Instance Methods
*/
constructor(data) {
constructor(data, uid) {
// Define the main "_data" private property as an immutable property.
// IMPORTANT: This property can only be set during instance construction.
Object.defineProperty(this, '_data', {
@@ -24,7 +28,16 @@ export class Metadata {
value: data
});
// Define "_custom" properties as an immutable property
// Define the main "_uid" private property as an immutable property.
// IMPORTANT: This property can only be set during instance construction.
Object.defineProperty(this, '_uid', {
configurable: false,
enumerable: false,
writable: false,
value: uid
});
// Define "_custom" properties as an immutable property.
// IMPORTANT: This property can only be set during instance construction.
Object.defineProperty(this, '_custom', {
configurable: false,
@@ -47,6 +60,13 @@ export class Metadata {
return propertyValue;
}
/**
* Get unique object ID
*/
getObjectID() {
return this._uid;
}
/**
* Set custom attribute value
* @param {String} attribute Custom attribute name
@@ -74,6 +94,20 @@ export class Metadata {
return attribute in this._custom;
}
/**
* Set custom attributes in batch mode.
* @param {Object} attributeMap An object whose own properties will be used as custom attributes.
*/
setCustomAttributes(attributeMap) {
const _hasOwn = Object.prototype.hasOwnProperty;
const _custom = this._custom;
for (let attribute in attributeMap) {
if (_hasOwn.call(attributeMap, attribute)) {
_custom[attribute] = attributeMap[attribute];
}
}
}
/**
* Static Methods
*/
@@ -3,8 +3,8 @@ import { InstanceMetadata } from './InstanceMetadata';
export class SeriesMetadata extends Metadata {
constructor(data) {
super(data);
constructor(data, uid) {
super(data, uid);
// Initialize Private Properties
Object.defineProperties(this, {
_seriesInstanceUID: {
@@ -18,6 +18,12 @@ export class SeriesMetadata extends Metadata {
enumerable: false,
writable: false,
value: []
},
_firstInstance: {
configurable: false,
enumerable: false,
writable: true,
value: null
}
});
// Initialize Public Properties
@@ -77,6 +83,23 @@ export class SeriesMetadata extends Metadata {
return result;
}
/**
* Get the first instance of the current series retaining a consistent result across multiple calls.
* @return {InstanceMetadata} An instance of the InstanceMetadata class or null if it does not exist.
*/
getFirstInstance() {
let instance = this._firstInstance;
if (!(instance instanceof InstanceMetadata)) {
instance = null;
const found = this.getInstanceByIndex(0);
if (found instanceof InstanceMetadata) {
this._firstInstance = found;
instance = found;
}
}
return instance;
}
/**
* Find an instance by index.
* @param {number} index An integer representing a list index.
@@ -1,12 +1,13 @@
import { Metadata } from './Metadata';
import { SeriesMetadata } from './SeriesMetadata';
import { InstanceMetadata } from './InstanceMetadata';
import { ImageSet } from '../ImageSet';
import { OHIFError } from '../OHIFError';
export class StudyMetadata extends Metadata {
constructor(data) {
super(data);
constructor(data, uid) {
super(data, uid);
// Initialize Private Properties
Object.defineProperties(this, {
_studyInstanceUID: {
@@ -26,6 +27,18 @@ export class StudyMetadata extends Metadata {
enumerable: false,
writable: false,
value: []
},
_firstSeries: {
configurable: false,
enumerable: false,
writable: true,
value: null
},
_firstInstance: {
configurable: false,
enumerable: false,
writable: true,
value: null
}
});
// Initialize Public Properties
@@ -232,23 +245,13 @@ export class StudyMetadata extends Metadata {
/**
* 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.
* of SeriesMetadata and each display sets must be an instance of ImageSet.
* 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 = {};
@@ -299,18 +302,40 @@ export class StudyMetadata extends Metadata {
}
/**
* Get first instance of the first series
* @return {InstanceMetadata} InstanceMetadata class object or undefined if it doenst exist
* Get the first series of the current study retaining a consistent result across multiple calls.
* @return {SeriesMetadata} An instance of the SeriesMetadata class or null if it does not exist.
*/
getFirstSeries() {
let series = this._firstSeries;
if (!(series instanceof SeriesMetadata)) {
series = null;
const found = this.getSeriesByIndex(0);
if (found instanceof SeriesMetadata) {
this._firstSeries = found;
series = found;
}
}
return series;
}
/**
* Get the first instance of the current study retaining a consistent result across multiple calls.
* @return {InstanceMetadata} An instance of the InstanceMetadata class or null if it does not exist.
*/
getFirstInstance() {
let firstInstance;
const firstSeries = this.getSeriesByIndex(0);
if (firstSeries) {
firstInstance = firstSeries.getInstanceByIndex(0);
let instance = this._firstInstance;
if (!(instance instanceof InstanceMetadata)) {
instance = null;
const firstSeries = this.getFirstSeries();
if (firstSeries instanceof SeriesMetadata) {
const found = firstSeries.getFirstInstance();
if (found instanceof InstanceMetadata) {
this._firstInstance = found;
instance = found;
}
}
}
return firstInstance;
return instance;
}
}
@@ -1,26 +1,24 @@
import { Metadata } from './Metadata';
import { OHIFError } from '../OHIFError';
import { DICOMTagDescriptions } from '../../DICOMTagDescriptions';
const StudyInstanceUID = 'x0020000d';
/**
* Constants
*/
export class StudySummary {
const STUDY_INSTANCE_UID = 'x0020000d';
constructor(tagMap, propertyMap) {
/**
* Class Definition
*/
// Define the main immutable "_data" private property.
Object.defineProperties(this, {
_tags: {
configurable: false,
enumerable: false,
writable: false,
value: Object.create(null)
},
_properties: {
configurable: false,
enumerable: false,
writable: false,
value: Object.create(null)
}
});
export class StudySummary extends Metadata {
constructor(tagMap, attributeMap, uid) {
// Call the superclass constructor passing an plain object with no prototype to be used as the main "_data" attribute.
const _data = Object.create(null);
super(_data, uid);
// Initialize internal tag map if first argument is given.
if (tagMap !== void 0) {
@@ -28,67 +26,53 @@ export class StudySummary {
}
// Initialize internal property map if second argument is given.
if (propertyMap !== void 0) {
this.addProperties(addProperties);
if (attributeMap !== void 0) {
this.setCustomAttributes(attributeMap);
}
}
getStudyInstanceUID() {
// This method should return null if StudyInstanceUID is not available to keep compatibility StudyMetadata API
return this.getTagValue(StudyInstanceUID) || null;
}
addProperties(propertyMap) {
const _hasOwn = Object.prototype.hasOwnProperty;
const _properties = this._properties;
for (let property in propertyMap) {
if (_hasOwn.call(propertyMap, property)) {
_properties[property] = propertyMap[property];
}
}
return this.getTagValue(STUDY_INSTANCE_UID) || null;
}
/**
* Append tags to internal tag map.
* @param {Object} tagMap An object whose own properties will be used as tag values and appended to internal tag map.
*/
addTags(tagMap) {
const _hasOwn = Object.prototype.hasOwnProperty;
const _tags = this._tags;
const _data = this._data;
for (let tag in tagMap) {
if (_hasOwn.call(tagMap, tag)) {
const description = DICOMTagDescriptions.find(tag);
// When a description is available, use its tag as internal key...
if (description) {
_tags[description.tag] = tagMap[tag];
_data[description.tag] = tagMap[tag];
} else {
_tags[tag] = tagMap[tag];
_data[tag] = tagMap[tag];
}
}
}
}
tagExists(tagName) {
const _tags = this._tags;
const _data = this._data;
const description = DICOMTagDescriptions.find(tagName);
if (description) {
return (description.tag in _tags);
return (description.tag in _data);
}
return (tagName in _tags);
return (tagName in _data);
}
getTagValue(tagName) {
const _tags = this._tags;
const _data = this._data;
const description = DICOMTagDescriptions.find(tagName);
if (description) {
return _tags[description.tag];
return _data[description.tag];
}
return _tags[tagName];
}
propertyExists(propertyName) {
return (propertyName in this._properties);
}
getPropertyValue(propertyName) {
return this._properties[propertyName];
return _data[tagName];
}
}