larvitar 0.20.0 → 1.2.2

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 (45) hide show
  1. package/.github/workflows/build-docs.yml +1 -1
  2. package/.github/workflows/deploy.yml +2 -11
  3. package/MIGRATION.md +25 -0
  4. package/README.md +28 -27
  5. package/imaging/dataDictionary.json +21865 -21865
  6. package/imaging/{image_anonymization.js → imageAnonymization.js} +1 -1
  7. package/imaging/{image_colormaps.js → imageColormaps.js} +2 -2
  8. package/imaging/{image_contours.js → imageContours.js} +1 -2
  9. package/imaging/{image_io.js → imageIo.js} +18 -15
  10. package/imaging/{image_layers.js → imageLayers.js} +2 -2
  11. package/imaging/{image_loading.js → imageLoading.js} +9 -6
  12. package/imaging/imageParsing.js +301 -0
  13. package/imaging/{image_presets.js → imagePresets.js} +2 -2
  14. package/imaging/{image_rendering.js → imageRendering.js} +36 -32
  15. package/imaging/imageReslice.js +78 -0
  16. package/imaging/{image_store.js → imageStore.js} +24 -7
  17. package/imaging/{image_tools.js → imageTools.js} +15 -23
  18. package/imaging/{image_utils.js → imageUtils.js} +1 -1
  19. package/imaging/loaders/commonLoader.js +1 -1
  20. package/imaging/loaders/dicomLoader.js +1 -1
  21. package/imaging/loaders/fileLoader.js +2 -2
  22. package/imaging/loaders/multiframeLoader.js +6 -2
  23. package/imaging/loaders/nrrdLoader.js +11 -7
  24. package/imaging/tools/{contourTool.js → custom/contourTool.js} +25 -20
  25. package/imaging/tools/{diameterTool.js → custom/diameterTool.js} +9 -3
  26. package/imaging/tools/{editMaskTool.js → custom/editMaskTool.js} +7 -1
  27. package/imaging/tools/{polylineScissorsTool.js → custom/polylineScissorsTool.js} +12 -5
  28. package/imaging/tools/{seedTool.js → custom/seedTool.js} +3 -3
  29. package/imaging/tools/{thresholdsBrushTool.js → custom/thresholdsBrushTool.js} +7 -1
  30. package/imaging/tools/{tools.default.js → default.js} +9 -2
  31. package/imaging/tools/{tools.interaction.js → interaction.js} +13 -6
  32. package/imaging/tools/{tools.io.js → io.js} +15 -6
  33. package/imaging/tools/{tools.main.js → main.js} +14 -13
  34. package/imaging/tools/polygonSegmentationMixin.js +8 -4
  35. package/imaging/tools/{tools.segmentation.js → segmentation.js} +171 -58
  36. package/imaging/tools/segmentations.md +38 -0
  37. package/imaging/tools/setLabelMap3D.js +248 -0
  38. package/imaging/tools/{tools.state.js → state.js} +7 -1
  39. package/imaging/tools/strategies/eraseFreehand.js +8 -9
  40. package/imaging/tools/strategies/fillFreehand.js +8 -9
  41. package/index.js +41 -39
  42. package/modules/vuex/larvitar.js +2 -1
  43. package/package.json +11 -8
  44. package/imaging/image_parsing.js +0 -307
  45. package/imaging/image_reslice.js +0 -80
package/index.js CHANGED
@@ -5,6 +5,7 @@ console.log(`LARVITAR v${VERSION}`);
5
5
  import cornerstone from "cornerstone-core";
6
6
  import cornerstoneTools from "cornerstone-tools";
7
7
  import cornerstoneWADOImageLoader from "cornerstone-wado-image-loader";
8
+ const segModule = cornerstoneTools.getModule("segmentation");
8
9
 
9
10
  import larvitarModule from "./modules/vuex/larvitar";
10
11
 
@@ -14,15 +15,15 @@ import {
14
15
  getAvailableMemory
15
16
  } from "./imaging/monitors/memory";
16
17
 
17
- import { initLarvitarStore, larvitar_store } from "./imaging/image_store";
18
+ import { initLarvitarStore, larvitar_store } from "./imaging/imageStore";
18
19
 
