Skip to content

Commit

Permalink
ENH: Add results checks to the visual dicom browser
Browse files Browse the repository at this point in the history
  • Loading branch information
Punzo committed Oct 18, 2023
1 parent b1b9de9 commit c2dcec9
Show file tree
Hide file tree
Showing 21 changed files with 314 additions and 149 deletions.
115 changes: 77 additions & 38 deletions Libs/DICOM/Core/ctkDICOMDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,10 @@ bool ctkDICOMDatabasePrivate::insertPatient(const ctkDICOMItem& dataset, int& db

// Check if patient is already present in the db

QString patientsName, patientID, studyInstanceUID, seriesInstanceUID;
if (!this->uidsForDataSet(dataset, patientsName, patientID, studyInstanceUID, seriesInstanceUID))
{
// error occurred, message is already logged
return false;
}
QString patientsBirthDate(dataset.GetElementAsString(DCM_PatientBirthDate));
QString patientsName, patientID, patientsBirthDate;
patientsName = dataset.GetElementAsString(DCM_PatientName);
patientID = dataset.GetElementAsString(DCM_PatientID);
patientsBirthDate = dataset.GetElementAsString(DCM_PatientBirthDate);

QSqlQuery checkPatientExistsQuery(this->Database);
checkPatientExistsQuery.prepare("SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?");
Expand Down Expand Up @@ -968,23 +965,89 @@ void ctkDICOMDatabase::insert(QList<ctkDICOMTaskResults *> taskResultsList)
bool storeFile = taskResults->copyFile();

QMap<QString, ctkDICOMItem*> datasets = taskResults->datasets();
QString patientsUID = this->patientForStudy(taskResults->studyInstanceUID());
QString patientID = taskResults->patientID();
QString patientName = this->fieldForPatient("PatientsName", patientsUID);

for(QString key : datasets.keys())
{
ctkDICOMItem* dataset = datasets.value(key);
if (!dataset)
{
continue;
}
QString patientID, patientName, studyInstanceUID, seriesInstanceUID;;
patientName = dataset->GetElementAsString(DCM_PatientName);
patientID = dataset->GetElementAsString(DCM_PatientID);
studyInstanceUID = dataset->GetElementAsString(DCM_StudyInstanceUID);
seriesInstanceUID = dataset->GetElementAsString(DCM_SeriesInstanceUID);

if (patientID.isEmpty())
{
if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryPatients)
{
patientID = key;
}
else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryStudies ||
typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries ||
typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveStudy ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance)
{
patientID = taskResults->patientID();
}

dataset->SetElementAsString(DCM_PatientID, patientID);
}

if (studyInstanceUID.isEmpty())
{
if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryStudies)
{
studyInstanceUID = key;
}
else if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries ||
typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveStudy ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance)
{
studyInstanceUID = taskResults->studyInstanceUID();
}

dataset->SetElementAsString(DCM_StudyInstanceUID, studyInstanceUID);
}

if (seriesInstanceUID.isEmpty())
{
if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries)
{
seriesInstanceUID = key;
}
else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSeries ||
typeOfTask == ctkDICOMTaskResults::TaskType::RetrieveSOPInstance)
{
seriesInstanceUID = taskResults->seriesInstanceUID();
}

dataset->SetElementAsString(DCM_SeriesInstanceUID, seriesInstanceUID);
}

if (patientID.isEmpty())
{
logger.error("ctkDICOMDatabase::insert: dataset has no patientID");
continue;
}

if (patientName.isEmpty() && !patientID.isEmpty())
{
patientName = patientID;
dataset->SetElementAsString(DCM_PatientName, patientName);
}

if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances)
{
filePath = "server://" + taskResults->connectionName() +
"_" + taskResults->studyInstanceUID() +
"_" + taskResults->seriesInstanceUID() +
"_" + studyInstanceUID +
"_" + seriesInstanceUID +
"_" + key;
}

Expand Down Expand Up @@ -1024,26 +1087,6 @@ void ctkDICOMDatabase::insert(QList<ctkDICOMTaskResults *> taskResultsList)
}
}

