@radicalimaging/static-wado-creator 1.6.10 → 1.6.12

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 (51) hide show
  1. package/dist/index.js +84817 -54902
  2. package/lib/DeleteStudy.js +9 -14
  3. package/lib/RejectInstance.js +4 -15
  4. package/lib/StaticWado.js +92 -147
  5. package/lib/createMain.js +3 -3
  6. package/lib/createPart10.js +19 -23
  7. package/lib/createThumbnail.js +27 -45
  8. package/lib/deleteMain.js +2 -2
  9. package/lib/groupMain.js +2 -2
  10. package/lib/index.js +6 -6
  11. package/lib/indexMain.js +2 -2
  12. package/lib/instanceMain.js +2 -2
  13. package/lib/metadataMain.js +2 -2
  14. package/lib/mkdicomwebConfig.js +157 -165
  15. package/lib/model/TagLists.js +5 -17
  16. package/lib/model/uids.js +29 -29
  17. package/lib/operation/InstanceDeduplicate.js +14 -19
  18. package/lib/operation/ScanStudy.js +11 -18
  19. package/lib/operation/StudyData.js +87 -156
  20. package/lib/operation/ThumbnailService.js +29 -54
  21. package/lib/operation/adapter/decodeImage.js +2 -2
  22. package/lib/operation/adapter/getImageInfo.js +7 -8
  23. package/lib/operation/adapter/transcodeImage.js +95 -146
  24. package/lib/operation/extractImageFrames.js +13 -17
  25. package/lib/operation/getDataSet.js +9 -43
  26. package/lib/operation/getEncapsulatedImageFrame.js +7 -19
  27. package/lib/operation/getNumberOfFrames.js +2 -2
  28. package/lib/operation/getUncompressedImageFrame.js +2 -10
  29. package/lib/operation/getVR.js +5 -5
  30. package/lib/operation/getValue.js +42 -65
  31. package/lib/operation/validateMetadata.js +4 -4
  32. package/lib/program/index.js +2 -5
  33. package/lib/rejectMain.js +2 -2
  34. package/lib/serverMain.js +8 -14
  35. package/lib/util/IdCreator.js +8 -17
  36. package/lib/util/adaptProgramOpts.js +2 -2
  37. package/lib/util/compressionOptionParser.js +5 -14
  38. package/lib/util/resultsReport.ts +67 -68
  39. package/lib/writer/CompleteStudyWriter.js +24 -37
  40. package/lib/writer/DeduplicateWriter.js +7 -8
  41. package/lib/writer/ExpandUriPath.js +3 -5
  42. package/lib/writer/HashDataWriter.js +18 -18
  43. package/lib/writer/ImageFrameWriter.js +20 -33
  44. package/lib/writer/MultipartHeader.js +1 -1
  45. package/lib/writer/RawDicomWriter.js +12 -13
  46. package/lib/writer/ThumbnailWriter.js +2 -2
  47. package/lib/writer/VideoWriter.js +23 -34
  48. package/lib/writer/WriteMultipart.js +4 -6
  49. package/lib/writer/WriteStream.js +14 -20
  50. package/package.json +1 -1
  51. package/lib/writer/static-dicomweb.code-workspace +0 -8
@@ -1,21 +1,16 @@
1
- const { JSONReader } = require("@radicalimaging/static-wado-util");
2
- const { JSONWriter } = require("@radicalimaging/static-wado-util");
3
- const { Tags } = require("@radicalimaging/static-wado-util");
1
+ const { JSONReader } = require('@radicalimaging/static-wado-util');
2
+ const { JSONWriter } = require('@radicalimaging/static-wado-util');
3
+ const { Tags } = require('@radicalimaging/static-wado-util');
4
4
 