19
- import { parseContours } from "./imaging/image_contours";
20
+ import { parseContours } from "./imaging/imageContours";
20
21
 
21
22
  import {
22
23
  getImagePresets,
23
24
  setImagePreset,
24
25
  setImageCustomPreset
25
- } from "./imaging/image_presets";
26
+ } from "./imaging/imagePresets";
26
27
 
27
28
  import {
28
29
  getNormalOrientation,
@@ -37,7 +38,7 @@ import {
37
38
  getReslicedMetadata,
38
39
  getReslicedPixeldata,
39
40
  getDistanceBetweenSlices
40
- } from "./imaging/image_utils";
41
+ } from "./imaging/imageUtils";
41
42
 
42
43
  import {
43
44
  buildHeader,
@@ -45,16 +46,16 @@ import {
45
46
  buildData,
46
47
  buildDataAsync,
47
48
  importNRRDImage
48
- } from "./imaging/image_io";
49
+ } from "./imaging/imageIo";
49
50
 
50
- import { anonymize, encrypt } from "./imaging/image_anonymization";
51
+ import { anonymize, encrypt } from "./imaging/imageAnonymization";
51
52
 
52
53
  import {
53
54
  buildLayer,
54
55
  updateLayer,
55
56
  getActiveLayer,
56
57
  setActiveLayer
57
- } from "./imaging/image_layers";
58
+ } from "./imaging/imageLayers";
58
59
 
59
60
  import {
60
61
  initializeImageLoader,
@@ -64,14 +65,14 @@ import {
64
65
  registerResliceLoader,
65
66
  registerMultiFrameImageLoader,
66
67
  updateLoadedStack
67
- } from "./imaging/image_loading";
68
+ } from "./imaging/imageLoading";
68
69
 
69
70
  import {
70
71
  readFile,
71
72
  readFiles,
72
- dumpDataSet,
73
+ parseDataSet,
73
74
  clearImageParsing
74
- } from "./imaging/image_parsing";
75
+ } from "./imaging/imageParsing";
75
76
 
76
77
  import {
77
78
  clearImageCache,
@@ -91,9 +92,9 @@ import {
91
92
  flipImageVertical,
92
93
  rotateImageLeft,
93
94
  rotateImageRight
94
- } from "./imaging/image_rendering";
95
+ } from "./imaging/imageRendering";
95
96
 
96
- import { resliceSeries } from "./imaging/image_reslice";
97
+ import { resliceSeries } from "./imaging/imageReslice";
97
98
 
98
99
  import {
99
100
  addDiameterTool,
@@ -111,7 +112,7 @@ import {
111
112
  syncToolStack,
112
113
  updateStackToolState,
113
114
  setSegmentationConfig
114
- } from "./imaging/image_tools";
115
+ } from "./imaging/imageTools";
115
116
 
116
117
  import {
117
118
  csToolsCreateStack,
@@ -126,13 +127,13 @@ import {
126
127
  setToolEnabled,
127
128
  setToolPassive,
128
129
  exportAnnotations
129
- } from "./imaging/tools/tools.main";
130
+ } from "./imaging/tools/main";
130
131
 
131
132
  import {
132
133
  DEFAULT_TOOLS,
133
134
  getDefaultToolsByType,
134
135
  setDefaultToolsProps
135
- } from "./imaging/tools/tools.default";
136
+ } from "./imaging/tools/default";
136
137
 
137
138
  import {
138
139
  initSegmentationModule,
@@ -142,7 +143,7 @@ import {
142
143
  undoLastStroke,
143
144
  redoLastStroke,
144
145
  setBrushProps
145
- } from "./imaging/tools/tools.segmentation";
146
+ } from "./imaging/tools/segmentation";
146
147
 
147
148
  import {
148
149
  updateLarvitarManager,
@@ -189,20 +190,21 @@ import {
189
190
  addColorMap,
190
191
  fillPixelData,
191
192
  HSVToRGB
192
- } from "./imaging/image_colormaps";
193
+ } from "./imaging/imageColormaps";
193
194
 
