4 Commits
rsab ... phkg

Author SHA1 Message Date
AlfandiMario
ac162cd2a3 startDate h-7 2026-08-20 15:52:12 +07:00
AlfandiMario
bfb55055a2 additional field untuk overlay MRI OHIF 2026-08-20 15:52:12 +07:00
AlfandiMario
af9ec01c19 additional field untuk overlay MRI OHIF 2025-11-04 11:47:12 +07:00
AlfandiMario
ae53d7faa3 support MRI custom overlay data for OHIF through fetchMeta because it couldn't retrieved from C-FIND / FINDSCU 2025-11-03 16:05:34 +07:00
3 changed files with 73 additions and 7 deletions

View File

@@ -2,7 +2,7 @@ version: '3'
services:
dicomweb-proxy:
image: dicomweb-proxy:2.0
image: dicomweb-proxy:3.0.1
container_name: dicomweb-proxy
ports:
- "5000:5000"

View File

@@ -58,6 +58,34 @@ function parseFile(filename: string): Promise<ElementType> {
const sliceThickness = dataset.string('x00180050');
const sliceLocation = dataset.string('x00201041');
// TODO: buat ini dynamic berdasarkan includefields atau modality
// TODO: hapus tambahan di bawah ini yang tidak diperlukan
// MR-specific tags for overlay
const spacingBetweenSlices = dataset.string('x00180088');
const percentPhaseFieldOfView = dataset.string('x00180094');
const fovDimensionElement = dataset.elements.x00181149;
const fovDimension = fovDimensionElement ? [dataset.uint16('x00181149', 0), dataset.uint16('x00181149', 1)] : null;
const acquisitionMatrixElement = dataset.elements.x00181310;
const acquisitionMatrix = acquisitionMatrixElement
? [dataset.uint16('x00181310', 0), dataset.uint16('x00181310', 1), dataset.uint16('x00181310', 2), dataset.uint16('x00181310', 3)]
: null;
const scanningSequence = dataset.string('x00180020');
const repetitionTime = dataset.string('x00180080');
const echoTime = dataset.string('x00180081');
const inversionTime = dataset.string('x00180082');
const receiveCoilName = dataset.string('x00181250');
const mrAcquisitionType = dataset.string('x00180023');
const phaseEncodingDirection = dataset.string('x00181312');
const numOfAverages = dataset.string('x00180083');
const echoTrainLength = dataset.string('x00180091');
const flipAngle = dataset.string('x00181314');
const pixelBandwidth = dataset.string('x00180095');
const acquisitionTime = dataset.string('x00080032');
const acquistionDurationTotal = dataset.string('x00189073'); // in seconds
const acquistionDurationPerFrame = dataset.string('x00189220'); // in ms
const parallelAcquisitionTechnique = dataset.string('x00189078');
// append to all results
const result: ElementType = {
'00100010': { Value: [{ Alphabetic: patientName }], vr: 'PN' },
@@ -88,7 +116,27 @@ function parseFile(filename: string): Promise<ElementType> {
'00200013': { Value: [instanceNumber], vr: 'IS' },
'00180050': { Value: [sliceThickness], vr: 'DS' },
'00201041': { Value: [sliceLocation], vr: 'DS' },
'00180088': { Value: [spacingBetweenSlices], vr: 'DS' },
'00180094': { Value: [percentPhaseFieldOfView], vr: 'DS' },
...(fovDimension && { '00181149': { Value: fovDimension, vr: 'IS' } }),
...(acquisitionMatrix && { '00181310': { Value: acquisitionMatrix, vr: 'US' } }),
'00180020': { Value: [scanningSequence], vr: 'CS' },
'00180080': { Value: [repetitionTime], vr: 'DS' },
'00180081': { Value: [echoTime], vr: 'DS' },
'00180082': { Value: [inversionTime], vr: 'DS' },
'00181250': { Value: [receiveCoilName], vr: 'SH' },
'00180023': { Value: [mrAcquisitionType], vr: 'CS' },
'00181312': { Value: [phaseEncodingDirection], vr: 'CS' },
'00180083': { Value: [numOfAverages], vr: 'DS' },
'00180091': { Value: [echoTrainLength], vr: 'IS' },
'00181314': { Value: [flipAngle], vr: 'DS' },
'00180095': { Value: [pixelBandwidth], vr: 'DS' },
'00080032': { Value: [acquisitionTime], vr: 'TM' },
'00189073': { Value: [acquistionDurationTotal], vr: 'DS' },
'00189220': { Value: [acquistionDurationPerFrame], vr: 'FD' },
'00189078': { Value: [parallelAcquisitionTechnique], vr: 'CS' },
};
resolve(result);
});
});
@@ -105,7 +153,6 @@ export function parseMeta(json: object, studyInstanceUID: string, seriesInstance
const sopInstanceUid = json[key]['00080018'].Value[0];
const pathname = path.join(storagePath, studyInstanceUID, sopInstanceUid);
parsing.push(parseFile(pathname));
}
return Promise.all(parsing);
}

View File

@@ -51,7 +51,7 @@ module.exports = function (server: FastifyInstance, opts: unknown, done: () => v
const hasStudyDate = query.StudyDate !== undefined;
if (!hasMedicalRecord && !hasAccessionNumber && !hasPatientName && !hasStudyInstanceUID && !hasStudyDate) {
const startDate = moment().format('YYYYMMDD');
const startDate = moment().subtract(7, 'days').format('YYYYMMDD');
const endDate = moment().format('YYYYMMDD');
query.StudyDate = `${startDate}-${endDate}`;
@@ -410,6 +410,25 @@ module.exports = function (server: FastifyInstance, opts: unknown, done: () => v
}
});
server.get<{
Params: IParamsImage;
Querystring: QueryParams;
}>('/rs/studies/:studyInstanceUid/series/:seriesInstanceUid/instances/:sopInstanceUid/metadata', async (req, reply) => {
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid } = req.params;
const { query } = req;
query.StudyInstanceUID = studyInstanceUid;
query.SeriesInstanceUID = seriesInstanceUid;
query.SOPInstanceUID = sopInstanceUid;
try {
const rsp = await fetchMeta(query, studyInstanceUid, seriesInstanceUid);
return reply.send(rsp);
} catch (error) {
logger.error(error);
return reply.send(500);
}
});
done();
};