From 101fd5761f23d63d92d8c18342fe09a39048ef6e Mon Sep 17 00:00:00 2001 From: ivmartel Date: Fri, 18 Aug 2023 15:30:52 +0200 Subject: [PATCH 1/3] Add data element class, update users Rename dicom element to data element (except parser) --- src/dicom/dataElement.js | 76 +++++++++++++++ src/dicom/dicomParser.js | 86 ++++++++-------- src/dicom/dicomWriter.js | 128 +++++++++++++----------- src/image/dicomBufferToView.js | 19 +++- src/image/imageFactory.js | 107 +++++++++++--------- src/image/maskFactory.js | 173 +++++++++++++++++---------------- src/image/viewFactory.js | 9 +- src/index.js | 2 + 8 files changed, 370 insertions(+), 230 deletions(-) create mode 100644 src/dicom/dataElement.js diff --git a/src/dicom/dataElement.js b/src/dicom/dataElement.js new file mode 100644 index 0000000000..e7a61c95b6 --- /dev/null +++ b/src/dicom/dataElement.js @@ -0,0 +1,76 @@ +// doc imports +/* eslint-disable no-unused-vars */ +import {Tag} from './dicomTag'; +/* eslint-enable no-unused-vars */ + +/** + * DICOM data element. + */ +export class DataElement { + /** + * The element Value Representation. + * + * @type {string} + */ + vr; + /** + * The element value. + * + * @type {Array} + */ + value; + + // [start] internal values + // only present during parsing or writing otherwise not set + + /** + * The element dicom tag. + * + * @type {Tag} + */ + tag; + + /** + * The element Value Length. + * + * @type {number} + */ + vl; + + /** + * Flag to know if defined or undefined sequence length. + * + * @type {boolean} + */ + undefinedLength; + + /** + * The element start offset. + * + * @type {number} + */ + startOffset; + + /** + * The element end offset. + * + * @type {number} + */ + endOffset; + + /** + * The sequence items. + * + * @type {Array} + */ + items; + + // [end] internal values + + /** + * @param {string} vr The element VR (Value Representation). + */ + constructor(vr) { + this.vr = vr; + } +} \ No newline at end of file diff --git a/src/dicom/dicomParser.js b/src/dicom/dicomParser.js index 724501eb99..b4329cd5d9 100755 --- a/src/dicom/dicomParser.js +++ b/src/dicom/dicomParser.js @@ -13,6 +13,18 @@ import {DataReader} from './dataReader'; import {logger} from '../utils/logger'; import {arrayEquals} from '../utils/array'; +// doc imports +/* eslint-disable no-unused-vars */ +import {DataElement} from '../dicom/dataElement'; +/* eslint-enable no-unused-vars */ + +/** + * List of DICOM data elements indexed via a 8 character string formed from + * the group and element numbers. + * + * @typedef {Object} DataElements + */ + /** * Get the version of the library. * @@ -382,8 +394,9 @@ export function getTransferSyntaxName(syntax) { * See https://github.com/ivmartel/dwv/issues/188 * (Allow to load DICOM with no DICM preamble) for more details. * - * @param {object} firstDataElement The first data element of the DICOM header. - * @returns {object} The transfer syntax data element. + * @param {DataElement} firstDataElement The first data element + * of the DICOM header. + * @returns {DataElement} The transfer syntax data element. */ function guessTransferSyntax(firstDataElement) { const oEightGroupBigEndian = '0800'; @@ -426,10 +439,8 @@ function guessTransferSyntax(firstDataElement) { } } // set transfer syntax data element - const dataElement = { - tag: new Tag('0002', '0010'), - vr: 'UI' - }; + const dataElement = new DataElement('UI'); + dataElement.tag = new Tag('0002', '0010'); dataElement.value = [syntax + ' ']; // even length dataElement.vl = dataElement.value[0].length; dataElement.startOffset = firstDataElement.startOffset; @@ -539,9 +550,9 @@ export class DicomParser { /** * The list of DICOM elements. * - * @type {object} + * @type {DataElements} */ - #dicomElements = {}; + #dataElements = {}; /** * Default character set (optional). @@ -617,13 +628,15 @@ export class DicomParser { this.#textDecoder = new TextDecoder(characterSet); } + // not using type DataElements since the typedef is not exported with the API + /** - * Get the raw DICOM data elements. + * Get the DICOM data elements. * - * @returns {object} The raw DICOM elements. + * @returns {Object} The data elements. */ getDicomElements() { - return this.#dicomElements; + return this.#dataElements; } /** @@ -753,8 +766,7 @@ export class DicomParser { * @param {DataReader} reader The raw data reader. * @param {number} offset The offset where to start to read. * @param {boolean} implicit Is the DICOM VR implicit? - * @returns {object} An object containing the element - * 'tag', 'vl', 'vr', 'data' and 'endOffset'. + * @returns {DataElement} The data element. */ #readDataElement(reader, offset, implicit) { // Tag: group, element @@ -813,7 +825,7 @@ export class DicomParser { let endOffset = startOffset + vl; // read sequence elements - let data = null; + let data; if (isPixelDataTag(tag) && undefinedLength) { // pixel data sequence (implicit) const pixItemData = @@ -857,13 +869,11 @@ export class DicomParser { } // return - const element = { - tag: tag, - vr: vr, - vl: vl, - startOffset: startOffset, - endOffset: endOffset - }; + const element = new DataElement(vr); + element.tag = tag; + element.vl = vl; + element.startOffset = startOffset; + element.endOffset = endOffset; // only set if true (only for sequences and items) if (undefinedLength) { element.undefinedLength = undefinedLength; @@ -877,7 +887,7 @@ export class DicomParser { /** * Interpret the data of an element. * - * @param {object} element The data element. + * @param {DataElement} element The data element. * @param {DataReader} reader The raw data reader. * @param {number} [pixelRepresentation] PixelRepresentation 0->unsigned, * 1->signed (needed for pixel data or VR=xs). @@ -1041,7 +1051,7 @@ export class DicomParser { /** * Interpret the data of a list of elements. * - * @param {Array} elements A list of data elements. + * @param {DataElements} elements A list of data elements. * @param {DataReader} reader The raw data reader. * @param {number} pixelRepresentation PixelRepresentation 0->unsigned, * 1->signed. @@ -1068,7 +1078,7 @@ export class DicomParser { /** * Parse the complete DICOM file (given as input to the class). - * Fills in the member object 'dicomElements'. + * Fills in the member object 'dataElements'. * * @param {ArrayBuffer} buffer The input array buffer. */ @@ -1091,7 +1101,7 @@ export class DicomParser { // increment offset offset = dataElement.endOffset; // store the data element - this.#dicomElements[dataElement.tag.getKey()] = dataElement; + this.#dataElements[dataElement.tag.getKey()] = dataElement; // get meta length const metaLength = dataElement.value[0]; @@ -1102,11 +1112,11 @@ export class DicomParser { dataElement = this.#readDataElement(metaReader, offset, false); offset = dataElement.endOffset; // store the data element - this.#dicomElements[dataElement.tag.getKey()] = dataElement; + this.#dataElements[dataElement.tag.getKey()] = dataElement; } // check the TransferSyntaxUID (has to be there!) - dataElement = this.#dicomElements['00020010']; + dataElement = this.#dataElements['00020010']; if (typeof dataElement === 'undefined') { throw new Error('Not a valid DICOM file (no TransferSyntaxUID found)'); } @@ -1120,7 +1130,7 @@ export class DicomParser { // guess transfer syntax const tsElement = guessTransferSyntax(dataElement); // store - this.#dicomElements[tsElement.tag.getKey()] = tsElement; + this.#dataElements[tsElement.tag.getKey()] = tsElement; syntax = tsElement.value[0]; // reset offset offset = 0; @@ -1151,8 +1161,8 @@ export class DicomParser { offset = dataElement.endOffset; // store the data element const key = dataElement.tag.getKey(); - if (typeof this.#dicomElements[key] === 'undefined') { - this.#dicomElements[key] = dataElement; + if (typeof this.#dataElements[key] === 'undefined') { + this.#dataElements[key] = dataElement; } else { logger.warn('Not saving duplicate tag: ' + key); } @@ -1173,9 +1183,9 @@ export class DicomParser { // pixel specific let pixelRepresentation = 0; let bitsAllocated = 16; - if (typeof this.#dicomElements['7FE00010'] !== 'undefined') { + if (typeof this.#dataElements['7FE00010'] !== 'undefined') { // PixelRepresentation 0->unsigned, 1->signed - dataElement = this.#dicomElements['00280103']; + dataElement = this.#dataElements['00280103']; if (typeof dataElement !== 'undefined') { dataElement.value = this.#interpretElement(dataElement, dataReader); pixelRepresentation = dataElement.value[0]; @@ -1185,7 +1195,7 @@ export class DicomParser { } // BitsAllocated - dataElement = this.#dicomElements['00280100']; + dataElement = this.#dataElements['00280100']; if (typeof dataElement !== 'undefined') { dataElement.value = this.#interpretElement(dataElement, dataReader); bitsAllocated = dataElement.value[0]; @@ -1200,7 +1210,7 @@ export class DicomParser { } // SpecificCharacterSet - dataElement = this.#dicomElements['00080005']; + dataElement = this.#dataElements['00080005']; if (typeof dataElement !== 'undefined') { dataElement.value = this.#interpretElement(dataElement, dataReader); let charSetTerm; @@ -1216,19 +1226,19 @@ export class DicomParser { // interpret the dicom elements this.#interpret( - this.#dicomElements, dataReader, + this.#dataElements, dataReader, pixelRepresentation, bitsAllocated ); // handle fragmented pixel buffer // Reference: http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_8.2.html // (third note, "Depending on the transfer syntax...") - dataElement = this.#dicomElements['7FE00010']; + dataElement = this.#dataElements['7FE00010']; if (typeof dataElement !== 'undefined') { if (dataElement.undefinedLength) { let numberOfFrames = 1; - if (typeof this.#dicomElements['00280008'] !== 'undefined') { - numberOfFrames = Number(this.#dicomElements['00280008'].value[0]); + if (typeof this.#dataElements['00280008'] !== 'undefined') { + numberOfFrames = Number(this.#dataElements['00280008'].value[0]); } const pixItems = dataElement.value; if (pixItems.length > 1 && pixItems.length > numberOfFrames) { diff --git a/src/dicom/dicomWriter.js b/src/dicom/dicomWriter.js index 25c18f3274..01c38944e7 100644 --- a/src/dicom/dicomWriter.js +++ b/src/dicom/dicomWriter.js @@ -21,6 +21,7 @@ import { isBigEndianTransferSyntax, getDataElementPrefixByteSize } from './dicomParser'; +import {DataElement} from './dataElement'; import {DataWriter} from './dataWriter'; import {logger} from '../utils/logger'; @@ -376,8 +377,8 @@ export class DicomWriter { * Get the element to write according to the class rules. * Priority order: tagName, groupName, default. * - * @param {object} element The element to check - * @returns {object} The element to write, can be null. + * @param {DataElement} element The element to check + * @returns {DataElement|null} The element to write, can be null. */ getElementToWrite(element) { // get group and tag string name @@ -427,12 +428,16 @@ export class DicomWriter { if (typeof item['FFFEE000'].undefinedLength !== 'undefined') { undefinedLength = item['FFFEE000'].undefinedLength; } - const itemElement = { - tag: getItemTag(), - vr: 'NONE', - vl: undefinedLength ? 0xffffffff : item['FFFEE000'].vl, - value: [] - }; + // const itemElement = { + // tag: getItemTag(), + // vr: 'NONE', + // vl: undefinedLength ? 0xffffffff : item['FFFEE000'].vl, + // value: [] + // }; + const itemElement = new DataElement('NONE'); + itemElement.vl = undefinedLength ? 0xffffffff : item['FFFEE000'].vl, + itemElement.tag = getItemTag(); + itemElement.value = []; byteOffset = this.#writeDataElement( writer, itemElement, byteOffset, isImplicit); // write rest @@ -444,12 +449,16 @@ export class DicomWriter { } // item delimitation if (undefinedLength) { - const itemDelimElement = { - tag: getItemDelimitationItemTag(), - vr: 'NONE', - vl: 0, - value: [] - }; + // const itemDelimElement = { + // tag: getItemDelimitationItemTag(), + // vr: 'NONE', + // vl: 0, + // value: [] + // }; + const itemDelimElement = new DataElement('NONE'); + itemDelimElement.vl = 0; + itemDelimElement.tag = getItemDelimitationItemTag(); + itemDelimElement.value = []; byteOffset = this.#writeDataElement( writer, itemDelimElement, byteOffset, isImplicit); } @@ -463,7 +472,7 @@ export class DicomWriter { * Write data with a specific Value Representation (VR). * * @param {DataWriter} writer The raw data writer. - * @param {object} element The element to write. + * @param {DataElement} element The element to write. * @param {number} byteOffset The offset to start writing from. * @param {Array} value The array to write. * @param {boolean} isImplicit Is the DICOM VR implicit? @@ -558,7 +567,7 @@ export class DicomWriter { * Write a pixel data element. * * @param {DataWriter} writer The raw data writer. - * @param {object} element The element to write. + * @param {DataElement} element The element to write. * @param {number} byteOffset The offset to start writing from. * @param {Array} value The array to write. * @param {boolean} isImplicit Is the DICOM VR implicit? @@ -613,7 +622,7 @@ export class DicomWriter { * Write a data element. * * @param {DataWriter} writer The raw data writer. - * @param {object} element The DICOM data element to write. + * @param {DataElement} element The DICOM data element to write. * @param {number} byteOffset The offset to start writing from. * @param {boolean} isImplicit Is the DICOM VR implicit? * @returns {number} The new offset position. @@ -687,12 +696,16 @@ export class DicomWriter { // sequence delimitation item for sequence with undefined length if (undefinedLengthSequence) { - const seqDelimElement = { - tag: getSequenceDelimitationItemTag(), - vr: 'NONE', - vl: 0, - value: [] - }; + // const seqDelimElement = { + // tag: getSequenceDelimitationItemTag(), + // vr: 'NONE', + // vl: 0, + // value: [] + // }; + const seqDelimElement = new DataElement('NONE'); + seqDelimElement.vl = 0; + seqDelimElement.tag = getSequenceDelimitationItemTag(); + seqDelimElement.value = []; byteOffset = this.#writeDataElement( writer, seqDelimElement, byteOffset, isImplicit); } @@ -704,28 +717,31 @@ export class DicomWriter { /** * Get the ArrayBuffer corresponding to input DICOM elements. * - * @param {Array} dicomElements The wrapped elements to write. + * @param {Object} dataElements The elements to write. * @returns {ArrayBuffer} The elements as a buffer. */ - getBuffer(dicomElements) { + getBuffer(dataElements) { // Transfer Syntax - const syntax = dicomElements['00020010'].value[0]; + // const el = dataElements['00020010']; + // el.value = 1; + // el.vl = 'a'; + const syntax = dataElements['00020010'].value[0]; const isImplicit = isImplicitTransferSyntax(syntax); const isBigEndian = isBigEndianTransferSyntax(syntax); // Specific CharacterSet - if (typeof dicomElements['00080005'] !== 'undefined') { - const oldscs = dicomElements['00080005'].value[0]; + if (typeof dataElements['00080005'] !== 'undefined') { + const oldscs = dataElements['00080005'].value[0]; // force UTF-8 if not default character set if (typeof oldscs !== 'undefined' && oldscs !== 'ISO-IR 6') { logger.debug('Change charset to UTF, was: ' + oldscs); this.useSpecialTextEncoder(); - dicomElements['00080005'].value = ['ISO_IR 192']; + dataElements['00080005'].value = ['ISO_IR 192']; } } // Bits Allocated (for image data) let bitsAllocated; - if (typeof dicomElements['00280100'] !== 'undefined') { - bitsAllocated = dicomElements['00280100'].value[0]; + if (typeof dataElements['00280100'] !== 'undefined') { + bitsAllocated = dataElements['00280100'].value[0]; } // calculate buffer size and split elements (meta and non meta) @@ -746,11 +762,11 @@ export class DicomWriter { const ivnTag = new Tag('0002', '0013'); // loop through elements to get the buffer size - const keys = Object.keys(dicomElements); + const keys = Object.keys(dataElements); for (let i = 0, leni = keys.length; i < leni; ++i) { - const originalElement = dicomElements[keys[i]]; + const originalElement = dataElements[keys[i]]; originalElement.tag = getTagFromKey(keys[i]); - element = this.#getElementToWrite(originalElement); + element = this.getElementToWrite(originalElement); if (element !== null && !fmiglTag.equals(element.tag) && !fmivTag.equals(element.tag) && @@ -797,14 +813,14 @@ export class DicomWriter { } // FileMetaInformationVersion - const fmiv = getDicomElement('FileMetaInformationVersion'); + const fmiv = getDataElement('FileMetaInformationVersion'); let fmivSize = getDataElementPrefixByteSize(fmiv.vr, false); fmivSize += this.#setElementValue(fmiv, [0, 1], false); metaElements.push(fmiv); metaLength += fmivSize; totalSize += fmivSize; // ImplementationClassUID - const icUID = getDicomElement('ImplementationClassUID'); + const icUID = getDataElement('ImplementationClassUID'); let icUIDSize = getDataElementPrefixByteSize(icUID.vr, false); icUIDSize += this.#setElementValue( icUID, [getUID('ImplementationClassUID')], false); @@ -812,7 +828,7 @@ export class DicomWriter { metaLength += icUIDSize; totalSize += icUIDSize; // ImplementationVersionName - const ivn = getDicomElement('ImplementationVersionName'); + const ivn = getDataElement('ImplementationVersionName'); let ivnSize = getDataElementPrefixByteSize(ivn.vr, false); const ivnValue = 'DWV_' + getDwvVersion(); ivnSize += this.#setElementValue(ivn, [ivnValue], false); @@ -828,7 +844,7 @@ export class DicomWriter { rawElements.sort(elemSortFunc); // create the FileMetaInformationGroupLength element - const fmigl = getDicomElement('FileMetaInformationGroupLength'); + const fmigl = getDataElement('FileMetaInformationGroupLength'); let fmiglSize = getDataElementPrefixByteSize(fmigl.vr, false); fmiglSize += this.#setElementValue( fmigl, new Uint32Array([metaLength]), false); @@ -878,7 +894,7 @@ export class DicomWriter { /** * Set a DICOM element value according to its VR (Value Representation). * - * @param {object} element The DICOM element to set the value. + * @param {DataElement} element The DICOM element to set the value. * @param {object} value The value to set. * @param {boolean} isImplicit Does the data use implicit VR? * @param {number} [bitsAllocated] Bits allocated used for pixel data. @@ -1061,7 +1077,7 @@ export class DicomWriter { * Fix for broken DICOM elements: Replace "UN" with correct VR if the * element exists in dictionary * - * @param {object} element The DICOM element. + * @param {DataElement} element The DICOM element. */ function checkUnknownVR(element) { if (element.vr === 'UN') { @@ -1079,14 +1095,13 @@ function checkUnknownVR(element) { * Get a DICOM element from its tag name (value set separatly). * * @param {string} tagName The string tag name. - * @returns {object} The DICOM element. + * @returns {DataElement} The DICOM element. */ -function getDicomElement(tagName) { +function getDataElement(tagName) { const tag = getTagFromDictionary(tagName); - return { - tag: tag, - vr: tag.getVrFromDictionary() - }; + const element = new DataElement(tag.getVrFromDictionary()); + element.tag = tag; + return element; } /** @@ -1126,15 +1141,15 @@ function getBpeForVrType(vrType) { * simple tags. * * @param {object} jsonTags The DICOM json tags object. - * @returns {object} The DICOM elements. + * @returns {Object} The DICOM elements. */ export function getElementsFromJSONTags(jsonTags) { const keys = Object.keys(jsonTags); - const dicomElements = {}; + const dataElements = {}; for (let k = 0, len = keys.length; k < len; ++k) { // get the DICOM element definition from its name const tag = getTagFromDictionary(keys[k]); - if (!tag) { + if (typeof tag === 'undefined') { continue; } const vr = tag.getVrFromDictionary(); @@ -1164,17 +1179,16 @@ export function getElementsFromJSONTags(jsonTags) { } } // create element - const dicomElement = { - tag: tag, - vr: vr, - value: value - }; + const dataElement = new DataElement(vr); + dataElement.tag = tag; + dataElement.value = value; if (undefinedLength) { - dicomElement.undefinedLength = undefinedLength; + dataElement.undefinedLength = undefinedLength; } // store - dicomElements[tag.getKey()] = dicomElement; + dataElements[tag.getKey()] = dataElement; } // return - return dicomElements; + // @ts-expect-error + return dataElements; } diff --git a/src/image/dicomBufferToView.js b/src/image/dicomBufferToView.js index 635e6e7508..21274e04fc 100644 --- a/src/image/dicomBufferToView.js +++ b/src/image/dicomBufferToView.js @@ -7,6 +7,15 @@ import {ImageFactory} from './imageFactory'; import {MaskFactory} from './maskFactory'; import {PixelBufferDecoder} from './decoder'; +// doc imports +/* eslint-disable no-unused-vars */ +import {DataElement} from '../dicom/dataElement'; +/* eslint-enable no-unused-vars */ + +/** + * @typedef {Object} DataElements + */ + /** * Create a View from a DICOM buffer. */ @@ -45,7 +54,7 @@ export class DicomBufferToView { /** * Get the factory associated to input DICOM elements. * - * @param {object} elements The DICOM elements. + * @param {DataElements} elements The DICOM elements. * @returns {ImageFactory|MaskFactory} The associated factory. */ #getFactory(elements) { @@ -72,19 +81,19 @@ export class DicomBufferToView { * @param {string} origin The data origin. */ #generateImage(index, origin) { - const dicomElements = this.#dicomParserStore[index].getDicomElements(); - const factory = this.#getFactory(dicomElements); + const dataElements = this.#dicomParserStore[index].getDicomElements(); + const factory = this.#getFactory(dataElements); // create the image try { const image = factory.create( - dicomElements, + dataElements, this.#finalBufferStore[index], this.#options.numberOfFiles); // call onloaditem this.onloaditem({ data: { image: image, - info: dicomElements + info: dataElements }, source: origin, warn: this.#factoryWarnings[index] diff --git a/src/image/imageFactory.js b/src/image/imageFactory.js index c3dd426bd5..b844876dd9 100644 --- a/src/image/imageFactory.js +++ b/src/image/imageFactory.js @@ -19,6 +19,15 @@ import {Matrix33} from '../math/matrix'; import {Point3D} from '../math/point'; import {logger} from '../utils/logger'; +// doc imports +/* eslint-disable no-unused-vars */ +import {DataElement} from '../dicom/dataElement'; +/* eslint-enable no-unused-vars */ + +/** + * @typedef {Object} DataElements + */ + /** * {@link Image} factory. */ @@ -27,30 +36,30 @@ export class ImageFactory { /** * Check dicom elements. Throws an error if not suitable. * - * @param {object} dicomElements The DICOM tags. + * @param {DataElements} dataElements The DICOM data elements. * @returns {object|undefined} A possible warning. */ - checkElements(dicomElements) { + checkElements(dataElements) { // will throw if columns or rows is not defined - getImage2DSize(dicomElements); + getImage2DSize(dataElements); } /** * Get an {@link Image} object from the read DICOM file. * - * @param {object} dicomElements The DICOM tags. + * @param {DataElements} dataElements The DICOM tags. * @param {Uint8Array | Int8Array | * Uint16Array | Int16Array | * Uint32Array | Int32Array} pixelBuffer The pixel buffer. * @param {number} numberOfFiles The input number of files. * @returns {Image} A new Image. */ - create(dicomElements, pixelBuffer, numberOfFiles) { - const size2D = getImage2DSize(dicomElements); + create(dataElements, pixelBuffer, numberOfFiles) { + const size2D = getImage2DSize(dataElements); const sizeValues = [size2D[0], size2D[1], 1]; // frames - const frames = dicomElements['00280008']; + const frames = dataElements['00280008']; if (frames) { sizeValues.push(frames.value[0]); } @@ -59,16 +68,16 @@ export class ImageFactory { const size = new Size(sizeValues); // image spacing - const spacing = getPixelSpacing(dicomElements); + const spacing = getPixelSpacing(dataElements); // TransferSyntaxUID - const syntax = dicomElements['00020010'].value[0]; + const syntax = dataElements['00020010'].value[0]; const jpeg2000 = isJpeg2000TransferSyntax(syntax); const jpegBase = isJpegBaselineTransferSyntax(syntax); const jpegLoss = isJpegLosslessTransferSyntax(syntax); // ImagePositionPatient - const imagePositionPatient = dicomElements['00200032']; + const imagePositionPatient = dataElements['00200032']; // slice position let slicePosition = new Array(0, 0, 0); if (typeof imagePositionPatient !== 'undefined') { @@ -81,7 +90,7 @@ export class ImageFactory { // slice orientation (cosines are matrices' columns) // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.2.html#sect_C.7.6.2.1.1 - const imageOrientationPatient = dicomElements['00200037']; + const imageOrientationPatient = dataElements['00200037']; let orientationMatrix; if (typeof imageOrientationPatient !== 'undefined') { const rowCosines = new Vector3D( @@ -106,20 +115,20 @@ export class ImageFactory { const origin = new Point3D( slicePosition[0], slicePosition[1], slicePosition[2]); const extractor = new TagValueExtractor(); - const time = extractor.getTime(dicomElements); + const time = extractor.getTime(dataElements); const geometry = new Geometry( origin, size, spacing, orientationMatrix, time); // SOP Instance UID let sopInstanceUid; - const siu = dicomElements['00080018']; + const siu = dataElements['00080018']; if (typeof siu !== 'undefined') { sopInstanceUid = siu.value[0]; } // Sample per pixels let samplesPerPixel = 1; - const spp = dicomElements['00280002']; + const spp = dataElements['00280002']; if (typeof spp !== 'undefined') { samplesPerPixel = spp.value[0]; } @@ -139,7 +148,7 @@ export class ImageFactory { // image const image = new Image(geometry, pixelBuffer, [sopInstanceUid]); // PhotometricInterpretation - const photometricInterpretation = dicomElements['00280004']; + const photometricInterpretation = dataElements['00280004']; if (typeof photometricInterpretation !== 'undefined') { let photo = photometricInterpretation.value[0].toUpperCase(); // jpeg decoders output RGB data @@ -154,7 +163,7 @@ export class ImageFactory { image.setPhotometricInterpretation(photo); } // PlanarConfiguration - const planarConfiguration = dicomElements['00280006']; + const planarConfiguration = dataElements['00280006']; if (typeof planarConfiguration !== 'undefined') { image.setPlanarConfiguration(planarConfiguration.value[0]); } @@ -162,7 +171,7 @@ export class ImageFactory { // rescale slope and intercept let slope = 1; // RescaleSlope - const rescaleSlope = dicomElements['00281053']; + const rescaleSlope = dataElements['00281053']; if (typeof rescaleSlope !== 'undefined') { const value = parseFloat(rescaleSlope.value[0]); if (!isNaN(value)) { @@ -171,7 +180,7 @@ export class ImageFactory { } let intercept = 0; // RescaleIntercept - const rescaleIntercept = dicomElements['00281052']; + const rescaleIntercept = dataElements['00281052']; if (typeof rescaleIntercept !== 'undefined') { const value = parseFloat(rescaleIntercept.value[0]); if (!isNaN(value)) { @@ -185,47 +194,47 @@ export class ImageFactory { const meta = { numberOfFiles: numberOfFiles }; - const modality = dicomElements['00080060']; + const modality = dataElements['00080060']; if (typeof modality !== 'undefined') { meta.Modality = modality.value[0]; } - const sopClassUID = dicomElements['00080016']; + const sopClassUID = dataElements['00080016']; if (typeof sopClassUID !== 'undefined') { meta.SOPClassUID = sopClassUID.value[0]; } - const studyUID = dicomElements['0020000D']; + const studyUID = dataElements['0020000D']; if (typeof studyUID !== 'undefined') { meta.StudyInstanceUID = studyUID.value[0]; } - const seriesUID = dicomElements['0020000E']; + const seriesUID = dataElements['0020000E']; if (typeof seriesUID !== 'undefined') { meta.SeriesInstanceUID = seriesUID.value[0]; } - const bits = dicomElements['00280101']; + const bits = dataElements['00280101']; if (typeof bits !== 'undefined') { meta.BitsStored = bits.value[0]; } - const pixelRep = dicomElements['00280103']; + const pixelRep = dataElements['00280103']; if (typeof pixelRep !== 'undefined') { meta.PixelRepresentation = pixelRep.value[0]; } // PixelRepresentation -> is signed meta.IsSigned = meta.PixelRepresentation === 1; // local pixel unit - const pixelUnit = getPixelUnit(dicomElements); + const pixelUnit = getPixelUnit(dataElements); if (typeof pixelUnit !== 'undefined') { meta.pixelUnit = pixelUnit; } // FrameOfReferenceUID (optional) - const frameOfReferenceUID = dicomElements['00200052']; + const frameOfReferenceUID = dataElements['00200052']; if (typeof frameOfReferenceUID !== 'undefined') { meta.FrameOfReferenceUID = frameOfReferenceUID.value[0]; } // window level presets const windowPresets = {}; - const windowCenter = dicomElements['00281050']; - const windowWidth = dicomElements['00281051']; - const windowCWExplanation = dicomElements['00281055']; + const windowCenter = dataElements['00281050']; + const windowWidth = dataElements['00281051']; + const windowCWExplanation = dataElements['00281055']; if (typeof windowCenter !== 'undefined' && typeof windowWidth !== 'undefined') { let name; @@ -254,19 +263,22 @@ export class ImageFactory { // PALETTE COLOR luts if (image.getPhotometricInterpretation() === 'PALETTE COLOR') { - let redLut = dicomElements['00281201']; - let greenLut = dicomElements['00281202']; - let blueLut = dicomElements['00281203']; + const redLutElement = dataElements['00281201']; + const greenLutElement = dataElements['00281202']; + const blueLutElement = dataElements['00281203']; + let redLut; + let greenLut; + let blueLut; // check red palette descriptor (should all be equal) - const descriptor = dicomElements['00281101']; + const descriptor = dataElements['00281101']; if (typeof descriptor !== 'undefined' && - descriptor.length === 3) { - if (descriptor[2] === 16) { + descriptor.value.length === 3) { + if (descriptor.value[2] === 16) { let doScale = false; // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor) // Some implementations have encoded 8 bit entries with 16 bits // allocated, padding the high bits; - let descSize = descriptor[0]; + let descSize = descriptor.value[0]; // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor) // The first Palette Color Lookup Table Descriptor value is the // number of entries in the lookup table. When the number of table @@ -275,7 +287,7 @@ export class ImageFactory { descSize = 65536; } // red palette VL - const vlSize = redLut.vl; + const vlSize = redLutElement.vl; // check double size if (vlSize !== 2 * descSize) { doScale = true; @@ -286,7 +298,7 @@ export class ImageFactory { // Palette color values must always be scaled across the full // range of available intensities const bitsAllocated = parseInt( - dicomElements['00280100'].value[0], 10); + dataElements['00280100'].value[0], 10); if (bitsAllocated === 8) { doScale = true; logger.info( @@ -298,19 +310,22 @@ export class ImageFactory { return value >> 8; }; - redLut = redLut.map(scaleTo8); - greenLut = greenLut.map(scaleTo8); - blueLut = blueLut.map(scaleTo8); + redLut = redLutElement.value.map(scaleTo8); + greenLut = greenLutElement.value.map(scaleTo8); + blueLut = blueLutElement.value.map(scaleTo8); } - } else if (descriptor[2] === 8) { + } else if (descriptor.value[2] === 8) { // lut with vr=OW was read as Uint16, convert it to Uint8 logger.info( 'Scaling 16bits color lut since the lut descriptor is 8.'); - let clone = redLut.slice(0); + let clone = redLutElement.value.slice(0); + // @ts-expect-error redLut = new Uint8Array(clone.buffer); - clone = greenLut.slice(0); + clone = greenLutElement.value.slice(0); + // @ts-expect-error greenLut = new Uint8Array(clone.buffer); - clone = blueLut.slice(0); + clone = blueLutElement.value.slice(0); + // @ts-expect-error blueLut = new Uint8Array(clone.buffer); } } @@ -323,7 +338,7 @@ export class ImageFactory { } // RecommendedDisplayFrameRate - const recommendedDisplayFrameRate = dicomElements['00082144']; + const recommendedDisplayFrameRate = dataElements['00082144']; if (typeof recommendedDisplayFrameRate !== 'undefined') { meta.RecommendedDisplayFrameRate = parseInt( recommendedDisplayFrameRate.value[0], 10); diff --git a/src/image/maskFactory.js b/src/image/maskFactory.js index c0fcfb2c0b..3543da1888 100644 --- a/src/image/maskFactory.js +++ b/src/image/maskFactory.js @@ -15,6 +15,15 @@ import { } from '../utils/colour'; import {Size} from './size'; +// doc imports +/* eslint-disable no-unused-vars */ +import {DataElement} from '../dicom/dataElement'; +/* eslint-enable no-unused-vars */ + +/** + * @typedef {Object} DataElements + */ + /** * Check two position patients for equality. * @@ -53,11 +62,11 @@ function getComparePosPat(orientation) { /** * Check that a DICOM tag definition is present in a parsed element. * - * @param {object} rootElement The root dicom element. + * @param {DataElements} dataElements The root dicom element. * @param {object} tagDefinition The tag definition as {name, tag, type, enum}. */ -function checkTag(rootElement, tagDefinition) { - const element = rootElement[tagDefinition.tag]; +function checkTag(dataElements, tagDefinition) { + const element = dataElements[tagDefinition.tag]; // check null and undefined if (tagDefinition.type === 1 || tagDefinition.type === 2) { if (typeof element === 'undefined') { @@ -196,12 +205,12 @@ function getDefaultDicomSegJson() { /** * Check the dimension organization from a dicom element. * - * @param {object} rootElement The root dicom element. + * @param {DataElements} dataElements The root dicom element. * @returns {object} The dimension organizations and indices. */ -function getDimensionOrganization(rootElement) { +function getDimensionOrganization(dataElements) { // Dimension Organization Sequence (required) - const orgSq = rootElement['00209221']; + const orgSq = dataElements['00209221']; if (typeof orgSq === 'undefined' || orgSq.value.length !== 1) { throw new Error('Unsupported dimension organization sequence length'); } @@ -210,7 +219,7 @@ function getDimensionOrganization(rootElement) { // Dimension Index Sequence (conditionally required) const indices = []; - const indexSqElem = rootElement['00209222']; + const indexSqElem = dataElements['00209222']; if (typeof indexSqElem !== 'undefined') { const indexSq = indexSqElem.value; // expecting 2D index @@ -262,31 +271,31 @@ function getDimensionOrganization(rootElement) { /** * Get a code object from a dicom element. * - * @param {object} element The dicom element. + * @param {DataElements} dataElements The dicom element. * @returns {object} A code object. */ -function getCode(element) { +function getCode(dataElements) { // meaning -> CodeMeaning (type1) const code = { - meaning: element['00080104'].value[0] + meaning: dataElements['00080104'].value[0] }; // value -> CodeValue (type1C) // longValue -> LongCodeValue (type1C) // urnValue -> URNCodeValue (type1C) - if (element['00080100']) { - code.value = element['00080100'].value[0]; - } else if (element['00080119']) { - code.longValue = element['00080119'].value[0]; - } else if (element['00080120']) { - code.urnValue = element['00080120'].value[0]; + if (dataElements['00080100']) { + code.value = dataElements['00080100'].value[0]; + } else if (dataElements['00080119']) { + code.longValue = dataElements['00080119'].value[0]; + } else if (dataElements['00080120']) { + code.urnValue = dataElements['00080120'].value[0]; } else { throw Error('Invalid code with no value, no long value and no urn value.'); } // schemeDesignator -> CodingSchemeDesignator (type1C) if (typeof code.value !== 'undefined' || typeof code.longValue !== 'undefined') { - if (element['00080102']) { - code.schemeDesignator = element['00080102'].value[0]; + if (dataElements['00080102']) { + code.schemeDesignator = dataElements['00080102'].value[0]; } else { throw Error( 'No coding sheme designator when code value or long value is present'); @@ -298,21 +307,21 @@ function getCode(element) { /** * Get a segment object from a dicom element. * - * @param {object} element The dicom element. + * @param {DataElements} dataElements The dicom element. * @returns {object} A segment object. */ -function getSegment(element) { +function getSegment(dataElements) { // number -> SegmentNumber (type1) // label -> SegmentLabel (type1) // algorithmType -> SegmentAlgorithmType (type1) const segment = { - number: element['00620004'].value[0], - label: element['00620005'].value[0], - algorithmType: element['00620008'].value[0] + number: dataElements['00620004'].value[0], + label: dataElements['00620005'].value[0], + algorithmType: dataElements['00620008'].value[0] }; // algorithmName -> SegmentAlgorithmName (type1C) - if (element['00620009']) { - segment.algorithmName = element['00620009'].value[0]; + if (dataElements['00620009']) { + segment.algorithmName = dataElements['00620009'].value[0]; } // // required if type is not MANUAL // if (segment.algorithmType !== 'MANUAL' && @@ -323,10 +332,10 @@ function getSegment(element) { // displayValue -> // - RecommendedDisplayGrayscaleValue // - RecommendedDisplayCIELabValue converted to RGB - if (typeof element['0062000C'] !== 'undefined') { - segment.displayValue = element['006200C'].value; - } else if (typeof element['0062000D'] !== 'undefined') { - const cielabElement = element['0062000D'].value; + if (typeof dataElements['0062000C'] !== 'undefined') { + segment.displayValue = dataElements['006200C'].value; + } else if (typeof dataElements['0062000D'] !== 'undefined') { + const cielabElement = dataElements['0062000D'].value; const rgb = cielabToSrgb(uintLabToLab({ l: cielabElement[0], a: cielabElement[1], @@ -335,23 +344,23 @@ function getSegment(element) { segment.displayValue = rgb; } // Segmented Property Category Code Sequence (type1, only one) - if (typeof element['00620003'] !== 'undefined') { + if (typeof dataElements['00620003'] !== 'undefined') { segment.propertyCategoryCode = - getCode(element['00620003'].value[0]); + getCode(dataElements['00620003'].value[0]); } else { throw Error('Missing Segmented Property Category Code Sequence.'); } // Segmented Property Type Code Sequence (type1) - if (typeof element['0062000F'] !== 'undefined') { + if (typeof dataElements['0062000F'] !== 'undefined') { segment.propertyTypeCode = - getCode(element['0062000F'].value[0]); + getCode(dataElements['0062000F'].value[0]); } else { throw Error('Missing Segmented Property Type Code Sequence.'); } // tracking Id and UID (type1C) - if (typeof element['00620020'] !== 'undefined') { - segment.trackingId = element['00620020'].value[0]; - segment.trackingUid = element['00620021'].value[0]; + if (typeof dataElements['00620020'] !== 'undefined') { + segment.trackingId = dataElements['00620020'].value[0]; + segment.trackingUid = dataElements['00620021'].value[0]; } return segment; @@ -436,25 +445,25 @@ export function isSimilarSegment(seg1, seg2) { /** * Get a spacing object from a dicom measure element. * - * @param {object} measure The dicom element. + * @param {DataElements} dataElements The dicom element. * @returns {Spacing} A spacing object. */ -function getSpacingFromMeasure(measure) { +function getSpacingFromMeasure(dataElements) { // Pixel Spacing - if (typeof measure['00280030'] === 'undefined') { + if (typeof dataElements['00280030'] === 'undefined') { return null; } - const pixelSpacing = measure['00280030']; + const pixelSpacing = dataElements['00280030']; const spacingValues = [ parseFloat(pixelSpacing.value[0]), parseFloat(pixelSpacing.value[1]) ]; // Slice Thickness - if (typeof measure['00180050'] !== 'undefined') { - spacingValues.push(parseFloat(measure['00180050'].value[0])); - } else if (typeof measure['00180088'] !== 'undefined') { + if (typeof dataElements['00180050'] !== 'undefined') { + spacingValues.push(parseFloat(dataElements['00180050'].value[0])); + } else if (typeof dataElements['00180088'] !== 'undefined') { // Spacing Between Slices - spacingValues.push(parseFloat(measure['00180088'].value[0])); + spacingValues.push(parseFloat(dataElements['00180088'].value[0])); } return new Spacing(spacingValues); } @@ -462,14 +471,14 @@ function getSpacingFromMeasure(measure) { /** * Get a frame information object from a dicom element. * - * @param {object} groupItem The dicom element. + * @param {DataElements} dataElements The dicom element. * @returns {object} A frame information object. */ -function getSegmentFrameInfo(groupItem) { +function getSegmentFrameInfo(dataElements) { // Derivation Image Sequence const derivationImages = []; - if (typeof groupItem['00089124'] !== 'undefined') { - const derivationImageSq = groupItem['00089124'].value; + if (typeof dataElements['00089124'] !== 'undefined') { + const derivationImageSq = dataElements['00089124'].value; // Source Image Sequence for (let i = 0; i < derivationImageSq.length; ++i) { const sourceImages = []; @@ -494,15 +503,15 @@ function getSegmentFrameInfo(groupItem) { } } // Frame Content Sequence (required, only one) - const frameContentSq = groupItem['00209111'].value; + const frameContentSq = dataElements['00209111'].value; // Dimension Index Value const dimIndex = frameContentSq[0]['00209157'].value; // Segment Identification Sequence (required, only one) - const segmentIdSq = groupItem['0062000A'].value; + const segmentIdSq = dataElements['0062000A'].value; // Referenced Segment Number const refSegmentNumber = segmentIdSq[0]['0062000B'].value[0]; // Plane Position Sequence (required, only one) - const planePosSq = groupItem['00209113'].value; + const planePosSq = dataElements['00209113'].value; // Image Position (Patient) (conditionally required) const imagePosPat = planePosSq[0]['00200032'].value; for (let p = 0; p < imagePosPat.length; ++p) { @@ -515,8 +524,8 @@ function getSegmentFrameInfo(groupItem) { refSegmentNumber: refSegmentNumber }; // Plane Orientation Sequence - if (typeof groupItem['00209116'] !== 'undefined') { - const framePlaneOrientationSeq = groupItem['00209116']; + if (typeof dataElements['00209116'] !== 'undefined') { + const framePlaneOrientationSeq = dataElements['00209116']; if (framePlaneOrientationSeq.value.length !== 0) { // should only be one Image Orientation (Patient) const frameImageOrientation = @@ -527,8 +536,8 @@ function getSegmentFrameInfo(groupItem) { } } // Pixel Measures Sequence - if (typeof groupItem['00289110'] !== 'undefined') { - const framePixelMeasuresSeq = groupItem['00289110']; + if (typeof dataElements['00289110'] !== 'undefined') { + const framePixelMeasuresSeq = dataElements['00289110']; if (framePixelMeasuresSeq.value.length !== 0) { // should only be one const frameSpacing = @@ -563,27 +572,27 @@ export class MaskFactory { /** * Get an {@link Image} object from the read DICOM file. * - * @param {object} dicomElements The DICOM tags. + * @param {DataElements} dataElements The DICOM tags. * @param {Uint8Array | Int8Array | * Uint16Array | Int16Array | * Uint32Array | Int32Array} pixelBuffer The pixel buffer. * @returns {Image} A new Image. */ - create(dicomElements, pixelBuffer) { + create(dataElements, pixelBuffer) { // check required and supported tags for (let d = 0; d < RequiredDicomSegTags.length; ++d) { - checkTag(dicomElements, RequiredDicomSegTags[d]); + checkTag(dataElements, RequiredDicomSegTags[d]); } // image size - const size2D = getImage2DSize(dicomElements); + const size2D = getImage2DSize(dataElements); const size = new Size([size2D[0], size2D[1], 1]); const sliceSize = size.getTotalSize(); // frames let frames = 1; - const framesElem = dicomElements['00280008']; + const framesElem = dataElements['00280008']; if (typeof framesElem !== 'undefined') { frames = parseInt(framesElem.value[0], 10); } @@ -595,10 +604,10 @@ export class MaskFactory { } // Dimension Organization and Index - const dimension = getDimensionOrganization(dicomElements); + const dimension = getDimensionOrganization(dataElements); // Segment Sequence - const segSequence = dicomElements['00620002']; + const segSequence = dataElements['00620002']; if (typeof segSequence === 'undefined') { throw new Error('Missing or empty segmentation sequence'); } @@ -620,7 +629,7 @@ export class MaskFactory { // Shared Functional Groups Sequence let spacing; let imageOrientationPatient; - const sharedFunctionalGroupsSeq = dicomElements['52009229']; + const sharedFunctionalGroupsSeq = dataElements['52009229']; if (typeof sharedFunctionalGroupsSeq !== 'undefined') { // should be only one const funcGroup0 = sharedFunctionalGroupsSeq.value[0]; @@ -662,7 +671,7 @@ export class MaskFactory { }; // Per-frame Functional Groups Sequence - const perFrameFuncGroupSequence = dicomElements['52009230']; + const perFrameFuncGroupSequence = dataElements['52009230']; if (typeof perFrameFuncGroupSequence === 'undefined') { throw new Error('Missing or empty per frame functional sequence'); } @@ -873,25 +882,25 @@ export class MaskFactory { // meta information const meta = getDefaultDicomSegJson(); // Study - meta.StudyDate = dicomElements['00080020'].value[0]; - meta.StudyTime = dicomElements['00080030'].value[0]; - meta.StudyInstanceUID = dicomElements['0020000D'].value[0]; - meta.StudyID = dicomElements['00200010'].value[0]; + meta.StudyDate = dataElements['00080020'].value[0]; + meta.StudyTime = dataElements['00080030'].value[0]; + meta.StudyInstanceUID = dataElements['0020000D'].value[0]; + meta.StudyID = dataElements['00200010'].value[0]; // Series - meta.SeriesInstanceUID = dicomElements['0020000E'].value[0]; - meta.SeriesNumber = dicomElements['00200011'].value[0]; + meta.SeriesInstanceUID = dataElements['0020000E'].value[0]; + meta.SeriesNumber = dataElements['00200011'].value[0]; // ReferringPhysicianName - meta.ReferringPhysicianName = dicomElements['00080090'].value[0]; + meta.ReferringPhysicianName = dataElements['00080090'].value[0]; // patient info - meta.PatientName = dicomElements['00100010'].value[0]; - meta.PatientID = dicomElements['00100020'].value[0]; - meta.PatientBirthDate = dicomElements['00100030'].value[0]; - meta.PatientSex = dicomElements['00100040'].value[0]; + meta.PatientName = dataElements['00100010'].value[0]; + meta.PatientID = dataElements['00100020'].value[0]; + meta.PatientBirthDate = dataElements['00100030'].value[0]; + meta.PatientSex = dataElements['00100040'].value[0]; // Enhanced General Equipment Module - meta.Manufacturer = dicomElements['00080070'].value[0]; - meta.ManufacturerModelName = dicomElements['00081090'].value[0]; - meta.DeviceSerialNumber = dicomElements['00181000'].value[0]; - meta.SoftwareVersions = dicomElements['00181020'].value[0]; + meta.Manufacturer = dataElements['00080070'].value[0]; + meta.ManufacturerModelName = dataElements['00081090'].value[0]; + meta.DeviceSerialNumber = dataElements['00181000'].value[0]; + meta.SoftwareVersions = dataElements['00181020'].value[0]; // dicom seg dimension meta.DimensionOrganizationSequence = dimension.organizations; meta.DimensionIndexSequence = dimension.indices; @@ -899,19 +908,19 @@ export class MaskFactory { meta.custom = { segments: segments, frameInfos: frameInfos, - SOPInstanceUID: dicomElements['00080018'].value[0] + SOPInstanceUID: dataElements['00080018'].value[0] }; // number of files: in this case equal to number slices, // used to calculate buffer size meta.numberOfFiles = numberOfSlices; // FrameOfReferenceUID (optional) - const frameOfReferenceUID = dicomElements['00200052']; + const frameOfReferenceUID = dataElements['00200052']; if (frameOfReferenceUID) { meta.FrameOfReferenceUID = frameOfReferenceUID.value[0]; } // LossyImageCompression (optional) - const lossyImageCompression = dicomElements['00282110']; + const lossyImageCompression = dataElements['00282110']; if (lossyImageCompression) { meta.LossyImageCompression = lossyImageCompression.value[0]; } diff --git a/src/image/viewFactory.js b/src/image/viewFactory.js index 1354bc9c1a..8e08765bfc 100644 --- a/src/image/viewFactory.js +++ b/src/image/viewFactory.js @@ -8,8 +8,13 @@ import { // doc imports /* eslint-disable no-unused-vars */ import {Image} from './image'; +import {DataElement} from '../dicom/dataElement'; /* eslint-enable no-unused-vars */ +/** + * @typedef {Object} DataElements + */ + /** * {@link View} factory. */ @@ -18,11 +23,11 @@ export class ViewFactory { /** * Get an View object from the read DICOM file. * - * @param {object} dicomElements The DICOM tags. + * @param {DataElements} dataElements The DICOM tags. * @param {Image} image The associated image. * @returns {View} The new View. */ - create(dicomElements, image) { + create(dataElements, image) { // view const view = new View(image); diff --git a/src/index.js b/src/index.js index 96bba77f8a..c83de28612 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,7 @@ import { getElementsFromJSONTags, DicomWriter } from './dicom/dicomWriter'; +import {DataElement} from './dicom/dataElement'; import {TagValueExtractor} from './dicom/dicomElementsWrapper'; import {addTagsToDictionary} from './dicom/dictionary'; import { @@ -63,6 +64,7 @@ import {i18n} from './utils/i18n'; export { App, ViewController, + DataElement, DicomParser, DicomWriter, TagValueExtractor, From 1a5e92b7b9e26792041cb7ae82ef4d9912140ae3 Mon Sep 17 00:00:00 2001 From: ivmartel Date: Mon, 21 Aug 2023 15:33:33 +0200 Subject: [PATCH 2/3] Add type to value extractor --- src/dicom/dicomElementsWrapper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dicom/dicomElementsWrapper.js b/src/dicom/dicomElementsWrapper.js index d4a29e1958..47fedb5e75 100644 --- a/src/dicom/dicomElementsWrapper.js +++ b/src/dicom/dicomElementsWrapper.js @@ -20,6 +20,7 @@ import {logger} from '../utils/logger'; // doc imports /* eslint-disable no-unused-vars */ import {Tag} from './dicomTag'; +import {DataElement} from './dataElement'; /* eslint-enable no-unused-vars */ /** @@ -749,7 +750,7 @@ export class TagValueExtractor { /** * Get the time. * - * @param {object} _elements The DICOM elements. + * @param {Object} _elements The DICOM elements. * @returns {number|undefined} The time value if available. */ getTime(_elements) { From 4ed0ee8f056c688d7ed7ffe815ef14559bc9c99f Mon Sep 17 00:00:00 2001 From: ivmartel Date: Mon, 21 Aug 2023 15:44:39 +0200 Subject: [PATCH 3/3] Remove typedef when used only once --- src/image/dicomBufferToView.js | 6 +----- src/image/viewFactory.js | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/image/dicomBufferToView.js b/src/image/dicomBufferToView.js index 21274e04fc..31dd65fb7c 100644 --- a/src/image/dicomBufferToView.js +++ b/src/image/dicomBufferToView.js @@ -12,10 +12,6 @@ import {PixelBufferDecoder} from './decoder'; import {DataElement} from '../dicom/dataElement'; /* eslint-enable no-unused-vars */ -/** - * @typedef {Object} DataElements - */ - /** * Create a View from a DICOM buffer. */ @@ -54,7 +50,7 @@ export class DicomBufferToView { /** * Get the factory associated to input DICOM elements. * - * @param {DataElements} elements The DICOM elements. + * @param {Object} elements The DICOM elements. * @returns {ImageFactory|MaskFactory} The associated factory. */ #getFactory(elements) { diff --git a/src/image/viewFactory.js b/src/image/viewFactory.js index 3e4b818545..18f1b9a0b8 100644 --- a/src/image/viewFactory.js +++ b/src/image/viewFactory.js @@ -11,10 +11,6 @@ import {Image} from './image'; import {DataElement} from '../dicom/dataElement'; /* eslint-enable no-unused-vars */ -/** - * @typedef {Object} DataElements - */ - /** * {@link View} factory. */ @@ -23,7 +19,7 @@ export class ViewFactory { /** * Get an View object from the read DICOM file. * - * @param {DataElements} dataElements The DICOM tags. + * @param {Object} dataElements The DICOM tags. * @param {Image} image The associated image. * @returns {View} The new View. */