194
- import { saveAnnotations, loadAnnotations } from "./imaging/tools/tools.io";
195
+ import { saveAnnotations, loadAnnotations } from "./imaging/tools/io";
195
196
 
196
197
  import {
197
198
  addMouseKeyHandlers,
198
199
  toggleMouseToolsListeners
199
- } from "./imaging/tools/tools.interaction";
200
+ } from "./imaging/tools/interaction";
200
201
 
201
202
  export {
202
203
  VERSION,
203
204
  // global cornerstone variables
204
205
  cornerstone,
205
206
  cornerstoneTools,
207
+ segModule,
206
208
  cornerstoneWADOImageLoader,
207
209
  // vuex module
208
210
  larvitarModule,
@@ -210,14 +212,14 @@ export {
210
212
  checkMemoryAllocation,
211
213
  getUsedMemory,
212
214
  getAvailableMemory,
213
- // larvitar store
215
+ // larvitarStore
214
216
  initLarvitarStore,
215
217
  larvitar_store,
216
- // image_presets
218
+ // imagePresets
217
219
  getImagePresets,
218
220
  setImagePreset,
219
221
  setImageCustomPreset,
220
- // image_utils
222
+ // imageUtils
221
223
  getNormalOrientation,
222
224
  getMinPixelValue,
223
225
  getMaxPixelValue,
@@ -230,21 +232,21 @@ export {
230
232
  getReslicedMetadata,
231
233
  getReslicedPixeldata,
232
234
  getDistanceBetweenSlices,
233
- // image_io
235
+ // imageIo
234
236
  buildHeader,
235
237
  getCachedPixelData,
236
238
  buildData,
237
239
  buildDataAsync,
238
240
  importNRRDImage,
239
- // image_anonymization
241
+ // imageAnonymization
240
242
  anonymize,
241
243
  encrypt,
242
- // image_layers
244
+ // imageLayers
243
245
  buildLayer,
244
246
  updateLayer,
245
247
  getActiveLayer,
246
248
  setActiveLayer,
247
- // image_loading
249
+ // imageLoading
248
250
  initializeImageLoader,
249
251
  initializeWebImageLoader,
250
252
  initializeFileImageLoader,
@@ -252,12 +254,12 @@ export {
252
254
  registerResliceLoader,
253
255
  registerMultiFrameImageLoader,
254
256
  updateLoadedStack,
255
- // image_parsing
257
+ // imageParsing
256
258
  readFile,
257
259
  readFiles,
258
- dumpDataSet,
260
+ parseDataSet,
259
261
  clearImageParsing,
260
- // image_rendering
262
+ // imageRendering
261
263
  clearImageCache,
262
264
  loadAndCacheImages,
263
265
  renderFileImage,
@@ -276,15 +278,15 @@ export {
276
278
  flipImageVertical,
277
279
  rotateImageLeft,
278
280
  rotateImageRight,
279
- // image_reslice
281
+ // imageReslice
280
282
  resliceSeries,
281
- // image_colormaps
283
+ // imageColormaps
282
284
  getColormapsList,
283
285
  applyColorMap,
284
286
  addColorMap,
285
287
  fillPixelData,
286
288
  HSVToRGB,
287
- // image_contours
289
+ // imageContours
288
290
  parseContours,
289
291
  // loaders/commonLoader
290
292
  updateLarvitarManager,
@@ -307,7 +309,7 @@ export {
307
309
  // loaders/dicomLoader
308
310
  getDicomImageId,
309
311
  cacheImages,
310
- // loaders/multiFrameLoader
312
+ // loaders/multiframeLoader
311
313
  loadMultiFrameImage,
312
314
  buildMultiFrameImage,
313
315
  getMultiFrameImageId,
@@ -318,7 +320,7 @@ export {
318
320
  resetFileManager,
319
321
  populateFileManager,
320
322
  getFileImageId,
321
- // image_tools
323
+ // imageTools
322
324
  addDiameterTool,
323
325
  addContoursTool,
324
326
  addMaskEditingTool,
@@ -334,7 +336,7 @@ export {
334
336
  syncToolStack,
335
337
  updateStackToolState,
336
338
  setSegmentationConfig,
337
- // tools.main
339
+ // tools/main
338
340
  csToolsCreateStack,
339
341
  csToolsUpdateImageIds,
340
342
  csToolsUpdateImageIndex,
@@ -347,16 +349,16 @@ export {
347
349
  setToolEnabled,
348
350
  setToolPassive,
349
351
  exportAnnotations,
350
- // tools.default
352
+ // tools/default
351
353
  DEFAULT_TOOLS,
352
354
  getDefaultToolsByType,
353
355
  setDefaultToolsProps,
354
- // tools.io
356
+ // tools/io
355
357
  saveAnnotations,
356
358
  loadAnnotations,
357
- // tools.interaction
359
+ // tools/interaction
358
360
  addMouseKeyHandlers,
359
- // tools.segmentation
361
+ // tools/segmentation
360
362
  initSegmentationModule,
361
363
  addSegmentationMask,
362
364
  setActiveLabelmap,
@@ -1,4 +1,4 @@
1
- // Larvitare storage
1
+ // Larvitar Vuex storage
2
2
 
3
3
  import Vue from "vue";
4
4
 
@@ -99,6 +99,7 @@ export default {
99
99
  },
100
100
  removeSeriesIds: ({ state }, seriesId) =>
101
101
  Vue.delete(state.series, seriesId),
102
+ resetSeriesIds: ({ state }) => Vue.set(state.series, {}),
102
103
  setErrorLog: () => {}, // TODO LT pass elementId
103
104
 
104
105
  // Series fields setters
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "larvitar",
3
3
  "keywords": [
4
- "dicom",
5
- "imaging"
4
+ "DICOM",
5
+ "imaging",
6
+ "medical",
7
+ "cornerstone"
6
8
  ],
7
- "version": "0.20.0",
8
- "description": "javascript library for loading, rendering and interact with DICOM images",
9
+ "version": "1.2.2",
10
+ "description": "javascript library for parsing, loading, rendering and interacting with DICOM images",
9
11
  "repository": {
10
12
  "url": "https://github.com/dvisionlab/Larvitar.git",
11
13
  "type": "git"
@@ -18,15 +20,16 @@
18
20
  "author": "Simone Manini <simone.manini@dvisionlab.com> (https://www.dvisionlab.com)",
19
21
  "contributors": [
20
22
  "Mattia Ronzoni <mattia.ronzoni@dvisionlab.com> (https://www.dvisionlab.com)",
21
- "Sara Zanchi <sara.zanchi@dvisionlab.com> (https://www.dvisionlab.com)"
23
+ "Sara Zanchi <sara.zanchi@dvisionlab.com> (https://www.dvisionlab.com)",
24
+ "Ale Re <ale.re@dvisionlab.com> (https://www.dvisionlab.com)"
22
25
  ],
23
26
  "license": "MIT",
24
27
  "dependencies": {
25
28
  "@rollup/plugin-commonjs": "^17.1.0",
26
- "cornerstone-core": "^2.6.0",
29
+ "cornerstone-core": "^2.6.1",
27
30
  "cornerstone-file-image-loader": "^0.3.0",
28
- "cornerstone-tools": "^5.3.0",
29
- "cornerstone-wado-image-loader": "^3.3.2",
31
+ "cornerstone-tools": "^6.0.6",
32
+ "cornerstone-wado-image-loader": "^4.0.1",
30
33
  "cornerstone-web-image-loader": "^2.1.1",
31
34
  "crypto-js": "^4.1.1",
32
35
  "dicom-character-set": "^1.0.3",
@@ -1,307 +0,0 @@
1
- /** @module imaging/parsing
2
- * @desc This file provides functionalities for parsing DICOM image files
3
- */
4
-
5
- // external libraries
6
- import { parseDicom } from "dicom-parser";
7
- import { forEach, each, has, pick } from "lodash";
8
-
9
- // internal libraries
10
- import { getPixelRepresentation, randomId, parseTag } from "./image_utils.js";
11
- import { updateLoadedStack } from "./image_loading.js";
12
- import { checkMemoryAllocation } from "./monitors/memory.js";
13
-
14
- // global module variables
15
- var parsingQueueFlag = null; // flag to handle the queue
16
- var t0 = null; // t0 variable for timing debugging purpose
17
-
18
- /*
19
- * This module provides the following functions to be exported:
20
- * readFiles(fileList, callback)
21
- * readFile(file, callback)
22
- * dumpDataSet(dataSet, metadata, customFilter)
23
- * clearImageParsing(seriesStack)
24
- */
25
-
26
- /**
27
- * Reset series stack object and its internal data
28
- * @instance
29
- * @function clearImageParsing
30
- * @param {Object} seriesStack - Parsed series stack object
31
- */
32
- export const clearImageParsing = function (seriesStack) {
33
- each(seriesStack, function (stack) {
34
- each(stack.instances, function (instance) {
35
- if (instance.dataSet) {
36
- instance.dataSet.byteArray = null;
37
- }
38
- instance.dataSet = null;
39
- instance.file = null;
40
- instance.metadata = null;
41
- });
42
- });
43
- seriesStack = null;
44
- };
45
-
46
- /**
47
- * Read dicom files and return allSeriesStack object
48
- * @instance
49
- * @function readFiles
50
- * @param {Array} entries - List of file objects
51
- * @param {Function} callback - Will receive (imageObject, errorString) as args
52
- */
53
- export const readFiles = function (entries, callback) {
54
- let allSeriesStack = {};
55
- let parsingQueue = [];
56
- dumpFiles(entries, parsingQueue, allSeriesStack, callback);
57
- };
58
-
59
- /**
60
- * Read a single dicom file and return parsed object
61
- * @instance
62
- * @function readFile
63
- * @param {File} entry - File object
64
- * @param {Function} callback - Will receive (imageObject, errorString) as args
65
- */
66
- export const readFile = function (entry, callback) {
67
- dumpFile(entry, callback);
68
- };
69
-
70
- /* Internal module functions */
71
-
72
- /**
73
- * Dump metadata from dicom parser dataSet object
74
- * @instance
75
- * @function dumpDataSet
76
- * @param {Object} dataSet - dicom parser dataSet object
77
- * @param {Array} metadata - Initialized metadata object
78
- * @param {Array} customFilter - Optional filter: {tags:[], frameId: 0}
79
- */
80
- // This function iterates through dataSet recursively and adds new HTML strings
81
- // to the output array passed into it
82
- export const dumpDataSet = function (dataSet, metadata, customFilter) {
83
- // customFilter= {tags:[], frameId:xxx}
84
- // the dataSet.elements object contains properties for each element parsed. The name of the property
85
- // is based on the elements tag and looks like 'xGGGGEEEE' where GGGG is the group number and EEEE is the
86
- // element number both with lowercase hexadecimal letters. For example, the Series Description DICOM element 0008,103E would
87
- // be named 'x0008103e'. Here we iterate over each property (element) so we can build a string describing its
88
- // contents to add to the output array
89
- try {
90
- let elements =
91
- customFilter && has(customFilter, "tags")
92
- ? pick(dataSet.elements, customFilter.tags)
93
- : dataSet.elements;
94
- for (let propertyName in elements) {
95
- let element = elements[propertyName];
96
- // Here we check for Sequence items and iterate over them if present. items will not be set in the
97
- // element object for elements that don't have SQ VR type. Note that implicit little endian
98
- // sequences will are currently not parsed.
99
- if (element.items) {
100
- // each item contains its own data set so we iterate over the items
101
- // and recursively call this function
102
- if (customFilter && has(customFilter, "frameId")) {
103
- let item = element.items[customFilter.frameId];
104
- dumpDataSet(item.dataSet, metadata);
105
- } else {
106
- element.items.forEach(function (item) {
107
- dumpDataSet(item.dataSet, metadata);
108
- });
109
- }
110
- } else {
111
- let tagValue = parseTag(dataSet, propertyName, element);
112
- metadata[propertyName] = tagValue;
113
- }
114
- }
115
- } catch (err) {
116
- console.log(err);
117
- }
118
- };
119
-
120
- /**
121
- * Manage the parsing process waiting for the parsed object before proceeding with the next parse request
122
- * @inner
123
- * @function parseNextFile
124
- * @param {Array} parsingQueue - Array of queued files to be parsed
125
- * @param {Object} allSeriesStack - Series stack object to be populated
126
- * @param {Function} callback - Passed through
127
- */
128
- let parseNextFile = function (parsingQueue, allSeriesStack, callback) {
129
- // initialize t0 on first file of the queue
130
- if (
131
- Object.keys(allSeriesStack).length === 0 &&
132
- allSeriesStack.constructor === Object
133
- ) {
134
- t0 = performance.now();
135
- }
136
-
137
- if (!parsingQueueFlag || parsingQueue.length === 0) {
138
- if (parsingQueue.length === 0) {
139
- let t1 = performance.now();
140
- console.log(`Call to readFiles took ${t1 - t0} milliseconds.`);
141
- parsingQueueFlag = null;
142
- callback(allSeriesStack);
143
- }
144
- return;
145
- }
146
-
147
- parsingQueueFlag = false;
148
-
149
- // remove and return first item from queue
150
- let file = parsingQueue.shift();
151
-
152
- // Check if there is enough memory to dump the file
153
- if (checkMemoryAllocation(file.size) === false) {
154
- // do not parse the file and stop parsing
155
- clearImageParsing(allSeriesStack);
156
- let t1 = performance.now();
157
- console.log(`Call to readFiles took ${t1 - t0} milliseconds.`);
158
- parsingQueueFlag = null;
159
- file = null;
160
- callback(allSeriesStack, "Available memory is not enough");
161
- } else {
162
- // parse the file and wait for results
163
- dumpFile(file, function (seriesData, err) {
164
- if (parsingQueueFlag === null) {
165
- console.log("parsingQueueFlag is null");
166
- // parsing process has been stopped, but there could be a
167
- // dumpFile callback still working: prevent actions
168
- return;
169
- }
170
- if (err) {
171
- console.warn(err);
172
- parsingQueueFlag = true;
173
- parseNextFile(parsingQueue, allSeriesStack, callback);
174
- } else {
175
- // add file to cornerstoneWADOImageLoader file manager
176
- updateLoadedStack(seriesData, allSeriesStack);
177
- // proceed with the next file to parse
178
- parsingQueueFlag = true;
179
- parseNextFile(parsingQueue, allSeriesStack, callback);
180
- }
181
- file = null;
182
- seriesData = null;
183
- });
184
- }
185
- };
186
-
187
- /**
188
- * Push files in queue and start parsing next file
189
- * @inner
190
- * @function dumpFiles
191
- * @param {Array} fileList - Array of file objects
192
- * @param {Array} parsingQueue - Array of queued files to be parsed
193
- * @param {Object} allSeriesStack - Series stack object to be populated
194
- * @param {Function} callback - Passed through
195
- */
196
- let dumpFiles = function (fileList, parsingQueue, allSeriesStack, callback) {
197
- forEach(fileList, function (file) {
198
- if (!file.name.startsWith(".") && !file.name.startsWith("DICOMDIR")) {
199
- parsingQueue.push(file);
200
- // enable parsing on first available path
201
- if (parsingQueueFlag === null) {
202
- parsingQueueFlag = true;
203
- }
204
- }
205
- });
206
- parseNextFile(parsingQueue, allSeriesStack, callback);
207
- };
208
-
209
- /**
210
- * Dump a single DICOM File (metaData and pixelData)
211
- * @inner
212
- * @function dumpFile
213
- * @param {File} file - File object to be dumped
214
- * @param {Function} callback - called with (imageObject, errorString)
215
- */
216
- let dumpFile = function (file, callback) {
217
- let reader = new FileReader();
218
- reader.onload = function () {
219
- let arrayBuffer = reader.result;
220
- // Here we have the file data as an ArrayBuffer.
221
- // dicomParser requires as input a Uint8Array so we create that here.
222
- let byteArray = new Uint8Array(arrayBuffer);
223
-
224
- let dataSet;
225
- try {
226
- dataSet = parseDicom(byteArray);
227
- byteArray = null;
228
- let metadata = {};
229
- dumpDataSet(dataSet, metadata);
230
-
231
- let numberOfFrames = metadata["x00280008"];
232
- let isMultiframe = numberOfFrames > 1 ? true : false;
233
- // Overwrite SOPInstanceUID to manage multiframes.
234
- // Usually different SeriesInstanceUID means different series and that value
235
- // is used into the application to group different instances into the same series,
236
- // but if a DICOM file contains a multiframe series, then the SeriesInstanceUID
237
- // can be shared by other files of the same study.
238
- // In multiframe cases, the SOPInstanceUID (unique) is used as SeriesInstanceUID.
239
- let seriesInstanceUID = isMultiframe
240
- ? metadata["x00080018"]
241
- : metadata["x0020000e"];
242
- let pixelSpacing = metadata["x00280030"];
243
- let imageOrientation = metadata["x00200037"];
244
- let imagePosition = metadata["x00200032"];
245
- let sliceThickness = metadata["x00180050"];
246
-
247
- if (dataSet.warnings.length > 0) {
248
- // warnings
249
- callback(null, dataSet.warnings);
250
- } else {
251
- let pixelDataElement = dataSet.elements.x7fe00010;
252
-
253
- if (pixelDataElement) {
254
- // done, pixelDataElement found
255
- let instanceUID = metadata["x00080018"] || randomId();
256
- let imageObject = {
257
- // data needed for rendering
258
- file: file,
259
- dataSet: dataSet
260
- };
261
- imageObject.metadata = metadata;
262
- imageObject.metadata.seriesUID = seriesInstanceUID;
263
- imageObject.metadata.instanceUID = instanceUID;
264
- imageObject.metadata.studyUID = metadata["x0020000d"];
265
- imageObject.metadata.accessionNumber = metadata["x00080050"];
266
- imageObject.metadata.studyDescription = metadata["x00081030"];
267
- imageObject.metadata.patientName = metadata["x00100010"];
268
- imageObject.metadata.patientBirthdate = metadata["x00100030"];
269
- imageObject.metadata.seriesDescription = metadata["x0008103e"];
270
- imageObject.metadata.seriesDate = metadata["x00080021"];
271
- imageObject.metadata.seriesModality =
272
- metadata["x00080060"].toLowerCase();
273
- imageObject.metadata.intercept = metadata["x00281052"];
274
- imageObject.metadata.slope = metadata["x00281053"];
275
- imageObject.metadata.pixelSpacing = pixelSpacing;
276
- imageObject.metadata.sliceThickness = sliceThickness;
277
- imageObject.metadata.imageOrientation = imageOrientation;
278
- imageObject.metadata.imagePosition = imagePosition;
279
- imageObject.metadata.rows = metadata["x00280010"];
280
- imageObject.metadata.cols = metadata["x00280011"];
281
- imageObject.metadata.numberOfSlices = metadata["x00540081"]
282
- ? metadata["x00540081"] // number of slices
283
- : metadata["x00201002"]; // number of instances
284
- imageObject.metadata.numberOfFrames = numberOfFrames;
285
- if (isMultiframe) {
286
- imageObject.metadata.frameTime = metadata["x00181063"];
287
- imageObject.metadata.frameDelay = metadata["x00181066"];
288
- }
289
- imageObject.metadata.windowCenter = metadata["x00281050"];
290
- imageObject.metadata.windowWidth = metadata["x00281051"];
291
- imageObject.metadata.minPixelValue = metadata["x00280106"];
292
- imageObject.metadata.maxPixelValue = metadata["x00280107"];
293
- imageObject.metadata.length = pixelDataElement.length;
294
- imageObject.metadata.repr = getPixelRepresentation(dataSet);
295
- callback(imageObject);
296
- } else {
297
- // done, no pixelData
298
- callback(null, "no pixelData.");
299
- }
300
- }
301
- } catch (err) {
302
- console.log(err);
303
- callback(null, "can not read this file.");
304
- }
305
- };
306
- reader.readAsArrayBuffer(file);
307
- };