dcmjs 0.34.2 → 0.34.4
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/.eslintrc.json +4 -0
- package/.github/workflows/lint-and-format.yml +27 -0
- package/.github/workflows/tests.yml +2 -2
- package/build/dcmjs.es.js +4103 -4093
- package/build/dcmjs.es.js.map +1 -1
- package/build/dcmjs.js +4103 -4093
- package/build/dcmjs.js.map +1 -1
- package/package.json +7 -2
- package/test/adapters.test.js +14 -16
- package/test/data-encoding.test.js +1 -4
- package/test/data-options.test.js +0 -1
- package/test/data.test.js +224 -117
- package/test/lossless-read-write.test.js +430 -250
- package/test/testUtils.js +1 -2
- package/test/utilities/deepEqual.test.js +29 -20
|
@@ -8,14 +8,12 @@ import { getTestDataset } from "./testUtils";
|
|
|
8
8
|
|
|
9
9
|
const { DicomDict, DicomMessage } = dcmjs.data;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
describe(
|
|
13
|
-
|
|
14
|
-
describe('storeRaw option', () => {
|
|
11
|
+
describe("lossless-read-write", () => {
|
|
12
|
+
describe("storeRaw option", () => {
|
|
15
13
|
const dataset = {
|
|
16
|
-
|
|
14
|
+
"00080008": {
|
|
17
15
|
vr: "CS",
|
|
18
|
-
Value: ["DERIVED"]
|
|
16
|
+
Value: ["DERIVED"]
|
|
19
17
|
},
|
|
20
18
|
"00082112": {
|
|
21
19
|
vr: "SQ",
|
|
@@ -23,32 +21,32 @@ describe('lossless-read-write', () => {
|
|
|
23
21
|
{
|
|
24
22
|
"00081150": {
|
|
25
23
|
vr: "UI",
|
|
26
|
-
Value: [
|
|
27
|
-
|
|
28
|
-
],
|
|
29
|
-
},
|
|
24
|
+
Value: ["1.2.840.10008.5.1.4.1.1.7"]
|
|
25
|
+
}
|
|
30
26
|
}
|
|
31
27
|
]
|
|
32
28
|
},
|
|
33
29
|
"00180050": {
|
|
34
30
|
vr: "DS",
|
|
35
|
-
Value: [1]
|
|
31
|
+
Value: [1]
|
|
36
32
|
},
|
|
37
33
|
"00181708": {
|
|
38
34
|
vr: "IS",
|
|
39
|
-
Value: [426]
|
|
35
|
+
Value: [426]
|
|
40
36
|
},
|
|
41
37
|
"00189328": {
|
|
42
38
|
vr: "FD",
|
|
43
|
-
Value: [30.98]
|
|
39
|
+
Value: [30.98]
|
|
44
40
|
},
|
|
45
41
|
"0020000D": {
|
|
46
42
|
vr: "UI",
|
|
47
|
-
Value: [
|
|
43
|
+
Value: [
|
|
44
|
+
"1.3.6.1.4.1.5962.99.1.2280943358.716200484.1363785608958.3.0"
|
|
45
|
+
]
|
|
48
46
|
},
|
|
49
47
|
"00400254": {
|
|
50
48
|
vr: "LO",
|
|
51
|
-
Value: ["DUCTO/GALACTOGRAM 1 DUCT LT"]
|
|
49
|
+
Value: ["DUCTO/GALACTOGRAM 1 DUCT LT"]
|
|
52
50
|
},
|
|
53
51
|
"7FE00010": {
|
|
54
52
|
vr: "OW",
|
|
@@ -56,8 +54,8 @@ describe('lossless-read-write', () => {
|
|
|
56
54
|
}
|
|
57
55
|
};
|
|
58
56
|
|
|
59
|
-
test(
|
|
60
|
-
const tagsWithoutRaw = [
|
|
57
|
+
test("storeRaw flag on VR should be respected by read", () => {
|
|
58
|
+
const tagsWithoutRaw = ["00082112", "7FE00010"];
|
|
61
59
|
|
|
62
60
|
const dicomDict = new DicomDict({});
|
|
63
61
|
dicomDict.dict = dataset;
|
|
@@ -73,14 +71,14 @@ describe('lossless-read-write', () => {
|
|
|
73
71
|
}
|
|
74
72
|
});
|
|
75
73
|
|
|
76
|
-
test(
|
|
77
|
-
const tagsWithoutRaw = ['00082112', '7FE00010'];
|
|
78
|
-
|
|
74
|
+
test("forceStoreRaw read option should override VR setting", () => {
|
|
79
75
|
const dicomDict = new DicomDict({});
|
|
80
76
|
dicomDict.dict = dataset;
|
|
81
77
|
|
|
82
78
|
// write and re-read
|
|
83
|
-
const outputDicomDict = DicomMessage.readFile(dicomDict.write(), {
|
|
79
|
+
const outputDicomDict = DicomMessage.readFile(dicomDict.write(), {
|
|
80
|
+
forceStoreRaw: true
|
|
81
|
+
});
|
|
84
82
|
|
|
85
83
|
for (const tag in outputDicomDict.dict) {
|
|
86
84
|
expect(outputDicomDict.dict[tag]._rawValue).toBeTruthy();
|
|
@@ -88,13 +86,13 @@ describe('lossless-read-write', () => {
|
|
|
88
86
|
});
|
|
89
87
|
});
|
|
90
88
|
|
|
91
|
-
test(
|
|
89
|
+
test("test DS value with additional allowed characters is written to file", () => {
|
|
92
90
|
const dataset = {
|
|
93
|
-
|
|
91
|
+
"00181041": {
|
|
94
92
|
_rawValue: [" +1.4000 ", "-0.00", "1.2345e2", "1E34"],
|
|
95
|
-
Value: [1.4, -0, 123.45,
|
|
96
|
-
vr:
|
|
97
|
-
}
|
|
93
|
+
Value: [1.4, -0, 123.45, 1e34],
|
|
94
|
+
vr: "DS"
|
|
95
|
+
}
|
|
98
96
|
};
|
|
99
97
|
|
|
100
98
|
const dicomDict = new DicomDict({});
|
|
@@ -104,17 +102,24 @@ describe('lossless-read-write', () => {
|
|
|
104
102
|
const outputDicomDict = DicomMessage.readFile(dicomDict.write());
|
|
105
103
|
|
|
106
104
|
// expect raw value to be unchanged, and Value parsed as Number to lose precision
|
|
107
|
-
expect(outputDicomDict.dict[
|
|
108
|
-
|
|
105
|
+
expect(outputDicomDict.dict["00181041"]._rawValue).toEqual([
|
|
106
|
+
" +1.4000 ",
|
|
107
|
+
"-0.00",
|
|
108
|
+
"1.2345e2",
|
|
109
|
+
"1E34"
|
|
110
|
+
]);
|
|
111
|
+
expect(outputDicomDict.dict["00181041"].Value).toEqual([
|
|
112
|
+
1.4, -0, 123.45, 1e34
|
|
113
|
+
]);
|
|
109
114
|
});
|
|
110
115
|
|
|
111
|
-
test(
|
|
116
|
+
test("test DS value that exceeds Number.MAX_SAFE_INTEGER is written to file", () => {
|
|
112
117
|
const dataset = {
|
|
113
|
-
|
|
118
|
+
"00181041": {
|
|
114
119
|
_rawValue: ["9007199254740993"],
|
|
115
120
|
Value: [9007199254740993],
|
|
116
|
-
vr:
|
|
117
|
-
}
|
|
121
|
+
vr: "DS"
|
|
122
|
+
}
|
|
118
123
|
};
|
|
119
124
|
|
|
120
125
|
const dicomDict = new DicomDict({});
|
|
@@ -124,15 +129,22 @@ describe('lossless-read-write', () => {
|
|
|
124
129
|
const outputDicomDict = DicomMessage.readFile(dicomDict.write());
|
|
125
130
|
|
|
126
131
|
// expect raw value to be unchanged, and Value parsed as Number to lose precision
|
|
127
|
-
expect(outputDicomDict.dict[
|
|
128
|
-
|
|
132
|
+
expect(outputDicomDict.dict["00181041"]._rawValue).toEqual([
|
|
133
|
+
"9007199254740993"
|
|
134
|
+
]);
|
|
135
|
+
expect(outputDicomDict.dict["00181041"].Value).toEqual([
|
|
136
|
+
9007199254740992
|
|
137
|
+
]);
|
|
129
138
|
});
|
|
130
139
|
|
|
131
|
-
test(
|
|
140
|
+
test("test DS with multiplicity > 1 and added space for even padding is read and written correctly", () => {
|
|
132
141
|
const dataset = {
|
|
133
|
-
|
|
134
|
-
vr:
|
|
135
|
-
Value: [
|
|
142
|
+
"00200037": {
|
|
143
|
+
vr: "DS",
|
|
144
|
+
Value: [
|
|
145
|
+
0.99924236548978, -0.0322633220972, -0.0217663285287,
|
|
146
|
+
0.02949870928067, 0.99267261121054, -0.1171789789306
|
|
147
|
+
]
|
|
136
148
|
}
|
|
137
149
|
};
|
|
138
150
|
|
|
@@ -144,28 +156,49 @@ describe('lossless-read-write', () => {
|
|
|
144
156
|
|
|
145
157
|
// ensure _rawValue strings have no added trailing spaces
|
|
146
158
|
const expectedDataset = {
|
|
147
|
-
|
|
148
|
-
vr:
|
|
149
|
-
Value: [
|
|
150
|
-
|
|
159
|
+
"00200037": {
|
|
160
|
+
vr: "DS",
|
|
161
|
+
Value: [
|
|
162
|
+
0.99924236548978, -0.0322633220972, -0.0217663285287,
|
|
163
|
+
0.02949870928067, 0.99267261121054, -0.1171789789306
|
|
164
|
+
],
|
|
165
|
+
_rawValue: [
|
|
166
|
+
"0.99924236548978",
|
|
167
|
+
"-0.0322633220972",
|
|
168
|
+
"-0.0217663285287",
|
|
169
|
+
"0.02949870928067",
|
|
170
|
+
"0.99267261121054",
|
|
171
|
+
"-0.1171789789306"
|
|
172
|
+
]
|
|
151
173
|
}
|
|
152
174
|
};
|
|
153
175
|
|
|
154
176
|
expect(deepEqual(expectedDataset, outputDicomDict.dict)).toBeTruthy();
|
|
155
177
|
|
|
156
178
|
// re-write should succeeed
|
|
157
|
-
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
179
|
+
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
180
|
+
outputDicomDict.write()
|
|
181
|
+
);
|
|
158
182
|
|
|
159
183
|
// dataset should still be equal
|
|
160
|
-
expect(
|
|
184
|
+
expect(
|
|
185
|
+
deepEqual(expectedDataset, outputDicomDictPass2.dict)
|
|
186
|
+
).toBeTruthy();
|
|
161
187
|
});
|
|
162
188
|
|
|
163
|
-
test(
|
|
189
|
+
test("test DS with multiplicity > 1 with padding byte on last element within VR max length is losslessly read", () => {
|
|
164
190
|
const dataset = {
|
|
165
|
-
|
|
166
|
-
vr:
|
|
167
|
-
Value: [
|
|
168
|
-
|
|
191
|
+
"00200037": {
|
|
192
|
+
vr: "DS",
|
|
193
|
+
Value: [
|
|
194
|
+
0.99924236548978, -0.0322633220972, -0.0217663285287, 0
|
|
195
|
+
],
|
|
196
|
+
_rawValue: [
|
|
197
|
+
"0.99924236548978",
|
|
198
|
+
"-0.0322633220972",
|
|
199
|
+
"-0.0217663285287",
|
|
200
|
+
" +0.00 "
|
|
201
|
+
]
|
|
169
202
|
}
|
|
170
203
|
};
|
|
171
204
|
|
|
@@ -177,26 +210,35 @@ describe('lossless-read-write', () => {
|
|
|
177
210
|
|
|
178
211
|
// ensure _rawValue strings have no added trailing spaces and retain original encoding details for + and spaces
|
|
179
212
|
const expectedDataset = {
|
|
180
|
-
|
|
181
|
-
vr:
|
|
182
|
-
Value: [
|
|
183
|
-
|
|
213
|
+
"00200037": {
|
|
214
|
+
vr: "DS",
|
|
215
|
+
Value: [
|
|
216
|
+
0.99924236548978, -0.0322633220972, -0.0217663285287, 0
|
|
217
|
+
],
|
|
218
|
+
_rawValue: [
|
|
219
|
+
"0.99924236548978",
|
|
220
|
+
"-0.0322633220972",
|
|
221
|
+
"-0.0217663285287",
|
|
222
|
+
" +0.00"
|
|
223
|
+
]
|
|
184
224
|
}
|
|
185
225
|
};
|
|
186
226
|
|
|
187
227
|
expect(outputDicomDict.dict).toEqual(expectedDataset);
|
|
188
228
|
|
|
189
229
|
// re-write should succeeed
|
|
190
|
-
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
230
|
+
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
231
|
+
outputDicomDict.write()
|
|
232
|
+
);
|
|
191
233
|
|
|
192
234
|
// dataset should still be equal
|
|
193
235
|
expect(outputDicomDictPass2.dict).toEqual(expectedDataset);
|
|
194
236
|
});
|
|
195
237
|
|
|
196
|
-
test(
|
|
238
|
+
test("test IS with multiplicity > 1 and added space for even padding is read and written correctly", () => {
|
|
197
239
|
const dataset = {
|
|
198
|
-
|
|
199
|
-
vr:
|
|
240
|
+
"00081160": {
|
|
241
|
+
vr: "IS",
|
|
200
242
|
Value: [1234, 5678]
|
|
201
243
|
}
|
|
202
244
|
};
|
|
@@ -209,8 +251,8 @@ describe('lossless-read-write', () => {
|
|
|
209
251
|
|
|
210
252
|
// last _rawValue strings does allow trailing space as it does not exceed max length
|
|
211
253
|
const expectedDataset = {
|
|
212
|
-
|
|
213
|
-
vr:
|
|
254
|
+
"00081160": {
|
|
255
|
+
vr: "IS",
|
|
214
256
|
Value: [1234, 5678],
|
|
215
257
|
_rawValue: ["1234", "5678"]
|
|
216
258
|
}
|
|
@@ -219,84 +261,103 @@ describe('lossless-read-write', () => {
|
|
|
219
261
|
expect(outputDicomDict.dict).toEqual(expectedDataset);
|
|
220
262
|
|
|
221
263
|
// re-write should succeeed
|
|
222
|
-
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
264
|
+
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
265
|
+
outputDicomDict.write()
|
|
266
|
+
);
|
|
223
267
|
|
|
224
268
|
// dataset should still be equal
|
|
225
269
|
expect(outputDicomDictPass2.dict).toEqual(expectedDataset);
|
|
226
270
|
});
|
|
227
271
|
|
|
228
|
-
describe(
|
|
272
|
+
describe("Multiplicity for non-binary String VRs", () => {
|
|
229
273
|
const maxLengthCases = [
|
|
230
274
|
{
|
|
231
|
-
vr:
|
|
275
|
+
vr: "AE",
|
|
232
276
|
Value: ["MAX_LENGTH_CHARS", "MAX_LENGTH_CHARS"],
|
|
233
277
|
_rawValue: ["MAX_LENGTH_CHARS", "MAX_LENGTH_CHARS"]
|
|
234
278
|
},
|
|
235
279
|
{
|
|
236
|
-
vr:
|
|
280
|
+
vr: "AS",
|
|
237
281
|
Value: ["120D", "045Y"],
|
|
238
282
|
_rawValue: ["120D", "045Y"]
|
|
239
283
|
},
|
|
240
284
|
{
|
|
241
|
-
vr:
|
|
242
|
-
Value: [
|
|
243
|
-
_rawValue: [
|
|
285
|
+
vr: "AT",
|
|
286
|
+
Value: [0x00207e14, 0x0012839a],
|
|
287
|
+
_rawValue: [0x00207e14, 0x0012839a]
|
|
244
288
|
},
|
|
245
289
|
{
|
|
246
|
-
vr:
|
|
290
|
+
vr: "CS",
|
|
247
291
|
Value: ["MAX_LENGTH_CHARS", "MAX_LENGTH_CHARS"],
|
|
248
292
|
_rawValue: ["MAX_LENGTH_CHARS", "MAX_LENGTH_CHARS"]
|
|
249
293
|
},
|
|
250
294
|
{
|
|
251
|
-
vr:
|
|
295
|
+
vr: "DA",
|
|
252
296
|
Value: ["20230826", "20230826"],
|
|
253
297
|
_rawValue: ["20230826", "20230826"]
|
|
254
298
|
},
|
|
255
299
|
{
|
|
256
|
-
vr:
|
|
300
|
+
vr: "DS",
|
|
257
301
|
Value: [123456789012.345, 123456789012.345],
|
|
258
302
|
_rawValue: ["123456789012.345", "123456789012.345"]
|
|
259
303
|
},
|
|
260
304
|
{
|
|
261
|
-
vr:
|
|
262
|
-
Value: [
|
|
263
|
-
|
|
305
|
+
vr: "DT",
|
|
306
|
+
Value: [
|
|
307
|
+
"20230826123045.123456+0100",
|
|
308
|
+
"20230826123045.123456+0100"
|
|
309
|
+
],
|
|
310
|
+
_rawValue: [
|
|
311
|
+
"20230826123045.123456+0100",
|
|
312
|
+
"20230826123045.123456+0100"
|
|
313
|
+
]
|
|
264
314
|
},
|
|
265
315
|
{
|
|
266
|
-
vr:
|
|
316
|
+
vr: "IS",
|
|
267
317
|
Value: [123456789012, 123456789012],
|
|
268
318
|
_rawValue: ["123456789012", "123456789012"]
|
|
269
319
|
},
|
|
270
320
|
{
|
|
271
|
-
vr:
|
|
272
|
-
Value: [
|
|
273
|
-
|
|
321
|
+
vr: "LO",
|
|
322
|
+
Value: [
|
|
323
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOP",
|
|
324
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOP"
|
|
325
|
+
],
|
|
326
|
+
_rawValue: [
|
|
327
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOP",
|
|
328
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOP"
|
|
329
|
+
]
|
|
274
330
|
},
|
|
275
331
|
{
|
|
276
|
-
vr:
|
|
332
|
+
vr: "SH",
|
|
277
333
|
Value: ["ABCDEFGHIJKLMNOP", "ABCDEFGHIJKLMNOP"],
|
|
278
334
|
_rawValue: ["ABCDEFGHIJKLMNOP", "ABCDEFGHIJKLMNOP"]
|
|
279
335
|
},
|
|
280
336
|
{
|
|
281
|
-
vr:
|
|
282
|
-
Value: [
|
|
283
|
-
|
|
337
|
+
vr: "UI",
|
|
338
|
+
Value: [
|
|
339
|
+
"1.2.840.12345678901234567890123456789012345678901234567890123456",
|
|
340
|
+
"1.2.840.12345678901234567890123456789012345678901234567890123456"
|
|
341
|
+
],
|
|
342
|
+
_rawValue: [
|
|
343
|
+
"1.2.840.12345678901234567890123456789012345678901234567890123456",
|
|
344
|
+
"1.2.840.12345678901234567890123456789012345678901234567890123456"
|
|
345
|
+
]
|
|
284
346
|
},
|
|
285
347
|
{
|
|
286
|
-
vr:
|
|
348
|
+
vr: "TM",
|
|
287
349
|
Value: ["142530.1234567", "142530.1234567"],
|
|
288
|
-
_rawValue: ["142530.1234567", "142530.1234567"]
|
|
289
|
-
}
|
|
290
|
-
|
|
350
|
+
_rawValue: ["142530.1234567", "142530.1234567"]
|
|
351
|
+
}
|
|
291
352
|
];
|
|
292
353
|
|
|
293
354
|
test.each(maxLengthCases)(
|
|
294
355
|
`Test multiple values with VR max length handle pad byte correctly during read and write - $vr`,
|
|
295
|
-
|
|
356
|
+
dataElement => {
|
|
296
357
|
const dataset = {
|
|
297
|
-
|
|
358
|
+
"00081160": {
|
|
298
359
|
vr: dataElement.vr,
|
|
299
|
-
Value: dataElement.Value
|
|
360
|
+
Value: dataElement.Value
|
|
300
361
|
}
|
|
301
362
|
};
|
|
302
363
|
|
|
@@ -304,103 +365,136 @@ describe('lossless-read-write', () => {
|
|
|
304
365
|
dicomDict.dict = dataset;
|
|
305
366
|
|
|
306
367
|
// write and re-read
|
|
307
|
-
const outputDicomDict = DicomMessage.readFile(
|
|
368
|
+
const outputDicomDict = DicomMessage.readFile(
|
|
369
|
+
dicomDict.write()
|
|
370
|
+
);
|
|
308
371
|
|
|
309
372
|
// expect full _rawValue to match following read
|
|
310
373
|
const expectedDataset = {
|
|
311
|
-
|
|
312
|
-
...dataElement
|
|
374
|
+
"00081160": {
|
|
375
|
+
...dataElement
|
|
313
376
|
}
|
|
314
377
|
};
|
|
315
378
|
|
|
316
379
|
expect(outputDicomDict.dict).toEqual(expectedDataset);
|
|
317
380
|
|
|
318
381
|
// re-write should succeed without max length issues
|
|
319
|
-
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
382
|
+
const outputDicomDictPass2 = DicomMessage.readFile(
|
|
383
|
+
outputDicomDict.write()
|
|
384
|
+
);
|
|
320
385
|
|
|
321
386
|
// dataset should still be equal
|
|
322
387
|
expect(expectedDataset).toEqual(outputDicomDictPass2.dict);
|
|
323
388
|
}
|
|
324
389
|
);
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
describe('Individual VR comparisons', () => {
|
|
390
|
+
});
|
|
328
391
|
|
|
392
|
+
describe("Individual VR comparisons", () => {
|
|
329
393
|
const unchangedTestCases = [
|
|
330
394
|
{
|
|
331
395
|
vr: "AE",
|
|
332
396
|
_rawValue: [" TEST_AE "], // spaces non-significant for interpretation but allowed
|
|
333
|
-
Value: ["TEST_AE"]
|
|
397
|
+
Value: ["TEST_AE"]
|
|
334
398
|
},
|
|
335
399
|
{
|
|
336
400
|
vr: "AS",
|
|
337
401
|
_rawValue: ["045Y"],
|
|
338
|
-
Value: ["045Y"]
|
|
402
|
+
Value: ["045Y"]
|
|
339
403
|
},
|
|
340
404
|
{
|
|
341
405
|
vr: "AT",
|
|
342
|
-
_rawValue: [
|
|
343
|
-
Value: [
|
|
406
|
+
_rawValue: [0x00207e14, 0x0012839a],
|
|
407
|
+
Value: [0x00207e14, 0x0012839a]
|
|
344
408
|
},
|
|
345
409
|
{
|
|
346
410
|
vr: "CS",
|
|
347
411
|
_rawValue: ["ORIGINAL ", " PRIMARY"], // spaces non-significant for interpretation but allowed
|
|
348
|
-
Value: ["ORIGINAL", "PRIMARY"]
|
|
412
|
+
Value: ["ORIGINAL", "PRIMARY"]
|
|
349
413
|
},
|
|
350
414
|
{
|
|
351
415
|
vr: "DA",
|
|
352
416
|
_rawValue: ["20240101"],
|
|
353
|
-
Value: ["20240101"]
|
|
417
|
+
Value: ["20240101"]
|
|
354
418
|
},
|
|
355
419
|
{
|
|
356
420
|
vr: "DS",
|
|
357
421
|
_rawValue: ["0000123.45"], // leading zeros allowed
|
|
358
|
-
Value: [123.45]
|
|
422
|
+
Value: [123.45]
|
|
359
423
|
},
|
|
360
424
|
{
|
|
361
|
-
vr:
|
|
425
|
+
vr: "DT",
|
|
362
426
|
_rawValue: ["20240101123045.1 "], // trailing spaces allowed
|
|
363
|
-
Value: ["20240101123045.1 "]
|
|
427
|
+
Value: ["20240101123045.1 "]
|
|
364
428
|
},
|
|
365
429
|
{
|
|
366
|
-
vr:
|
|
430
|
+
vr: "FL",
|
|
367
431
|
_rawValue: [3.125],
|
|
368
|
-
Value: [3.125]
|
|
432
|
+
Value: [3.125]
|
|
369
433
|
},
|
|
370
434
|
{
|
|
371
|
-
vr:
|
|
435
|
+
vr: "FD",
|
|
372
436
|
_rawValue: [3.14159265358979], // trailing spaces allowed
|
|
373
|
-
Value: [3.14159265358979]
|
|
437
|
+
Value: [3.14159265358979]
|
|
374
438
|
},
|
|
375
439
|
{
|
|
376
|
-
vr:
|
|
440
|
+
vr: "IS",
|
|
377
441
|
_rawValue: [" -123 "], // leading/trailing spaces & sign allowed
|
|
378
|
-
Value: [-123]
|
|
442
|
+
Value: [-123]
|
|
379
443
|
},
|
|
380
444
|
{
|
|
381
|
-
vr:
|
|
445
|
+
vr: "LO",
|
|
382
446
|
_rawValue: [" A long string with spaces "], // leading/trailing spaces allowed
|
|
383
|
-
Value: ["A long string with spaces"]
|
|
447
|
+
Value: ["A long string with spaces"]
|
|
384
448
|
},
|
|
385
449
|
{
|
|
386
|
-
vr:
|
|
387
|
-
_rawValue: [
|
|
388
|
-
|
|
450
|
+
vr: "LT",
|
|
451
|
+
_rawValue: [
|
|
452
|
+
" It may contain the Graphic Character set and the Control Characters, CR\r, LF\n, FF\f, and ESC\x1b. "
|
|
453
|
+
], // leading spaces significant, trailing spaces allowed
|
|
454
|
+
Value: [
|
|
455
|
+
" It may contain the Graphic Character set and the Control Characters, CR\r, LF\n, FF\f, and ESC\x1b."
|
|
456
|
+
]
|
|
389
457
|
},
|
|
390
458
|
{
|
|
391
|
-
vr:
|
|
392
|
-
_rawValue: [
|
|
393
|
-
|
|
459
|
+
vr: "OB",
|
|
460
|
+
_rawValue: [
|
|
461
|
+
new Uint8Array([
|
|
462
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
463
|
+
]).buffer
|
|
464
|
+
],
|
|
465
|
+
Value: [
|
|
466
|
+
new Uint8Array([
|
|
467
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
468
|
+
]).buffer
|
|
469
|
+
]
|
|
394
470
|
},
|
|
395
471
|
{
|
|
396
|
-
vr:
|
|
397
|
-
_rawValue: [
|
|
398
|
-
|
|
472
|
+
vr: "OD",
|
|
473
|
+
_rawValue: [
|
|
474
|
+
new Uint8Array([
|
|
475
|
+
0x00, 0x00, 0x00, 0x54, 0x34, 0x6f, 0x9d, 0x41
|
|
476
|
+
]).buffer
|
|
477
|
+
],
|
|
478
|
+
Value: [
|
|
479
|
+
new Uint8Array([
|
|
480
|
+
0x00, 0x00, 0x00, 0x54, 0x34, 0x6f, 0x9d, 0x41
|
|
481
|
+
]).buffer
|
|
482
|
+
]
|
|
399
483
|
},
|
|
400
484
|
{
|
|
401
|
-
vr:
|
|
402
|
-
_rawValue: [
|
|
403
|
-
|
|
485
|
+
vr: "OF",
|
|
486
|
+
_rawValue: [
|
|
487
|
+
new Uint8Array([
|
|
488
|
+
0x00, 0x00, 0x28, 0x41, 0x00, 0x00, 0x30, 0xc0, 0x00,
|
|
489
|
+
0x00, 0xf6, 0x42
|
|
490
|
+
]).buffer
|
|
491
|
+
],
|
|
492
|
+
Value: [
|
|
493
|
+
new Uint8Array([
|
|
494
|
+
0x00, 0x00, 0x28, 0x41, 0x00, 0x00, 0x30, 0xc0, 0x00,
|
|
495
|
+
0x00, 0xf6, 0x42
|
|
496
|
+
]).buffer
|
|
497
|
+
]
|
|
404
498
|
},
|
|
405
499
|
// TODO: VRs currently unimplemented
|
|
406
500
|
// {
|
|
@@ -414,34 +508,44 @@ describe('lossless-read-write', () => {
|
|
|
414
508
|
// Value: [new Uint8Array([0x00, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x28, 0x41]).buffer],
|
|
415
509
|
// },
|
|
416
510
|
{
|
|
417
|
-
vr:
|
|
418
|
-
_rawValue: [
|
|
419
|
-
|
|
511
|
+
vr: "OW",
|
|
512
|
+
_rawValue: [
|
|
513
|
+
new Uint8Array([
|
|
514
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
515
|
+
]).buffer
|
|
516
|
+
],
|
|
517
|
+
Value: [
|
|
518
|
+
new Uint8Array([
|
|
519
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
520
|
+
]).buffer
|
|
521
|
+
]
|
|
420
522
|
},
|
|
421
523
|
{
|
|
422
|
-
vr:
|
|
524
|
+
vr: "PN",
|
|
423
525
|
_rawValue: ["Doe^John^A^Jr.^MD "], // trailing spaces allowed
|
|
424
|
-
Value: [{
|
|
526
|
+
Value: [{ Alphabetic: "Doe^John^A^Jr.^MD " }]
|
|
425
527
|
},
|
|
426
528
|
{
|
|
427
|
-
vr:
|
|
529
|
+
vr: "SH",
|
|
428
530
|
_rawValue: [" CT_SCAN_01 "], // leading/trailing spaces allowed
|
|
429
|
-
Value: ["CT_SCAN_01"]
|
|
531
|
+
Value: ["CT_SCAN_01"]
|
|
430
532
|
},
|
|
431
533
|
{
|
|
432
|
-
vr:
|
|
534
|
+
vr: "SL",
|
|
433
535
|
_rawValue: [-2147483648],
|
|
434
|
-
Value: [-2147483648]
|
|
536
|
+
Value: [-2147483648]
|
|
435
537
|
},
|
|
436
538
|
{
|
|
437
|
-
vr:
|
|
539
|
+
vr: "SS",
|
|
438
540
|
_rawValue: [-32768, 1234, 832],
|
|
439
|
-
Value: [-32768, 1234, 832]
|
|
541
|
+
Value: [-32768, 1234, 832]
|
|
440
542
|
},
|
|
441
543
|
{
|
|
442
|
-
vr:
|
|
443
|
-
_rawValue: [
|
|
444
|
-
|
|
544
|
+
vr: "ST",
|
|
545
|
+
_rawValue: [
|
|
546
|
+
"Patient complains of headaches over the last week. "
|
|
547
|
+
], // trailing spaces allowed
|
|
548
|
+
Value: ["Patient complains of headaches over the last week."]
|
|
445
549
|
},
|
|
446
550
|
// TODO: VR currently unimplemented
|
|
447
551
|
// {
|
|
@@ -450,40 +554,48 @@ describe('lossless-read-write', () => {
|
|
|
450
554
|
// Value: [9007199254740993],
|
|
451
555
|
// },
|
|
452
556
|
{
|
|
453
|
-
vr:
|
|
557
|
+
vr: "TM",
|
|
454
558
|
_rawValue: ["42530.123456 "], // trailing spaces allowed
|
|
455
|
-
Value: ["42530.123456"]
|
|
559
|
+
Value: ["42530.123456"]
|
|
456
560
|
},
|
|
457
561
|
{
|
|
458
|
-
vr:
|
|
459
|
-
_rawValue: [
|
|
460
|
-
|
|
562
|
+
vr: "UC",
|
|
563
|
+
_rawValue: [
|
|
564
|
+
"Detailed description of procedure or clinical notes that could be very long. "
|
|
565
|
+
], // trailing spaces allowed
|
|
566
|
+
Value: [
|
|
567
|
+
"Detailed description of procedure or clinical notes that could be very long."
|
|
568
|
+
]
|
|
461
569
|
},
|
|
462
570
|
{
|
|
463
|
-
vr:
|
|
571
|
+
vr: "UI",
|
|
464
572
|
_rawValue: ["1.2.840.10008.1.2.1"],
|
|
465
|
-
Value: ["1.2.840.10008.1.2.1"]
|
|
573
|
+
Value: ["1.2.840.10008.1.2.1"]
|
|
466
574
|
},
|
|
467
575
|
{
|
|
468
|
-
vr:
|
|
576
|
+
vr: "UL",
|
|
469
577
|
_rawValue: [4294967295],
|
|
470
|
-
Value: [4294967295]
|
|
578
|
+
Value: [4294967295]
|
|
471
579
|
},
|
|
472
580
|
{
|
|
473
|
-
vr:
|
|
581
|
+
vr: "UR",
|
|
474
582
|
_rawValue: ["http://dicom.nema.org "], // trailing spaces ignored but allowed
|
|
475
|
-
Value: ["http://dicom.nema.org "]
|
|
583
|
+
Value: ["http://dicom.nema.org "]
|
|
476
584
|
},
|
|
477
585
|
{
|
|
478
|
-
vr:
|
|
586
|
+
vr: "US",
|
|
479
587
|
_rawValue: [65535],
|
|
480
|
-
Value: [65535]
|
|
588
|
+
Value: [65535]
|
|
481
589
|
},
|
|
482
590
|
{
|
|
483
|
-
vr:
|
|
484
|
-
_rawValue: [
|
|
485
|
-
|
|
486
|
-
|
|
591
|
+
vr: "UT",
|
|
592
|
+
_rawValue: [
|
|
593
|
+
" This is a detailed explanation that can span multiple lines and paragraphs in the DICOM dataset. "
|
|
594
|
+
], // leading spaces significant, trailing spaces allowed
|
|
595
|
+
Value: [
|
|
596
|
+
" This is a detailed explanation that can span multiple lines and paragraphs in the DICOM dataset."
|
|
597
|
+
]
|
|
598
|
+
}
|
|
487
599
|
// TODO: VR currently unimplemented
|
|
488
600
|
// {
|
|
489
601
|
// vr: 'UV',
|
|
@@ -493,50 +605,57 @@ describe('lossless-read-write', () => {
|
|
|
493
605
|
];
|
|
494
606
|
test.each(unchangedTestCases)(
|
|
495
607
|
`Test unchanged value is retained following read and write - $vr`,
|
|
496
|
-
|
|
608
|
+
dataElement => {
|
|
497
609
|
const dataset = {
|
|
498
|
-
|
|
610
|
+
"00181041": {
|
|
499
611
|
...dataElement
|
|
500
|
-
}
|
|
612
|
+
}
|
|
501
613
|
};
|
|
502
614
|
|
|
503
615
|
const dicomDict = new DicomDict({});
|
|
504
616
|
dicomDict.dict = dataset;
|
|
505
617
|
|
|
506
618
|
// write and re-read
|
|
507
|
-
const outputDicomDict = DicomMessage.readFile(
|
|
619
|
+
const outputDicomDict = DicomMessage.readFile(
|
|
620
|
+
dicomDict.write(),
|
|
621
|
+
{ forceStoreRaw: true }
|
|
622
|
+
);
|
|
508
623
|
|
|
509
624
|
// expect raw value to be unchanged, and Value parsed as Number to lose precision
|
|
510
|
-
expect(outputDicomDict.dict[
|
|
511
|
-
|
|
625
|
+
expect(outputDicomDict.dict["00181041"]._rawValue).toEqual(
|
|
626
|
+
dataElement._rawValue
|
|
627
|
+
);
|
|
628
|
+
expect(outputDicomDict.dict["00181041"].Value).toEqual(
|
|
629
|
+
dataElement.Value
|
|
630
|
+
);
|
|
512
631
|
}
|
|
513
|
-
)
|
|
632
|
+
);
|
|
514
633
|
|
|
515
634
|
const changedTestCases = [
|
|
516
635
|
{
|
|
517
636
|
vr: "AE",
|
|
518
637
|
_rawValue: [" TEST_AE "], // spaces non-significant for interpretation but allowed
|
|
519
|
-
Value: ["NEW_AE"]
|
|
638
|
+
Value: ["NEW_AE"]
|
|
520
639
|
},
|
|
521
640
|
{
|
|
522
641
|
vr: "AS",
|
|
523
642
|
_rawValue: ["045Y"],
|
|
524
|
-
Value: ["999Y"]
|
|
643
|
+
Value: ["999Y"]
|
|
525
644
|
},
|
|
526
645
|
{
|
|
527
646
|
vr: "AT",
|
|
528
|
-
_rawValue: [
|
|
529
|
-
Value: [0x00200010]
|
|
647
|
+
_rawValue: [0x00207e14, 0x0012839a],
|
|
648
|
+
Value: [0x00200010]
|
|
530
649
|
},
|
|
531
650
|
{
|
|
532
651
|
vr: "CS",
|
|
533
652
|
_rawValue: ["ORIGINAL ", " PRIMARY "], // spaces non-significant for interpretation but allowed
|
|
534
|
-
Value: ["ORIGINAL", "PRIMARY", "SECONDARY"]
|
|
653
|
+
Value: ["ORIGINAL", "PRIMARY", "SECONDARY"]
|
|
535
654
|
},
|
|
536
655
|
{
|
|
537
656
|
vr: "DA",
|
|
538
657
|
_rawValue: ["20240101"],
|
|
539
|
-
Value: ["20231225"]
|
|
658
|
+
Value: ["20231225"]
|
|
540
659
|
},
|
|
541
660
|
{
|
|
542
661
|
vr: "DS",
|
|
@@ -545,50 +664,74 @@ describe('lossless-read-write', () => {
|
|
|
545
664
|
newRawValue: ["123.456 "]
|
|
546
665
|
},
|
|
547
666
|
{
|
|
548
|
-
vr:
|
|
667
|
+
vr: "DT",
|
|
549
668
|
_rawValue: ["20240101123045.1 "], // trailing spaces allowed
|
|
550
|
-
Value: ["20240101123045.3"]
|
|
669
|
+
Value: ["20240101123045.3"]
|
|
551
670
|
},
|
|
552
671
|
{
|
|
553
|
-
vr:
|
|
672
|
+
vr: "FL",
|
|
554
673
|
_rawValue: [3.125],
|
|
555
|
-
Value: [22]
|
|
674
|
+
Value: [22]
|
|
556
675
|
},
|
|
557
676
|
{
|
|
558
|
-
vr:
|
|
677
|
+
vr: "FD",
|
|
559
678
|
_rawValue: [3.14159265358979], // trailing spaces allowed
|
|
560
|
-
Value: [50.1242]
|
|
679
|
+
Value: [50.1242]
|
|
561
680
|
},
|
|
562
681
|
{
|
|
563
|
-
vr:
|
|
682
|
+
vr: "IS",
|
|
564
683
|
_rawValue: [" -123 "], // leading/trailing spaces & sign allowed
|
|
565
684
|
Value: [0],
|
|
566
685
|
newRawValue: ["0 "]
|
|
567
686
|
},
|
|
568
687
|
{
|
|
569
|
-
vr:
|
|
688
|
+
vr: "LO",
|
|
570
689
|
_rawValue: [" A long string with spaces "], // leading/trailing spaces allowed
|
|
571
|
-
Value: ["A changed string that is still long."]
|
|
690
|
+
Value: ["A changed string that is still long."]
|
|
572
691
|
},
|
|
573
692
|
{
|
|
574
|
-
vr:
|
|
575
|
-
_rawValue: [
|
|
576
|
-
|
|
693
|
+
vr: "LT",
|
|
694
|
+
_rawValue: [
|
|
695
|
+
" It may contain the Graphic Character set and the Control Characters, CR\r, LF\n, FF\f, and ESC\x1b. "
|
|
696
|
+
], // leading spaces significant, trailing spaces allowed
|
|
697
|
+
Value: [" A modified string of text"]
|
|
577
698
|
},
|
|
578
699
|
{
|
|
579
|
-
vr:
|
|
580
|
-
_rawValue: [
|
|
581
|
-
|
|
700
|
+
vr: "OB",
|
|
701
|
+
_rawValue: [
|
|
702
|
+
new Uint8Array([
|
|
703
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
704
|
+
]).buffer
|
|
705
|
+
],
|
|
706
|
+
Value: [new Uint8Array([0x01, 0x02]).buffer]
|
|
582
707
|
},
|
|
583
708
|
{
|
|
584
|
-
vr:
|
|
585
|
-
_rawValue: [
|
|
586
|
-
|
|
709
|
+
vr: "OD",
|
|
710
|
+
_rawValue: [
|
|
711
|
+
new Uint8Array([
|
|
712
|
+
0x00, 0x00, 0x00, 0x54, 0x34, 0x6f, 0x9d, 0x41
|
|
713
|
+
]).buffer
|
|
714
|
+
],
|
|
715
|
+
Value: [
|
|
716
|
+
new Uint8Array([
|
|
717
|
+
0x00, 0x00, 0x00, 0x54, 0x35, 0x6e, 0x9e, 0x42
|
|
718
|
+
]).buffer
|
|
719
|
+
]
|
|
587
720
|
},
|
|
588
721
|
{
|
|
589
|
-
vr:
|
|
590
|
-
_rawValue: [
|
|
591
|
-
|
|
722
|
+
vr: "OF",
|
|
723
|
+
_rawValue: [
|
|
724
|
+
new Uint8Array([
|
|
725
|
+
0x00, 0x00, 0x28, 0x41, 0x00, 0x00, 0x30, 0xc0, 0x00,
|
|
726
|
+
0x00, 0xf6, 0x42
|
|
727
|
+
]).buffer
|
|
728
|
+
],
|
|
729
|
+
Value: [
|
|
730
|
+
new Uint8Array([
|
|
731
|
+
0x00, 0x00, 0x28, 0x41, 0x00, 0x00, 0x30, 0xc0, 0x00,
|
|
732
|
+
0x00, 0xf6, 0x43
|
|
733
|
+
]).buffer
|
|
734
|
+
]
|
|
592
735
|
},
|
|
593
736
|
// TODO: VRs currently unimplemented
|
|
594
737
|
// {
|
|
@@ -600,35 +743,45 @@ describe('lossless-read-write', () => {
|
|
|
600
743
|
// _rawValue: [new Uint8Array([0x00, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x28, 0x41]).buffer],
|
|
601
744
|
// },
|
|
602
745
|
{
|
|
603
|
-
vr:
|
|
604
|
-
_rawValue: [
|
|
605
|
-
|
|
746
|
+
vr: "OW",
|
|
747
|
+
_rawValue: [
|
|
748
|
+
new Uint8Array([
|
|
749
|
+
0x13, 0x40, 0x80, 0x88, 0x89, 0x91, 0x89, 0x89
|
|
750
|
+
]).buffer
|
|
751
|
+
],
|
|
752
|
+
Value: [
|
|
753
|
+
new Uint8Array([
|
|
754
|
+
0x13, 0x40, 0x80, 0x88, 0x88, 0x90, 0x88, 0x88
|
|
755
|
+
]).buffer
|
|
756
|
+
]
|
|
606
757
|
},
|
|
607
758
|
{
|
|
608
|
-
vr:
|
|
759
|
+
vr: "PN",
|
|
609
760
|
_rawValue: ["Doe^John^A^Jr.^MD "], // trailing spaces allowed
|
|
610
|
-
Value: [{
|
|
761
|
+
Value: [{ Alphabetic: "Doe^Jane^A^Jr.^MD" }],
|
|
611
762
|
newRawValue: ["Doe^Jane^A^Jr.^MD"]
|
|
612
763
|
},
|
|
613
764
|
{
|
|
614
|
-
vr:
|
|
765
|
+
vr: "SH",
|
|
615
766
|
_rawValue: [" CT_SCAN_01 "], // leading/trailing spaces allowed
|
|
616
|
-
Value: ["MR_SCAN_91"]
|
|
767
|
+
Value: ["MR_SCAN_91"]
|
|
617
768
|
},
|
|
618
769
|
{
|
|
619
|
-
vr:
|
|
770
|
+
vr: "SL",
|
|
620
771
|
_rawValue: [-2147483648],
|
|
621
|
-
Value: [-2147481234]
|
|
772
|
+
Value: [-2147481234]
|
|
622
773
|
},
|
|
623
774
|
{
|
|
624
|
-
vr:
|
|
775
|
+
vr: "SS",
|
|
625
776
|
_rawValue: [-32768, 1234, 832],
|
|
626
|
-
Value: [1234]
|
|
777
|
+
Value: [1234]
|
|
627
778
|
},
|
|
628
779
|
{
|
|
629
|
-
vr:
|
|
630
|
-
_rawValue: [
|
|
631
|
-
|
|
780
|
+
vr: "ST",
|
|
781
|
+
_rawValue: [
|
|
782
|
+
"Patient complains of headaches over the last week. "
|
|
783
|
+
], // trailing spaces allowed
|
|
784
|
+
Value: ["Patient complains of headaches"]
|
|
632
785
|
},
|
|
633
786
|
// TODO: VR currently unimplemented
|
|
634
787
|
// {
|
|
@@ -636,41 +789,45 @@ describe('lossless-read-write', () => {
|
|
|
636
789
|
// _rawValue: [9007199254740993], // trailing spaces allowed
|
|
637
790
|
// },
|
|
638
791
|
{
|
|
639
|
-
vr:
|
|
792
|
+
vr: "TM",
|
|
640
793
|
_rawValue: ["42530.123456 "], // trailing spaces allowed
|
|
641
794
|
Value: ["42530"],
|
|
642
795
|
newRawValue: ["42530 "]
|
|
643
796
|
},
|
|
644
797
|
{
|
|
645
|
-
vr:
|
|
646
|
-
_rawValue: [
|
|
647
|
-
|
|
798
|
+
vr: "UC",
|
|
799
|
+
_rawValue: [
|
|
800
|
+
"Detailed description of procedure or clinical notes that could be very long. "
|
|
801
|
+
], // trailing spaces allowed
|
|
802
|
+
Value: ["Detailed description of procedure and other things"]
|
|
648
803
|
},
|
|
649
804
|
{
|
|
650
|
-
vr:
|
|
805
|
+
vr: "UI",
|
|
651
806
|
_rawValue: ["1.2.840.10008.1.2.1"],
|
|
652
|
-
Value: ["1.2.840.10008.1.2.2"]
|
|
807
|
+
Value: ["1.2.840.10008.1.2.2"]
|
|
653
808
|
},
|
|
654
809
|
{
|
|
655
|
-
vr:
|
|
810
|
+
vr: "UL",
|
|
656
811
|
_rawValue: [4294967295],
|
|
657
|
-
Value: [1]
|
|
812
|
+
Value: [1]
|
|
658
813
|
},
|
|
659
814
|
{
|
|
660
|
-
vr:
|
|
815
|
+
vr: "UR",
|
|
661
816
|
_rawValue: ["http://dicom.nema.org "], // trailing spaces ignored but allowed
|
|
662
|
-
Value: ["https://github.com/dcmjs-org"]
|
|
817
|
+
Value: ["https://github.com/dcmjs-org"]
|
|
663
818
|
},
|
|
664
819
|
{
|
|
665
|
-
vr:
|
|
820
|
+
vr: "US",
|
|
666
821
|
_rawValue: [65535],
|
|
667
|
-
Value: [1]
|
|
822
|
+
Value: [1]
|
|
668
823
|
},
|
|
669
824
|
{
|
|
670
|
-
vr:
|
|
671
|
-
_rawValue: [
|
|
672
|
-
|
|
673
|
-
|
|
825
|
+
vr: "UT",
|
|
826
|
+
_rawValue: [
|
|
827
|
+
" This is a detailed explanation that can span multiple lines and paragraphs in the DICOM dataset. "
|
|
828
|
+
], // leading spaces significant, trailing spaces allowed
|
|
829
|
+
Value: [""]
|
|
830
|
+
}
|
|
674
831
|
// TODO: VR currently unimplemented
|
|
675
832
|
// {
|
|
676
833
|
// vr: 'UV',
|
|
@@ -680,37 +837,45 @@ describe('lossless-read-write', () => {
|
|
|
680
837
|
|
|
681
838
|
test.each(changedTestCases)(
|
|
682
839
|
`Test changed value overwrites original value following read and write - $vr`,
|
|
683
|
-
|
|
840
|
+
dataElement => {
|
|
684
841
|
const dataset = {
|
|
685
|
-
|
|
842
|
+
"00181041": {
|
|
686
843
|
...dataElement
|
|
687
|
-
}
|
|
844
|
+
}
|
|
688
845
|
};
|
|
689
846
|
|
|
690
847
|
const dicomDict = new DicomDict({});
|
|
691
848
|
dicomDict.dict = dataset;
|
|
692
849
|
|
|
693
850
|
// write and re-read
|
|
694
|
-
const outputDicomDict = DicomMessage.readFile(
|
|
851
|
+
const outputDicomDict = DicomMessage.readFile(
|
|
852
|
+
dicomDict.write(),
|
|
853
|
+
{ forceStoreRaw: true }
|
|
854
|
+
);
|
|
695
855
|
|
|
696
856
|
// expect raw value to be updated to match new Value parsed as Number to lose precision
|
|
697
|
-
expect(outputDicomDict.dict[
|
|
698
|
-
|
|
857
|
+
expect(outputDicomDict.dict["00181041"]._rawValue).toEqual(
|
|
858
|
+
dataElement.newRawValue ?? dataElement.Value
|
|
859
|
+
);
|
|
860
|
+
expect(outputDicomDict.dict["00181041"].Value).toEqual(
|
|
861
|
+
dataElement.Value
|
|
862
|
+
);
|
|
699
863
|
}
|
|
700
|
-
)
|
|
701
|
-
|
|
864
|
+
);
|
|
702
865
|
});
|
|
703
866
|
|
|
704
|
-
describe(
|
|
705
|
-
test(
|
|
867
|
+
describe("sequences", () => {
|
|
868
|
+
test("nested sequences should support lossless round trip", () => {
|
|
706
869
|
const dataset = {
|
|
707
|
-
|
|
870
|
+
52009229: {
|
|
708
871
|
vr: "SQ",
|
|
709
872
|
Value: [
|
|
710
873
|
{
|
|
711
874
|
"0020000E": {
|
|
712
875
|
vr: "UI",
|
|
713
|
-
Value: [
|
|
876
|
+
Value: [
|
|
877
|
+
"1.3.6.1.4.1.5962.99.1.2280943358.716200484.1363785608958.1.1"
|
|
878
|
+
]
|
|
714
879
|
},
|
|
715
880
|
"00089123": {
|
|
716
881
|
vr: "SQ",
|
|
@@ -719,24 +884,24 @@ describe('lossless-read-write', () => {
|
|
|
719
884
|
"00181030": {
|
|
720
885
|
vr: "AE",
|
|
721
886
|
_rawValue: [" TEST_AE "],
|
|
722
|
-
Value: ["TEST_AE"]
|
|
887
|
+
Value: ["TEST_AE"]
|
|
723
888
|
},
|
|
724
889
|
"00180050": {
|
|
725
890
|
vr: "DS",
|
|
726
891
|
Value: [5.0],
|
|
727
|
-
|
|
892
|
+
_rawValue: ["5.000 "]
|
|
728
893
|
}
|
|
729
894
|
},
|
|
730
895
|
{
|
|
731
896
|
"00181030": {
|
|
732
897
|
vr: "AE",
|
|
733
898
|
_rawValue: [" TEST_AE "],
|
|
734
|
-
Value: ["TEST_AE"]
|
|
899
|
+
Value: ["TEST_AE"]
|
|
735
900
|
},
|
|
736
901
|
"00180050": {
|
|
737
902
|
vr: "DS",
|
|
738
903
|
Value: [6.0],
|
|
739
|
-
|
|
904
|
+
_rawValue: ["6.000 "]
|
|
740
905
|
}
|
|
741
906
|
}
|
|
742
907
|
]
|
|
@@ -745,7 +910,9 @@ describe('lossless-read-write', () => {
|
|
|
745
910
|
{
|
|
746
911
|
"0020000E": {
|
|
747
912
|
vr: "UI",
|
|
748
|
-
Value: [
|
|
913
|
+
Value: [
|
|
914
|
+
"1.3.6.1.4.1.5962.99.1.2280943358.716200484.1363785608958.1.2"
|
|
915
|
+
]
|
|
749
916
|
},
|
|
750
917
|
"00089123": {
|
|
751
918
|
vr: "SQ",
|
|
@@ -756,9 +923,9 @@ describe('lossless-read-write', () => {
|
|
|
756
923
|
Value: ["ABDOMEN MRI"]
|
|
757
924
|
},
|
|
758
925
|
"00180050": {
|
|
759
|
-
vr:
|
|
926
|
+
vr: "IS",
|
|
760
927
|
_rawValue: [" -123 "], // leading/trailing spaces & sign allowed
|
|
761
|
-
Value: [-123]
|
|
928
|
+
Value: [-123]
|
|
762
929
|
}
|
|
763
930
|
}
|
|
764
931
|
]
|
|
@@ -767,7 +934,7 @@ describe('lossless-read-write', () => {
|
|
|
767
934
|
]
|
|
768
935
|
}
|
|
769
936
|
};
|
|
770
|
-
|
|
937
|
+
|
|
771
938
|
const dicomDict = new DicomDict({});
|
|
772
939
|
dicomDict.dict = dataset;
|
|
773
940
|
|
|
@@ -776,35 +943,48 @@ describe('lossless-read-write', () => {
|
|
|
776
943
|
const outputDicomDict = DicomMessage.readFile(outputBuffer);
|
|
777
944
|
|
|
778
945
|
// lossless read/write should match entire data set
|
|
779
|
-
deepEqual(dicomDict.dict, outputDicomDict.dict)
|
|
780
|
-
})
|
|
781
|
-
})
|
|
946
|
+
deepEqual(dicomDict.dict, outputDicomDict.dict);
|
|
947
|
+
});
|
|
948
|
+
});
|
|
782
949
|
|
|
783
|
-
test(
|
|
784
|
-
const inputBuffer = await getDcmjsDataFile(
|
|
950
|
+
test("File dataset should be equal after read and write", async () => {
|
|
951
|
+
const inputBuffer = await getDcmjsDataFile(
|
|
952
|
+
"unknown-VR",
|
|
953
|
+
"sample-dicom-with-un-vr.dcm"
|
|
954
|
+
);
|
|
785
955
|
const dicomDict = DicomMessage.readFile(inputBuffer);
|
|
786
956
|
|
|
787
957
|
// confirm raw string representation of DS contains extra additional metadata
|
|
788
958
|
// represented by bytes [30 2E 31 34 30 5C 30 2E 31 34 30 20]
|
|
789
|
-
expect(dicomDict.dict[
|
|
790
|
-
|
|
959
|
+
expect(dicomDict.dict["00280030"]._rawValue).toEqual([
|
|
960
|
+
"0.140",
|
|
961
|
+
"0.140 "
|
|
962
|
+
]);
|
|
963
|
+
expect(dicomDict.dict["00280030"].Value).toEqual([0.14, 0.14]);
|
|
791
964
|
|
|
792
965
|
// confirm after write raw values are re-encoded
|
|
793
966
|
const outputBuffer = dicomDict.write();
|
|
794
967
|
const outputDicomDict = DicomMessage.readFile(outputBuffer);
|
|
795
968
|
|
|
796
969
|
// explicitly verify for DS for clarity
|
|
797
|
-
expect(outputDicomDict.dict[
|
|
798
|
-
|
|
970
|
+
expect(outputDicomDict.dict["00280030"]._rawValue).toEqual([
|
|
971
|
+
"0.140",
|
|
972
|
+
"0.140 "
|
|
973
|
+
]);
|
|
974
|
+
expect(outputDicomDict.dict["00280030"].Value).toEqual([0.14, 0.14]);
|
|
799
975
|
|
|
800
976
|
// lossless read/write should match entire data set
|
|
801
|
-
deepEqual(dicomDict.dict, outputDicomDict.dict)
|
|
977
|
+
deepEqual(dicomDict.dict, outputDicomDict.dict);
|
|
802
978
|
});
|
|
803
979
|
});
|
|
804
980
|
|
|
805
981
|
const getDcmjsDataFile = async (release, fileName) => {
|
|
806
|
-
const url =
|
|
982
|
+
const url =
|
|
983
|
+
"https://github.com/dcmjs-org/data/releases/download/" +
|
|
984
|
+
release +
|
|
985
|
+
"/" +
|
|
986
|
+
fileName;
|
|
807
987
|
const dcmPath = await getTestDataset(url, fileName);
|
|
808
988
|
|
|
809
989
|
return fs.readFileSync(dcmPath).buffer;
|
|
810
|
-
}
|
|
990
|
+
};
|