Skip to content

Commit

Permalink
feat: add DIMSE study C-Find
Browse files Browse the repository at this point in the history
  • Loading branch information
Chinlinlee committed Aug 20, 2023
1 parent dad9efa commit 8299656
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 17 deletions.
83 changes: 66 additions & 17 deletions dimse/c-find.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,73 @@ const { default: EnumSet } = require("@java-wrapper/java/util/EnumSet");
const { default: BasicModCFindSCP } = require("@java-wrapper/org/github/chinlinlee/dcm777/net/BasicModCFindSCP");
const { createCFindSCPInjectProxy } = require("@java-wrapper/org/github/chinlinlee/dcm777/net/CFindSCPInject");
const { JsPatientQueryTask } = require("./patientQueryTask");
const { JsStudyQueryTask } = require("./studyQueryTask");

const PATIENT_ROOT_LEVELS = EnumSet.ofSync(
QueryRetrieveLevel2.PATIENT,
QueryRetrieveLevel2.STUDY,
QueryRetrieveLevel2.SERIES,
QueryRetrieveLevel2.IMAGE
);

const STUDY_ROOT_LEVELS = EnumSet.ofSync(
QueryRetrieveLevel2.STUDY,
QueryRetrieveLevel2.SERIES,
QueryRetrieveLevel2.IMAGE
);

const PATIENT_STUDY_ONLY_LEVELS = EnumSet.ofSync(
QueryRetrieveLevel2.PATIENT,
QueryRetrieveLevel2.STUDY
);

class JsCFindScp {
constructor() { }

getPatientRootLevel() {
const cFindScpInject = createCFindSCPInjectProxy(this.getCFindScpInjectProxyMethods(), {
keepAsDaemon: true
});
let basicModCFindSCP = new BasicModCFindSCP(
cFindScpInject,
UID.PatientRootQueryRetrieveInformationModelFind,
PATIENT_ROOT_LEVELS
);

this.scpObj = basicModCFindSCP;
return basicModCFindSCP;
}

getStudyRootLevel() {
const cFindScpInject = createCFindSCPInjectProxy(this.getCFindScpInjectProxyMethods(), {
keepAsDaemon: true
});
let basicModCFindSCP = new BasicModCFindSCP(
cFindScpInject,
UID.StudyRootQueryRetrieveInformationModelFind,
STUDY_ROOT_LEVELS
);

this.scpObj = basicModCFindSCP;
return basicModCFindSCP;
}

getPatientStudyOnlyLevel() {
const cFindScpInject = createCFindSCPInjectProxy(this.getCFindScpInjectProxyMethods(), {
keepAsDaemon: true
});

let basicModCFindSCP = new BasicModCFindSCP(
cFindScpInject,
UID.PatientStudyOnlyQueryRetrieveInformationModelFind,
PATIENT_STUDY_ONLY_LEVELS
);

this.scpObj = basicModCFindSCP;
return basicModCFindSCP;
}

getCFindScpInjectProxyMethods() {
/**
* @type { import("@java-wrapper/org/github/chinlinlee/dcm777/net/CFindSCPInject").CFindSCPInjectInterface }
*/
Expand All @@ -38,31 +99,19 @@ class JsCFindScp {
},
calculateMatches: async (as, pc, rq, keys) => {
try {
let level = await basicModCFindSCP.getQrLevel(as, pc, rq, keys);
let level = await this.scpObj.getQrLevel(as, pc, rq, keys);
if (await level.compareTo(QueryRetrieveLevel2.PATIENT) === 0) {
return await (new JsPatientQueryTask(as, pc, rq, keys)).get();
} else if (await level.compareTo(QueryRetrieveLevel2.STUDY) === 0) {
return await (new JsStudyQueryTask(as, pc, rq, keys)).get();
}
} catch(e) {
} catch (e) {
console.error(e);
}
}
};

const cFindScpInject = createCFindSCPInjectProxy(cFindScpInjectProxyMethods, {
keepAsDaemon: true
});
let basicModCFindSCP = new BasicModCFindSCP(
cFindScpInject,
UID.PatientRootQueryRetrieveInformationModelFind,
EnumSet.ofSync(
QueryRetrieveLevel2.PATIENT,
QueryRetrieveLevel2.STUDY,
QueryRetrieveLevel2.SERIES,
QueryRetrieveLevel2.IMAGE
)
);

return basicModCFindSCP;
return cFindScpInjectProxyMethods;
}
}

Expand Down
1 change: 1 addition & 0 deletions dimse/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class DcmQrScp {
let jsCStoreScp = new JsCStoreScp();
await dicomServiceRegistry.addDicomService(jsCStoreScp.get());
await dicomServiceRegistry.addDicomService(new JsCFindScp().getPatientRootLevel());
await dicomServiceRegistry.addDicomService(new JsCFindScp().getStudyRootLevel());
return dicomServiceRegistry;
}

