larvitar 2.0.5 → 2.0.6

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 (71) hide show
  1. package/README.md +2 -2
  2. package/dist/larvitar.js +1 -1
  3. package/package.json +6 -2
  4. package/.github/workflows/build-docs.yml +0 -59
  5. package/.github/workflows/codeql-analysis.yml +0 -71
  6. package/.github/workflows/deploy.yml +0 -37
  7. package/.vscode/settings.json +0 -4
  8. package/CODE_OF_CONDUCT.md +0 -76
  9. package/MIGRATION.md +0 -25
  10. package/bundler/webpack.common.js +0 -27
  11. package/bundler/webpack.dev.js +0 -23
  12. package/bundler/webpack.prod.js +0 -19
  13. package/decs.d.ts +0 -12
  14. package/imaging/MetaDataReadable.ts +0 -42
  15. package/imaging/MetaDataTypes.ts +0 -3491
  16. package/imaging/dataDictionary.json +0 -21866
  17. package/imaging/imageAnonymization.ts +0 -135
  18. package/imaging/imageColormaps.ts +0 -217
  19. package/imaging/imageContours.ts +0 -196
  20. package/imaging/imageIo.ts +0 -251
  21. package/imaging/imageLayers.ts +0 -121
  22. package/imaging/imageLoading.ts +0 -299
  23. package/imaging/imageParsing.ts +0 -444
  24. package/imaging/imagePresets.ts +0 -156
  25. package/imaging/imageRendering.ts +0 -1091
  26. package/imaging/imageReslice.ts +0 -87
  27. package/imaging/imageStore.ts +0 -487
  28. package/imaging/imageTags.ts +0 -609
  29. package/imaging/imageTools.js +0 -708
  30. package/imaging/imageUtils.ts +0 -1079
  31. package/imaging/loaders/commonLoader.ts +0 -275
  32. package/imaging/loaders/dicomLoader.ts +0 -66
  33. package/imaging/loaders/fileLoader.ts +0 -71
  34. package/imaging/loaders/multiframeLoader.ts +0 -435
  35. package/imaging/loaders/nrrdLoader.ts +0 -630
  36. package/imaging/loaders/resliceLoader.ts +0 -205
  37. package/imaging/monitors/memory.ts +0 -151
  38. package/imaging/monitors/performance.ts +0 -34
  39. package/imaging/parsers/ecg.ts +0 -54
  40. package/imaging/parsers/nrrd.js +0 -485
  41. package/imaging/tools/README.md +0 -27
  42. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  43. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  44. package/imaging/tools/custom/contourTool.js +0 -1884
  45. package/imaging/tools/custom/diameterTool.js +0 -141
  46. package/imaging/tools/custom/editMaskTool.js +0 -141
  47. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  48. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  49. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  50. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  51. package/imaging/tools/custom/seedTool.js +0 -342
  52. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  53. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  54. package/imaging/tools/default.ts +0 -594
  55. package/imaging/tools/interaction.ts +0 -266
  56. package/imaging/tools/io.ts +0 -229
  57. package/imaging/tools/main.ts +0 -427
  58. package/imaging/tools/segmentation.ts +0 -532
  59. package/imaging/tools/segmentations.md +0 -38
  60. package/imaging/tools/state.ts +0 -74
  61. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  62. package/imaging/tools/strategies/fillFreehand.js +0 -79
  63. package/imaging/tools/strategies/index.js +0 -2
  64. package/imaging/tools/types.d.ts +0 -243
  65. package/imaging/types.d.ts +0 -200
  66. package/imaging/waveforms/ecg.ts +0 -191
  67. package/index.ts +0 -431
  68. package/jsdoc.json +0 -52
  69. package/rollup.config.js +0 -51
  70. package/template/.gitkeep +0 -0
  71. package/tsconfig.json +0 -102
