larvitar 1.2.2 → 1.2.5

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,11 +6,11 @@
6
6
 
7
7
  ## Dicom Image Toolkit for CornestoneJS
8
8
 
9
- ### Current version: 1.2.2
9
+ ### Current version: 1.2.5
10
10
 
11
- ### Latest Stable version: 1.2.2
11
+ ### Latest Stable version: 1.2.5
12
12
 
13
- ### Latest Published Release: 1.2.2
13
+ ### Latest Published Release: 1.2.5
14
14
 
15
15
  This library provides common DICOM functionalities to be used in web-applications: it's wrapper that simplifies the use of cornestone-js environment.
16
16
  Orthogonal multiplanar reformat is included as well as custom loader/exporter for nrrd files and [Vuex](https://vuex.vuejs.org/) custom integration.
@@ -278,6 +278,7 @@ let parseFile = function (file) {
278
278
  imageObject.metadata.frameTime = metadata["x00181063"];
279
279
  imageObject.metadata.frameDelay = metadata["x00181066"];
280
280
  }
281
+ imageObject.metadata.isMultiframe = isMultiframe;
281
282
  imageObject.metadata.windowCenter = metadata["x00281050"];
282
283
  imageObject.metadata.windowWidth = metadata["x00281051"];
283
284
  imageObject.metadata.minPixelValue = metadata["x00280106"];
@@ -253,7 +253,6 @@ export const resizeViewport = function (elementId) {
253
253
  */
254
254
  export const renderImage = function (seriesStack, elementId, defaultProps) {
255
255
  let t0 = performance.now();
256
-
257
256
  // get element and enable it
258
257
  let element = isElement(elementId)
259
258
  ? elementId
@@ -266,9 +265,6 @@ export const renderImage = function (seriesStack, elementId, defaultProps) {
266
265
 
267
266
  let series = { ...seriesStack };
268
267
 
269
- // default to 0 if multiframe and frameId is null
270
- // let frameId = series.isMultiframe ? 1 : null;
271
-
272
268
  larvitar_store.set("renderingStatus", [elementId, false]);
273
269
  let data = getSeriesData(series, defaultProps);
274
270
  if (!data.imageId) {
@@ -328,20 +324,7 @@ export const renderImage = function (seriesStack, elementId, defaultProps) {
328
324
  }
329
325
 
330
326
  let storedViewport = cornerstone.getViewport(element);
331
- storeViewportData(
332
- image,
333
- elementId,
334
- data.imageIndex,
335
- data.numberOfSlices,
336
- data.rows,
337
- data.cols,
338
- data.spacing_x,
339
- data.spacing_y,
340
- data.thickness,
341
- storedViewport,
342
- data.defaultWW,
343
- data.defaultWC
344
- );
327
+ storeViewportData(image, elementId, storedViewport, data);
345
328
  larvitar_store.set("renderingStatus", [elementId, true]);
346
329
  let t1 = performance.now();
347
330
  console.log(`Call to renderImage took ${t1 - t0} milliseconds.`);
@@ -385,17 +368,23 @@ export const updateImage = function (
385
368
  console.log("not element");
386
369
  return;
387
370
  }
388
- let index = imageIndex == 0 ? imageIndex : imageIndex - 1;
389
- if (cacheImage) {
390
- cornerstone
391
- .loadAndCacheImage(series.imageIds[index])
392
- .then(function (image) {
371
+ let imageId = series.imageIds[imageIndex];
372
+ if (imageId) {
373
+ if (cacheImage) {
374
+ cornerstone.loadAndCacheImage(imageId).then(function (image) {
393
375
  cornerstone.displayImage(element, image);
376
+ larvitar_store.set("sliceId", [elementId, imageIndex]);
394
377
  });
378
+ } else {
379
+ cornerstone.loadImage(imageId).then(function (image) {
380
+ cornerstone.displayImage(element, image);
381
+ larvitar_store.set("sliceId", [elementId, imageIndex]);
382
+ });
383
+ }
395
384
  } else {
396
- cornerstone.loadImage(series.imageIds[index]).then(function (image) {
397
- cornerstone.displayImage(element, image);
398
- });
385
+ console.warn(
386
+ `Error: wrong image index ${imageIndex}, no imageId available`
387
+ );
399
388
  }
400
389
  };
401
390
 
@@ -534,47 +523,27 @@ export const updateViewportData = function (
534
523
  * @function storeViewportData
535
524
  * @param {Object} image - The cornerstone image frame
536
525
  * @param {String} elementId - The html div id used for rendering
537
- * @param {Number} imageIndex - The index of the image
538
- * @param {Number} numberOfSlices - The number of slices of the series
539
- * @param {Number} rows - The number of rows of the image
540
- * @param {Number} cols - The number of columns of the image
541
- * @param {Number} spacing_x - The spacing value for x axis
542
- * @param {Number} spacing_y - The spacing value for y direction
543
- * @param {Number} thickness - The thickness value between slices
544
526
  * @param {String} viewport - The viewport tag name
545
- * @param {Number} defaultWW - The default WW value
546
- * @param {Number} defaultWC - The default WC value
527
+ * @param {Object} data - The viewport data object
547
528
  */
548
- export const storeViewportData = function (
549
- image,
550
- elementId,
551
- imageIndex,
552
- numberOfSlices,
553
- rows,
554
- cols,
555
- spacing_x,
556
- spacing_y,
557
- thickness,
558
- viewport,
559
- defaultWW,
560
- defaultWC
561
- ) {
562
- larvitar_store.set("dimensions", [elementId, rows, cols]);
563
- larvitar_store.set("spacing", [elementId, spacing_x, spacing_y]);
564
- larvitar_store.set("thickness", [elementId, thickness]);
529
+ export const storeViewportData = function (image, elementId, viewport, data) {
530
+ larvitar_store.set("dimensions", [elementId, data.rows, data.cols]);
531
+ larvitar_store.set("spacing", [elementId, data.spacing_x, data.spacing_y]);
532
+ larvitar_store.set("thickness", [elementId, data.thickness]);
565
533
  larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
566
534
  larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
567
- larvitar_store.set("minSliceId", [elementId, 1]);
568
- larvitar_store.set("sliceId", [elementId, imageIndex]);
569
- larvitar_store.set("maxSliceId", [elementId, numberOfSlices]);
535
+ // slice id from 0 to n - 1
536
+ larvitar_store.set("minSliceId", [elementId, 0]);
537
+ larvitar_store.set("sliceId", [elementId, data.imageIndex]);
538
+ larvitar_store.set("maxSliceId", [elementId, data.numberOfSlices - 1]);
570
539
  larvitar_store.set("defaultViewport", [
571
540
  elementId,
572
541
  viewport.scale,
573
542
  viewport.rotation,
574
543
  viewport.translation.x,
575
544
  viewport.translation.y,
576
- defaultWW,
577
- defaultWC
545
+ data.defaultWW,
546
+ data.defaultWC
578
547
  ]);
579
548
  larvitar_store.set("scale", [elementId, viewport.scale]);
580
549
  larvitar_store.set("rotation", [elementId, viewport.rotation]);
@@ -588,6 +557,9 @@ export const storeViewportData = function (
588
557
  viewport.voi.windowWidth,
589
558
  viewport.voi.windowCenter
590
559
  ]);
560
+ larvitar_store.set("isColor", [elementId, data.isColor]);
561
+ larvitar_store.set("isMultiframe", [elementId, data.isMultiframe]);
562
+ larvitar_store.set("isTimeserie", [elementId, data.isTimeserie]);
591
563
  };
592
564
 
593
565
  /**
@@ -697,12 +669,13 @@ export const rotateImageRight = function (elementId) {
697
669
  */
698
670
  let getSeriesData = function (series, defaultProps) {
699
671
  let data = {};
700
- // image index
701
672
  if (series.isMultiframe) {
673
+ data.isMultiframe = true;
702
674
  data.numberOfSlices = series.imageIds.length;
703
- data.imageIndex = 1;
704
- data.imageId = series.imageIds[0];
675
+ data.imageIndex = 0;
676
+ data.imageId = series.imageIds[data.imageIndex];
705
677
  } else {
678
+ data.isMultiframe = false;
706
679
  data.numberOfSlices =
707
680
  defaultProps && has(defaultProps, "numberOfSlices")
708
681
  ? defaultProps["numberOfSlices"]
@@ -711,15 +684,15 @@ let getSeriesData = function (series, defaultProps) {
711
684
  data.imageIndex =
712
685
  defaultProps &&
713
686
  has(defaultProps, "sliceNumber") &&
714
- defaultProps["sliceNumber"] <= data.numberOfSlices
687
+ defaultProps["sliceNumber"] >= 0 && // slice number between 0 and n-1
688
+ defaultProps["sliceNumber"] < data.numberOfSlices
715
689
  ? defaultProps["sliceNumber"]
716
690
  : Math.floor(data.numberOfSlices / 2);
717
691
 
718
- data.imageId =
719
- data.imageIndex > 0
720
- ? series.imageIds[data.imageIndex - 1]
721
- : series.imageIds[0];
692
+ data.imageId = series.imageIds[data.imageIndex];
722
693
  }
694
+ data.isColor = series.color;
695
+ data.isTimeserie = false; // TODO 4D
723
696
 
724
697
  // rows, cols and x y z spacing
725
698
  data.rows = series.instances[series.imageIds[0]].metadata["x00280010"];
@@ -22,6 +22,9 @@ const DEFAULT_VIEWPORT = {
22
22
  thickness: 0.0,
23
23
  minPixelValue: 0,
24
24
  maxPixelValue: 0,
25
+ isColor: false,
26
+ isMultiframe: false,
27
+ isTimeserie: false,
25
28
  viewport: {
26
29
  scale: 0.0,
27
30
  rotation: 0.0,
@@ -66,7 +69,6 @@ class Larvitar_Store {
66
69
  this.vuex_store = vuex_store;
67
70
  this.vuex_module = vuex_module;
68
71
  this.state = {
69
- manager: null,
70
72
  series: {}, // seriesUID: {imageIds:[], progress:value}
71
73
  leftActiveTool: "Wwwc",
72
74
  rightActiveTool: "Zoom",
@@ -230,6 +232,12 @@ class Larvitar_Store {
230
232
  this.state["viewports"][data[0]]["maxSliceId"] = data[1];
231
233
  } else if (field == "sliceId") {
232
234
  this.state["viewports"][data[0]]["sliceId"] = data[1];
235
+ } else if (field == "isColor") {
236
+ this.state["viewports"][data[0]]["isColor"] = data[1];
237
+ } else if (field == "isMultiframe") {
238
+ this.state["viewports"][data[0]]["isMultiframe"] = data[1];
239
+ } else if (field == "isTimeserie") {
240
+ this.state["viewports"][data[0]]["isTimeserie"] = data[1];
233
241
  } else if (field == "defaultViewport") {
234
242
  this.state["viewports"][data[0]]["default"]["scale"] = data[1];
235
243
  this.state["viewports"][data[0]]["default"]["rotation"] = data[2];
@@ -243,8 +251,6 @@ class Larvitar_Store {
243
251
  data[6];
244
252
  } else if (field == "progress") {
245
253
  this.state.series[data[0]]["progress"] = data[1];
246
- } else if (field == "manager") {
247
- this.state.manager = data;
248
254
  } else {
249
255
  if (Array.isArray(data)) {
250
256
  this.state[field][data[0]] = data[1];
@@ -38,10 +38,14 @@ export const updateLarvitarManager = function (imageObject, customId) {
38
38
  if (larvitarManager === null) {
39
39
  larvitarManager = {};
40
40
  }
41
+
41
42
  let seriesId = customId || imageObject.seriesUID;
42
43
  let data = { ...imageObject };
43
- if (data.isMultiframe) {
44
- buildMultiFrameImage(seriesId, data);
44
+
45
+ if (data.metadata.isMultiframe) {
46
+ seriesId = customId || imageObject.metadata.seriesUID;
47
+ updateLoadedStack(data, larvitarManager, customId);
48
+ buildMultiFrameImage(seriesId, larvitarManager[seriesId]);
45
49
  } else {
46
50
  updateLoadedStack(data, larvitarManager, customId);
47
51
  }
@@ -15,6 +15,9 @@ const DEFAULT_VIEWPORT = {
15
15
  thickness: 0.0,
16
16
  minPixelValue: 0,
17
17
  maxPixelValue: 0,
18
+ isColor: false,
19
+ isMultiframe: false,
20
+ isTimeserie: false,
18
21
  viewport: {
19
22
  scale: 0.0,
20
23
  rotation: 0.0,
@@ -46,7 +49,6 @@ export default {
46
49
  colormapId: "gray",
47
50
  leftActiveTool: "Wwwc",
48
51
  rightActiveTool: "Wwwc",
49
- manager: null,
50
52
  series: {}, // seriesUID: {imageIds:[], progress:value}
51
53
  viewports: {}
52
54
  },
@@ -90,7 +92,6 @@ export default {
90
92
  },
91
93
  deleteViewport: ({ state }, viewportId) =>
92
94
  Vue.delete(state.viewports, viewportId),
93
- setManager: ({ state }, value) => (state.manager = value),
94
95
  setLeftActiveTool: ({ commit }, value) => {
95
96
  commit("leftActiveTool", { d: { value } });
96
97
  },
@@ -127,6 +128,12 @@ export default {
127
128
  commit("viewport", { id, d: { maxSliceId } }),
128
129
  setSliceId: ({ commit }, [id, sliceId]) =>
129
130
  commit("viewport", { id, d: { sliceId } }),
131
+ setIsColor: ({ commit }, [id, isColor]) =>
132
+ commit("viewport", { id, d: { isColor } }),
133
+ setIsMultiframe: ({ commit }, [id, isMultiframe]) =>
134
+ commit("viewport", { id, d: { isMultiframe } }),
135
+ setIsTimeserie: ({ commit }, [id, isTimeserie]) =>
136
+ commit("viewport", { id, d: { isTimeserie } }),
130
137
  setDefaultViewport: (
131
138
  { commit },
132
139
  [id, scale, rotation, x, y, windowWidth, windowCenter]
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "medical",
7
7
  "cornerstone"
8
8
  ],
9
- "version": "1.2.2",
9
+ "version": "1.2.5",
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",
@@ -29,11 +29,11 @@
29
29
  "cornerstone-core": "^2.6.1",
30
30
  "cornerstone-file-image-loader": "^0.3.0",
31
31
  "cornerstone-tools": "^6.0.6",
32
- "cornerstone-wado-image-loader": "^4.0.1",
32
+ "cornerstone-wado-image-loader": "^4.1.2",
33
33
  "cornerstone-web-image-loader": "^2.1.1",
34
34
  "crypto-js": "^4.1.1",
35
35
  "dicom-character-set": "^1.0.3",
36
- "dicom-parser": "^1.8.11",
36
+ "dicom-parser": "^1.8.13",
37
37
  "docdash": "^1.2.0",
38
38
  "hammerjs": "^2.0.8",
39
39
  "keycode-js": "^3.1.0",