@abasb75/dicom-parser
Version:
a javascript powerfull dicom parser
559 lines (558 loc) • 21.6 kB
JavaScript
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;