@radicalimaging/static-wado-creator 0.6.4 → 0.6.5

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.
@@ -8,7 +8,7 @@ module.exports = (options) =>
8
8
  const studyData = await this.scanStudy("studies", studyInstanceUid);
9
9
  studyData.delete();
10
10
  const allStudies = await JSONReader(options.directoryName, "studies/index.json.gz", []);
11
- const studiesWithoutDeleted = allStudies.filter((study) => studyInstanceUid != Tags.getValue(study,Tags.StudyInstanceUID));
11
+ const studiesWithoutDeleted = allStudies.filter((study) => studyInstanceUid != Tags.getValue(study, Tags.StudyInstanceUID));
12
12
  await JSONWriter(options.directoryName, "studies", studiesWithoutDeleted);
13
13
  delete this.studyData;
14
14
  };
package/lib/StaticWado.js CHANGED
@@ -4,7 +4,8 @@ const dicomParser = require("dicom-parser");
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const { dirScanner } = require("@radicalimaging/static-wado-util");
7
- const asyncIterableToBuffer = require("./operation/adapter/asyncIterableToBuffer");
7
+ const { JSONReader } = require("@radicalimaging/static-wado-util");
8
+ const asyncIterableToBuffer = require("@radicalimaging/static-wado-util/lib/asyncIterableToBuffer");
8
9
  const getDataSet = require("./operation/getDataSet");
9
10
  const InstanceDeduplicate = require("./operation/InstanceDeduplicate");
10
11
  const DeduplicateWriter = require("./writer/DeduplicateWriter");
@@ -19,6 +20,7 @@ const ThumbnailWriter = require("./writer/ThumbnailWriter");
19
20
  const ThumbnailService = require("./operation/ThumbnailService");
20
21
  const DeleteStudy = require("./DeleteStudy");
21
22
  const RejectInstance = require("./RejectInstance");
23
+ const JSONWriter = require("./writer/JSONWriter");
22
24
 
23
25
  function setStudyData(studyData) {
24
26
  this.studyData = studyData;
@@ -202,5 +204,24 @@ class StaticWado {
202
204
  await this.callback.completeStudy();
203
205
  Stats.OverallStats.summarize("Completed Study Processing");
204
206
  }
207
+
208
+ async reindex() {
209
+ const { directoryName } = this.options;
210
+ const studiesDir = `${directoryName}/studies/`;
211
+
212
+ console.log("Re-indexing", studiesDir);
213
+ const dirs = await fs.promises.readdir(studiesDir);
214
+ const studies = [];
215
+ for (const dir of dirs) {
216
+ const study = await JSONReader(`${studiesDir}/${dir}`, "index.json.gz", null);
217
+ if (study === null) {
218
+ console.log("No study found in", dir);
219
+ continue;
220
+ }
221
+ console.log("Adding study", dir);
222
+ studies.push(...study);
223
+ }
224
+ return JSONWriter(directoryName, "studies", studies);
225
+ }
205
226
  }
206
227
  module.exports = StaticWado;
@@ -1,41 +1,42 @@
1
- const dataDictionary = require("./dataDictionary");
2
1
  const dcmjs = require("dcmjs");
2
+ const dataDictionary = require("./dataDictionary");
3
3
 
4
- const { naturalizeDataset, denaturalizeDataset} = dcmjs.data.DicomMetaDictionary
4
+ const { naturalizeDataset, denaturalizeDataset } = dcmjs.data.DicomMetaDictionary;
5
5
 
6
6
  /** Find the actual tag for a private value */
