larvitar 2.0.4 → 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 (72) hide show
  1. package/README.md +2 -2
  2. package/dist/larvitar.js +5 -3
  3. package/dist/larvitar.js.map +1 -1
  4. package/package.json +6 -2
  5. package/.github/workflows/build-docs.yml +0 -59
  6. package/.github/workflows/codeql-analysis.yml +0 -71
  7. package/.github/workflows/deploy.yml +0 -37
  8. package/.vscode/settings.json +0 -4
  9. package/CODE_OF_CONDUCT.md +0 -76
  10. package/MIGRATION.md +0 -25
  11. package/bundler/webpack.common.js +0 -27
  12. package/bundler/webpack.dev.js +0 -23
  13. package/bundler/webpack.prod.js +0 -19
  14. package/decs.d.ts +0 -12
  15. package/imaging/MetaDataReadable.ts +0 -42
  16. package/imaging/MetaDataTypes.ts +0 -3491
  17. package/imaging/dataDictionary.json +0 -21866
  18. package/imaging/imageAnonymization.ts +0 -135
  19. package/imaging/imageColormaps.ts +0 -217
  20. package/imaging/imageContours.ts +0 -196
  21. package/imaging/imageIo.ts +0 -251
  22. package/imaging/imageLayers.ts +0 -121
  23. package/imaging/imageLoading.ts +0 -299
  24. package/imaging/imageParsing.ts +0 -444
  25. package/imaging/imagePresets.ts +0 -156
  26. package/imaging/imageRendering.ts +0 -1091
  27. package/imaging/imageReslice.ts +0 -87
  28. package/imaging/imageStore.ts +0 -487
  29. package/imaging/imageTags.ts +0 -609
  30. package/imaging/imageTools.js +0 -708
  31. package/imaging/imageUtils.ts +0 -1079
  32. package/imaging/loaders/commonLoader.ts +0 -275
  33. package/imaging/loaders/dicomLoader.ts +0 -66
  34. package/imaging/loaders/fileLoader.ts +0 -71
  35. package/imaging/loaders/multiframeLoader.ts +0 -435
  36. package/imaging/loaders/nrrdLoader.ts +0 -630
  37. package/imaging/loaders/resliceLoader.ts +0 -205
  38. package/imaging/monitors/memory.ts +0 -151
  39. package/imaging/monitors/performance.ts +0 -34
  40. package/imaging/parsers/ecg.ts +0 -54
  41. package/imaging/parsers/nrrd.js +0 -485
  42. package/imaging/tools/README.md +0 -27
  43. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  44. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  45. package/imaging/tools/custom/contourTool.js +0 -1884
  46. package/imaging/tools/custom/diameterTool.js +0 -141
  47. package/imaging/tools/custom/editMaskTool.js +0 -141
  48. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  49. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  50. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  51. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  52. package/imaging/tools/custom/seedTool.js +0 -342
  53. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  54. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  55. package/imaging/tools/default.ts +0 -594
  56. package/imaging/tools/interaction.ts +0 -266
  57. package/imaging/tools/io.ts +0 -229
  58. package/imaging/tools/main.ts +0 -424
  59. package/imaging/tools/segmentation.ts +0 -532
  60. package/imaging/tools/segmentations.md +0 -38
  61. package/imaging/tools/state.ts +0 -74
  62. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  63. package/imaging/tools/strategies/fillFreehand.js +0 -79
  64. package/imaging/tools/strategies/index.js +0 -2
  65. package/imaging/tools/types.d.ts +0 -243
  66. package/imaging/types.d.ts +0 -200
  67. package/imaging/waveforms/ecg.ts +0 -191
  68. package/index.ts +0 -431
  69. package/jsdoc.json +0 -52
  70. package/rollup.config.js +0 -51
  71. package/template/.gitkeep +0 -0
  72. 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
- };