Skip to content

Commit b94f07f

Browse files
committed
fix: 🐛 IDC1346, convert fractional segs into binary
1 parent 42a7ca7 commit b94f07f

File tree

1 file changed

+63
-14
lines changed

1 file changed

+63
-14
lines changed

src/adapters/Cornerstone/Segmentation_4X.js

+63-14
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ function _createSegFromImages(images, isMultiframe, options) {
264264
* @param {*} metadataProvider.
265265
* @param {bool} skipOverlapping - skip checks for overlapping segs, default value false.
266266
* @param {number} tolerance - default value 1.e-3.
267+
* @param {bool} binarizeFractionalSegs - binarize fractional segmentation by thresholding - default value true.
268+
* @param {number} fractionalSegsThreshold - thresholding parameter for fractional segmentations - default value 0.8 (80% respect to the maximum value).
267269
*
268270
* @return {[]ArrayBuffer}a list of array buffer for each labelMap
269271
* @return {Object} an object from which the segment metadata can be derived
@@ -276,7 +278,9 @@ function generateToolState(
276278
arrayBuffer,
277279
metadataProvider,
278280
skipOverlapping = false,
279-
tolerance = 1e-3
281+
tolerance = 1e-3,
282+
binarizeFractionalSegs = true,
283+
fractionalSegsThreshold = 0.8
280284
) {
281285
const dicomData = DicomMessage.readFile(arrayBuffer);
282286
const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
@@ -337,7 +341,11 @@ function generateToolState(
337341
return;
338342
}
339343
} else {
340-
pixelData = unpackPixelData(multiframe);
344+
pixelData = unpackPixelData(
345+
multiframe,
346+
binarizeFractionalSegs,
347+
fractionalSegsThreshold
348+
);
341349

342350
if (!pixelData) {
343351
throw new Error("Fractional segmentations are not yet supported");
@@ -1218,9 +1226,15 @@ function checkIfPerpendicular(iop1, iop2, tolerance) {
12181226
* unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
12191227
*
12201228
* @param {Object} multiframe The multiframe dataset.
1229+
* @param {bool} binarizeFractionalSegs - binarize fractional segmentation by thresholding.
1230+
* @param {number} fractionalSegsThreshold - thresholding parameter for fractional segmentations.
12211231
* @return {Uint8Array} The unpacked pixelData.
12221232
*/
1223-
function unpackPixelData(multiframe) {
1233+
function unpackPixelData(
1234+
multiframe,
1235+
binarizeFractionalSegs,
1236+
fractionalSegsThreshold
1237+
) {
12241238
const segType = multiframe.SegmentationType;
12251239

12261240
let data;
@@ -1240,21 +1254,56 @@ function unpackPixelData(multiframe) {
12401254

12411255
const pixelData = new Uint8Array(data);
12421256

1243-
const max = multiframe.MaximumFractionalValue;
1244-
const onlyMaxAndZero =
1245-
pixelData.find(element => element !== 0 && element !== max) ===
1246-
undefined;
1257+
// IDC: we encountered segmentations defined as fractional with a constant value which is not the MaximumFractionalValue.
1258+
// Here we add the following check: if the labelmap has a constant value (independently by the value itself), it is considered a binary segmentation
1259+
const firstNonZeroIndex = pixelData.findIndex(element => element > 0);
1260+
const firstNonZeroValue = pixelData[firstNonZeroIndex];
1261+
const onlyOneValueAndZero =
1262+
pixelData.find(
1263+
element => element !== 0 && element !== firstNonZeroValue
1264+
) === undefined;
1265+
1266+
if (onlyOneValueAndZero) {
1267+
log.warn(
1268+
"This segmentation object is actually binary... processing as such."
1269+
);
12471270

1248-
if (!onlyMaxAndZero) {
1249-
// This is a fractional segmentation, which is not currently supported.
1250-
return;
1271+
return pixelData;
12511272
}
12521273

1253-
log.warn(
1254-
"This segmentation object is actually binary... processing as such."
1255-
);
1274+
// This is a fractional segmentation, which is not currently supported.
1275+
if (binarizeFractionalSegs) {
1276+
console.warn(
1277+
"This segmentation object is fractional. Fractional segmentations are not supported. Computing binary labelMap by thresholding (80% from the maximum value)."
1278+
);
1279+
// IDC: binarize fractional segmentation if requested
1280+
1281+
// we calculcate the maximum since unfortunatly it looks like
1282+
// (at least for IDC datasets) the maximum value is the array
1283+
// is not the DICOM attirbute MaximumFractionalValue
1284+
let max = -Number.MAX_VALUE;
1285+
pixelData.forEach(element => {
1286+
if (element > max) {
1287+
max = element;
1288+
}
1289+
});
1290+
max = Math.min(max, multiframe.MaximumFractionalValue);
1291+
1292+
// use as threshold: max * factor (default 80%)
1293+
const thershold = max * fractionalSegsThreshold;
1294+
1295+
for (let i = 0; i < pixelData.length; i++) {
1296+
if (pixelData[i] < thershold) {
1297+
pixelData[i] = 0;
1298+
} else {
1299+
pixelData[i] = 1;
1300+
}
1301+
}
1302+
1303+
return pixelData;
1304+
}
12561305

1257-
return pixelData;
1306+
return;
12581307
}
12591308

12601309
/**

0 commit comments

Comments
 (0)