dcmjs 0.49.3 → 0.50.0
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 +50 -0
- package/build/dcmjs.es.js +1071 -112
- package/build/dcmjs.es.js.map +1 -1
- package/build/dcmjs.js +1071 -112
- package/build/dcmjs.js.map +1 -1
- package/build/dcmjs.min.js +2 -2
- package/build/dcmjs.min.js.map +1 -1
- package/generate/dictionary.mjs +56029 -0
- package/package.json +18 -2
- package/.babelrc +0 -9
- package/.github/workflows/lint-and-format.yml +0 -27
- package/.github/workflows/publish-package.yml +0 -45
- package/.github/workflows/tests.yml +0 -24
- package/.prettierrc +0 -5
- package/.vscode/extensions.json +0 -7
- package/.vscode/settings.json +0 -8
- package/changelog.md +0 -31
- package/docs/ArrayBufferExpanderListener.md +0 -303
- package/docs/AsyncDicomReader-skill.md +0 -730
- package/eslint.config.mjs +0 -30
- package/generate-dictionary.js +0 -145
- package/jest.setup.js +0 -39
- package/netlify.toml +0 -22
- package/rollup.config.mjs +0 -57
- package/test/ArrayBufferExpanderListener.test.js +0 -365
- package/test/DICOMWEB.test.js +0 -1
- package/test/DicomMetaDictionary.test.js +0 -73
- package/test/SequenceOfItems.test.js +0 -86
- package/test/adapters.test.js +0 -43
- package/test/anonymizer.test.js +0 -176
- package/test/arrayItem.json +0 -351
- package/test/async-data.test.js +0 -575
- package/test/data-encoding.test.js +0 -59
- package/test/data-options.test.js +0 -199
- package/test/data.test.js +0 -1776
- package/test/derivations.test.js +0 -1
- package/test/helper/DicomDataReadBufferStreamBuilder.js +0 -89
- package/test/information-filter.test.js +0 -165
- package/test/integration/DicomMessage.readFile.test.js +0 -50
- package/test/lossless-read-write.test.js +0 -1407
- package/test/mocks/minimal_fields_dataset.json +0 -17
- package/test/mocks/null_number_vrs_dataset.json +0 -102
- package/test/normalizers.test.js +0 -38
- package/test/odd-frame-bit-data.js +0 -138
- package/test/rawTags.js +0 -170
- package/test/readBufferStream.test.js +0 -158
- package/test/sample-dicom.json +0 -904
- package/test/sample-op.lei +0 -0
- package/test/sample-sr.json +0 -997
- package/test/sr-tid.test.js +0 -251
- package/test/testUtils.js +0 -85
- package/test/utilities/deepEqual.test.js +0 -87
- package/test/utilities.test.js +0 -205
- package/test/video-test-dict.js +0 -40
- package/test/writeBufferStream.test.js +0 -149
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { DicomMetaDictionary } from "../src/DicomMetaDictionary";
|
|
2
|
-
|
|
3
|
-
describe("DicomMetaDictionary", () => {
|
|
4
|
-
describe("static methods", () => {
|
|
5
|
-
describe("unpunctuateTag", () => {
|
|
6
|
-
it("returns the unpunctuated tag String", () => {
|
|
7
|
-
const originalTag = "(0000,0003)";
|
|
8
|
-
const unpunctuatedTag = "00000003";
|
|
9
|
-
|
|
10
|
-
expect(DicomMetaDictionary.unpunctuateTag(originalTag)).toMatch(
|
|
11
|
-
unpunctuatedTag
|
|
12
|
-
);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
describe("parseIntFromTag", () => {
|
|
17
|
-
it("returns the correct Integer of a simple Integer", () => {
|
|
18
|
-
const originalTag = "(0000,0003)";
|
|
19
|
-
const integerValue = 3;
|
|
20
|
-
|
|
21
|
-
expect(DicomMetaDictionary.parseIntFromTag(originalTag)).toBe(
|
|
22
|
-
integerValue
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("returns the correct Integer of a simple hexadecimal String", () => {
|
|
27
|
-
const originalTag = "(0000,000F)";
|
|
28
|
-
const integerValue = 15;
|
|
29
|
-
|
|
30
|
-
expect(DicomMetaDictionary.parseIntFromTag(originalTag)).toBe(
|
|
31
|
-
integerValue
|
|
32
|
-
);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("returns the correct Integer of a complex hexadecimal String", () => {
|
|
36
|
-
const originalTag = "(000F,0000)";
|
|
37
|
-
const integerValue = 983040;
|
|
38
|
-
|
|
39
|
-
expect(DicomMetaDictionary.parseIntFromTag(originalTag)).toBe(
|
|
40
|
-
integerValue
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("returns NaN if String can not be parsed", () => {
|
|
45
|
-
const originalTag = "()";
|
|
46
|
-
|
|
47
|
-
expect(DicomMetaDictionary.parseIntFromTag(originalTag)).toBe(
|
|
48
|
-
NaN
|
|
49
|
-
);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe("tagAsIntegerFromName", () => {
|
|
54
|
-
it("returns undefined if name has no item in dictionary", () => {
|
|
55
|
-
const tagName = "dummy";
|
|
56
|
-
|
|
57
|
-
expect(DicomMetaDictionary.tagAsIntegerFromName(tagName)).toBe(
|
|
58
|
-
undefined
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe("tagAsIntegerFromName", () => {
|
|
63
|
-
it("returns the tag as integer value", () => {
|
|
64
|
-
const tagName = "AffectedSOPClassUID";
|
|
65
|
-
|
|
66
|
-
expect(
|
|
67
|
-
DicomMetaDictionary.tagAsIntegerFromName(tagName)
|
|
68
|
-
).toBe(2);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
});
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IMPLICIT_LITTLE_ENDIAN,
|
|
3
|
-
UNDEFINED_LENGTH
|
|
4
|
-
} from "../src/constants/dicom";
|
|
5
|
-
import "../src/index.js";
|
|
6
|
-
import { ValueRepresentation } from "../src/ValueRepresentation";
|
|
7
|
-
import { DicomMessage } from "../src/DicomMessage";
|
|
8
|
-
import { DicomDataReadBufferStreamBuilder } from "./helper/DicomDataReadBufferStreamBuilder";
|
|
9
|
-
|
|
10
|
-
ValueRepresentation.setDicomMessageClass(DicomMessage);
|
|
11
|
-
|
|
12
|
-
describe("SequenceOfItems extends ValueRepresentation", () => {
|
|
13
|
-
const sequenceOfItems = ValueRepresentation.createByTypeString("SQ");
|
|
14
|
-
|
|
15
|
-
describe("zero length tests", () => {
|
|
16
|
-
it("returns an empty elements array", () => {
|
|
17
|
-
const syntax = IMPLICIT_LITTLE_ENDIAN;
|
|
18
|
-
const sqLength = 0x0;
|
|
19
|
-
const streamBuilder = new DicomDataReadBufferStreamBuilder();
|
|
20
|
-
const stream = streamBuilder.build();
|
|
21
|
-
|
|
22
|
-
const elements = sequenceOfItems.readBytes(
|
|
23
|
-
stream,
|
|
24
|
-
sqLength,
|
|
25
|
-
syntax
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
expect(elements.length).toBe(0);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe("undefined length tests", () => {
|
|
33
|
-
const sqLength = UNDEFINED_LENGTH;
|
|
34
|
-
it("returns an empty elements array", () => {
|
|
35
|
-
const syntax = IMPLICIT_LITTLE_ENDIAN;
|
|
36
|
-
const streamBuilder = new DicomDataReadBufferStreamBuilder();
|
|
37
|
-
streamBuilder.addSequenceDelimitationTagAndValue();
|
|
38
|
-
const stream = streamBuilder.build();
|
|
39
|
-
|
|
40
|
-
const elements = sequenceOfItems.readBytes(
|
|
41
|
-
stream,
|
|
42
|
-
sqLength,
|
|
43
|
-
syntax
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
expect(elements.length).toBe(0);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("returns an empty elements array sinnce the item is empty", () => {
|
|
50
|
-
const syntax = IMPLICIT_LITTLE_ENDIAN;
|
|
51
|
-
const streamBuilder = new DicomDataReadBufferStreamBuilder();
|
|
52
|
-
streamBuilder.addUndefinedLengthItem();
|
|
53
|
-
streamBuilder.addUndefinedLengthItemDelimitation();
|
|
54
|
-
streamBuilder.addSequenceDelimitationTagAndValue();
|
|
55
|
-
const stream = streamBuilder.build();
|
|
56
|
-
|
|
57
|
-
const elements = sequenceOfItems.readBytes(
|
|
58
|
-
stream,
|
|
59
|
-
sqLength,
|
|
60
|
-
syntax
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
expect(elements.length).toBe(0);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("returns an elements array with one item", () => {
|
|
67
|
-
const syntax = IMPLICIT_LITTLE_ENDIAN;
|
|
68
|
-
const streamBuilder = new DicomDataReadBufferStreamBuilder();
|
|
69
|
-
streamBuilder.addUndefinedLengthItem();
|
|
70
|
-
streamBuilder.addUlExampleItem();
|
|
71
|
-
streamBuilder.addUndefinedLengthItemDelimitation();
|
|
72
|
-
streamBuilder.addSequenceDelimitationTagAndValue();
|
|
73
|
-
const stream = streamBuilder.build();
|
|
74
|
-
|
|
75
|
-
const elements = sequenceOfItems.readBytes(
|
|
76
|
-
stream,
|
|
77
|
-
sqLength,
|
|
78
|
-
syntax
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
expect(elements.length).toBe(1);
|
|
82
|
-
expect(elements[0]["00020000"].vr).toBe("UL");
|
|
83
|
-
expect(elements[0]["00020000"].Value[0]).toBe(4);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
});
|
package/test/adapters.test.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import "../src/index.js";
|
|
3
|
-
import Segmentation_4X from "../src/adapters/Cornerstone/Segmentation_4X";
|
|
4
|
-
import { getTestDataset } from "./testUtils.js";
|
|
5
|
-
|
|
6
|
-
const mockMetadataProvider = {
|
|
7
|
-
get: (type, imageId) => {
|
|
8
|
-
// Unlike CT, is missing coordinate system such as frameOfReferenceUID or rowCosines attributes
|
|
9
|
-
if (imageId === "mg://1") {
|
|
10
|
-
return {
|
|
11
|
-
seriesInstanceUID:
|
|
12
|
-
"1.2.840.113681.167838594.1562401072.4432.2070.71100000",
|
|
13
|
-
rows: 3328,
|
|
14
|
-
columns: 2560,
|
|
15
|
-
pixelSpacing: [0.065238, 0.065238],
|
|
16
|
-
rowPixelSpacing: 0.065238,
|
|
17
|
-
columnPixelSpacing: 0.065238,
|
|
18
|
-
columnCosines: null,
|
|
19
|
-
frameOfReferenceUID: undefined,
|
|
20
|
-
imageOrientationPatient: undefined,
|
|
21
|
-
imagePositionPatient: undefined,
|
|
22
|
-
rowCosines: null,
|
|
23
|
-
sliceLocation: undefined,
|
|
24
|
-
sliceThickness: undefined
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
it("Can generate tool state (4X) with SEG sourcing MG images without throwing any errors", async () => {
|
|
31
|
-
const url =
|
|
32
|
-
"https://github.com/dcmjs-org/data/releases/download/mg-seg/seg-test-SEG.dcm";
|
|
33
|
-
const dcmPath = await getTestDataset(url, "seg-test-SEG.dcm");
|
|
34
|
-
const arrayBuffer = fs.readFileSync(dcmPath).buffer;
|
|
35
|
-
|
|
36
|
-
expect(() => {
|
|
37
|
-
Segmentation_4X.generateToolState(
|
|
38
|
-
["mg://1"],
|
|
39
|
-
arrayBuffer,
|
|
40
|
-
mockMetadataProvider
|
|
41
|
-
);
|
|
42
|
-
}).not.toThrowError();
|
|
43
|
-
});
|
package/test/anonymizer.test.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import dcmjs from "../src/index.js";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import { validationLog } from "./../src/log.js";
|
|
4
|
-
|
|
5
|
-
// Ignore validation errors
|
|
6
|
-
validationLog.setLevel(5);
|
|
7
|
-
|
|
8
|
-
const { DicomMessage } = dcmjs.data;
|
|
9
|
-
const { cleanTags, getTagsNameToEmpty } = dcmjs.anonymizer;
|
|
10
|
-
|
|
11
|
-
it("test_export", () => {
|
|
12
|
-
expect(typeof cleanTags).toEqual("function");
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("test_anonymization", () => {
|
|
16
|
-
// given
|
|
17
|
-
const arrayBuffer = fs.readFileSync("test/sample-dicom.dcm").buffer;
|
|
18
|
-
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
19
|
-
|
|
20
|
-
const tagInfo = dcmjs.data.DicomMetaDictionary.nameMap["PatientName"];
|
|
21
|
-
const tagNumber = tagInfo.tag,
|
|
22
|
-
tagString = dcmjs.data.Tag.fromPString(tagNumber).toCleanString();
|
|
23
|
-
|
|
24
|
-
const patientIDTag = dicomDict.dict[tagString];
|
|
25
|
-
const patientIDValue = patientIDTag.Value;
|
|
26
|
-
|
|
27
|
-
expect(JSON.stringify(patientIDValue)).toEqual(
|
|
28
|
-
JSON.stringify([{ Alphabetic: "Fall 3" }])
|
|
29
|
-
);
|
|
30
|
-
expect(patientIDValue.toString()).toEqual(["Fall 3"].toString());
|
|
31
|
-
|
|
32
|
-
// when
|
|
33
|
-
cleanTags(dicomDict.dict);
|
|
34
|
-
|
|
35
|
-
// then
|
|
36
|
-
expect(JSON.stringify(patientIDTag.Value)).toEqual(
|
|
37
|
-
JSON.stringify([{ Alphabetic: "ANON^PATIENT" }])
|
|
38
|
-
);
|
|
39
|
-
expect(patientIDTag.Value.toString()).toEqual(["ANON^PATIENT"].toString());
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("test_anonymization_no_change_ref", () => {
|
|
43
|
-
// given
|
|
44
|
-
const arrayBuffer = fs.readFileSync("test/sample-sr.dcm").buffer;
|
|
45
|
-
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
46
|
-
|
|
47
|
-
// multiple value name
|
|
48
|
-
const tagInfo = dcmjs.data.DicomMetaDictionary.nameMap["OtherPatientNames"];
|
|
49
|
-
const tagNumber = tagInfo.tag,
|
|
50
|
-
tagString = dcmjs.data.Tag.fromPString(tagNumber).toCleanString();
|
|
51
|
-
|
|
52
|
-
const otherPatientNamesIDTag = dicomDict.dict[tagString];
|
|
53
|
-
const otherPatientNamesIDValue = otherPatientNamesIDTag.Value;
|
|
54
|
-
const otherPatientNamesIDValueJSON = JSON.stringify(
|
|
55
|
-
otherPatientNamesIDValue
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
expect(JSON.stringify(otherPatientNamesIDValue)).toEqual(
|
|
59
|
-
JSON.stringify([
|
|
60
|
-
{
|
|
61
|
-
Alphabetic: "Doe^John",
|
|
62
|
-
Ideographic: "Johnny",
|
|
63
|
-
Phonetic: "Jonny"
|
|
64
|
-
},
|
|
65
|
-
{ Alphabetic: "Doe^Jane", Ideographic: "Janie", Phonetic: "Jayne" }
|
|
66
|
-
])
|
|
67
|
-
);
|
|
68
|
-
expect(otherPatientNamesIDValue.toString()).toEqual(
|
|
69
|
-
["Doe^John=Johnny=Jonny\\Doe^Jane=Janie=Jayne"].toString()
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
// when
|
|
73
|
-
cleanTags(dicomDict.dict, { "00101001": "ANON^PATIENT" });
|
|
74
|
-
|
|
75
|
-
// then
|
|
76
|
-
expect(JSON.stringify(otherPatientNamesIDTag.Value)).toEqual(
|
|
77
|
-
JSON.stringify([{ Alphabetic: "ANON^PATIENT" }])
|
|
78
|
-
);
|
|
79
|
-
expect(otherPatientNamesIDTag.Value.toString()).toEqual(
|
|
80
|
-
["ANON^PATIENT"].toString()
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
expect(JSON.stringify(otherPatientNamesIDValue)).toEqual(
|
|
84
|
-
otherPatientNamesIDValueJSON
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("test_anonymization_tagtoreplace_param", () => {
|
|
89
|
-
// given
|
|
90
|
-
const arrayBuffer = fs.readFileSync("test/sample-dicom.dcm").buffer;
|
|
91
|
-
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
92
|
-
|
|
93
|
-
const tagInfo = dcmjs.data.DicomMetaDictionary.nameMap["PatientName"];
|
|
94
|
-
const tagNumber = tagInfo.tag,
|
|
95
|
-
tagString = dcmjs.data.Tag.fromPString(tagNumber).toCleanString();
|
|
96
|
-
|
|
97
|
-
const patientNameTag = dicomDict.dict[tagString];
|
|
98
|
-
const patientNameValue = patientNameTag.Value;
|
|
99
|
-
|
|
100
|
-
expect(JSON.stringify(patientNameValue)).toEqual(
|
|
101
|
-
JSON.stringify([{ Alphabetic: "Fall 3" }])
|
|
102
|
-
);
|
|
103
|
-
expect(patientNameValue.toString()).toEqual(["Fall 3"].toString());
|
|
104
|
-
|
|
105
|
-
var tagsToReplace = {
|
|
106
|
-
"00100010": "REPLACE^PATIENT"
|
|
107
|
-
};
|
|
108
|
-
// when
|
|
109
|
-
cleanTags(dicomDict.dict, tagsToReplace);
|
|
110
|
-
|
|
111
|
-
// then
|
|
112
|
-
|
|
113
|
-
expect(JSON.stringify(patientNameTag.Value)).toEqual(
|
|
114
|
-
JSON.stringify([{ Alphabetic: "REPLACE^PATIENT" }])
|
|
115
|
-
);
|
|
116
|
-
expect(patientNameTag.Value.toString()).toEqual(
|
|
117
|
-
["REPLACE^PATIENT"].toString()
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("test_anonymization_keep_tag", () => {
|
|
122
|
-
// given
|
|
123
|
-
const arrayBuffer = fs.readFileSync("test/sample-dicom.dcm").buffer;
|
|
124
|
-
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
125
|
-
|
|
126
|
-
const tagInfo = dcmjs.data.DicomMetaDictionary.nameMap["SeriesDescription"];
|
|
127
|
-
const tagNumber = tagInfo.tag,
|
|
128
|
-
tagString = dcmjs.data.Tag.fromPString(tagNumber).toCleanString();
|
|
129
|
-
|
|
130
|
-
const seriesDescriptionTag = dicomDict.dict[tagString];
|
|
131
|
-
const seriesDescriptionValue = seriesDescriptionTag.Value;
|
|
132
|
-
|
|
133
|
-
expect(seriesDescriptionValue).toEqual(["Oberbauch *sSSH/FB/4mm"]);
|
|
134
|
-
|
|
135
|
-
var tagsToReplace = {};
|
|
136
|
-
var tagsToKeep = getTagsNameToEmpty();
|
|
137
|
-
var seriesDescription = "SeriesDescription";
|
|
138
|
-
if (tagsToKeep.indexOf(seriesDescription) != -1) {
|
|
139
|
-
tagsToKeep.splice(tagsToKeep.indexOf(seriesDescription), 1);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// when
|
|
143
|
-
cleanTags(dicomDict.dict, tagsToReplace, tagsToKeep);
|
|
144
|
-
|
|
145
|
-
// then
|
|
146
|
-
expect(seriesDescriptionTag.Value).toEqual(["Oberbauch *sSSH/FB/4mm"]);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("test_anonymization_anonymize_tag", () => {
|
|
150
|
-
// given
|
|
151
|
-
const arrayBuffer = fs.readFileSync("test/sample-dicom.dcm").buffer;
|
|
152
|
-
const dicomDict = DicomMessage.readFile(arrayBuffer);
|
|
153
|
-
|
|
154
|
-
const tagInfo = dcmjs.data.DicomMetaDictionary.nameMap["SeriesInstanceUID"];
|
|
155
|
-
const tagNumber = tagInfo.tag,
|
|
156
|
-
tagString = dcmjs.data.Tag.fromPString(tagNumber).toCleanString();
|
|
157
|
-
|
|
158
|
-
const SeriesInstanceUIDTag = dicomDict.dict[tagString];
|
|
159
|
-
const SeriesInstanceUIDValue = SeriesInstanceUIDTag.Value;
|
|
160
|
-
|
|
161
|
-
expect(SeriesInstanceUIDValue).toEqual([
|
|
162
|
-
"1.2.276.0.50.192168001092.11156604.14547392.303"
|
|
163
|
-
]);
|
|
164
|
-
|
|
165
|
-
var tagsToReplace = {};
|
|
166
|
-
var tagsToAnon = getTagsNameToEmpty();
|
|
167
|
-
if (!tagsToAnon.includes("SeriesInstanceUID")) {
|
|
168
|
-
tagsToAnon.push("SeriesInstanceUID");
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// when
|
|
172
|
-
cleanTags(dicomDict.dict, tagsToReplace, tagsToAnon);
|
|
173
|
-
|
|
174
|
-
// then
|
|
175
|
-
expect(SeriesInstanceUIDTag.Value).toEqual([]);
|
|
176
|
-
});
|