-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathloadImageData.js
134 lines (105 loc) · 3.48 KB
/
loadImageData.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import cornerstone from 'cornerstone-core';
import insertSlice from './data/insertSlice.js';
import getPatientWeightAndCorrectedDose from './data/getPatientWeightAndCorrectedDose.js';
// TODO: If we attempt to load multiple imageDataObjects at once this will break.
export default function loadImageDataProgressively(imageDataObject) {
if (imageDataObject.loaded || imageDataObject.isLoading) {
// Returning instantly resolved promise as good to go.
// Returning promise to be resolved by other process as loading.
return;
}
const {
imageIds,
vtkImageData,
metaDataMap,
sortedDatasets,
} = imageDataObject;
const imageId0 = imageIds[0];
const seriesModule = cornerstone.metaData.get(
'generalSeriesModule',
imageId0
);
// If no seriesModule is present will default to linear scaling function.
const modality = seriesModule && seriesModule.modality;
let modalitySpecificScalingParameters;
if (modality === 'PT') {
modalitySpecificScalingParameters = getPatientWeightAndCorrectedDose(
imageId0
);
}
imageDataObject.isLoading = true;
// This is straight up a hack: vtkjs cries when you feed it data with a range of zero.
// So lets set the first voxel to 1, which will be replaced when the first image comes in.
const scalars = vtkImageData.getPointData().getScalars();
const scalarData = scalars.getData();
scalarData[0] = 1;
const range = {
max: Number.NEGATIVE_INFINITY,
min: Number.POSITIVE_INFINITY,
};
const numberOfFrames = imageIds.length;
let numberProcessed = 0;
const reRenderFraction = numberOfFrames / 5;
let reRenderTarget = reRenderFraction;
const insertPixelDataErrorHandler = error => {
numberProcessed++;
imageDataObject._publishPixelDataInsertedError(error);
if (numberProcessed === numberOfFrames) {
// Done loading, publish complete and remove all subscriptions.
imageDataObject._publishAllPixelDataInserted();
}
};
const insertPixelData = image => {
const { imagePositionPatient } = metaDataMap.get(image.imageId);
const sliceIndex = sortedDatasets.findIndex(
dataset => dataset.imagePositionPatient === imagePositionPatient
);
const { max, min } = insertSlice(
vtkImageData,
sliceIndex,
image,
modality,
modalitySpecificScalingParameters
);
if (max > range.max) {
range.max = max;
}
if (min < range.min) {
range.min = min;
}
const dataArray = vtkImageData.getPointData().getScalars();
dataArray.setRange(range, 1);
numberProcessed++;
if (numberProcessed > reRenderTarget) {
reRenderTarget += reRenderFraction;
vtkImageData.modified();
}
imageDataObject._publishPixelDataInserted(numberProcessed);
if (numberProcessed === numberOfFrames) {
// Done loading, publish complete and remove all subscriptions.
imageDataObject._publishAllPixelDataInserted();
}
};
prefetchImageIds(imageIds, insertPixelData, insertPixelDataErrorHandler);
}
function prefetchImageIds(
imageIds,
insertPixelData,
insertPixelDataErrorHandler
) {
const imageLoadPoolManager = cornerstone.imageLoadPoolManager;
const requestType = 'prefetch';
const requestFn = id =>
cornerstone
.loadAndCacheImage(id)
.then(insertPixelData, insertPixelDataErrorHandler);
imageIds.forEach(imageId => {
imageLoadPoolManager.addRequest(
requestFn.bind(this, imageId),
requestType,
{
imageId,
}
);
});
}