Skip to content

Commit

Permalink
feat: Retrieve Thumbnail Resources APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Chinlinlee committed Aug 14, 2023
1 parent 905ff93 commit 8fc1a0b
Show file tree
Hide file tree
Showing 8 changed files with 505 additions and 1 deletion.
155 changes: 155 additions & 0 deletions api-sql/dicom-web/controller/WADO-RS/service/thumbnail.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const errorResponse = require("@root/utils/errorResponse/errorResponseMessage");
const renderedService = require("../service/rendered.service");
const _ = require("lodash");
const {
ThumbnailService,
StudyThumbnailFactory,
SeriesThumbnailFactory,
InstanceThumbnailFactory
} = require("@root/api/dicom-web/controller/WADO-RS/service/thumbnail.service");
const { InstanceModel } = require("@models/sql/models/instance.model");
class SqlThumbnailService extends ThumbnailService {

/**
*
* @param {import("express").Request} req
* @param {import("express").Response} res
* @param {typeof ThumbnailFactory} thumbnailFactory
*/
constructor(req, res, apiLogger, thumbnailFactory) {
super(req, res, apiLogger, thumbnailFactory);
}

async getThumbnailAndResponse() {
if (!_.get(this.request, "query.viewport")) {
_.set(this.request, "query.viewport", "100,100");
}

let instanceFramesObj = await this.thumbnailFactory.getThumbnailInstance();
if (this.checkInstanceExists(instanceFramesObj)) {
return;
}

let thumbnail = await this.getThumbnailByInstance(instanceFramesObj);
if (thumbnail) {
return this.response.end(thumbnail, "binary");
}
throw new Error(`Can not process this image, instanceUID: ${instanceFramesObj.instanceUID}`);
}

async getThumbnailByInstance(instanceFramesObj) {
let dicomNumberOfFrames = _.get(instanceFramesObj, "x00280008", 1);
dicomNumberOfFrames = parseInt(dicomNumberOfFrames);
let medianFrame = 1;
if (dicomNumberOfFrames > 1) medianFrame = dicomNumberOfFrames >> 1;
if (this.request.params.frameNumber) {
medianFrame = this.request.params.frameNumber[0];
}

let postProcessResult = await renderedService.postProcessFrameImage(this.request, medianFrame, instanceFramesObj);
if (postProcessResult.status) {
this.response.writeHead(200, {
"Content-Type": "image/jpeg"
});
this.apiLogger.logger.info(`Get instance's thumbnail successfully, instance UID: ${instanceFramesObj.instanceUID}`);
return postProcessResult.magick.toBuffer();
}
return undefined;
}

checkInstanceExists(instanceFramesObj) {
if (!instanceFramesObj) {
this.response.writeHead(404, {
"Content-Type": "application/dicom+json"
});
let notFoundMessage = errorResponse.getNotFoundErrorMessage(`Not Found, ${this.thumbnailFactory.getUidsString()}`);

let notFoundMessageStr = JSON.stringify(notFoundMessage);

this.apiLogger.logger.warn(`[${notFoundMessageStr}]`);

return this.response.end(notFoundMessageStr);
}
return undefined;
}
}


class SqlStudyThumbnailFactory extends StudyThumbnailFactory {
constructor(uids) {
super(uids);
}

/**
*
* @param {import("../../../../../utils/typeDef/dicom").Uids} uids
*/
async getThumbnailInstance() {
let medianInstance = await InstanceModel.getInstanceOfMedianIndex({
studyUID: this.uids.studyUID
});
if (!medianInstance) return undefined;

let instanceFramesObj = await renderedService.getInstanceFrameObj({
studyUID: this.uids.studyUID,
seriesUID: medianInstance.seriesUID,
instanceUID: medianInstance.instanceUID
});

return instanceFramesObj;
}

}

class SqlSeriesThumbnailFactory extends SeriesThumbnailFactory {
constructor(uids) {
super(uids);
}

/**
*
* @param {import("../../../../../utils/typeDef/dicom").Uids} uids
*/
async getThumbnailInstance() {
let medianInstance = await InstanceModel.getInstanceOfMedianIndex({
studyUID: this.uids.studyUID,
seriesUID: this.uids.seriesUID
});
if (!medianInstance) return undefined;

let instanceFramesObj = await renderedService.getInstanceFrameObj({
studyUID: this.uids.studyUID,
seriesUID: this.uids.seriesUID,
instanceUID: medianInstance.instanceUID
});

return instanceFramesObj;
}

}

class SqlInstanceThumbnailFactory extends InstanceThumbnailFactory {
constructor(uids) {
super(uids);
}

/**
*
* @param {import("../../../../../utils/typeDef/dicom").Uids} uids
*/
async getThumbnailInstance() {
let instanceFramesObj = await renderedService.getInstanceFrameObj({
studyUID: this.uids.studyUID,
seriesUID: this.uids.seriesUID,
instanceUID: this.uids.instanceUID
});

return instanceFramesObj;
}

}

module.exports.ThumbnailService = SqlThumbnailService;
module.exports.StudyThumbnailFactory = SqlStudyThumbnailFactory;
module.exports.SeriesThumbnailFactory = SqlSeriesThumbnailFactory;
module.exports.InstanceThumbnailFactory = SqlInstanceThumbnailFactory;
52 changes: 52 additions & 0 deletions api-sql/dicom-web/controller/WADO-RS/thumbnail/frame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const { Controller } = require("@root/api/controller.class");
const { ApiLogger } = require("@root/utils/logs/api-logger");
const {
ThumbnailService,
InstanceThumbnailFactory
} = require("../service/thumbnail.service");



