larvitar 1.3.3 → 1.4.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/README.md +11 -7
- package/imaging/imageParsing.js +14 -4
- package/imaging/imageTools.js +8 -1
- package/imaging/tools/interaction.js +38 -35
- package/imaging/tools/segmentation.js +26 -10
- package/imaging/tools/segmentations.md +1 -1
- package/index.js +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
# Larvitar
|
|
6
6
|
|
|
7
|
-
## Dicom Image Toolkit for
|
|
7
|
+
## Dicom Image Toolkit for CornerstoneJS
|
|
8
8
|
|
|
9
|
-
### Current version: 1.
|
|
9
|
+
### Current version: 1.4.0
|
|
10
10
|
|
|
11
|
-
### Latest
|
|
11
|
+
### Latest Published Release: 1.4.0
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
This library provides common DICOM functionalities to be used in web-applications: it's wrapper that simplifies the use of cornestone-js environment.
|
|
13
|
+
This library provides common DICOM functionalities to be used in web-applications: it's wrapper that simplifies the use of cornerstone-js environment.
|
|
16
14
|
Orthogonal multiplanar reformat is included as well as custom loader/exporter for nrrd files and [Vuex](https://vuex.vuejs.org/) custom integration.
|
|
17
15
|
|
|
18
16
|
- `index` main file
|
|
@@ -22,7 +20,7 @@ Orthogonal multiplanar reformat is included as well as custom loader/exporter fo
|
|
|
22
20
|
- `imageIo` import a dicom image in .nrrd format and build contiguous array for exporting data as volume
|
|
23
21
|
- `imageLayers` provide support for multi-layer cornerstone fusion renderer
|
|
24
22
|
- `imageLoading` initialize loader and custom loaders
|
|
25
|
-
- `imageParsing` parse dicom files and return a
|
|
23
|
+
- `imageParsing` parse dicom files and return a cornerstone data structure ready to be used for rendering
|
|
26
24
|
- `imagePresets` provides default image CT presets and set functionality
|
|
27
25
|
- `imageRendering` provides rendering functionalities
|
|
28
26
|
- `imageReslice` provides reslice functionalities
|
|
@@ -90,3 +88,9 @@ Full documentation and examples are available at http://www.dvisionlab.com/Larvi
|
|
|
90
88
|
# Build package
|
|
91
89
|
|
|
92
90
|
`yarn build-lib`
|
|
91
|
+
|
|
92
|
+
# Development
|
|
93
|
+
|
|
94
|
+
Use `yarn dev-lib` to have `rollup` hot-reload (live recompiling the library).
|
|
95
|
+
In order to test functionalities you can modify the library import path in an example (see the `docs/examples` folder) to use the recompiled bundle in `dist/`, then serve the .html file with VSCode extension [LiveServer](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) or other similar tools.
|
|
96
|
+
Once you are done, upgrade the version, build the library and copy it to the `docs/examples` folder. This file must be included into the commit, while docs will be compiled by the Github action.
|
package/imaging/imageParsing.js
CHANGED
|
@@ -78,11 +78,10 @@ export const readFile = function (entry) {
|
|
|
78
78
|
* @instance
|
|
79
79
|
* @function parseDataSet
|
|
80
80
|
* @param {Object} dataSet - dicom parser dataSet object
|
|
81
|
-
* @param {
|
|
81
|
+
* @param {Object} metadata - Initialized metadata object
|
|
82
82
|
* @param {Array} customFilter - Optional filter: {tags:[], frameId: 0}
|
|
83
83
|
*/
|
|
84
|
-
// This function iterates through dataSet recursively and
|
|
85
|
-
// to the output array passed into it
|
|
84
|
+
// This function iterates through dataSet recursively and store tag values into metadata object
|
|
86
85
|
export const parseDataSet = function (dataSet, metadata, customFilter) {
|
|
87
86
|
// customFilter= {tags:[], frameId:xxx}
|
|
88
87
|
// the dataSet.elements object contains properties for each element parsed. The name of the property
|
|
@@ -113,7 +112,18 @@ export const parseDataSet = function (dataSet, metadata, customFilter) {
|
|
|
113
112
|
}
|
|
114
113
|
} else {
|
|
115
114
|
let tagValue = parseTag(dataSet, propertyName, element);
|
|
116
|
-
|
|
115
|
+
|
|
116
|
+
// identify duplicated tags (keep the first occurency and store the others in another tag eg x00280010_uuid)
|
|
117
|
+
if (metadata[propertyName] !== undefined) {
|
|
118
|
+
console.debug(
|
|
119
|
+
`Identified duplicated tag "${propertyName}", values are:`,
|
|
120
|
+
metadata[propertyName],
|
|
121
|
+
tagValue
|
|
122
|
+
);
|
|
123
|
+
metadata[propertyName + "_" + uuidv4()] = tagValue;
|
|
124
|
+
} else {
|
|
125
|
+
metadata[propertyName] = tagValue;
|
|
126
|
+
}
|
|
117
127
|
}
|
|
118
128
|
}
|
|
119
129
|
} catch (err) {
|
package/imaging/imageTools.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/** @module imaging/imageTools
|
|
2
2
|
* @desc This file provides functionalities for
|
|
3
3
|
* interacting with cornerstone tools
|
|
4
|
+
* DEPRECATION WARNING: these are legacy functions
|
|
5
|
+
* that will be removed soon. Use the corresponding
|
|
6
|
+
* functions in /tools/main.js instead.
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
// external libraries
|
|
@@ -277,6 +280,7 @@ export const clearMeasurements = function () {
|
|
|
277
280
|
* @param {Object} options - The custom options. @default from tools/default.js
|
|
278
281
|
* @param {String} activeViewport - The active viewport (if "all", viewports array will be used)
|
|
279
282
|
* @param {Array} viewports - The hmtl element id to be used for tool initialization.
|
|
283
|
+
* @deprecated (OBSOLETE)
|
|
280
284
|
*/
|
|
281
285
|
export const setToolActive = function (
|
|
282
286
|
toolName,
|
|
@@ -304,10 +308,11 @@ export const setToolActive = function (
|
|
|
304
308
|
|
|
305
309
|
/**
|
|
306
310
|
* Set Tool "disabled" on all elements (ie, not rendered) & refresh cornerstone elements
|
|
307
|
-
* @function
|
|
311
|
+
* @function setToolDisabled
|
|
308
312
|
* @param {String} toolName - The tool name.
|
|
309
313
|
* @param {String} activeViewport - The active viewport (if "all", viewports array will be used)
|
|
310
314
|
* @param {Array} viewports - The hmtl element id to be used for tool initialization.
|
|
315
|
+
* @deprecated (OBSOLETE)
|
|
311
316
|
*/
|
|
312
317
|
export const setToolDisabled = function (toolName, activeViewport, viewports) {
|
|
313
318
|
cornerstoneTools.setToolDisabled(toolName);
|
|
@@ -332,6 +337,7 @@ export const setToolDisabled = function (toolName, activeViewport, viewports) {
|
|
|
332
337
|
* @param {String} toolName - The tool name.
|
|
333
338
|
* @param {String} activeViewport - The active viewport (if "all", viewports array will be used)
|
|
334
339
|
* @param {Array} viewports - The hmtl element id to be used for tool initialization.
|
|
340
|
+
* @deprecated (OBSOLETE)
|
|
335
341
|
*/
|
|
336
342
|
export const setToolEnabled = function (toolName, activeViewport, viewports) {
|
|
337
343
|
cornerstoneTools.setToolEnabled(toolName);
|
|
@@ -356,6 +362,7 @@ export const setToolEnabled = function (toolName, activeViewport, viewports) {
|
|
|
356
362
|
* @param {String} toolName - The tool name.
|
|
357
363
|
* @param {String} activeViewport - The active viewport (if "all", viewports array will be used)
|
|
358
364
|
* @param {Array} viewports - The hmtl element id to be used for tool initialization.
|
|
365
|
+
* @deprecated (OBSOLETE)
|
|
359
366
|
*/
|
|
360
367
|
export const setToolPassive = function (toolName, activeViewport, viewports) {
|
|
361
368
|
cornerstoneTools.setToolPassive(toolName);
|
|
@@ -22,27 +22,42 @@ import { updateViewportData } from "../imageRendering";
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
|
|
25
|
+
* Global event callbacks
|
|
26
|
+
*/
|
|
27
|
+
let onKeyDownFn = null;
|
|
28
|
+
let onKeyUpFn = null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Setup mouse handler modifiers and keyboard shortcuts:
|
|
32
|
+
* register a tool on right button and another one
|
|
33
|
+
* when pressing a modifier (ctrl/shift/alt) + right button
|
|
34
|
+
* The activation take place on all active viewports
|
|
27
35
|
* Improvements could be:
|
|
28
36
|
* - "restore previous active tool" instead of passed "default" tool
|
|
29
37
|
* - manage left button (an idea could be to cycle over object keys for both buttons)
|
|
30
38
|
* - possibility to change modifier keys
|
|
31
39
|
* @param {Object} config - see tools/default
|
|
32
|
-
* @param {Array} viewports - The hmtl element ids to be used for tool activation.
|
|
33
40
|
*/
|
|
34
41
|
|
|
35
|
-
export function addMouseKeyHandlers(config
|
|
42
|
+
export function addMouseKeyHandlers(config) {
|
|
36
43
|
if (!config) {
|
|
37
44
|
config = DEFAULT_MOUSE_KEYS;
|
|
38
45
|
}
|
|
39
46
|
|
|
47
|
+
if (onKeyDownFn) {
|
|
48
|
+
document.removeEventListener("keydown", onKeyDownFn);
|
|
49
|
+
}
|
|
50
|
+
if (onKeyUpFn) {
|
|
51
|
+
document.removeEventListener("keyup", onKeyUpFn);
|
|
52
|
+
}
|
|
53
|
+
|
|
40
54
|
// Prevent context menu on right click
|
|
41
55
|
document.addEventListener("contextmenu", evt => {
|
|
42
56
|
evt.preventDefault();
|
|
43
57
|
return false;
|
|
44
58
|
});
|
|
45
59
|
|
|
60
|
+
// Define behaviour on key down: activate registered tool
|
|
46
61
|
function onKeyDown(evt) {
|
|
47
62
|
// keyboard shortcuts (activate on left mouse button)
|
|
48
63
|
let codes = config.keyboard_shortcuts
|
|
@@ -56,11 +71,7 @@ export function addMouseKeyHandlers(config, viewports) {
|
|
|
56
71
|
.filter(key => keyCodes[key] == evt.keyCode)
|
|
57
72
|
.pop();
|
|
58
73
|
if (config.debug) console.log("active", config.keyboard_shortcuts[key]);
|
|
59
|
-
setToolActive(
|
|
60
|
-
config.keyboard_shortcuts[key],
|
|
61
|
-
{ mouseButtonMask: 1 },
|
|
62
|
-
viewports
|
|
63
|
-
);
|
|
74
|
+
setToolActive(config.keyboard_shortcuts[key], { mouseButtonMask: 1 });
|
|
64
75
|
document.addEventListener("keydown", onKeyDown, { once: true });
|
|
65
76
|
}
|
|
66
77
|
// right drag + shift
|
|
@@ -70,11 +81,7 @@ export function addMouseKeyHandlers(config, viewports) {
|
|
|
70
81
|
evt.keyCode == keyCodes.KEY_SHIFT
|
|
71
82
|
) {
|
|
72
83
|
if (config.debug) console.log("active", config.mouse_button_right.shift);
|
|
73
|
-
setToolActive(
|
|
74
|
-
config.mouse_button_right.shift,
|
|
75
|
-
{ mouseButtonMask: 2 },
|
|
76
|
-
viewports
|
|
77
|
-
);
|
|
84
|
+
setToolActive(config.mouse_button_right.shift, { mouseButtonMask: 2 });
|
|
78
85
|
document.addEventListener("keyup", onKeyUp, { once: true });
|
|
79
86
|
}
|
|
80
87
|
// right drag + ctrl
|
|
@@ -84,11 +91,7 @@ export function addMouseKeyHandlers(config, viewports) {
|
|
|
84
91
|
evt.keyCode == keyCodes.KEY_CONTROL
|
|
85
92
|
) {
|
|
86
93
|
if (config.debug) console.log("active", config.mouse_button_right.ctrl);
|
|
87
|
-
setToolActive(
|
|
88
|
-
config.mouse_button_right.ctrl,
|
|
89
|
-
{ mouseButtonMask: 2 },
|
|
90
|
-
viewports
|
|
91
|
-
);
|
|
94
|
+
setToolActive(config.mouse_button_right.ctrl, { mouseButtonMask: 2 });
|
|
92
95
|
document.addEventListener("keyup", onKeyUp, { once: true });
|
|
93
96
|
}
|
|
94
97
|
// leave default
|
|
@@ -98,36 +101,36 @@ export function addMouseKeyHandlers(config, viewports) {
|
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
|
|
104
|
+
// Define behaviour on key up: restore original tool
|
|
101
105
|
function onKeyUp(e) {
|
|
102
106
|
if (config.debug)
|
|
103
107
|
console.log("active default", config.mouse_button_right.default);
|
|
104
|
-
setToolActive(
|
|
105
|
-
config.mouse_button_right.default,
|
|
106
|
-
{ mouseButtonMask: 2 },
|
|
107
|
-
viewports
|
|
108
|
-
);
|
|
108
|
+
setToolActive(config.mouse_button_right.default, { mouseButtonMask: 2 });
|
|
109
109
|
document.addEventListener("keydown", onKeyDown, { once: true });
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// activate default, if any
|
|
113
|
-
|
|
114
113
|
if (config.mouse_button_right && config.mouse_button_right.default) {
|
|
115
|
-
setToolActive(
|
|
116
|
-
config.mouse_button_right.default,
|
|
117
|
-
{ mouseButtonMask: 2 },
|
|
118
|
-
viewports
|
|
119
|
-
);
|
|
114
|
+
setToolActive(config.mouse_button_right.default, { mouseButtonMask: 2 });
|
|
120
115
|
}
|
|
121
116
|
|
|
122
117
|
if (config.mouse_button_left && config.mouse_button_left.default) {
|
|
123
|
-
setToolActive(
|
|
124
|
-
config.mouse_button_left.default,
|
|
125
|
-
{ mouseButtonMask: 1 },
|
|
126
|
-
viewports
|
|
127
|
-
);
|
|
118
|
+
setToolActive(config.mouse_button_left.default, { mouseButtonMask: 1 });
|
|
128
119
|
}
|
|
129
120
|
|
|
130
121
|
document.addEventListener("keydown", onKeyDown, { once: true });
|
|
122
|
+
|
|
123
|
+
onKeyDownFn = onKeyDown;
|
|
124
|
+
onKeyUpFn = onKeyUp;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
export function removeMouseKeyHandlers() {
|
|
131
|
+
document.removeEventListener("keydown", onKeyDownFn);
|
|
132
|
+
onKeyDownFn = null;
|
|
133
|
+
onKeyUpFn = null;
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
/**
|
|
@@ -18,6 +18,7 @@ import { updateStackToolState } from "../imageTools";
|
|
|
18
18
|
|
|
19
19
|
// custom code
|
|
20
20
|
import { setLabelmap3DForElement } from "./setLabelMap3D";
|
|
21
|
+
import { each } from "hammerjs";
|
|
21
22
|
// override function
|
|
22
23
|
setters.labelmap3DForElement = setLabelmap3DForElement;
|
|
23
24
|
|
|
@@ -419,22 +420,37 @@ export function clearSegmentationState() {
|
|
|
419
420
|
|
|
420
421
|
/**
|
|
421
422
|
* Enable brushing
|
|
422
|
-
*
|
|
423
|
-
*
|
|
423
|
+
* NOTE: if options contains `thresholds`, ThresholdsBrush is activated, otherwise BrushTool is activated.
|
|
424
|
+
* Anyway, the activated tool name is returned
|
|
425
|
+
* @param {Object} options - An object containing configuration values (eg radius, thresholds, etc...)
|
|
424
426
|
*/
|
|
425
|
-
export function enableBrushTool(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
427
|
+
export function enableBrushTool(viewports, options) {
|
|
428
|
+
console.log("enable", options);
|
|
429
|
+
setBrushProps(options);
|
|
430
|
+
const brushType = "thresholds" in options ? "ThresholdsBrush" : "Brush";
|
|
431
|
+
setToolActive(brushType, viewports);
|
|
432
|
+
return brushType;
|
|
429
433
|
}
|
|
430
434
|
|
|
431
435
|
/**
|
|
432
436
|
* Disable brushing
|
|
433
|
-
*
|
|
437
|
+
* This function disables both brush tools, if found active on `viewports`
|
|
438
|
+
* @param {String} toolToActivate - The name of the tool to activate after removing the brush @optional
|
|
434
439
|
*/
|
|
435
|
-
export function disableBrushTool(toolToActivate) {
|
|
436
|
-
|
|
437
|
-
|
|
440
|
+
export function disableBrushTool(viewports, toolToActivate) {
|
|
441
|
+
each(viewports, viewport => {
|
|
442
|
+
const el = document.getElementById(viewport);
|
|
443
|
+
if (cornerstoneTools.isToolActiveForElement(el, "ThresholdsBrush")) {
|
|
444
|
+
setToolDisabled("ThresholdsBrush", [viewport]);
|
|
445
|
+
}
|
|
446
|
+
if (cornerstoneTools.isToolActiveForElement(el, "Brush")) {
|
|
447
|
+
setToolDisabled("Brush", [viewport]);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
if (toolToActivate) {
|
|
452
|
+
setToolActive(toolToActivate);
|
|
453
|
+
}
|
|
438
454
|
}
|
|
439
455
|
|
|
440
456
|
/**
|
|
@@ -29,7 +29,7 @@ TODO
|
|
|
29
29
|
|
|
30
30
|
# Larvitar segmentation API
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
To enable brush tools, user can call directly the `setToolActive` / `setToolDisabled` api, in this case he has to handle brush type (thresholds or not), props (radius etc) and tool switching. Otherwise, Larvitar implements the utility functions `enableBrushTool` and `disableBrushTool` that internally handle brush type and props with a single call.
|
|
33
33
|
|
|
34
34
|
# Customization
|
|
35
35
|
|
package/index.js
CHANGED
|
@@ -205,6 +205,7 @@ import { saveAnnotations, loadAnnotations } from "./imaging/tools/io";
|
|
|
205
205
|
|
|
206
206
|
import {
|
|
207
207
|
addMouseKeyHandlers,
|
|
208
|
+
removeMouseKeyHandlers,
|
|
208
209
|
toggleMouseToolsListeners
|
|
209
210
|
} from "./imaging/tools/interaction";
|
|
210
211
|
|
|
@@ -367,6 +368,7 @@ export {
|
|
|
367
368
|
loadAnnotations,
|
|
368
369
|
// tools/interaction
|
|
369
370
|
addMouseKeyHandlers,
|
|
371
|
+
removeMouseKeyHandlers,
|
|
370
372
|
// tools/segmentation
|
|
371
373
|
initSegmentationModule,
|
|
372
374
|
addSegmentationMask,
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"medical",
|
|
7
7
|
"cornerstone"
|
|
8
8
|
],
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.4.0",
|
|
10
10
|
"description": "javascript library for parsing, loading, rendering and interacting with DICOM images",
|
|
11
11
|
"repository": {
|
|
12
12
|
"url": "https://github.com/dvisionlab/Larvitar.git",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
"module": "dist/larvitar.js",
|
|
55
55
|
"browser": "dist/larvitar.js",
|
|
56
56
|
"type": "module"
|
|
57
|
-
}
|
|
57
|
+
}
|