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.
Files changed (55) hide show
  1. package/README.md +50 -0
  2. package/build/dcmjs.es.js +1071 -112
  3. package/build/dcmjs.es.js.map +1 -1
  4. package/build/dcmjs.js +1071 -112
  5. package/build/dcmjs.js.map +1 -1
  6. package/build/dcmjs.min.js +2 -2
  7. package/build/dcmjs.min.js.map +1 -1
  8. package/generate/dictionary.mjs +56029 -0
  9. package/package.json +18 -2
  10. package/.babelrc +0 -9
  11. package/.github/workflows/lint-and-format.yml +0 -27
  12. package/.github/workflows/publish-package.yml +0 -45
  13. package/.github/workflows/tests.yml +0 -24
  14. package/.prettierrc +0 -5
  15. package/.vscode/extensions.json +0 -7
  16. package/.vscode/settings.json +0 -8
  17. package/changelog.md +0 -31
  18. package/docs/ArrayBufferExpanderListener.md +0 -303
  19. package/docs/AsyncDicomReader-skill.md +0 -730
  20. package/eslint.config.mjs +0 -30
  21. package/generate-dictionary.js +0 -145
  22. package/jest.setup.js +0 -39
  23. package/netlify.toml +0 -22
  24. package/rollup.config.mjs +0 -57
  25. package/test/ArrayBufferExpanderListener.test.js +0 -365
  26. package/test/DICOMWEB.test.js +0 -1
  27. package/test/DicomMetaDictionary.test.js +0 -73
  28. package/test/SequenceOfItems.test.js +0 -86
  29. package/test/adapters.test.js +0 -43
  30. package/test/anonymizer.test.js +0 -176
  31. package/test/arrayItem.json +0 -351
  32. package/test/async-data.test.js +0 -575
  33. package/test/data-encoding.test.js +0 -59
  34. package/test/data-options.test.js +0 -199
  35. package/test/data.test.js +0 -1776
  36. package/test/derivations.test.js +0 -1
  37. package/test/helper/DicomDataReadBufferStreamBuilder.js +0 -89
  38. package/test/information-filter.test.js +0 -165
  39. package/test/integration/DicomMessage.readFile.test.js +0 -50
  40. package/test/lossless-read-write.test.js +0 -1407
  41. package/test/mocks/minimal_fields_dataset.json +0 -17
  42. package/test/mocks/null_number_vrs_dataset.json +0 -102
  43. package/test/normalizers.test.js +0 -38
  44. package/test/odd-frame-bit-data.js +0 -138
  45. package/test/rawTags.js +0 -170
  46. package/test/readBufferStream.test.js +0 -158
  47. package/test/sample-dicom.json +0 -904
  48. package/test/sample-op.lei +0 -0
  49. package/test/sample-sr.json +0 -997
  50. package/test/sr-tid.test.js +0 -251
  51. package/test/testUtils.js +0 -85
  52. package/test/utilities/deepEqual.test.js +0 -87
  53. package/test/utilities.test.js +0 -205
  54. package/test/video-test-dict.js +0 -40
  55. package/test/writeBufferStream.test.js +0 -149