class RetrieveFrameThumbnailController extends Controller {
constructor(req, res) {
super(req, res);
}

async mainProcess() {

let apiLogger = new ApiLogger(this.request, "WADO-RS");
apiLogger.addTokenValue();

apiLogger.logger.info(`Get Study's Series' Instance Thumbnail [study UID: ${this.request.params.studyUID},\
series UID: ${this.request.params.seriesUID}]\
instance UID: ${this.request.params.instanceUID}\
frames: ${JSON.stringify(this.request.params.frameNumber)}`);

try {
let thumbnailService = new ThumbnailService(this.request, this.response, apiLogger, InstanceThumbnailFactory);
return thumbnailService.getThumbnailAndResponse();
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
apiLogger.logger.error(errorStr);

this.response.writeHead(500, {
"Content-Type": "application/dicom+json"
});
return this.response.end({
code: 500,
message: "An exception occurred"
});
}
}
}

/**
*
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse} res
*/
module.exports = async function (req, res) {
let controller = new RetrieveFrameThumbnailController(req, res);

await controller.doPipeline();
};
51 changes: 51 additions & 0 deletions api-sql/dicom-web/controller/WADO-RS/thumbnail/instance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const { Controller } = require("@root/api/controller.class");
const { ApiLogger } = require("@root/utils/logs/api-logger");
const {
ThumbnailService,
InstanceThumbnailFactory
} = require("../service/thumbnail.service");



class RetrieveInstanceThumbnailController extends Controller {
constructor(req, res) {
super(req, res);
}

async mainProcess() {

let apiLogger = new ApiLogger(this.request, "WADO-RS");
apiLogger.addTokenValue();

apiLogger.logger.info(`Get Study's Series' Instance Thumbnail [study UID: ${this.request.params.studyUID},\
series UID: ${this.request.params.seriesUID}]\
instance UID: ${this.request.params.instanceUID}`);

try {
let thumbnailService = new ThumbnailService(this.request, this.response, apiLogger, InstanceThumbnailFactory);
return thumbnailService.getThumbnailAndResponse();
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
apiLogger.logger.error(errorStr);

this.response.writeHead(500, {
"Content-Type": "application/dicom+json"
});
return this.response.end({
code: 500,
message: "An exception occurred"
});
}
}
}

/**
*
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse} res
*/
module.exports = async function (req, res) {
let controller = new RetrieveInstanceThumbnailController(req, res);

await controller.doPipeline();
};
50 changes: 50 additions & 0 deletions api-sql/dicom-web/controller/WADO-RS/thumbnail/series.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const { Controller } = require("@root/api/controller.class");
const { ApiLogger } = require("@root/utils/logs/api-logger");
const {
ThumbnailService,
SeriesThumbnailFactory
} = require("../service/thumbnail.service");



class RetrieveSeriesThumbnailController extends Controller {
constructor(req, res) {
super(req, res);
}

async mainProcess() {

let apiLogger = new ApiLogger(this.request, "WADO-RS");
apiLogger.addTokenValue();

apiLogger.logger.info(`Get Study's Series' Thumbnail [study UID: ${this.request.params.studyUID},\
series UID: ${this.request.params.seriesUID}]`);

try {
let thumbnailService = new ThumbnailService(this.request, this.response, apiLogger, SeriesThumbnailFactory);
return thumbnailService.getThumbnailAndResponse();
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
apiLogger.logger.error(errorStr);

this.response.writeHead(500, {
"Content-Type": "application/dicom+json"
});
return this.response.end({
code: 500,
message: "An exception occurred"
});
}
}
}

/**
*
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse} res
*/
module.exports = async function (req, res) {
let controller = new RetrieveSeriesThumbnailController(req, res);

await controller.doPipeline();
};
49 changes: 49 additions & 0 deletions api-sql/dicom-web/controller/WADO-RS/thumbnail/study.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const { Controller } = require("@root/api/controller.class");
const { ApiLogger } = require("@root/utils/logs/api-logger");
const {
ThumbnailService,
StudyThumbnailFactory
} = require("../service/thumbnail.service");



class RetrieveStudyThumbnailController extends Controller {
constructor(req, res) {
super(req, res);
}

async mainProcess() {

let apiLogger = new ApiLogger(this.request, "WADO-RS");
apiLogger.addTokenValue();

apiLogger.logger.info(`Get Study's Thumbnail [study UID: ${this.request.params.studyUID}]`);

try {
let thumbnailService = new ThumbnailService(this.request, this.response, apiLogger, StudyThumbnailFactory);
return thumbnailService.getThumbnailAndResponse();
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
apiLogger.logger.error(errorStr);

this.response.writeHead(500, {
"Content-Type": "application/dicom+json"
});
return this.response.end({
code: 500,
message: "An exception occurred"
});
}
}
}

/**
*
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse} res
*/
module.exports = async function (req, res) {
let controller = new RetrieveStudyThumbnailController(req, res);

await controller.doPipeline();
};
Loading

0 comments on commit 8fc1a0b

Please sign in to comment.