feat: Annotation and Measurements support on multi-frame DICOM (#2973)

* added utilities to get frameNumber from imageId and add frameNumber to per-frame instance copy

* Fix measurements' display texts on the Measurements Panel to have the correct instance number and frame number

* fixed minor React bugs (errors on console)

* fixed React's console bugs that are logged for some series that doesn't have "description"

* bug fix - multi-frame files was not loading frames correctly. It was loading Frame 1 twice, and not loading the last frame. Due to wrong frame number indexing (frame number begins with 1, not 0)

* metadata parser fix - providing default values of imagePlaneModule

* measurement SR support on multi-frame DICOM

* bug fix - jumping to the selected measurment on multi-frame DICOM

* upgrade dcmjs dependency to 2.8.1

* StudySummary component - allow "description" to be null

* make getUIDsFromImageID() method public from MetadataProvider

* imageId usage fixes to be more stable

* change the variable name to be more meaningful

* fix metaProvider importing

* for(...of) instead of for(i=0;i<length;..)
as that doesn't assume anything about the layout/design and just gets next until done.

* use Array.findIndex instead of plain for loop

* use ReferencedSOPSequence[0] - because the ReferencedSOPSequence is an array that happens to have attributes of child zero when of length 1, but you shouldn't count on that.

* DisplaySetService.getDisplaySetForSOPInstanceUID() - added optional frameNumber parameter for future usage : now they are just ignored as we are not supporting multiframe splits

* simple code refactoring

* refactoring for checking undefined values - mappedAnnotations

* remove unreachable code

* code refactoring  - prefer conditional chaining

* fix how we access imageIds of viewport (StackViewport)
This commit is contained in:
md-prog authored and GitHub committed 2022-10-13 11:07:56 -04:00
1 parent af09578544
commit b93067b6a2
30 files changed
+276 -132

No files matched your search

+10 -8
View File
@@ -52,7 +52,7 @@ class MetadataProvider {
}
_getInstance(imageId) {
const uids = this._getUIDsFromImageID(imageId);
const uids = this.getUIDsFromImageID(imageId);
if (!uids) {
return;
@@ -191,14 +191,16 @@ class MetadataProvider {
rows: toNumber(instance.Rows),
columns: toNumber(instance.Columns),
imageOrientationPatient: toNumber(ImageOrientationPatient),
rowCosines: toNumber(rowCosines),
columnCosines: toNumber(columnCosines),
imagePositionPatient: toNumber(instance.ImagePositionPatient),
rowCosines: toNumber(rowCosines || [0, 1, 0]),
columnCosines: toNumber(columnCosines || [0, 0, -1]),
imagePositionPatient: toNumber(
instance.ImagePositionPatient || [0, 0, 0]
),
sliceThickness: toNumber(instance.SliceThickness),
sliceLocation: toNumber(instance.SliceLocation),
pixelSpacing: toNumber(PixelSpacing),
rowPixelSpacing: toNumber(rowPixelSpacing),
columnPixelSpacing: toNumber(columnPixelSpacing),
pixelSpacing: toNumber(PixelSpacing || 1),
rowPixelSpacing: toNumber(rowPixelSpacing || 1),
columnPixelSpacing: toNumber(columnPixelSpacing || 1),
};
break;
case WADO_IMAGE_LOADER_TAGS.IMAGE_PIXEL_MODULE:
@@ -409,7 +411,7 @@ class MetadataProvider {
return metadata;
}
_getUIDsFromImageID(imageId) {
getUIDsFromImageID(imageId) {
// TODO: adding csiv here is not really correct. Probably need to use
// metadataProvider.addImageIdToUIDs(imageId, {
// StudyInstanceUID,
@@ -75,7 +75,11 @@ export default class DisplaySetService {
);
};
getDisplaySetForSOPInstanceUID(SOPInstanceUID, SeriesInstanceUID) {
getDisplaySetForSOPInstanceUID(
SOPInstanceUID,
SeriesInstanceUID,
frameNumber
) {
const displaySets = SeriesInstanceUID
? this.getDisplaySetsForSeries(SeriesInstanceUID)
: this.getDisplaySetCache();
@@ -38,6 +38,7 @@ const MEASUREMENT_SCHEMA_KEYS = [
'FrameOfReferenceUID',
'referenceStudyUID',
'referenceSeriesUID',
'frameNumber',
'displaySetInstanceUID',
'label',
'description',
+26 -15
View File
@@ -12,22 +12,33 @@ const combineFrameInstance = (frame, instance) => {
const {
PerFrameFunctionalGroupsSequence,
SharedFunctionalGroupsSequence,
NumberOfFrames,
} = instance;
if (!PerFrameFunctionalGroupsSequence) return instance;
const shared = Object.values(SharedFunctionalGroupsSequence[0])
.map(it => it[0])
.filter(it => it !== undefined && typeof it === 'object');
const perFrame = Object.values(
PerFrameFunctionalGroupsSequence[(frame || 1) - 1]
)
.map(it => it[0])
.filter(it => it !== undefined && typeof it === 'object');
return Object.assign(
{},
instance,
...Object.values(shared),
...Object.values(perFrame)
);
if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) {
const frameNumber = Number.parseInt(frame || 1);
const shared = (SharedFunctionalGroupsSequence
? Object.values(SharedFunctionalGroupsSequence[0])
: []
)
.map(it => it[0])
.filter(it => it !== undefined && typeof it === 'object');
const perFrame = (PerFrameFunctionalGroupsSequence
? Object.values(PerFrameFunctionalGroupsSequence[frameNumber - 1])
: []
)
.map(it => it[0])
.filter(it => it !== undefined && typeof it === 'object');
return Object.assign(
{ frameNumber: frameNumber },
instance,
...Object.values(shared),
...Object.values(perFrame)
);
} else {
return instance;
}
};
export default combineFrameInstance;