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
@@ -20,20 +20,32 @@
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
+ import BorderMagnifyTool from "./custom/BorderMagnifyTool";
35
+
36
+ import type {
37
+ ToolConfig,
38
+ ToolMouseKeys,
39
+ ToolSettings,
40
+ ToolStyle
41
+ } from "./types";
32
42
 
33
43
  /**
34
44
  * These tools are added with `addDefaultTools()`
35
45
  */
36
- const DEFAULT_TOOLS = {
46
+ const DEFAULT_TOOLS: {
47
+ [key: string]: ToolConfig;
48
+ } = {
37
49
  ScaleOverlay: {
38
50
  name: "ScaleOverlay",
39
51
  viewports: "all",
@@ -47,7 +59,6 @@ const DEFAULT_TOOLS = {
47
59
  cleanable: false,
48
60
  defaultActive: false,
49
61
  class: "ScaleOverlayTool",
50
- sync: null,
51
62
  description: "Add scale overlay",
52
63
  shortcut: "ctrl-m",
53
64
  type: "overlay"
@@ -62,7 +73,6 @@ const DEFAULT_TOOLS = {
62
73
  cleanable: false,
63
74
  defaultActive: false,
64
75
  class: "OrientationMarkersTool",
65
- sync: null,
66
76
  description: "Add orientation markers",
67
77
  shortcut: "ctrl-m",
68
78
  type: "overlay"
@@ -78,7 +88,7 @@ const DEFAULT_TOOLS = {
78
88
  cleanable: false,
79
89
  defaultActive: true,
80
90
  class: "WwwcTool",
81
- sync: "wwwcSynchronizer",
91
+ // sync: "wwwcSynchronizer",
82
92
  description: "Change image contrast",
83
93
  shortcut: "ctrl-m",
84
94
  type: "utils"
@@ -94,38 +104,53 @@ const DEFAULT_TOOLS = {
94
104
  cleanable: false,
95
105
  defaultActive: false,
96
106
  class: "WwwcRegionTool",
97
- sync: "wwwcSynchronizer",
107
+ // sync: "wwwcSynchronizer",
98
108
  description: "Change image contrast based on selected region",
99
109
  shortcut: "ctrl-m",
100
110
  type: "utils"
101
111
  },
102
- StackScrollMouseWheel: {
103
- name: "StackScrollMouseWheel",
112
+ StackScroll: {
113
+ name: "StackScroll",
104
114
  viewports: "all",
105
- configuration: {},
106
- options: {
115
+ configuration: {
107
116
  loop: false, // default false
108
- allowSkipping: false, // default true
109
- invert: false
117
+ allowSkipping: true // default true
118
+ },
119
+ options: {
120
+ mouseButtonMask: 1,
121
+ deltaY: 0 // default 0
110
122
  },
111
123
  cleanable: false,
112
124
  defaultActive: false,
113
- class: "StackScrollMouseWheelTool"
125
+ class: "StackScrollTool"
114
126
  },
115
- Slice4DScrollMouseWheel: {
116
- name: "Slice4DScrollMouseWheel",
127
+ StackScrollMouseWheel: {
128
+ name: "StackScrollMouseWheel",
117
129
  viewports: "all",
118
130
  configuration: {
119
131
  loop: false, // default false
120
- allowSkipping: false, // default true
121
- invert: false,
122
- framesNumber: 1
132
+ allowSkipping: true, // default true
133
+ invert: false
123
134
  },
124
135
  options: {},
125
136
  cleanable: false,
126
137
  defaultActive: true,
127
- class: "Slice4DScrollMouseWheelTool"
138
+ class: "StackScrollMouseWheelTool"
128
139
  },
140
+ // Slice4DScrollMouseWheel: {
141
+ // name: "Slice4DScrollMouseWheel",
142
+ // viewports: "all",
143
+ // configuration: {
144
+ // loop: false, // default false
145
+ // allowSkipping: false, // default true
146
+ // invert: false,
147
+ // framesNumber: 1
148
+ // },
149
+ // options: {},
150
+ // cleanable: false,
151
+ // defaultActive: true,
152
+ // class: "Slice4DScrollMouseWheelTool"
153
+ // },
129
154
  Pan: {
130
155
  name: "Pan",
131
156
  viewports: "all",
@@ -161,8 +186,8 @@ const DEFAULT_TOOLS = {
161
186
  shortcut: "ctrl-z",
162
187
  type: "utils"
163
188
  },
164
- Magnify: {
165
- name: "Magnify",
189
+ BorderMagnify: {
190
+ name: "BorderMagnify",
166
191
  viewports: "all",
167
192
  configuration: {},
168
193
  options: {
@@ -170,7 +195,7 @@ const DEFAULT_TOOLS = {
170
195
  supportedInteractionTypes: ["Mouse", "Touch"]
171
196
  },
172
197
  cleanable: false,
173
- class: "MagnifyTool",
198
+ class: "BorderMagnifyTool",
174
199
  defaultActive: false,
175
200
  description: "Magnify image at mouse position",
176
201
  shortcut: "ctrl-m",
@@ -246,6 +271,7 @@ const DEFAULT_TOOLS = {
246
271
  RectangleRoi: {
247
272
  name: "RectangleRoi",
248
273
  viewports: "all",
274
+ configuration: {},
249
275
  options: { mouseButtonMask: 1 },
250
276
  cleanable: true,
251
277
  defaultActive: false,
@@ -254,6 +280,29 @@ const DEFAULT_TOOLS = {
254
280
  shortcut: "ctrl-a",
255
281
  type: "annotation"
256
282
  },
283
+ EllipticalRoiOverlay: {
284
+ name: "EllipticalRoiOverlay",
285
+ viewports: "all",
286
+ configuration: {},
287
+ options: { mouseButtonMask: 1 },
288
+ cleanable: true,
289
+ class: "EllipticalRoiOverlayTool",
290
+ description: "Draw an ellipse",
291
+ shortcut: "ctrl-f",
292
+ type: "annotation"
293
+ },
294
+ RectangleRoiOverlay: {
295
+ name: "RectangleRoiOverlay",
296
+ viewports: "all",
297
+ configuration: {},
298
+ options: { mouseButtonMask: 1 },
299
+ cleanable: true,
300
+ defaultActive: false,
301
+ class: "RectangleRoiOverlayTool",
302
+ description: "Draw a rectangle",
303
+ shortcut: "ctrl-a",
304
+ type: "annotation"
305
+ },
257
306
  FreehandRoi: {
258
307
  name: "FreehandRoi",
259
308
  viewports: "all",
@@ -268,6 +317,7 @@ const DEFAULT_TOOLS = {
268
317
  Probe: {
269
318
  name: "Probe",
270
319
  viewports: "all",
320
+ configuration: {},
271
321
  options: { mouseButtonMask: 1 },
272
322
  cleanable: true,
273
323
  class: "ProbeTool"
@@ -411,10 +461,15 @@ const DEFAULT_TOOLS = {
411
461
  /**
412
462
  * D/Vision Lab custom tools
413
463
  */
414
- const dvTools = {
464
+ const dvTools: {
465
+ [key: string]: any; // TODO-ts tools class type @mronzoni
466
+ } = {
415
467
  ThresholdsBrushTool: ThresholdsBrushTool,
416
468
  PolylineScissorsTool: PolylineScissorsTool,
417
- Slice4DScrollMouseWheelTool: Slice4DScrollMouseWheelTool
469
+ // Slice4DScrollMouseWheelTool: Slice4DScrollMouseWheelTool,
470
+ RectangleRoiOverlayTool: RectangleRoiOverlayTool,
471
+ EllipticalRoiOverlayTool: EllipticalRoiOverlayTool,
472
+ BorderMagnifyTool: BorderMagnifyTool
418
473
  };
419
474
 
420
475
  /**
@@ -424,7 +479,7 @@ const dvTools = {
424
479
  * Helvetica Neue Light, Helvetica Neue, Helvetica,
425
480
  * Arial, Lucida Grande, sans-serif;
426
481
  */
427
- const DEFAULT_STYLE = {
482
+ const DEFAULT_STYLE: ToolStyle = {
428
483
  width: 1,
429
484
  color: "#02FAE5",
430
485
  activeColor: "#00FF00",
@@ -437,7 +492,7 @@ const DEFAULT_STYLE = {
437
492
  /**
438
493
  * Tools default settings
439
494
  */
440
- const DEFAULT_SETTINGS = {
495
+ const DEFAULT_SETTINGS: ToolSettings = {
441
496
  mouseEnabled: true,
442
497
  touchEnabled: true,
443
498
  showSVGCursors: true,
@@ -449,7 +504,7 @@ const DEFAULT_SETTINGS = {
449
504
  /**
450
505
  * Shortcut and mouse bindings defaults
451
506
  */
452
- const DEFAULT_MOUSE_KEYS = {
507
+ const DEFAULT_MOUSE_KEYS: ToolMouseKeys = {
453
508
  debug: true, // log changes
454
509
  mouse_button_left: {
455
510
  shift: "Zoom",
@@ -473,7 +528,7 @@ const DEFAULT_MOUSE_KEYS = {
473
528
  * Get available tools by type (useful to populate menus)
474
529
  * @param {String} type
475
530
  */
476
- const getDefaultToolsByType = function (type) {
531
+ const getDefaultToolsByType = function (type: NonNullable<ToolConfig["type"]>) {
477
532
  return filter(DEFAULT_TOOLS, ["type", type]);
478
533
  };
479
534
 
@@ -482,14 +537,19 @@ const getDefaultToolsByType = function (type) {
482
537
  * @param {Array} newProps - An array of objects as in the DEFAULT_TOOLS list, but with a subset of props
483
538
  * NOTE: prop "name" is mandatory
484
539
  */
485
- const setDefaultToolsProps = function (newProps) {
540
+ const setDefaultToolsProps = function (newProps: Partial<ToolConfig>[]) {
486
541
  if (isArray(newProps)) {
487
542
  newProps.forEach(props => {
543
+ if (!props.name) {
544
+ console.error("newProps must have a name property");
545
+ return;
546
+ }
547
+
488
548
  let targetTool = DEFAULT_TOOLS[props.name];
489
549
  if (targetTool) {
490
550
  DEFAULT_TOOLS[props.name] = Object.assign(targetTool, props);
491
551
  } else {
492
- console.error(`${newProps.name} does not exist`);
552
+ console.error(`${props.name} does not exist`);
493
553
  }
494
554
  });
495
555
  } else {
@@ -497,6 +557,31 @@ const setDefaultToolsProps = function (newProps) {
497
557
  }
498
558
  };
499
559
 
560
+ /**
561
+ * Register a custom tool
562
+ * @param {String} toolName - The name of the tool
563
+ * @param {Object} toolClass - The tool class
564
+ * NOTE: toolName must be unique
565
+ * NOTE: toolClass must be a valid cornerstone tool
566
+ */
567
+
568
+ const registerExternalTool = function (toolName: string, toolClass: any) {
569
+ if (dvTools[toolName] || DEFAULT_TOOLS[toolName]) {
570
+ console.error(`${toolName} already exists`);
571
+ return;
572
+ }
573
+
574
+ dvTools[toolClass.name] = toolClass;
575
+ DEFAULT_TOOLS[toolName] = {
576
+ name: toolName,
577
+ class: toolClass.name,
578
+ viewports: "all",
579
+ configuration: {},
580
+ options: { mouseButtonMask: 1 },
581
+ defaultActive: false
582
+ };
583
+ };
584
+
500
585
  export {
501
586
  DEFAULT_TOOLS,
502
587
  DEFAULT_STYLE,
@@ -504,5 +589,6 @@ export {
504
589
  DEFAULT_MOUSE_KEYS,
505
590
  dvTools,
506
591
  getDefaultToolsByType,
507
- setDefaultToolsProps
508
- };
592
+ setDefaultToolsProps,
593
+ registerExternalTool
594
+ };
@@ -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/dist/cornerstoneTools.js";
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 { larvitar_store } from "../imageStore";
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(key => keyCodes[key])
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
- .filter(key => keyCodes[key] == evt.keyCode)
81
+ // @ts-ignore
82
+ .filter(key => keyCodes[key] == evt.keyCode) // TODO keyCode is deprecated
78
83
  .pop();
79
- if (config.debug) console.log("active", config.keyboard_shortcuts[key]);
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
- config.keyboard_shortcuts[key],
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 (elementId, disable) {
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
- ? larvitar_store.get("leftActiveTool")
226
- : larvitar_store.get("rightActiveTool");
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
- larvitar_store.set("sliceId", [evt.target.id, evt.detail.newImageIdIndex]);
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 "../imageTools";
13
+ import { setToolEnabled } from "./main";
14
+ import type { ToolState } from "./types";
15
+ import { fileManager } from "../loaders/fileLoader";
14
16
 
15
- // DEV
16
- // import { saved_state_2 } from "./cstools_state_example.js";
17
- // import { devState } from "./devState.js";
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
- cornerstone.updateImage(document.getElementById(elementId));
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 (toDownload, filename = "state.json") {
70
+ export const saveAnnotations = function (
71
+ download: boolean,
72
+ filename = "state.json"
73
+ ) {
63
74
  let currentToolState =
64
75
  cornerstoneTools.globalImageIdSpecificToolStateManager.saveToolState();
65
- if (toDownload) {
76
+ if (download) {
66
77
  // Convert JSON Array to string.
67
78
  var json_string = JSON.stringify(currentToolState);
68
- download(json_string, filename);
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 csvdata = generateCSV(fileManager, currentToolState);
85
- let csvstring = unparse(csvdata);
86
- download(csvstring, filename);
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 download(stringContent, filename) {
105
+ function downloadFile(stringContent: string, filename: string) {
95
106
  // Convert string to BLOB.
96
- stringContent = [stringContent];
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(fileManager, allToolState) {
119
- let fields = new Set();
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(fileManager)[imageId];
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
- fields = Array.from(fields);
150
+ let fieldsArr: string[] = Array.from(fields);
138
151
 
139
152
  return {
140
- fields,
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(toolName, toolData) {
150
- let dataArray = [];
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":