7
7
  const findPrivate = (item, tagObject, create) => {
8
- if( typeof tagObject === "string" ) return tagObject;
9
- if( typeof tagObject === "number" ) return `00000000${tagObject.toString(16)}`.slice(-8);
10
- const {creator,tag} = tagObject;
11
- if( !creator ) return tag;
12
- const start = tag.substring(0,4);
13
- const end = tag.substring(6,8);
14
- // Should technically go all the way up, but for now only test 0x30 items
15
- let assignPosition;
16
- for(let offset = 0x10; offset < 0x40; offset++) {
17
- const testTag = `${start}00${offset.toString(16)}`
18
- const testCreator = item[testTag];
19
- if( testCreator===undefined && assignPosition===undefined ) assignPosition = offset;
20
- if( testCreator && testCreator.Value && testCreator.Value[0]===creator ) {
21
- return `${start}${offset.toString(16)}${end}`
22
- }
23
- }
24
- if( create ) {
25
- if( !assignPosition ) throw new Error(`Couldn't find any assign positions for ${creator} ${tag} in ${item}`);
26
- const creatorTag = `${start}00${assignPosition.toString(16)}`
27
- item[creatorTag] = { Value: [creator], vr: 'CS' };
28
- return `${start}${assignPosition.toString(16)}${end}`
8
+ if (typeof tagObject === "string") return tagObject;
9
+ if (typeof tagObject === "number") return `00000000${tagObject.toString(16)}`.slice(-8);
10
+ const { creator, tag } = tagObject;
11
+ if (!creator) return tag;
12
+ const start = tag.substring(0, 4);
13
+ const end = tag.substring(6, 8);
14
+ // Should technically go all the way up, but for now only test 0x30 items
15
+ let assignPosition;
16
+ for (let offset = 0x10; offset < 0x40; offset++) {
17
+ const testTag = `${start}00${offset.toString(16)}`;
18
+ const testCreator = item[testTag];
19
+ if (testCreator === undefined && assignPosition === undefined) assignPosition = offset;
20
+ if (testCreator && testCreator.Value && testCreator.Value[0] === creator) {
21
+ return `${start}${offset.toString(16)}${end}`;
29
22
  }
30
- };
23
+ }
24
+ if (create) {
25
+ if (!assignPosition) throw new Error(`Couldn't find any assign positions for ${creator} ${tag} in ${item}`);
26
+ const creatorTag = `${start}00${assignPosition.toString(16)}`;
27
+ item[creatorTag] = { Value: [creator], vr: "CS" };
28
+ return `${start}${assignPosition.toString(16)}${end}`;
29
+ }
30
+ };
31
31
 
32
32
  const DeduppedCreator = "dedupped";
