larvitar 2.0.5 → 2.0.7

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 (77) hide show
  1. package/README.md +2 -2
  2. package/dist/imaging/imageRendering.d.ts +1 -71
  3. package/dist/imaging/imageStore.d.ts +5 -0
  4. package/dist/imaging/loaders/commonLoader.d.ts +4 -4
  5. package/dist/imaging/loaders/nrrdLoader.d.ts +1 -51
  6. package/dist/larvitar.js +13 -1
  7. package/dist/larvitar.js.map +1 -1
  8. package/imaging/tools/types.d.ts +19 -19
  9. package/imaging/types.d.ts +110 -2
  10. package/package.json +7 -2
  11. package/.github/workflows/build-docs.yml +0 -59
  12. package/.github/workflows/codeql-analysis.yml +0 -71
  13. package/.github/workflows/deploy.yml +0 -37
  14. package/.vscode/settings.json +0 -4
  15. package/CODE_OF_CONDUCT.md +0 -76
  16. package/MIGRATION.md +0 -25
  17. package/bundler/webpack.common.js +0 -27
  18. package/bundler/webpack.dev.js +0 -23
  19. package/bundler/webpack.prod.js +0 -19
  20. package/decs.d.ts +0 -12
  21. package/dist/imaging/MetaDataReadable.d.ts +0 -41
  22. package/dist/imaging/MetaDataTypes.d.ts +0 -3489
  23. package/imaging/dataDictionary.json +0 -21866
  24. package/imaging/imageAnonymization.ts +0 -135
  25. package/imaging/imageColormaps.ts +0 -217
  26. package/imaging/imageContours.ts +0 -196
  27. package/imaging/imageIo.ts +0 -251
  28. package/imaging/imageLayers.ts +0 -121
  29. package/imaging/imageLoading.ts +0 -299
  30. package/imaging/imageParsing.ts +0 -444
  31. package/imaging/imagePresets.ts +0 -156
  32. package/imaging/imageRendering.ts +0 -1091
  33. package/imaging/imageReslice.ts +0 -87
  34. package/imaging/imageStore.ts +0 -487
  35. package/imaging/imageTags.ts +0 -609
  36. package/imaging/imageTools.js +0 -708
  37. package/imaging/imageUtils.ts +0 -1079
  38. package/imaging/loaders/commonLoader.ts +0 -275
  39. package/imaging/loaders/dicomLoader.ts +0 -66
  40. package/imaging/loaders/fileLoader.ts +0 -71
  41. package/imaging/loaders/multiframeLoader.ts +0 -435
  42. package/imaging/loaders/nrrdLoader.ts +0 -630
  43. package/imaging/loaders/resliceLoader.ts +0 -205
  44. package/imaging/monitors/memory.ts +0 -151
  45. package/imaging/monitors/performance.ts +0 -34
  46. package/imaging/parsers/ecg.ts +0 -54
  47. package/imaging/parsers/nrrd.js +0 -485
  48. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  49. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  50. package/imaging/tools/custom/contourTool.js +0 -1884
  51. package/imaging/tools/custom/diameterTool.js +0 -141
  52. package/imaging/tools/custom/editMaskTool.js +0 -141
  53. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  54. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  55. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  56. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  57. package/imaging/tools/custom/seedTool.js +0 -342
  58. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  59. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  60. package/imaging/tools/default.ts +0 -594
  61. package/imaging/tools/interaction.ts +0 -266
  62. package/imaging/tools/io.ts +0 -229
  63. package/imaging/tools/main.ts +0 -427
  64. package/imaging/tools/segmentation.ts +0 -532
  65. package/imaging/tools/segmentations.md +0 -38
  66. package/imaging/tools/state.ts +0 -74
  67. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  68. package/imaging/tools/strategies/fillFreehand.js +0 -79
  69. package/imaging/tools/strategies/index.js +0 -2
  70. package/imaging/waveforms/ecg.ts +0 -191
  71. package/index.ts +0 -431
  72. package/jsdoc.json +0 -52
  73. package/rollup.config.js +0 -51
  74. package/template/.gitkeep +0 -0
  75. package/tsconfig.json +0 -102
  76. /package/imaging/{MetaDataReadable.ts → MetaDataReadable.d.ts} +0 -0
  77. /package/imaging/{MetaDataTypes.ts → MetaDataTypes.d.ts} +0 -0
