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.
- package/.vscode/settings.json +4 -0
- package/README.md +78 -48
- package/bundler/webpack.common.js +27 -0
- package/bundler/webpack.dev.js +23 -0
- package/bundler/webpack.prod.js +19 -0
- package/decs.d.ts +12 -0
- package/dist/imaging/MetaDataReadable.d.ts +40 -0
- package/dist/imaging/MetaDataTypes.d.ts +3489 -0
- package/dist/imaging/imageAnonymization.d.ts +12 -0
- package/dist/imaging/imageColormaps.d.ts +47 -0
- package/dist/imaging/imageContours.d.ts +18 -0
- package/dist/imaging/imageIo.d.ts +42 -0
- package/dist/imaging/imageLayers.d.ts +56 -0
- package/dist/imaging/imageLoading.d.ts +65 -0
- package/dist/imaging/imageParsing.d.ts +46 -0
- package/dist/imaging/imagePresets.d.ts +43 -0
- package/dist/imaging/imageRendering.d.ts +238 -0
- package/dist/imaging/imageReslice.d.ts +14 -0
- package/dist/imaging/imageStore.d.ts +121 -0
- package/dist/imaging/imageTags.d.ts +22 -0
- package/dist/imaging/imageTools.d.ts +20 -0
- package/dist/imaging/imageUtils.d.ts +165 -0
- package/dist/imaging/loaders/commonLoader.d.ts +103 -0
- package/dist/imaging/loaders/dicomLoader.d.ts +29 -0
- package/dist/imaging/loaders/fileLoader.d.ts +33 -0
- package/dist/imaging/loaders/multiframeLoader.d.ts +37 -0
- package/dist/imaging/loaders/nrrdLoader.d.ts +113 -0
- package/dist/imaging/loaders/resliceLoader.d.ts +15 -0
- package/dist/imaging/monitors/memory.d.ts +41 -0
- package/dist/imaging/monitors/performance.d.ts +23 -0
- package/dist/imaging/parsers/ecg.d.ts +15 -0
- package/dist/imaging/parsers/nrrd.d.ts +3 -0
- package/dist/imaging/tools/custom/4dSliceScrollTool.d.ts +12 -0
- package/dist/imaging/tools/custom/BorderMagnifyTool.d.ts +18 -0
- package/dist/imaging/tools/custom/contourTool.d.ts +409 -0
- package/dist/imaging/tools/custom/diameterTool.d.ts +18 -0
- package/dist/imaging/tools/custom/editMaskTool.d.ts +22 -0
- package/dist/imaging/tools/custom/ellipticalRoiOverlayTool.d.ts +45 -0
- package/dist/imaging/tools/custom/polygonSegmentationMixin.d.ts +54 -0
- package/dist/imaging/tools/custom/polylineScissorsTool.d.ts +11 -0
- package/dist/imaging/tools/custom/rectangleRoiOverlayTool.d.ts +45 -0
- package/dist/imaging/tools/custom/seedTool.d.ts +0 -0
- package/dist/imaging/tools/custom/setLabelMap3D.d.ts +39 -0
- package/dist/imaging/tools/custom/thresholdsBrushTool.d.ts +19 -0
- package/dist/imaging/tools/default.d.ts +53 -0
- package/dist/imaging/tools/interaction.d.ts +30 -0
- package/dist/imaging/tools/io.d.ts +38 -0
- package/dist/imaging/tools/main.d.ts +81 -0
- package/dist/imaging/tools/segmentation.d.ts +125 -0
- package/dist/imaging/tools/state.d.ts +17 -0
- package/dist/imaging/tools/strategies/eraseFreehand.d.ts +16 -0
- package/dist/imaging/tools/strategies/fillFreehand.d.ts +16 -0
- package/dist/imaging/tools/strategies/index.d.ts +2 -0
- package/dist/imaging/waveforms/ecg.d.ts +39 -0
- package/dist/index.d.ts +35 -0
- package/dist/larvitar.js +90104 -0
- package/dist/larvitar.js.map +1 -0
- package/imaging/MetaDataReadable.ts +41 -0
- package/imaging/MetaDataTypes.ts +3491 -0
- package/imaging/dataDictionary.json +5328 -5328
- package/imaging/{imageAnonymization.js → imageAnonymization.ts} +41 -13
- package/imaging/{imageColormaps.js → imageColormaps.ts} +48 -30
- package/imaging/{imageContours.js → imageContours.ts} +24 -22
- package/imaging/{imageIo.js → imageIo.ts} +89 -52
- package/imaging/{imageLayers.js → imageLayers.ts} +31 -14
- package/imaging/{imageLoading.js → imageLoading.ts} +107 -43
- package/imaging/{imageParsing.js → imageParsing.ts} +160 -80
- package/imaging/{imagePresets.js → imagePresets.ts} +44 -11
- package/imaging/imageRendering.ts +1091 -0
- package/imaging/{imageReslice.js → imageReslice.ts} +18 -9
- package/imaging/imageStore.ts +487 -0
- package/imaging/imageTags.ts +609 -0
- package/imaging/imageTools.js +2 -1
- package/imaging/{imageUtils.js → imageUtils.ts} +211 -701
- package/imaging/loaders/{commonLoader.js → commonLoader.ts} +73 -24
- package/imaging/loaders/{dicomLoader.js → dicomLoader.ts} +25 -5
- package/imaging/loaders/{fileLoader.js → fileLoader.ts} +5 -5
- package/imaging/loaders/{multiframeLoader.js → multiframeLoader.ts} +145 -90
- package/imaging/loaders/{nrrdLoader.js → nrrdLoader.ts} +231 -64
- package/imaging/loaders/{resliceLoader.js → resliceLoader.ts} +51 -20
- package/imaging/monitors/{memory.js → memory.ts} +54 -8
- package/imaging/monitors/performance.ts +34 -0
- package/imaging/parsers/ecg.ts +54 -0
- package/imaging/tools/README.md +27 -0
- package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
- package/imaging/tools/custom/BorderMagnifyTool.js +99 -0
- package/imaging/tools/custom/ellipticalRoiOverlayTool.js +534 -0
- package/imaging/tools/custom/polylineScissorsTool.js +1 -1
- package/imaging/tools/custom/rectangleRoiOverlayTool.js +564 -0
- package/imaging/tools/{setLabelMap3D.js → custom/setLabelMap3D.ts} +19 -25
- package/imaging/tools/{default.js → default.ts} +119 -33
- package/imaging/tools/{interaction.js → interaction.ts} +42 -23
- package/imaging/tools/{io.js → io.ts} +47 -31
- package/imaging/tools/{main.js → main.ts} +105 -40
- package/imaging/tools/{segmentation.js → segmentation.ts} +95 -68
- package/imaging/tools/{state.js → state.ts} +7 -12
- package/imaging/tools/types.d.ts +243 -0
- package/imaging/types.d.ts +200 -0
- package/imaging/waveforms/ecg.ts +191 -0
- package/{index.js → index.ts} +53 -14
- package/jsdoc.json +1 -1
- package/package.json +35 -14
- package/tsconfig.json +102 -0
- package/imaging/imageRendering.js +0 -860
- package/imaging/imageStore.js +0 -322
- package/modules/vuex/larvitar.js +0 -187
- /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
|
-
*
|
|
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()
|
|
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
|
|
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
|
|
14
|
+
const scrollToIndex = cornerstoneTools.importInternal("util/scrollToIndex");
|
|
15
15
|
const getToolState = cornerstoneTools.getToolState;
|
|
16
|
-
const 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:
|
|
30
|
-
supportedInteractionTypes: [
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
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(
|
|
64
|
-
|
|
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
|
-
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
74
|
+
const stackData = toolData.data[0];
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
if (!stackData.pending) {
|
|
77
|
+
stackData.pending = [];
|
|
78
|
+
}
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
if (allowSkipping) {
|
|
89
|
+
scrollToIndex(element, newImageIdIndex);
|
|
90
|
+
} else {
|
|
91
|
+
const pendingEvent = {
|
|
92
|
+
index: newImageIdIndex
|
|
93
|
+
};
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
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
|
+
}
|