UNPKG

@abasb75/dicom-parser

Version:

a javascript powerfull dicom parser

559 lines (558 loc) 21.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; import PixelData from "./utils/PixelData"; import Tag from "./Tag"; import Value from "./Value"; import PaletteColor from "./utils/PaletteColor"; var Dataset = /** @class */ (function () { function Dataset(tags, dataView, littleEndian, start, end) { /** duration of parse */ Object.defineProperty(this, "start", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "end", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "tags", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "transferSyntaxUID", { enumerable: true, configurable: true, writable: true, value: "1.2.840.10008.1.2" }); Object.defineProperty(this, "dataView", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "studyInstanceUID", { enumerable: true, configurable: true, writable: true, value: "" }); Object.defineProperty(this, "studyID", { enumerable: true, configurable: true, writable: true, value: "" }); Object.defineProperty(this, "seriesInstanceUID", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "seriesNumber", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "studyDate", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "studyTime", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "littleEndian", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "accessionNumber", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "imageType", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "modality", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "seriesDescription", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "basicOffsetTable", { enumerable: true, configurable: true, writable: true, value: void 0 }); /** modules */ Object.defineProperty(this, "voiLUTModule", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "patientModule", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "pixelModule", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "scalingModule", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.tags = tags; this.dataView = dataView; this.littleEndian = littleEndian; this.studyID = this.get(0x0020, 0x0010); this.studyInstanceUID = this.string(0x0020, 0x000D); this.seriesInstanceUID = this.get(0x0020, 0x000E); this.seriesNumber = this.get(0x0020, 0x0011); this.studyDate = this.date(0x0008, 0x0020); this.studyTime = this.time(0x0008, 0x0030); this.accessionNumber = this.string(0x0008, 0x0050); this.imageType = this.get(0x0008, 0x0008); this.modality = this.get(0x0008, 0x0060); this.seriesDescription = this.string(0x0008, 0x103E); this.voiLUTModule = this.getVOILutModule(); this.patientModule = this.getPatientModule(); this.pixelModule = this.getPixelModule(); this.scalingModule = this.getScalingModule(); this.start = start; this.end = end; } Object.defineProperty(Dataset.prototype, "hasPixelData", { enumerable: false, configurable: true, writable: true, value: function () { if (this.tags['0x7FE00010'] || this.tags['0x7FE00008'] || this.tags['0x7FE00009']) { return true; } return false; } }); Object.defineProperty(Dataset.prototype, "getPixelTypes", { enumerable: false, configurable: true, writable: true, value: function () { if (this.tags['0x7FE00008'] || this.tags['0x7FE00009']) { return Dataset.Float; } else if (this.tags['0x7FE00010']) { return Dataset.Integer; } return null; } }); Object.defineProperty(Dataset.prototype, "getPixelData", { enumerable: false, configurable: true, writable: true, value: function () { return __awaiter(this, arguments, void 0, function (frame) { if (frame === void 0) { frame = 0; } return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, PixelData.get(this, frame)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } }); Object.defineProperty(Dataset.prototype, "getVOILutModule", { enumerable: false, configurable: true, writable: true, value: function () { return { voiLUTFunction: this.get(0x0028, 0x1056), windowWidth: this.int(0x0028, 0x1051), windowCenter: this.int(0x0028, 0x1050), voiLUTSequence: this.get(0x0028, 0x3010), lutDescriptor: this.get(0x0028, 0x3002), lutExplanation: this.get(0x0028, 0x3003), lutData: this.get(0x0028, 0x3006), windowCenterAndWidthExplanation: this.get(0x0028, 0x1055), }; } }); Object.defineProperty(Dataset.prototype, "getPatientModule", { enumerable: false, configurable: true, writable: true, value: function () { return { patientName: this.get(0x0010, 0x0010), patientID: this.get(0x0010, 0x0020), typeofPatientID: this.get(0x0010, 0x0022), patientSex: this.get(0x0010, 0x0040), patientBirthDate: this.get(0x0010, 0x0030), patientAge: this.get(0x0010, 0x1010), patientSize: this.get(0x0010, 0x1020), otherPatientIDs: this.get(0x0010, 0x1000), otherPatientNames: this.get(0x0010, 0x1001), patientWeight: this.get(0x0010, 0x1030), }; } }); Object.defineProperty(Dataset.prototype, "getPixelModule", { enumerable: false, configurable: true, writable: true, value: function () { var pixelMeasuresSequence = this.get(0x0028, 0x9110); return { pixelMeasuresSequence: pixelMeasuresSequence, photometricInterpretation: this.get(0x0028, 0x0004), numberOfFrames: this.int(0x0028, 0x0008), pixelRepresentation: this.int(0x0028, 0x0103), pixelSpacing: this.getPixelSpacing(), rows: this.int(0x0028, 0x0010), columns: this.int(0x0028, 0x0011), bitsAllocated: this.int(0x0028, 0x0100), highBit: this.int(0x0028, 0x0102), bitsStored: this.int(0x0028, 0x0101), samplesPerPixel: this.int(0x0028, 0x0002), pixelDataProviderURL: this.get(0x0028, 0x7FE0), pixelPaddingRangeLimit: this.get(0x0028, 0x0121), extendedOffsetTable: this.get(0x7FE0, 0x0001), extendedOffsetTableLengths: this.get(0x7FE0, 0x0002), pixelAspectRatio: this.get(0x0028, 0x0034), planarConfiguration: this.int(0x0028, 0x0006), redPaletteColorLookupTableDescriptor: this.get(0x0028, 0x1101), greenPaletteColorLookupTableDescriptor: this.get(0x0028, 0x1102), bluePaletteColorLookupTableDescriptor: this.get(0x0028, 0x1103), alphaPaletteColorLookupTableDescriptor: this.get(0x0028, 0x1104), redPaletteColorLookupTableData: this.get(0x0028, 0x1201), greenPaletteColorLookupTableData: this.get(0x0028, 0x1202), bluePaletteColorLookupTableData: this.get(0x0028, 0x1203), alphaPaletteColorLookupTableData: this.get(0x0028, 0x1204), segmentedRedPaletteColorLookupTableData: this.get(0x0028, 0x1221), segmentedGreenPaletteColorLookupTableData: this.get(0x0028, 0x1222), segmentedBluePaletteColorLookupTableData: this.get(0x0028, 0x1223), segmentedAlphaPaletteColorLookupTableData: this.get(0x0028, 0x1224), }; } }); // TODO: need to add more login to advance Object.defineProperty(Dataset.prototype, "getPixelSpacing", { enumerable: false, configurable: true, writable: true, value: function () { var pixelSpacing = this.get(0x0028, 0x0030); if (pixelSpacing) return pixelSpacing; var sharedFunctionalGroupsSequence = this.tags["0x52009229"]; console.log({ sharedFunctionalGroupsSequence: sharedFunctionalGroupsSequence }); if (sharedFunctionalGroupsSequence && sharedFunctionalGroupsSequence.vr === "SQ" && typeof sharedFunctionalGroupsSequence.value) { var pixelSpacing_1 = this._findTagsByKey('0x00280030', sharedFunctionalGroupsSequence.value, 1024); if (pixelSpacing_1) { return Value.byVr(this.dataView, pixelSpacing_1.offset, pixelSpacing_1.valueLength, pixelSpacing_1.vr, this.littleEndian); } } } }); Object.defineProperty(Dataset.prototype, "getScalingModule", { enumerable: false, configurable: true, writable: true, value: function () { return { rescaleSlope: this.int(0x0028, 0x1053), rescaleIntercept: this.int(0x0028, 0x1052), modality: this.modality, }; } }); Object.defineProperty(Dataset.prototype, "date", { enumerable: false, configurable: true, writable: true, value: function (group, element) { var dateValue = this.get(group, element); if (/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/.exec(dateValue)) { var dateVaues = dateValue.split('-'); return { year: dateVaues[0], month: dateVaues[1], day: dateVaues[2], }; } return dateValue; } }); Object.defineProperty(Dataset.prototype, "time", { enumerable: false, configurable: true, writable: true, value: function (group, element) { var dateValue = this.get(group, element); if (/^[0-9]{2}\:[0-9]{2}\:[0-9]{2}$/.exec(dateValue)) { var dateVaues = dateValue.split(':'); return { hour: dateVaues[0], minute: dateVaues[1], second: dateVaues[2], }; } return dateValue; } }); Object.defineProperty(Dataset.prototype, "int", { enumerable: false, configurable: true, writable: true, value: function (group, element) { var is = this.get(group, element); if (typeof is === "number") { return is; } else if (Array.isArray(is) && typeof is[0] === "number") { return is[0]; } else { return undefined; } } }); Object.defineProperty(Dataset.prototype, "get", { enumerable: false, configurable: true, writable: true, value: function (group, element) { var value = this.getValue(group, element); return value; } }); Object.defineProperty(Dataset.prototype, "string", { enumerable: false, configurable: true, writable: true, value: function (group, element) { return this.getValue(group, element, 'string') + ""; } }); Object.defineProperty(Dataset.prototype, "getValue", { enumerable: false, configurable: true, writable: true, value: function (element, elementId, vr) { if (!element && !elementId) { return ""; } var _group, _element = ""; if (typeof element === 'string' && element.length >= 8) { var el = element.replace(/^0[xX]/, ''); if (el.length !== 8) { return ""; } _group = el.slice(0, 3); _element = el.slice(4, 7); } else if (typeof element === 'number' && element > 0xffff) { var el = Tag.intTo4digitString(element); _group = el.slice(0, 3); _element = el.slice(4, 7); } else { _group = this._reformatToString(element); _element = this._reformatToString(elementId); if (!_group || !_element) return ""; } var key = "0x".concat(_group).concat(_element); var tag = this._findTagsByKey(key, this.tags); if (!tag) { return ""; } var _vr = vr || (tag === null || tag === void 0 ? void 0 : tag.vr) || Tag.getTagVRFromDictionary(_group, _element) || "AA"; if (_vr === "SQ") { return tag.value; } return this._getValue(tag, _vr); } }); Object.defineProperty(Dataset.prototype, "getPaletteColorData", { enumerable: false, configurable: true, writable: true, value: function () { return PaletteColor.get(this); } }); Object.defineProperty(Dataset.prototype, "_findTagsByKey", { enumerable: false, configurable: true, writable: true, value: function (key, tags, depth) { if (depth === void 0) { depth = 1; } if (tags[key]) { return tags[key]; } if (depth === 1) { return null; } var keys = Object.keys(tags); var sqs = []; keys.forEach(function (key) { if (tags[key].vr === 'SQ' && typeof tags[key].value === "object") { sqs.push(tags[key].value); } }); for (var i = 0; i < sqs.length; i++) { var finded = this._findTagsByKey(key, sqs[i], depth - 1); if (finded) { return finded; } } return null; } }); Object.defineProperty(Dataset.prototype, "_getValue", { enumerable: false, configurable: true, writable: true, value: function (tag, vr) { if (vr === void 0) { vr = "AA"; } var offset = tag.offset; if (!offset) return ""; var len = tag.valueLength; var value = Value.byVr(this.dataView, offset, len, vr, this.littleEndian); tag.value = value; return value; } }); // private _getSqValues(key:string){ // const sqValues:object = {}; // const values = this.tags[key]?.value as Tags; // console.log({values}) // if(!values) return {}; // const keys = Object.keys(values as object); // if(!keys || !Array.isArray(keys) || keys.length<1){ // return {}; // } // keys.forEach((key:string)=>{ // //@ts-ignore // if(typeof values[key] === "object"){ // const name = (values[key])?.name as string; // if(typeof name === "string" && name.length>0){ // const offset = (values[key])?.offset; // const vr = (values[key])?.vr; // const len = (values[key])?.valueLength; // //@ts-ignore // sqValues[name] = Value.byVr( // this.dataView, // offset, // len, // vr, // this.littleEndian // ); // } // } // }) // } Object.defineProperty(Dataset.prototype, "_reformatToString", { enumerable: false, configurable: true, writable: true, value: function (input) { if (!input) return ""; if (typeof input === "string") { return input.replace(/^0[xX]/, ''); } return Tag.intTo4digitString(input); } }); Object.defineProperty(Dataset, "Float", { enumerable: true, configurable: true, writable: true, value: "Float" }); Object.defineProperty(Dataset, "Integer", { enumerable: true, configurable: true, writable: true, value: "Integer" }); return Dataset; }()); export default Dataset;