@@ -1,87 +0,0 @@
1
- /** @module imaging/imageReslice
2
- * @desc This file provides functionalities for
3
- * image reslice in orthogonal directions
4
- */
5
-
6
- // external libraries
7
- import { v4 as uuidv4 } from "uuid";
8
- import { each } from "lodash";
9
-
10
- // internal libraries
11
- import { getReslicedMetadata, getReslicedPixeldata } from "./imageUtils";
12
- import {
13
- getLarvitarImageTracker,
14
- getLarvitarManager
15
- } from "./loaders/commonLoader";
16
- import store from "./imageStore";
17
- import { Series } from "./types";
18
-
19
- /*
20
- * This module provides the following functions to be exported:
21
- * resliceSeries(seriesId, seriesData, orientation)
22
- */
23
-
24
- /**
25
- * Reslice a serie from native orientation to coronal or sagittal orientation
26
- * @instance
27
- * @function resliceSeries
28
- * @param {Object} seriesData the original series data
29
- * @param {String} orientation the reslice orientation [coronal or sagittal]
30
- * @returns {Promise} - Return a promise which will resolve when data is available
31
- */
32
- export function resliceSeries(
33
- seriesData: Series,
34
- orientation: "axial" | "coronal" | "sagittal"
35
- ) {
36
- let reslicePromise = new Promise(resolve => {
37
- let reslicedSeries: Partial<Series> = {};
38
- let reslicedSeriesId = uuidv4();
39
- let reslicedMetaData = getReslicedMetadata(
40
- reslicedSeriesId,
41
- "axial",
42
- orientation,
43
- seriesData,
44
- "resliceLoader"
45
- );
46
-
47
- reslicedSeries.imageIds = reslicedMetaData.imageIds;
48
- // @ts-ignore fix incompatibilities between these types
49
- reslicedSeries.instances = reslicedMetaData.instances;
50
-
51
- reslicedSeries.currentImageIdIndex = Math.floor(
52
- reslicedSeries.imageIds.length / 2
53
- );
54
-
55
- function computeReslice(
56
- seriesData: Series,
57
- reslicedSeriesId: string,
58
- reslicedSeries: Series
59
- ) {
60
- let t0 = performance.now();
61
- let imageTracker = getLarvitarImageTracker();
62
- let manager = getLarvitarManager();
63
- each(reslicedSeries.imageIds, function (imageId: string) {
64
- reslicedSeries.instances[imageId].pixelData = getReslicedPixeldata(
65
- imageId,
66
- seriesData,
67
- reslicedSeries
68
- ) as Uint16Array;
69
- imageTracker[imageId] = reslicedSeriesId;
70
- });
71
- store.addSeriesId(reslicedSeriesId, reslicedSeries.imageIds);
72
- reslicedSeries.numberOfImages = reslicedSeries.imageIds.length;
73
- reslicedSeries.seriesUID = reslicedSeriesId;
74
- reslicedSeries.seriesDescription = seriesData.seriesDescription;
75
- reslicedSeries.orientation = orientation;
76
- manager[reslicedSeriesId] = reslicedSeries;
77
- //@ts-ignore deprecated
78
- manager[seriesData.seriesUID][orientation] = reslicedSeriesId;
79
- let t1 = performance.now();
80
- console.log(`Call to resliceSeries took ${t1 - t0} milliseconds.`);
81
- resolve(reslicedSeries);
82
- }
83
- // reslice the data
84
- computeReslice(seriesData, reslicedSeriesId, reslicedSeries as Series);
85
- });
86
- return reslicePromise;
87
- }
@@ -1,487 +0,0 @@
1
- /** @module imaging/imageStore
2
- * @desc This file provides functionalities
3
- * for data config store.
4
- */
5
-
6
- // external libraries
7
- import { get as _get, cloneDeep as _cloneDeep } from "lodash";
8
-
9
- type StoreSeries = { imageIds: string[]; progress: number };
10
-
11
- type Store = {
12
- colormapId: string;
13
- errorLog: string; // TODO review this, should be an array?
14
- leftActiveTool?: string;
15
- rightActiveTool?: string;
16
- series: { [seriesUID: string]: StoreSeries };
17
- viewports: { [key: string]: typeof DEFAULT_VIEWPORT };
18
- // fallback for any other field
19
- [key: string]: any;
20
- };
21
-
22
- type SetPayload =
23
- | ["errorLog" | "leftActiveTool" | "rightActiveTool", string]
24
- | [
25
- "isColor" | "isMultiframe" | "isPDF" | "isTimeserie" | "ready",
26
- string,
27
- boolean
28
- ]
29
- | [
30
- (
31
- | "progress"
32
- | "loading"
33
- | "minPixelValue"
34
- | "maxPixelValue"
35
- | "minSliceId"
36
- | "maxSliceId"
37
- | "minTimeId"
38
- | "maxTimeId"
39
- | "rotation"
40
- | "scale"
41
- | "sliceId"
42
- | "timeId"
43
- | "thickness"
44
- ),
45
- string,
46
- number
47
- ]
48
- | ["timestamp", string, number | undefined]
49
- | ["pendingSliceId", string, number | undefined]
50
- | ["timestamps" | "timeIds", string, number[]]
51
- | [
52
- "contrast" | "dimensions" | "spacing" | "translation",
53
- string,
54
- number,
55
- number
56
- ]
57
- | [
58
- "defaultViewport",
59
- string,
60
- number,
61
- number,
62
- number,
63
- number,
64
- number,
65
- number,
66
- boolean
67
- ];
68
-
69
- // Larvitar store object
70
- let STORE: Store;
71
-
72
- // Data listeners
73
- let storeListener: ((data: Store) => {}) | undefined = undefined;
74
- const seriesListeners = {} as {
75
- [seriesId: string]: (data: StoreSeries) => {};
76
- };
77
- const viewportsListeners = {} as {
78
- [elementId: string]: (data: typeof DEFAULT_VIEWPORT) => {};
79
- };
80
-
81
- // default initial store object
82
- const INITIAL_STORE_DATA: Store = {
83
- colormapId: "gray",
84
- errorLog: "",
85
- leftActiveTool: undefined,
86
- rightActiveTool: undefined,
87
- series: {},
88
- viewports: {}
89
- };
90
-
91
- // default viewport object
92
- export const DEFAULT_VIEWPORT: {
93
- loading: number;
94
- ready: boolean;
95
- minSliceId: number;
96
- maxSliceId: number;
97
- sliceId: number;
98
- pendingSliceId?: number;
99
- minTimeId: number;
100
- maxTimeId: number;
101
- timeId: number;
102
- timestamp: number;
103
- timestamps: number[];
104
- timeIds: number[];
105
- rows: number;
106
- cols: number;
107
- spacing_x: number;
108
- spacing_y: number;
109
- thickness: number;
110
- minPixelValue: number;
111
- maxPixelValue: number;
112
- isColor: boolean;
113
- isMultiframe: boolean;
114
- isTimeserie: boolean;
115
- isPDF: boolean;
116
- viewport: {
117
- scale: number;
118
- rotation: number;
119
- translation: {
120
- x: number;
121
- y: number;
122
- };
123
- voi: {
124
- windowCenter: number;
125
- windowWidth: number;
126
- };
127
- // redundant fields ?
128
- rows: number;
129
- cols: number;
130
- spacing_x: number;
131
- spacing_y: number;
132
- thickness: number;
133
- };
134
- default: {
135
- scale: number;
136
- rotation: number;
137
- translation: {
138
- x: number;
139
- y: number;
140
- };
141
- voi: {
142
- windowCenter: number;
143
- windowWidth: number;
144
- invert: boolean;
145
- };
146
- };
147
- } = {
148
- loading: 0, // from 0 to 100 (%)
149
- ready: false, // true when currentImageId is rendered
150
- minSliceId: 0,
151
- maxSliceId: 0,
152
- sliceId: 0,
153
- pendingSliceId: undefined,
154
- minTimeId: 0,
155
- maxTimeId: 0,
156
- timeId: 0,
157
- timestamp: 0,
158
- timestamps: [],
159
- timeIds: [],
160
- rows: 0,
161
- cols: 0,
162
- spacing_x: 0.0,
163
- spacing_y: 0.0,
164
- thickness: 0.0,
165
- minPixelValue: 0,
166
- maxPixelValue: 0,
167
- isColor: false,
168
- isMultiframe: false,
169
- isTimeserie: false,
170
- isPDF: false,
171
- viewport: {
172
- scale: 0.0,
173
- rotation: 0.0,
174
- translation: {
175
- x: 0.0,
176
- y: 0.0
177
- },
178
- voi: {
179
- windowCenter: 0.0,
180
- windowWidth: 0.0
181
- },
182
- // redundant fields ?
183
- rows: 0,
184
- cols: 0,
185
- spacing_x: 0.0,
186
- spacing_y: 0.0,
187
- thickness: 0.0
188
- },
189
- default: {
190
- scale: 0.0,
191
- rotation: 0.0,
192
- translation: {
193
- x: 0.0,
194
- y: 0.0
195
- },
196
- voi: {
197
- windowCenter: 0.0,
198
- windowWidth: 0.0,
199
- invert: false
200
- }
201
- }
202
- };
203
-
204
- export type Viewport = typeof DEFAULT_VIEWPORT;
205
-
206
- // Trigger store listeners
207
- const triggerStoreListener = (data: Store) =>
208
- storeListener ? storeListener(data) : undefined;
209
-
210
- const triggerViewportListener = (elementId: string) => {
211
- if (viewportsListeners[elementId] && STORE?.viewports[elementId]) {
212
- viewportsListeners[elementId](STORE.viewports[elementId]);
213
- }
214
- };
215
-
216
- const triggerSeriesListener = (seriesId: string) => {
217
- if (seriesListeners[seriesId] && STORE?.series[seriesId]) {
218
- seriesListeners[seriesId](STORE.series[seriesId]);
219
- }
220
- };
221
-
222
- /**
223
- * Set a value into store
224
- * @function setValue
225
- * @param {Object} data - The data object
226
- */
227
- const setValue = (store: Store, data: SetPayload) => {
228
- let field = data[0];
229
- const k = data[1];
230
- let [_1, _2, ...v] = data;
231
-
232
- const viewport = store.viewports[k];
233
-
234
- // assign values
235
- switch (field) {
236
- case "progress":
237
- if (!store.series[k]) {
238
- return;
239
- }
240
- store.series[k][field] = (v as [number])[0];
241
- triggerSeriesListener(k);
242
- break;
243
-
244
- case "isColor":
245
- case "isMultiframe":
246
- case "isPDF":
247
- case "isTimeserie":
248
- case "ready":
249
- if (!viewport) {
250
- return;
251
- }
252
- viewport[field] = (v as [boolean])[0];
253
- triggerViewportListener(k);
254
- break;
255
-
256
- case "loading":
257
- case "minPixelValue":
258
- case "maxPixelValue":
259
- case "minSliceId":
260
- case "maxSliceId":
261
- case "minTimeId":
262
- case "maxTimeId":
263
- case "sliceId":
264
- case "pendingSliceId":
265
- case "timeId":
266
- case "timestamp":
267
- if (!viewport) {
268
- return;
269
- }
270
- viewport[field] = (v as [number])[0];
271
- triggerViewportListener(k);
272
- break;
273
-
274
- case "timestamps":
275
- case "timeIds":
276
- if (!viewport) {
277
- return;
278
- }
279
- viewport[field] = (v as [[number]])[0];
280
- triggerViewportListener(k);
281
- break;
282
-
283
- case "rotation":
284
- case "scale":
285
- if (!viewport) {
286
- return;
287
- }
288
- viewport.viewport[field] = (v as [number])[0];
289
- triggerViewportListener(k);
290
- break;
291
-
292
- case "thickness":
293
- if (!viewport) {
294
- return;
295
- }
296
- viewport[field] = (v as [number])[0];
297
- viewport.viewport[field] = (v as [number])[0];
298
- triggerViewportListener(k);
299
- break;
300
-
301
- case "translation":
302
- if (!viewport) {
303
- return;
304
- }
305
- v = v as [number, number];
306
- viewport.viewport[field] = { x: v[0], y: v[1] };
307
- triggerViewportListener(k);
308
- break;
309
-
310
- case "contrast":
311
- if (!viewport) {
312
- return;
313
- }
314
- v = v as [number, number];
315
- viewport.viewport.voi.windowWidth = v[0];
316
- viewport.viewport.voi.windowCenter = v[1];
317
- triggerViewportListener(k);
318
- break;
319
-
320
- case "dimensions":
321
- if (!viewport) {
322
- return;
323
- }
324
- v = v as [number, number];
325
- viewport.rows = v[0];
326
- viewport.cols = v[1];
327
- viewport.viewport.rows = v[0];
328
- viewport.viewport.cols = v[1];
329
- triggerViewportListener(k);
330
- break;
331
-
332
- case "spacing":
333
- if (!viewport) {
334
- return;
335
- }
336
- v = v as [number, number];
337
- viewport.spacing_x = v[0];
338
- viewport.spacing_y = v[1];
339
- viewport.viewport.spacing_x = v[0];
340
- viewport.viewport.spacing_y = v[1];
341
- triggerViewportListener(k);
342
- break;
343
-
344
- case "defaultViewport":
345
- if (!viewport) {
346
- return;
347
- }
348
- v = v as [number, number, number, number, number, number, boolean];
349
- viewport.default.scale = v[0];
350
- viewport.default.rotation = v[1];
351
- viewport.default.translation.x = v[2];
352
- viewport.default.translation.y = v[3];
353
- viewport.default.voi.windowWidth = v[4];
354
- viewport.default.voi.windowCenter = v[5];
355
- viewport.default.voi.invert = v[6];
356
- triggerViewportListener(k);
357
- break;
358
-
359
- default:
360
- store[field] = k;
361
- break;
362
- }
363
- };
364
-
365
- /**
366
- * Instancing the store
367
- */
368
- const setup = (data = _cloneDeep(INITIAL_STORE_DATA)) => {
369
- /**
370
- * Create the Proxy handler object
371
- * @param {String} name The namespace
372
- * @param {Object} data The data object
373
- * @return {Object} The Proxy handler
374
- */
375
- const handler: ProxyHandler<Store> = {
376
- get: (obj, prop: string) => {
377
- if (prop === "_isProxy") return true;
378
- if (
379
- ["object", "array"].includes(
380
- Object.prototype.toString.call(obj[prop]).slice(8, -1).toLowerCase()
381
- ) &&
382
- !obj[prop]._isProxy
383
- ) {
384
- obj[prop] = new Proxy<Store>(obj[prop], handler);
385
- }
386
- return obj[prop];
387
- },
388
- set: (obj, prop: string, value) => {
389
- // console.warn("SET", obj, prop, value);
390
- if (obj[prop] === value) return true;
391
- obj[prop] = value;
392
- triggerStoreListener(data);
393
- return true;
394
- },
395
- deleteProperty: (obj, prop: string) => {
396
- delete obj[prop];
397
- triggerStoreListener(data);
398
- return true;
399
- }
400
- };
401
-
402
- return new Proxy<Store>(data, handler);
403
- };
404
-
405
- const initializeStore = () => {
406
- STORE = setup();
407
- };
408
-
409
- const validateStore = () => {
410
- if (!STORE) {
411
- throw "Larvitar store does not exists. Initialize it with the 'initializeStore' function.";
412
- }
413
- };
414
-
415
- export const set = (payload: SetPayload) => {
416
- validateStore();
417
- setValue(STORE!, payload);
418
- };
419
-
420
- export default {
421
- initialize: initializeStore,
422
- // add/remove viewports
423
- addViewport: (name: string) => {
424
- validateStore();
425
- STORE!.viewports[name] = _cloneDeep(DEFAULT_VIEWPORT);
426
- },
427
- deleteViewport: (name: string) => {
428
- validateStore();
429
- delete STORE!.viewports[name];
430
- },
431
- // add/remove series instances ids
432
- addSeriesId: (seriesId: string, imageIds: string[]) => {
433
- validateStore();
434
- if (!STORE!.series[seriesId]) {
435
- STORE!.series[seriesId] = {} as StoreSeries;
436
- }
437
- STORE!.series[seriesId].imageIds = imageIds;
438
- triggerSeriesListener(seriesId);
439
- },
440
- removeSeriesId: (seriesId: string) => {
441
- validateStore();
442
- delete STORE!.series[seriesId];
443
- },
444
- resetSeriesIds: () => {
445
- validateStore();
446
- STORE!.series = {};
447
- },
448
- // expose useful sets
449
- setSliceId: (elementId: string, imageIndex: number) => {
450
- set(["sliceId", elementId, imageIndex]);
451
- },
452
- setPendingSliceId: (elementId: string, imageIndex: number) => {
453
- set(["pendingSliceId", elementId, imageIndex]);
454
- },
455
- setMaxSliceId: (elementId: string, imageIndex: number) => {
456
- set(["maxSliceId", elementId, imageIndex]);
457
- },
458
- // get
459
- get: (props: string | string[]) => {
460
- validateStore();
461
- return _get(STORE, props);
462
- },
463
- // watch store
464
- addStoreListener: (listener: (data: Store) => {}) =>
465
- (storeListener = listener),
466
- removeStoreListener: () => (storeListener = undefined),
467
- // watch single viewport
468
- addViewportListener: (
469
- elementId: string,
470
- listener: (data: typeof DEFAULT_VIEWPORT) => {}
471
- ) => {
472
- viewportsListeners[elementId] = listener;
473
- },
474
- removeViewportListener: (elementId: string) => {
475
- delete viewportsListeners[elementId];
476
- },
477
- // watch single series
478
- addSeriesListener: (
479
- seriesId: string,
480
- listener: (data: StoreSeries) => {}
481
- ) => {
482
- seriesListeners[seriesId] = listener;
483
- },
484
- removeSeriesListener: (seriesId: string) => {
485
- delete seriesListeners[seriesId];
486
- }
487
- };