fix(staticwado): SM and RT and update the server with new data (#3422)

* fix bugs for the RT for the new demo

* fix SM with the static-wado server

* remove thumbnail from tmtv

* migration guide

* fix stability for the rt struct

* apply review comments

* add loading indicator to SM

* pdf works

* try to fix relative bulkData

* fix the rest

* fix preflight for the SM

* fix typo

* apply review comments

* yarn lock
This commit is contained in:
Alireza authored and GitHub committed 2023-05-29 09:04:49 -04:00
1 parent b684d80426
commit c7bcf1134d
30 files changed
+290 -156

No files matched your search

@@ -7,12 +7,13 @@ async function checkAndLoadContourData(instance, datasource) {
return Promise.reject('Invalid instance object or ROIContourSequence');
}
const promises = [];
let counter = 0;
const promisesMap = new Map();
for (const ROIContour of instance.ROIContourSequence) {
const referencedROINumber = ROIContour.ReferencedROINumber;
if (!ROIContour || !ROIContour.ContourSequence) {
return Promise.reject('Invalid ROIContour or ContourSequence');
promisesMap.set(referencedROINumber, [Promise.resolve([])]);
continue;
}
for (const Contour of ROIContour.ContourSequence) {
@@ -21,9 +22,15 @@ async function checkAndLoadContourData(instance, datasource) {
}
const contourData = Contour.ContourData;
counter++;
if (Array.isArray(contourData)) {
promises.push(Promise.resolve(contourData));
promisesMap.has(referencedROINumber)
? promisesMap
.get(referencedROINumber)
.push(Promise.resolve(contourData))
: promisesMap.set(referencedROINumber, [
Promise.resolve(contourData),
]);
} else if (contourData && contourData.BulkDataURI) {
const bulkDataURI = contourData.BulkDataURI;
@@ -44,53 +51,59 @@ async function checkAndLoadContourData(instance, datasource) {
SOPInstanceUID: instance.SOPInstanceUID,
});
promises.push(bulkDataPromise);
promisesMap.has(referencedROINumber)
? promisesMap.get(referencedROINumber).push(bulkDataPromise)
: promisesMap.set(referencedROINumber, [bulkDataPromise]);
} else {
return Promise.reject(`Invalid ContourData: ${contourData}`);
}
}
}
const flattenedPromises = promises.flat();
const resolvedPromises = await Promise.allSettled(flattenedPromises);
// Modify contourData and replace it in its corresponding ROIContourSequence's Contour's contourData
let index = 0;
instance.ROIContourSequence.forEach((ROIContour, roiIndex) => {
ROIContour.ContourSequence.forEach((Contour, contourIndex) => {
const promise = resolvedPromises[index++];
const resolvedPromisesMap = new Map();
for (const [key, promiseArray] of promisesMap.entries()) {
resolvedPromisesMap.set(key, await Promise.allSettled(promiseArray));
}
if (promise.status === 'fulfilled') {
const uint8Array = new Uint8Array(promise.value);
const textDecoder = new TextDecoder();
const dataUint8Array = textDecoder.decode(uint8Array);
if (
typeof dataUint8Array === 'string' &&
dataUint8Array.includes('\\')
) {
const numSlashes = (dataUint8Array.match(/\\/g) || []).length;
let startIndex = 0;
let endIndex = dataUint8Array.indexOf('\\', startIndex);
let numbersParsed = 0;
const ContourData = [];
instance.ROIContourSequence.forEach(ROIContour => {
try {
const referencedROINumber = ROIContour.ReferencedROINumber;
const resolvedPromises = resolvedPromisesMap.get(referencedROINumber);
while (numbersParsed !== numSlashes + 1) {
const str = dataUint8Array.substring(startIndex, endIndex);
let value = parseFloat(str);
ContourData.push(value);
startIndex = endIndex + 1;
endIndex = dataUint8Array.indexOf('\\', startIndex);
endIndex === -1 ? (endIndex = dataUint8Array.length) : endIndex;
numbersParsed++;
if (ROIContour.ContourSequence) {
ROIContour.ContourSequence.forEach((Contour, index) => {
const promise = resolvedPromises[index];
if (promise.status === 'fulfilled') {
if (
Array.isArray(promise.value) &&
promise.value.every(Number.isFinite)
) {
// If promise.value is already an array of numbers, use it directly
Contour.ContourData = promise.value;
} else {
// If the resolved promise value is a byte array (Blob), it needs to be decoded
const uint8Array = new Uint8Array(promise.value);
const textDecoder = new TextDecoder();
const dataUint8Array = textDecoder.decode(uint8Array);
if (
typeof dataUint8Array === 'string' &&
dataUint8Array.includes('\\')
) {
Contour.ContourData = dataUint8Array
.split('\\')
.map(parseFloat);
} else {
Contour.ContourData = [];
}
}
} else {
console.error(promise.reason);
}
Contour.ContourData = ContourData;
} else {
Contour.ContourData = [];
}
} else {
console.error(promise.reason);
});
}
});
} catch (error) {
console.error(error);
}
});
}
@@ -104,7 +117,7 @@ export default async function loadRTStruct(
'@ohif/extension-cornerstone.utilityModule.common'
);
const dataSource = extensionManager.getActiveDataSource()[0];
const { useBulkDataURI } = dataSource.getConfig?.() || {};
const { bulkDataURI } = dataSource.getConfig?.() || {};
const { dicomLoaderService } = utilityModule.exports;
const imageIdSopInstanceUidPairs = _getImageIdSopInstanceUidPairsForDisplaySet(
@@ -116,7 +129,7 @@ export default async function loadRTStruct(
rtStructDisplaySet.isLoaded = true;
let instance = rtStructDisplaySet.instance;
if (!useBulkDataURI) {
if (!bulkDataURI || !bulkDataURI.enabled) {
const segArrayBuffer = await dicomLoaderService.findDicomDataPromise(
rtStructDisplaySet,
null,