Skip to content

Commit

Permalink
feat: add new QIDO-RS transations
Browse files Browse the repository at this point in the history
- Refactoring, move the get DICOM Json of
each level to `QIDO-RS.service.js` file
- Add query All Instances, /instances
- Add query All Series, /series
- Add query Study's Instances, /studies/{study}/instances
  • Loading branch information
Chinlinlee committed May 9, 2022
1 parent e549625 commit 70efb15
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 161 deletions.
65 changes: 65 additions & 0 deletions api/dicom-web/controller/QIDO-RS/queryAllInstances.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const _ = require("lodash");
const {
convertAllQueryToDICOMTag,
getInstanceDicomJson
} = require("./service/QIDO-RS.service");
const { logger } = require("../../../../utils/log");

/**
* @openapi
* /dicom-web/studies:
* get:
* tags:
* - QIDO-RS
* description: Query for studies
* parameters:
* - $ref: "#/components/parameters/StudyDate"
* - $ref: "#/components/parameters/StudyTime"
* - $ref: "#/components/parameters/AccessionNumber"
* - $ref: "#/components/parameters/ModalitiesInStudy"
* - $ref: "#/components/parameters/ReferringPhysicianName"
* - $ref: "#/components/parameters/PatientName"
* - $ref: "#/components/parameters/PatientID"
* - $ref: "#/components/parameters/StudyID"
* responses:
* 200:
* description: Query successfully
*/

/**
*
* @param {import('http').IncomingMessage} req
* @param {import('http').ServerResponse} res
*/
module.exports = async function (req, res) {
logger.info(
`[QIDO-RS] [Query all instances]`
);
try {
let limit = parseInt(req.query.limit) || 100;
let skip = parseInt(req.query.offset) || 0;
delete req.query["limit"];
delete req.query["offset"];
let query = _.cloneDeep(req.query);
let queryKeys = Object.keys(query).sort();
for (let i = 0; i < queryKeys.length; i++) {
let queryKey = queryKeys[i];
if (!query[queryKey]) delete query[queryKey];
}

let dicomTagQuery = convertAllQueryToDICOMTag(query);
let studiesJson = await getInstanceDicomJson(
dicomTagQuery,
limit,
skip,
req
);
res.writeHead(200, {
"Content-Type": "application/dicom+json"
});
res.end(JSON.stringify(studiesJson.data));
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[QIDO-RS] [Error: ${errorStr}]`);
}
};
67 changes: 67 additions & 0 deletions api/dicom-web/controller/QIDO-RS/queryAllSeries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const _ = require("lodash");
const mongoose = require("mongoose");
const moment = require("moment");
const {
convertAllQueryToDICOMTag,
getSeriesDicomJson
} = require("./service/QIDO-RS.service");
const { logger } = require("../../../../utils/log");

/**
* @openapi
* /dicom-web/studies:
* get:
* tags:
* - QIDO-RS
* description: Query for studies
* parameters:
* - $ref: "#/components/parameters/StudyDate"
* - $ref: "#/components/parameters/StudyTime"
* - $ref: "#/components/parameters/AccessionNumber"
* - $ref: "#/components/parameters/ModalitiesInStudy"
* - $ref: "#/components/parameters/ReferringPhysicianName"
* - $ref: "#/components/parameters/PatientName"
* - $ref: "#/components/parameters/PatientID"
* - $ref: "#/components/parameters/StudyID"
* responses:
* 200:
* description: Query successfully
*/

/**
*
* @param {import('http').IncomingMessage} req
* @param {import('http').ServerResponse} res
*/
module.exports = async function (req, res) {
logger.info(
`[QIDO-RS] [Query all series]`
);
try {
let limit = parseInt(req.query.limit) || 100;
let skip = parseInt(req.query.offset) || 0;
delete req.query["limit"];
delete req.query["offset"];
let query = _.cloneDeep(req.query);
let queryKeys = Object.keys(query).sort();
for (let i = 0; i < queryKeys.length; i++) {
let queryKey = queryKeys[i];
if (!query[queryKey]) delete query[queryKey];
}

let dicomTagQuery = convertAllQueryToDICOMTag(query);
let studiesJson = await getSeriesDicomJson(
dicomTagQuery,
limit,
skip,
req
);
res.writeHead(200, {
"Content-Type": "application/dicom+json"
});
res.end(JSON.stringify(studiesJson.data));
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[QIDO-RS] [Error: ${errorStr}]`);
}
};
49 changes: 6 additions & 43 deletions api/dicom-web/controller/QIDO-RS/queryAllStudies.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ const mongoose = require("mongoose");
const moment = require("moment");
const {
convertAllQueryToDICOMTag,
convertRequestQueryToMongoQuery,
getStudyLevelFields,
sortObjByFieldKey
getStudyDicomJson
} = require("./service/QIDO-RS.service");
const { logger } = require("../../../../utils/log");

