feat(panel and auth): fix study panel to not rely on priors and add token param to url (#3381)
* fix: multiframe * fix the unnecessary use of prior since some servers dont like it * add authentication via token in url * add data citation * add resources * upgrade packages * yarn lock * apply review comments
This commit is contained in:
1 parent
cba57a1b65
commit
84cb709b44
24 files changed
+387
-211
No files matched your search
@@ -200,6 +200,7 @@ function createDicomLocalApi(dicomLocalConfig) {
|
||||
displaySet.images.forEach(instance => {
|
||||
const NumberOfFrames = instance.NumberOfFrames;
|
||||
if (NumberOfFrames > 1) {
|
||||
// in multiframe we start at frame 1
|
||||
for (let i = 1; i <= NumberOfFrames; i++) {
|
||||
const imageId = this.getImageIdsForInstance({
|
||||
instance,
|
||||
|
||||
@@ -12,7 +12,7 @@ const { sortStudyInstances, formatDate } = utils;
|
||||
function PanelStudyBrowser({
|
||||
servicesManager,
|
||||
getImageSrc,
|
||||
getStudiesForPatientByStudyInstanceUID,
|
||||
getStudiesForPatientByMRN,
|
||||
requestDisplaySetCreationForStudy,
|
||||
dataSource,
|
||||
}) {
|
||||
@@ -64,12 +64,24 @@ function PanelStudyBrowser({
|
||||
useEffect(() => {
|
||||
// Fetch all studies for the patient in each primary study
|
||||
async function fetchStudiesForPatient(StudyInstanceUID) {
|
||||
const qidoStudiesForPatient =
|
||||
(await getStudiesForPatientByStudyInstanceUID(StudyInstanceUID)) || [];
|
||||
// current study qido
|
||||
const qidoForStudyUID = await dataSource.query.studies.search({
|
||||
studyInstanceUid: StudyInstanceUID,
|
||||
});
|
||||
|
||||
let qidoStudiesForPatient = qidoForStudyUID;
|
||||
|
||||
// try to fetch the prior studies based on the patientID if the
|
||||
// server can respond.
|
||||
try {
|
||||
qidoStudiesForPatient = await getStudiesForPatientByMRN(
|
||||
qidoForStudyUID
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
|
||||
// TODO: This should be "naturalized DICOM JSON" studies
|
||||
const mappedStudies = _mapDataSourceStudies(qidoStudiesForPatient);
|
||||
|
||||
const actuallyMappedStudies = mappedStudies.map(qidoStudy => {
|
||||
return {
|
||||
studyInstanceUid: qidoStudy.StudyInstanceUID,
|
||||
@@ -77,29 +89,27 @@ function PanelStudyBrowser({
|
||||
description: qidoStudy.StudyDescription,
|
||||
modalities: qidoStudy.ModalitiesInStudy,
|
||||
numInstances: qidoStudy.NumInstances,
|
||||
// displaySets: []
|
||||
};
|
||||
});
|
||||
if (isMounted.current) {
|
||||
setStudyDisplayList(prevArray => {
|
||||
const ret = [...prevArray];
|
||||
for (const study of actuallyMappedStudies) {
|
||||
if (
|
||||
!prevArray.find(
|
||||
it => it.studyInstanceUid === study.studyInstanceUid
|
||||
)
|
||||
) {
|
||||
ret.push(study);
|
||||
}
|
||||
|
||||
setStudyDisplayList(prevArray => {
|
||||
const ret = [...prevArray];
|
||||
for (const study of actuallyMappedStudies) {
|
||||
if (
|
||||
!prevArray.find(
|
||||
it => it.studyInstanceUid === study.studyInstanceUid
|
||||
)
|
||||
) {
|
||||
ret.push(study);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
StudyInstanceUIDs.forEach(sid => fetchStudiesForPatient(sid));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [StudyInstanceUIDs, getStudiesForPatientByStudyInstanceUID]);
|
||||
}, [StudyInstanceUIDs, getStudiesForPatientByMRN]);
|
||||
|
||||
// // ~~ Initial Thumbnails
|
||||
useEffect(() => {
|
||||
@@ -254,7 +264,7 @@ PanelStudyBrowser.propTypes = {
|
||||
getImageIdsForDisplaySet: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
getImageSrc: PropTypes.func.isRequired,
|
||||
getStudiesForPatientByStudyInstanceUID: PropTypes.func.isRequired,
|
||||
getStudiesForPatientByMRN: PropTypes.func.isRequired,
|
||||
requestDisplaySetCreationForStudy: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
//
|
||||
import PanelStudyBrowser from './PanelStudyBrowser';
|
||||
import getImageSrcFromImageId from './getImageSrcFromImageId';
|
||||
import getStudiesForPatientByStudyInstanceUID from './getStudiesForPatientByStudyInstanceUID';
|
||||
import getStudiesForPatientByMRN from './getStudiesForPatientByMRN';
|
||||
import requestDisplaySetCreationForStudy from './requestDisplaySetCreationForStudy';
|
||||
|
||||
/**
|
||||
@@ -21,7 +21,7 @@ function WrappedPanelStudyBrowser({
|
||||
// TODO: This should be made available a different way; route should have
|
||||
// already determined our datasource
|
||||
const dataSource = extensionManager.getDataSources()[0];
|
||||
const _getStudiesForPatientByStudyInstanceUID = getStudiesForPatientByStudyInstanceUID.bind(
|
||||
const _getStudiesForPatientByMRN = getStudiesForPatientByMRN.bind(
|
||||
null,
|
||||
dataSource
|
||||
);
|
||||
@@ -38,9 +38,7 @@ function WrappedPanelStudyBrowser({
|
||||
servicesManager={servicesManager}
|
||||
dataSource={dataSource}
|
||||
getImageSrc={_getImageSrcFromImageId}
|
||||
getStudiesForPatientByStudyInstanceUID={
|
||||
_getStudiesForPatientByStudyInstanceUID
|
||||
}
|
||||
getStudiesForPatientByMRN={_getStudiesForPatientByMRN}
|
||||
requestDisplaySetCreationForStudy={_requestDisplaySetCreationForStudy}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ function getImageSrcFromImageId(cornerstone, imageId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const canvas = document.createElement('canvas');
|
||||
cornerstone.utilities
|
||||
.loadImageToCanvas(canvas, imageId)
|
||||
.loadImageToCanvas({ canvas, imageId })
|
||||
.then(imageId => {
|
||||
resolve(canvas.toDataURL());
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
async function getStudiesForPatientByMRN(dataSource, qidoForStudyUID) {
|
||||
if (qidoForStudyUID && qidoForStudyUID.length && qidoForStudyUID[0].mrn) {
|
||||
return dataSource.query.studies.search({
|
||||
patientId: qidoForStudyUID[0].mrn,
|
||||
});
|
||||
}
|
||||
console.log('No mrn found for', qidoForStudyUID);
|
||||
return qidoForStudyUID;
|
||||
}
|
||||
|
||||
export default getStudiesForPatientByMRN;
|
||||
@@ -1,29 +0,0 @@
|
||||
async function getStudiesForPatientByStudyInstanceUID(
|
||||
dataSource,
|
||||
StudyInstanceUID
|
||||
) {
|
||||
if (StudyInstanceUID === undefined) {
|
||||
return;
|
||||
}
|
||||
// TODO: The `DicomMetadataStore` should short-circuit both of these requests
|
||||
// Data _could_ be here from route query, or if using JSON data source
|
||||
// We could also force this to "await" these values being available in the DICOMStore?
|
||||
// Kind of like promise fulfillment in @cornerstonejs/dicom-image-loader when there are multiple
|
||||
// outgoing requests for the same data
|
||||
const getStudyResult = await dataSource.query.studies.search({
|
||||
studyInstanceUid: StudyInstanceUID,
|
||||
});
|
||||
|
||||
// TODO: To Erik's point, the data source likely shouldn't deviate from
|
||||
// Naturalized DICOM JSON when returning. It makes things like this awkward (mrn)
|
||||
if (getStudyResult && getStudyResult.length && getStudyResult[0].mrn) {
|
||||
return dataSource.query.studies.search({
|
||||
patientId: getStudyResult[0].mrn,
|
||||
});
|
||||
}
|
||||
console.log('No mrn found for', getStudyResult);
|
||||
// The original study we KNOW belongs to the same set, so just return it
|
||||
return getStudyResult;
|
||||
}
|
||||
|
||||
export default getStudiesForPatientByStudyInstanceUID;
|
||||
@@ -7,7 +7,7 @@ import getSopClassHandlerModule from './getSopClassHandlerModule.js';
|
||||
import getToolbarModule from './getToolbarModule';
|
||||
import getCommandsModule from './commandsModule';
|
||||
import getHangingProtocolModule from './getHangingProtocolModule';
|
||||
import getStudiesForPatientByStudyInstanceUID from './Panels/getStudiesForPatientByStudyInstanceUID';
|
||||
import getStudiesForPatientByMRN from './Panels/getStudiesForPatientByMRN';
|
||||
import getCustomizationModule from './getCustomizationModule';
|
||||
import { id } from './id.js';
|
||||
import preRegistration from './init';
|
||||
@@ -34,7 +34,7 @@ const defaultExtension: Types.Extensions.Extension = {
|
||||
{
|
||||
name: 'common',
|
||||
exports: {
|
||||
getStudiesForPatientByStudyInstanceUID,
|
||||
getStudiesForPatientByMRN,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -45,4 +45,8 @@ const defaultExtension: Types.Extensions.Extension = {
|
||||
|
||||
export default defaultExtension;
|
||||
|
||||
export { ContextMenuController, CustomizeableContextMenuTypes };
|
||||
export {
|
||||
ContextMenuController,
|
||||
CustomizeableContextMenuTypes,
|
||||
getStudiesForPatientByMRN,
|
||||
};
|
||||
Reference in new issue
Block a user