Expand Down
97 changes: 97 additions & 0 deletions dimse/studyQueryTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const _ = require("lodash");

const { StudyQueryTask } = require("@chinlinlee/dcm777/net/StudyQueryTask");
const { JsPatientQueryTask } = require("./patientQueryTask");
const { default: Tag } = require("@dcm4che/data/Tag");
const { createQueryTaskInjectProxy } = require("@java-wrapper/org/github/chinlinlee/dcm777/net/QueryTaskInject");
const { StudyQueryTaskInjectInterface, createStudyQueryTaskInjectProxy } = require("@java-wrapper/org/github/chinlinlee/dcm777/net/StudyQueryTaskInject");
const { DimseQueryBuilder } = require("./queryBuilder");
const dicomStudyModel = require("@models/mongodb/models/dicomStudy");

class JsStudyQueryTask extends JsPatientQueryTask {
constructor(as, pc, rq, keys) {
super(as, pc, rq, keys);

this.studyInit = false;
this.studyCursor = false;
this.study = null;
this.studyAttr = null;
}

async get() {
let studyQueryTask = await StudyQueryTask.newInstanceAsync(
this.as,
this.pc,
this.rq,
this.keys,
this.getQueryTaskInjectProxy(),
this.getPatientQueryTaskInjectProxy(),
this.getStudyQueryTaskInjectProxy()
);

return studyQueryTask;
}

getQueryTaskInjectProxy() {
/** @type { QueryTaskInjectInterface } */
this.studyBasicQueryTaskInjectMethods = {
hasMoreMatches: () => {
return !_.isNull(this.studyAttr);
},
nextMatch: async () => {
let tempRecord = this.studyAttr;
await this.studyQueryTaskInjectMethods.wrappedFindNextStudy();
return tempRecord;
},
adjust: async (match) => {
return await this.patientAdjust(match);
}
};

if (!this.queryTaskInjectProxy) {
this.queryTaskInjectProxy = createQueryTaskInjectProxy(this.studyBasicQueryTaskInjectMethods);
}

return this.queryTaskInjectProxy;
}

getStudyQueryTaskInjectProxy() {
/** @type { StudyQueryTaskInjectInterface } */
this.studyQueryTaskInjectMethods = {
wrappedFindNextStudy: async () => {
await this.studyQueryTaskInjectMethods.findNextStudy();
},
getStudy: async () => {
let queryBuilder = new DimseQueryBuilder(this.keys, "study");
let normalQuery = await queryBuilder.toNormalQuery();
let mongoQuery = await queryBuilder.getMongoQuery(normalQuery);

if (_.isNull(this.studyAttr) && !this.studyInit) {
let returnKeys = this.getReturnKeys(normalQuery);

this.studyCursor = await dicomStudyModel.getDimseResultCursor({
...mongoQuery.$match
}, returnKeys);

this.study = await this.studyCursor.next();
this.studyAttr = this.study ? await this.study.getAttributes() : null;
} else {
this.study = await this.studyCursor.next();
this.studyAttr = this.study ? await this.study.getAttributes() : null;
}
},
findNextStudy: async () => {
await this.studyQueryTaskInjectMethods.getStudy();
return !_.isNull(this.studyAttr);
}
};

if (!this.studyQueryTaskInjectProxy) {
this.studyQueryTaskInjectProxy = createStudyQueryTaskInjectProxy(this.studyQueryTaskInjectMethods);
}

return this.studyQueryTaskInjectProxy;
}
}

module.exports.JsStudyQueryTask = JsStudyQueryTask;
Binary file not shown.
17 changes: 17 additions & 0 deletions models/mongodb/models/dicomStudy.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
const { raccoonConfig } = require("../../../config-class");
const { dictionary } = require("@models/DICOM/dicom-tags-dic");
const { logger } = require("@root/utils/logs/log");
const { Common } = require("@java-wrapper/org/github/chinlinlee/dcm777/net/common/Common");

let dicomStudySchema = new mongoose.Schema(
{
Expand Down Expand Up @@ -50,6 +51,22 @@ let dicomStudySchema = new mongoose.Schema(
force: true,
recursive: true
});
},
getAttributes: async function() {
let study = this.toObject();
delete study._id;
delete study.id;

let jsonStr = JSON.stringify(study);
return await Common.getAttributesFromJsonString(jsonStr);
}
},
statics: {
getDimseResultCursor: async function (query, keys) {
return mongoose.model("dicomStudy").find(query, keys).setOptions({
strictQuery: false
})
.cursor();
}
},
timestamps: true
Expand Down

0 comments on commit 8299656

Please sign in to comment.