larvitar 1.5.14 → 2.0.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 (107) hide show
  1. package/.vscode/settings.json +4 -0
  2. package/README.md +78 -48
  3. package/bundler/webpack.common.js +27 -0
  4. package/bundler/webpack.dev.js +23 -0
  5. package/bundler/webpack.prod.js +19 -0
  6. package/decs.d.ts +12 -0
  7. package/dist/imaging/MetaDataReadable.d.ts +40 -0
  8. package/dist/imaging/MetaDataTypes.d.ts +3489 -0
  9. package/dist/imaging/imageAnonymization.d.ts +12 -0
  10. package/dist/imaging/imageColormaps.d.ts +47 -0
  11. package/dist/imaging/imageContours.d.ts +18 -0
  12. package/dist/imaging/imageIo.d.ts +42 -0
  13. package/dist/imaging/imageLayers.d.ts +56 -0
  14. package/dist/imaging/imageLoading.d.ts +65 -0
  15. package/dist/imaging/imageParsing.d.ts +46 -0
  16. package/dist/imaging/imagePresets.d.ts +43 -0
  17. package/dist/imaging/imageRendering.d.ts +238 -0
  18. package/dist/imaging/imageReslice.d.ts +14 -0
  19. package/dist/imaging/imageStore.d.ts +121 -0
  20. package/dist/imaging/imageTags.d.ts +22 -0
  21. package/dist/imaging/imageTools.d.ts +20 -0
  22. package/dist/imaging/imageUtils.d.ts +165 -0
  23. package/dist/imaging/loaders/commonLoader.d.ts +103 -0
  24. package/dist/imaging/loaders/dicomLoader.d.ts +29 -0
  25. package/dist/imaging/loaders/fileLoader.d.ts +33 -0
  26. package/dist/imaging/loaders/multiframeLoader.d.ts +37 -0
  27. package/dist/imaging/loaders/nrrdLoader.d.ts +113 -0
  28. package/dist/imaging/loaders/resliceLoader.d.ts +15 -0
  29. package/dist/imaging/monitors/memory.d.ts +41 -0
  30. package/dist/imaging/monitors/performance.d.ts +23 -0
  31. package/dist/imaging/parsers/ecg.d.ts +15 -0
  32. package/dist/imaging/parsers/nrrd.d.ts +3 -0
  33. package/dist/imaging/tools/custom/4dSliceScrollTool.d.ts +12 -0
  34. package/dist/imaging/tools/custom/BorderMagnifyTool.d.ts +18 -0
  35. package/dist/imaging/tools/custom/contourTool.d.ts +409 -0
  36. package/dist/imaging/tools/custom/diameterTool.d.ts +18 -0
  37. package/dist/imaging/tools/custom/editMaskTool.d.ts +22 -0
  38. package/dist/imaging/tools/custom/ellipticalRoiOverlayTool.d.ts +45 -0
  39. package/dist/imaging/tools/custom/polygonSegmentationMixin.d.ts +54 -0
  40. package/dist/imaging/tools/custom/polylineScissorsTool.d.ts +11 -0
  41. package/dist/imaging/tools/custom/rectangleRoiOverlayTool.d.ts +45 -0
  42. package/dist/imaging/tools/custom/seedTool.d.ts +0 -0
  43. package/dist/imaging/tools/custom/setLabelMap3D.d.ts +39 -0
  44. package/dist/imaging/tools/custom/thresholdsBrushTool.d.ts +19 -0
  45. package/dist/imaging/tools/default.d.ts +53 -0
  46. package/dist/imaging/tools/interaction.d.ts +30 -0
  47. package/dist/imaging/tools/io.d.ts +38 -0
  48. package/dist/imaging/tools/main.d.ts +81 -0
  49. package/dist/imaging/tools/segmentation.d.ts +125 -0
  50. package/dist/imaging/tools/state.d.ts +17 -0
  51. package/dist/imaging/tools/strategies/eraseFreehand.d.ts +16 -0
  52. package/dist/imaging/tools/strategies/fillFreehand.d.ts +16 -0
  53. package/dist/imaging/tools/strategies/index.d.ts +2 -0
  54. package/dist/imaging/waveforms/ecg.d.ts +39 -0
  55. package/dist/index.d.ts +35 -0
  56. package/dist/larvitar.js +90104 -0
  57. package/dist/larvitar.js.map +1 -0
  58. package/imaging/MetaDataReadable.ts +41 -0
  59. package/imaging/MetaDataTypes.ts +3491 -0
  60. package/imaging/dataDictionary.json +5328 -5328
  61. package/imaging/{imageAnonymization.js → imageAnonymization.ts} +41 -13
  62. package/imaging/{imageColormaps.js → imageColormaps.ts} +48 -30
  63. package/imaging/{imageContours.js → imageContours.ts} +24 -22
  64. package/imaging/{imageIo.js → imageIo.ts} +89 -52
  65. package/imaging/{imageLayers.js → imageLayers.ts} +31 -14
  66. package/imaging/{imageLoading.js → imageLoading.ts} +107 -43
  67. package/imaging/{imageParsing.js → imageParsing.ts} +160 -80
  68. package/imaging/{imagePresets.js → imagePresets.ts} +44 -11
  69. package/imaging/imageRendering.ts +1091 -0
  70. package/imaging/{imageReslice.js → imageReslice.ts} +18 -9
  71. package/imaging/imageStore.ts +487 -0
  72. package/imaging/imageTags.ts +609 -0
  73. package/imaging/imageTools.js +2 -1
  74. package/imaging/{imageUtils.js → imageUtils.ts} +211 -701
  75. package/imaging/loaders/{commonLoader.js → commonLoader.ts} +73 -24
  76. package/imaging/loaders/{dicomLoader.js → dicomLoader.ts} +25 -5
  77. package/imaging/loaders/{fileLoader.js → fileLoader.ts} +5 -5
  78. package/imaging/loaders/{multiframeLoader.js → multiframeLoader.ts} +145 -90
  79. package/imaging/loaders/{nrrdLoader.js → nrrdLoader.ts} +231 -64
  80. package/imaging/loaders/{resliceLoader.js → resliceLoader.ts} +51 -20
  81. package/imaging/monitors/{memory.js → memory.ts} +54 -8
  82. package/imaging/monitors/performance.ts +34 -0
  83. package/imaging/parsers/ecg.ts +54 -0
  84. package/imaging/tools/README.md +27 -0
  85. package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
  86. package/imaging/tools/custom/BorderMagnifyTool.js +99 -0
  87. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +534 -0
  88. package/imaging/tools/custom/polylineScissorsTool.js +1 -1
  89. package/imaging/tools/custom/rectangleRoiOverlayTool.js +564 -0
  90. package/imaging/tools/{setLabelMap3D.js → custom/setLabelMap3D.ts} +19 -25
  91. package/imaging/tools/{default.js → default.ts} +119 -33
  92. package/imaging/tools/{interaction.js → interaction.ts} +42 -23
  93. package/imaging/tools/{io.js → io.ts} +47 -31
  94. package/imaging/tools/{main.js → main.ts} +105 -40
  95. package/imaging/tools/{segmentation.js → segmentation.ts} +95 -68
  96. package/imaging/tools/{state.js → state.ts} +7 -12
  97. package/imaging/tools/types.d.ts +243 -0
  98. package/imaging/types.d.ts +200 -0
  99. package/imaging/waveforms/ecg.ts +191 -0
  100. package/{index.js → index.ts} +53 -14
  101. package/jsdoc.json +1 -1
  102. package/package.json +35 -14
  103. package/tsconfig.json +102 -0
  104. package/imaging/imageRendering.js +0 -860
  105. package/imaging/imageStore.js +0 -322
  106. package/modules/vuex/larvitar.js +0 -187
  107. /package/imaging/tools/{polygonSegmentationMixin.js → custom/polygonSegmentationMixin.js} +0 -0