if (typeOfTask == ctkDICOMTaskResults::TaskType::QuerySeries)
{
dataset->SetElementAsString(DCM_PatientName, patientName);
dataset->SetElementAsString(DCM_PatientID, patientID);
}
else if (typeOfTask == ctkDICOMTaskResults::TaskType::QueryInstances)
{
dataset->SetElementAsString(DCM_PatientName, patientName);
dataset->SetElementAsString(DCM_PatientID, patientID);
dataset->SetElementAsString(DCM_StudyInstanceUID, taskResults->studyInstanceUID());
}

// Verify that minimum required fields are present
QString patientsName, studyInstanceUID, seriesInstanceUID;
if (!d->uidsForDataSet(*dataset, patientsName, patientID, studyInstanceUID, seriesInstanceUID))
{
logger.error("Failed to insert dataset into database (required fields missing)");
continue;
}

if (filePath.contains("server://") && storeFile)
{
filePath = "";
Expand All @@ -1059,7 +1102,7 @@ void ctkDICOMDatabase::insert(QList<ctkDICOMTaskResults *> taskResultsList)
}
}

if (d->insertPatientStudySeries(*dataset, patientID, patientsName))
if (d->insertPatientStudySeries(*dataset, patientID, patientName))
{
databaseWasChanged = true;
}
Expand Down Expand Up @@ -1125,10 +1168,6 @@ void ctkDICOMDatabase::insert(QList<ctkDICOMTaskResults *> taskResultsList)
}
}
}

patientsUID = this->patientForStudy(taskResults->studyInstanceUID());
patientID = taskResults->patientID();
patientName = this->fieldForPatient("PatientsName", patientsUID);
}

d->Database.commit();
Expand Down
23 changes: 10 additions & 13 deletions Libs/DICOM/Core/ctkDICOMQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ ctkDICOMQueryPrivate::ctkDICOMQueryPrivate()
this->Canceled = false;
this->MaximumPatientsQuery = 2;

this->SCU.setACSETimeout(3);
this->SCU.setConnectionTimeout(3);
this->SCU.setACSETimeout(10);
this->SCU.setConnectionTimeout(10);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -601,7 +601,7 @@ bool ctkDICOMQuery::query(ctkDICOMDatabase& database)
}

//----------------------------------------------------------------------------
bool ctkDICOMQuery::queryPatients(const QString &taskUID)
bool ctkDICOMQuery::queryPatients()
{
Q_D(ctkDICOMQuery);
// In the following, we emit progress(int) after progress(QString), this
Expand Down Expand Up @@ -678,7 +678,7 @@ bool ctkDICOMQuery::queryPatients(const QString &taskUID)
ctkDICOMTaskResults* taskResults = new ctkDICOMTaskResults;
taskResults->setTypeOfTask(ctkDICOMTaskResults::TaskType::QueryPatients);
taskResults->setConnectionName(d->ConnectionName);
taskResults->setTaskUID(taskUID);
taskResults->setTaskUID(d->TaskUID);

QMap<QString, DcmItem *> datasetsMap;
OFList<QRResponse *> responses;
Expand Down Expand Up @@ -728,8 +728,7 @@ bool ctkDICOMQuery::queryPatients(const QString &taskUID)
}