33
-
33
+
34
34
  const Tags = {
35
35
  // Raw tags have the x before them, not parsed yet
36
36
  RawMinTag: "x00000000",
37
37
  RawFirstBodyTag: "x00080000",
38
38
  RawTransferSyntaxUID: "x00020010",
39
+ RawSopInstanceUID: "x00080018",
39
40
 
40
41
  // This one isn't defined in the dataDictionary
41
42
  AvailableTransferSyntaxUID: "00083002",
@@ -43,60 +44,67 @@ const Tags = {
43
44
  DeduppedCreator,
44
45
 
45
46
  // The references to extract data included in this object, 1..n values
46
- DeduppedRef: { creator: DeduppedCreator, tag: "00091010"},
47
+ DeduppedRef: { creator: DeduppedCreator, tag: "00091010" },
47
48
 
48
49
  // The hash value of THIS object
49
- DeduppedHash: {creator: DeduppedCreator, tag: "00091011"},
50
+ DeduppedHash: { creator: DeduppedCreator, tag: "00091011" },
50
51
 
51
52
  // Type of hash instance
52
- DeduppedType: {creator: DeduppedCreator, tag: "00091012"},
53
+ DeduppedType: { creator: DeduppedCreator, tag: "00091012" },
53
54
  InstanceType: "instance",
54
55
  InfoType: "info",
55
56
 
56
- naturalizeDataset, denaturalizeDataset,
57
-
57
+ naturalizeDataset,
58
+ denaturalizeDataset,
59
+
58
60
  setValue: (item, tag, value) => {
59
- const actualTag = findPrivate(item,tag,true);
61
+ const actualTag = findPrivate(item, tag, true);
60
62
  item[actualTag] = { Value: Array.isArray(value) ? value : [value] };
61
63
  return actualTag;
62
64
  },
63
65
 
64
66
  setList: (item, tag, value) => {
65
- const actualTag = findPrivate(item,tag,true);
66
- item[actualTag] = {Value: Array.isArray(value) ? value : [value]};
67
+ const actualTag = findPrivate(item, tag, true);
68
+ item[actualTag] = { Value: Array.isArray(value) ? value : [value] };
67
69
  return actualTag;
68
70
  },
69
71
 
70
72
  pushList: (item, tag, value) => {
71
- const actualTag = findPrivate(item,tag,true);
72
- if( !item[actualTag] ) item[actualTag] = { Value: [] };
73
+ const actualTag = findPrivate(item, tag, true);
74
+ if (!item[actualTag]) item[actualTag] = { Value: [] };
73
75
  item[actualTag].Value.push(value);
74
76
  return actualTag;
75
77
  },
76
78
 
77
79
  getValue: (item, tag) => {
78
- const actualTag = findPrivate(item,tag);
79
- if( !actualTag ) return undefined;
80
+ const actualTag = findPrivate(item, tag);
81
+ if (!actualTag) return undefined;
80
82
  const value = item[actualTag];
81
- if( value===undefined ) return undefined;
82
- if( Array.isArray(value) ) return value.length==1 ? value[0] : (value.length===0 ? "" : value);
83
- if( value.Value ) return value.Value.length==1 ? value.Value[0] : (value.Value.length===0 ? "" : value.Value);
83
+ if (value === undefined) return undefined;
84
+ if (Array.isArray(value)) {
85
+ if (value.length == 1) return value[0];
86
+ return value.length === 0 ? "" : value;
87
+ }
88
+ if (value.Value) {
89
+ if (value.Value.length == 1) return value.Value[0];
90
+ return value.Value.length === 0 ? "" : value.Value;
91
+ }
84
92
  return value;
85
93
  },
86
94
 
87
95
  getList: (item, tag) => {
88
- const actualTag = findPrivate(item,tag);
89
- if( !actualTag ) return undefined;
96
+ const actualTag = findPrivate(item, tag);
97
+ if (!actualTag) return undefined;
90
98
  const value = item[actualTag];
91
- if( value===undefined ) return undefined;
92
- if( Array.isArray(value) ) return value;
93
- if( value.Value ) return value.Value;
99
+ if (value === undefined) return undefined;
100
+ if (Array.isArray(value)) return value;
101
+ if (value.Value) return value.Value;
94
102
  return [value];
95
103
  },
96
104
 
97
- removeValue: (item,tag) => {
98
- const actualTag = findPrivate(item,tag);
99
- if( actualTag ) delete item[actualTag];
105
+ removeValue: (item, tag) => {
106
+ const actualTag = findPrivate(item, tag);
107
+ if (actualTag) delete item[actualTag];
100
108
  // TODO, remove creator tag if not used any longer
101
109
  },
102
110
 
@@ -0,0 +1,10 @@
1
+ const StaticWado = require("./StaticWado");
2
+ const adaptProgramOpts = require("./util/adaptProgramOpts");
3
+
4
+ module.exports = function createMain(options) {
5
+ const finalOptions = adaptProgramOpts(options, {
6
+ ...this,
7
+ });
8
+ const importer = new StaticWado(finalOptions);
9
+ return importer.reindex();
10
+ };
@@ -4,6 +4,7 @@ const createMain = require("./createMain");
4
4
  const deleteMain = require("./deleteMain");
5
5
  const rejectMain = require("./rejectMain");
6
6
  const instanceMain = require("./instanceMain");
7
+ const indexMain = require("./indexMain");
7
8
  const groupMain = require("./groupMain");
8
9
  const metadataMain = require("./metadataMain");
9
10
  const compressionOptionParser = require("./util/compressionOptionParser");
@@ -114,6 +115,11 @@ const { mkdicomwebConfig } = ConfigPoint.register({
114
115
  "deduplicated files each time a study instance UID is found, and only updates those studies\n" +
115
116
  "having at least one ",
116
117
  },
118
+ {
119
+ command: "index",
120
+ main: indexMain,
121
+ helpDescription: "Recreate the index for the DICOMweb data.",
122
+ },
117
123
  {
118
124
  command: "instance",
119
125
  arguments: ["input"],
@@ -9,9 +9,9 @@ const { PatientID, PatientName, IssuerOfPatientID } = Tags;
9
9
  const { StudyDescription, AccessionNumber, StudyInstanceUID, StudyDate, StudyTime } = Tags;
10
10
  const { SeriesDescription, SeriesNumber, SeriesInstanceUID, SeriesDate, SeriesTime } = Tags;
11
11
 
12
- const { DeduppedHash, DeduppedRef, DeduppedType, } = Tags;
12
+ const { DeduppedHash, DeduppedRef, DeduppedType } = Tags;
13
13
 
14
- const { pushList, getList, setValue, getValue } = Tags;
14
+ const { pushList, setValue, getValue } = Tags;
15
15
 
16
16
  const PatientQuery = [
17
17
  PatientID,
@@ -106,14 +106,14 @@ const ImageExtract = [
106
106
  ];
107
107
 
108
108
  const addHash = (data, type) => {
109
- const existing = getValue(data,DeduppedHash);
109
+ const existing = getValue(data, DeduppedHash);
110
110
  if (existing) {
111
111
  return existing;
112
112
  }
113
113
 
114
114
  const hashValue = hasher.hash(data);
115
- setValue(data, DeduppedHash, hashValue );
116
- setValue(data, DeduppedType, type );
115
+ setValue(data, DeduppedHash, hashValue);
116
+ setValue(data, DeduppedType, type);
117
117
  return hashValue;
118
118
  };
119
119
 
@@ -141,7 +141,7 @@ const TagSets = {
141
141
  });
142
142
  const hashValue = addHash(ret, type);
143
143
  if (hashRef) {
144
- pushList(data,DeduppedRef,hashValue);
144
+ pushList(data, DeduppedRef, hashValue);
145
145
  }
146
146
  return ret;
147
147
  },
@@ -3,7 +3,7 @@ const JSONWriter = require("../writer/JSONWriter");
3
3
  const TagLists = require("../model/TagLists");
4
4
  const Tags = require("../dictionary/Tags");
5
5
 
6
- const {getValue, setValue} = Tags;
6
+ const { getValue, setValue } = Tags;
7
7
 
8
8
  const extractors = {
9
9
  patient: TagLists.PatientQuery,
@@ -21,26 +21,26 @@ const extractors = {
21
21
  async function deduplicateSingleInstance(id, imageFrame) {
22
22
  if (!imageFrame) return {};
23
23
  const studyData = await this.completeStudy.getCurrentStudyData(this, id);
24
- const seriesUID = getValue(imageFrame,Tags.SeriesInstanceUID);
25
- const sopUID = getValue(imageFrame,Tags.SOPInstanceUID);
24
+ const seriesUID = getValue(imageFrame, Tags.SeriesInstanceUID);
25
+ const sopUID = getValue(imageFrame, Tags.SOPInstanceUID);
26
26
  if (!sopUID) {
27
27
  console.warn("No sop instance UID in", imageFrame);
28
28
  return {};
29
29
  }
30
30
  if (studyData.sopExists(sopUID)) {
31
- if( this.verbose ) console.log('SOP Instance UID', sopUID, 'already exists, skipping');
31
+ if (this.verbose) console.log("SOP Instance UID", sopUID, "already exists, skipping");
32
32
  // TODO - allow replace as an option
33
33
  // Null value means skip writing this instance
34
34
  return null;
35
35
  }
36
36
 
37
- if( this.verbose ) console.log('SOP Instance UID', sopUID, 'being added');
37
+ if (this.verbose) console.log("SOP Instance UID", sopUID, "being added");
38
38
  const deduplicated = { ...imageFrame };
39
39
 
40
40
  if (!this.extractors) this.extractors = extractors;
41
41
  for (const key of Object.keys(this.extractors)) {
42
42
  const extracted = TagLists.extract(deduplicated, key, this.extractors[key], TagLists.RemoveExtract);
43
- const hashKey = getValue(extracted,Tags.DeduppedHash);
43
+ const hashKey = getValue(extracted, Tags.DeduppedHash);
44
44
  await studyData.addExtracted(this, hashKey, extracted);
45
45
  }
46
46
 
@@ -6,11 +6,10 @@ const Tags = require("../dictionary/Tags");
6
6
  const TagLists = require("../model/TagLists");
7
7
  const JSONWriter = require("../writer/JSONWriter");
8
8
 
9
- const {getValue, setValue, getList, setList} = Tags;
9
+ const { getValue, setValue, getList, setList } = Tags;
10
10
  const hasher = hashFactory();
11
11
 
12
- const getSeriesInstanceUid = (seriesInstance) =>
13
- getValue(seriesInstance,Tags.SeriesInstanceUID);
12
+ const getSeriesInstanceUid = (seriesInstance) => getValue(seriesInstance, Tags.SeriesInstanceUID);
14
13
 
15
14
  /**
16
15
  * StudyData contains information about the grouped study data. It is used to create
@@ -88,10 +87,10 @@ class StudyData {
88
87
  return true;
89
88
  }
90
89
  const info = deduplicatedTopFile[0];
91
- if (!info || getValue(info,Tags.DeduppedHash) || getValue(info,Tags.DeduppedType) != "info") {
90
+ if (!info || getValue(info, Tags.DeduppedHash) || getValue(info, Tags.DeduppedType) != "info") {
92
91
  return true;
93
92
  }
94
- const hashValue = getValue(info,Tags.DeduppedHash);
93
+ const hashValue = getValue(info, Tags.DeduppedHash);
95
94
  return this.existingFiles[0].indexOf(hashValue) == -1;
96
95
  } catch (e) {
97
96
  console.log("Assume study metadata is dirty", e);
@@ -105,12 +104,12 @@ class StudyData {
105
104
  this.newInstancesAdded += 1;
106
105
  for (let i = 0; i < this.deduplicated.length; i++) {
107
106
  const recombined = await this.recombine(i);
108
- const reSeriesUid = getValue(recombined,Tags.SeriesInstanceUID);
107
+ const reSeriesUid = getValue(recombined, Tags.SeriesInstanceUID);
109
108
  if (reSeriesUid !== seriesInstanceUid) continue;
110
- const reSop = getValue(recombined,Tags.SOPInstanceUID);
109
+ const reSop = getValue(recombined, Tags.SOPInstanceUID);
111
110
  if (!reSop) continue;
112
111
  if (reSop !== sopInstanceUid) continue;
113
- setValue(this.deduplicated[i], Tags.DeduppedType,"deleted");
112
+ setValue(this.deduplicated[i], Tags.DeduppedType, "deleted");
114
113
  }
115
114
  }
116
115
 
@@ -150,7 +149,7 @@ class StudyData {
150
149
  if (index < 0 || index >= this.deduplicated.length) {
151
150
  throw new Error(`Can't read index ${index}, out of bounds [0..${this.deduplicated.length})`);
152
151
  }
153
- const refs = getList(deduplicated,Tags.DeduppedRef);
152
+ const refs = getList(deduplicated, Tags.DeduppedRef);
154
153
  if (!refs) {
155
154
  console.log("No refs for", deduplicated);
156
155
  return deduplicated;
@@ -165,7 +164,7 @@ class StudyData {
165
164
 
166
165
  async addExtracted(callback, hashKey, item) {
167
166
  if (this.extractData[hashKey]) {
168
- if( this.verbose ) console.log("Already have extracted", hashKey, getValue(item,Tags.DeduppedType));
167
+ if (this.verbose) console.log("Already have extracted", hashKey, getValue(item, Tags.DeduppedType));
169
168
  return;
170
169
  }
171
170
  await callback.bulkdata(this, hashKey, item);
@@ -192,7 +191,7 @@ class StudyData {
192
191
  // console.log('Not adding', hashValue, 'because the hash exists');
193
192
  return false;
194
193
  }
195
- const sopValue = getValue(data,Tags.SOPInstanceUID);
194
+ const sopValue = getValue(data, Tags.SOPInstanceUID);
196
195
  const sopIndex = this.sopInstances[sopValue];
197
196
  if (!sopValue) {
198
197
  console.warn("No sop value in", filename, "reading", data);
@@ -275,14 +274,14 @@ class StudyData {
275
274
  if (type == Tags.InstanceType) {
276
275
  this.internalAddDeduplicated(item, name);
277
276
  } else if (type == "info") {
278
- const refs = getList(item,Tags.DeduppedRef);
277
+ const refs = getList(item, Tags.DeduppedRef);
279
278
  if (refs) {
280
279
  refs.forEach((hashValue) => {
281
280
  this.readHashes[hashValue] = `${hashValue}.gz`;
282
281
  });
283
282
  }
284
283
  } else {
285
- const hashValue = getValue(item,Tags.DeduppedHash);
284
+ const hashValue = getValue(item, Tags.DeduppedHash);
286
285
  if (hashValue) {
287
286
  this.extractData[hashValue] = item;
288
287
  }
@@ -299,7 +298,7 @@ class StudyData {
299
298
 
300
299
  for (let i = 0; i < this.numberOfInstances; i++) {
301
300
  const seriesInstance = await this.recombine(i);
302
- const type = getValue(seriesInstance,Tags.DeduppedType);
301
+ const type = getValue(seriesInstance, Tags.DeduppedType);
303
302
  if (type == "deleted") {
304
303
  console.log("Skipping", type);
305
304
  continue;
@@ -337,7 +336,7 @@ class StudyData {
337
336
  numberOfInstances += instances.length;
338
337
  numberOfSeries += 1;
339
338
  seriesList.push(seriesQuery);
340
- const modality = getValue(seriesQuery,Tags.Modality);
339
+ const modality = getValue(seriesQuery, Tags.Modality);
341
340
  if (modalitiesInStudy.indexOf(modality) == -1) modalitiesInStudy.push(modality);
342
341
  await JSONWriter(seriesPath, "metadata", instances, {
343
342
  gzip: true,
@@ -379,8 +378,8 @@ class StudyData {
379
378
  createInfo() {
380
379
  const data = {};
381
380
  const hashValue = hasher.hash(this.deduplicated);
382
- setValue(data,Tags.DeduppedHash,hashValue);
383
- setValue(data,Tags.DeduppedType,"info");
381
+ setValue(data, Tags.DeduppedHash, hashValue);
382
+ setValue(data, Tags.DeduppedType, "info");
384
383
  return data;
385
384
  }
386
385
 
@@ -393,7 +392,7 @@ class StudyData {
393
392
  /** Writes the deduplicated group */
394
393
  async writeDeduplicatedGroup() {
395
394
  const data = this.createInfo();
396
- const hashValue = getValue(data,Tags.DeduppedHash);
395
+ const hashValue = getValue(data, Tags.DeduppedHash);
397
396
  console.log(
398
397
  "Writing deduplicated hash data set data with",
399
398
  Object.values(this.extractData).length,
@@ -401,8 +400,11 @@ class StudyData {
401
400
  this.deduplicated.length,
402
401
  "instance items"
403
402
  );
404
- setList(data,Tags.DeduppedRef,
405
- Object.keys(this.readHashes).filter(() => this.deduplicatedHashes[hashValue] == undefined));
403
+ setList(
404
+ data,
405
+ Tags.DeduppedRef,
406
+ Object.keys(this.readHashes).filter(() => this.deduplicatedHashes[hashValue] == undefined)
407
+ );
406
408
  const deduplicatedList = [data, ...Object.values(this.extractData), ...this.deduplicated];
407
409
  // const naturalList = deduplicatedList.map(Tags.naturalizeDataset);
408
410
  // // console.log("naturalList=", JSON.stringify(naturalList,null,2));
@@ -15,7 +15,7 @@ const transcodeOp = {
15
15
  const transcodeDestinationMap = {
16
16
  lei: {
17
17
  transferSyntaxUid: "1.2.840.10008.1.2.1",
18
- transcodeOp: transcodeOp.none
18
+ transcodeOp: transcodeOp.none,
19
19
  },
20
20
  jls: {
21
21
  transferSyntaxUid: "1.2.840.10008.1.2.4.80",
@@ -71,9 +71,9 @@ const transcodeSourceMap = {
71
71
  };
72
72
 
73
73
  /**
74
- * Get an existing destination transcoder from destination map.
74
+ * Get an existing destination transcoder from destination map.
75
75
  *
76
- * @param {*} id Destination type to compress to
76
+ * @param {*} id Destination type to compress to
77
77
  * @returns A partial transcoder definition. Otherwise it returns undefined.
78
78
  */
79
79
  function getDestinationTranscoder(id) {
@@ -99,7 +99,7 @@ function getTranscoder(transferSyntaxUid, { contentType, verbose }) {
99
99
  if (!sourceTranscoder || !destinationTranscoder) {
100
100
  return undefined;
101
101
  }
102
-
102
+
103
103
  return {
104
104
  transferSyntaxUid: destinationTranscoder.transferSyntaxUid,
105
105
  transcodeOp: sourceTranscoder.transcodeOp | destinationTranscoder.transcodeOp, // eslint-disable-line no-bitwise
@@ -107,7 +107,6 @@ function getTranscoder(transferSyntaxUid, { contentType, verbose }) {
107
107
  };
108
108
  }
109
109
 
110
-
111
110
  /**
112
111
  * Tell whether given id contain transferSyntaxUid which can be transcoded or not.
113
112
  * @param {*} id object containing transferSyntaxUid
@@ -289,7 +288,7 @@ function transcodeMetadata(metadata, id, options) {
289
288
  const result = { ...metadata };
290
289
 
291
290
  if (result[Tags.AvailableTransferSyntaxUID]) {
292
- Tags.setValue(result,Tags.AvailableTransferSyntaxUID, transcodedId.transferSyntaxUid);
291
+ Tags.setValue(result, Tags.AvailableTransferSyntaxUID, transcodedId.transferSyntaxUid);
293
292
  }
294
293
 
295
294
  return result;
@@ -1,13 +1,13 @@
1
1
  const { program } = require("@radicalimaging/static-wado-util");
2
2
  const { getDestinationTranscoder } = require("../operation/adapter/transcodeImage");
3
3
 
4
- module.exports = function compressionOptionParser(value) {
4
+ module.exports = function compressionOptionParser(value) {
5
5
  const destination = getDestinationTranscoder(value);
6
6
  if (destination) {
7
7
  console.log("Found destination transferSyntax ", destination.transferSyntaxUid, "for ", value);
8
8
  } else {
9
9
  console.log("No transcoder destination for ", value);
10
10
  throw new program.InvalidArgumentError(`No transcoder destination for ${value}`);
11
- }
11
+ }
12
12
  return destination.transferSyntaxUid;
13
- }
13
+ };
@@ -47,12 +47,12 @@ const CompleteStudyWriter = (options) => {
47
47
  const studyQuery = await studyData.writeMetadata();
48
48
 
49
49
  const allStudies = await JSONReader(options.directoryName, "studies/index.json.gz", []);
50
- const studyUID = Tags.getValue(studyQuery,Tags.StudyInstanceUID);
50
+ const studyUID = Tags.getValue(studyQuery, Tags.StudyInstanceUID);
51
51
  if (!studyUID) {
52
52
  console.error("studyQuery=", studyQuery);
53
53
  throw new Error("Study query has null studyUID");
54
54
  }
55
- const studyIndex = allStudies.findIndex((item) => Tags.getValue(item,Tags.StudyInstanceUID) == studyUID);
55
+ const studyIndex = allStudies.findIndex((item) => Tags.getValue(item, Tags.StudyInstanceUID) == studyUID);
56
56
  if (studyIndex == -1) {
57
57
  allStudies.push(studyQuery);
58
58
  } else {
@@ -47,7 +47,7 @@ HashDataWriter.createHashPath = (data, options = {}) => {
47
47
  const { mimeType } = options;
48
48
  const isRaw = ArrayBuffer.isView(data);
49
49
  const extension = isRaw ? (mimeType && extensions[mimeType]) || "" : ".json";
50
- const hashValue = Tags.getValue(data,Tags.DeduppedHash) || hasher.hash(data);
50
+ const hashValue = Tags.getValue(data, Tags.DeduppedHash) || hasher.hash(data);
51
51
 
52
52
  return {
53
53
  // Use string concat as this value is used for the BulkDataURI which needs forward slashes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radicalimaging/static-wado-creator",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Library to convert DICOMP10 to DICOMweb format. Original upstream: https://github.com/chafey/dicomp10-to-dicomweb-js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -53,8 +53,8 @@
53
53
  "build": "echo \"No build yet\" && exit 0",
54
54
  "link:exec": "npm link",
55
55
  "lint": "npx eslint --color \"*(bin|lib)/**/*.{js,mjs}\"",
56
- "lint:fix": "npx eslint --fix --color \"*(bin|lib)/**/*.{js,mjs}\""
57
- },
56
+ "lint:fix": "npx eslint --fix --color \"*(bin|lib)/**/*.{js,mjs}\""
57
+ },
58
58
  "jest": {
59
59
  "verbose": true
60
60
  },
@@ -63,11 +63,12 @@
63
63
  "@radicalimaging/static-cs-lite": "^0.0.2",
64
64
  "@radicalimaging/static-wado-util": "^0.6.2",
65
65
  "canvas": "^2.9.1",
66
- "config-point": "^0.5.0",
66
+ "config-point": "0.5.1",
67
+ "dcmjs": "^0.27.0",
67
68
  "dicom-parser": "^1.8.13",
68
69
  "glob": "^7.2.0",
69
- "uuid": "^8.3.2",
70
- "node-object-hash": "^2.3.10"
70
+ "node-object-hash": "^2.3.10",
71
+ "uuid": "^8.3.2"
71
72
  },
72
73
  "devDependencies": {
73
74
  "must": "^0.13.4"
@@ -1,112 +0,0 @@
1
- const { Stats } = require("@radicalimaging/static-wado-util");
2
- /* eslint "no-param-reassign": "off" */
3
-
4
- const handler = {
5
- get(obj, key) {
6
- const ikey = parseInt(key);
7
- if (ikey == key) return obj.index_get(ikey);
8
- const handlerFunc = handler[key];
9
- if (handlerFunc && key != "get") return handlerFunc(obj, key);
10
- if (!obj._keys[key]) {
11
- console.log("New call to", key);
12
- obj._keys[key] = true;
13
- }
14
- return obj[key];
15
- },
16
-
17
- length: (obj) => obj.combinedLength,
18
- };
19
-
20
- const StreamingFunctions = {
21
- addChunks(chunks) {
22
- if (!this.chunks) this.chunks = [];
23
- chunks.forEach((chunk) => this.chunks.push(chunk));
24
- this.combinedLength = 0;
25
- let i = 0;
26
- this.chunks.forEach((chunk) => {
27
- chunk.start = this.combinedLength;
28
- chunk.i = i;
29
- i += 1;
30
- this.combinedLength += chunk.length;
31
- });
32
- this.lastChunk = this.chunks[0];
33
- },
34
-
35
- index_get(ikey) {
36
- const found = this.findChunk(ikey);
37
- if (!found) throw Error(`index ${ikey} not found between 0..${this.combinedLength}`);
38
- return found[ikey - found.start];
39
- },
40
-
41
- findChunk(ikey) {
42
- let i = (this.lastChunk.start <= ikey && this.lastChunk.i) || 0;
43
- while (i < this.chunks.length) {
44
- const chunk = this.chunks[i];
45
- if (ikey >= chunk.start && ikey < chunk.start + chunk.length) {
46
- this.lastChunk = chunk;
47
- return chunk;
48
- }
49
- i += 1;
50
- }
51
- return undefined;
52
- },
53
-
54
- slice(start, end) {
55
- const buflen = end - start;
56
- const ret = Buffer.alloc(buflen);
57
- let i = 0;
58
- while (i < buflen) {
59
- const chunk = this.findChunk(start + i);
60
- const chunkI = start + i - chunk.start;
61
- const useLen = Math.min(buflen, chunk.length - chunkI);
62
- chunk.copy(ret, i, chunkI, chunkI + useLen);
63
- i += useLen;
64
- }
65
- return ret;
66
- },
67
-
68
- hexSlice(start, end) {
69
- return this.slice(start, end).hexSlice();
70
- },
71
-
72
- /** The internal node copy function is a native that directly accesses internal class details, so over-ride it.
73
- * TODO: Make this efficient by using the internal copy function when available rather than copy one at a time.
74
- */
75
- copy(target, targetStart = 0, srcStart = 0, srcEnd = 0) {
76
- const { length } = target;
77
- const srcLength = (srcEnd === undefined && Math.min(this.length, srcEnd)) || this.length;
78
- const copied = 0;
79
- while (targetStart < length && srcStart < srcLength) {
80
- target[targetStart] = this[srcStart];
81
- targetStart += 1;
82
- srcStart += 1;
83
- }
84
- return copied;
85
- },
86
-
87
- _keys: { then: true, lastChunk: true, chunks: true },
88
- };
89
-
90
- Object.keys(StreamingFunctions).forEach((key) => {
91
- StreamingFunctions._keys[key] = true;
92
- });
93
-
94
- const StreamingBuffer = (chunks) => {
95
- const buf = Buffer.from("NotUsed");
96
- Object.assign(buf, StreamingFunctions);
97
- buf.addChunks(chunks);
98
- return new Proxy(buf, handler);
99
- };
100
-
101
- const asyncIteratorToBuffer = async (readable) => {
102
- if (ArrayBuffer.isView(readable)) return readable;
103
- const chunks = [];
104
- for await (const chunk of readable) {
105
- chunks.push(chunk);
106
- Stats.BufferStats.add("Read Async", `Read async buffer ${chunks.length}`, 1024);
107
- }
108
- Stats.BufferStats.reset();
109
- return StreamingBuffer(chunks);
110
- };
111
-
112
- module.exports = asyncIteratorToBuffer;