larvitar 2.0.5 → 2.0.7
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 +2 -2
- package/dist/imaging/imageRendering.d.ts +1 -71
- package/dist/imaging/imageStore.d.ts +5 -0
- package/dist/imaging/loaders/commonLoader.d.ts +4 -4
- package/dist/imaging/loaders/nrrdLoader.d.ts +1 -51
- package/dist/larvitar.js +13 -1
- package/dist/larvitar.js.map +1 -1
- package/imaging/tools/types.d.ts +19 -19
- package/imaging/types.d.ts +110 -2
- package/package.json +7 -2
- package/.github/workflows/build-docs.yml +0 -59
- package/.github/workflows/codeql-analysis.yml +0 -71
- package/.github/workflows/deploy.yml +0 -37
- package/.vscode/settings.json +0 -4
- package/CODE_OF_CONDUCT.md +0 -76
- package/MIGRATION.md +0 -25
- package/bundler/webpack.common.js +0 -27
- package/bundler/webpack.dev.js +0 -23
- package/bundler/webpack.prod.js +0 -19
- package/decs.d.ts +0 -12
- package/dist/imaging/MetaDataReadable.d.ts +0 -41
- package/dist/imaging/MetaDataTypes.d.ts +0 -3489
- package/imaging/dataDictionary.json +0 -21866
- package/imaging/imageAnonymization.ts +0 -135
- package/imaging/imageColormaps.ts +0 -217
- package/imaging/imageContours.ts +0 -196
- package/imaging/imageIo.ts +0 -251
- package/imaging/imageLayers.ts +0 -121
- package/imaging/imageLoading.ts +0 -299
- package/imaging/imageParsing.ts +0 -444
- package/imaging/imagePresets.ts +0 -156
- package/imaging/imageRendering.ts +0 -1091
- package/imaging/imageReslice.ts +0 -87
- package/imaging/imageStore.ts +0 -487
- package/imaging/imageTags.ts +0 -609
- package/imaging/imageTools.js +0 -708
- package/imaging/imageUtils.ts +0 -1079
- package/imaging/loaders/commonLoader.ts +0 -275
- package/imaging/loaders/dicomLoader.ts +0 -66
- package/imaging/loaders/fileLoader.ts +0 -71
- package/imaging/loaders/multiframeLoader.ts +0 -435
- package/imaging/loaders/nrrdLoader.ts +0 -630
- package/imaging/loaders/resliceLoader.ts +0 -205
- package/imaging/monitors/memory.ts +0 -151
- package/imaging/monitors/performance.ts +0 -34
- package/imaging/parsers/ecg.ts +0 -54
- package/imaging/parsers/nrrd.js +0 -485
- package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
- package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
- package/imaging/tools/custom/contourTool.js +0 -1884
- package/imaging/tools/custom/diameterTool.js +0 -141
- package/imaging/tools/custom/editMaskTool.js +0 -141
- package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
- package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
- package/imaging/tools/custom/polylineScissorsTool.js +0 -59
- package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
- package/imaging/tools/custom/seedTool.js +0 -342
- package/imaging/tools/custom/setLabelMap3D.ts +0 -242
- package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
- package/imaging/tools/default.ts +0 -594
- package/imaging/tools/interaction.ts +0 -266
- package/imaging/tools/io.ts +0 -229
- package/imaging/tools/main.ts +0 -427
- package/imaging/tools/segmentation.ts +0 -532
- package/imaging/tools/segmentations.md +0 -38
- package/imaging/tools/state.ts +0 -74
- package/imaging/tools/strategies/eraseFreehand.js +0 -76
- package/imaging/tools/strategies/fillFreehand.js +0 -79
- package/imaging/tools/strategies/index.js +0 -2
- package/imaging/waveforms/ecg.ts +0 -191
- package/index.ts +0 -431
- package/jsdoc.json +0 -52
- package/rollup.config.js +0 -51
- package/template/.gitkeep +0 -0
- package/tsconfig.json +0 -102
- /package/imaging/{MetaDataReadable.ts → MetaDataReadable.d.ts} +0 -0
- /package/imaging/{MetaDataTypes.ts → MetaDataTypes.d.ts} +0 -0
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
// // external libraries
|
|
2
|
-
// import csTools from "cornerstone-tools";
|
|
3
|
-
// import { each, cloneDeep } from "lodash";
|
|
4
|
-
|
|
5
|
-
// // internal libraries
|
|
6
|
-
// import { remapVoxel } from "../../imageUtils";
|
|
7
|
-
// import { addToolStateSingleSlice, setToolEnabled } from "../../imageTools";
|
|
8
|
-
// import { getSliceNumberFromImageId } from "../../loaders/nrrdLoader";
|
|
9
|
-
|
|
10
|
-
// // cornerstone tools imports
|
|
11
|
-
// const BaseAnnotationTool = csTools.importInternal("base/BaseAnnotationTool");
|
|
12
|
-
// // State
|
|
13
|
-
// const getToolState = csTools.getToolState;
|
|
14
|
-
// // Drawing
|
|
15
|
-
// const getNewContext = csTools.importInternal("drawing/getNewContext");
|
|
16
|
-
// const draw = csTools.importInternal("drawing/draw");
|
|
17
|
-
// const drawTextBox = csTools.importInternal("drawing/drawTextBox");
|
|
18
|
-
// const drawCircle = csTools.importInternal("drawing/drawCircle");
|
|
19
|
-
// // Utilities
|
|
20
|
-
// const getRGBPixels = csTools.importInternal("util/getRGBPixels");
|
|
21
|
-
// const calculateSUV = csTools.importInternal("util/calculateSUV");
|
|
22
|
-
// const probeCursor = csTools.importInternal("util/probeCursor");
|
|
23
|
-
// const getLogger = csTools.importInternal("util/getLogger");
|
|
24
|
-
// const throttle = csTools.importInternal("util/throttle");
|
|
25
|
-
|
|
26
|
-
// const logger = getLogger("tools:annotation:ProbeTool");
|
|
27
|
-
|
|
28
|
-
// // internal constants
|
|
29
|
-
// const seedLabels = {
|
|
30
|
-
// segmentation_01: "Aorta",
|
|
31
|
-
// segmentation_02: "Aneurysm",
|
|
32
|
-
// segmentation_03: "Carrefour",
|
|
33
|
-
// regionGrowing: "regionGrowing"
|
|
34
|
-
// };
|
|
35
|
-
|
|
36
|
-
// /**
|
|
37
|
-
// * @public
|
|
38
|
-
// * @class SeedsTool
|
|
39
|
-
// * @memberof Tools.Annotation
|
|
40
|
-
// * @classdesc Tool which provides cohordinates of the picked poin
|
|
41
|
-
// * @extends Tools.Base.BaseAnnotationTool
|
|
42
|
-
// */
|
|
43
|
-
// export class SeedsTool extends BaseAnnotationTool {
|
|
44
|
-
// constructor(props = {}) {
|
|
45
|
-
// const defaultProps = {
|
|
46
|
-
// name: "Seeds",
|
|
47
|
-
// supportedInteractionTypes: ["Mouse"],
|
|
48
|
-
// svgCursor: probeCursor
|
|
49
|
-
// };
|
|
50
|
-
|
|
51
|
-
// super(props, defaultProps);
|
|
52
|
-
|
|
53
|
-
// if (props.initialize) {
|
|
54
|
-
// this.initializeTool(props.preLoadSeeds, props.initViewport);
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
|
-
// this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);
|
|
58
|
-
// }
|
|
59
|
-
|
|
60
|
-
// initializeTool(seeds, elementId) {
|
|
61
|
-
// let element = document.getElementById(elementId);
|
|
62
|
-
|
|
63
|
-
// each(seeds, seed => {
|
|
64
|
-
// let change = {
|
|
65
|
-
// visible: true,
|
|
66
|
-
// active: true,
|
|
67
|
-
// invalidated: true,
|
|
68
|
-
// color: seed.color,
|
|
69
|
-
// name: seed.tag,
|
|
70
|
-
// slice: seed.native_k,
|
|
71
|
-
// handles: {
|
|
72
|
-
// end: {
|
|
73
|
-
// x: seed.native_i,
|
|
74
|
-
// y: seed.native_j,
|
|
75
|
-
// highlight: true,
|
|
76
|
-
// active: true
|
|
77
|
-
// }
|
|
78
|
-
// }
|
|
79
|
-
// };
|
|
80
|
-
|
|
81
|
-
// let sliceNumber = seed.native_k;
|
|
82
|
-
|
|
83
|
-
// // add to master viewport
|
|
84
|
-
// addToolStateSingleSlice(element, this.name, change, sliceNumber);
|
|
85
|
-
|
|
86
|
-
// // sync remaining viewports
|
|
87
|
-
// this.syncViewports(elementId, change, sliceNumber);
|
|
88
|
-
// });
|
|
89
|
-
|
|
90
|
-
// csTools.external.cornerstone.updateImage(element);
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
// createNewMeasurement(eventData) {
|
|
94
|
-
// if (eventData.event.srcElement.localName != "canvas") {
|
|
95
|
-
// return;
|
|
96
|
-
// }
|
|
97
|
-
// const goodEventData =
|
|
98
|
-
// eventData && eventData.currentPoints && eventData.currentPoints.image;
|
|
99
|
-
|
|
100
|
-
// if (!goodEventData) {
|
|
101
|
-
// logger.error(
|
|
102
|
-
// `required eventData not supplied to tool ${this.name}'s createNewMeasurement`
|
|
103
|
-
// );
|
|
104
|
-
|
|
105
|
-
// return;
|
|
106
|
-
// }
|
|
107
|
-
|
|
108
|
-
// var res = {
|
|
109
|
-
// visible: true,
|
|
110
|
-
// active: true,
|
|
111
|
-
// invalidated: true,
|
|
112
|
-
// color: this.options.color,
|
|
113
|
-
// name: this.options.seed_name,
|
|
114
|
-
// slice: getSliceNumberFromImageId(
|
|
115
|
-
// eventData.image.imageId,
|
|
116
|
-
// eventData.element.id
|
|
117
|
-
// ),
|
|
118
|
-
// handles: {
|
|
119
|
-
// end: {
|
|
120
|
-
// x: eventData.currentPoints.image.x,
|
|
121
|
-
// y: eventData.currentPoints.image.y,
|
|
122
|
-
// highlight: true,
|
|
123
|
-
// active: true
|
|
124
|
-
// }
|
|
125
|
-
// },
|
|
126
|
-
// native_i: 0,
|
|
127
|
-
// native_j: 0,
|
|
128
|
-
// native_k: 0
|
|
129
|
-
// };
|
|
130
|
-
|
|
131
|
-
// let sliceNumber = getSliceNumberFromImageId(
|
|
132
|
-
// eventData.image.imageId,
|
|
133
|
-
// eventData.element.id
|
|
134
|
-
// );
|
|
135
|
-
|
|
136
|
-
// // store native coordinates
|
|
137
|
-
// this.storeNativeCoordinates(res, eventData.element.id, sliceNumber);
|
|
138
|
-
|
|
139
|
-
// // sync all the viewports
|
|
140
|
-
// this.syncViewports(eventData.element.id, res, sliceNumber);
|
|
141
|
-
|
|
142
|
-
// // optionally set data in store
|
|
143
|
-
|
|
144
|
-
// // set mode to "enabled"
|
|
145
|
-
// setToolEnabled(this.name);
|
|
146
|
-
|
|
147
|
-
// return res;
|
|
148
|
-
// }
|
|
149
|
-
|
|
150
|
-
// /**
|
|
151
|
-
// *
|
|
152
|
-
// *
|
|
153
|
-
// * @param {*} element
|
|
154
|
-
// * @param {*} data
|
|
155
|
-
// * @param {*} coords
|
|
156
|
-
// * @returns {Boolean}
|
|
157
|
-
// */
|
|
158
|
-
// pointNearTool(element, data, coords) {
|
|
159
|
-
// const hasEndHandle = data && data.handles && data.handles.end;
|
|
160
|
-
// const validParameters = hasEndHandle;
|
|
161
|
-
|
|
162
|
-
// if (!validParameters) {
|
|
163
|
-
// logger.warn(
|
|
164
|
-
// `invalid parameters supplied to tool ${this.name}'s pointNearTool`
|
|
165
|
-
// );
|
|
166
|
-
// }
|
|
167
|
-
|
|
168
|
-
// if (!validParameters || data.visible === false) {
|
|
169
|
-
// return false;
|
|
170
|
-
// }
|
|
171
|
-
|
|
172
|
-
// const probeCoords = csTools.external.cornerstone.pixelToCanvas(
|
|
173
|
-
// element,
|
|
174
|
-
// data.handles.end
|
|
175
|
-
// );
|
|
176
|
-
|
|
177
|
-
// return (
|
|
178
|
-
// csTools.external.cornerstoneMath.point.distance(probeCoords, coords) < 5
|
|
179
|
-
// );
|
|
180
|
-
// }
|
|
181
|
-
|
|
182
|
-
// updateCachedStats(image, element, data) {
|
|
183
|
-
// const x = Math.round(data.handles.end.x);
|
|
184
|
-
// const y = Math.round(data.handles.end.y);
|
|
185
|
-
|
|
186
|
-
// const stats = {};
|
|
187
|
-
|
|
188
|
-
// if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {
|
|
189
|
-
// stats.x = x;
|
|
190
|
-
// stats.y = y;
|
|
191
|
-
|
|
192
|
-
// if (image.color) {
|
|
193
|
-
// stats.storedPixels = getRGBPixels(element, x, y, 1, 1);
|
|
194
|
-
// } else {
|
|
195
|
-
// stats.storedPixels = csTools.external.cornerstone.getStoredPixels(
|
|
196
|
-
// element,
|
|
197
|
-
// x,
|
|
198
|
-
// y,
|
|
199
|
-
// 1,
|
|
200
|
-
// 1
|
|
201
|
-
// );
|
|
202
|
-
// stats.sp = stats.storedPixels[0];
|
|
203
|
-
// stats.mo = stats.sp * image.slope + image.intercept;
|
|
204
|
-
// stats.suv = calculateSUV(image, stats.sp);
|
|
205
|
-
// stats.color = data.color || this.options.color;
|
|
206
|
-
// stats.name = data.name || this.options.seed_name;
|
|
207
|
-
// }
|
|
208
|
-
// }
|
|
209
|
-
|
|
210
|
-
// data.cachedStats = stats;
|
|
211
|
-
// data.invalidated = false;
|
|
212
|
-
// }
|
|
213
|
-
|
|
214
|
-
// renderToolData(evt) {
|
|
215
|
-
// const eventData = evt.detail;
|
|
216
|
-
// const toolData = getToolState(evt.currentTarget, this.name);
|
|
217
|
-
|
|
218
|
-
// if (!toolData) {
|
|
219
|
-
// return;
|
|
220
|
-
// }
|
|
221
|
-
|
|
222
|
-
// // We have tool data for this element - iterate over each one and draw it
|
|
223
|
-
// const context = getNewContext(eventData.canvasContext.canvas);
|
|
224
|
-
// const { image, element } = eventData;
|
|
225
|
-
|
|
226
|
-
// for (let i = 0; i < toolData.data.length; i++) {
|
|
227
|
-
// const data = toolData.data[i];
|
|
228
|
-
|
|
229
|
-
// if (data.visible === false) {
|
|
230
|
-
// continue;
|
|
231
|
-
// }
|
|
232
|
-
|
|
233
|
-
// draw(context, context => {
|
|
234
|
-
// const center = data.handles.end;
|
|
235
|
-
|
|
236
|
-
// // Update textbox stats
|
|
237
|
-
// if (data.invalidated === true) {
|
|
238
|
-
// if (data.cachedStats) {
|
|
239
|
-
// this.throttledUpdateCachedStats(image, element, data);
|
|
240
|
-
// } else {
|
|
241
|
-
// this.updateCachedStats(image, element, data);
|
|
242
|
-
// }
|
|
243
|
-
// }
|
|
244
|
-
|
|
245
|
-
// const { x, y, color, name } = data.cachedStats;
|
|
246
|
-
|
|
247
|
-
// let text;
|
|
248
|
-
|
|
249
|
-
// if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {
|
|
250
|
-
// text = this.getLabelText(name);
|
|
251
|
-
|
|
252
|
-
// // Coords for text
|
|
253
|
-
// const coords = {
|
|
254
|
-
// // Translate the x/y away from the cursor
|
|
255
|
-
// x: data.handles.end.x + 3,
|
|
256
|
-
// y: data.handles.end.y - 3
|
|
257
|
-
// };
|
|
258
|
-
// const textCoords = csTools.external.cornerstone.pixelToCanvas(
|
|
259
|
-
// eventData.element,
|
|
260
|
-
// coords
|
|
261
|
-
// );
|
|
262
|
-
|
|
263
|
-
// drawTextBox(context, text, textCoords.x, textCoords.y, color);
|
|
264
|
-
|
|
265
|
-
// drawCircle(context, element, center, this.options.radius || 3, {
|
|
266
|
-
// color: color,
|
|
267
|
-
// fillStyle: color
|
|
268
|
-
// });
|
|
269
|
-
// }
|
|
270
|
-
// });
|
|
271
|
-
// }
|
|
272
|
-
// }
|
|
273
|
-
|
|
274
|
-
// getLabelText(name) {
|
|
275
|
-
// // let text = (text = ` ${name}`);
|
|
276
|
-
// let text = seedLabels[name];
|
|
277
|
-
// return text;
|
|
278
|
-
// }
|
|
279
|
-
|
|
280
|
-
// storeNativeCoordinates(input, inputViewportId, frame) {
|
|
281
|
-
// let native = remapVoxel(
|
|
282
|
-
// [
|
|
283
|
-
// Math.floor(input.handles.end.x),
|
|
284
|
-
// Math.floor(input.handles.end.y),
|
|
285
|
-
// parseInt(frame)
|
|
286
|
-
// ],
|
|
287
|
-
// inputViewportId,
|
|
288
|
-
// "axial"
|
|
289
|
-
// );
|
|
290
|
-
// input.native_i = native[0];
|
|
291
|
-
// input.native_j = native[1];
|
|
292
|
-
// input.native_k = native[2];
|
|
293
|
-
// }
|
|
294
|
-
|
|
295
|
-
// syncViewports(pickingViewportId, change, sliceNumber) {
|
|
296
|
-
// let enabledElements = csTools.external.cornerstone.getEnabledElements();
|
|
297
|
-
// var from = pickingViewportId;
|
|
298
|
-
|
|
299
|
-
// each(enabledElements, el => {
|
|
300
|
-
// if (el.element.id == pickingViewportId) {
|
|
301
|
-
// return;
|
|
302
|
-
// }
|
|
303
|
-
|
|
304
|
-
// let remapped = this.getRemappedChange(
|
|
305
|
-
// change,
|
|
306
|
-
// sliceNumber,
|
|
307
|
-
// from,
|
|
308
|
-
// el.element.id
|
|
309
|
-
// );
|
|
310
|
-
|
|
311
|
-
// addToolStateSingleSlice(
|
|
312
|
-
// el.element,
|
|
313
|
-
// this.name,
|
|
314
|
-
// remapped.change,
|
|
315
|
-
// remapped.sliceNumber
|
|
316
|
-
// );
|
|
317
|
-
// csTools.external.cornerstone.updateImage(el.element);
|
|
318
|
-
// });
|
|
319
|
-
// }
|
|
320
|
-
|
|
321
|
-
// getRemappedChange(input, frame, fromOrientation, toOrientation) {
|
|
322
|
-
// let ijk = remapVoxel(
|
|
323
|
-
// [
|
|
324
|
-
// Math.floor(input.handles.end.x),
|
|
325
|
-
// Math.floor(input.handles.end.y),
|
|
326
|
-
// parseInt(frame)
|
|
327
|
-
// ],
|
|
328
|
-
// fromOrientation,
|
|
329
|
-
// toOrientation
|
|
330
|
-
// );
|
|
331
|
-
|
|
332
|
-
// let output = cloneDeep(input);
|
|
333
|
-
|
|
334
|
-
// output.handles.end.x = ijk[0];
|
|
335
|
-
// output.handles.end.y = ijk[1];
|
|
336
|
-
|
|
337
|
-
// return {
|
|
338
|
-
// change: output,
|
|
339
|
-
// sliceNumber: ijk[2]
|
|
340
|
-
// };
|
|
341
|
-
// }
|
|
342
|
-
// }
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is a custom version of setLabelMap3D from cs tools source code
|
|
3
|
-
* This let us implement a non-blocking version of the for loop that loads 3d labelmaps on a volume
|
|
4
|
-
* @ronzim
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const ARRAY_TYPES = {
|
|
8
|
-
UINT_16_ARRAY: 0,
|
|
9
|
-
FLOAT_32_ARRAY: 1
|
|
10
|
-
};
|
|
11
|
-
const { UINT_16_ARRAY, FLOAT_32_ARRAY } = ARRAY_TYPES;
|
|
12
|
-
|
|
13
|
-
import cornerstoneTools from "cornerstone-tools";
|
|
14
|
-
import type { TypedArray } from "../../types";
|
|
15
|
-
import { EnabledElement } from "cornerstone-core";
|
|
16
|
-
const { triggerLabelmapModifiedEvent } = cornerstoneTools.importInternal(
|
|
17
|
-
"util/segmentationUtils"
|
|
18
|
-
);
|
|
19
|
-
const getModule = cornerstoneTools.getModule;
|
|
20
|
-
const getToolState = cornerstoneTools.getToolState;
|
|
21
|
-
const storeGetters = cornerstoneTools.store.getters;
|
|
22
|
-
const state = getModule("segmentation").state;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* These function are reported since they are not exposed by cs tools
|
|
26
|
-
*
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
// from getSegmentsOnPixelData.js
|
|
30
|
-
function getSegmentsOnPixelData(pixelData: TypedArray) {
|
|
31
|
-
return [...new Set(pixelData)];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// from getElement.js
|
|
35
|
-
function getElement(elementOrEnabledElementUID: EnabledElement | string) {
|
|
36
|
-
if (elementOrEnabledElementUID instanceof HTMLElement) {
|
|
37
|
-
return elementOrEnabledElementUID;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return storeGetters.enabledElementByUID(elementOrEnabledElementUID);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Takes a 16-bit encoded `ArrayBuffer` and stores it as a `Labelmap3D` for the
|
|
45
|
-
* `BrushStackState` associated with the element.
|
|
46
|
-
*
|
|
47
|
-
* @param {HTMLElement|string} elementOrEnabledElementUID The cornerstone
|
|
48
|
-
* enabled element or its UUID.
|
|
49
|
-
* @param {ArrayBuffer} buffer
|
|
50
|
-
* @param {number} labelmapIndex The index to store the labelmap under.
|
|
51
|
-
* @param {Object[]} metadata = [] Any metadata about the segments.
|
|
52
|
-
* @param {number[][]} [segmentsOnLabelmapArray] An array of array of segments on each imageIdIndex.
|
|
53
|
-
* If not present, is calculated.
|
|
54
|
-
* @param {colorLUTIndex} [colorLUTIndex = 0] The index of the colorLUT to use to render the segmentation.
|
|
55
|
-
* @returns {null}
|
|
56
|
-
*/
|
|
57
|
-
async function setLabelmap3DForElement(
|
|
58
|
-
elementOrEnabledElementUID: EnabledElement | string,
|
|
59
|
-
buffer: ArrayBuffer,
|
|
60
|
-
labelmapIndex: number,
|
|
61
|
-
metadata: Object[] = [],
|
|
62
|
-
segmentsOnLabelmapArray: number[][],
|
|
63
|
-
colorLUTIndex = 0
|
|
64
|
-
) {
|
|
65
|
-
const element = getElement(elementOrEnabledElementUID);
|
|
66
|
-
|
|
67
|
-
if (!element) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const stackState = getToolState(element, "stack");
|
|
72
|
-
const numberOfFrames = stackState.data[0].imageIds.length;
|
|
73
|
-
const firstImageId = stackState.data[0].imageIds[0];
|
|
74
|
-
|
|
75
|
-
const res = await setLabelmap3DByFirstImageId(
|
|
76
|
-
firstImageId,
|
|
77
|
-
buffer,
|
|
78
|
-
labelmapIndex,
|
|
79
|
-
metadata,
|
|
80
|
-
numberOfFrames,
|
|
81
|
-
segmentsOnLabelmapArray,
|
|
82
|
-
colorLUTIndex
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
triggerLabelmapModifiedEvent(element, labelmapIndex);
|
|
86
|
-
|
|
87
|
-
return res;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Takes an 16-bit encoded `ArrayBuffer` and stores it as a `Labelmap3D` for
|
|
92
|
-
* the `BrushStackState` associated with the firstImageId.
|
|
93
|
-
*
|
|
94
|
-
* @param {HTMLElement|string} firstImageId The firstImageId of the series to
|
|
95
|
-
* store the segmentation on.
|
|
96
|
-
* @param {ArrayBuffer} buffer
|
|
97
|
-
* @param {number} labelmapIndex The index to store the labelmap under.
|
|
98
|
-
* @param {Object[]} metadata = [] Any metadata about the segments.
|
|
99
|
-
* @param {number} numberOfFrames The number of frames, required to set up the
|
|
100
|
-
* relevant labelmap2D views.
|
|
101
|
-
* @param {number[][]} [segmentsOnLabelmapArray] An array of array of segments on each imageIdIndex.
|
|
102
|
-
* If not present, is calculated.
|
|
103
|
-
* @param {colorLUTIndex} [colorLUTIndex = 0] The index of the colorLUT to use to render the segmentation.
|
|
104
|
-
* @returns {null}
|
|
105
|
-
*/
|
|
106
|
-
function setLabelmap3DByFirstImageId(
|
|
107
|
-
firstImageId: string,
|
|
108
|
-
buffer: ArrayBuffer,
|
|
109
|
-
labelmapIndex: number,
|
|
110
|
-
metadata: Object[] = [],
|
|
111
|
-
numberOfFrames: number,
|
|
112
|
-
segmentsOnLabelmapArray: number[][],
|
|
113
|
-
colorLUTIndex: number = 0
|
|
114
|
-
) {
|
|
115
|
-
const { configuration } = getModule("segmentation");
|
|
116
|
-
|
|
117
|
-
let brushStackState = state.series[firstImageId];
|
|
118
|
-
|
|
119
|
-
if (!brushStackState) {
|
|
120
|
-
state.series[firstImageId] = {
|
|
121
|
-
activeLabelmapIndex: labelmapIndex,
|
|
122
|
-
labelmaps3D: []
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
brushStackState = state.series[firstImageId];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
brushStackState.labelmaps3D[labelmapIndex] = {
|
|
129
|
-
buffer,
|
|
130
|
-
labelmaps2D: [],
|
|
131
|
-
metadata,
|
|
132
|
-
activeSegmentIndex: 1,
|
|
133
|
-
colorLUTIndex,
|
|
134
|
-
segmentsHidden: [],
|
|
135
|
-
undo: [],
|
|
136
|
-
redo: []
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
const labelmaps2D = brushStackState.labelmaps3D[labelmapIndex].labelmaps2D;
|
|
140
|
-
const slicelengthInBytes = buffer.byteLength / numberOfFrames;
|
|
141
|
-
|
|
142
|
-
/* non-blocking implementation by @ronzim */
|
|
143
|
-
|
|
144
|
-
return new Promise(resolve => {
|
|
145
|
-
function setSingleSlice(i: number, numberOfFrames: number) {
|
|
146
|
-
var pixelData: TypedArray | undefined = void 0;
|
|
147
|
-
|
|
148
|
-
switch (configuration.arrayType) {
|
|
149
|
-
case UINT_16_ARRAY:
|
|
150
|
-
pixelData = new Uint16Array(
|
|
151
|
-
buffer,
|
|
152
|
-
slicelengthInBytes * i, // 2 bytes/voxel
|
|
153
|
-
slicelengthInBytes / 2
|
|
154
|
-
);
|
|
155
|
-
break;
|
|
156
|
-
|
|
157
|
-
case FLOAT_32_ARRAY:
|
|
158
|
-
pixelData = new Float32Array(
|
|
159
|
-
buffer,
|
|
160
|
-
slicelengthInBytes * i,
|
|
161
|
-
slicelengthInBytes / 4
|
|
162
|
-
);
|
|
163
|
-
break;
|
|
164
|
-
|
|
165
|
-
default:
|
|
166
|
-
throw new Error(
|
|
167
|
-
"Unsupported Array Type ".concat(configuration.arrayType)
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
var segmentsOnLabelmap = segmentsOnLabelmapArray
|
|
172
|
-
? segmentsOnLabelmapArray[i]
|
|
173
|
-
: getSegmentsOnPixelData(pixelData);
|
|
174
|
-
|
|
175
|
-
if (
|
|
176
|
-
segmentsOnLabelmap &&
|
|
177
|
-
segmentsOnLabelmap.some(function (segment) {
|
|
178
|
-
return segment;
|
|
179
|
-
})
|
|
180
|
-
) {
|
|
181
|
-
labelmaps2D[i] = {
|
|
182
|
-
pixelData: pixelData,
|
|
183
|
-
segmentsOnLabelmap: segmentsOnLabelmap
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
++i;
|
|
188
|
-
|
|
189
|
-
if (i < numberOfFrames) {
|
|
190
|
-
setTimeout(() => {
|
|
191
|
-
setSingleSlice(i, numberOfFrames);
|
|
192
|
-
}, 0);
|
|
193
|
-
} else {
|
|
194
|
-
resolve("OK");
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
setSingleSlice(0, numberOfFrames);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
/* original implementation
|
|
202
|
-
|
|
203
|
-
for (let i = 0; i < numberOfFrames; i++) {
|
|
204
|
-
let pixelData;
|
|
205
|
-
|
|
206
|
-
switch (configuration.arrayType) {
|
|
207
|
-
case UINT_16_ARRAY:
|
|
208
|
-
pixelData = new Uint16Array(
|
|
209
|
-
buffer,
|
|
210
|
-
slicelengthInBytes * i, // 2 bytes/voxel
|
|
211
|
-
slicelengthInBytes / 2
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
break;
|
|
215
|
-
|
|
216
|
-
case FLOAT_32_ARRAY:
|
|
217
|
-
pixelData = new Float32Array(
|
|
218
|
-
buffer,
|
|
219
|
-
slicelengthInBytes * i,
|
|
220
|
-
slicelengthInBytes / 4
|
|
221
|
-
);
|
|
222
|
-
break;
|
|
223
|
-
|
|
224
|
-
default:
|
|
225
|
-
throw new Error(`Unsupported Array Type ${configuration.arrayType}`);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const segmentsOnLabelmap = segmentsOnLabelmapArray
|
|
229
|
-
? segmentsOnLabelmapArray[i]
|
|
230
|
-
: getSegmentsOnPixelData(pixelData);
|
|
231
|
-
|
|
232
|
-
if (segmentsOnLabelmap && segmentsOnLabelmap.some(segment => segment)) {
|
|
233
|
-
labelmaps2D[i] = {
|
|
234
|
-
pixelData,
|
|
235
|
-
segmentsOnLabelmap
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
*/
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export { setLabelmap3DByFirstImageId, setLabelmap3DForElement };
|