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.
Files changed (103) 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 +39 -0
  8. package/dist/imaging/MetaDataTypes.d.ts +3488 -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 +112 -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/contourTool.d.ts +409 -0
  35. package/dist/imaging/tools/custom/diameterTool.d.ts +18 -0
  36. package/dist/imaging/tools/custom/editMaskTool.d.ts +22 -0
  37. package/dist/imaging/tools/custom/ellipticalRoiOverlayTool.d.ts +45 -0
  38. package/dist/imaging/tools/custom/polygonSegmentationMixin.d.ts +54 -0
  39. package/dist/imaging/tools/custom/polylineScissorsTool.d.ts +11 -0
  40. package/dist/imaging/tools/custom/rectangleRoiOverlayTool.d.ts +45 -0
  41. package/dist/imaging/tools/custom/seedTool.d.ts +0 -0
  42. package/dist/imaging/tools/custom/setLabelMap3D.d.ts +39 -0
  43. package/dist/imaging/tools/custom/thresholdsBrushTool.d.ts +19 -0
  44. package/dist/imaging/tools/default.d.ts +53 -0
  45. package/dist/imaging/tools/interaction.d.ts +30 -0
  46. package/dist/imaging/tools/io.d.ts +38 -0
  47. package/dist/imaging/tools/main.d.ts +81 -0
  48. package/dist/imaging/tools/segmentation.d.ts +125 -0
  49. package/dist/imaging/tools/state.d.ts +17 -0
  50. package/dist/imaging/tools/strategies/eraseFreehand.d.ts +16 -0
  51. package/dist/imaging/tools/strategies/fillFreehand.d.ts +16 -0
  52. package/dist/imaging/tools/strategies/index.d.ts +2 -0
  53. package/dist/index.d.ts +34 -0
  54. package/dist/larvitar.js +89801 -0
  55. package/dist/larvitar.js.map +1 -0
  56. package/imaging/MetaDataReadable.ts +40 -0
  57. package/imaging/MetaDataTypes.ts +3490 -0
  58. package/imaging/dataDictionary.json +5328 -5328
  59. package/imaging/{imageAnonymization.js → imageAnonymization.ts} +41 -13
  60. package/imaging/{imageColormaps.js → imageColormaps.ts} +48 -30
  61. package/imaging/{imageContours.js → imageContours.ts} +24 -22
  62. package/imaging/{imageIo.js → imageIo.ts} +89 -52
  63. package/imaging/{imageLayers.js → imageLayers.ts} +31 -14
  64. package/imaging/{imageLoading.js → imageLoading.ts} +108 -45
  65. package/imaging/{imageParsing.js → imageParsing.ts} +158 -80
  66. package/imaging/{imagePresets.js → imagePresets.ts} +44 -11
  67. package/imaging/imageRendering.ts +1091 -0
  68. package/imaging/{imageReslice.js → imageReslice.ts} +18 -9
  69. package/imaging/imageStore.ts +487 -0
  70. package/imaging/imageTags.ts +609 -0
  71. package/imaging/imageTools.js +2 -1
  72. package/imaging/{imageUtils.js → imageUtils.ts} +211 -701
  73. package/imaging/loaders/{commonLoader.js → commonLoader.ts} +73 -24
  74. package/imaging/loaders/{dicomLoader.js → dicomLoader.ts} +25 -5
  75. package/imaging/loaders/{fileLoader.js → fileLoader.ts} +5 -5
  76. package/imaging/loaders/{multiframeLoader.js → multiframeLoader.ts} +145 -90
  77. package/imaging/loaders/{nrrdLoader.js → nrrdLoader.ts} +230 -64
  78. package/imaging/loaders/{resliceLoader.js → resliceLoader.ts} +51 -20
  79. package/imaging/monitors/{memory.js → memory.ts} +54 -8
  80. package/imaging/monitors/performance.ts +34 -0
  81. package/imaging/parsers/ecg.ts +51 -0
  82. package/imaging/tools/README.md +27 -0
  83. package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
  84. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +534 -0
  85. package/imaging/tools/custom/polylineScissorsTool.js +1 -1
  86. package/imaging/tools/custom/rectangleRoiOverlayTool.js +564 -0
  87. package/imaging/tools/{setLabelMap3D.js → custom/setLabelMap3D.ts} +19 -25
  88. package/imaging/tools/{default.js → default.ts} +114 -30
  89. package/imaging/tools/{interaction.js → interaction.ts} +42 -23
  90. package/imaging/tools/{io.js → io.ts} +47 -31
  91. package/imaging/tools/{main.js → main.ts} +105 -40
  92. package/imaging/tools/{segmentation.js → segmentation.ts} +95 -68
  93. package/imaging/tools/{state.js → state.ts} +7 -12
  94. package/imaging/tools/types.d.ts +243 -0
  95. package/imaging/types.d.ts +197 -0
  96. package/{index.js → index.ts} +43 -14
  97. package/jsdoc.json +1 -1
  98. package/package.json +32 -14
  99. package/tsconfig.json +102 -0
  100. package/imaging/imageRendering.js +0 -860
  101. package/imaging/imageStore.js +0 -322
  102. package/modules/vuex/larvitar.js +0 -187
  103. /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
- StackScrollMouseWheel: {
103
- name: "StackScrollMouseWheel",
111
+ StackScroll: {
112
+ name: "StackScroll",
104
113
  viewports: "all",
105
- configuration: {},
106
- options: {
114
+ configuration: {
107
115
  loop: false, // default false
108
- allowSkipping: false, // default true
109
- invert: false
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: "StackScrollMouseWheelTool"
124
+ class: "StackScrollTool"
114
125
  },
115
- Slice4DScrollMouseWheel: {
116
- name: "Slice4DScrollMouseWheel",
126
+ StackScrollMouseWheel: {
127
+ name: "StackScrollMouseWheel",
117
128
  viewports: "all",
118
129
  configuration: {
119
130
  loop: false, // default false
120
- allowSkipping: false, // default true
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: "Slice4DScrollMouseWheelTool"
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(`${newProps.name} does not exist`);
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/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":