5
- module.exports = (options) =>
5
+ module.exports = options =>
6
6
  async function (studyInstanceUid) {
7
- console.log("Delete Study", studyInstanceUid);
8
- const studyData = await this.scanStudy("studies", studyInstanceUid);
7
+ console.log('Delete Study', studyInstanceUid);
8
+ const studyData = await this.scanStudy('studies', studyInstanceUid);
9
9
  studyData.delete();
10
- const allStudies = await JSONReader(
11
- options.directoryName,
12
- "studies/index.json.gz",
13
- [],
14
- );
10
+ const allStudies = await JSONReader(options.directoryName, 'studies/index.json.gz', []);
15
11
  const studiesWithoutDeleted = allStudies.filter(
16
- (study) =>
17
- studyInstanceUid != Tags.getValue(study, Tags.StudyInstanceUID),
12
+ study => studyInstanceUid != Tags.getValue(study, Tags.StudyInstanceUID)
18
13
  );
19
- await JSONWriter(options.directoryName, "studies", studiesWithoutDeleted);
14
+ await JSONWriter(options.directoryName, 'studies', studiesWithoutDeleted);
20
15
  delete this.studyData;
21
16
  };
@@ -6,30 +6,19 @@ module.exports = () =>
6
6
  let studyInstanceUid = args[0];
7
7
  let seriesInstanceUid;
8
8
  let sopInstanceUid;
9
- const reason = args[2] || "REJECT";
9
+ const reason = args[2] || 'REJECT';
10
10
  const extracted = args[0].match(dataExtractor);
11
11
  if (extracted) {
12
12
  studyInstanceUid = extracted[2];
13
13
  seriesInstanceUid = extracted[4];
14
14
  sopInstanceUid = extracted[6];
15
- console.log(
16
- "Extracted",
17
- studyInstanceUid,
18
- seriesInstanceUid,
19
- sopInstanceUid,
20
- reason,
21
- );
15
+ console.log('Extracted', studyInstanceUid, seriesInstanceUid, sopInstanceUid, reason);
22
16
  } else {
23
- console.log(
24
- "Not extracting from URL",
25
- studyInstanceUid,
26
- seriesInstanceUid,
27
- reason,
28
- );
17
+ console.log('Not extracting from URL', studyInstanceUid, seriesInstanceUid, reason);
29
18
  seriesInstanceUid = args[1];
30
19
  }
31
20
  const studyData = await this.scanStudy(studyInstanceUid);
32
- console.verbose("Trying to reject", seriesInstanceUid, "because", reason);
21
+ console.verbose('Trying to reject', seriesInstanceUid, 'because', reason);
33
22
  await studyData.reject(seriesInstanceUid, sopInstanceUid, reason);
34
23
  await studyData.writeDeduplicatedGroup();
35
24
  return studyData.writeMetadata();