@@ -1,444 +0,0 @@
1
- /** @module imaging/imageParsing
2
- * @desc This file provides functionalities for parsing DICOM image files
3
- */
4
-
5
- // external libraries
6
- import { DataSet, parseDicom } from "dicom-parser";
7
- import { forEach, each, has, pick } from "lodash";
8
- import { v4 as uuidv4 } from "uuid";
9
-
10
- // internal libraries
11
- import { getPixelRepresentation, randomId } from "./imageUtils";
12
- import { parseTag } from "./imageTags";
13
- import { updateLoadedStack } from "./imageLoading";
14
- import { checkMemoryAllocation } from "./monitors/memory";
15
- import { ImageObject, Instance, MetaData, Series } from "./types";
16
- import { getLarvitarManager } from "./loaders/commonLoader";
17
- import type { MetaDataTypes } from "./MetaDataTypes";
18
- import { NrrdSeries } from "./loaders/nrrdLoader";
19
-
20
- // global module variables
21
- var t0: number; // t0 variable for timing debugging purpose
22
-
23
- /*
24
- * This module provides the following functions to be exported:
25
- * readFiles(fileList)
26
- * readFile(file)
27
- * parseDataSet(dataSet, metadata, customFilter)
28
- * clearImageParsing(seriesStack)
29
- */
30
-
31
- /**
32
- * Reset series stack object and its internal data
33
- * @instance
34
- * @function clearImageParsing
35
- * @param {Object} seriesStack - Parsed series stack object
36
- */
37
- export const clearImageParsing = function (
38
- seriesStack: ReturnType<typeof getLarvitarManager> | null
39
- ) {
40
- each(seriesStack, function (stack: Series | NrrdSeries) {
41
- each(stack.instances, function (instance: Instance) {
42
- if (instance.dataSet) {
43
- // @ts-ignore
44
- instance.dataSet.byteArray = null;
45
- }
46
- instance.dataSet = null;
47
- instance.file = null;
48
- // @ts-ignore
49
- instance.metadata = null;
50
- });
51
- });
52
- seriesStack = null;
53
- };
54
-
55
- /**
56
- * Read dicom files and return allSeriesStack object
57
- * @instance
58
- * @function readFiles
59
- * @param {Array} entries - List of file objects
60
- * @returns {Promise} - Return a promise which will resolve to a image object list or fail if an error occurs
61
- */
62
- export const readFiles = function (entries: File[]) {
63
- return parseFiles(entries);
64
- };
65
-
66
- /**
67
- * Read a single dicom file and return parsed object
68
- * @instance
69
- * @function readFile
70
- * @param {File} entry - File object
71
- * @returns {Promise} - Return a promise which will resolve to a image object or fail if an error occurs
72
- */
73
- export const readFile = function (entry: File) {
74
- return parseFile(entry);
75
- };
76
-
77
- /* Internal module functions */
78
-
79
- //This type is used to instantiate metadata and nested objects in imageParsing in order to allow dynamic setting
80
- //of MetaDataTypes objects' properties.
81
- //In other words, metadata : ExtendedMetaDataTypes is useful and substitutes metadata : MetaDataTypes when metadata values
82
- //aren't called explicitly using metadata['xGGGGEEEEE']
83
- //and are instead called using TAG as a variable (i.e. metadata[TAG]).
84
- //It is important to highlight that even if we set metadata[TAG]=tagValue; whose type (of tagValue) is the correct one (returned by ParseTag).
85
- //if we then extract x=metadata[TAG]; we obtain tagValue : unknown and a casting with : MetaDataType[typeof TAG] is necessary.
86
-
87
- type ExtendedMetaDataTypes = MetaDataTypes & {
88
- [key: string]: unknown;
89
- };
90
-
91
- /**
92
- * Parse metadata from dicom parser dataSet object
93
- * @instance
94
- * @function parseDataSet
95
- * @param {Object} dataSet - dicom parser dataSet object
96
- * @param {Object} metadata - Initialized metadata object
97
- * @param {Array} customFilter - Optional filter: {tags:[], frameId: 0}
98
- */
99
- // This function iterates through dataSet recursively and store tag values into metadata object
100
-
101
- export const parseDataSet = function (
102
- dataSet: DataSet,
103
- metadata: ExtendedMetaDataTypes,
104
- customFilter?: { tags: string[]; frameId: number }
105
- ) {
106
- // customFilter= {tags:[], frameId:xxx}
107
- // the dataSet.elements object contains properties for each element parsed. The name of the property
108
- // is based on the elements tag and looks like 'xGGGGEEEE' where GGGG is the group number and EEEE is the
109
- // element number both with lowercase hexadecimal letters. For example, the Series Description DICOM element 0008,103E would
110
- // be named 'x0008103e'. Here we iterate over each property (element) so we can build a string describing its
111
- // contents to add to the output array
112
- try {
113
- let elements = dataSet.elements;
114
-
115
- customFilter && has(customFilter, "tags")
116
- ? pick(dataSet.elements, customFilter.tags)
117
- : dataSet.elements;
118
- for (let propertyName in elements) {
119
- let element = elements[propertyName]; //metadata
120
- const TAG = propertyName as keyof ExtendedMetaDataTypes;
121
- // Here we check for Sequence items and iterate over them if present. items will not be set in the
122
- // element object for elements that don't have SQ VR type. Note that implicit little endian
123
- // sequences will are currently not parsed.
124
- if (element.items) {
125
- let nestedArray: MetaDataTypes[] = [];
126
-
127
- // iterates over nested elements (nested metadata)
128
- element.items.forEach(function (item) {
129
- let nestedObject: ExtendedMetaDataTypes = {};
130
- for (let nestedPropertyName in item.dataSet!.elements) {
131
- let TAG_tagValue = nestedPropertyName as keyof MetaDataTypes;
132
-
133
- let tagValue = parseTag<MetaDataTypes[typeof TAG_tagValue]>(
134
- item.dataSet!,
135
- nestedPropertyName,
136
- item.dataSet!.elements[nestedPropertyName]
137
- );
138
-
139
- let TAG_nested = nestedPropertyName as keyof ExtendedMetaDataTypes;
140
- nestedObject[TAG_nested] = tagValue;
141
- //see MetaDataTypes.ts last property to understand how this dynamic value setting is possible
142
- }
143
- nestedArray.push(nestedObject);
144
- });
145
- metadata[TAG] = nestedArray;
146
- } else {
147
- let TAG_tagValue = propertyName as keyof MetaDataTypes;
148
- let tagValue = parseTag<MetaDataTypes[typeof TAG_tagValue]>(
149
- dataSet,
150
- propertyName,
151
- element
152
- );
153
- let TAG = propertyName as keyof ExtendedMetaDataTypes;
154
- // identify duplicated tags (keep the first occurency and store the others in another tag eg x00280010_uuid)
155
- if (metadata[TAG] !== undefined) {
156
- console.debug(
157
- `Identified duplicated tag "${propertyName}", values are:`,
158
- metadata[TAG],
159
- tagValue
160
- );
161
- let TAG_uuidv4 = (propertyName +
162
- "_" +
163
- uuidv4()) as keyof ExtendedMetaDataTypes;
164
- metadata[TAG_uuidv4] = tagValue;
165
- } else {
166
- metadata[TAG] = tagValue;
167
- }
168
- }
169
- }
170
- } catch (err) {
171
- console.log(err);
172
- }
173
- };
174
-
175
- /**
176
- * Manage the parsing process waiting for the parsed object before proceeding with the next parse request
177
- * @inner
178
- * @function parseNextFile
179
- * @param {Array} parsingQueue - Array of queued files to be parsed
180
- * @param {Object} allSeriesStack - Series stack object to be populated
181
- * @param {string} uuid - Series uuid to be used if series instance uuid is missing
182
- * @param {Function} resolve - Promise resolve function
183
- * @param {Function} reject - Promise reject function
184
- */
185
- let parseNextFile = function (
186
- parsingQueue: File[],
187
- allSeriesStack: ReturnType<typeof getLarvitarManager>,
188
- uuid: string,
189
- resolve: Function,
190
- reject: Function
191
- ) {
192
- // initialize t0 on first file of the queue
193
- if (
194
- Object.keys(allSeriesStack).length === 0 &&
195
- allSeriesStack.constructor === Object
196
- ) {
197
- t0 = performance.now();
198
- }
199
-
200
- if (parsingQueue.length === 0) {
201
- let t1 = performance.now();
202
- console.log(`Call to readFiles took ${t1 - t0} milliseconds.`);
203
- resolve(allSeriesStack);
204
- return;
205
- }
206
-
207
- // remove and return first item from queue
208
- let file = parsingQueue.shift() as File | undefined | null;
209
-
210
- if (!file) {
211
- console.warn("File is undefined or null");
212
- return;
213
- }
214
-
215
- // Check if there is enough memory to parse the file
216
- if (checkMemoryAllocation(file.size) === false) {
217
- // do not parse the file and stop parsing
218
- clearImageParsing(allSeriesStack);
219
- let t1 = performance.now();
220
- console.log(`Call to readFiles took ${t1 - t0} milliseconds.`);
221
- file = null;
222
- reject("Available memory is not enough");
223
- return;
224
- } else {
225
- // parse the file and wait for results
226
- parseFile(file)
227
- .then((seriesData: ImageObject | null) => {
228
- // use generated series uid if not found in dicom file
229
- seriesData!.metadata.seriesUID = seriesData!.metadata.seriesUID || uuid;
230
- // add file to cornerstoneDICOMImageLoader file manager
231
- updateLoadedStack(seriesData!, allSeriesStack);
232
- // proceed with the next file to parse
233
- parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
234
- seriesData = null;
235
- file = null;
236
- })
237
- .catch(err => {
238
- console.error(err);
239
- parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
240
- file = null;
241
- });
242
- }
243
- };
244
-
245
- /**
246
- * Push files in queue and start parsing next file
247
- * @inner
248
- * @function parseFiles
249
- * @param {Array} fileList - Array of file objects
250
- * @returns {Promise} - Return a promise which will resolve to a image object list or fail if an error occurs
251
- */
252
- const parseFiles = function (fileList: File[]) {
253
- let allSeriesStack = {};
254
- let parsingQueue: File[] = [];
255
-
256
- forEach(fileList, function (file: File) {
257
- if (!file.name.startsWith(".") && !file.name.startsWith("DICOMDIR")) {
258
- parsingQueue.push(file);
259
- }
260
- });
261
- return new Promise((resolve, reject) => {
262
- const uuid = uuidv4();
263
- parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
264
- });
265
- };
266
-
267
- /**
268
- * Parse a single DICOM File (metaData and pixelData)
269
- * @inner
270
- * @function parseFile
271
- * @param {File} file - File object to be parsed
272
- * @returns {Promise} - Return a promise which will resolve to a image object or fail if an error occurs
273
- */
274
- const parseFile = function (file: File) {
275
- const parsePromise = new Promise<ImageObject>((resolve, reject) => {
276
- let reader = new FileReader();
277
- reader.onload = function () {
278
- let arrayBuffer = reader.result;
279
- // Here we have the file data as an ArrayBuffer.
280
- // dicomParser requires as input a Uint8Array so we create that here.
281
-
282
- if (!arrayBuffer || typeof arrayBuffer === "string") {
283
- reject("Error reading file");
284
- return;
285
- }
286
-
287
- let byteArray: Uint8Array | null = new Uint8Array(arrayBuffer);
288
- let dataSet;
289
-
290
- // this try-catch is used to handle non-DICOM files: log error but continue parsing the other files
291
- try {
292
- dataSet = parseDicom(byteArray);
293
- byteArray = null;
294
- let metadata: MetaData = {};
295
- parseDataSet(dataSet, metadata);
296
-
297
- let temporalPositionIdentifier = metadata["x00200100"]; // Temporal order of a dynamic or functional set of Images.
298
- let numberOfTemporalPositions = metadata["x00200105"]; // Total number of temporal positions prescribed.
299
- const is4D =
300
- temporalPositionIdentifier !== undefined &&
301
- (numberOfTemporalPositions as number) > 1
302
- ? true
303
- : false;
304
-
305
- let modality = metadata["x00080060"] as string;
306
- let singleFrameModalities = [
307
- "CR",
308
- "DX",
309
- "MG",
310
- "PX",
311
- "RF",
312
- "XA",
313
- "US",
314
- "IVUS",
315
- "OCT"
316
- ];
317
- // US XA RF IVUS OCT DX CR PX MG
318
- // Overwrite SOPInstanceUID to manage single stack images (US, XA).
319
- // Usually different SeriesInstanceUID means different series and that value
320
- // is used into the application to group different instances into the same series,
321
- // but if a DICOM file contains a multiframe series, then the SeriesInstanceUID
322
- // can be shared by other files of the same study.
323
- // In these cases, the SOPInstanceUID (unique) is used as SeriesInstanceUID.
324
- let uniqueId = singleFrameModalities.includes(modality)
325
- ? metadata["x00080018"]
326
- : metadata["x0020000e"];
327
- let seriesInstanceUID = metadata["x0020000e"];
328
- let pixelSpacing = metadata["x00280030"];
329
- let imageOrientation = metadata["x00200037"];
330
- let imagePosition = metadata["x00200032"];
331
- let sliceThickness = metadata["x00180050"];
332
- let numberOfFrames = metadata["x00280008"];
333
- let isMultiframe = (numberOfFrames as number) > 1 ? true : false;
334
- let waveform = metadata["x50003000"] ? true : false;
335
-
336
- if (dataSet.warnings.length > 0) {
337
- // warnings
338
- reject(dataSet.warnings);
339
- } else {
340
- let pixelDataElement = dataSet.elements.x7fe00010;
341
- let SOPUID = metadata["x00080016"];
342
- if (pixelDataElement) {
343
- // done, pixelDataElement found
344
- let instanceUID = metadata["x00080018"] || randomId();
345
- let imageObject: Partial<ImageObject> = {
346
- // data needed for rendering
347
- file: file,
348
- dataSet: dataSet
349
- };
350
- imageObject.metadata = metadata as MetaData;
351
- imageObject.metadata.anonymized = false;
352
- imageObject.metadata.larvitarSeriesInstanceUID = uniqueId;
353
- imageObject.metadata.sopClassUID = metadata["x00080016"];
354
- imageObject.metadata.seriesUID = seriesInstanceUID;
355
- imageObject.metadata.instanceUID = instanceUID;
356
- imageObject.metadata.studyUID = metadata["x0020000d"];
357
- imageObject.metadata.accessionNumber = metadata["x00080050"];
358
- imageObject.metadata.studyDescription = metadata["x00081030"];
359
- imageObject.metadata.patientName = metadata["x00100010"] as string;
360
- imageObject.metadata.patientBirthdate = metadata["x00100030"];
361
- imageObject.metadata.seriesDescription = metadata[
362
- "x0008103e"
363
- ] as string;
364
- imageObject.metadata.seriesDate = metadata["x00080021"];
365
- imageObject.metadata.seriesModality = metadata["x00080060"]
366
- ?.toString()
367
- .toLowerCase();
368
- imageObject.metadata.intercept = metadata["x00281052"];
369
- imageObject.metadata.slope = metadata["x00281053"];
370
- imageObject.metadata.pixelSpacing = pixelSpacing;
371
- imageObject.metadata.sliceThickness = sliceThickness;
372
- imageObject.metadata.imageOrientation = imageOrientation;
373
- imageObject.metadata.imagePosition = imagePosition;
374
- imageObject.metadata.rows = metadata["x00280010"];
375
- imageObject.metadata.cols = metadata["x00280011"];
376
- imageObject.metadata.numberOfSlices = metadata["x00540081"]
377
- ? metadata["x00540081"] // number of slices
378
- : metadata["x00201002"]; // number of instances
379
- imageObject.metadata.numberOfFrames = numberOfFrames;
380
- if (isMultiframe) {
381
- imageObject.metadata.frameTime = metadata["x00181063"];
382
- imageObject.metadata.frameDelay = metadata["x00181066"];
383
- if (metadata["x00186060"]) {
384
- imageObject.metadata.rWaveTimeVector = metadata["x00186060"];
385
- }
386
- }
387
- imageObject.metadata.isMultiframe = isMultiframe;
388
- if (is4D) {
389
- imageObject.metadata.temporalPositionIdentifier =
390
- metadata["x00200100"];
391
- imageObject.metadata.numberOfTemporalPositions =
392
- metadata["x00200105"];
393
- imageObject.metadata.contentTime = metadata["x00080033"];
394
- }
395
- imageObject.metadata.is4D = is4D;
396
- imageObject.metadata.waveform = waveform;
397
- imageObject.metadata.windowCenter = metadata["x00281050"];
398
- imageObject.metadata.windowWidth = metadata["x00281051"];
399
- imageObject.metadata.minPixelValue = metadata["x00280106"];
400
- imageObject.metadata.maxPixelValue = metadata["x00280107"];
401
- imageObject.metadata.length = pixelDataElement.length;
402
- imageObject.metadata.repr = getPixelRepresentation(dataSet);
403
- resolve(imageObject as ImageObject);
404
- } else if (SOPUID == "1.2.840.10008.5.1.4.1.1.104.1") {
405
- let pdfObject: Partial<ImageObject> = {
406
- // data needed for rendering
407
- file: file,
408
- dataSet: dataSet
409
- };
410
- pdfObject.metadata = metadata;
411
- pdfObject.metadata.larvitarSeriesInstanceUID = uniqueId;
412
- pdfObject.metadata.seriesUID = seriesInstanceUID;
413
- pdfObject.instanceUID =
414
- metadata["x00080018"]?.toString() || randomId();
415
- pdfObject.metadata.studyUID = metadata["x0020000d"];
416
- pdfObject.metadata.accessionNumber = metadata["x00080050"];
417
- pdfObject.metadata.studyDescription = metadata["x00081030"];
418
- pdfObject.metadata.patientName = metadata["x00100010"] as string;
419
- pdfObject.metadata.patientBirthdate = metadata["x00100030"];
420
- pdfObject.metadata.seriesDate = metadata["x00080021"];
421
- pdfObject.metadata.seriesModality = metadata["x00080060"]
422
- ?.toString()
423
- .toLowerCase();
424
- pdfObject.metadata.mimeType = metadata["x00420012"];
425
- pdfObject.metadata.is4D = false;
426
- pdfObject.metadata.numberOfFrames = 0;
427
- pdfObject.metadata.numberOfSlices = 0;
428
- pdfObject.metadata.numberOfTemporalPositions = 0;
429
- resolve(pdfObject as ImageObject);
430
- } else {
431
- // done, no pixelData
432
- reject("no pixelData");
433
- }
434
- }
435
- } catch (err) {
436
- reject(
437
- `Larvitar: can not read file "${file.name}" \nParsing error: ${err}`
438
- );
439
- }
440
- };
441
- reader.readAsArrayBuffer(file);
442
- });
443
- return parsePromise;
444
- };
@@ -1,156 +0,0 @@
1
- /** @module imaging/imagePresets
2
- * @desc This file provides functionalities for
3
- * image presets for ww and wc
4
- */
5
-
6
- // external libraries
7
- import cornerstone from "cornerstone-core";
8
- import { each, find } from "lodash";
9
-
10
- // internal libraries
11
- import { set as setStore } from "./imageStore";
12
-
13
- /**
14
- * Object used to list image presets
15
- * @object
16
- */
17
- const IMAGE_PRESETS = [
18
- { name: "CT: Abdomen", ww: 350, wl: 50 },
19
- { name: "CT: Bone", ww: 2500, wl: 500 },
20
- { name: "CT: Cerebrum", ww: 80, wl: 0 },
21
- { name: "CT: Covid-19", ww: 240, wl: -860 },
22
- { name: "CT: Liver", ww: 150, wl: 50 },
23
- { name: "CT: Lung", ww: 1500, wl: -500 },
24
- { name: "CT: Mediastinum", ww: 300, wl: 50 },
25
- { name: "CT: Pelvis", ww: 400, wl: 40 }
26
- ];
27
-
28
- /*
29
- * This module provides the following functions to be exported:
30
- * getImagePresets()
31
- * setImagePreset(name)
32
- * setImageCustomPreset(viewportNames, customValues)
33
- */
34
-
35
- /**
36
- * Get Image presets object
37
- * @instance
38
- * @function getImagePresets
39
- */
40
- export const getImagePresets = function () {
41
- return IMAGE_PRESETS;
42
- };
43
-
44
- /**
45
- * Set Image presets
46
- * @instance
47
- * @function setImagePreset
48
- * @param {Array} viewportNames - List of viewports where to apply preset
49
- * @param {String} preset - The image preset name or the preset object
50
- */
51
- export const setImagePreset = function (
52
- viewportNames: string[],
53
- preset: string | (typeof IMAGE_PRESETS)[0]
54
- ) {
55
- if (!Array.isArray(viewportNames)) {
56
- console.error(
57
- "Invalid parameter, viewportNames has to be an array of viewport names."
58
- );
59
- return;
60
- }
61
- let image_preset =
62
- typeof preset === "string" ? find(IMAGE_PRESETS, { name: preset }) : preset;
63
-
64
- if (!image_preset) {
65
- console.error("Invalid image preset");
66
- return;
67
- }
68
-
69
- each(viewportNames, function (viewportName: string) {
70
- let element = document.getElementById(viewportName);
71
- let enabledElement;
72
-
73
- if (!element) {
74
- console.warn("No element with id", viewportName);
75
- return;
76
- }
77
-
78
- try {
79
- enabledElement = cornerstone.getEnabledElement(element);
80
- } catch {
81
- console.warn("No enabledElement with id", viewportName);
82
- return;
83
- }
84
-
85
- let viewport = cornerstone.getViewport(element);
86
-
87
- if (!viewport) {
88
- console.warn("No viewport with id", viewportName);
89
- return;
90
- }
91
-
92
- viewport.voi.windowWidth = image_preset!.ww;
93
- viewport.voi.windowCenter = image_preset!.wl;
94
- cornerstone.setViewport(element, viewport);
95
- // sync ww and wc values in store
96
- setStore([
97
- "contrast",
98
- viewportName,
99
- viewport.voi.windowWidth,
100
- viewport.voi.windowCenter
101
- ]);
102
- });
103
- };
104
-
105
- /**
106
- * Set Image presets
107
- * @instance
108
- * @function setImageCustomPreset
109
- * @param {Array} viewportNames - List of viewports where to apply preset
110
- * @param {Object} customValues - {wl: value, ww: value}
111
- */
112
- export const setImageCustomPreset = function (
113
- viewportNames: string[],
114
- customValues: { wl: number; ww: number }
115
- ) {
116
- if (!Array.isArray(viewportNames)) {
117
- console.error(
118
- "Invalid parameter, viewportNames has to be an array of viewport names."
119
- );
120
- return;
121
- }
122
- each(viewportNames, function (viewportName: string) {
123
- let element = document.getElementById(viewportName);
124
- let enabledElement;
125
-
126
- if (!element) {
127
- console.warn("No element with id", viewportName);
128
- return;
129
- }
130
-
131
- try {
132
- enabledElement = cornerstone.getEnabledElement(element);
133
- } catch {
134
- console.warn("No enabledElement with id", viewportName);
135
- return;
136
- }
137
-
138
- let viewport = cornerstone.getViewport(element);
139
-
140
- if (!viewport) {
141
- console.warn("No viewport with id", viewportName);
142
- return;
143
- }
144
-
145
- viewport.voi.windowWidth = customValues.ww;
146
- viewport.voi.windowCenter = customValues.wl;
147
- cornerstone.setViewport(element, viewport);
148
- // sync ww and wc values in store
149
- setStore([
150
- "contrast",
151
- viewportName,
152
- viewport.voi.windowWidth,
153
- viewport.voi.windowCenter
154
- ]);
155
- });
156
- };