dcmjs 0.24.1 → 0.24.2
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/build/dcmjs.es.js +94 -47
- package/build/dcmjs.es.js.map +1 -1
- package/build/dcmjs.js +94 -47
- package/build/dcmjs.js.map +1 -1
- package/package.json +1 -1
- package/test/data-options.test.js +237 -0
- package/test/data.test.js +22 -50
- package/test/untilTag.test.js +0 -44
package/package.json
CHANGED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import "regenerator-runtime/runtime.js";
|
|
2
|
+
|
|
3
|
+
import dcmjs from "../src/index.js";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import os from "os";
|
|
7
|
+
import followRedirects from "follow-redirects";
|
|
8
|
+
const { https } = followRedirects;
|
|
9
|
+
import { promisify } from "util";
|
|
10
|
+
import unzipper from "unzipper";
|
|
11
|
+
import fsPromises from "fs/promises";
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
DicomMetaDictionary,
|
|
15
|
+
DicomDict,
|
|
16
|
+
DicomMessage,
|
|
17
|
+
ReadBufferStream
|
|
18
|
+
} = dcmjs.data;
|
|
19
|
+
|
|
20
|
+
function downloadToFile(url, filePath) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const fileStream = fs.createWriteStream(filePath);
|
|
23
|
+
https
|
|
24
|
+
.get(url, response => {
|
|
25
|
+
response.pipe(fileStream);
|
|
26
|
+
fileStream.on("finish", () => {
|
|
27
|
+
resolve(filePath);
|
|
28
|
+
});
|
|
29
|
+
})
|
|
30
|
+
.on("error", reject);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const areEqual = (first, second) =>
|
|
35
|
+
first.byteLength === second.byteLength &&
|
|
36
|
+
first.every((value, index) => value === second[index]);
|
|
37
|
+
|
|
38
|
+
it("test_untilTag", () => {
|
|
39
|
+
const buffer = fs.readFileSync("test/sample-dicom.dcm");
|
|
40
|
+
console.time("readFile");
|
|
41
|
+
const fullData = DicomMessage.readFile(buffer.buffer);
|
|
42
|
+
console.timeEnd("readFile");
|
|
43
|
+
|
|
44
|
+
console.time("readFile without untilTag");
|
|
45
|
+
const dicomData = DicomMessage.readFile(buffer.buffer, {
|
|
46
|
+
untilTag: "7FE00010",
|
|
47
|
+
includeUntilTagValue: false
|
|
48
|
+
});
|
|
49
|
+
console.timeEnd("readFile without untilTag");
|
|
50
|
+
|
|
51
|
+
console.time("readFile with untilTag");
|
|
52
|
+
const dicomData2 = DicomMessage.readFile(buffer.buffer, {
|
|
53
|
+
untilTag: "7FE00010",
|
|
54
|
+
includeUntilTagValue: true
|
|
55
|
+
});
|
|
56
|
+
console.timeEnd("readFile with untilTag");
|
|
57
|
+
|
|
58
|
+
const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
|
|
59
|
+
full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
|
|
60
|
+
|
|
61
|
+
const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
|
62
|
+
dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
|
63
|
+
|
|
64
|
+
const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
|
|
65
|
+
dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
|
|
66
|
+
|
|
67
|
+
expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
|
|
68
|
+
expect(dataset.PixelData).toEqual(0);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("noCopy multiframe DICOM which has trailing padding", async () => {
|
|
72
|
+
const dicomUrl =
|
|
73
|
+
"https://github.com/dcmjs-org/data/releases/download/binary-parsing-stressors/multiframe-ultrasound.dcm";
|
|
74
|
+
const dicomPath = path.join(os.tmpdir(), "multiframe-ultrasound.dcm");
|
|
75
|
+
|
|
76
|
+
await downloadToFile(dicomUrl, dicomPath);
|
|
77
|
+
|
|
78
|
+
const dicomDictNoCopy = DicomMessage.readFile(
|
|
79
|
+
fs.readFileSync(dicomPath).buffer,
|
|
80
|
+
{
|
|
81
|
+
noCopy: true
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const dicomDict = DicomMessage.readFile(fs.readFileSync(dicomPath).buffer, {
|
|
86
|
+
noCopy: false
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
Object.keys(dicomDict.dict).map(key => {
|
|
90
|
+
const value = dicomDict.dict[key].Value;
|
|
91
|
+
if (value[0] instanceof ArrayBuffer) {
|
|
92
|
+
value.map((e, idx) => {
|
|
93
|
+
const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
|
|
94
|
+
const copyValue = new Uint8Array(e);
|
|
95
|
+
expect(areEqual(noCopyValue, copyValue)).toEqual(true);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("noCopy multiframe DICOM with large private tags before and after the image data", async () => {
|
|
102
|
+
const dicomUrl =
|
|
103
|
+
"https://github.com/dcmjs-org/data/releases/download/binary-parsing-stressors/large-private-tags.dcm";
|
|
104
|
+
const dicomPath = path.join(os.tmpdir(), "large-private-tags.dcm");
|
|
105
|
+
|
|
106
|
+
await downloadToFile(dicomUrl, dicomPath);
|
|
107
|
+
|
|
108
|
+
const dicomDictNoCopy = DicomMessage.readFile(
|
|
109
|
+
fs.readFileSync(dicomPath).buffer,
|
|
110
|
+
{
|
|
111
|
+
noCopy: true
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const dicomDict = DicomMessage.readFile(fs.readFileSync(dicomPath).buffer, {
|
|
116
|
+
noCopy: false
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
Object.keys(dicomDict.dict).map(key => {
|
|
120
|
+
const value = dicomDict.dict[key].Value;
|
|
121
|
+
if (value[0] instanceof ArrayBuffer) {
|
|
122
|
+
value.map((e, idx) => {
|
|
123
|
+
const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
|
|
124
|
+
const copyValue = new Uint8Array(e);
|
|
125
|
+
expect(areEqual(noCopyValue, copyValue)).toEqual(true);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("noCopy binary data into an ArrayBuffer", async () => {
|
|
132
|
+
const dicomUrl =
|
|
133
|
+
"https://github.com/dcmjs-org/data/releases/download/binary-tag/binary-tag.dcm";
|
|
134
|
+
const dicomPath = path.join(os.tmpdir(), "binary-tag.dcm");
|
|
135
|
+
|
|
136
|
+
await downloadToFile(dicomUrl, dicomPath);
|
|
137
|
+
const fileData = await promisify(fs.readFile)(dicomPath);
|
|
138
|
+
|
|
139
|
+
const dicomDictNoCopy = DicomMessage.readFile(fileData.buffer, {
|
|
140
|
+
noCopy: true
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const dicomDict = DicomMessage.readFile(fileData.buffer, {
|
|
144
|
+
noCopy: false
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
Object.keys(dicomDict.dict).map(key => {
|
|
148
|
+
const value = dicomDict.dict[key].Value;
|
|
149
|
+
if (value[0] instanceof ArrayBuffer) {
|
|
150
|
+
value.map((e, idx) => {
|
|
151
|
+
const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
|
|
152
|
+
const copyValue = new Uint8Array(e);
|
|
153
|
+
expect(areEqual(noCopyValue, copyValue)).toEqual(true);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("noCopy test_multiframe_1", async () => {
|
|
160
|
+
const url =
|
|
161
|
+
"https://github.com/dcmjs-org/data/releases/download/MRHead/MRHead.zip";
|
|
162
|
+
const zipFilePath = path.join(os.tmpdir(), "MRHead.zip");
|
|
163
|
+
const unzipPath = path.join(os.tmpdir(), "test_multiframe_1");
|
|
164
|
+
|
|
165
|
+
await downloadToFile(url, zipFilePath);
|
|
166
|
+
|
|
167
|
+
await new Promise(resolve => {
|
|
168
|
+
fs.createReadStream(zipFilePath).pipe(
|
|
169
|
+
unzipper.Extract({ path: unzipPath }).on("close", resolve)
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const mrHeadPath = path.join(unzipPath, "MRHead");
|
|
174
|
+
const fileNames = await fsPromises.readdir(mrHeadPath);
|
|
175
|
+
|
|
176
|
+
const datasets = [];
|
|
177
|
+
fileNames.forEach(fileName => {
|
|
178
|
+
const arrayBuffer = fs.readFileSync(path.join(mrHeadPath, fileName))
|
|
179
|
+
.buffer;
|
|
180
|
+
const dicomDictNoCopy = DicomMessage.readFile(arrayBuffer, {
|
|
181
|
+
noCopy: true
|
|
182
|
+
});
|
|
183
|
+
const dicomDict = DicomMessage.readFile(arrayBuffer, {
|
|
184
|
+
noCopy: false
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
Object.keys(dicomDict.dict).map(key => {
|
|
188
|
+
const value = dicomDict.dict[key].Value;
|
|
189
|
+
if (value[0] instanceof ArrayBuffer) {
|
|
190
|
+
value.map((e, idx) => {
|
|
191
|
+
const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
|
|
192
|
+
const copyValue = new Uint8Array(e);
|
|
193
|
+
expect(areEqual(noCopyValue, copyValue)).toEqual(true);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("noCopy test_fragment_multiframe", async () => {
|
|
201
|
+
const url =
|
|
202
|
+
"https://github.com/dcmjs-org/data/releases/download/encapsulation/encapsulation-fragment-multiframe.dcm";
|
|
203
|
+
const dcmPath = path.join(
|
|
204
|
+
os.tmpdir(),
|
|
205
|
+
"encapsulation-fragment-multiframe.dcm"
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
await downloadToFile(url, dcmPath);
|
|
209
|
+
const file = fs.readFileSync(dcmPath);
|
|
210
|
+
|
|
211
|
+
const dicomDict = dcmjs.data.DicomMessage.readFile(file.buffer, {
|
|
212
|
+
// ignoreErrors: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const dicomDictNoCopy = DicomMessage.readFile(file.buffer, {
|
|
216
|
+
noCopy: true
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
Object.keys(dicomDict.dict).map(key => {
|
|
220
|
+
const value = dicomDict.dict[key].Value;
|
|
221
|
+
if (value[0] instanceof ArrayBuffer) {
|
|
222
|
+
value.map((e, idx) => {
|
|
223
|
+
const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
|
|
224
|
+
const copyValue = new Uint8Array(e);
|
|
225
|
+
const areEqual = (first, second) =>
|
|
226
|
+
first.every((value, index) => value === second[index]);
|
|
227
|
+
|
|
228
|
+
const totalSize = noCopyValue.reduce(
|
|
229
|
+
(sum, arr) => sum + arr.byteLength,
|
|
230
|
+
0
|
|
231
|
+
);
|
|
232
|
+
expect(totalSize).toEqual(copyValue.length);
|
|
233
|
+
expect(areEqual(noCopyValue[0], copyValue)).toEqual(true);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
});
|
package/test/data.test.js
CHANGED
|
@@ -17,8 +17,12 @@ import minimalDataset from "./mocks/minimal_fields_dataset.json";
|
|
|
17
17
|
import arrayItem from "./arrayItem.json";
|
|
18
18
|
import { rawTags } from "./rawTags";
|
|
19
19
|
|
|
20
|
-
const {
|
|
21
|
-
|
|
20
|
+
const {
|
|
21
|
+
DicomMetaDictionary,
|
|
22
|
+
DicomDict,
|
|
23
|
+
DicomMessage,
|
|
24
|
+
ReadBufferStream
|
|
25
|
+
} = dcmjs.data;
|
|
22
26
|
|
|
23
27
|
const EXPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2.1";
|
|
24
28
|
|
|
@@ -171,8 +175,9 @@ it("test_json_1", () => {
|
|
|
171
175
|
//
|
|
172
176
|
// make a natural version of a dataset with sequence tags and confirm it has correct values
|
|
173
177
|
//
|
|
174
|
-
const naturalSequence =
|
|
175
|
-
|
|
178
|
+
const naturalSequence = DicomMetaDictionary.naturalizeDataset(
|
|
179
|
+
sequenceMetadata
|
|
180
|
+
);
|
|
176
181
|
|
|
177
182
|
// The match object needs to be done on the actual element, not the proxied value
|
|
178
183
|
expect(naturalSequence.ProcedureCodeSequence[0]).toMatchObject({
|
|
@@ -234,17 +239,17 @@ it("test_multiframe_1", async () => {
|
|
|
234
239
|
|
|
235
240
|
const datasets = [];
|
|
236
241
|
fileNames.forEach(fileName => {
|
|
237
|
-
const arrayBuffer = fs.readFileSync(
|
|
238
|
-
|
|
239
|
-
).buffer;
|
|
242
|
+
const arrayBuffer = fs.readFileSync(path.join(mrHeadPath, fileName))
|
|
243
|
+
.buffer;
|
|
240
244
|
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
241
245
|
const dataset = DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
|
|
242
246
|
|
|
243
247
|
datasets.push(dataset);
|
|
244
248
|
});
|
|
245
249
|
|
|
246
|
-
const multiframe =
|
|
247
|
-
|
|
250
|
+
const multiframe = dcmjs.normalizers.Normalizer.normalizeToDataset(
|
|
251
|
+
datasets
|
|
252
|
+
);
|
|
248
253
|
const spacing =
|
|
249
254
|
multiframe.SharedFunctionalGroupsSequence.PixelMeasuresSequence
|
|
250
255
|
.SpacingBetweenSlices;
|
|
@@ -280,9 +285,8 @@ it("test_oneslice_seg", async () => {
|
|
|
280
285
|
|
|
281
286
|
const datasets = [];
|
|
282
287
|
fileNames.forEach(fileName => {
|
|
283
|
-
const arrayBuffer = fs.readFileSync(
|
|
284
|
-
|
|
285
|
-
).buffer;
|
|
288
|
+
const arrayBuffer = fs.readFileSync(path.join(ctPelvisPath, fileName))
|
|
289
|
+
.buffer;
|
|
286
290
|
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
287
291
|
const dataset = DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
|
|
288
292
|
datasets.push(dataset);
|
|
@@ -308,8 +312,9 @@ it("test_oneslice_seg", async () => {
|
|
|
308
312
|
});
|
|
309
313
|
|
|
310
314
|
it("test_normalizer_smaller", () => {
|
|
311
|
-
const naturalizedTags =
|
|
312
|
-
|
|
315
|
+
const naturalizedTags = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
|
|
316
|
+
rawTags
|
|
317
|
+
);
|
|
313
318
|
|
|
314
319
|
const rawTagsLen = JSON.stringify(rawTags).length;
|
|
315
320
|
const naturalizedTagsLen = JSON.stringify(naturalizedTags).length;
|
|
@@ -452,39 +457,6 @@ it("test_invalid_vr_length", () => {
|
|
|
452
457
|
}
|
|
453
458
|
});
|
|
454
459
|
|
|
455
|
-
it("test_untiltag", () => {
|
|
456
|
-
const buffer = fs.readFileSync("test/sample-dicom.dcm");
|
|
457
|
-
console.time("readFile");
|
|
458
|
-
const fullData = DicomMessage.readFile(buffer.buffer);
|
|
459
|
-
console.timeEnd("readFile");
|
|
460
|
-
|
|
461
|
-
console.time("readFile without untilTag");
|
|
462
|
-
const dicomData = DicomMessage.readFile(buffer.buffer, {
|
|
463
|
-
untilTag: "7FE00010",
|
|
464
|
-
includeUntilTagValue: false
|
|
465
|
-
});
|
|
466
|
-
console.timeEnd("readFile without untilTag");
|
|
467
|
-
|
|
468
|
-
console.time("readFile with untilTag");
|
|
469
|
-
const dicomData2 = DicomMessage.readFile(buffer.buffer, {
|
|
470
|
-
untilTag: "7FE00010",
|
|
471
|
-
includeUntilTagValue: true
|
|
472
|
-
});
|
|
473
|
-
console.timeEnd("readFile with untilTag");
|
|
474
|
-
|
|
475
|
-
const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
|
|
476
|
-
full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
|
|
477
|
-
|
|
478
|
-
const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
|
479
|
-
dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
|
480
|
-
|
|
481
|
-
const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
|
|
482
|
-
dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
|
|
483
|
-
|
|
484
|
-
expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
|
|
485
|
-
expect(dataset.PixelData).toEqual(0);
|
|
486
|
-
});
|
|
487
|
-
|
|
488
460
|
it("test_encapsulation", async () => {
|
|
489
461
|
const url =
|
|
490
462
|
"https://github.com/dcmjs-org/data/releases/download/encapsulation/encapsulation.dcm";
|
|
@@ -531,10 +503,10 @@ it("test_encapsulation", async () => {
|
|
|
531
503
|
throw new Error("Invalid a dicom file");
|
|
532
504
|
}
|
|
533
505
|
|
|
534
|
-
const el = DicomMessage.
|
|
506
|
+
const el = DicomMessage._readTag(stream, useSyntax),
|
|
535
507
|
metaLength = el.values[0]; //read header buffer
|
|
536
508
|
const metaStream = stream.more(metaLength);
|
|
537
|
-
const metaHeader = DicomMessage.
|
|
509
|
+
const metaHeader = DicomMessage._read(metaStream, useSyntax); //get the syntax
|
|
538
510
|
let mainSyntax = metaHeader["00020010"].Value[0];
|
|
539
511
|
|
|
540
512
|
mainSyntax = DicomMessage._normalizeSyntax(mainSyntax);
|
|
@@ -565,7 +537,7 @@ it("test_encapsulation", async () => {
|
|
|
565
537
|
lengths.push(length);
|
|
566
538
|
}
|
|
567
539
|
|
|
568
|
-
DicomMessage.
|
|
540
|
+
DicomMessage._readTag(stream, mainSyntax);
|
|
569
541
|
}
|
|
570
542
|
|
|
571
543
|
// then
|
package/test/untilTag.test.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import dcmjs from "../src/index.js";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
|
|
4
|
-
it("test_untilTag", () => {
|
|
5
|
-
const buffer = fs.readFileSync("test/sample-dicom.dcm");
|
|
6
|
-
|
|
7
|
-
const { DicomMessage, DicomMetaDictionary } = dcmjs.data;
|
|
8
|
-
|
|
9
|
-
console.time("readFile");
|
|
10
|
-
const fullData = DicomMessage.readFile(buffer.buffer);
|
|
11
|
-
console.timeEnd("readFile");
|
|
12
|
-
|
|
13
|
-
console.time("readFile without untilTag");
|
|
14
|
-
const dicomData = DicomMessage.readFile(buffer.buffer, {
|
|
15
|
-
untilTag: "7FE00010",
|
|
16
|
-
includeUntilTagValue: false
|
|
17
|
-
});
|
|
18
|
-
console.timeEnd("readFile without untilTag");
|
|
19
|
-
|
|
20
|
-
console.time("readFile with untilTag");
|
|
21
|
-
const dicomData2 = DicomMessage.readFile(buffer.buffer, {
|
|
22
|
-
untilTag: "7FE00010",
|
|
23
|
-
includeUntilTagValue: true
|
|
24
|
-
});
|
|
25
|
-
console.timeEnd("readFile with untilTag");
|
|
26
|
-
|
|
27
|
-
const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
|
|
28
|
-
full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
|
|
29
|
-
|
|
30
|
-
// console.log(full_dataset.PixelData);
|
|
31
|
-
|
|
32
|
-
const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
|
33
|
-
dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
|
34
|
-
|
|
35
|
-
// console.log(dataset.PixelData);
|
|
36
|
-
|
|
37
|
-
const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
|
|
38
|
-
dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
|
|
39
|
-
|
|
40
|
-
// console.log(dataset2.PixelData);
|
|
41
|
-
|
|
42
|
-
expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
|
|
43
|
-
expect(dataset.PixelData).toEqual(0);
|
|
44
|
-
});
|