Expand Down Expand Up @@ -36,9 +34,12 @@ const { logger } = require("../../../../utils/log");
* @param {import('http').ServerResponse} res
*/
module.exports = async function (req, res) {
logger.info(
`[QIDO-RS] [Query instance Level, Study UID: ${req.params.studyUID}, Series UID: ${req.params.seriesUID}]`
);
try {
let limit = req.query.limit || 100;
let skip = req.query.offset || 0;
let limit = parseInt(req.query.limit) || 100;
let skip = parseInt(req.query.offset) || 0;
delete req.query["limit"];
delete req.query["offset"];
let query = _.cloneDeep(req.query);
Expand All @@ -65,41 +66,3 @@ module.exports = async function (req, res) {
}
};

async function getStudyDicomJson(iQuery, limit, skip, req) {
logger.info(`[QIDO-RS] [Query Study Level]`);
let result = {
data: "",
status: false
};
let protocol = req.secure ? "https" : "http";
let retrieveUrl = `${protocol}://${req.headers.host}/${process.env.DICOMWEB_API}/studies`;
try {
iQuery = await convertRequestQueryToMongoQuery(iQuery);
// iQuery = iQuery.$match;
logger.info(`[QIDO-RS] [Query for MongoDB: ${JSON.stringify(iQuery)}]`);
let studyFields = getStudyLevelFields();
let docs = await mongoose
.model("dicomStudy")
.find(iQuery.$match, studyFields)
.limit(limit)
.skip(skip)
.exec();
result.data = docs.map((v) => {
let obj = v.toObject();
delete obj._id;
delete obj.id;
obj["00081190"] = {
vr: "UR",
Value: [`${retrieveUrl}/${obj["0020000D"]["Value"][0]}`]
};
return sortObjByFieldKey(obj);
});
result.status = true;
return result;
} catch (e) {
console.error("get Study DICOM error", e);
result.data = e;
result.status = false;
return result;
}
}
68 changes: 68 additions & 0 deletions api/dicom-web/controller/QIDO-RS/queryStudies-Instances.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const _ = require("lodash");
const {
convertAllQueryToDICOMTag,
getInstanceDicomJson
} = require("./service/QIDO-RS.service");
const { logger } = require("../../../../utils/log");

/**
* @openapi
* /dicom-web/studies/{studyUID}/series:
* get:
* tags:
* - QIDO-RS
* description: Query for studies
* parameters:
* - $ref: "#/components/parameters/studyUID"
* - $ref: "#/components/parameters/StudyDate"
* - $ref: "#/components/parameters/StudyTime"
* - $ref: "#/components/parameters/AccessionNumber"
* - $ref: "#/components/parameters/ModalitiesInStudy"
* - $ref: "#/components/parameters/ReferringPhysicianName"
* - $ref: "#/components/parameters/PatientName"
* - $ref: "#/components/parameters/PatientID"
* - $ref: "#/components/parameters/StudyID"
* - $ref: "#/components/parameters/Modality"
* - $ref: "#/components/parameters/SeriesNumber"
* responses:
* 200:
* description: Query successfully
*/

/**
*
* @param {import('http').IncomingMessage} req
* @param {import('http').ServerResponse} res
*/
module.exports = async function (req, res) {
logger.info(
`[QIDO-RS] [Query instances in study, Study UID: ${req.params.studyUID}]`
);
try {
let limit = parseInt(req.query.limit) || 100;
let skip = parseInt(req.query.offset) || 0;
delete req.query["limit"];
delete req.query["offset"];
let query = _.cloneDeep(req.query);
let queryKeys = Object.keys(query).sort();
for (let i = 0; i < queryKeys.length; i++) {
let queryKey = queryKeys[i];
if (!query[queryKey]) delete query[queryKey];
}

let dicomTagQuery = convertAllQueryToDICOMTag(query);
let studiesJson = await getInstanceDicomJson(
dicomTagQuery,
limit,
skip,
req
);
res.writeHead(200, {
"Content-Type": "application/dicom+json"
});
res.end(JSON.stringify(studiesJson.data));
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[QIDO-RS] [Error: ${errorStr}]`);
}
};
66 changes: 6 additions & 60 deletions api/dicom-web/controller/QIDO-RS/queryStudies-Series-Instance.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
const _ = require("lodash");
const mongoose = require("mongoose");
const {
convertAllQueryToDICOMTag,
convertRequestQueryToMongoQuery,
getStudyLevelFields,
getSeriesLevelFields,
getInstanceLevelFields,
sortObjByFieldKey
getInstanceDicomJson
} = require("./service/QIDO-RS.service");
const { logger } = require("../../../../utils/log");

Expand Down Expand Up @@ -40,9 +35,12 @@ const { logger } = require("../../../../utils/log");
* @param {import('http').ServerResponse} res
*/
module.exports = async function (req, res) {
logger.info(
`[QIDO-RS] [Query instance Level, Study UID: ${req.params.studyUID}, Series UID: ${req.params.seriesUID}]`
);
try {
let limit = req.query.limit || 100;
let skip = req.query.offset || 0;
let limit = parseInt(req.query.limit) || 100;
let skip = parseInt(req.query.offset) || 0;
delete req.query["limit"];
delete req.query["offset"];
let query = _.cloneDeep(req.query);
Expand All @@ -68,55 +66,3 @@ module.exports = async function (req, res) {
logger.error(`[QIDO-RS] [Error: ${errorStr}]`);
}
};

async function getInstanceDicomJson(iQuery, limit, skip, req) {
logger.info(
`[QIDO-RS] [Query instance Level, Study UID: ${req.params.studyUID}, Series UID: ${req.params.seriesUID}]`
);
let result = {
data: "",
status: false
};
let protocol = req.secure ? "https" : "http";
let retrieveUrl = `${protocol}://${req.headers.host}/${process.env.DICOMWEB_API}/studies`;
try {
iQuery = await convertRequestQueryToMongoQuery(iQuery);
let query = {
...req.params,
...iQuery.$match
};
logger.info(`[QIDO-RS] [Query for MongoDB: ${JSON.stringify(query)}]`);
let studyFields = getStudyLevelFields();
let seriesFields = getSeriesLevelFields();
let instanceFields = getInstanceLevelFields();
let docs = await mongoose
.model("dicom")
.find(query, {
...studyFields,
...seriesFields,
...instanceFields
})
.limit(limit)
.skip(skip)
.exec();
result.data = docs.map((v) => {
let obj = v.toObject();
delete obj._id;
delete obj.id;
obj["00081190"] = {
vr: "UR",
Value: [
`${retrieveUrl}/${obj["0020000D"]["Value"][0]}/series/${obj["0020000E"]["Value"][0]}/instance/${obj["00080016"]["Value"][0]}`
]
};
return sortObjByFieldKey(obj);
});
result.status = true;
return result;
} catch (e) {
console.error("get Series DICOM error", e);
result.data = e;
result.status = false;
return result;
}
}
Loading

0 comments on commit 70efb15

Please sign in to comment.