@radicalimaging/static-wado-creator 1.6.10 → 1.6.11
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/dist/index.js +84811 -54896
- package/lib/DeleteStudy.js +9 -14
- package/lib/RejectInstance.js +4 -15
- package/lib/StaticWado.js +92 -147
- package/lib/createMain.js +3 -3
- package/lib/createPart10.js +19 -23
- package/lib/createThumbnail.js +27 -45
- package/lib/deleteMain.js +2 -2
- package/lib/groupMain.js +2 -2
- package/lib/index.js +6 -6
- package/lib/indexMain.js +2 -2
- package/lib/instanceMain.js +2 -2
- package/lib/metadataMain.js +2 -2
- package/lib/mkdicomwebConfig.js +157 -165
- package/lib/model/TagLists.js +5 -17
- package/lib/model/uids.js +29 -29
- package/lib/operation/InstanceDeduplicate.js +14 -19
- package/lib/operation/ScanStudy.js +11 -18
- package/lib/operation/StudyData.js +87 -156
- package/lib/operation/ThumbnailService.js +29 -54
- package/lib/operation/adapter/decodeImage.js +2 -2
- package/lib/operation/adapter/getImageInfo.js +7 -8
- package/lib/operation/adapter/transcodeImage.js +95 -146
- package/lib/operation/extractImageFrames.js +13 -17
- package/lib/operation/getDataSet.js +9 -43
- package/lib/operation/getEncapsulatedImageFrame.js +7 -19
- package/lib/operation/getNumberOfFrames.js +2 -2
- package/lib/operation/getUncompressedImageFrame.js +2 -10
- package/lib/operation/getVR.js +5 -5
- package/lib/operation/getValue.js +42 -65
- package/lib/operation/validateMetadata.js +4 -4
- package/lib/program/index.js +2 -5
- package/lib/rejectMain.js +2 -2
- package/lib/serverMain.js +8 -14
- package/lib/util/IdCreator.js +8 -17
- package/lib/util/adaptProgramOpts.js +2 -2
- package/lib/util/compressionOptionParser.js +5 -14
- package/lib/util/resultsReport.ts +67 -68
- package/lib/writer/CompleteStudyWriter.js +24 -37
- package/lib/writer/DeduplicateWriter.js +7 -8
- package/lib/writer/ExpandUriPath.js +3 -5
- package/lib/writer/HashDataWriter.js +18 -18
- package/lib/writer/ImageFrameWriter.js +20 -33
- package/lib/writer/MultipartHeader.js +1 -1
- package/lib/writer/RawDicomWriter.js +12 -13
- package/lib/writer/ThumbnailWriter.js +2 -2
- package/lib/writer/VideoWriter.js +23 -34
- package/lib/writer/WriteMultipart.js +4 -6
- package/lib/writer/WriteStream.js +14 -20
- package/package.json +1 -1
- package/lib/writer/static-dicomweb.code-workspace +0 -8
|
@@ -1,46 +1,34 @@
|
|
|
1
|
-
const dicomParser = require(
|
|
1
|
+
const dicomParser = require('dicom-parser');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Function to deal with extracting an image frame from an encapsulated data set.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const getEncapsulatedImageFrame = (
|
|
8
|
-
dataSet
|
|
9
|
-
attr,
|
|
10
|
-
frameIndex,
|
|
11
|
-
framesAreFragmented,
|
|
12
|
-
) => {
|
|
13
|
-
if (
|
|
14
|
-
dataSet.elements.x7fe00010 &&
|
|
15
|
-
dataSet.elements.x7fe00010.basicOffsetTable.length
|
|
16
|
-
) {
|
|
7
|
+
const getEncapsulatedImageFrame = (dataSet, attr, frameIndex, framesAreFragmented) => {
|
|
8
|
+
if (dataSet.elements.x7fe00010 && dataSet.elements.x7fe00010.basicOffsetTable.length) {
|
|
17
9
|
// Basic Offset Table is not empty
|
|
18
|
-
return dicomParser.readEncapsulatedImageFrame(
|
|
19
|
-
dataSet,
|
|
20
|
-
dataSet.elements.x7fe00010,
|
|
21
|
-
frameIndex,
|
|
22
|
-
);
|
|
10
|
+
return dicomParser.readEncapsulatedImageFrame(dataSet, dataSet.elements.x7fe00010, frameIndex);
|
|
23
11
|
}
|
|
24
12
|
|
|
25
13
|
// Empty basic offset table
|
|
26
14
|
if (framesAreFragmented) {
|
|
27
15
|
const basicOffsetTable = dicomParser.createJPEGBasicOffsetTable(
|
|
28
16
|
dataSet,
|
|
29
|
-
dataSet.elements.x7fe00010
|
|
17
|
+
dataSet.elements.x7fe00010
|
|
30
18
|
);
|
|
31
19
|
|
|
32
20
|
return dicomParser.readEncapsulatedImageFrame(
|
|
33
21
|
dataSet,
|
|
34
22
|
dataSet.elements.x7fe00010,
|
|
35
23
|
frameIndex,
|
|
36
|
-
basicOffsetTable
|
|
24
|
+
basicOffsetTable
|
|
37
25
|
);
|
|
38
26
|
}
|
|
39
27
|
|
|
40
28
|
return dicomParser.readEncapsulatedPixelDataFromFragments(
|
|
41
29
|
dataSet,
|
|
42
30
|
dataSet.elements.x7fe00010,
|
|
43
|
-
frameIndex
|
|
31
|
+
frameIndex
|
|
44
32
|
);
|
|
45
33
|
};
|
|
46
34
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const getNumberOfFrames =
|
|
1
|
+
const getNumberOfFrames = dataSet => {
|
|
2
2
|
if (dataSet.elements.x00280008) {
|
|
3
|
-
const numberOfFramesString = dataSet.string(
|
|
3
|
+
const numberOfFramesString = dataSet.string('x00280008');
|
|
4
4
|
if (numberOfFramesString.length === 0) {
|
|
5
5
|
return 1;
|
|
6
6
|
}
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
function getUncompressedImageFrame(
|
|
2
|
-
dataSet,
|
|
3
|
-
attr,
|
|
4
|
-
frame,
|
|
5
|
-
uncompressedFrameSize,
|
|
6
|
-
) {
|
|
1
|
+
function getUncompressedImageFrame(dataSet, attr, frame, uncompressedFrameSize) {
|
|
7
2
|
const start = attr.dataOffset + frame * uncompressedFrameSize;
|
|
8
|
-
const binaryValue = dataSet.byteArray.slice(
|
|
9
|
-
start,
|
|
10
|
-
start + uncompressedFrameSize,
|
|
11
|
-
);
|
|
3
|
+
const binaryValue = dataSet.byteArray.slice(start, start + uncompressedFrameSize);
|
|
12
4
|
return binaryValue;
|
|
13
5
|
}
|
|
14
6
|
|
package/lib/operation/getVR.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const { dataDictionary } = require(
|
|
1
|
+
const { dataDictionary } = require('@radicalimaging/static-wado-util');
|
|
2
2
|
|
|
3
3
|
const nullVrTags = new Set();
|
|
4
|
-
nullVrTags.add(
|
|
4
|
+
nullVrTags.add('FFFEE00D');
|
|
5
5
|
|
|
6
|
-
const getVR =
|
|
6
|
+
const getVR = attr => {
|
|
7
7
|
if (attr.vr) {
|
|
8
8
|
return attr.vr;
|
|
9
9
|
}
|
|
@@ -17,8 +17,8 @@ const getVR = (attr) => {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
console.log(
|
|
21
|
-
return
|
|
20
|
+
console.log('Unknown VR', tag, attr, dataDictAttr);
|
|
21
|
+
return 'UN';
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
module.exports = getVR;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const extractImageFrames = require(
|
|
1
|
+
const extractImageFrames = require('./extractImageFrames');
|
|
2
2
|
|
|
3
3
|
function decodeUtf8(s, options) {
|
|
4
|
-
if (options?.SpecificCharacterSet ===
|
|
4
|
+
if (options?.SpecificCharacterSet === 'ISO_IR 192') {
|
|
5
5
|
return decodeURIComponent(escape(s));
|
|
6
6
|
}
|
|
7
7
|
return s;
|
|
@@ -22,19 +22,14 @@ const getStrings = (dataSet, attr, options) => {
|
|
|
22
22
|
|
|
23
23
|
const getValuePatientName = (dataSet, attr) => {
|
|
24
24
|
const strings = getStrings(dataSet, attr);
|
|
25
|
-
return (
|
|
26
|
-
(strings && strings.map((item) => ({ Alphabetic: item }))) || undefined
|
|
27
|
-
);
|
|
25
|
+
return (strings && strings.map(item => ({ Alphabetic: item }))) || undefined;
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
/** Gets either InlineBinary or BulkDataURI, if already defined */
|
|
31
29
|
const getValueInlineBinary = (dataSet, attr) => {
|
|
32
30
|
if (attr.BulkDataURI) return { BulkDataURI: attr.BulkDataURI };
|
|
33
|
-
const binaryValue = dataSet.byteArray.slice(
|
|
34
|
-
|
|
35
|
-
attr.dataOffset + attr.length,
|
|
36
|
-
);
|
|
37
|
-
return { InlineBinary: binaryValue.toString("base64") };
|
|
31
|
+
const binaryValue = dataSet.byteArray.slice(attr.dataOffset, attr.dataOffset + attr.length);
|
|
32
|
+
return { InlineBinary: binaryValue.toString('base64') };
|
|
38
33
|
};
|
|
39
34
|
|
|
40
35
|
const getValueInlineSignedShort = (dataSet, attr) => {
|
|
@@ -79,10 +74,10 @@ const getValueInlineFloat = (dataSet, attr) => {
|
|
|
79
74
|
};
|
|
80
75
|
|
|
81
76
|
const getValueInlineIntString = (dataSet, attr) =>
|
|
82
|
-
getStrings(dataSet, attr).map(
|
|
77
|
+
getStrings(dataSet, attr).map(val => parseInt(val));
|
|
83
78
|
|
|
84
79
|
const getValueInlineFloatString = (dataSet, attr) =>
|
|
85
|
-
getStrings(dataSet, attr).map(
|
|
80
|
+
getStrings(dataSet, attr).map(val => parseFloat(val));
|
|
86
81
|
|
|
87
82
|
const getValueInlineFloatDouble = (dataSet, attr) => {
|
|
88
83
|
if (attr.length > 8) {
|
|
@@ -105,63 +100,63 @@ const getValueInline = (dataSet, attr, vr, options) => {
|
|
|
105
100
|
}
|
|
106
101
|
|
|
107
102
|
switch (vr) {
|
|
108
|
-
case
|
|
109
|
-
case
|
|
103
|
+
case 'AE':
|
|
104
|
+
case 'AS':
|
|
110
105
|
return getValueInlineString(dataSet, attr, options);
|
|
111
|
-
case
|
|
106
|
+
case 'AT':
|
|
112
107
|
return getValueInlineAttributeTag(dataSet, attr);
|
|
113
|
-
case
|
|
108
|
+
case 'DS':
|
|
114
109
|
return getValueInlineFloatString(dataSet, attr);
|
|
115
|
-
case
|
|
116
|
-
case
|
|
117
|
-
case
|
|
110
|
+
case 'CS':
|
|
111
|
+
case 'DA':
|
|
112
|
+
case 'DT':
|
|
118
113
|
return getValueInlineString(dataSet, attr, options);
|
|
119
|
-
case
|
|
114
|
+
case 'FL':
|
|
120
115
|
return getValueInlineFloat(dataSet, attr);
|
|
121
|
-
case
|
|
116
|
+
case 'FD':
|
|
122
117
|
return getValueInlineFloatDouble(dataSet, attr);
|
|
123
|
-
case
|
|
118
|
+
case 'IS':
|
|
124
119
|
return getValueInlineIntString(dataSet, attr);
|
|
125
|
-
case
|
|
126
|
-
case
|
|
120
|
+
case 'LO':
|
|
121
|
+
case 'LT':
|
|
127
122
|
return getValueInlineString(dataSet, attr, options);
|
|
128
|
-
case
|
|
129
|
-
case
|
|
130
|
-
case
|
|
123
|
+
case 'OB':
|
|
124
|
+
case 'OF':
|
|
125
|
+
case 'OW':
|
|
131
126
|
return getValueInlineBinary(dataSet, attr);
|
|
132
|
-
case
|
|
127
|
+
case 'PN':
|
|
133
128
|
return getValuePatientName(dataSet, attr);
|
|
134
|
-
case
|
|
129
|
+
case 'SH':
|
|
135
130
|
return getValueInlineString(dataSet, attr, options);
|
|
136
|
-
case
|
|
131
|
+
case 'SL':
|
|
137
132
|
return getValueInlineSignedLong(dataSet, attr);
|
|
138
|
-
case
|
|
133
|
+
case 'SS':
|
|
139
134
|
return getValueInlineSignedShort(dataSet, attr);
|
|
140
|
-
case
|
|
141
|
-
case
|
|
142
|
-
case
|
|
135
|
+
case 'ST':
|
|
136
|
+
case 'TM':
|
|
137
|
+
case 'UI':
|
|
143
138
|
return getValueInlineString(dataSet, attr, options);
|
|
144
|
-
case
|
|
139
|
+
case 'UL':
|
|
145
140
|
return getValueInlineUnsignedLong(dataSet, attr);
|
|
146
|
-
case
|
|
141
|
+
case 'UN':
|
|
147
142
|
return getValueInlineBinary(dataSet, attr);
|
|
148
|
-
case
|
|
143
|
+
case 'US':
|
|
149
144
|
return getValueInlineUnsignedShort(dataSet, attr);
|
|
150
|
-
case
|
|
145
|
+
case 'UT':
|
|
151
146
|
return getValueInlineString(dataSet, attr, options);
|
|
152
147
|
default:
|
|
153
148
|
return getValueInlineBinary(dataSet, attr);
|
|
154
149
|
}
|
|
155
150
|
};
|
|
156
151
|
|
|
157
|
-
const isPrivate =
|
|
152
|
+
const isPrivate = attr => {
|
|
158
153
|
const { tag } = attr;
|
|
159
154
|
const ch = tag.substr(4, 1);
|
|
160
155
|
const chHex = parseInt(ch, 16);
|
|
161
156
|
return chHex % 2 == 1;
|
|
162
157
|
};
|
|
163
158
|
|
|
164
|
-
const RawEncapsulatedDocument =
|
|
159
|
+
const RawEncapsulatedDocument = 'x00420011';
|
|
165
160
|
|
|
166
161
|
const isValueInline = (attr, options) => {
|
|
167
162
|
if (isPrivate(attr)) {
|
|
@@ -187,30 +182,15 @@ const isValueInline = (attr, options) => {
|
|
|
187
182
|
* @param {*} parentAttr attr's parent. If not present means attr is at root level.
|
|
188
183
|
* @returns
|
|
189
184
|
*/
|
|
190
|
-
const getValue = async (
|
|
191
|
-
dataSet,
|
|
192
|
-
attr,
|
|
193
|
-
vr,
|
|
194
|
-
getDataSet,
|
|
195
|
-
callback,
|
|
196
|
-
options,
|
|
197
|
-
parentAttr,
|
|
198
|
-
) => {
|
|
185
|
+
const getValue = async (dataSet, attr, vr, getDataSet, callback, options, parentAttr) => {
|
|
199
186
|
// It will only process pixelData tag if on metadata root. Otherwise it will be skiped.
|
|
200
|
-
if (attr.tag ===
|
|
201
|
-
const BulkDataURI = await extractImageFrames(
|
|
202
|
-
dataSet,
|
|
203
|
-
attr,
|
|
204
|
-
vr,
|
|
205
|
-
callback,
|
|
206
|
-
options,
|
|
207
|
-
);
|
|
187
|
+
if (attr.tag === 'x7fe00010' && !parentAttr) {
|
|
188
|
+
const BulkDataURI = await extractImageFrames(dataSet, attr, vr, callback, options);
|
|
208
189
|
return { BulkDataURI };
|
|
209
190
|
}
|
|
210
|
-
if (attr.tag ===
|
|
191
|
+
if (attr.tag === 'xfffee00d') return undefined;
|
|
211
192
|
// Group length
|
|
212
|
-
if (attr.tag.length == 9 && attr.tag.substring(5, 9) ===
|
|
213
|
-
return undefined;
|
|
193
|
+
if (attr.tag.length == 9 && attr.tag.substring(5, 9) === '0000') return undefined;
|
|
214
194
|
if (attr.items) {
|
|
215
195
|
// sequences
|
|
216
196
|
const result = [];
|
|
@@ -227,11 +207,8 @@ const getValue = async (
|
|
|
227
207
|
if (isValueInline(attr, options)) {
|
|
228
208
|
return getValueInline(dataSet, attr, vr, options);
|
|
229
209
|
}
|
|
230
|
-
const binaryValue = dataSet.byteArray.slice(
|
|
231
|
-
|
|
232
|
-
attr.dataOffset + attr.length,
|
|
233
|
-
);
|
|
234
|
-
const mimeType = attr.tag == "x00420011" && dataSet.string("x00420012");
|
|
210
|
+
const binaryValue = dataSet.byteArray.slice(attr.dataOffset, attr.dataOffset + attr.length);
|
|
211
|
+
const mimeType = attr.tag == 'x00420011' && dataSet.string('x00420012');
|
|
235
212
|
|
|
236
213
|
const BulkDataURI = await callback.bulkdata(binaryValue, { mimeType });
|
|
237
214
|
return { BulkDataURI, vr };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const { Tags } = require(
|
|
1
|
+
const { Tags } = require('@radicalimaging/static-wado-util');
|
|
2
2
|
|
|
3
3
|
function validateMetadata(options) {
|
|
4
|
-
const serviceUrl =
|
|
4
|
+
const serviceUrl = '';
|
|
5
5
|
const { verify, multipart: stowResponse } = options;
|
|
6
6
|
|
|
7
7
|
return function (id, result) {
|
|
8
8
|
const getValue = Tags.getValue.bind(null, result.metadata);
|
|
9
9
|
if (verify) {
|
|
10
|
-
console.verbose(
|
|
10
|
+
console.verbose('Validating metadata', id);
|
|
11
11
|
if (id.studyInstanceUid.length > 64) {
|
|
12
12
|
throw new Error(`StudyInstanceUID too long: ${id.studyInstanceUid}`);
|
|
13
13
|
}
|
|
@@ -32,7 +32,7 @@ function validateMetadata(options) {
|
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
};
|
|
35
|
-
this.success(
|
|
35
|
+
this.success('instanceStored', successMessage, filename);
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
}
|
package/lib/program/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const staticWadoUtil = require(
|
|
1
|
+
const staticWadoUtil = require('@radicalimaging/static-wado-util');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Configure static-wado-creator commander program.
|
|
@@ -7,10 +7,7 @@ const staticWadoUtil = require("@radicalimaging/static-wado-util");
|
|
|
7
7
|
* @returns Program object
|
|
8
8
|
*/
|
|
9
9
|
async function configureProgram(defaults) {
|
|
10
|
-
const configurationFile = await staticWadoUtil.loadConfiguration(
|
|
11
|
-
defaults,
|
|
12
|
-
process.argv,
|
|
13
|
-
);
|
|
10
|
+
const configurationFile = await staticWadoUtil.loadConfiguration(defaults, process.argv);
|
|
14
11
|
return staticWadoUtil.configureCommands(defaults);
|
|
15
12
|
}
|
|
16
13
|
|
package/lib/rejectMain.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const StaticWado = require(
|
|
2
|
-
const adaptProgramOpts = require(
|
|
1
|
+
const StaticWado = require('./StaticWado');
|
|
2
|
+
const adaptProgramOpts = require('./util/adaptProgramOpts');
|
|
3
3
|
|
|
4
4
|
module.exports = function rejectMain(args, options) {
|
|
5
5
|
const finalOptions = adaptProgramOpts(options, {
|
package/lib/serverMain.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
const readline = require(
|
|
2
|
-
const {
|
|
3
|
-
argv,
|
|
4
|
-
argv0,
|
|
5
|
-
exit,
|
|
6
|
-
stdin: input,
|
|
7
|
-
stdout: output,
|
|
8
|
-
} = require("node:process");
|
|
1
|
+
const readline = require('node:readline');
|
|
2
|
+
const { argv, argv0, exit, stdin: input, stdout: output } = require('node:process');
|
|
9
3
|
|
|
10
|
-
const StaticWado = require(
|
|
11
|
-
const adaptProgramOpts = require(
|
|
4
|
+
const StaticWado = require('./StaticWado');
|
|
5
|
+
const adaptProgramOpts = require('./util/adaptProgramOpts');
|
|
12
6
|
|
|
13
7
|
module.exports = async function createMain(options, program) {
|
|
14
8
|
const rl = readline.createInterface({ input, output });
|
|
15
9
|
for await (const line of rl) {
|
|
16
10
|
if (!line) continue;
|
|
17
|
-
if (line.startsWith(
|
|
11
|
+
if (line.startsWith('exit')) {
|
|
18
12
|
exit(0);
|
|
19
13
|
}
|
|
20
|
-
argv.splice(2, argv.length - 2, ...line.split(
|
|
21
|
-
console.verbose(
|
|
14
|
+
argv.splice(2, argv.length - 2, ...line.split(' '));
|
|
15
|
+
console.verbose('exec mkdicomweb', JSON.stringify(argv));
|
|
22
16
|
|
|
23
17
|
// Configure program commander
|
|
24
18
|
await StaticWado.configureProgram(StaticWado.mkdicomwebConfig);
|
|
25
|
-
output.write(
|
|
19
|
+
output.write('mkdicomweb server -->\n');
|
|
26
20
|
}
|
|
27
21
|
};
|
package/lib/util/IdCreator.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
const path = require(
|
|
2
|
-
const {
|
|
3
|
-
getStudyUIDPathAndSubPath,
|
|
4
|
-
} = require("@radicalimaging/static-wado-util");
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { getStudyUIDPathAndSubPath } = require('@radicalimaging/static-wado-util');
|
|
5
3
|
|
|
6
4
|
function IdCreator({
|
|
7
5
|
directoryName,
|
|
@@ -12,7 +10,7 @@ function IdCreator({
|
|
|
12
10
|
return (uids, filename) => {
|
|
13
11
|
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid } = uids;
|
|
14
12
|
|
|
15
|
-
const { path: hashPath =
|
|
13
|
+
const { path: hashPath = '', subpath: hashSubpath = '' } = hashStudyUidPath
|
|
16
14
|
? getStudyUIDPathAndSubPath(studyInstanceUid)
|
|
17
15
|
: {};
|
|
18
16
|
|
|
@@ -20,20 +18,13 @@ function IdCreator({
|
|
|
20
18
|
? path.join(hashPath, hashSubpath, studyInstanceUid)
|
|
21
19
|
: studyInstanceUid;
|
|
22
20
|
|
|
23
|
-
const studyPath = path.join(directoryName,
|
|
24
|
-
const seriesRootPath = path.join(studyPath,
|
|
25
|
-
const sopInstanceRootPath = path.join(
|
|
26
|
-
|
|
27
|
-
"instances",
|
|
28
|
-
sopInstanceUid,
|
|
29
|
-
);
|
|
30
|
-
const imageFrameRootPath = path.join(sopInstanceRootPath, "frames");
|
|
21
|
+
const studyPath = path.join(directoryName, 'studies', studySubDir);
|
|
22
|
+
const seriesRootPath = path.join(studyPath, 'series', seriesInstanceUid);
|
|
23
|
+
const sopInstanceRootPath = path.join(seriesRootPath, 'instances', sopInstanceUid);
|
|
24
|
+
const imageFrameRootPath = path.join(sopInstanceRootPath, 'frames');
|
|
31
25
|
|
|
32
26
|
const deduplicatedPath = path.join(deduplicatedRoot, studySubDir);
|
|
33
|
-
const deduplicatedInstancesPath = path.join(
|
|
34
|
-
deduplicatedInstancesRoot,
|
|
35
|
-
studySubDir,
|
|
36
|
-
);
|
|
27
|
+
const deduplicatedInstancesPath = path.join(deduplicatedInstancesRoot, studySubDir);
|
|
37
28
|
|
|
38
29
|
return {
|
|
39
30
|
...uids,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const assignDefined = (dest, src) => {
|
|
2
|
-
Object.keys(src).forEach(
|
|
2
|
+
Object.keys(src).forEach(key => {
|
|
3
3
|
const val = src[key];
|
|
4
4
|
if (val !== undefined) {
|
|
5
5
|
dest[key] = val;
|
|
@@ -34,6 +34,6 @@ module.exports = function adaptProgramOpts(programOpts, defaults) {
|
|
|
34
34
|
encapsulatedImage: encapsulatedImage ?? singlePartImage !== true,
|
|
35
35
|
singlePartImage: singlePartImage ?? encapsulatedImage === false,
|
|
36
36
|
delete: deleteInstances,
|
|
37
|
-
}
|
|
37
|
+
}
|
|
38
38
|
);
|
|
39
39
|
};
|
|
@@ -1,22 +1,13 @@
|
|
|
1
|
-
const { program } = require(
|
|
2
|
-
const {
|
|
3
|
-
getDestinationTranscoder,
|
|
4
|
-
} = require("../operation/adapter/transcodeImage");
|
|
1
|
+
const { program } = require('@radicalimaging/static-wado-util');
|
|
2
|
+
const { getDestinationTranscoder } = require('../operation/adapter/transcodeImage');
|
|
5
3
|
|
|
6
4
|
module.exports = function compressionOptionParser(value) {
|
|
7
5
|
const destination = getDestinationTranscoder(value);
|
|
8
6
|
if (destination) {
|
|
9
|
-
console.log(
|
|
10
|
-
"Found destination transferSyntax ",
|
|
11
|
-
destination.transferSyntaxUid,
|
|
12
|
-
"for ",
|
|
13
|
-
value,
|
|
14
|
-
);
|
|
7
|
+
console.log('Found destination transferSyntax ', destination.transferSyntaxUid, 'for ', value);
|
|
15
8
|
} else {
|
|
16
|
-
console.log(
|
|
17
|
-
throw new program.InvalidArgumentError(
|
|
18
|
-
`No transcoder destination for ${value}`,
|
|
19
|
-
);
|
|
9
|
+
console.log('No transcoder destination for ', value);
|
|
10
|
+
throw new program.InvalidArgumentError(`No transcoder destination for ${value}`);
|
|
20
11
|
}
|
|
21
12
|
return destination.transferSyntaxUid;
|
|
22
13
|
};
|
|
@@ -1,88 +1,87 @@
|
|
|
1
|
-
import fs from
|
|
1
|
+
import fs from 'fs';
|
|
2
2
|
|
|
3
3
|
const results = [];
|
|
4
4
|
let sopResponse = null;
|
|
5
5
|
|
|
6
6
|
function ensureSOPResponse(data) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
7
|
+
if (!data.ReferencedSOPSequence && !data.FailedSOPSequence) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (!sopResponse) {
|
|
11
|
+
sopResponse = {
|
|
12
|
+
...data,
|
|
13
|
+
FailedSOPSequence: undefined,
|
|
14
|
+
ReferencedSOPSequence: undefined,
|
|
15
|
+
};
|
|
16
|
+
results.push(sopResponse);
|
|
17
|
+
}
|
|
18
|
+
if (data.ReferencedSOPSequence) {
|
|
19
|
+
sopResponse.ReferencedSOPSequence ||= [];
|
|
20
|
+
sopResponse.ReferencedSOPSequence.push(...data.ReferencedSOPSequence);
|
|
21
|
+
}
|
|
22
|
+
if (data.FailedSOPSequence) {
|
|
23
|
+
sopResponse.FailedSOPSequence ||= [];
|
|
24
|
+
sopResponse.FailedSOPSequence.push(...data.FailedSOPSequence);
|
|
25
|
+
}
|
|
27
26
|
}
|
|
28
27
|
export function Success(options) {
|
|
29
|
-
|
|
28
|
+
const { deleteInput = false } = options;
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} else if(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
return (_action, data, file) => {
|
|
31
|
+
if (data.ReferencedSOPSequence) {
|
|
32
|
+
ensureSOPResponse(data);
|
|
33
|
+
} else {
|
|
34
|
+
results.push(data);
|
|
35
|
+
}
|
|
36
|
+
if (file && deleteInput) {
|
|
37
|
+
console.noQuiet('Deleting', file);
|
|
38
|
+
fs.unlinkSync(file);
|
|
39
|
+
} else if (file) {
|
|
40
|
+
console.verbose('Not deleting', file);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
export function Failure(options) {
|
|
47
|
-
|
|
46
|
+
const { deleteFailed } = options;
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
return (_action, data, file) => {
|
|
49
|
+
if (data.FailedSOPSequence) {
|
|
50
|
+
ensureSOPResponse(data);
|
|
51
|
+
} else {
|
|
52
|
+
results.push(data);
|
|
53
|
+
}
|
|
54
|
+
if (file && deleteFailed) {
|
|
55
|
+
console.noQuiet('Deleting failure', file);
|
|
56
|
+
fs.unlinkSync(file);
|
|
57
|
+
} else if (file) {
|
|
58
|
+
console.verbose('Not deleting failure file', file);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
export function clearResults() {
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
results.splice(0, results.length);
|
|
65
|
+
sopResponse = null;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
export function WriteResults(options) {
|
|
70
|
-
|
|
69
|
+
const { multipart } = options;
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
71
|
+
return function () {
|
|
72
|
+
if (multipart) {
|
|
73
|
+
const str =
|
|
74
|
+
results.length === 1
|
|
75
|
+
? JSON.stringify(results[0])
|
|
76
|
+
: `[\n${results.map(r => JSON.stringify(r, null, 2)).join(',\n')}\n]`;
|
|
77
|
+
console.log(
|
|
78
|
+
'\r\n--boundary-response\r\n' +
|
|
79
|
+
'content-type: application/json\r\n\r\n' +
|
|
80
|
+
str +
|
|
81
|
+
'\r\n--boundary-response--\r\n'
|
|
82
|
+
);
|
|
83
|
+
}
|
|
85
84
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
85
|
+
clearResults();
|
|
86
|
+
};
|
|
87
|
+
}
|