@@ -3,18 +3,60 @@
3
3
  * monitoring memory usage
4
4
  */
5
5
 
6
+ import {
7
+ getLarvitarManager,
8
+ removeSeriesFromLarvitarManager
9
+ } from "../loaders/commonLoader";
10
+ import { clearImageCache } from "../imageRendering";
11
+ import store from "../imageStore";
12
+
13
+ // Custom types for chrome
14
+ interface Performance {
15
+ memory?: any;
16
+ }
17
+
6
18
  // global module variables
7
19
  const backingMemory = 100 * 1048576; // 100 MB
8
- var customMemoryLimit = null;
20
+ var customMemoryLimit: number | null = null;
9
21
 
10
22
  /*
11
23
  * This module provides the following functions to be exported:
12
- * checkMemoryAllocation()
24
+ * checkAndClearMemory(bytes, [seriesUUIDs])
25
+ * checkMemoryAllocation(bytes)
13
26
  * getUsedMemory()
14
27
  * getAvailableMemory()
15
28
  * setAvailableMemory()
16
29
  */
17
30
 
31
+ /**
32
+ * Check memory allocation and clear memory if needed
33
+ * @instance
34
+ * @function checkAndClearMemory
35
+ * @param {Number} - Number of bytes to allocate
36
+ * @param {Array} - Rendered Series ids
37
+ */
38
+ export const checkAndClearMemory = function (
39
+ bytes: number,
40
+ renderedSeriesIds: string[]
41
+ ) {
42
+ const isEnough = checkMemoryAllocation(bytes);
43
+ if (isEnough === false) {
44
+ const manager = getLarvitarManager();
45
+ // get all key of manager and create a list
46
+ const seriesIds = Object.keys(manager);
47
+ // create a list of non rendered series ids
48
+ const nonRenderedSeriesIds = seriesIds.filter(
49
+ seriesId => !renderedSeriesIds.includes(seriesId)
50
+ );
51
+ // remove non rendered series from manager
52
+ nonRenderedSeriesIds.forEach(seriesId => {
53
+ removeSeriesFromLarvitarManager(seriesId);
54
+ clearImageCache(seriesId);
55
+ store.removeSeriesId(seriesId);
56
+ });
57
+ }
58
+ };
59
+
18
60
  /**
19
61
  * Check memory allocation and returns false if js Heap size has reached its limit
20
62
  * @instance
@@ -22,7 +64,7 @@ var customMemoryLimit = null;
22
64
  * @param {Number} - Number of bytes to allocate
23
65
  * @return {Boolean} - Returns a boolean flag to warn the user about memory allocation limit
24
66
  */