package/lib/StaticWado.js CHANGED
@@ -1,5 +1,5 @@
1
- const dicomCodec = require("@cornerstonejs/dicom-codec");
2
- const staticCS = require("@radicalimaging/cs3d");
1
+ const dicomCodec = require('@cornerstonejs/dicom-codec');
2
+ const staticCS = require('@radicalimaging/cs3d');
3
3
  const {
4
4
  Stats,
5
5
  handleHomeRelative,
@@ -8,41 +8,36 @@ const {
8
8
  JSONWriter,
9
9
  asyncIterableToBuffer,
10
10
  Tags,
11
- } = require("@radicalimaging/static-wado-util");
12
- const dicomParser = require("dicom-parser");
13
- const fs = require("fs");
14
- const path = require("path");
15
- const { NotificationService } = require("@radicalimaging/static-wado-util");
16
- const getDataSet = require("./operation/getDataSet");
17
- const InstanceDeduplicate = require("./operation/InstanceDeduplicate");
18
- const DeduplicateWriter = require("./writer/DeduplicateWriter");
19
- const ImageFrameWriter = require("./writer/ImageFrameWriter");
20
- const WriteStream = require("./writer/WriteStream");
21
- const CompleteStudyWriter = require("./writer/CompleteStudyWriter");
22
- const IdCreator = require("./util/IdCreator");
23
- const ScanStudy = require("./operation/ScanStudy");
24
- const HashDataWriter = require("./writer/HashDataWriter");
25
- const VideoWriter = require("./writer/VideoWriter");
11
+ } = require('@radicalimaging/static-wado-util');
12
+ const dicomParser = require('dicom-parser');
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { NotificationService } = require('@radicalimaging/static-wado-util');
16
+ const getDataSet = require('./operation/getDataSet');
17
+ const InstanceDeduplicate = require('./operation/InstanceDeduplicate');
18
+ const DeduplicateWriter = require('./writer/DeduplicateWriter');
19
+ const ImageFrameWriter = require('./writer/ImageFrameWriter');
20
+ const WriteStream = require('./writer/WriteStream');
21
+ const CompleteStudyWriter = require('./writer/CompleteStudyWriter');
22
+ const IdCreator = require('./util/IdCreator');
23
+ const ScanStudy = require('./operation/ScanStudy');
24
+ const HashDataWriter = require('./writer/HashDataWriter');
25
+ const VideoWriter = require('./writer/VideoWriter');
26
26
  const {
27
27
  transcodeImageFrame,
28
28
  generateLossyImage,
29
29
  transcodeId,
30
30
  transcodeMetadata,
31
- } = require("./operation/adapter/transcodeImage");
32
- const ThumbnailWriter = require("./writer/ThumbnailWriter");
33
- const decodeImage = require("./operation/adapter/decodeImage");
34
- const ThumbnailService = require("./operation/ThumbnailService");
35
- const DeleteStudy = require("./DeleteStudy");
36
- const RejectInstance = require("./RejectInstance");
37
- const RawDicomWriter = require("./writer/RawDicomWriter");
38
- const { isVideo } = require("./writer/VideoWriter");
39
- const validateMetadata = require("./operation/validateMetadata.js");
40
- const {
41
- Success,
42
- Failure,
43
- clearResults,
44
- WriteResults,
45
- } = require("./util/resultsReport");
31
+ } = require('./operation/adapter/transcodeImage');
32
+ const ThumbnailWriter = require('./writer/ThumbnailWriter');
33
+ const decodeImage = require('./operation/adapter/decodeImage');
34
+ const ThumbnailService = require('./operation/ThumbnailService');
35
+ const DeleteStudy = require('./DeleteStudy');
36
+ const RejectInstance = require('./RejectInstance');
37
+ const RawDicomWriter = require('./writer/RawDicomWriter');
38
+ const { isVideo } = require('./writer/VideoWriter');
39
+ const validateMetadata = require('./operation/validateMetadata.js');
40
+ const { Success, Failure, clearResults, WriteResults } = require('./util/resultsReport');
46
41
 
