feat(4D): Add 4D dynamic volume rendering and new pre-clinical 4d pt/ct mode (#3664)
Co-authored-by: Alireza <ar.sedghi@gmail.com> Co-authored-by: Neil <neil.a.macphee@gmail.com>
This commit is contained in:
200 files changed
+9589
-2178
No files matched your search
-45
@@ -1,45 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
|
||||
function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
onClick={onExportClick}
|
||||
disabled={disabled}
|
||||
type={ButtonEnums.type.secondary}
|
||||
size={ButtonEnums.size.small}
|
||||
>
|
||||
{t('Export')}
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={onCreateReportClick}
|
||||
type={ButtonEnums.type.secondary}
|
||||
size={ButtonEnums.size.small}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('Create Report')}
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
ActionButtons.propTypes = {
|
||||
onExportClick: PropTypes.func,
|
||||
onCreateReportClick: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
ActionButtons.defaultProps = {
|
||||
onExportClick: () => alert('Export'),
|
||||
onCreateReportClick: () => alert('Create Report'),
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
export default ActionButtons;
|
||||
+25
-20
@@ -1,19 +1,12 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
StudySummary,
|
||||
MeasurementTable,
|
||||
Dialog,
|
||||
Input,
|
||||
useViewportGrid,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { StudySummary, MeasurementTable, useViewportGrid, ActionButtons } from '@ohif/ui';
|
||||
import { DicomMetadataStore, utils } from '@ohif/core';
|
||||
import { useDebounce } from '@hooks';
|
||||
import { useAppConfig } from '@state';
|
||||
import ActionButtons from './ActionButtons';
|
||||
import { useTrackedMeasurements } from '../../getContextModule';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { downloadCSVReport } = utils;
|
||||
const { formatDate } = utils;
|
||||
@@ -27,9 +20,11 @@ const DISPLAY_STUDY_SUMMARY_INITIAL_VALUE = {
|
||||
|
||||
function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
||||
const [viewportGrid] = useViewportGrid();
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
const [measurementChangeTimestamp, setMeasurementsUpdated] = useState(Date.now().toString());
|
||||
const debouncedMeasurementChangeTimestamp = useDebounce(measurementChangeTimestamp, 200);
|
||||
const { measurementService, uiDialogService, displaySetService, customizationService } = servicesManager.services;
|
||||
const { measurementService, uiDialogService, displaySetService, customizationService } =
|
||||
servicesManager.services;
|
||||
const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements();
|
||||
const { trackedStudy, trackedSeries } = trackedMeasurements.context;
|
||||
const [displayStudySummary, setDisplayStudySummary] = useState(
|
||||
@@ -172,6 +167,9 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
||||
dm => dm.measurementType === measurementService.VALUE_TYPES.POINT
|
||||
);
|
||||
|
||||
const disabled =
|
||||
additionalFindings.length === 0 && displayMeasurementsWithoutFindings.length === 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -206,16 +204,23 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
||||
{!appConfig?.disableEditing && (
|
||||
<div className="flex justify-center p-4">
|
||||
<ActionButtons
|
||||
onExportClick={exportReport}
|
||||
onCreateReportClick={() => {
|
||||
sendTrackedMeasurementsEvent('SAVE_REPORT', {
|
||||
viewportId: viewportGrid.activeViewportId,
|
||||
isBackupSave: true,
|
||||
});
|
||||
}}
|
||||
disabled={
|
||||
additionalFindings.length === 0 && displayMeasurementsWithoutFindings.length === 0
|
||||
}
|
||||
t={t}
|
||||
actions={[
|
||||
{
|
||||
label: 'Export',
|
||||
onClick: exportReport,
|
||||
},
|
||||
{
|
||||
label: 'Create Report',
|
||||
onClick: () => {
|
||||
sendTrackedMeasurementsEvent('SAVE_REPORT', {
|
||||
viewportId: viewportGrid.activeViewportId,
|
||||
isBackupSave: true,
|
||||
});
|
||||
},
|
||||
},
|
||||
]}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
+24
-5
@@ -19,8 +19,13 @@ function PanelStudyBrowserTracking({
|
||||
requestDisplaySetCreationForStudy,
|
||||
dataSource,
|
||||
}) {
|
||||
const { displaySetService, uiDialogService, hangingProtocolService, uiNotificationService, measurementService } =
|
||||
servicesManager.services;
|
||||
const {
|
||||
displaySetService,
|
||||
uiDialogService,
|
||||
hangingProtocolService,
|
||||
uiNotificationService,
|
||||
measurementService,
|
||||
} = servicesManager.services;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { t } = useTranslation('Common');
|
||||
@@ -129,7 +134,8 @@ function PanelStudyBrowserTracking({
|
||||
const newImageSrcEntry = {};
|
||||
const displaySet = displaySetService.getDisplaySetByUID(dSet.displaySetInstanceUID);
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
|
||||
const imageId = imageIds[Math.floor(imageIds.length / 2)];
|
||||
|
||||
const imageId = getImageIdForThumbnail(displaySet, imageIds);
|
||||
|
||||
// TODO: Is it okay that imageIds are not returned here for SR displaySets?
|
||||
if (!imageId || displaySet?.unsupported) {
|
||||
@@ -195,7 +201,7 @@ function PanelStudyBrowserTracking({
|
||||
}
|
||||
|
||||
const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);
|
||||
const imageId = imageIds[Math.floor(imageIds.length / 2)];
|
||||
const imageId = getImageIdForThumbnail(displaySet, imageIds);
|
||||
|
||||
// TODO: Is it okay that imageIds are not returned here for SR displaysets?
|
||||
if (!imageId) {
|
||||
@@ -366,6 +372,19 @@ PanelStudyBrowserTracking.propTypes = {
|
||||
|
||||
export default PanelStudyBrowserTracking;
|
||||
|
||||
function getImageIdForThumbnail(displaySet: any, imageIds: any) {
|
||||
let imageId;
|
||||
if (displaySet.isDynamicVolume) {
|
||||
const timePoints = displaySet.dynamicVolumeInfo.timePoints;
|
||||
const middleIndex = Math.floor(timePoints.length / 2);
|
||||
const middleTimePointImageIds = timePoints[middleIndex];
|
||||
imageId = middleTimePointImageIds[Math.floor(middleTimePointImageIds.length / 2)];
|
||||
} else {
|
||||
imageId = imageIds[Math.floor(imageIds.length / 2)];
|
||||
}
|
||||
return imageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps from the DataSource's format to a naturalized object
|
||||
*
|
||||
@@ -631,4 +650,4 @@ function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user