larvitar 1.2.10 → 1.3.1
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 +3 -3
- package/imaging/imageLoading.js +15 -3
- package/imaging/imageParsing.js +31 -4
- package/imaging/imageRendering.js +69 -1
- package/imaging/imageStore.js +18 -0
- package/imaging/imageUtils.js +3 -10
- package/imaging/loaders/nrrdLoader.js +28 -26
- package/imaging/tools/interaction.js +1 -0
- package/modules/vuex/larvitar.js +18 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
## Dicom Image Toolkit for CornestoneJS
|
|
8
8
|
|
|
9
|
-
### Current version: 1.
|
|
9
|
+
### Current version: 1.3.1
|
|
10
10
|
|
|
11
|
-
### Latest Stable version: 1.
|
|
11
|
+
### Latest Stable version: 1.3.1
|
|
12
12
|
|
|
13
|
-
### Latest Published Release: 1.
|
|
13
|
+
### Latest Published Release: 1.3.1
|
|
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.
|
package/imaging/imageLoading.js
CHANGED
|
@@ -145,6 +145,10 @@ export const updateLoadedStack = function (
|
|
|
145
145
|
let numberOfFrames = seriesData.metadata["x00280008"];
|
|
146
146
|
let modality = seriesData.metadata["x00080060"];
|
|
147
147
|
let isMultiframe = numberOfFrames > 1 ? true : false;
|
|
148
|
+
let numberOfTemporalPositions = seriesData.metadata["x00200105"];
|
|
149
|
+
let acquisitionNumberAttribute = seriesData.metadata["x00200012"];
|
|
150
|
+
let is4D = seriesData.metadata.is4D;
|
|
151
|
+
|
|
148
152
|
let color = cornerstoneWADOImageLoader.isColorImage(
|
|
149
153
|
seriesData.metadata["x00280004"]
|
|
150
154
|
);
|
|
@@ -160,16 +164,22 @@ export const updateLoadedStack = function (
|
|
|
160
164
|
larvitarSeriesInstanceUID: sid,
|
|
161
165
|
seriesUID: sid,
|
|
162
166
|
studyUID: ssid,
|
|
163
|
-
numberOfImages: 0,
|
|
167
|
+
numberOfImages: is4D ? acquisitionNumberAttribute : 0,
|
|
164
168
|
numberOfSlices: numberOfSlices,
|
|
165
169
|
numberOfFrames: numberOfFrames,
|
|
170
|
+
numberOfTemporalPositions: numberOfTemporalPositions,
|
|
166
171
|
isMultiframe: isMultiframe,
|
|
172
|
+
is4D: is4D,
|
|
167
173
|
modality: modality,
|
|
168
174
|
color: color,
|
|
169
175
|
bytes: 0
|
|
170
176
|
};
|
|
171
177
|
}
|
|
172
178
|
|
|
179
|
+
const sortMethods = is4D
|
|
180
|
+
? ["imagePosition", "contentTime"]
|
|
181
|
+
: ["imagePosition"];
|
|
182
|
+
|
|
173
183
|
// if the parsed file is a new series instance, keep it
|
|
174
184
|
if (isNewInstance(allSeriesStack[id].instances, iid)) {
|
|
175
185
|
// generate an imageId for the file and store it
|
|
@@ -180,7 +190,9 @@ export const updateLoadedStack = function (
|
|
|
180
190
|
);
|
|
181
191
|
|
|
182
192
|
allSeriesStack[id].imageIds.push(imageId);
|
|
183
|
-
|
|
193
|
+
if (is4D === false) {
|
|
194
|
+
allSeriesStack[id].numberOfImages += 1;
|
|
195
|
+
}
|
|
184
196
|
allSeriesStack[id].bytes += seriesData.file.size;
|
|
185
197
|
// store needed instance tags
|
|
186
198
|
allSeriesStack[id].instances[imageId] = {
|
|
@@ -191,7 +203,7 @@ export const updateLoadedStack = function (
|
|
|
191
203
|
// order images in stack
|
|
192
204
|
allSeriesStack[id].imageIds = getSortedStack(
|
|
193
205
|
allSeriesStack[id],
|
|
194
|
-
|
|
206
|
+
sortMethods,
|
|
195
207
|
true
|
|
196
208
|
);
|
|
197
209
|
// populate the ordered dictionary of instanceUIDs
|
package/imaging/imageParsing.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// external libraries
|
|
6
6
|
import { parseDicom } from "dicom-parser";
|
|
7
7
|
import { forEach, each, has, pick } from "lodash";
|
|
8
|
+
import { v4 as uuidv4 } from "uuid";
|
|
8
9
|
|
|
9
10
|
// internal libraries
|
|
10
11
|
import { getPixelRepresentation, randomId, parseTag } from "./imageUtils.js";
|
|
@@ -126,10 +127,17 @@ export const parseDataSet = function (dataSet, metadata, customFilter) {
|
|
|
126
127
|
* @function parseNextFile
|
|
127
128
|
* @param {Array} parsingQueue - Array of queued files to be parsed
|
|
128
129
|
* @param {Object} allSeriesStack - Series stack object to be populated
|
|
130
|
+
* @param {string} uuid - Series uuid to be used if series instance uuid is missing
|
|
129
131
|
* @param {Function} resolve - Promise resolve function
|
|
130
132
|
* @param {Function} reject - Promise reject function
|
|
131
133
|
*/
|
|
132
|
-
let parseNextFile = function (
|
|
134
|
+
let parseNextFile = function (
|
|
135
|
+
parsingQueue,
|
|
136
|
+
allSeriesStack,
|
|
137
|
+
uuid,
|
|
138
|
+
resolve,
|
|
139
|
+
reject
|
|
140
|
+
) {
|
|
133
141
|
// initialize t0 on first file of the queue
|
|
134
142
|
if (
|
|
135
143
|
Object.keys(allSeriesStack).length === 0 &&
|
|
@@ -161,16 +169,18 @@ let parseNextFile = function (parsingQueue, allSeriesStack, resolve, reject) {
|
|
|
161
169
|
// parse the file and wait for results
|
|
162
170
|
parseFile(file)
|
|
163
171
|
.then(seriesData => {
|
|
172
|
+
// use generated series uid if not found in dicom file
|
|
173
|
+
seriesData.metadata.seriesUID = seriesData.metadata.seriesUID || uuid;
|
|
164
174
|
// add file to cornerstoneWADOImageLoader file manager
|
|
165
175
|
updateLoadedStack(seriesData, allSeriesStack);
|
|
166
176
|
// proceed with the next file to parse
|
|
167
|
-
parseNextFile(parsingQueue, allSeriesStack, resolve, reject);
|
|
177
|
+
parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
|
|
168
178
|
seriesData = null;
|
|
169
179
|
file = null;
|
|
170
180
|
})
|
|
171
181
|
.catch(err => {
|
|
172
182
|
console.warn(err);
|
|
173
|
-
parseNextFile(parsingQueue, allSeriesStack, resolve, reject);
|
|
183
|
+
parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
|
|
174
184
|
file = null;
|
|
175
185
|
});
|
|
176
186
|
}
|
|
@@ -193,7 +203,8 @@ let parseFiles = function (fileList) {
|
|
|
193
203
|
}
|
|
194
204
|
});
|
|
195
205
|
return new Promise((resolve, reject) => {
|
|
196
|
-
|
|
206
|
+
const uuid = uuidv4();
|
|
207
|
+
parseNextFile(parsingQueue, allSeriesStack, uuid, resolve, reject);
|
|
197
208
|
});
|
|
198
209
|
};
|
|
199
210
|
|
|
@@ -220,6 +231,14 @@ let parseFile = function (file) {
|
|
|
220
231
|
let metadata = {};
|
|
221
232
|
parseDataSet(dataSet, metadata);
|
|
222
233
|
|
|
234
|
+
let temporalPositionIdentifier = metadata["x00200100"]; // Temporal order of a dynamic or functional set of Images.
|
|
235
|
+
let numberOfTemporalPositions = metadata["x00200105"]; // Total number of temporal positions prescribed.
|
|
236
|
+
const is4D =
|
|
237
|
+
(temporalPositionIdentifier !== undefined) &
|
|
238
|
+
(numberOfTemporalPositions > 1)
|
|
239
|
+
? true
|
|
240
|
+
: false;
|
|
241
|
+
|
|
223
242
|
let numberOfFrames = metadata["x00280008"];
|
|
224
243
|
let isMultiframe = numberOfFrames > 1 ? true : false;
|
|
225
244
|
// Overwrite SOPInstanceUID to manage multiframes.
|
|
@@ -279,6 +298,14 @@ let parseFile = function (file) {
|
|
|
279
298
|
imageObject.metadata.frameDelay = metadata["x00181066"];
|
|
280
299
|
}
|
|
281
300
|
imageObject.metadata.isMultiframe = isMultiframe;
|
|
301
|
+
if (is4D) {
|
|
302
|
+
imageObject.metadata.temporalPositionIdentifier =
|
|
303
|
+
metadata["x00200100"];
|
|
304
|
+
imageObject.metadata.numberOfTemporalPositions =
|
|
305
|
+
metadata["x00200105"];
|
|
306
|
+
imageObject.metadata.contentTime = metadata["x00080033"];
|
|
307
|
+
}
|
|
308
|
+
imageObject.metadata.is4D = is4D;
|
|
282
309
|
imageObject.metadata.windowCenter = metadata["x00281050"];
|
|
283
310
|
imageObject.metadata.windowWidth = metadata["x00281051"];
|
|
284
311
|
imageObject.metadata.minPixelValue = metadata["x00280106"];
|
|
@@ -369,16 +369,29 @@ export const updateImage = function (
|
|
|
369
369
|
return;
|
|
370
370
|
}
|
|
371
371
|
let imageId = series.imageIds[imageIndex];
|
|
372
|
+
|
|
372
373
|
if (imageId) {
|
|
374
|
+
if (series.is4D) {
|
|
375
|
+
const timestamp = series.instances[imageId].metadata.contentTime;
|
|
376
|
+
const timeId =
|
|
377
|
+
series.instances[imageId].metadata.temporalPositionIdentifier - 1; // timeId from 0 to N
|
|
378
|
+
larvitar_store.set("timeId", [elementId, timeId]);
|
|
379
|
+
larvitar_store.set("timestamp", [elementId, timestamp]);
|
|
380
|
+
}
|
|
381
|
+
|
|
373
382
|
if (cacheImage) {
|
|
374
383
|
cornerstone.loadAndCacheImage(imageId).then(function (image) {
|
|
375
384
|
cornerstone.displayImage(element, image);
|
|
376
385
|
larvitar_store.set("sliceId", [elementId, imageIndex]);
|
|
386
|
+
larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
|
|
387
|
+
larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
|
|
377
388
|
});
|
|
378
389
|
} else {
|
|
379
390
|
cornerstone.loadImage(imageId).then(function (image) {
|
|
380
391
|
cornerstone.displayImage(element, image);
|
|
381
392
|
larvitar_store.set("sliceId", [elementId, imageIndex]);
|
|
393
|
+
larvitar_store.set("minPixelValue", [elementId, image.minPixelValue]);
|
|
394
|
+
larvitar_store.set("maxPixelValue", [elementId, image.maxPixelValue]);
|
|
382
395
|
});
|
|
383
396
|
}
|
|
384
397
|
} else {
|
|
@@ -512,6 +525,26 @@ export const updateViewportData = function (
|
|
|
512
525
|
case "Rotate":
|
|
513
526
|
larvitar_store.set("rotation", [elementId, viewportData.rotation]);
|
|
514
527
|
break;
|
|
528
|
+
case "mouseWheel":
|
|
529
|
+
const isTimeserie = larvitar_store.get(
|
|
530
|
+
"viewports",
|
|
531
|
+
elementId,
|
|
532
|
+
"isTimeserie"
|
|
533
|
+
);
|
|
534
|
+
if (isTimeserie) {
|
|
535
|
+
const index = viewportData.newImageIdIndex;
|
|
536
|
+
const timeId = larvitar_store.get("viewports", elementId, "timeIds")[
|
|
537
|
+
index
|
|
538
|
+
];
|
|
539
|
+
const timestamp = larvitar_store.get(
|
|
540
|
+
"viewports",
|
|
541
|
+
elementId,
|
|
542
|
+
"timestamps"
|
|
543
|
+
)[index];
|
|
544
|
+
larvitar_store.set("timeId", [elementId, timeId]);
|
|
545
|
+
larvitar_store.set("timestamp", [elementId, timestamp]);
|
|
546
|
+
}
|
|
547
|
+
break;
|
|
515
548
|
default:
|
|
516
549
|
break;
|
|
517
550
|
}
|
|
@@ -536,6 +569,23 @@ export const storeViewportData = function (image, elementId, viewport, data) {
|
|
|
536
569
|
larvitar_store.set("minSliceId", [elementId, 0]);
|
|
537
570
|
larvitar_store.set("sliceId", [elementId, data.imageIndex]);
|
|
538
571
|
larvitar_store.set("maxSliceId", [elementId, data.numberOfSlices - 1]);
|
|
572
|
+
|
|
573
|
+
if (data.isTimeserie) {
|
|
574
|
+
larvitar_store.set("minTimeId", [elementId, 0]);
|
|
575
|
+
larvitar_store.set("timeId", [elementId, data.timeIndex]);
|
|
576
|
+
larvitar_store.set("maxTimeId", [
|
|
577
|
+
elementId,
|
|
578
|
+
data.numberOfTemporalPositions - 1
|
|
579
|
+
]);
|
|
580
|
+
larvitar_store.set("maxSliceId", [
|
|
581
|
+
elementId,
|
|
582
|
+
data.numberOfSlices * data.numberOfTemporalPositions - 1
|
|
583
|
+
]);
|
|
584
|
+
larvitar_store.set("timestamp", [elementId, data.timestamp]);
|
|
585
|
+
larvitar_store.set("timestamps", [elementId, data.timestamps]);
|
|
586
|
+
larvitar_store.set("timeIds", [elementId, data.timeIds]);
|
|
587
|
+
}
|
|
588
|
+
|
|
539
589
|
larvitar_store.set("defaultViewport", [
|
|
540
590
|
elementId,
|
|
541
591
|
viewport.scale,
|
|
@@ -674,6 +724,25 @@ let getSeriesData = function (series, defaultProps) {
|
|
|
674
724
|
data.numberOfSlices = series.imageIds.length;
|
|
675
725
|
data.imageIndex = 0;
|
|
676
726
|
data.imageId = series.imageIds[data.imageIndex];
|
|
727
|
+
} else if (series.is4D) {
|
|
728
|
+
data.isMultiframe = false;
|
|
729
|
+
data.isTimeserie = true;
|
|
730
|
+
// check with real indices
|
|
731
|
+
data.numberOfSlices =
|
|
732
|
+
series.imageIds.length / series.numberOfTemporalPositions;
|
|
733
|
+
data.numberOfTemporalPositions = series.numberOfTemporalPositions;
|
|
734
|
+
data.imageIndex = 0;
|
|
735
|
+
data.timeIndex = 0;
|
|
736
|
+
data.timestamp = series.instances[series.imageIds[0]].metadata["x00080033"];
|
|
737
|
+
data.imageId = series.imageIds[data.imageIndex];
|
|
738
|
+
data.timestamps = [];
|
|
739
|
+
data.timeIds = [];
|
|
740
|
+
each(series.imageIds, function (imageId) {
|
|
741
|
+
data.timestamps.push(series.instances[imageId].metadata.contentTime);
|
|
742
|
+
data.timeIds.push(
|
|
743
|
+
series.instances[imageId].metadata.temporalPositionIdentifier - 1 // timeId from 0 to N
|
|
744
|
+
);
|
|
745
|
+
});
|
|
677
746
|
} else {
|
|
678
747
|
data.isMultiframe = false;
|
|
679
748
|
data.numberOfSlices =
|
|
@@ -692,7 +761,6 @@ let getSeriesData = function (series, defaultProps) {
|
|
|
692
761
|
data.imageId = series.imageIds[data.imageIndex];
|
|
693
762
|
}
|
|
694
763
|
data.isColor = series.color;
|
|
695
|
-
data.isTimeserie = false; // TODO 4D
|
|
696
764
|
|
|
697
765
|
// rows, cols and x y z spacing
|
|
698
766
|
data.rows = series.instances[series.imageIds[0]].metadata["x00280010"];
|
package/imaging/imageStore.js
CHANGED
|
@@ -15,6 +15,12 @@ const DEFAULT_VIEWPORT = {
|
|
|
15
15
|
minSliceId: 0,
|
|
16
16
|
maxSliceId: 0,
|
|
17
17
|
sliceId: 0,
|
|
18
|
+
minTimeId: 0,
|
|
19
|
+
maxTimeId: 0,
|
|
20
|
+
timeId: 0,
|
|
21
|
+
timestamp: 0,
|
|
22
|
+
timestamps: [],
|
|
23
|
+
timeIds: [],
|
|
18
24
|
rows: 0,
|
|
19
25
|
cols: 0,
|
|
20
26
|
spacing_x: 0.0,
|
|
@@ -232,6 +238,18 @@ class Larvitar_Store {
|
|
|
232
238
|
this.state["viewports"][data[0]]["maxSliceId"] = data[1];
|
|
233
239
|
} else if (field == "sliceId") {
|
|
234
240
|
this.state["viewports"][data[0]]["sliceId"] = data[1];
|
|
241
|
+
} else if (field == "minTimeId") {
|
|
242
|
+
this.state["viewports"][data[0]]["minTimeId"] = data[1];
|
|
243
|
+
} else if (field == "maxTimeId") {
|
|
244
|
+
this.state["viewports"][data[0]]["maxTimeId"] = data[1];
|
|
245
|
+
} else if (field == "timeId") {
|
|
246
|
+
this.state["viewports"][data[0]]["timeId"] = data[1];
|
|
247
|
+
} else if (field == "timestamp") {
|
|
248
|
+
this.state["viewports"][data[0]]["timestamp"] = data[1];
|
|
249
|
+
} else if (field == "timestamps") {
|
|
250
|
+
this.state["viewports"][data[0]]["timestamps"] = data[1];
|
|
251
|
+
} else if (field == "timeIds") {
|
|
252
|
+
this.state["viewports"][data[0]]["timeIds"] = data[1];
|
|
235
253
|
} else if (field == "isColor") {
|
|
236
254
|
this.state["viewports"][data[0]]["isColor"] = data[1];
|
|
237
255
|
} else if (field == "isMultiframe") {
|
package/imaging/imageUtils.js
CHANGED
|
@@ -205,8 +205,8 @@ export const getPixelTypedArray = function (dataSet, pixelDataElement) {
|
|
|
205
205
|
* @instance
|
|
206
206
|
* @function getSortedStack
|
|
207
207
|
* @param {Object} seriesData - The dataset
|
|
208
|
-
* @param {Array} sortPriorities -
|
|
209
|
-
* @param {Bool} returnSuccessMethod -
|
|
208
|
+
* @param {Array} sortPriorities - An array which represents the priority tasks
|
|
209
|
+
* @param {Bool} returnSuccessMethod - Boolean for returning the success method
|
|
210
210
|
* @return {Object} The sorted stack
|
|
211
211
|
*/
|
|
212
212
|
export const getSortedStack = function (
|
|
@@ -868,14 +868,7 @@ let sortStackCallback = function (seriesData, imageId, method) {
|
|
|
868
868
|
return instanceNumber;
|
|
869
869
|
|
|
870
870
|
case "contentTime":
|
|
871
|
-
|
|
872
|
-
seriesData.instances[imageId].metadata.x00181090;
|
|
873
|
-
var contentTime = seriesData.instances[imageId].metadata.x00080033;
|
|
874
|
-
if (cardiacNumberOfImages && cardiacNumberOfImages > 1 && contentTime) {
|
|
875
|
-
return contentTime;
|
|
876
|
-
} else {
|
|
877
|
-
throw "Not a time series: cardiacNumberOfImages tag not available or <= 1.";
|
|
878
|
-
}
|
|
871
|
+
return seriesData.instances[imageId].metadata.x00080033;
|
|
879
872
|
|
|
880
873
|
case "imagePosition":
|
|
881
874
|
var p = seriesData.instances[imageId].metadata.imagePosition;
|
|
@@ -62,33 +62,35 @@ export const buildNrrdImage = function (volume, seriesId, custom_header) {
|
|
|
62
62
|
// need to extract header from nrrd file format
|
|
63
63
|
// sizes, spaceDirections and spaceOrigin
|
|
64
64
|
|
|
65
|
+
const index = volume.header.kinds[0] == "domain" ? 0 : 1;
|
|
66
|
+
|
|
65
67
|
let spacing_x = Math.sqrt(
|
|
66
|
-
volume.header["space directions"][0][0] *
|
|
67
|
-
volume.header["space directions"][0][0] +
|
|
68
|
-
volume.header["space directions"][0][1] *
|
|
69
|
-
volume.header["space directions"][0][1] +
|
|
70
|
-
volume.header["space directions"][0][2] *
|
|
71
|
-
volume.header["space directions"][0][2]
|
|
68
|
+
volume.header["space directions"][index + 0][0] *
|
|
69
|
+
volume.header["space directions"][index + 0][0] +
|
|
70
|
+
volume.header["space directions"][index + 0][1] *
|
|
71
|
+
volume.header["space directions"][index + 0][1] +
|
|
72
|
+
volume.header["space directions"][index + 0][2] *
|
|
73
|
+
volume.header["space directions"][index + 0][2]
|
|
72
74
|
);
|
|
73
75
|
let spacing_y = Math.sqrt(
|
|
74
|
-
volume.header["space directions"][1][0] *
|
|
75
|
-
volume.header["space directions"][1][0] +
|
|
76
|
-
volume.header["space directions"][1][1] *
|
|
77
|
-
volume.header["space directions"][1][1] +
|
|
78
|
-
volume.header["space directions"][1][2] *
|
|
79
|
-
volume.header["space directions"][1][2]
|
|
76
|
+
volume.header["space directions"][index + 1][0] *
|
|
77
|
+
volume.header["space directions"][index + 1][0] +
|
|
78
|
+
volume.header["space directions"][index + 1][1] *
|
|
79
|
+
volume.header["space directions"][index + 1][1] +
|
|
80
|
+
volume.header["space directions"][index + 1][2] *
|
|
81
|
+
volume.header["space directions"][index + 1][2]
|
|
80
82
|
);
|
|
81
83
|
let spacing_z = Math.sqrt(
|
|
82
|
-
volume.header["space directions"][2][0] *
|
|
83
|
-
volume.header["space directions"][2][0] +
|
|
84
|
-
volume.header["space directions"][2][1] *
|
|
85
|
-
volume.header["space directions"][2][1] +
|
|
86
|
-
volume.header["space directions"][2][2] *
|
|
87
|
-
volume.header["space directions"][2][2]
|
|
84
|
+
volume.header["space directions"][index + 2][0] *
|
|
85
|
+
volume.header["space directions"][index + 2][0] +
|
|
86
|
+
volume.header["space directions"][index + 2][1] *
|
|
87
|
+
volume.header["space directions"][index + 2][1] +
|
|
88
|
+
volume.header["space directions"][index + 2][2] *
|
|
89
|
+
volume.header["space directions"][index + 2][2]
|
|
88
90
|
);
|
|
89
|
-
header.volume.rows = volume.header.sizes[1];
|
|
90
|
-
header.volume.cols = volume.header.sizes[0];
|
|
91
|
-
header.volume.numberOfSlices = volume.header.sizes[2];
|
|
91
|
+
header.volume.rows = volume.header.sizes[index + 1];
|
|
92
|
+
header.volume.cols = volume.header.sizes[index + 0];
|
|
93
|
+
header.volume.numberOfSlices = volume.header.sizes[index + 2];
|
|
92
94
|
header.volume.imagePosition = volume.header["space origin"];
|
|
93
95
|
header.volume.pixelSpacing = [spacing_x, spacing_y];
|
|
94
96
|
header.volume.sliceThickness = spacing_z;
|
|
@@ -107,11 +109,11 @@ export const buildNrrdImage = function (volume, seriesId, custom_header) {
|
|
|
107
109
|
? custom_header.acquisition_date
|
|
108
110
|
: "";
|
|
109
111
|
|
|
110
|
-
let rows = volume.header.sizes[1];
|
|
111
|
-
let cols = volume.header.sizes[0];
|
|
112
|
-
let frames = volume.header.sizes[2];
|
|
113
|
-
let iop = volume.header["space directions"][0].concat(
|
|
114
|
-
volume.header["space directions"][1]
|
|
112
|
+
let rows = volume.header.sizes[index + 1];
|
|
113
|
+
let cols = volume.header.sizes[index + 0];
|
|
114
|
+
let frames = volume.header.sizes[index + 2];
|
|
115
|
+
let iop = volume.header["space directions"][index + 0].concat(
|
|
116
|
+
volume.header["space directions"][index + 1]
|
|
115
117
|
);
|
|
116
118
|
let firstIpp = header.volume.imagePosition;
|
|
117
119
|
let w = getNormalOrientation(iop);
|
|
@@ -158,6 +158,7 @@ export const toggleMouseToolsListeners = function (elementId, disable) {
|
|
|
158
158
|
// mouse wheel handler
|
|
159
159
|
function mouseWheelHandler(evt) {
|
|
160
160
|
larvitar_store.set("sliceId", [evt.target.id, evt.detail.newImageIdIndex]);
|
|
161
|
+
updateViewportData(evt.srcElement.id, evt.detail, "mouseWheel");
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
if (disable) {
|
package/modules/vuex/larvitar.js
CHANGED
|
@@ -8,6 +8,12 @@ const DEFAULT_VIEWPORT = {
|
|
|
8
8
|
minSliceId: 0,
|
|
9
9
|
maxSliceId: 0,
|
|
10
10
|
sliceId: 0,
|
|
11
|
+
minTimeId: 0,
|
|
12
|
+
maxTimeId: 0,
|
|
13
|
+
timeId: 0,
|
|
14
|
+
timestamp: 0,
|
|
15
|
+
timestamps: [],
|
|
16
|
+
timeIds: [],
|
|
11
17
|
rows: 0,
|
|
12
18
|
cols: 0,
|
|
13
19
|
spacing_x: 0.0,
|
|
@@ -128,6 +134,18 @@ export default {
|
|
|
128
134
|
commit("viewport", { id, d: { maxSliceId } }),
|
|
129
135
|
setSliceId: ({ commit }, [id, sliceId]) =>
|
|
130
136
|
commit("viewport", { id, d: { sliceId } }),
|
|
137
|
+
setMinTimeId: ({ commit }, [id, minTimeId]) =>
|
|
138
|
+
commit("viewport", { id, d: { minTimeId } }),
|
|
139
|
+
setMaxTimeId: ({ commit }, [id, maxTimeId]) =>
|
|
140
|
+
commit("viewport", { id, d: { maxTimeId } }),
|
|
141
|
+
setTimeId: ({ commit }, [id, timeId]) =>
|
|
142
|
+
commit("viewport", { id, d: { timeId } }),
|
|
143
|
+
setTimestamp: ({ commit }, [id, timestamp]) =>
|
|
144
|
+
commit("viewport", { id, d: { timestamp } }),
|
|
145
|
+
setTimestamps: ({ commit }, [id, timestamps]) =>
|
|
146
|
+
commit("viewport", { id, d: { timestamps } }),
|
|
147
|
+
setTimeIds: ({ commit }, [id, timeIds]) =>
|
|
148
|
+
commit("viewport", { id, d: { timeIds } }),
|
|
131
149
|
setIsColor: ({ commit }, [id, isColor]) =>
|
|
132
150
|
commit("viewport", { id, d: { isColor } }),
|
|
133
151
|
setIsMultiframe: ({ commit }, [id, isMultiframe]) =>
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"medical",
|
|
7
7
|
"cornerstone"
|
|
8
8
|
],
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.3.1",
|
|
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",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"@rollup/plugin-commonjs": "^17.1.0",
|
|
29
29
|
"cornerstone-core": "^2.6.1",
|
|
30
30
|
"cornerstone-file-image-loader": "^0.3.0",
|
|
31
|
-
"cornerstone-tools": "^6.0.
|
|
32
|
-
"cornerstone-wado-image-loader": "^4.1.
|
|
31
|
+
"cornerstone-tools": "^6.0.7",
|
|
32
|
+
"cornerstone-wado-image-loader": "^4.1.3",
|
|
33
33
|
"cornerstone-web-image-loader": "^2.1.1",
|
|
34
34
|
"crypto-js": "^4.1.1",
|
|
35
35
|
"dicom-character-set": "^1.0.3",
|