47
42
  function setStudyData(studyData) {
48
43
  this.studyData = studyData;
@@ -53,31 +48,24 @@ async function cs3dThumbnail(
53
48
  dataset,
54
49
  metadata,
55
50
  transferSyntaxUid,
56
- doneCallback,
51
+ doneCallback
57
52
  ) {
58
53
  if (!originalImageFrame) {
59
54
  throw new Error(`No originalImageFrame data available`);
60
55
  }
61
56
  if (!dataset && !metadata) {
62
- throw new Error(
63
- `Neither dataset ${!!dataset} nor metadata ${!!metadata} available.`,
64
- );
57
+ throw new Error(`Neither dataset ${!!dataset} nor metadata ${!!metadata} available.`);
65
58
  }
66
59
  if (isVideo(transferSyntaxUid)) {
67
- console.log("Video data - no thumbnail generator yet");
60
+ console.log('Video data - no thumbnail generator yet');
68
61
  return;
69
62
  }
70
63
 
71
64
  let decodeResult;
72
65
  try {
73
- decodeResult = await decodeImage(
74
- originalImageFrame,
75
- dataset,
76
- metadata,
77
- transferSyntaxUid,
78
- );
66
+ decodeResult = await decodeImage(originalImageFrame, dataset, metadata, transferSyntaxUid);
79
67
  } catch (error) {
80
- console.log("Error while decoding image:", error);
68
+ console.noQuiet('Error while decoding image:', error);
81
69
  return;
82
70
  }
83
71
 
@@ -87,25 +75,20 @@ async function cs3dThumbnail(
87
75
  }
88
76
 
89
77
  const { imageFrame, imageInfo } = decodeResult;
90
- const pixelData = dicomCodec.getPixelData(
91
- imageFrame,
92
- imageInfo,
93
- transferSyntaxUid,
94
- );
95
- return staticCS.getRenderedBuffer(
96
- transferSyntaxUid,
97
- pixelData,
98
- metadata,
99
- doneCallback,
100
- );
78
+ const pixelData = dicomCodec.getPixelData(imageFrame, imageInfo, transferSyntaxUid);
79
+ return staticCS.getRenderedBuffer(transferSyntaxUid, pixelData, metadata, doneCallback, {
80
+ quality: 0.6,
81
+ width: 256,
82
+ height: 256,
83
+ });
101
84
  }
102
85
 
103
86
  class StaticWado {
104
87
  constructor(configuration) {
105
88
  const {
106
- rootDir = "~/dicomweb",
107
- pathDeduplicated = "deduplicated",
108
- pathInstances = "instances",
89
+ rootDir = '~/dicomweb',
90
+ pathDeduplicated = 'deduplicated',
91
+ pathInstances = 'instances',
109
92
  verbose,
110
93
  quiet = false,
111
94
  multipart = false,
@@ -124,7 +107,7 @@ class StaticWado {
124
107
  deduplicatedRoot: path.join(directoryName, pathDeduplicated),
125
108
  deduplicatedInstancesRoot: path.join(directoryName, pathInstances),
126
109
  // TODO - make this configurable and auto-detect by updating the parseDicom library
127
- TransferSyntaxUID: "1.2.840.10008.1.2.1",
110
+ TransferSyntaxUID: '1.2.840.10008.1.2.1',
128
111
  };
129
112
  this.callback = {
130
113
  uids: IdCreator(this.options),
@@ -145,9 +128,7 @@ class StaticWado {
145
128
  clearResults,
146
129
  setStudyData,
147
130
  rawDicomWriter: RawDicomWriter(this.options),
148
- notificationService: new NotificationService(
149
- this.options.notificationDir,
150
- ),
131
+ notificationService: new NotificationService(this.options.notificationDir),
151
132
  internalGenerateImage: cs3dThumbnail,
152
133
  };
153
134
  }
@@ -169,7 +150,7 @@ class StaticWado {
169
150
  * @param {string[]} args listing the studies to remove
170
151
  */
171
152
  async delete(args) {
172
- args.forEach((studyUID) => this.callback.delete(studyUID));
153
+ args.forEach(studyUID => this.callback.delete(studyUID));
173
154
  }
174
155
 
175
156
  /**
@@ -183,14 +164,11 @@ class StaticWado {
183
164
  updateProgress() {
184
165
  if (!this.showProgress) return;
185
166
  this.processedFiles++;
186
- const percentage = Math.round(
187
- (this.processedFiles / this.totalFiles) * 100,
188
- );
167
+ const percentage = Math.round((this.processedFiles / this.totalFiles) * 100);
189
168
  const progressBar =
190
- "=".repeat(Math.floor(percentage / 4)) +
191
- "-".repeat(25 - Math.floor(percentage / 4));
169
+ '='.repeat(Math.floor(percentage / 4)) + '-'.repeat(25 - Math.floor(percentage / 4));
192
170
  process.stdout.write(
193
- `\r[${progressBar}] ${percentage}% | ${this.processedFiles}/${this.totalFiles} files`,
171
+ `\r[${progressBar}] ${percentage}% | ${this.processedFiles}/${this.totalFiles} files`
194
172
  );
195
173
  }
196
174
 
@@ -202,20 +180,19 @@ class StaticWado {
202
180
  if (fs.statSync(file).isDirectory()) {
203
181
  const dirFiles = fs.readdirSync(file, { recursive: true });
204
182
  this.totalFiles += dirFiles.filter(
205
- (f) => !fs.statSync(path.join(file, f)).isDirectory(),
183
+ f => !fs.statSync(path.join(file, f)).isDirectory()
206
184
  ).length;
207
185
  } else {
208
186
  this.totalFiles++;
209
187
  }
210
188
  } catch (e) {
189
+ console.verbose('File not dicom', e);
211
190
  this.callback.failure(
212
- "File not DICOM",
191
+ 'File not DICOM',
213
192
  {
214
- FailedSOPSequence: [
215
- { FailureReason: 0xd000, TextValue: "File not DICOM" },
216
- ],
193
+ FailedSOPSequence: [{ FailureReason: 0xd000, TextValue: 'File not DICOM' }],
217
194
  },
218
- file,
195
+ file
219
196
  );
220
197
  }
221
198
  }
@@ -225,40 +202,41 @@ class StaticWado {
225
202
  let filesProcessed = 0;
226
203
  const result = await dirScanner(files, {
227
204
  ...params,
228
- callback: async (file) => {
205
+ callback: async file => {
229
206
  try {
230
207
  const dicomp10stream = fs.createReadStream(file);
231
208
  await this.importBinaryDicom(dicomp10stream, { ...params, file });
232
209
  filesProcessed++;
233
- Stats.StudyStats.add("DICOM P10", "Parse DICOM P10 file");
210
+ Stats.StudyStats.add('DICOM P10', 'Parse DICOM P10 file');
234
211
  this.updateProgress();
235
212
  } catch (e) {
213
+ console.noQuiet('Create failure', e);
236
214
  this.updateProgress();
237
215
  const message = {
238
216
  FailedSOPSequence: [
239
217
  {
240
218
  FailureReason: 0xd000,
241
- TextValue: "File not DICOM",
219
+ TextValue: 'File not DICOM',
242
220
  StorageURL: file,
243
221
  },
244
222
  ],
245
223
  };
246
- this.callback.failure("Not DICOM", message, file, e);
224
+ this.callback.failure('Not DICOM', message, file, e);
247
225
  }
248
226
  },
249
227
  });
250
228
 
251
229
  if (!filesProcessed) {
252
230
  const message = {
253
- action: "metadata",
231
+ action: 'metadata',
254
232
  count: 0,
255
233
  status: -1,
256
234
  };
257
- this.callback.failure("No files processed", message);
235
+ this.callback.failure('No files processed', message);
258
236
  }
259
237
 
260
238
  if (this.showProgress) {
261
- console.log("\n"); // Move to next line after progress bar
239
+ console.log('\n'); // Move to next line after progress bar
262
240
  }
263
241
  return result;
264
242
  }
@@ -271,7 +249,7 @@ class StaticWado {
271
249
  async processStudyDir(studyUids /* , options */) {
272
250
  for (const studyUid of studyUids) {
273
251
  const study = await this.callback.scanStudy(studyUid);
274
- console.log("Processed study", study.studyInstanceUid);
252
+ console.log('Processed study', study.studyInstanceUid);
275
253
  }
276
254
  }
277
255
 
@@ -282,7 +260,7 @@ class StaticWado {
282
260
  // Parse it
283
261
  const dataSet = dicomParser.parseDicom(buffer, params);
284
262
 
285
- const studyInstanceUid = dataSet.string("x0020000d");
263
+ const studyInstanceUid = dataSet.string('x0020000d');
286
264
 
287
265
  if (!studyInstanceUid) {
288
266
  console.log("No study UID, can't import file", params.file);
@@ -293,18 +271,14 @@ class StaticWado {
293
271
  const id = this.callback.uids(
294
272
  {
295
273
  studyInstanceUid,
296
- seriesInstanceUid: dataSet.string("x0020000e"),
297
- sopInstanceUid: dataSet.string("x00080018"),
298
- transferSyntaxUid: dataSet.string("x00020010"),
274
+ seriesInstanceUid: dataSet.string('x0020000e'),
275
+ sopInstanceUid: dataSet.string('x00080018'),
276
+ transferSyntaxUid: dataSet.string('x00020010'),
299
277
  },
300
- params.file,
278
+ params.file
301
279
  );
302
280
 
303
- const targetId = transcodeId(
304
- id,
305
- this.options,
306
- dataSet.uint16(Tags.RawSamplesPerPixel),
307
- );
281
+ const targetId = transcodeId(id, this.options, dataSet.uint16(Tags.RawSamplesPerPixel));
308
282
 
309
283
  let bulkDataIndex = 0;
310
284
  let imageFrameIndex = 0;
@@ -315,38 +289,23 @@ class StaticWado {
315
289
  const _bulkDataIndex = bulkDataIndex;
316
290
  bulkDataIndex += 1;
317
291
  // TODO - handle other types here too as single part rendered
318
- if (options?.mimeType === "application/pdf") {
319
- console.log("Writing rendered mimeType", options.mimeType);
320
- const writeStream = WriteStream(
321
- id.sopInstanceRootPath,
322
- "rendered.pdf",
323
- {
324
- gzip: false,
325
- mkdir: true,
326
- },
327
- );
292
+ if (options?.mimeType === 'application/pdf') {
293
+ console.verbose('Writing rendered mimeType', options.mimeType);
294
+ const writeStream = WriteStream(id.sopInstanceRootPath, 'rendered.pdf', {
295
+ gzip: false,
296
+ mkdir: true,
297
+ });
328
298
  await writeStream.write(bulkData);
329
299
  await writeStream.close();
330
300
  }
331
- return this.callback.bulkdata(
332
- targetId,
333
- _bulkDataIndex,
334
- bulkData,
335
- options,
336
- );
301
+ return this.callback.bulkdata(targetId, _bulkDataIndex, bulkData, options);
337
302
  },
338
- imageFrame: async (originalImageFrame) => {
303
+ imageFrame: async originalImageFrame => {
339
304
  const {
340
305
  imageFrame: transcodedImageFrame,
341
306
  decoded,
342
307
  id: transcodedId,
343
- } = await transcodeImageFrame(
344
- id,
345
- targetId,
346
- originalImageFrame,
347
- dataSet,
348
- this.options,
349
- );
308
+ } = await transcodeImageFrame(id, targetId, originalImageFrame, dataSet, this.options);
350
309
 
351
310
  const lossyImage = await generateLossyImage(id, decoded, this.options);
352
311
 
@@ -357,7 +316,7 @@ class StaticWado {
357
316
  await this.callback.imageFrame(
358
317
  lossyImage.id,
359
318
  currentImageFrameIndex,
360
- lossyImage.imageFrame,
319
+ lossyImage.imageFrame
361
320
  );
362
321
  }
363
322
 
@@ -369,16 +328,12 @@ class StaticWado {
369
328
  id,
370
329
  frameIndex: currentImageFrameIndex,
371
330
  },
372
- this.options,
331
+ this.options
373
332
  );
374
333
 
375
- return this.callback.imageFrame(
376
- transcodedId,
377
- currentImageFrameIndex,
378
- transcodedImageFrame,
379
- );
334
+ return this.callback.imageFrame(transcodedId, currentImageFrameIndex, transcodedImageFrame);
380
335
  },
381
- videoWriter: async (_dataSet) => this.callback.videoWriter(id, _dataSet),
336
+ videoWriter: async _dataSet => this.callback.videoWriter(id, _dataSet),
382
337
  };
383
338
 
384
339
  // convert to DICOMweb MetaData and BulkData
@@ -394,14 +349,14 @@ class StaticWado {
394
349
  dataSet,
395
350
  transcodedMeta,
396
351
  this.callback,
397
- this.options,
352
+ this.options
398
353
  );
399
354
  await thumbnailService.generateRendered(
400
355
  id,
401
356
  dataSet,
402
357
  transcodedMeta,
403
358
  this.callback,
404
- this.options,
359
+ this.options
405
360
  );
406
361
  await this.callback.metadata(targetId, transcodedMeta);
407
362
 
@@ -418,15 +373,9 @@ class StaticWado {
418
373
  dataSet,
419
374
  metadata,
420
375
  transferSyntaxUid,
421
- doneCallback,
376
+ doneCallback
422
377
  ) {
423
- return cs3dThumbnail(
424
- originalImageFrame,
425
- dataSet,
426
- metadata,
427
- transferSyntaxUid,
428
- doneCallback,
429
- );
378
+ return cs3dThumbnail(originalImageFrame, dataSet, metadata, transferSyntaxUid, doneCallback);
430
379
  }
431
380
 
432
381
  /**
@@ -437,11 +386,11 @@ class StaticWado {
437
386
  async executeCommand(input) {
438
387
  this.callback.clearResults();
439
388
  if (this.options.scanStudies) {
440
- console.log("Scanning study dir", input);
389
+ console.log('Scanning study dir', input);
441
390
  // Scan one of the study directories - in this case, files is a set of study directories
442
391
  await this.processStudyDir(input, this.options);
443
392
  } else {
444
- console.noQuiet("Scanning files", input);
393
+ console.noQuiet('Scanning files', input);
445
394
  await this.processFiles(input, this.options);
446
395
  }
447
396
  await this.close();
@@ -450,30 +399,26 @@ class StaticWado {
450
399
 
451
400
  async close() {
452
401
  await this.callback.completeStudy(this.callback);
453
- Stats.OverallStats.summarize("Completed Study Processing");
402
+ Stats.OverallStats.summarize('Completed Study Processing');
454
403
  }
455
404
 
456
405
  async reindex() {
457
406
  const { directoryName } = this.options;
458
407
  const studiesDir = `${directoryName}/studies/`;
459
408
 
460
- console.log("Re-indexing", studiesDir);
409
+ console.noQuiet('Re-indexing', studiesDir);
461
410
  const dirs = await fs.promises.readdir(studiesDir);
462
411
  const studies = [];
463
412
  for (const dir of dirs) {
464
- const study = await JSONReader(
465
- `${studiesDir}/${dir}`,
466
- "index.json.gz",
467
- null,
468
- );
413
+ const study = await JSONReader(`${studiesDir}/${dir}`, 'index.json.gz', null);
469
414
  if (study === null) {
470
- console.log("No study found in", dir);
415
+ console.log('No study found in', dir);
471
416
  continue;
472
417
  }
473
- console.log("Adding study", dir);
418
+ console.log('Adding study', dir);
474
419
  studies.push(...study);
475
420
  }
476
- return JSONWriter(directoryName, "studies", studies);
421
+ return JSONWriter(directoryName, 'studies', studies);
477
422
  }
478
423
  }
479
424
  module.exports = StaticWado;
package/lib/createMain.js CHANGED
@@ -1,11 +1,11 @@
1
- const StaticWado = require("./StaticWado");
2
- const adaptProgramOpts = require("./util/adaptProgramOpts");
1
+ const StaticWado = require('./StaticWado');
2
+ const adaptProgramOpts = require('./util/adaptProgramOpts');
3
3
 
4
4
  module.exports = function createMain(options, program) {
5
5
  const finalOptions = adaptProgramOpts(options, {
6
6
  ...this,
7
7
  // Instance metadata is the instances/<sopUID>/metadata.gz files
8
- isInstance: true,
8
+ isInstance: false,
9
9
  // Deduplicated data is single instance deduplicated data
10
10
  isDeduplicate: false,
11
11
  // Group data is the group file directories
@@ -1,32 +1,28 @@
1
- const { Tags, readBulkData } = require("@radicalimaging/static-wado-util");
2
- const dcmjs = require("dcmjs");
1
+ const { Tags, readBulkData } = require('@radicalimaging/static-wado-util');
2
+ const dcmjs = require('dcmjs');
3
3
 
4
- const StaticWado = require("./StaticWado");
5
- const adaptProgramOpts = require("./util/adaptProgramOpts");
6
- const WriteStream = require("./writer/WriteStream");
4
+ const StaticWado = require('./StaticWado');
5
+ const adaptProgramOpts = require('./util/adaptProgramOpts');
6
+ const WriteStream = require('./writer/WriteStream');
7
7
 
8
- const UncompressedLEIExplicit = "1.2.840.10008.1.2.1";
8
+ const UncompressedLEIExplicit = '1.2.840.10008.1.2.1';
9
9
  const { DicomDict, DicomMetaDictionary } = dcmjs.data;
10
10
 
11
11
  const fileMetaInformationVersionArray = new Uint8Array(2);
12
12
  fileMetaInformationVersionArray[1] = 1;
13
13
 
14
- const createFmi = (instance) => {
14
+ const createFmi = instance => {
15
15
  // Assume the TSUID is in the value 0
16
16
  const TransferSyntaxUID =
17
- Tags.getValue(instance, Tags.AvailableTransferSyntaxUID) ||
18
- UncompressedLEIExplicit;
19
- const MediaStorageSOPClassUID = Tags.getValue(
20
- instance,
21
- Tags.MediaStorageSOPClassUID,
22
- );
17
+ Tags.getValue(instance, Tags.AvailableTransferSyntaxUID) || UncompressedLEIExplicit;
18
+ const MediaStorageSOPClassUID = Tags.getValue(instance, Tags.MediaStorageSOPClassUID);
23
19
  const SOPInstanceUID = Tags.getValue(instance, Tags.SOPInstanceUID);
24
20
  const naturalFmi = {
25
21
  MediaStorageSOPClassUID,
26
22
  MediaStorageSOPInstanceUID: SOPInstanceUID,
27
- ImplementationVersionName: "mkdicomweb",
23
+ ImplementationVersionName: 'mkdicomweb',
28
24
  TransferSyntaxUID,
29
- ImplementationClassUID: "2.25.984723498557234098.001",
25
+ ImplementationClassUID: '2.25.984723498557234098.001',
30
26
  FileMetaInformationVersion: fileMetaInformationVersionArray.buffer,
31
27
  };
32
28
  const denaturalized = DicomMetaDictionary.denaturalizeDataset(naturalFmi);
@@ -35,11 +31,11 @@ const createFmi = (instance) => {
35
31
 
36
32
  const readBulkDataValue = async (studyDir, instance, value) => {
37
33
  const { BulkDataURI } = value;
38
- value.vr = "OB";
34
+ value.vr = 'OB';
39
35
  const seriesUid = Tags.getValue(instance, Tags.SeriesInstanceUID);
40
36
  const numberOfFrames = Tags.getValue(instance, Tags.NumberOfFrames) || 1;
41
37
  const dir = `${studyDir}/series/${seriesUid}`;
42
- if (BulkDataURI.indexOf("/frames") !== -1) {
38
+ if (BulkDataURI.indexOf('/frames') !== -1) {
43
39
  // Really only support a limited number of frames based on memory size
44
40
  value.Value = [];
45
41
  for (let frame = 1; frame <= numberOfFrames; frame++) {
@@ -61,15 +57,15 @@ const readBinaryData = async (dir, instance) => {
61
57
  }
62
58
  if (!v.vr) {
63
59
  const value0 = v.Value?.[0];
64
- if (typeof value0 === "string") {
65
- v.vr = "LT";
60
+ if (typeof value0 === 'string') {
61
+ v.vr = 'LT';
66
62
  } else {
67
- console.log("Deleting", tag, v.Value, v);
63
+ console.log('Deleting', tag, v.Value, v);
68
64
  delete instance[tag];
69
65
  }
70
66
  continue;
71
67
  }
72
- if (v.vr === "SQ") {
68
+ if (v.vr === 'SQ') {
73
69
  await Promise.all(v.Values.map(readBinaryData));
74
70
  continue;
75
71
  }
@@ -100,14 +96,14 @@ module.exports = async function createMain(options, program) {
100
96
  const importer = new StaticWado(finalOptions);
101
97
  const studyInstanceUid = program.args[0];
102
98
  const dir = `${importer.options.rootDir}/studies/${studyInstanceUid}`;
103
- console.log("Creating part 10 for", studyInstanceUid, dir);
99
+ console.log('Creating part 10 for', studyInstanceUid, dir);
104
100
  const study = await importer.callback.scanStudy(studyInstanceUid);
105
101
  const outputPath = `./studies/${studyInstanceUid}`;
106
102
  for (const sop of study.getSopUids()) {
107
103
  const instance = await study.recombine(sop);
108
104
  const fmi = createFmi(instance);
109
105
 
110
- console.noQuiet("Processing sop", sop);
106
+ console.noQuiet('Processing sop', sop);
111
107
  const dicomDict = new DicomDict(fmi);
112
108
  await readBinaryData(dir, instance);
113
109
  dicomDict.dict = instance;