larvitar 1.5.13 → 2.0.0
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 +39 -0
- package/dist/imaging/MetaDataTypes.d.ts +3488 -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 +112 -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/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/index.d.ts +34 -0
- package/dist/larvitar.js +89801 -0
- package/dist/larvitar.js.map +1 -0
- package/imaging/MetaDataReadable.ts +40 -0
- package/imaging/MetaDataTypes.ts +3490 -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} +108 -45
- package/imaging/{imageParsing.js → imageParsing.ts} +158 -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} +230 -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 +51 -0
- package/imaging/tools/README.md +27 -0
- package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
- 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} +114 -30
- 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 +197 -0
- package/{index.js → index.ts} +43 -14
- package/jsdoc.json +1 -1
- package/package.json +32 -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
|
@@ -20,20 +20,31 @@
|
|
|
20
20
|
* cleanable : if true, this tool will be removed when calling "no tools",
|
|
21
21
|
* defaultActive : if true, this tool will be activated when calling "addDefaultTools",
|
|
22
22
|
* shortcut : keyboard shortcut [not implemented],
|
|
23
|
-
* type : tool category inside Larvitar (one of: "utils", "annotation", "segmentation")
|
|
23
|
+
* type : tool category inside Larvitar (one of: "utils", "annotation", "segmentation", "overlay")
|
|
24
24
|
* }
|
|
25
25
|
*
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { filter, isArray } from "lodash";
|
|
29
29
|
import ThresholdsBrushTool from "./custom/thresholdsBrushTool";
|
|
30
|
-
import Slice4DScrollMouseWheelTool from "./custom/4dSliceScrollTool";
|
|
30
|
+
// import Slice4DScrollMouseWheelTool from "./custom/4dSliceScrollTool";
|
|
31
31
|
import PolylineScissorsTool from "./custom/polylineScissorsTool";
|
|
32
|
+
import RectangleRoiOverlayTool from "./custom/rectangleRoiOverlayTool";
|
|
33
|
+
import EllipticalRoiOverlayTool from "./custom/ellipticalRoiOverlayTool";
|
|
34
|
+
|
|
35
|
+
import type {
|
|
36
|
+
ToolConfig,
|
|
37
|
+
ToolMouseKeys,
|
|
38
|
+
ToolSettings,
|
|
39
|
+
ToolStyle
|
|
40
|
+
} from "./types";
|
|
32
41
|
|
|
33
42
|
/**
|
|
34
43
|
* These tools are added with `addDefaultTools()`
|
|
35
44
|
*/
|
|
36
|
-
const DEFAULT_TOOLS
|
|
45
|
+
const DEFAULT_TOOLS: {
|
|
46
|
+
[key: string]: ToolConfig;
|
|
47
|
+
} = {
|
|
37
48
|
ScaleOverlay: {
|
|
38
49
|
name: "ScaleOverlay",
|
|
39
50
|
viewports: "all",
|
|
@@ -47,7 +58,6 @@ const DEFAULT_TOOLS = {
|
|
|
47
58
|
cleanable: false,
|
|
48
59
|
defaultActive: false,
|
|
49
60
|
class: "ScaleOverlayTool",
|
|
50
|
-
sync: null,
|
|
51
61
|
description: "Add scale overlay",
|
|
52
62
|
shortcut: "ctrl-m",
|
|
53
63
|
type: "overlay"
|
|
@@ -62,7 +72,6 @@ const DEFAULT_TOOLS = {
|
|
|
62
72
|
cleanable: false,
|
|
63
73
|
defaultActive: false,
|
|
64
74
|
class: "OrientationMarkersTool",
|
|
65
|
-
sync: null,
|
|
66
75
|
description: "Add orientation markers",
|
|
67
76
|
shortcut: "ctrl-m",
|
|
68
77
|
type: "overlay"
|
|
@@ -78,7 +87,7 @@ const DEFAULT_TOOLS = {
|
|
|
78
87
|
cleanable: false,
|
|
79
88
|
defaultActive: true,
|
|
80
89
|
class: "WwwcTool",
|
|
81
|
-
sync: "wwwcSynchronizer",
|
|
90
|
+
// sync: "wwwcSynchronizer",
|
|
82
91
|
description: "Change image contrast",
|
|
83
92
|
shortcut: "ctrl-m",
|
|
84
93
|
type: "utils"
|
|
@@ -94,38 +103,53 @@ const DEFAULT_TOOLS = {
|
|
|
94
103
|
cleanable: false,
|
|
95
104
|
defaultActive: false,
|
|
96
105
|
class: "WwwcRegionTool",
|
|
97
|
-
sync: "wwwcSynchronizer",
|
|
106
|
+
// sync: "wwwcSynchronizer",
|
|
98
107
|
description: "Change image contrast based on selected region",
|
|
99
108
|
shortcut: "ctrl-m",
|
|
100
109
|
type: "utils"
|
|
101
110
|
},
|
|
102
|
-
|
|
103
|
-
name: "
|
|
111
|
+
StackScroll: {
|
|
112
|
+
name: "StackScroll",
|
|
104
113
|
viewports: "all",
|
|
105
|
-
configuration: {
|
|
106
|
-
options: {
|
|
114
|
+
configuration: {
|
|
107
115
|
loop: false, // default false
|
|
108
|
-
allowSkipping:
|
|
109
|
-
|
|
116
|
+
allowSkipping: true // default true
|
|
117
|
+
},
|
|
118
|
+
options: {
|
|
119
|
+
mouseButtonMask: 1,
|
|
120
|
+
deltaY: 0 // default 0
|
|
110
121
|
},
|
|
111
122
|
cleanable: false,
|
|
112
123
|
defaultActive: false,
|
|
113
|
-
class: "
|
|
124
|
+
class: "StackScrollTool"
|
|
114
125
|
},
|
|
115
|
-
|
|
116
|
-
name: "
|
|
126
|
+
StackScrollMouseWheel: {
|
|
127
|
+
name: "StackScrollMouseWheel",
|
|
117
128
|
viewports: "all",
|
|
118
129
|
configuration: {
|
|
119
130
|
loop: false, // default false
|
|
120
|
-
allowSkipping:
|
|
121
|
-
invert: false
|
|
122
|
-
framesNumber: 1
|
|
131
|
+
allowSkipping: true, // default true
|
|
132
|
+
invert: false
|
|
123
133
|
},
|
|
124
134
|
options: {},
|
|
125
135
|
cleanable: false,
|
|
126
136
|
defaultActive: true,
|
|
127
|
-
class: "
|
|
137
|
+
class: "StackScrollMouseWheelTool"
|
|
128
138
|
},
|
|
139
|
+
// Slice4DScrollMouseWheel: {
|
|
140
|
+
// name: "Slice4DScrollMouseWheel",
|
|
141
|
+
// viewports: "all",
|
|
142
|
+
// configuration: {
|
|
143
|
+
// loop: false, // default false
|
|
144
|
+
// allowSkipping: false, // default true
|
|
145
|
+
// invert: false,
|
|
146
|
+
// framesNumber: 1
|
|
147
|
+
// },
|
|
148
|
+
// options: {},
|
|
149
|
+
// cleanable: false,
|
|
150
|
+
// defaultActive: true,
|
|
151
|
+
// class: "Slice4DScrollMouseWheelTool"
|
|
152
|
+
// },
|
|
129
153
|
Pan: {
|
|
130
154
|
name: "Pan",
|
|
131
155
|
viewports: "all",
|
|
@@ -246,6 +270,7 @@ const DEFAULT_TOOLS = {
|
|
|
246
270
|
RectangleRoi: {
|
|
247
271
|
name: "RectangleRoi",
|
|
248
272
|
viewports: "all",
|
|
273
|
+
configuration: {},
|
|
249
274
|
options: { mouseButtonMask: 1 },
|
|
250
275
|
cleanable: true,
|
|
251
276
|
defaultActive: false,
|
|
@@ -254,6 +279,29 @@ const DEFAULT_TOOLS = {
|
|
|
254
279
|
shortcut: "ctrl-a",
|
|
255
280
|
type: "annotation"
|
|
256
281
|
},
|
|
282
|
+
EllipticalRoiOverlay: {
|
|
283
|
+
name: "EllipticalRoiOverlay",
|
|
284
|
+
viewports: "all",
|
|
285
|
+
configuration: {},
|
|
286
|
+
options: { mouseButtonMask: 1 },
|
|
287
|
+
cleanable: true,
|
|
288
|
+
class: "EllipticalRoiOverlayTool",
|
|
289
|
+
description: "Draw an ellipse",
|
|
290
|
+
shortcut: "ctrl-f",
|
|
291
|
+
type: "annotation"
|
|
292
|
+
},
|
|
293
|
+
RectangleRoiOverlay: {
|
|
294
|
+
name: "RectangleRoiOverlay",
|
|
295
|
+
viewports: "all",
|
|
296
|
+
configuration: {},
|
|
297
|
+
options: { mouseButtonMask: 1 },
|
|
298
|
+
cleanable: true,
|
|
299
|
+
defaultActive: false,
|
|
300
|
+
class: "RectangleRoiOverlayTool",
|
|
301
|
+
description: "Draw a rectangle",
|
|
302
|
+
shortcut: "ctrl-a",
|
|
303
|
+
type: "annotation"
|
|
304
|
+
},
|
|
257
305
|
FreehandRoi: {
|
|
258
306
|
name: "FreehandRoi",
|
|
259
307
|
viewports: "all",
|
|
@@ -268,6 +316,7 @@ const DEFAULT_TOOLS = {
|
|
|
268
316
|
Probe: {
|
|
269
317
|
name: "Probe",
|
|
270
318
|
viewports: "all",
|
|
319
|
+
configuration: {},
|
|
271
320
|
options: { mouseButtonMask: 1 },
|
|
272
321
|
cleanable: true,
|
|
273
322
|
class: "ProbeTool"
|
|
@@ -411,10 +460,14 @@ const DEFAULT_TOOLS = {
|
|
|
411
460
|
/**
|
|
412
461
|
* D/Vision Lab custom tools
|
|
413
462
|
*/
|
|
414
|
-
const dvTools
|
|
463
|
+
const dvTools: {
|
|
464
|
+
[key: string]: any; // TODO-ts tools class type @mronzoni
|
|
465
|
+
} = {
|
|
415
466
|
ThresholdsBrushTool: ThresholdsBrushTool,
|
|
416
467
|
PolylineScissorsTool: PolylineScissorsTool,
|
|
417
|
-
Slice4DScrollMouseWheelTool: Slice4DScrollMouseWheelTool
|
|
468
|
+
// Slice4DScrollMouseWheelTool: Slice4DScrollMouseWheelTool,
|
|
469
|
+
RectangleRoiOverlayTool: RectangleRoiOverlayTool,
|
|
470
|
+
EllipticalRoiOverlayTool: EllipticalRoiOverlayTool
|
|
418
471
|
};
|
|
419
472
|
|
|
420
473
|
/**
|
|
@@ -424,7 +477,7 @@ const dvTools = {
|
|
|
424
477
|
* Helvetica Neue Light, Helvetica Neue, Helvetica,
|
|
425
478
|
* Arial, Lucida Grande, sans-serif;
|
|
426
479
|
*/
|
|
427
|
-
const DEFAULT_STYLE = {
|
|
480
|
+
const DEFAULT_STYLE: ToolStyle = {
|
|
428
481
|
width: 1,
|
|
429
482
|
color: "#02FAE5",
|
|
430
483
|
activeColor: "#00FF00",
|
|
@@ -437,7 +490,7 @@ const DEFAULT_STYLE = {
|
|
|
437
490
|
/**
|
|
438
491
|
* Tools default settings
|
|
439
492
|
*/
|
|
440
|
-
const DEFAULT_SETTINGS = {
|
|
493
|
+
const DEFAULT_SETTINGS: ToolSettings = {
|
|
441
494
|
mouseEnabled: true,
|
|
442
495
|
touchEnabled: true,
|
|
443
496
|
showSVGCursors: true,
|
|
@@ -449,7 +502,7 @@ const DEFAULT_SETTINGS = {
|
|
|
449
502
|
/**
|
|
450
503
|
* Shortcut and mouse bindings defaults
|
|
451
504
|
*/
|
|
452
|
-
const DEFAULT_MOUSE_KEYS = {
|
|
505
|
+
const DEFAULT_MOUSE_KEYS: ToolMouseKeys = {
|
|
453
506
|
debug: true, // log changes
|
|
454
507
|
mouse_button_left: {
|
|
455
508
|
shift: "Zoom",
|
|
@@ -473,7 +526,7 @@ const DEFAULT_MOUSE_KEYS = {
|
|
|
473
526
|
* Get available tools by type (useful to populate menus)
|
|
474
527
|
* @param {String} type
|
|
475
528
|
*/
|
|
476
|
-
const getDefaultToolsByType = function (type) {
|
|
529
|
+
const getDefaultToolsByType = function (type: NonNullable<ToolConfig["type"]>) {
|
|
477
530
|
return filter(DEFAULT_TOOLS, ["type", type]);
|
|
478
531
|
};
|
|
479
532
|
|
|
@@ -482,14 +535,19 @@ const getDefaultToolsByType = function (type) {
|
|
|
482
535
|
* @param {Array} newProps - An array of objects as in the DEFAULT_TOOLS list, but with a subset of props
|
|
483
536
|
* NOTE: prop "name" is mandatory
|
|
484
537
|
*/
|
|
485
|
-
const setDefaultToolsProps = function (newProps) {
|
|
538
|
+
const setDefaultToolsProps = function (newProps: Partial<ToolConfig>[]) {
|
|
486
539
|
if (isArray(newProps)) {
|
|
487
540
|
newProps.forEach(props => {
|
|
541
|
+
if (!props.name) {
|
|
542
|
+
console.error("newProps must have a name property");
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
488
546
|
let targetTool = DEFAULT_TOOLS[props.name];
|
|
489
547
|
if (targetTool) {
|
|
490
548
|
DEFAULT_TOOLS[props.name] = Object.assign(targetTool, props);
|
|
491
549
|
} else {
|
|
492
|
-
console.error(`${
|
|
550
|
+
console.error(`${props.name} does not exist`);
|
|
493
551
|
}
|
|
494
552
|
});
|
|
495
553
|
} else {
|
|
@@ -497,6 +555,31 @@ const setDefaultToolsProps = function (newProps) {
|
|
|
497
555
|
}
|
|
498
556
|
};
|
|
499
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Register a custom tool
|
|
560
|
+
* @param {String} toolName - The name of the tool
|
|
561
|
+
* @param {Object} toolClass - The tool class
|
|
562
|
+
* NOTE: toolName must be unique
|
|
563
|
+
* NOTE: toolClass must be a valid cornerstone tool
|
|
564
|
+
*/
|
|
565
|
+
|
|
566
|
+
const registerExternalTool = function (toolName: string, toolClass: any) {
|
|
567
|
+
if (dvTools[toolName] || DEFAULT_TOOLS[toolName]) {
|
|
568
|
+
console.error(`${toolName} already exists`);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
dvTools[toolClass.name] = toolClass;
|
|
573
|
+
DEFAULT_TOOLS[toolName] = {
|
|
574
|
+
name: toolName,
|
|
575
|
+
class: toolClass.name,
|
|
576
|
+
viewports: "all",
|
|
577
|
+
configuration: {},
|
|
578
|
+
options: { mouseButtonMask: 1 },
|
|
579
|
+
defaultActive: false
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
|
|
500
583
|
export {
|
|
501
584
|
DEFAULT_TOOLS,
|
|
502
585
|
DEFAULT_STYLE,
|
|
@@ -504,5 +587,6 @@ export {
|
|
|
504
587
|
DEFAULT_MOUSE_KEYS,
|
|
505
588
|
dvTools,
|
|
506
589
|
getDefaultToolsByType,
|
|
507
|
-
setDefaultToolsProps
|
|
508
|
-
|
|
590
|
+
setDefaultToolsProps,
|
|
591
|
+
registerExternalTool
|
|
592
|
+
};
|
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
import { throttle } from "lodash";
|
|
8
8
|
import * as keyCodes from "keycode-js";
|
|
9
9
|
import cornerstone from "cornerstone-core";
|
|
10
|
-
import cornerstoneTools from "cornerstone-tools
|
|
10
|
+
import cornerstoneTools from "cornerstone-tools";
|
|
11
11
|
|
|
12
12
|
// internal libraries
|
|
13
13
|
import { DEFAULT_MOUSE_KEYS } from "./default";
|
|
14
14
|
import { setToolActive } from "./main";
|
|
15
15
|
import { isElement } from "../imageUtils";
|
|
16
|
-
import {
|
|
16
|
+
import store, { set as setStore } from "../imageStore";
|
|
17
17
|
import { updateViewportData } from "../imageRendering";
|
|
18
|
+
import type { ToolMouseKeys } from "./types";
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* TOOLS INTERACTIONS TODOS:
|
|
@@ -26,8 +27,8 @@ import { updateViewportData } from "../imageRendering";
|
|
|
26
27
|
/**
|
|
27
28
|
* Global event callbacks
|
|
28
29
|
*/
|
|
29
|
-
let onKeyDownFn = null;
|
|
30
|
-
let onKeyUpFn = null;
|
|
30
|
+
let onKeyDownFn: ((evt: KeyboardEvent) => void) | null = null;
|
|
31
|
+
let onKeyUpFn: ((evt: KeyboardEvent) => void) | null = null;
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Setup mouse handler modifiers and keyboard shortcuts:
|
|
@@ -42,7 +43,7 @@ let onKeyUpFn = null;
|
|
|
42
43
|
* @param {Object} config - see tools/default
|
|
43
44
|
*/
|
|
44
45
|
|
|
45
|
-
export function addMouseKeyHandlers(config) {
|
|
46
|
+
export function addMouseKeyHandlers(config: ToolMouseKeys) {
|
|
46
47
|
if (!config) {
|
|
47
48
|
config = DEFAULT_MOUSE_KEYS;
|
|
48
49
|
}
|
|
@@ -64,30 +65,42 @@ export function addMouseKeyHandlers(config) {
|
|
|
64
65
|
let allViewports = cornerstone.getEnabledElements().map(enel => enel.element);
|
|
65
66
|
|
|
66
67
|
// Define behaviour on key down: activate registered tool
|
|
67
|
-
function onKeyDown(evt) {
|
|
68
|
+
function onKeyDown(evt: KeyboardEvent) {
|
|
68
69
|
// keyboard shortcuts (activate on left mouse button)
|
|
69
70
|
let codes = config.keyboard_shortcuts
|
|
70
|
-
? Object.keys(config.keyboard_shortcuts).map(
|
|
71
|
+
? Object.keys(config.keyboard_shortcuts).map(
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
key => keyCodes[key]
|
|
74
|
+
)
|
|
71
75
|
: [];
|
|
72
76
|
|
|
73
77
|
if (codes.includes(evt.keyCode) && evt.altKey) {
|
|
74
78
|
evt.preventDefault(); // avoid browser menu selections
|
|
75
79
|
|
|
76
80
|
let key = Object.keys(config.keyboard_shortcuts)
|
|
77
|
-
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
.filter(key => keyCodes[key] == evt.keyCode) // TODO keyCode is deprecated
|
|
78
83
|
.pop();
|
|
79
|
-
|
|
84
|
+
|
|
85
|
+
if (!key) {
|
|
86
|
+
console.warn("Key not found in config.keyboard_shortcuts");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let toolName = config.keyboard_shortcuts[key];
|
|
91
|
+
|
|
92
|
+
if (config.debug) console.log("active", toolName);
|
|
93
|
+
|
|
80
94
|
const viewports = allViewports.filter(viewport =>
|
|
81
|
-
cornerstoneTools.getToolForElement(
|
|
82
|
-
viewport,
|
|
83
|
-
config.keyboard_shortcuts[key]
|
|
84
|
-
)
|
|
95
|
+
cornerstoneTools.getToolForElement(viewport, toolName)
|
|
85
96
|
);
|
|
97
|
+
|
|
86
98
|
setToolActive(
|
|
87
|
-
|
|
99
|
+
toolName,
|
|
88
100
|
{ mouseButtonMask: 1 },
|
|
89
101
|
viewports.map(v => v.id)
|
|
90
102
|
);
|
|
103
|
+
|
|
91
104
|
document.addEventListener("keydown", onKeyDown, { once: true });
|
|
92
105
|
}
|
|
93
106
|
// right drag + shift
|
|
@@ -140,7 +153,7 @@ export function addMouseKeyHandlers(config) {
|
|
|
140
153
|
}
|
|
141
154
|
|
|
142
155
|
// Define behaviour on key up: restore original tool
|
|
143
|
-
function onKeyUp(e) {
|
|
156
|
+
function onKeyUp(e: KeyboardEvent) {
|
|
144
157
|
if (config.debug)
|
|
145
158
|
console.log("active default", config.mouse_button_right.default);
|
|
146
159
|
const viewports = allViewports.filter(viewport =>
|
|
@@ -197,6 +210,7 @@ export function addMouseKeyHandlers(config) {
|
|
|
197
210
|
*
|
|
198
211
|
*/
|
|
199
212
|
export function removeMouseKeyHandlers() {
|
|
213
|
+
if (!onKeyDownFn) return;
|
|
200
214
|
document.removeEventListener("keydown", onKeyDownFn);
|
|
201
215
|
onKeyDownFn = null;
|
|
202
216
|
onKeyUpFn = null;
|
|
@@ -206,13 +220,16 @@ export function removeMouseKeyHandlers() {
|
|
|
206
220
|
* Add event handlers to mouse move
|
|
207
221
|
* @instance
|
|
208
222
|
* @function toggleMouseHandlers
|
|
209
|
-
* @param {String} elementId - The html div id used for rendering or its DOM HTMLElement
|
|
223
|
+
* @param {String | HTMLElement} elementId - The html div id used for rendering or its DOM HTMLElement
|
|
210
224
|
* @param {Boolean} disable - If true disable handlers, default is false
|
|
211
225
|
*/
|
|
212
|
-
export const toggleMouseToolsListeners = function (
|
|
226
|
+
export const toggleMouseToolsListeners = function (
|
|
227
|
+
elementId: string | HTMLElement,
|
|
228
|
+
disable: boolean
|
|
229
|
+
) {
|
|
213
230
|
let element = isElement(elementId)
|
|
214
|
-
? elementId
|
|
215
|
-
: document.getElementById(elementId);
|
|
231
|
+
? (elementId as HTMLElement)
|
|
232
|
+
: document.getElementById(elementId as string);
|
|
216
233
|
if (!element) {
|
|
217
234
|
console.error("invalid html element: " + elementId);
|
|
218
235
|
return;
|
|
@@ -222,14 +239,16 @@ export const toggleMouseToolsListeners = function (elementId, disable) {
|
|
|
222
239
|
let mouseMoveHandler = throttle(function (evt) {
|
|
223
240
|
let activeTool =
|
|
224
241
|
evt.detail.buttons == 1
|
|
225
|
-
?
|
|
226
|
-
:
|
|
242
|
+
? store.get("leftActiveTool")
|
|
243
|
+
: store.get("rightActiveTool");
|
|
227
244
|
updateViewportData(evt.srcElement.id, evt.detail.viewport, activeTool);
|
|
228
245
|
}, 250);
|
|
229
246
|
|
|
230
247
|
// mouse wheel handler
|
|
231
|
-
function mouseWheelHandler(evt) {
|
|
232
|
-
|
|
248
|
+
function mouseWheelHandler(evt: any) {
|
|
249
|
+
// TODO-ts fix type (should be a cornerstoneTools event type)
|
|
250
|
+
// @mronzoni does cornerstoneTools have a type for this event?
|
|
251
|
+
setStore(["sliceId", evt.target.id, evt.detail.newImageIdIndex]);
|
|
233
252
|
updateViewportData(evt.srcElement.id, evt.detail, "mouseWheel");
|
|
234
253
|
}
|
|
235
254
|
|
|
@@ -10,29 +10,31 @@ import { each, map, assign, invert } from "lodash";
|
|
|
10
10
|
import { unparse } from "papaparse";
|
|
11
11
|
|
|
12
12
|
// internal libraries
|
|
13
|
-
import { setToolEnabled } from "
|
|
13
|
+
import { setToolEnabled } from "./main";
|
|
14
|
+
import type { ToolState } from "./types";
|
|
15
|
+
import { fileManager } from "../loaders/fileLoader";
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
declare global {
|
|
18
|
+
interface Document {
|
|
19
|
+
documentMode?: any;
|
|
20
|
+
}
|
|
21
|
+
interface Navigator {
|
|
22
|
+
msSaveBlob?: (blob: any, defaultName?: string) => boolean;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
27
|
* Load annotation from json object
|
|
21
28
|
* @param {Object} jsonData - The previously saved tools state
|
|
22
29
|
*/
|
|
23
|
-
export const loadAnnotations = function (jsonData) {
|
|
24
|
-
// DEV
|
|
25
|
-
// if (!jsonData) {
|
|
26
|
-
// jsonData = saved_state_2;
|
|
27
|
-
// }
|
|
28
|
-
|
|
30
|
+
export const loadAnnotations = function (jsonData: ToolState) {
|
|
29
31
|
// restore saved tool state
|
|
30
32
|
cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState(
|
|
31
33
|
jsonData
|
|
32
34
|
);
|
|
33
35
|
|
|
34
36
|
// set all found tools to passive
|
|
35
|
-
let toolsInState = new Set();
|
|
37
|
+
let toolsInState: Set<string> = new Set();
|
|
36
38
|
for (let imageId in jsonData) {
|
|
37
39
|
for (let toolName in jsonData[imageId]) {
|
|
38
40
|
toolsInState.add(toolName);
|
|
@@ -40,6 +42,7 @@ export const loadAnnotations = function (jsonData) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
toolsInState.forEach(toolName => {
|
|
45
|
+
// TODO-ts fix 'null' this after setToolEnabled is typed @mronzoni
|
|
43
46
|
setToolEnabled(toolName);
|
|
44
47
|
});
|
|
45
48
|
|
|
@@ -50,7 +53,12 @@ export const loadAnnotations = function (jsonData) {
|
|
|
50
53
|
|
|
51
54
|
// FIXME error if called when image is not loaded
|
|
52
55
|
for (let elementId of enabledElementIds) {
|
|
53
|
-
|
|
56
|
+
let element = document.getElementById(elementId);
|
|
57
|
+
if (!element) {
|
|
58
|
+
console.warn(`Element ${elementId} not found`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
cornerstone.updateImage(element);
|
|
54
62
|
}
|
|
55
63
|
};
|
|
56
64
|
|
|
@@ -59,13 +67,16 @@ export const loadAnnotations = function (jsonData) {
|
|
|
59
67
|
* @param {bool} download - True to download json
|
|
60
68
|
* @param {string} filename - The json file name, @default state.json
|
|
61
69
|
*/
|
|
62
|
-
export const saveAnnotations = function (
|
|
70
|
+
export const saveAnnotations = function (
|
|
71
|
+
download: boolean,
|
|
72
|
+
filename = "state.json"
|
|
73
|
+
) {
|
|
63
74
|
let currentToolState =
|
|
64
75
|
cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState();
|
|
65
|
-
if (
|
|
76
|
+
if (download) {
|
|
66
77
|
// Convert JSON Array to string.
|
|
67
78
|
var json_string = JSON.stringify(currentToolState);
|
|
68
|
-
|
|
79
|
+
downloadFile(json_string, filename);
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
return currentToolState;
|
|
@@ -76,14 +87,14 @@ export const saveAnnotations = function (toDownload, filename = "state.json") {
|
|
|
76
87
|
* containing only useful informations for user
|
|
77
88
|
*/
|
|
78
89
|
export const exportAnnotations = function (
|
|
79
|
-
fileManager,
|
|
90
|
+
manager: typeof fileManager,
|
|
80
91
|
filename = "annotations.csv"
|
|
81
92
|
) {
|
|
82
93
|
let currentToolState =
|
|
83
94
|
cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState();
|
|
84
|
-
let
|
|
85
|
-
let csvstring = unparse(
|
|
86
|
-
|
|
95
|
+
let { fieldsArr: fields, data } = generateCSV(manager, currentToolState);
|
|
96
|
+
let csvstring = unparse({ fields, data });
|
|
97
|
+
downloadFile(csvstring, filename);
|
|
87
98
|
};
|
|
88
99
|
|
|
89
100
|
/**
|
|
@@ -91,13 +102,12 @@ export const exportAnnotations = function (
|
|
|
91
102
|
* @param {*} stringContent
|
|
92
103
|
* @param {*} filename
|
|
93
104
|
*/
|
|
94
|
-
function
|
|
105
|
+
function downloadFile(stringContent: string, filename: string) {
|
|
95
106
|
// Convert string to BLOB.
|
|
96
|
-
|
|
97
|
-
var blob = new Blob(stringContent, { type: "text/plain;charset=utf-8" });
|
|
107
|
+
var blob = new Blob([stringContent], { type: "text/plain;charset=utf-8" });
|
|
98
108
|
//Check the Browser.
|
|
99
109
|
var isIE = false || !!document.documentMode;
|
|
100
|
-
if (isIE) {
|
|
110
|
+
if (isIE && window.navigator.msSaveBlob) {
|
|
101
111
|
window.navigator.msSaveBlob(blob, filename);
|
|
102
112
|
} else {
|
|
103
113
|
var url = window.URL || window.webkitURL;
|
|
@@ -115,14 +125,17 @@ function download(stringContent, filename) {
|
|
|
115
125
|
*
|
|
116
126
|
* @param {*} allToolState
|
|
117
127
|
*/
|
|
118
|
-
export function generateCSV(
|
|
119
|
-
|
|
128
|
+
export function generateCSV(
|
|
129
|
+
manager: typeof fileManager,
|
|
130
|
+
allToolState: ToolState
|
|
131
|
+
) {
|
|
132
|
+
let fields: Set<string> = new Set();
|
|
120
133
|
fields.add("imagePath");
|
|
121
134
|
fields.add("toolName");
|
|
122
|
-
let data = [];
|
|
135
|
+
let data: Object[] = [];
|
|
123
136
|
each(allToolState, (imageToolState, imageId) => {
|
|
124
137
|
// convert imageId to imagePath
|
|
125
|
-
let imagePath = invert(
|
|
138
|
+
let imagePath = invert(manager)[imageId];
|
|
126
139
|
each(imageToolState, (toolState, toolName) => {
|
|
127
140
|
// extract useful information from tool state
|
|
128
141
|
let extractedData = extractToolInfo(toolName, toolState.data);
|
|
@@ -134,10 +147,10 @@ export function generateCSV(fileManager, allToolState) {
|
|
|
134
147
|
});
|
|
135
148
|
});
|
|
136
149
|
|
|
137
|
-
|
|
150
|
+
let fieldsArr: string[] = Array.from(fields);
|
|
138
151
|
|
|
139
152
|
return {
|
|
140
|
-
|
|
153
|
+
fieldsArr,
|
|
141
154
|
data
|
|
142
155
|
};
|
|
143
156
|
}
|
|
@@ -146,8 +159,11 @@ export function generateCSV(fileManager, allToolState) {
|
|
|
146
159
|
*
|
|
147
160
|
* @param {*} toolData
|
|
148
161
|
*/
|
|
149
|
-
function extractToolInfo(
|
|
150
|
-
|
|
162
|
+
function extractToolInfo(
|
|
163
|
+
toolName: string,
|
|
164
|
+
toolData: ToolState["imageId"][keyof ToolState["imageId"]]
|
|
165
|
+
) {
|
|
166
|
+
let dataArray: Object[] = [];
|
|
151
167
|
switch (toolName) {
|
|
152
168
|
case "RectangleRoi":
|
|
153
169
|
case "EllipticalRoi":
|