Files
DCMV/thirdparty/dcm_network/dcm_find.cpp
2022-07-08 10:04:23 +08:00

451 lines
12 KiB
C++

#include "dcm_find.h"
//--------------------------------------------------------------------------
// dcm_cfind_callback
dcm_cfind_callback::dcm_cfind_callback()
: DcmFindSCUCallback()
, extractResponse_(FEM_xmlFile)
, cancelAfterNReponses_(-1)
, outputDirectory_(".")
{
}
dcm_cfind_callback::dcm_cfind_callback(DcmFindSCUExtractMode extractResponse, int cancelAfterNResponse, const char *outputDirectory)
: DcmFindSCUCallback()
, extractResponse_(extractResponse)
, cancelAfterNReponses_(cancelAfterNResponse)
, outputDirectory_(outputDirectory)
{
}
void dcm_cfind_callback::callback(T_DIMSE_C_FindRQ *request, int &responseCount, T_DIMSE_C_FindRSP *rsp, DcmDataset *responseIdentifiers)
{
std::string outputFileName;
char rspIdsFileName[32];
if (extractResponse_ == FEM_dicomFile)
{
sprintf(rspIdsFileName, "rsp%04d.dcm", responseCount);
OFStandard::combineDirAndFilename(outputFileName, outputDirectory_, rspIdsFileName, true);
DcmFindSCU::writeToFile(outputFileName.c_str(), responseIdentifiers);
}
else if (extractResponse_ == FEM_xmlFile)
{
sprintf(rspIdsFileName, "rsp%04d.xml", responseCount);
OFStandard::combineDirAndFilename(outputFileName, outputDirectory_, rspIdsFileName, true);
DcmFindSCU::writeToXMLFile(outputFileName.c_str(), responseIdentifiers);
}
else if (extractResponse_ == FEM_singleXMLFile)
{
}
}
std::string dcm_cfind_callback::get_outputdir()
{
return outputDirectory_;
}
bool dcm_cfind_callback::verify()
{
if (extractResponse_ == DcmFindSCUExtractMode::FEM_none)
return true;
if (!OFStandard::dirExists(outputDirectory_))
{
// log >> output directory does not exist
return false;
}
else if (!OFStandard::isWriteable(outputDirectory_))
{
// log >> output directory is not writtable
return false;
}
return true;
}
//--------------------------------------------------------------------------
// dcm-cfind
////dcm_cfind::dcm_cfind()
//// : abortAssociation(false)
//// , abstractSyntax(UID_FINDPatientRootQueryRetrieveInformationModel)
//// , acse_timeout(30)
//// , blockMode(DIMSE_BLOCKING)
//// , dimse_timeout(0)
//// , maxReceivePDULength(ASC_DEFAULTMAXPDU)
//// , networkTransferSyntax(EXS_Unknown)
//// , repeatCount(1)
//// , cfind_callback(nullptr)
////
////{
//// peerIp_ = "127.0.0.1";
//// peerPort_ = 104;
//// peerTitle_ = "";
//// ourTitle_ = "";
////}
dcm_cfind::dcm_cfind(const char *peerIp, unsigned long peerPort, const char *peerTitle, const char *ourTile)
: abortAssociation(false)
, abstractSyntax(UID_FINDPatientRootQueryRetrieveInformationModel)
, acse_timeout(30)
, blockMode(DIMSE_BLOCKING)
, dimse_timeout(0)
, maxReceivePDULength(ASC_DEFAULTMAXPDU)
, networkTransferSyntax(EXS_Unknown)
, repeatCount(1)
, cfind_callback(nullptr)
{
peerIp_ = peerIp;
peerPort_ = peerPort;
peerTitle_ = peerTitle;
ourTitle_ = ourTile;
}
dcm_cfind::~dcm_cfind()
{
}
void dcm_cfind::set_asce_timeout(int timeout)
{
acse_timeout = timeout;
}
void dcm_cfind::set_dimse_timeout(int timeout)
{
dimse_timeout = timeout;
}
void dcm_cfind::set_max_received_pdu_lenght(unsigned long length)
{
maxReceivePDULength = length;
}
void dcm_cfind::set_find_callback(dcm_cfind_callback *callback)
{
cfind_callback = callback;
}
void dcm_cfind::initQueryInfo()
{
overrideKeys.clear();
overrideKeys.push_back("0008,0020="); // StudyDate
overrideKeys.push_back("0008,0050="); // AccessionNumber
overrideKeys.push_back("0010,0010="); // PatientName
overrideKeys.push_back("0010,0020="); // PatientID
overrideKeys.push_back("0010,0030="); // PatientBirthDate
overrideKeys.push_back("0010,0040="); // PatientSex
overrideKeys.push_back("0010,1010="); // PatientAge
overrideKeys.push_back("0020,000D="); // StudyInstanceUID
overrideKeys.push_back("0020,0010="); // StudyID
overrideKeys.push_back("0032,1032="); // RequestingPhysician
overrideKeys.push_back("0020,000E="); // SeriesInstanceUID
overrideKeys.push_back("0008,0060="); // Modality
overrideKeys.push_back("0020,0011="); // SeriesNumber
}
// for the purpose to get all the information we need, store a template DICOM file to contains all the information we need
// AND to return a int code to upper user, need to define globle erro code
int dcm_cfind::find_by_patient_id(std::string patient_id)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string patient_id_ = "0010,0020=";
patient_id_ += patient_id;
overrideKeys.push_back(patient_id_);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_patient_id_and_date(std::string patient_id, std::string startdate, std::string enddate)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string patient_id_ = "0010,0020=";
patient_id_ += patient_id;
overrideKeys.push_back(patient_id_);
std::string study_date_ = "0008,0020=";
if (!startdate.empty())
{
study_date_ += startdate;
study_date_ += "-";
}
if (!enddate.empty())
study_date_ += enddate;
overrideKeys.push_back(study_date_.c_str());
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_patient_name(std::string patient_name)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string patient_name_ = "0010,0010=";
patient_name_ += patient_name;
overrideKeys.push_back(patient_name_);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_patient_name_and_date(std::string patient_name, std::string startdate, std::string enddate)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string patient_name_ = "0010,0010=";
patient_name_ += patient_name;
overrideKeys.push_back(patient_name_);
std::string study_date_ = "0008,0020=";
if (!startdate.empty())
{
study_date_ += startdate;
study_date_ += "-";
}
if (!enddate.empty())
study_date_ += enddate;
overrideKeys.push_back(study_date_.c_str());
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_accession_no(std::string accession_no)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string accession_number = "0008,0050=";
accession_number += accession_no;
overrideKeys.push_back(accession_number);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_accession_no_and_date(std::string accession_no, std::string startdate, std::string enddate)
{
//abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel;
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "PATIENT";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string accession_number = "0008,0050=";
accession_number += accession_no;
overrideKeys.push_back(accession_number);
std::string study_date_ = "0008,0020=";
if (!startdate.empty())
{
study_date_ += startdate;
study_date_ += "-";
}
if (!enddate.empty())
study_date_ += enddate;
overrideKeys.push_back(study_date_.c_str());
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_study_uid(std::string study_uid)
{
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
//query_level += "STUDY";
query_level += "SERIES";
overrideKeys.push_back(query_level);
std::string study_instance_uid_ = "0020,000D=";
study_instance_uid_ += study_uid;
overrideKeys.push_back(study_instance_uid_);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_series_uid(std::string study_uid)
{
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
query_level += "SERIES";
overrideKeys.push_back(query_level);
std::string study_instance_uid_ = "0020,000D=";
study_instance_uid_ += study_uid;
overrideKeys.push_back(study_instance_uid_);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_series_uid(std::string study_uid, std::string series_uid)
{
abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel;
initQueryInfo();
std::string query_level = "0008,0052=";
query_level += "STUDY";
overrideKeys.push_back(query_level);
std::string study_instance_uid_ = "0020,000D=";
study_instance_uid_ += study_uid;
overrideKeys.push_back(study_instance_uid_);
std::string series_instance_uid_ = "0020,000E=";
series_instance_uid_ += series_uid;
overrideKeys.push_back(series_instance_uid_);
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
int dcm_cfind::find_by_timeinterval(std::string startDate, std::string endDate)
{
abstractSyntax = UID_FINDModalityWorklistInformationModel;
// Since worklist is used to get infos which
// will be used by upper user to construct user/study info,
// So we set all the infos except the filter to empty,
// and then pass them to C-Find SCP who will fill these
// value in response
initQueryInfo();
std::string scheduleStartDate = "(0040,0100)[0].(0040,0002)=";
if (!startDate.empty())
{
scheduleStartDate += startDate;
scheduleStartDate += "-";
}
if (!endDate.empty())
{
//std::string scheduleEndDate = "(0040,0100)[0].(0040,0002)=";
//scheduleEndDate += endDate;
//overrideKeys.push_back(scheduleEndDate.c_str());
scheduleStartDate += endDate;
}
overrideKeys.push_back(scheduleStartDate.c_str());
int ret = 0;
OFCondition cond = docfind();
cond == EC_Normal ? ret = 0 : ret = cond.code();
return ret;
}
// METHOD performQuery method from DCMTK sucks
OFCondition dcm_cfind::docfind()
{
OFStandard::initializeNetwork();
if (cfind_callback == nullptr)
{
// log >> No callback is provided
cfind_callback = new dcm_cfind_callback(DcmFindSCUExtractMode::FEM_xmlFile, -1, ".");
// Donnot need to verify, since the query operation should not care about property of callback
}
DcmFindSCU findscu;
OFCondition cond = findscu.initializeNetwork(acse_timeout);
if (cond.bad())
{
// log >> failed to connect scp;
return cond;
}
cond = findscu.performQuery(peerIp_, peerPort_, ourTitle_, peerTitle_, abstractSyntax,
networkTransferSyntax, blockMode, dimse_timeout, maxReceivePDULength, false, abortAssociation,
repeatCount, DcmFindSCUExtractMode::FEM_none, -1, &overrideKeys, cfind_callback, &fileNameList,
"", "");
if (cond.bad())
{
// log >> query failed
return cond;
}
cond = findscu.dropNetwork();
if (cond.bad())
{
// log >> drop network failed
return cond;
}
OFStandard::shutdownNetwork();
return cond;
}