larvitar 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/larvitar.js +5 -3
- package/dist/larvitar.js.map +1 -1
- package/package.json +6 -2
- package/.github/workflows/build-docs.yml +0 -59
- package/.github/workflows/codeql-analysis.yml +0 -71
- package/.github/workflows/deploy.yml +0 -37
- package/.vscode/settings.json +0 -4
- package/CODE_OF_CONDUCT.md +0 -76
- package/MIGRATION.md +0 -25
- package/bundler/webpack.common.js +0 -27
- package/bundler/webpack.dev.js +0 -23
- package/bundler/webpack.prod.js +0 -19
- package/decs.d.ts +0 -12
- package/imaging/MetaDataReadable.ts +0 -42
- package/imaging/MetaDataTypes.ts +0 -3491
- package/imaging/dataDictionary.json +0 -21866
- package/imaging/imageAnonymization.ts +0 -135
- package/imaging/imageColormaps.ts +0 -217
- package/imaging/imageContours.ts +0 -196
- package/imaging/imageIo.ts +0 -251
- package/imaging/imageLayers.ts +0 -121
- package/imaging/imageLoading.ts +0 -299
- package/imaging/imageParsing.ts +0 -444
- package/imaging/imagePresets.ts +0 -156
- package/imaging/imageRendering.ts +0 -1091
- package/imaging/imageReslice.ts +0 -87
- package/imaging/imageStore.ts +0 -487
- package/imaging/imageTags.ts +0 -609
- package/imaging/imageTools.js +0 -708
- package/imaging/imageUtils.ts +0 -1079
- package/imaging/loaders/commonLoader.ts +0 -275
- package/imaging/loaders/dicomLoader.ts +0 -66
- package/imaging/loaders/fileLoader.ts +0 -71
- package/imaging/loaders/multiframeLoader.ts +0 -435
- package/imaging/loaders/nrrdLoader.ts +0 -630
- package/imaging/loaders/resliceLoader.ts +0 -205
- package/imaging/monitors/memory.ts +0 -151
- package/imaging/monitors/performance.ts +0 -34
- package/imaging/parsers/ecg.ts +0 -54
- package/imaging/parsers/nrrd.js +0 -485
- package/imaging/tools/README.md +0 -27
- package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
- package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
- package/imaging/tools/custom/contourTool.js +0 -1884
- package/imaging/tools/custom/diameterTool.js +0 -141
- package/imaging/tools/custom/editMaskTool.js +0 -141
- package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
- package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
- package/imaging/tools/custom/polylineScissorsTool.js +0 -59
- package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
- package/imaging/tools/custom/seedTool.js +0 -342
- package/imaging/tools/custom/setLabelMap3D.ts +0 -242
- package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
- package/imaging/tools/default.ts +0 -594
- package/imaging/tools/interaction.ts +0 -266
- package/imaging/tools/io.ts +0 -229
- package/imaging/tools/main.ts +0 -424
- package/imaging/tools/segmentation.ts +0 -532
- package/imaging/tools/segmentations.md +0 -38
- package/imaging/tools/state.ts +0 -74
- package/imaging/tools/strategies/eraseFreehand.js +0 -76
- package/imaging/tools/strategies/fillFreehand.js +0 -79
- package/imaging/tools/strategies/index.js +0 -2
- package/imaging/tools/types.d.ts +0 -243
- package/imaging/types.d.ts +0 -200
- package/imaging/waveforms/ecg.ts +0 -191
- package/index.ts +0 -431
- package/jsdoc.json +0 -52
- package/rollup.config.js +0 -51
- package/template/.gitkeep +0 -0
- package/tsconfig.json +0 -102
package/imaging/imageTags.ts
DELETED
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
// external libraries
|
|
2
|
-
import TAG_DICT from "./dataDictionary.json";
|
|
3
|
-
//Changed data dictionary using:
|
|
4
|
-
//regex "\((\d+),(\d+)\)"
|
|
5
|
-
//"x$1$2"
|
|
6
|
-
//now tag are in format "x00000000"
|
|
7
|
-
import { convertBytes } from "dicom-character-set";
|
|
8
|
-
import { DataSet, Element } from "dicom-parser";
|
|
9
|
-
import type { MetaDataTypes } from "./MetaDataTypes"; //custom type created as tag-type. { "x0000000":string, ...}
|
|
10
|
-
/*
|
|
11
|
-
* This module provides the following functions to be exported:
|
|
12
|
-
* parseTag(dataSet, propertyName, element)
|
|
13
|
-
* getDICOMTagCode(code)
|
|
14
|
-
* getDICOMTag(code)
|
|
15
|
-
* isStringVr(vr)
|
|
16
|
-
* parseDateTag(tagValue)
|
|
17
|
-
* parseDateTimeTag(tagValue)
|
|
18
|
-
* parseTimeTag(tagValue)
|
|
19
|
-
* parsePatientNameTag(tagValue)
|
|
20
|
-
* parseAgeTag(tagValue)
|
|
21
|
-
* parseDICOMFileIDTag(tagValue)
|
|
22
|
-
* getTagValue(dataSet, tag)
|
|
23
|
-
* formatDate(date)
|
|
24
|
-
* formatDateTime(date)
|
|
25
|
-
* isValidDate(d)
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Convert date from dicom tag
|
|
30
|
-
* @instance
|
|
31
|
-
* @function formatDate
|
|
32
|
-
* @param {Date} dicomDate - A date from a DICOM tag
|
|
33
|
-
* @return {String} - The human readable date
|
|
34
|
-
*/
|
|
35
|
-
let formatDate = function (date: string) {
|
|
36
|
-
let yyyy = date.slice(0, 4);
|
|
37
|
-
let mm = date.slice(4, 6);
|
|
38
|
-
let dd = date.slice(6, 8);
|
|
39
|
-
return (
|
|
40
|
-
yyyy + "-" + (mm[1] ? mm : "0" + mm[0]) + "-" + (dd[1] ? dd : "0" + dd[0])
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Convert datetime from dicom tag
|
|
46
|
-
* @instance
|
|
47
|
-
* @function formatDateTime
|
|
48
|
-
* @param {Date} dicomDateTime - A dateTime from a DICOM tag
|
|
49
|
-
* @return {String} - The human readable dateTime
|
|
50
|
-
*/
|
|
51
|
-
let formatDateTime = function (date: string) {
|
|
52
|
-
let yyyy = date.slice(0, 4);
|
|
53
|
-
let mm = date.slice(4, 6);
|
|
54
|
-
let dd = date.slice(6, 8);
|
|
55
|
-
let hh = date.slice(8, 10);
|
|
56
|
-
let m = date.slice(10, 12);
|
|
57
|
-
let ss = date.slice(12, 14);
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
yyyy +
|
|
61
|
-
"-" +
|
|
62
|
-
(mm[1] ? mm : "0" + mm[0]) +
|
|
63
|
-
"-" +
|
|
64
|
-
(dd[1] ? dd : "0" + dd[0]) +
|
|
65
|
-
"/" +
|
|
66
|
-
hh +
|
|
67
|
-
":" +
|
|
68
|
-
m +
|
|
69
|
-
":" +
|
|
70
|
-
ss
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Check if argument is a valid Date Object
|
|
76
|
-
* @instance
|
|
77
|
-
* @function isValidDate
|
|
78
|
-
* @param {Date} d - The date object to be checked
|
|
79
|
-
* @return {Boolean} - Boolean result
|
|
80
|
-
*/
|
|
81
|
-
const isValidDate = function (d: Date) {
|
|
82
|
-
return d instanceof Date && !isNaN(d.getTime());
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Parse a dicom date tag into human readable format
|
|
87
|
-
* @instance
|
|
88
|
-
* @function parseDateTag
|
|
89
|
-
* @param {String} tagValue - The string to be parsed
|
|
90
|
-
* @return {String} - The parsed result
|
|
91
|
-
*/
|
|
92
|
-
const parseDateTag = function (tagValue: string) {
|
|
93
|
-
if (!tagValue) return "";
|
|
94
|
-
const year = tagValue.substring(0, 4);
|
|
95
|
-
const month = tagValue.substring(4, 6);
|
|
96
|
-
const day = tagValue.substring(6, 8);
|
|
97
|
-
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
|
|
98
|
-
if (isValidDate(date) === true) {
|
|
99
|
-
return date.toISOString();
|
|
100
|
-
} else {
|
|
101
|
-
return tagValue;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Parse a dicom datetime tag into human readable format
|
|
107
|
-
* @instance
|
|
108
|
-
* @function parseDateTimeTag
|
|
109
|
-
* @param {String} tagValue - The string to be parsed
|
|
110
|
-
* @return {String} - The parsed result
|
|
111
|
-
*/
|
|
112
|
-
const parseDateTimeTag = function (tagValue: string) {
|
|
113
|
-
if (!tagValue) return "";
|
|
114
|
-
const year = tagValue.substring(0, 4);
|
|
115
|
-
const month = tagValue.substring(4, 6);
|
|
116
|
-
const day = tagValue.substring(6, 8);
|
|
117
|
-
const hour = tagValue.substring(8, 10);
|
|
118
|
-
const min = tagValue.substring(10, 12);
|
|
119
|
-
const sec = tagValue.substring(12, 14);
|
|
120
|
-
// const msec = tagValue.substring(15, 21);
|
|
121
|
-
const date = new Date(
|
|
122
|
-
parseInt(year),
|
|
123
|
-
parseInt(month) - 1,
|
|
124
|
-
parseInt(day),
|
|
125
|
-
parseInt(hour),
|
|
126
|
-
parseInt(min),
|
|
127
|
-
parseInt(sec),
|
|
128
|
-
parseInt(sec)
|
|
129
|
-
);
|
|
130
|
-
if (isValidDate(date) === true) {
|
|
131
|
-
return date.toISOString();
|
|
132
|
-
} else {
|
|
133
|
-
return tagValue;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Parse a dicom time tag into human readable format
|
|
139
|
-
* @instance
|
|
140
|
-
* @function parseTimeTag
|
|
141
|
-
* @param {String} tagValue - The string to be parsed
|
|
142
|
-
* @return {String} - The parsed result
|
|
143
|
-
*/
|
|
144
|
-
const parseTimeTag = function (tagValue: string) {
|
|
145
|
-
if (!tagValue) return "";
|
|
146
|
-
let hour = tagValue.substring(0, 2);
|
|
147
|
-
let min = tagValue.substring(2, 4);
|
|
148
|
-
let sec = tagValue.substring(4, 6);
|
|
149
|
-
let msec = tagValue.substring(7, 13) ? tagValue.substring(7, 13) : "0";
|
|
150
|
-
let result = hour + ":" + min + ":" + sec + "." + msec;
|
|
151
|
-
return result;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Parse a dicom patient tag into human readable format
|
|
156
|
-
* @instance
|
|
157
|
-
* @function parsePatientNameTag
|
|
158
|
-
* @param {String} tagValue - The string to be parsed
|
|
159
|
-
* @return {String} - The parsed result
|
|
160
|
-
*/
|
|
161
|
-
const parsePatientNameTag = function (tagValue: string) {
|
|
162
|
-
if (!tagValue) return "";
|
|
163
|
-
return tagValue.replace(/\^/gi, " ");
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Parse a dicom age tag into human readable format
|
|
168
|
-
* @instance
|
|
169
|
-
* @function parseAgeTag
|
|
170
|
-
* @param {String} tagValue - The string to be parsed
|
|
171
|
-
* @return {String} - The parsed result
|
|
172
|
-
*/
|
|
173
|
-
const parseAgeTag = function (tagValue: string) {
|
|
174
|
-
if (!tagValue) return "";
|
|
175
|
-
let regs = /(\d{3})(D|W|M|Y)/gim.exec(tagValue);
|
|
176
|
-
if (regs) {
|
|
177
|
-
return parseInt(regs[1]) + " " + regs[2];
|
|
178
|
-
} else {
|
|
179
|
-
return "";
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Parse a dicom fileID tag into human readable format
|
|
185
|
-
* @instance
|
|
186
|
-
* @function parseDICOMFileIDTag
|
|
187
|
-
* @param {String} tagValue - The string to be parsed
|
|
188
|
-
* @return {String} - The parsed result
|
|
189
|
-
*/
|
|
190
|
-
const parseDICOMFileIDTag = function (tagValue: string) {
|
|
191
|
-
// The DICOM File Service does not specify any "separator" between
|
|
192
|
-
// the Components of the File ID. This is a Value Representation issue that
|
|
193
|
-
// may be addressed in a specific manner by each Media Format Layer.
|
|
194
|
-
// In DICOM IODs, File ID Components are generally handled as multiple
|
|
195
|
-
// Values and separated by "backslashes".
|
|
196
|
-
// There is no requirement that Media Format Layers use this separator.
|
|
197
|
-
if (!tagValue) return "";
|
|
198
|
-
// @ts-ignore //TODO this can't work!
|
|
199
|
-
return tagValue.split("\\").join(path.sep);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Check if argument is a string of concatenated vrs
|
|
204
|
-
* @instance
|
|
205
|
-
* @function isStringVr
|
|
206
|
-
* @param {String} vr - The string to be checked
|
|
207
|
-
* @return {Boolean} - Boolean result
|
|
208
|
-
*/
|
|
209
|
-
const isStringVr = function (vr: string) {
|
|
210
|
-
// vr can be a string of concatenated vrs
|
|
211
|
-
vr = vr || "";
|
|
212
|
-
vr = vr.split("|")[0];
|
|
213
|
-
|
|
214
|
-
if (
|
|
215
|
-
vr === "AT" ||
|
|
216
|
-
vr === "FL" ||
|
|
217
|
-
vr === "FD" ||
|
|
218
|
-
vr === "OB" ||
|
|
219
|
-
vr === "OF" ||
|
|
220
|
-
vr === "OW" ||
|
|
221
|
-
vr === "SI" ||
|
|
222
|
-
vr === "SL" || // signed long
|
|
223
|
-
vr === "SQ" ||
|
|
224
|
-
vr === "SS" ||
|
|
225
|
-
vr === "UL" ||
|
|
226
|
-
vr === "US"
|
|
227
|
-
) {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
return true;
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Get the dicom tag code from dicom image
|
|
235
|
-
* @instance
|
|
236
|
-
* @function getDICOMTagCode
|
|
237
|
-
* @param {String} dicomTag - The original DICOM tag code
|
|
238
|
-
* @return {String} - The human readable DICOM tag code
|
|
239
|
-
*/
|
|
240
|
-
/*function getDICOMTagCode(code: string) {
|
|
241
|
-
let re = /x(\w{4})(\w{4})/;
|
|
242
|
-
let result = re.exec(code);
|
|
243
|
-
if (!result) {
|
|
244
|
-
return code;
|
|
245
|
-
}
|
|
246
|
-
let newCode = "(" + result[1] + "," + result[2] + ")";
|
|
247
|
-
newCode = newCode.toUpperCase();
|
|
248
|
-
return newCode;
|
|
249
|
-
}*/
|
|
250
|
-
//This function is not necessary animore because dataDictionary contains tags in format "x00000000"
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Get the dicom tag from dicom tag code
|
|
254
|
-
* @instance
|
|
255
|
-
* @function getDICOMTag
|
|
256
|
-
* @param {String} dicomTagCode - The original DICOM tag code
|
|
257
|
-
* @return {String} - The human readable DICOM tag
|
|
258
|
-
*/
|
|
259
|
-
function getDICOMTag(code: string) {
|
|
260
|
-
let newCode = code;
|
|
261
|
-
|
|
262
|
-
if (!Object.keys(TAG_DICT).includes(newCode)) {
|
|
263
|
-
console.debug(`Invalid tag key: ${newCode}`);
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
266
|
-
// force type to keyof typeof TAG_DICT after having checked that it is a valid key
|
|
267
|
-
let tag = TAG_DICT[newCode as keyof typeof TAG_DICT];
|
|
268
|
-
return tag;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Parse a DICOM Tag according to its type
|
|
273
|
-
* @instance
|
|
274
|
-
* @function parseTag
|
|
275
|
-
* @param {Object} dataSet - The parsed dataset object from dicom parser
|
|
276
|
-
* @param {String} propertyName - The tag name
|
|
277
|
-
* @param {Object} element - The parsed dataset element
|
|
278
|
-
* @return {String} - The DICOM Tag value
|
|
279
|
-
*/
|
|
280
|
-
export function parseTag<T>(
|
|
281
|
-
dataSet: DataSet,
|
|
282
|
-
propertyName: string, //x0000000 string
|
|
283
|
-
element: Element // TODO-ts better type @szanchi
|
|
284
|
-
) {
|
|
285
|
-
// GET VR
|
|
286
|
-
var tagData = dataSet.elements[propertyName];
|
|
287
|
-
var vr = tagData?.vr;
|
|
288
|
-
if (!vr) {
|
|
289
|
-
// use dicom dict to get VR
|
|
290
|
-
var tag = getDICOMTag(propertyName);
|
|
291
|
-
//From now on tag is an object of datadictionary.json (TAG_TYPE) and tag.tag is rapresented as "x0000000"
|
|
292
|
-
//so propertyname= tag.tag=keyof MetaDataTypes
|
|
293
|
-
if (tag && tag.vr) {
|
|
294
|
-
vr = tag.vr;
|
|
295
|
-
} else {
|
|
296
|
-
return element;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
var valueIn;
|
|
301
|
-
var valueOut;
|
|
302
|
-
|
|
303
|
-
if (isStringVr(vr)) {
|
|
304
|
-
// We ask the dataset to give us the element's data in string form.
|
|
305
|
-
// Most elements are strings but some aren't so we do a quick check
|
|
306
|
-
// to make sure it actually has all ascii characters so we know it is
|
|
307
|
-
// reasonable to display it.
|
|
308
|
-
let TAG = propertyName as keyof MetaDataTypes;
|
|
309
|
-
var str = dataSet.string(propertyName);
|
|
310
|
-
if (str === undefined) {
|
|
311
|
-
return undefined;
|
|
312
|
-
} else {
|
|
313
|
-
// the string will be undefined if the element is present but has no data
|
|
314
|
-
// (i.e. attribute is of type 2 or 3) so we only display the string if it has
|
|
315
|
-
// data. Note that the length of the element will be 0 to indicate "no data"
|
|
316
|
-
// so we don't put anything here for the value in that case.
|
|
317
|
-
valueIn = str;
|
|
318
|
-
valueOut = str as MetaDataTypes[typeof TAG];
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// A string of characters representing an Integer in base-10 (decimal),
|
|
322
|
-
// shall contain only the characters 0 - 9, with an optional leading "+" or "-".
|
|
323
|
-
// It may be padded with leading and/or trailing spaces. Embedded spaces
|
|
324
|
-
// are not allowed. The integer, n, represented shall be in the range:
|
|
325
|
-
// -231 <= n <= (231 - 1).
|
|
326
|
-
if (vr === "IS") {
|
|
327
|
-
valueOut = parseInt(valueIn);
|
|
328
|
-
}
|
|
329
|
-
// A string of characters representing either a fixed point number
|
|
330
|
-
// or a floating point number. A fixed point number shall contain only
|
|
331
|
-
// the characters 0-9 with an optional leading "+" or "-" and an optional "."
|
|
332
|
-
// to mark the decimal point. A floating point number shall be conveyed
|
|
333
|
-
// as defined in ANSI X3.9, with an "E" or "e" to indicate the start
|
|
334
|
-
// of the exponent. Decimal Strings may be padded with leading or trailing spaces.
|
|
335
|
-
// Embedded spaces are not allowed.
|
|
336
|
-
else if (vr === "DS") {
|
|
337
|
-
valueIn = valueIn.split("\\").map(Number);
|
|
338
|
-
if (propertyName == "x00281050" || propertyName == "x00281051") {
|
|
339
|
-
valueOut = valueIn.length > 0 ? valueIn[0] : valueIn;
|
|
340
|
-
} else {
|
|
341
|
-
valueOut = valueIn.length == 1 ? valueIn[0] : valueIn;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
// A string of characters of the format YYYYMMDD; where YYYY shall contain year,
|
|
345
|
-
// MM shall contain the month, and DD shall contain the day,
|
|
346
|
-
// interpreted as a date of the Gregorian calendar system.
|
|
347
|
-
else if (vr === "DA") {
|
|
348
|
-
valueOut = parseDateTag(valueIn);
|
|
349
|
-
}
|
|
350
|
-
// A concatenated date-time character string in the format:
|
|
351
|
-
// YYYYMMDDHHMMSS.FFFFFF
|
|
352
|
-
else if (vr === "DT") {
|
|
353
|
-
valueOut = parseDateTimeTag(valueIn);
|
|
354
|
-
}
|
|
355
|
-
// A string of characters of the format HHMMSS.FFFFFF; where HH contains hours
|
|
356
|
-
// (range "00" - "23"), MM contains minutes (range "00" - "59"),
|
|
357
|
-
// SS contains seconds (range "00" - "60"), and FFFFFF contains a fractional
|
|
358
|
-
// part of a second as small as 1 millionth of a second (range "000000" - "999999").
|
|
359
|
-
else if (vr === "TM") {
|
|
360
|
-
valueOut = parseTimeTag(valueIn);
|
|
361
|
-
}
|
|
362
|
-
// Specific Character Set (0008,0005) identifies the Character Set that expands or
|
|
363
|
-
// replaces the Basic Graphic Set (ISO 646) for values of Data Elements that have
|
|
364
|
-
// Value Representation of SH, LO, ST, PN, LT, UC or UT.
|
|
365
|
-
// If the Attribute Specific Character Set (0008,0005) is not present or has only
|
|
366
|
-
// a single value, Code Extension techniques are not used. Defined Terms for the
|
|
367
|
-
// Attribute Specific Character Set (0008,0005), when single valued, are derived
|
|
368
|
-
// from the International Registration Number as per ISO 2375
|
|
369
|
-
// (e.g., ISO_IR 100 for Latin alphabet No. 1).
|
|
370
|
-
// See https://github.com/radialogica/dicom-character-set
|
|
371
|
-
else if (
|
|
372
|
-
vr == "PN" ||
|
|
373
|
-
vr == "SH" ||
|
|
374
|
-
vr == "LO" ||
|
|
375
|
-
vr == "ST" ||
|
|
376
|
-
vr == "LT" ||
|
|
377
|
-
vr == "UC" ||
|
|
378
|
-
vr == "UT"
|
|
379
|
-
) {
|
|
380
|
-
// get character set
|
|
381
|
-
let characterSet = dataSet.string("x00080005");
|
|
382
|
-
|
|
383
|
-
if (characterSet) {
|
|
384
|
-
let data = dataSet.elements[propertyName];
|
|
385
|
-
let arr: Uint8Array | null = new Uint8Array(
|
|
386
|
-
dataSet.byteArray.buffer,
|
|
387
|
-
data.dataOffset,
|
|
388
|
-
data.length
|
|
389
|
-
);
|
|
390
|
-
// try to convert bytes
|
|
391
|
-
// if raises invalid character set
|
|
392
|
-
// catch error
|
|
393
|
-
try {
|
|
394
|
-
valueOut = convertBytes(characterSet, arr, {
|
|
395
|
-
vr: vr
|
|
396
|
-
});
|
|
397
|
-
} catch (error) {
|
|
398
|
-
console.warn("Invalid Character Set: " + characterSet);
|
|
399
|
-
valueOut = "Invalid Character Set: " + characterSet;
|
|
400
|
-
}
|
|
401
|
-
arr = null;
|
|
402
|
-
}
|
|
403
|
-
if (vr == "PN") {
|
|
404
|
-
// PatientName tag value is: "LastName^FirstName^MiddleName".
|
|
405
|
-
// Spaces inside each name component are permitted. If you don't know
|
|
406
|
-
// any of the three components, just leave it empty.
|
|
407
|
-
// Actually you may even append a name prefix (^professor) and
|
|
408
|
-
// a name suffix (^senior) so you have a maximum of 5 components.
|
|
409
|
-
valueOut = parsePatientNameTag(valueIn);
|
|
410
|
-
}
|
|
411
|
-
valueOut = valueOut.replace(/\0/g, ""); // remove null char (\u0000)
|
|
412
|
-
}
|
|
413
|
-
// A string of characters with one of the following formats
|
|
414
|
-
// -- nnnD, nnnW, nnnM, nnnY; where nnn shall contain the number of days for D,
|
|
415
|
-
// weeks for W, months for M, or years for Y.
|
|
416
|
-
else if (vr == "AS") {
|
|
417
|
-
valueOut = parseAgeTag(valueIn);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// A string of characters with leading or trailing spaces (20H) being non-significant.
|
|
421
|
-
else if (vr === "CS") {
|
|
422
|
-
if (propertyName === "x00041500") {
|
|
423
|
-
valueOut = parseDICOMFileIDTag(valueIn);
|
|
424
|
-
} else {
|
|
425
|
-
valueOut = valueIn.split("\\").join(", ");
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
} else if (vr === "US") {
|
|
429
|
-
valueOut = dataSet.uint16(propertyName);
|
|
430
|
-
} else if (vr === "SS") {
|
|
431
|
-
valueOut = dataSet.int16(propertyName);
|
|
432
|
-
} else if (vr === "US|SS") {
|
|
433
|
-
valueOut = dataSet.int16(propertyName);
|
|
434
|
-
} else if (vr === "UL") {
|
|
435
|
-
valueOut = dataSet.uint32(propertyName);
|
|
436
|
-
} else if (vr === "SL") {
|
|
437
|
-
valueOut = dataSet.int32(propertyName);
|
|
438
|
-
} else if (vr == "FD") {
|
|
439
|
-
valueOut = dataSet.double(propertyName);
|
|
440
|
-
} else if (vr == "FL") {
|
|
441
|
-
// check if there are multiple values
|
|
442
|
-
if (propertyName === "x00186060") {
|
|
443
|
-
// RWaveTimeVector
|
|
444
|
-
let index = 0;
|
|
445
|
-
let rWaveTimeVector: number[] = [];
|
|
446
|
-
while (dataSet.float(propertyName, index)) {
|
|
447
|
-
let value = dataSet.float(propertyName, index);
|
|
448
|
-
// push value in array if is bigger than previous value
|
|
449
|
-
if (index > 0 && value && value < rWaveTimeVector[index - 1]) {
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
if (value) {
|
|
453
|
-
rWaveTimeVector.push(value);
|
|
454
|
-
}
|
|
455
|
-
index++;
|
|
456
|
-
}
|
|
457
|
-
valueOut = rWaveTimeVector;
|
|
458
|
-
} else {
|
|
459
|
-
valueOut = dataSet.float(propertyName);
|
|
460
|
-
}
|
|
461
|
-
} else if (
|
|
462
|
-
vr === "OB" ||
|
|
463
|
-
vr === "OW" ||
|
|
464
|
-
vr === "OW|OB" ||
|
|
465
|
-
vr === "US|OW" ||
|
|
466
|
-
vr === "UN" ||
|
|
467
|
-
vr === "OF" ||
|
|
468
|
-
vr === "UT"
|
|
469
|
-
) {
|
|
470
|
-
// If it is some other length and we have no string
|
|
471
|
-
if (element.length === 2) {
|
|
472
|
-
valueOut =
|
|
473
|
-
"binary data of length " +
|
|
474
|
-
element.length +
|
|
475
|
-
" as uint16: " +
|
|
476
|
-
dataSet.uint16(propertyName);
|
|
477
|
-
} else if (element.length === 4) {
|
|
478
|
-
valueOut =
|
|
479
|
-
"binary data of length " +
|
|
480
|
-
element.length +
|
|
481
|
-
" as uint32: " +
|
|
482
|
-
dataSet.uint32(propertyName);
|
|
483
|
-
} else {
|
|
484
|
-
valueOut = tagData;
|
|
485
|
-
}
|
|
486
|
-
} else if (vr === "AT") {
|
|
487
|
-
var group = dataSet.uint16(propertyName, 0);
|
|
488
|
-
if (group) {
|
|
489
|
-
var groupHexStr = ("0000" + group.toString(16)).substr(-4);
|
|
490
|
-
var elm = dataSet.uint16(propertyName, 1);
|
|
491
|
-
var elmHexStr = elm
|
|
492
|
-
? ("0000" + elm.toString(16)).substr(-4)
|
|
493
|
-
: "0000".substr(-4);
|
|
494
|
-
valueOut = "x" + groupHexStr + elmHexStr;
|
|
495
|
-
} else {
|
|
496
|
-
valueOut = "";
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
//seems it is not used TODO-ts sm
|
|
500
|
-
/*else if (vr === "SQ") {
|
|
501
|
-
// parse the nested tags and returns metadata in array of metadata.
|
|
502
|
-
var subTags = map(element, function (obj) {
|
|
503
|
-
return map(obj, function (v : Element, k : string) {
|
|
504
|
-
let TAG= k as keyof MetaDataTypes;
|
|
505
|
-
return parseTag<MetaDataTypes[typeof TAG]>(dataSet, k, v);
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
valueOut = subTags;
|
|
510
|
-
}*/
|
|
511
|
-
else {
|
|
512
|
-
// If it is some other length and we have no string
|
|
513
|
-
valueOut = "no display code for VR " + vr;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
return valueOut as T;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Extract tag value according to its value rapresentation, see
|
|
521
|
-
* {@link http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html}
|
|
522
|
-
* @instance
|
|
523
|
-
* @function getTagValue
|
|
524
|
-
* @param {Object} dataSet - the dataset
|
|
525
|
-
* @param {String} tag - the desired tag key
|
|
526
|
-
* @return {Number | Array | String} - the desired tag value
|
|
527
|
-
*/
|
|
528
|
-
export const getTagValue = function (dataSet: DataSet, tag: string) {
|
|
529
|
-
let tagObj = getDICOMTag(tag);
|
|
530
|
-
// tag value rapresentation
|
|
531
|
-
if (!tagObj) {
|
|
532
|
-
return null;
|
|
533
|
-
}
|
|
534
|
-
let vr = tagObj.vr;
|
|
535
|
-
|
|
536
|
-
// parse value according to vr map
|
|
537
|
-
let vrParsingMap: {
|
|
538
|
-
[key: string]: () => any;
|
|
539
|
-
} = {
|
|
540
|
-
// Date
|
|
541
|
-
// string of characters of the format YYYYMMDD; where YYYY shall contain year,
|
|
542
|
-
// MM shall contain the month, and DD shall contain the day,
|
|
543
|
-
// interpreted as a date of the Gregorian calendar system.
|
|
544
|
-
DA: function () {
|
|
545
|
-
let dateString = dataSet.string(tag);
|
|
546
|
-
return dateString ? formatDate(dateString) : "";
|
|
547
|
-
},
|
|
548
|
-
// Decimal String
|
|
549
|
-
// A string of characters representing either a fixed point number
|
|
550
|
-
// or a floating point number.
|
|
551
|
-
DS: function () {
|
|
552
|
-
if (!dataSet) {
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
let tag_str = dataSet.string(tag);
|
|
556
|
-
let array = tag_str ? tag_str.split("\\").map(Number) : null;
|
|
557
|
-
if (!array) {
|
|
558
|
-
return null;
|
|
559
|
-
}
|
|
560
|
-
return array.length === 1 ? array[0] : array;
|
|
561
|
-
},
|
|
562
|
-
// Date Time
|
|
563
|
-
// A concatenated date-time character string in the format:
|
|
564
|
-
// YYYYMMDDHHMMSS.FFFFFF&ZZXX
|
|
565
|
-
DT: function () {
|
|
566
|
-
let dateString = dataSet.string(tag);
|
|
567
|
-
return dateString ? formatDateTime(dateString) : "";
|
|
568
|
-
},
|
|
569
|
-
// Person Name
|
|
570
|
-
// A character string encoded using a 5 component convention.
|
|
571
|
-
// The character code 5CH (the BACKSLASH "\" in ISO-IR 6) shall
|
|
572
|
-
// not be present, as it is used as the delimiter between values
|
|
573
|
-
// in multiple valued data elements. The string may be padded
|
|
574
|
-
// with trailing spaces. For human use, the five components
|
|
575
|
-
// in their order of occurrence are: family name complex,
|
|
576
|
-
// given name complex, middle name, name prefix, name suffix.
|
|
577
|
-
PN: function () {
|
|
578
|
-
let tag_str = dataSet.string(tag);
|
|
579
|
-
let pn = tag_str ? tag_str.split("^") : null;
|
|
580
|
-
if (!pn) {
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
let pns = [pn[3], pn[0], pn[1], pn[2], pn[4]];
|
|
585
|
-
return pns.join(" ").trim();
|
|
586
|
-
},
|
|
587
|
-
// Signed Short
|
|
588
|
-
// Signed binary integer 16 bits long in 2's complement form
|
|
589
|
-
SS: function () {
|
|
590
|
-
return dataSet.uint16(tag);
|
|
591
|
-
},
|
|
592
|
-
// Unique Identifier
|
|
593
|
-
// A character string containing a UID that is used to uniquely
|
|
594
|
-
// identify a wide letiety of items. The UID is a series of numeric
|
|
595
|
-
// components separated by the period "." character.
|
|
596
|
-
UI: function () {
|
|
597
|
-
return dataSet.string(tag);
|
|
598
|
-
},
|
|
599
|
-
// Unsigned Short
|
|
600
|
-
// Unsigned binary integer 16 bits long.
|
|
601
|
-
US: function () {
|
|
602
|
-
return dataSet.uint16(tag);
|
|
603
|
-
},
|
|
604
|
-
"US|SS": function () {
|
|
605
|
-
return dataSet.uint16(tag);
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
return vrParsingMap[vr] ? vrParsingMap[vr]() : dataSet.string(tag);
|
|
609
|
-
};
|