//----------------------------------------------------------------------------
bool ctkDICOMQuery::queryStudies(const QString& taskUID,
const QString& patientID)
bool ctkDICOMQuery::queryStudies(const QString& patientID)
{
Q_D(ctkDICOMQuery);
// In the following, we emit progress(int) after progress(QString), this
Expand Down Expand Up @@ -809,7 +808,7 @@ bool ctkDICOMQuery::queryStudies(const QString& taskUID,
taskResults->setTypeOfTask(ctkDICOMTaskResults::TaskType::QueryStudies);
taskResults->setPatientID(patientID.toStdString().c_str());
taskResults->setConnectionName(d->ConnectionName);
taskResults->setTaskUID(taskUID);
taskResults->setTaskUID(d->TaskUID);

QMap<QString, DcmItem *> datasetsMap;

Expand Down Expand Up @@ -851,8 +850,7 @@ bool ctkDICOMQuery::queryStudies(const QString& taskUID,
}

//----------------------------------------------------------------------------
bool ctkDICOMQuery::querySeries(const QString& taskUID,
const QString& patientID,
bool ctkDICOMQuery::querySeries(const QString& patientID,
const QString& studyInstanceUID)
{
Q_D(ctkDICOMQuery);
Expand Down Expand Up @@ -931,7 +929,7 @@ bool ctkDICOMQuery::querySeries(const QString& taskUID,
taskResults->setPatientID(patientID.toStdString().c_str());
taskResults->setStudyInstanceUID(studyInstanceUID.toStdString().c_str());
taskResults->setConnectionName(d->ConnectionName);
taskResults->setTaskUID(taskUID);
taskResults->setTaskUID(d->TaskUID);

QMap<QString, DcmItem *> datasetsMap;

Expand Down Expand Up @@ -973,8 +971,7 @@ bool ctkDICOMQuery::querySeries(const QString& taskUID,
}

//----------------------------------------------------------------------------
bool ctkDICOMQuery::queryInstances(const QString& taskUID,
const QString& patientID,
bool ctkDICOMQuery::queryInstances(const QString& patientID,
const QString& studyInstanceUID,
const QString& seriesInstanceUID)
{
Expand Down Expand Up @@ -1052,7 +1049,7 @@ bool ctkDICOMQuery::queryInstances(const QString& taskUID,
taskResults->setStudyInstanceUID(studyInstanceUID.toStdString().c_str());
taskResults->setSeriesInstanceUID(seriesInstanceUID.toStdString().c_str());
taskResults->setConnectionName(d->ConnectionName);
taskResults->setTaskUID(taskUID);
taskResults->setTaskUID(d->TaskUID);

QMap<QString, DcmItem *> datasetsMap;

Expand Down
13 changes: 5 additions & 8 deletions Libs/DICOM/Core/ctkDICOMQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMQuery : public QObject
/// 0 by default.
void setPort(int port);
int port() const;
/// connection timeout, default 3 sec.
/// connection timeout, default 10 sec.
void setConnectionTimeout(const int timeout);
int connectionTimeout() const;
/// maximum number of responses allowed in one query
Expand All @@ -93,25 +93,22 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMQuery : public QObject

/// Utility method to query a remote DICOM Image Store SCP only at patient level.
/// You must at least set the host and port before calling query()
Q_INVOKABLE bool queryPatients(const QString& taskUID);
Q_INVOKABLE bool queryPatients();

/// Utility method to query a remote DICOM Image Store SCP only at study level.
/// You must at least set the host and port before calling query()
Q_INVOKABLE bool queryStudies(const QString& taskUID,
const QString& patientID);
Q_INVOKABLE bool queryStudies(const QString& patientID);

/// Utility method to query a remote DICOM Image Store SCP only at series level
/// given a studyInstanceUID.
/// You must at least set the host and port before calling query()
Q_INVOKABLE bool querySeries(const QString& taskUID,
const QString& patientID,
Q_INVOKABLE bool querySeries(const QString& patientID,
const QString& studyInstanceUID);

/// Utility method to query a remote DICOM Image Store SCP only at instance level
/// given a studyInstanceUID and seriesInstanceUID.
/// You must at least set the host and port before calling query()
Q_INVOKABLE bool queryInstances(const QString& taskUID,
const QString& patientID,
Q_INVOKABLE bool queryInstances(const QString& patientID,
const QString& studyInstanceUID,
const QString& seriesInstanceUID);

Expand Down
11 changes: 4 additions & 7 deletions Libs/DICOM/Core/ctkDICOMQueryTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,25 +127,23 @@ void ctkDICOMQueryTask::run()
switch(d->QueryLevel)
{
case DICOMLevel::Patients:
if (!d->Query->queryPatients(this->taskUID()))
if (!d->Query->queryPatients())
{
this->setIsFinished(true);
emit canceled();
return;
}
break;
case DICOMLevel::Studies:
if (!d->Query->queryStudies(this->taskUID(),
d->PatientID))
if (!d->Query->queryStudies(d->PatientID))
{
this->setIsFinished(true);
emit canceled();
return;
}
break;
case DICOMLevel::Series:
if (!d->Query->querySeries(this->taskUID(),
d->PatientID,
if (!d->Query->querySeries(d->PatientID,
d->StudyInstanceUID))
{
this->setIsFinished(true);
Expand All @@ -154,8 +152,7 @@ void ctkDICOMQueryTask::run()
}
break;
case DICOMLevel::Instances:
if (!d->Query->queryInstances(this->taskUID(),
d->PatientID,
if (!d->Query->queryInstances(d->PatientID,
d->StudyInstanceUID,
d->SeriesInstanceUID))
{
Expand Down
Loading

0 comments on commit c2dcec9

Please sign in to comment.