feat(metadata): metadata access improvement (#5292)
* feat(metadata): metadata access improvement * feat: Make a few fields commonly used at the instance level inherit multiframe
This commit is contained in:
parent
9413219206
commit
16233d980f
@ -2,6 +2,7 @@ import dcmjs from 'dcmjs';
|
||||
|
||||
import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
|
||||
import createStudyMetadata from './createStudyMetadata';
|
||||
import addProxyFields from '../../utils/addProxyFields';
|
||||
|
||||
const EVENTS = {
|
||||
STUDY_ADDED: 'event::dicomMetadataStore:studyAdded',
|
||||
@ -70,7 +71,7 @@ function _getStudy(StudyInstanceUID) {
|
||||
* @returns {*} A series object
|
||||
*/
|
||||
function _getSeries(StudyInstanceUID, SeriesInstanceUID) {
|
||||
if(!StudyInstanceUID) {
|
||||
if (!StudyInstanceUID) {
|
||||
const series = _model.studies.map(study => study.series).flat();
|
||||
return series.find(aSeries => aSeries.SeriesInstanceUID === SeriesInstanceUID);
|
||||
}
|
||||
@ -176,7 +177,7 @@ const BaseImplementation = {
|
||||
naturalizedDataset = dicomJSONDataset;
|
||||
}
|
||||
|
||||
const { StudyInstanceUID } = naturalizedDataset;
|
||||
const { StudyInstanceUID, NumberOfFrames: numberOfFrames } = naturalizedDataset;
|
||||
|
||||
let study = _model.studies.find(study => study.StudyInstanceUID === StudyInstanceUID);
|
||||
|
||||
@ -185,10 +186,19 @@ const BaseImplementation = {
|
||||
study = _model.studies[_model.studies.length - 1];
|
||||
}
|
||||
|
||||
naturalizedDataset = numberOfFrames > 1 ? addProxyFields(naturalizedDataset) : naturalizedDataset;
|
||||
|
||||
study.addInstanceToSeries(naturalizedDataset);
|
||||
},
|
||||
addInstances(instances, madeInClient = false) {
|
||||
const { StudyInstanceUID, SeriesInstanceUID } = instances[0];
|
||||
const { StudyInstanceUID, SeriesInstanceUID, NumberOfFrames } = instances[0];
|
||||
// For multiframe images (NumberOfFrames > 1), wrap each instance with a metadata proxy
|
||||
// to enable fallback access for key image plane fields. This allows fields like
|
||||
// ImagePositionPatient, ImageOrientationPatient, and PixelSpacing to be transparently
|
||||
// resolved from parent or shared metadata if they are not directly present on the instance directly
|
||||
if (NumberOfFrames > 1) {
|
||||
instances = instances.map(instance => addProxyFields(instance));
|
||||
}
|
||||
|
||||
let study = _model.studies.find(study => study.StudyInstanceUID === StudyInstanceUID);
|
||||
|
||||
|
||||
57
platform/core/src/utils/addProxyFields.js
Normal file
57
platform/core/src/utils/addProxyFields.js
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* fieldProxies has the set of fields which are proxied on a per-field basis
|
||||
* to the child element.
|
||||
*/
|
||||
export const fieldProxies = [
|
||||
'ImagePositionPatient',
|
||||
'ImageOrientationPatient',
|
||||
'PixelSpacing',
|
||||
// more fields as necessary
|
||||
];
|
||||
|
||||
const METADATA_PROXY_FLAG = Symbol('isMetadataProxy');
|
||||
|
||||
/**
|
||||
* Adds proxy properties for a limited number of values which are sometimes
|
||||
* defined in multiframe instance data.
|
||||
*
|
||||
* If a requested field is in `metadataFieldsToWrap`:
|
||||
* - It first tries to return the value from the current instance.
|
||||
* - If not found, it attempts to retrieve the value from the `_parentInstance`.
|
||||
* - If still not found, it checks `_parentInstance._shared`.
|
||||
* - If none exist, it returns `undefined`.
|
||||
*
|
||||
* For all other properties, it behaves like a regular property access.
|
||||
*
|
||||
* This allows graceful fallback access for DICOM metadata values that might be spread
|
||||
* across nested or shared metadata structures.
|
||||
*
|
||||
* @param {Object} instance - The target instance object to wrap.
|
||||
* @returns {Proxy} A proxy-wrapped instance with custom field resolution behavior.
|
||||
*/
|
||||
export function addProxyFields(instance) {
|
||||
// Skip wrapping if already wrapped
|
||||
if (!instance || instance[METADATA_PROXY_FLAG]) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
for(const fieldProxy of fieldProxies) {
|
||||
if( fieldProxy in instance) {
|
||||
continue;
|
||||
}
|
||||
Object.defineProperty(instance,fieldProxy, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: () => {
|
||||
return instance._parentInstance?.[fieldProxy] ?? instance._parentInstance?._shared?.[fieldProxy];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mark this proxy to avoid double wrapping
|
||||
Object.defineProperty(instance,METADATA_PROXY_FLAG, { value: true });
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
export default addProxyFields;
|
||||
Loading…
Reference in New Issue
Block a user