larvitar 1.5.7 → 1.5.9
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
CHANGED
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
## Dicom Image Toolkit for CornerstoneJS
|
|
8
8
|
|
|
9
|
-
### Current version: 1.5.
|
|
10
|
-
|
|
11
|
-
### Latest Published Release: 1.5.7
|
|
9
|
+
### Current version: 1.5.9
|
|
10
|
+
### Latest Published Release: 1.5.9
|
|
12
11
|
|
|
13
12
|
This library provides common DICOM functionalities to be used in web-applications: it's wrapper that simplifies the use of cornerstone-js environment.
|
|
14
13
|
Orthogonal multiplanar reformat is included as well as custom loader/exporter for nrrd files and [Vuex](https://vuex.vuejs.org/) custom integration.
|
|
@@ -40,6 +39,7 @@ Orthogonal multiplanar reformat is included as well as custom loader/exporter fo
|
|
|
40
39
|
- `tools/custom/editMaskTool` is a custom cornerstone tool for 2D visualization of segmentation masks with brush functionalities
|
|
41
40
|
- `tools/custom/seedTool` is a custom cornerstone tool for 2D interactive seeding with custom colors and labels
|
|
42
41
|
- `tools/custom/thresholdsBrushTool` is a custom cornerstone tool for handling thresholds in a brush tool
|
|
42
|
+
- `tools/custom/Slice4DScrollMouseWheel` is a custom cornerstone tool for handling navigation of slices in a 4D DICOM series
|
|
43
43
|
- `tools/default` default tools map and configuration
|
|
44
44
|
- `tools/io` import and export functionalities for tools
|
|
45
45
|
- `tools/main` tools main functionalities
|
package/imaging/imageStore.js
CHANGED
|
@@ -305,12 +305,14 @@ class Larvitar_Store {
|
|
|
305
305
|
* @param {Object} vuexStore - The app vuex store [optional]
|
|
306
306
|
* @param {String} vuexModule - The name of the vuex store module, can be null
|
|
307
307
|
* @param {Boolean} registerModule - If true, the module is registered under Vuex global store
|
|
308
|
+
* @param {Object} _Vue - The Vue instance
|
|
308
309
|
*/
|
|
309
310
|
|
|
310
|
-
export function initLarvitarStore(vuexStore, vuexModule, registerModule) {
|
|
311
|
+
export function initLarvitarStore(vuexStore, vuexModule, registerModule, _Vue) {
|
|
311
312
|
if (vuexStore) {
|
|
312
313
|
larvitar_store = new Larvitar_Store(vuexStore, vuexModule);
|
|
313
314
|
if (registerModule) {
|
|
315
|
+
larvitar.defineVue(_Vue);
|
|
314
316
|
vuexStore.registerModule(vuexModule, larvitar);
|
|
315
317
|
}
|
|
316
318
|
} else {
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/** @module imaging/tools/custom/4dSliceScrollTool
|
|
2
|
+
* @desc This file provides functionalities for an alternative scroll tool
|
|
3
|
+
* to handle 4d exam and navigate to the correct slice
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// external libraries
|
|
9
|
+
import cornerstoneTools from "cornerstone-tools";
|
|
10
|
+
const external = cornerstoneTools.external;
|
|
11
|
+
|
|
12
|
+
const BaseTool = cornerstoneTools.importInternal("base/BaseTool");
|
|
13
|
+
const scroll = cornerstoneTools.importInternal("util/scroll");
|
|
14
|
+
const scrollToIndex = cornerstoneTools.importInternal("util/scrollToIndex");
|
|
15
|
+
const getToolState = cornerstoneTools.getToolState;
|
|
16
|
+
const clip = cornerstoneTools.importInternal("util/clip");
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @public
|
|
20
|
+
* @class 4DScrollMouseWheelTool
|
|
21
|
+
* @memberof Tools
|
|
22
|
+
*
|
|
23
|
+
* @classdesc Tool for scrolling through a series using the mouse wheel.
|
|
24
|
+
* @extends Tools.Base.BaseTool
|
|
25
|
+
*/
|
|
26
|
+
export default class Slice4DScrollMouseWheelTool extends BaseTool {
|
|
27
|
+
constructor(props = {}) {
|
|
28
|
+
const defaultProps = {
|
|
29
|
+
name: 'Slice4DScrollMouseWheel',
|
|
30
|
+
supportedInteractionTypes: ['MouseWheel'],
|
|
31
|
+
configuration: {
|
|
32
|
+
loop: false,
|
|
33
|
+
allowSkipping: true,
|
|
34
|
+
invert: false,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
console.log('building wheel tool');
|
|
38
|
+
super(props, defaultProps);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
mouseWheelCallback(evt) {
|
|
42
|
+
const { direction: images, element } = evt.detail;
|
|
43
|
+
const { loop, allowSkipping, invert, framesNumber } = this.configuration;
|
|
44
|
+
const direction = invert ? (images * framesNumber)*(-1) : (images * framesNumber);
|
|
45
|
+
console.log('wheel callback');
|
|
46
|
+
console.log('Images ', images);
|
|
47
|
+
console.log('Direction ', direction);
|
|
48
|
+
scroll(element, direction, loop, allowSkipping);
|
|
49
|
+
// scroll4DSlices(element, direction, loop, allowSkipping);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Scrolls through the slice of a 4D stack.
|
|
54
|
+
* @export @public @method
|
|
55
|
+
* @name scroll4DSlices
|
|
56
|
+
*
|
|
57
|
+
* @param {HTMLElement} element The element to scroll.
|
|
58
|
+
* @param {number} images The number of images to scroll through.
|
|
59
|
+
* @param {type} [loop = false] Whether to loop the scrolling.
|
|
60
|
+
* @param {type} [allowSkipping = true] Whether frames can be skipped.
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
const scroll4DSlices = function(element, images, loop, allowSkipping, framesNumber) {
|
|
64
|
+
const toolData = getToolState(element, 'stack');
|
|
65
|
+
|
|
66
|
+
if (!toolData || !toolData.data || !toolData.data.length) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const stackData = toolData.data[0];
|
|
71
|
+
|
|
72
|
+
if (!stackData.pending) {
|
|
73
|
+
stackData.pending = [];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let newImageIdIndex = stackData.currentImageIdIndex + images ;//+ 1 + framesNumber;
|
|
77
|
+
console.log('currentImageIdIndex', stackData.currentImageIdIndex)
|
|
78
|
+
console.log('newImageIdIndex calculated ', newImageIdIndex);
|
|
79
|
+
if (loop) {
|
|
80
|
+
const nbImages = stackData.imageIds.length;
|
|
81
|
+
newImageIdIndex %= nbImages;
|
|
82
|
+
} else {
|
|
83
|
+
newImageIdIndex = clip(newImageIdIndex, 0, stackData.imageIds.length - 1);
|
|
84
|
+
console.log('newImageIdIndex after clip ', newImageIdIndex);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (allowSkipping) {
|
|
88
|
+
scrollToIndex(element, newImageIdIndex);
|
|
89
|
+
} else {
|
|
90
|
+
const pendingEvent = {
|
|
91
|
+
index: newImageIdIndex,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
stackData.pending.push(pendingEvent);
|
|
95
|
+
scrollWithoutSkipping(stackData, pendingEvent, element);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Recursively scrolls the stack until the desired image is reached.
|
|
101
|
+
* @private
|
|
102
|
+
* @method
|
|
103
|
+
* @name scrollWithoutSkipping
|
|
104
|
+
*
|
|
105
|
+
* @param {type} stackData Data object containing information about the stack.
|
|
106
|
+
* @param {Object} pendingEvent The event to process next.
|
|
107
|
+
* @param {HTMLElement} element The element being scrolled through.
|
|
108
|
+
* @returns {void}
|
|
109
|
+
*/
|
|
110
|
+
function scrollWithoutSkipping(stackData, pendingEvent, element) {
|
|
111
|
+
if (stackData.pending[0] === pendingEvent) {
|
|
112
|
+
if (stackData.currentImageIdIndex === pendingEvent.index) {
|
|
113
|
+
stackData.pending.splice(stackData.pending.indexOf(pendingEvent), 1);
|
|
114
|
+
|
|
115
|
+
if (stackData.pending.length > 0) {
|
|
116
|
+
scrollWithoutSkipping(stackData, stackData.pending[0], element);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const newImageHandler = function(event) {
|
|
123
|
+
const index = stackData.imageIds.indexOf(event.detail.image.imageId);
|
|
124
|
+
|
|
125
|
+
if (index === pendingEvent.index) {
|
|
126
|
+
stackData.pending.splice(stackData.pending.indexOf(pendingEvent), 1);
|
|
127
|
+
element.removeEventListener(
|
|
128
|
+
external.cornerstone.EVENTS.NEW_IMAGE,
|
|
129
|
+
newImageHandler
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (stackData.pending.length > 0) {
|
|
133
|
+
scrollWithoutSkipping(stackData, stackData.pending[0], element);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
element.addEventListener(
|
|
139
|
+
external.cornerstone.EVENTS.NEW_IMAGE,
|
|
140
|
+
newImageHandler
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
scrollToIndex(element, pendingEvent.index);
|
|
144
|
+
}
|
|
145
|
+
}
|
package/imaging/tools/default.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
import { filter, isArray } from "lodash";
|
|
29
29
|
import ThresholdsBrushTool from "./custom/thresholdsBrushTool";
|
|
30
|
+
import Slice4DScrollMouseWheelTool from "./custom/4dSliceScrollTool";
|
|
30
31
|
import PolylineScissorsTool from "./custom/polylineScissorsTool";
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -108,9 +109,23 @@ const DEFAULT_TOOLS = {
|
|
|
108
109
|
invert: false
|
|
109
110
|
},
|
|
110
111
|
cleanable: false,
|
|
111
|
-
defaultActive:
|
|
112
|
+
defaultActive: false,
|
|
112
113
|
class: "StackScrollMouseWheelTool"
|
|
113
114
|
},
|
|
115
|
+
Slice4DScrollMouseWheel: {
|
|
116
|
+
name: "Slice4DScrollMouseWheel",
|
|
117
|
+
viewports: "all",
|
|
118
|
+
configuration: {
|
|
119
|
+
loop: false, // default false
|
|
120
|
+
allowSkipping: false, // default true
|
|
121
|
+
invert: false,
|
|
122
|
+
framesNumber: 1
|
|
123
|
+
},
|
|
124
|
+
options: {},
|
|
125
|
+
cleanable: false,
|
|
126
|
+
defaultActive: true,
|
|
127
|
+
class: "Slice4DScrollMouseWheelTool"
|
|
128
|
+
},
|
|
114
129
|
Pan: {
|
|
115
130
|
name: "Pan",
|
|
116
131
|
viewports: "all",
|
|
@@ -398,7 +413,8 @@ const DEFAULT_TOOLS = {
|
|
|
398
413
|
*/
|
|
399
414
|
const dvTools = {
|
|
400
415
|
ThresholdsBrushTool: ThresholdsBrushTool,
|
|
401
|
-
PolylineScissorsTool: PolylineScissorsTool
|
|
416
|
+
PolylineScissorsTool: PolylineScissorsTool,
|
|
417
|
+
Slice4DScrollMouseWheelTool: Slice4DScrollMouseWheelTool
|
|
402
418
|
};
|
|
403
419
|
|
|
404
420
|
/**
|
|
@@ -489,4 +505,4 @@ export {
|
|
|
489
505
|
dvTools,
|
|
490
506
|
getDefaultToolsByType,
|
|
491
507
|
setDefaultToolsProps
|
|
492
|
-
};
|
|
508
|
+
};
|
package/modules/vuex/larvitar.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// Larvitar Vuex
|
|
2
|
-
|
|
3
|
-
import Vue from "vue";
|
|
1
|
+
// Larvitar Vuex instance
|
|
2
|
+
var Vue = null;
|
|
4
3
|
|
|
5
4
|
// default viewport store object
|
|
6
5
|
const DEFAULT_VIEWPORT = {
|
|
@@ -181,3 +180,8 @@ export default {
|
|
|
181
180
|
commit("canvas", { id, d: { voi: { windowWidth, windowCenter } } })
|
|
182
181
|
}
|
|
183
182
|
};
|
|
183
|
+
|
|
184
|
+
// define Vue instance from outside dependency
|
|
185
|
+
export const defineVue = _Vue => {
|
|
186
|
+
Vue = _Vue;
|
|
187
|
+
};
|
package/package.json
CHANGED