25
- export const checkMemoryAllocation = function (bytes) {
67
+ export const checkMemoryAllocation = function (bytes: number) {
26
68
  if (checkMemorySupport()) {
27
69
  let usedMemory = getUsedMemory();
28
70
  let availableMemory = getAvailableMemory();
@@ -50,7 +92,9 @@ export const checkMemoryAllocation = function (bytes) {
50
92
  * @return {Number} - Returns used JSHeapSize in bytes or NaN if not supported
51
93
  */
52
94
  export const getUsedMemory = function () {
53
- return checkMemorySupport() ? performance.memory.usedJSHeapSize : NaN;
95
+ return checkMemorySupport()
96
+ ? (performance as Performance).memory.usedJSHeapSize
97
+ : NaN;
54
98
  };
55
99
 
56
100
  /**
@@ -63,7 +107,7 @@ export const getAvailableMemory = function () {
63
107
  if (checkMemorySupport()) {
64
108
  return customMemoryLimit
65
109
  ? customMemoryLimit
66
- : performance.memory.jsHeapSizeLimit - backingMemory;
110
+ : (performance as Performance).memory.jsHeapSizeLimit - backingMemory;
67
111
  } else {
68
112
  return NaN;
69
113
  }
@@ -75,7 +119,7 @@ export const getAvailableMemory = function () {
75
119
  * @function setAvailableMemory
76
120
  * @param {Number} - Number of GB to set as maximum custom memory limit
77
121
  */
78
- export const setAvailableMemory = function (value) {
122
+ export const setAvailableMemory = function (value: number) {
79
123
  customMemoryLimit = value * 1024 * 1024 * 1024;
80
124
  };
81
125
 
@@ -90,7 +134,9 @@ export const setAvailableMemory = function (value) {
90
134
  * @return {Boolean} - Returns memory object or false if not supported
91
135
  */
92
136
  const checkMemorySupport = function () {
93
- return performance.memory ? performance.memory : false;
137
+ return (performance as Performance).memory
138
+ ? (performance as Performance).memory
139
+ : false;
94
140
  };
95
141
 
96
142
  /**
@@ -100,6 +146,6 @@ const checkMemorySupport = function () {
100
146
  * @param {Number} bytes - Memory in bytes
101
147
  * @return {Number} - Memory in MB
102
148
  */
103
- const getMB = function (bytes) {
149
+ const getMB = function (bytes: number) {
104
150
  return bytes / 1048576;
105
151
  };
@@ -0,0 +1,34 @@
1
+ /** @module monitors/performance
2
+ * @desc This file provides utility functions for
3
+ * monitoring performance usage
4
+ */
5
+
6
+ var PERFORMANCE_MONITOR = false;
7
+
8
+ /**
9
+ * Get performance monitor
10
+ * @instance
11
+ * @function getPerformanceMonitor
12
+ * @returns {Boolean} - Performance monitor status
13
+ */
14
+ export const getPerformanceMonitor = function () {
15
+ return PERFORMANCE_MONITOR;
16
+ };
17
+
18
+ /**
19
+ * Set performance monitor ON
20
+ * @instance
21
+ * @function activatePerformanceMonitor
22
+ */
23
+ export const activatePerformanceMonitor = function () {
24
+ PERFORMANCE_MONITOR = true;
25
+ };
26
+
27
+ /**
28
+ * Set performance monitor OFF
29
+ * @instance
30
+ * @function deactivatePerformanceMonitor
31
+ */
32
+ export const deactivatePerformanceMonitor = function () {
33
+ PERFORMANCE_MONITOR = false;
34
+ };
@@ -0,0 +1,54 @@
1
+ /** @module imaging/parsers/ecg
2
+ * @desc This file provides functionalities for
3
+ * handling ECG signales in DICOM files
4
+ */
5
+
6
+ import { DataSet, Element } from "dicom-parser";
7
+ import { getSeriesDataFromLarvitarManager } from "../loaders/commonLoader";
8
+
9
+ /*
10
+ * This module provides the following functions to be exported:
11
+ * parseECG(dataSet, tag, nSampling)
12
+ */
13
+
14
+ /**
15
+ * Generate an array of points representing the ECG signal
16
+ * @instance
17
+ * @function parseECG
18
+ * @param {DataSet} dataSet - the DICOM dataset
19
+ * @param {String} tag - the tag of the ECG signal
20
+ * @param {Number} nSampling - the sampling rate
21
+ * @returns {void}
22
+ */
23
+ export function parseECG(
24
+ seriesId: string,
25
+ dataSet: DataSet,
26
+ tag: string,
27
+ nSampling: number = 2
28
+ ): void {
29
+ const element: Element = dataSet.elements[tag];
30
+ let data: Uint8Array = dataSet.byteArray.slice(
31
+ element.dataOffset,
32
+ element.dataOffset + element.length
33
+ );
34
+ let points: number[] = [];
35
+ const nCountFrom: number = data.length / 2;
36
+ const nCountTo: number = Math.floor(0.5 + nCountFrom / nSampling);
37
+ let values: number[] = [];
38
+ let nFrom: number = 0;
39
+ for (let nTo: number = 0; nTo < nCountTo; nTo++) {
40
+ let v: number = data[nFrom] + 255 * data[nFrom + 1];
41
+ values.push(v);
42
+ nFrom += nSampling * 2;
43
+ }
44
+
45
+ const nMax: number = Math.max(...values);
46
+ const nMin: number = Math.min(...values);
47
+
48
+ for (let nTo: number = 0; nTo < nCountTo; nTo++) {
49
+ let data: number = ((values[nTo] - nMin) / (nMax - nMin)) * 100;
50
+ points.push(data);
51
+ }
52
+ let series = getSeriesDataFromLarvitarManager(seriesId);
53
+ series!.ecgData = points;
54
+ }
@@ -0,0 +1,27 @@
1
+ # Tools Management
2
+
3
+ ## Default tools
4
+
5
+ In `default.ts` the list of Larvitar default tools is exported as `DEFAULT_TOOLS`, along with their default configuration, that extendes the cornerstoneTools configuration with these properties:
6
+
7
+ ```
8
+ {
9
+ name : toolName (string),
10
+ viewports : "all" or [array of target viewports],
11
+ configuration : configuration {object},
12
+ options : options {object},
13
+ class : cornerstone tool library class name (ie "LengthTool" for Length tool),
14
+ sync : cornerstone synchronizer name (ie "wwwcSynchronizer" for Wwwc sync tool),
15
+ cleanable : if true, this tool will be removed when calling "no tools",
16
+ defaultActive : if true, this tool will be activated when calling "addDefaultTools",
17
+ shortcut : keyboard shortcut [not implemented],
18
+ type : tool category inside Larvitar (one of: "utils", "annotation", "segmentation", "overlay"),
19
+ description: a string that describes the tool (eg to be shown in a tooltip)
20
+ }
21
+ ```
22
+
23
+ These are the tools that will be added calling `addDefaultTools`. User can override defaults calling `setDefaultToolsProps`.
24
+
25
+ ## External Tools
26
+
27
+ User can add custom tools calling `registerExternalTool`. The tool will be registered in the dvTools object and in DEFAULT*TOOLS array. If done \_before* adding the tools with `addDefaultTools`, the tool will be added automatically along with the default ones. Otherwise, the user can simply add its tool using `addTool`.
@@ -1,8 +1,8 @@
1
1
  /** @module imaging/tools/custom/4dSliceScrollTool
2
- * @desc This file provides functionalities for an alternative scroll tool
2
+ * @desc This file provides functionalities for an alternative scroll tool
3
3
  * to handle 4d exam and navigate to the correct slice
4
- *
5
- *
4
+ *
5
+ *
6
6
  */
7
7
 
8
8
  // external libraries
@@ -11,9 +11,9 @@ const external = cornerstoneTools.external;
11
11
 
12
12
  const BaseTool = cornerstoneTools.importInternal("base/BaseTool");
13
13
  const scroll = cornerstoneTools.importInternal("util/scroll");
14
- const scrollToIndex = cornerstoneTools.importInternal("util/scrollToIndex");
14
+ const scrollToIndex = cornerstoneTools.importInternal("util/scrollToIndex");
15
15
  const getToolState = cornerstoneTools.getToolState;
16
- const clip = cornerstoneTools.importInternal("util/clip");
16
+ const clip = cornerstoneTools.importInternal("util/clip");
17
17
 
18
18
  /**
19
19
  * @public
@@ -26,25 +26,23 @@ const clip = cornerstoneTools.importInternal("util/clip");
26
26
  export default class Slice4DScrollMouseWheelTool extends BaseTool {
27
27
  constructor(props = {}) {
28
28
  const defaultProps = {
29
- name: 'Slice4DScrollMouseWheel',
30
- supportedInteractionTypes: ['MouseWheel'],
29
+ name: "Slice4DScrollMouseWheel",
30
+ supportedInteractionTypes: ["MouseWheel"],
31
31
  configuration: {
32
32
  loop: false,
33
33
  allowSkipping: true,
34
- invert: false,
35
- },
34
+ invert: false
35
+ }
36
36
  };
37
- console.log('building wheel tool');
38
37
  super(props, defaultProps);
39
38
  }
40
39
 
41
40
  mouseWheelCallback(evt) {
42
41
  const { direction: images, element } = evt.detail;
43
42
  const { loop, allowSkipping, invert, framesNumber } = this.configuration;
44
- const direction = invert ? (images * framesNumber)*(-1) : (images * framesNumber);
45
- console.log('wheel callback');
46
- console.log('Images ', images);
47
- console.log('Direction ', direction);
43
+ const direction = invert
44
+ ? images * framesNumber * -1
45
+ : images * framesNumber;
48
46
  scroll(element, direction, loop, allowSkipping);
49
47
  // scroll4DSlices(element, direction, loop, allowSkipping);
50
48
  }
@@ -60,41 +58,44 @@ export default class Slice4DScrollMouseWheelTool extends BaseTool {
60
58
  * @param {type} [allowSkipping = true] Whether frames can be skipped.
61
59
  * @returns {void}
62
60
  */
63
- const scroll4DSlices = function(element, images, loop, allowSkipping, framesNumber) {
64
- const toolData = getToolState(element, 'stack');
61
+ const scroll4DSlices = function (
62
+ element,
63
+ images,
64
+ loop,
65
+ allowSkipping,
66
+ framesNumber
67
+ ) {
68
+ const toolData = getToolState(element, "stack");
69
+
70
+ if (!toolData || !toolData.data || !toolData.data.length) {
71
+ return;
72
+ }
65
73
 
66
- if (!toolData || !toolData.data || !toolData.data.length) {
67
- return;
68
- }
74
+ const stackData = toolData.data[0];
69
75
 
70
- const stackData = toolData.data[0];
76
+ if (!stackData.pending) {
77
+ stackData.pending = [];
78
+ }
71
79
 
72
- if (!stackData.pending) {
73
- stackData.pending = [];
74
- }
75
-
76
- let newImageIdIndex = stackData.currentImageIdIndex + images ;//+ 1 + framesNumber;
77
- console.log('currentImageIdIndex', stackData.currentImageIdIndex)
78
- console.log('newImageIdIndex calculated ', newImageIdIndex);
79
- if (loop) {
80
- const nbImages = stackData.imageIds.length;
81
- newImageIdIndex %= nbImages;
82
- } else {
83
- newImageIdIndex = clip(newImageIdIndex, 0, stackData.imageIds.length - 1);
84
- console.log('newImageIdIndex after clip ', newImageIdIndex);
85
- }
80
+ let newImageIdIndex = stackData.currentImageIdIndex + images; //+ 1 + framesNumber;
81
+ if (loop) {
82
+ const nbImages = stackData.imageIds.length;
83
+ newImageIdIndex %= nbImages;
84
+ } else {
85
+ newImageIdIndex = clip(newImageIdIndex, 0, stackData.imageIds.length - 1);
86
+ }
86
87
 
87
- if (allowSkipping) {
88
- scrollToIndex(element, newImageIdIndex);
89
- } else {
90
- const pendingEvent = {
91
- index: newImageIdIndex,
92
- };
88
+ if (allowSkipping) {
89
+ scrollToIndex(element, newImageIdIndex);
90
+ } else {
91
+ const pendingEvent = {
92
+ index: newImageIdIndex
93
+ };
93
94
 
94
- stackData.pending.push(pendingEvent);
95
- scrollWithoutSkipping(stackData, pendingEvent, element);
96
- }
97
- }
95
+ stackData.pending.push(pendingEvent);
96
+ scrollWithoutSkipping(stackData, pendingEvent, element);
97
+ }
98
+ };
98
99
 
99
100
  /**
100
101
  * Recursively scrolls the stack until the desired image is reached.
@@ -119,7 +120,7 @@ function scrollWithoutSkipping(stackData, pendingEvent, element) {
119
120
  return;
120
121
  }
121
122
 
122
- const newImageHandler = function(event) {
123
+ const newImageHandler = function (event) {
123
124
  const index = stackData.imageIds.indexOf(event.detail.image.imageId);
124
125
 
125
126
  if (index === pendingEvent.index) {
@@ -142,4 +143,4 @@ function scrollWithoutSkipping(stackData, pendingEvent, element) {
142
143
 
143
144
  scrollToIndex(element, pendingEvent.index);
144
145
  }
145
- }
146
+ }
@@ -0,0 +1,99 @@
1
+ import cornerstone from "cornerstone-core";
2
+ import cornerstoneTools from "cornerstone-tools";
3
+ const MagnifyTool = cornerstoneTools.MagnifyTool;
4
+ const drawTextBox = cornerstoneTools.importInternal("drawing/drawTextBox");
5
+ const textStyle = cornerstoneTools.textStyle;
6
+ const toolColors = cornerstoneTools.toolColors;
7
+
8
+ export default class BorderMagnifyTool extends MagnifyTool {
9
+ constructor(props = {}) {
10
+ super(props);
11
+
12
+ // Additional configuration options
13
+ this.configuration.showBorders = props.showBorders || true; // Default to true
14
+ this.configuration.showInfo = props.showInfo || true; // Default to true
15
+ this.configuration.borderColor = props.borderColor ; // Default border color is green
16
+
17
+
18
+ // Add global keydown event listener
19
+ window.addEventListener('keydown', this.handleKeyDown.bind(this));
20
+ }
21
+
22
+ /**
23
+ * Event handler for the "keydown" event to toggle the visibility of borders and info on "B" key press.
24
+ * @param {KeyboardEvent} event
25
+ * @returns {void}
26
+ */
27
+ handleKeyDown(event) {
28
+ if (event.key === 'B' || event.key === 'b') {
29
+ // Toggle the visibility of borders
30
+ this.configuration.showBorders = !this.configuration.showBorders;
31
+
32
+ // Toggle the visibility of zoom/ROI info
33
+ this.configuration.showInfo = !this.configuration.showInfo;
34
+
35
+ // Redraw the magnification tool
36
+ this._drawMagnificationTool();
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Overrides the _drawMagnificationTool method to add configurable borders and display zoom/ROI dimensions.
42
+ * @param {*} evt
43
+ * @returns {void}
44
+ */
45
+ _drawMagnificationTool(evt) {
46
+ // Call the parent method to draw the magnification tool
47
+ super._drawMagnificationTool(evt);
48
+ // Query for the magnify canvas using the correct class name
49
+ const magnifyCanvas = evt ? evt.detail.element.querySelector('.magnifyTool') : null;
50
+
51
+ if (magnifyCanvas) {
52
+ const context = magnifyCanvas.getContext('2d');
53
+
54
+ // Check if the user wants to show borders
55
+ if (this.configuration.showBorders) {
56
+ // Add configurable borders
57
+ context.strokeStyle = this.configuration.borderColor|| toolColors.getColorIfActive({active: true});
58
+ context.lineWidth = 4;
59
+ context.strokeRect(0, 0, magnifyCanvas.width, magnifyCanvas.height);
60
+ }
61
+
62
+ // Check if the user wants to show info
63
+ if (this.configuration.showInfo) {
64
+ // Get the zoom level
65
+ const viewport = cornerstone.getViewport(evt.detail.element);
66
+ const zoomLevel = viewport.scale.toFixed(2); // Adjust the precision as needed
67
+
68
+ // Get ROI dimensions
69
+ const roiWidth = magnifyCanvas.width;
70
+ const roiHeight = magnifyCanvas.height;
71
+ const roiArea = (roiWidth * roiHeight).toFixed(2); // Area of the ROI
72
+
73
+ // Display the zoom level and ROI dimensions
74
+ //context.fillStyle = this.configuration.borderColor; // Adjust text color as needed
75
+ //context.font = 'bold 14px Arial';
76
+ //context.fillText(`Zoom: x${zoomLevel}`, 10, 20);
77
+ //context.fillText(`ROI Area: ${roiWidth} x ${roiHeight} square pixels`, 10, 40);
78
+ const text = `Zoom: x${zoomLevel}`;
79
+ const str = `ROI: ${roiWidth}px x ${roiHeight}px`;
80
+ const fontHeight = textStyle.getFontSize();
81
+ const color=this.configuration.borderColor|| toolColors.getColorIfActive({active: true});
82
+ // Draw text 5px away from cursor
83
+ const textCoords = {
84
+ x: 5,
85
+ y: 2,
86
+ };
87
+
88
+ drawTextBox(
89
+ context,
90
+ str,
91
+ textCoords.x,
92
+ textCoords.y + fontHeight + 5,
93
+ color
94
+ );
95
+ drawTextBox(context, text, textCoords.x, textCoords.y, color);
96
+ }
97
+ }
98
+ }
99
+ }