@@ -1 +0,0 @@
1
- it("No tests yet", () => {});
@@ -1,89 +0,0 @@
1
- import { ReadBufferStream } from "../../src/BufferStream";
2
- import {
3
- ITEM_DELIMITATION_LENGTH,
4
- SEQUENCE_DELIMITATION_VALUE,
5
- UNDEFINED_LENGTH
6
- } from "../../src/constants/dicom";
7
- import { DicomMetaDictionary } from "../../src/DicomMetaDictionary";
8
-
9
- export class DicomDataReadBufferStreamBuilder {
10
- constructor() {
11
- this.itemArray = [];
12
- this.options = {
13
- ignoreErrors: false,
14
- untilTag: null,
15
- includeUntilTagValue: false,
16
- noCopy: false
17
- };
18
- }
19
-
20
- addSequenceDelimitationTagAndValue() {
21
- this.splitIntoFourTwoByteItemsAndAddToDataArray(
22
- DicomMetaDictionary.tagAsIntegerFromName("SequenceDelimitationItem")
23
- );
24
- this.splitIntoFourTwoByteItemsAndAddToDataArray(
25
- SEQUENCE_DELIMITATION_VALUE
26
- );
27
- }
28
-
29
- addUndefinedLengthItem() {
30
- this.splitIntoFourTwoByteItemsAndAddToDataArray(
31
- DicomMetaDictionary.tagAsIntegerFromName("Item")
32
- );
33
- this.splitIntoFourTwoByteItemsAndAddToDataArray(UNDEFINED_LENGTH);
34
- }
35
-
36
- addUndefinedLengthItemDelimitation() {
37
- this.splitIntoFourTwoByteItemsAndAddToDataArray(
38
- DicomMetaDictionary.tagAsIntegerFromName("ItemDelimitationItem")
39
- );
40
- this.splitIntoFourTwoByteItemsAndAddToDataArray(
41
- ITEM_DELIMITATION_LENGTH
42
- );
43
- }
44
-
45
- /**
46
- * Converts a 8 byte hexadecimal value into a 4 * 2 byte String values array.
47
- * (0xfffee00d -> ['0xff', '0xfe', '0xe0', 0x0d'])
48
- */
49
- splitIntoFourTwoByteItemsAndAddToDataArray(hexValue) {
50
- let hexValueItemArray = [];
51
-
52
- for (
53
- let index = 0;
54
- index < hexValue.toString(16).length;
55
- index = index + 2
56
- ) {
57
- hexValueItemArray.push(
58
- "0x" + hexValue.toString(16).slice(index, index + 2)
59
- );
60
- }
61
-
62
- // ensure 4 items in the array
63
- while (hexValueItemArray.length < 4) {
64
- hexValueItemArray = ["0x00"].concat(hexValueItemArray);
65
- }
66
-
67
- this.itemArray = this.itemArray.concat(hexValueItemArray);
68
- }
69
-
70
- /**
71
- * Adds a "File Meta Information Group Length" tag (0002,0000) with the length 4 and the value 4 to the stream.
72
- */
73
- addUlExampleItem() {
74
- const fileMetaInfoGroupLengthTag = ["0x02", "0x00", "0x00", "0x00"];
75
- const length = ["0x04", "0x00", "0x00", "0x00"];
76
- const item = ["0x04", "0x00", "0x00", "0x00"];
77
-
78
- this.itemArray = this.itemArray.concat(fileMetaInfoGroupLengthTag);
79
- this.itemArray = this.itemArray.concat(length);
80
- this.itemArray = this.itemArray.concat(item);
81
- }
82
-
83
- build() {
84
- const byteArray = new Uint8Array(this.itemArray);
85
- return new ReadBufferStream(byteArray.buffer, null, {
86
- noCopy: this.options.noCopy
87
- });
88
- }
89
- }
@@ -1,165 +0,0 @@
1
- import fs from "fs";
2
- import { AsyncDicomReader } from "../src/AsyncDicomReader";
3
- import {
4
- DicomMetadataListener,
5
- createInformationFilter
6
- } from "../src/utilities/DicomMetadataListener";
7
- import { TagHex } from "../src/constants/dicom";
8
-
9
- describe("Information Filter", () => {
10
- test("listener.information is populated with default tags", async () => {
11
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
12
- const reader = new AsyncDicomReader();
13
- const listener = new DicomMetadataListener();
14
-
15
- reader.stream.addBuffer(buffer);
16
- reader.stream.setComplete();
17
-
18
- await reader.readFile({ listener });
19
-
20
- // Verify that information object exists
21
- expect(listener.information).toBeDefined();
22
-
23
- // Verify that tracked tags are present in information
24
- expect(listener.information.rows).toBe(512);
25
- expect(listener.information.columns).toBe(512);
26
-
27
- // Check that UIDs are populated if available in the test file
28
- if (listener.information.studyInstanceUid) {
29
- expect(typeof listener.information.studyInstanceUid).toBe("string");
30
- }
31
- if (listener.information.seriesInstanceUid) {
32
- expect(typeof listener.information.seriesInstanceUid).toBe(
33
- "string"
34
- );
35
- }
36
- if (listener.information.sopInstanceUid) {
37
- expect(typeof listener.information.sopInstanceUid).toBe("string");
38
- }
39
- });
40
-
41
- test("listener.information can be accessed for pixel data processing", async () => {
42
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
43
- const reader = new AsyncDicomReader();
44
- const listener = new DicomMetadataListener();
45
-
46
- reader.stream.addBuffer(buffer);
47
- reader.stream.setComplete();
48
-
49
- const { dict } = await reader.readFile({ listener });
50
-
51
- // Verify that pixel data was read correctly using information
52
- expect(dict[TagHex.PixelData]).toBeDefined();
53
- expect(dict[TagHex.PixelData].Value[0]).toBeDefined();
54
-
55
- // Verify information was used correctly (no errors during reading)
56
- expect(listener.information.rows).toBe(512);
57
- expect(listener.information.columns).toBe(512);
58
- expect(listener.information.bitsAllocated).toBe(16);
59
- expect(listener.information.samplesPerPixel).toBe(1);
60
- });
61
-
62
- test("custom information tags can be specified", async () => {
63
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
64
- const reader = new AsyncDicomReader();
65
-
66
- // Only track specific tags
67
- const customTags = new Set([TagHex.Rows, TagHex.Columns]);
68
- const listener = new DicomMetadataListener({
69
- informationTags: customTags
70
- });
71
-
72
- reader.stream.addBuffer(buffer);
73
- reader.stream.setComplete();
74
-
75
- await reader.readFile({ listener });
76
-
77
- // Verify that only tracked tags are present
78
- expect(listener.information.rows).toBe(512);
79
- expect(listener.information.columns).toBe(512);
80
-
81
- // Other default tags should not be tracked
82
- expect(listener.information.bitsAllocated).toBeUndefined();
83
- expect(listener.information.samplesPerPixel).toBeUndefined();
84
- });
85
-
86
- test("information contains normalized camelCase names", async () => {
87
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
88
- const reader = new AsyncDicomReader();
89
- const listener = new DicomMetadataListener();
90
-
91
- reader.stream.addBuffer(buffer);
92
- reader.stream.setComplete();
93
-
94
- await reader.readFile({ listener });
95
-
96
- // Verify normalized naming (lower camel case)
97
- expect(listener.information).toHaveProperty("rows");
98
- expect(listener.information).toHaveProperty("columns");
99
- expect(listener.information).toHaveProperty("samplesPerPixel");
100
- expect(listener.information).toHaveProperty("bitsAllocated");
101
-
102
- // Verify UID becomes Uid (not UID)
103
- if (listener.information.studyInstanceUid !== undefined) {
104
- expect(listener.information).toHaveProperty("studyInstanceUid");
105
- }
106
- });
107
-
108
- test("multiframe data uses information for frame processing", async () => {
109
- const url =
110
- "https://github.com/dcmjs-org/data/releases/download/binary-parsing-stressors/multiframe-ultrasound.dcm";
111
- const dcmPath = await import("./testUtils.js").then(m =>
112
- m.getTestDataset(url, "multiframe-ultrasound.dcm")
113
- );
114
-
115
- const reader = new AsyncDicomReader();
116
- const listener = new DicomMetadataListener();
117
-
118
- const stream = fs.createReadStream(dcmPath, {
119
- highWaterMark: 4001
120
- });
121
- reader.stream.fromAsyncStream(stream);
122
-
123
- const { dict } = await reader.readFile({ listener });
124
-
125
- // Verify information was populated
126
- expect(listener.information.numberOfFrames).toBe(29);
127
-
128
- // Verify frames were read correctly
129
- const frames = dict[TagHex.PixelData].Value;
130
- expect(frames.length).toBe(29);
131
- });
132
-
133
- test("custom informationFilter can be passed to listener", async () => {
134
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
135
- const reader = new AsyncDicomReader();
136
-
137
- // Create a custom information object to track the filter was used
138
- const customInformation = {};
139
- const customFilter = createInformationFilter();
140
-
141
- // Pass the custom filter via options
142
- const listener = new DicomMetadataListener({
143
- information: customInformation,
144
- informationFilter: customFilter
145
- });
146
-
147
- reader.stream.addBuffer(buffer);
148
- reader.stream.setComplete();
149
-
150
- const { meta } = await reader.readFile({ listener });
151
-
152
- // Verify that the custom information object was populated
153
- expect(listener.information).toBe(customInformation);
154
- expect(listener.information).toBeDefined();
155
-
156
- // Verify rows and columns are accessible
157
- expect(listener.information.rows).toBe(512);
158
- expect(listener.information.columns).toBe(512);
159
-
160
- // Verify transfer syntax UID is accessible from meta
161
- expect(meta[TagHex.TransferSyntaxUID].Value[0]).toBe(
162
- "1.2.840.10008.1.2"
163
- );
164
- });
165
- });
@@ -1,50 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import dcmjs from "../../src/index.js";
4
- import { validationLog } from "./../../src/log.js";
5
-
6
- // Ignore validation errors
7
- validationLog.setLevel(5);
8
-
9
- const { DicomMessage } = dcmjs.data;
10
-
11
- describe("test parsing of sample-dicom.dcm file", () => {
12
- const dicomTestFilesDataPath = path.join(
13
- __dirname,
14
- "./../sample-dicom.dcm"
15
- );
16
-
17
- const arrayBuffer = fs.readFileSync(dicomTestFilesDataPath).buffer;
18
- const dicomDict = DicomMessage.readFile(arrayBuffer);
19
-
20
- it("has dict and meta section", () => {
21
- expect(dicomDict["dict"]).not.toBeNull();
22
- expect(dicomDict["meta"]).not.toBeNull();
23
- });
24
-
25
- describe("test some tags from the dict section", () => {
26
- const dictTags = dicomDict["dict"];
27
-
28
- it("has the StudyDate", () => {
29
- expect(dictTags).toHaveProperty("00080020.Value[0]", "20010101");
30
- });
31
- // testing nested sequence parsing
32
- it("has the RequestAttributesSequence -> ScheduledProtocolCodeSequence -> CodeValue", () => {
33
- expect(dictTags).toHaveProperty(
34
- "00400275.Value[0].00400008.Value[0].00080100.Value[0]",
35
- "6310"
36
- );
37
- });
38
- });
39
-
40
- describe("test some tags from the meta section", () => {
41
- const metaTags = dicomDict["meta"];
42
-
43
- it("has the TransferSyntaxUID", () => {
44
- expect(metaTags).toHaveProperty(
45
- "00020010.Value[0]",
46
- "1.2.840.10008.1.2"
47
- );
48
- });
49
- });
50
- });