Browse Source

Major rework of ctkDICOMDatabase (WIP)

Still produces a few warnings that point to interface issues that have to be resolved.
Also look for TODO in the source code.
Marco Nolden 13 years ago
parent
commit
7dfdf10144
2 changed files with 251 additions and 492 deletions
  1. 248 491
      Libs/DICOM/Core/ctkDICOMDatabase.cpp
  2. 3 1
      Libs/DICOM/Core/ctkDICOMDatabase.h

+ 248 - 491
Libs/DICOM/Core/ctkDICOMDatabase.cpp

@@ -37,6 +37,7 @@
 // ctkDICOM includes
 #include "ctkDICOMDatabase.h"
 #include "ctkDICOMAbstractThumbnailGenerator.h"
+#include "ctkDICOMDataset.h"
 
 #include "ctkLogger.h"
 
@@ -89,11 +90,11 @@ public:
   
   /// these are for optimizing the import of image sequences
   /// since most information are identical for all slices
-  OFString lastPatientID;
-  OFString lastPatientsName;
-  OFString lastPatientsBirthDate;
-  OFString lastStudyInstanceUID;
-  OFString lastSeriesInstanceUID;
+  QString lastPatientID;
+  QString lastPatientsName;
+  QString lastPatientsBirthDate;
+  QString lastStudyInstanceUID;
+  QString lastSeriesInstanceUID;
   int lastPatientUID;
 };
 
@@ -325,12 +326,12 @@ QStringList ctkDICOMDatabase::patients()
 }
 
 //------------------------------------------------------------------------------
-QStringList ctkDICOMDatabase::studiesForPatient(QString patientUID)
+QStringList ctkDICOMDatabase::studiesForPatient(QString dbPatientID)
 {
   Q_D(ctkDICOMDatabase);
   QSqlQuery query(d->Database);
   query.prepare ( "SELECT StudyInstanceUID FROM Studies WHERE PatientsUID = ?" );
-  query.bindValue ( 0, patientUID );
+  query.bindValue ( 0, dbPatientID );
   query.exec();
   QStringList result;
   while (query.next()) 
@@ -438,235 +439,303 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset ) {
 */
 
 //------------------------------------------------------------------------------
-void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool generateThumbnail)
+void ctkDICOMDatabase::insert( DcmDataset *dataset, bool storeFile, bool generateThumbnail)
 {
-  Q_D(ctkDICOMDatabase);
-
   if (!dataset)
-    {
+  {
     return;
-    }
+  }
+  ctkDICOMDataset ctkDataset;
+  ctkDataset.InitializeFromDataset(dataset);
+  this->insert(ctkDataset,storeFile,generateThumbnail);
+}
+
+void ctkDICOMDatabase::insert( const ctkDICOMDataset& ctkDataset, bool storeFile, bool generateThumbnail)
+{
+  Q_D(ctkDICOMDatabase);
+
+
+
   // Check to see if the file has already been loaded
-  OFString sopInstanceUID ;
-  dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);
+  // TODO:
+  // It could make sense to actually remove the dataset and re-add it. This needs the remove
+  // method we still have to write.
+  //
+
+  QString sopInstanceUID ( ctkDataset.GetElementAsString(DCM_SOPInstanceUID) );
 
   QSqlQuery fileExists ( d->Database );
   fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == ?");
-  fileExists.bindValue(0,QString(sopInstanceUID.c_str()));
+  fileExists.bindValue(0,sopInstanceUID);
   fileExists.exec();
   if ( fileExists.next() && QFileInfo(fileExists.value(1).toString()).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) )
-    {
+  {
     logger.debug ( "File " + fileExists.value(1).toString() + " already added" );
     return;
-    }
-
-  OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex,
-    patientComments, patientsAge;
-
-  OFString studyInstanceUID, studyID, studyDate, studyTime,
-    accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription;
-
-  OFString seriesInstanceUID, seriesDate, seriesTime,
-    seriesDescription, bodyPartExamined, frameOfReferenceUID,
-    contrastAgent, scanningSequence;
-  OFString instanceNumber;
-
-  Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
+  }
 
   //If the following fields can not be evaluated, cancel evaluation of the DICOM file
-  dataset->findAndGetOFString(DCM_PatientName, patientsName);
-  dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
-  dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);
-  dataset->findAndGetOFString(DCM_PatientID, patientID);
-
-
-  dataset->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate);
-  dataset->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime);
-  dataset->findAndGetOFString(DCM_PatientSex, patientsSex);
-  dataset->findAndGetOFString(DCM_PatientAge, patientsAge);
-  dataset->findAndGetOFString(DCM_PatientComments, patientComments);
-  dataset->findAndGetOFString(DCM_StudyID, studyID);
-  dataset->findAndGetOFString(DCM_StudyDate, studyDate);
-  dataset->findAndGetOFString(DCM_StudyTime, studyTime);
-  dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
-  dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
-  dataset->findAndGetOFString(DCM_InstitutionName, institutionName);
-  dataset->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName);
-  dataset->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician);
-  dataset->findAndGetOFString(DCM_StudyDescription, studyDescription);
-
-  dataset->findAndGetOFString(DCM_SeriesDate, seriesDate);
-  dataset->findAndGetOFString(DCM_SeriesTime, seriesTime);
-  dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
-  dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
-  dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
-  dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
-  dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
-
-  dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
-  dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
-  dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber);
-  dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);
+  QString patientsName(ctkDataset.GetElementAsString(DCM_PatientName) );
+  QString studyInstanceUID(ctkDataset.GetElementAsString(DCM_StudyInstanceUID) );
+  QString seriesInstanceUID(ctkDataset.GetElementAsString(DCM_SeriesInstanceUID) );
+  QString patientID(ctkDataset.GetElementAsString(DCM_PatientID) );
+  if ( patientsName.isEmpty() || studyInstanceUID.isEmpty() || seriesInstanceUID.isEmpty() || patientID.isEmpty() )
+  {
+    logger.error("Dataset is missing necessary information!");
+    return;
+  } 
+
+  QString patientsBirthDate(ctkDataset.GetElementAsString(DCM_PatientBirthDate) );
+  QString patientsBirthTime(ctkDataset.GetElementAsString(DCM_PatientBirthTime) );
+  QString patientsSex(ctkDataset.GetElementAsString(DCM_PatientSex) );
+  QString patientsAge(ctkDataset.GetElementAsString(DCM_PatientAge) );
+  QString patientComments(ctkDataset.GetElementAsString(DCM_PatientComments) );
+  QString studyID(ctkDataset.GetElementAsString(DCM_StudyID) );
+  QString studyDate(ctkDataset.GetElementAsString(DCM_StudyDate) );
+  QString studyTime(ctkDataset.GetElementAsString(DCM_StudyTime) );
+  QString accessionNumber(ctkDataset.GetElementAsString(DCM_AccessionNumber) );
+  QString modalitiesInStudy(ctkDataset.GetElementAsString(DCM_ModalitiesInStudy) );
+  QString institutionName(ctkDataset.GetElementAsString(DCM_InstitutionName) );
+  QString performingPhysiciansName(ctkDataset.GetElementAsString(DCM_PerformingPhysicianName) );
+  QString referringPhysician(ctkDataset.GetElementAsString(DCM_ReferringPhysicianName) );
+  QString studyDescription(ctkDataset.GetElementAsString(DCM_StudyDescription) );
+
+  QString seriesDate(ctkDataset.GetElementAsString(DCM_SeriesDate) );
+  QString seriesTime(ctkDataset.GetElementAsString(DCM_SeriesTime) );
+  QString seriesDescription(ctkDataset.GetElementAsString(DCM_SeriesDescription) );
+  QString bodyPartExamined(ctkDataset.GetElementAsString(DCM_BodyPartExamined) );
+  QString frameOfReferenceUID(ctkDataset.GetElementAsString(DCM_FrameOfReferenceUID) );
+  QString contrastAgent(ctkDataset.GetElementAsString(DCM_ContrastBolusAgent) );
+  QString scanningSequence(ctkDataset.GetElementAsString(DCM_ScanningSequence) );
+
+  long seriesNumber(ctkDataset.GetElementAsInteger(DCM_SeriesNumber) );
+  long acquisitionNumber(ctkDataset.GetElementAsInteger(DCM_AcquisitionNumber) );
+  long echoNumber(ctkDataset.GetElementAsInteger(DCM_EchoNumbers) );
+  long temporalPosition(ctkDataset.GetElementAsInteger(DCM_TemporalPositionIdentifier) );
 
   // store the file if the database is not in memomry
+  // TODO: if we are called from insert(file) we
+  // have to do something else
+  // 
   QString filename;
   if ( storeFile && !this->isInMemory() )
   {
-    DcmFileFormat* fileformat = new DcmFileFormat ( dataset );
 
     QString destinationDirectoryName = databaseDirectory() + "/dicom/";
     QDir destinationDir(destinationDirectoryName);
-    QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str();
+    QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID;
     destinationDir.mkpath(studySeriesDirectory);
 
-    filename = databaseDirectory() + "/dicom/" + pathForDataset(dataset);
+    filename = databaseDirectory() + "/dicom/" + pathForDataset(ctkDataset);
     logger.debug ( "Saving file: " + filename );
-    OFCondition status = fileformat->saveFile ( filename.toAscii() );
-    if ( !status.good() )
-      {
-      logger.error ( "Error saving file: " + filename + "\nError is " + status.text() );
-      delete fileformat;
+    if ( !ctkDataset.SaveToFile( filename) )
+    {
+      logger.error ( "Error saving file: " + filename );
       return;
-      }
-    delete fileformat;
+    }
   }
 
+  QSqlQuery checkPatientExistsQuery(d->Database);
+  //The dbPatientID  is a unique number within the database, generated by the sqlite autoincrement
+  //The patientID  is the (non-unique) DICOM patient id
+  int dbPatientID = -1;
 
-  QSqlQuery check_exists_query(d->Database);
-  //The patient UID is a unique number within the database, generated by the sqlite autoincrement
-  int patientUID = -1;
   if ( patientID != "" && patientsName != "" )
+  {
+    //Speed up: Check if patient is the same as in last file; very probable, as all images belonging to a study have the same patient
+    if( d->lastPatientID != patientID || d->lastPatientsBirthDate != patientsBirthDate || d->lastPatientsName != patientsName )
     {
-    //Check if patient is already present in the db
-    check_exists_query.prepare ( "SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?" );
-    check_exists_query.bindValue ( 0, QString ( patientID.c_str() ) );
-    check_exists_query.bindValue ( 1, QString ( patientsName.c_str() ) );
-    check_exists_query.exec();
-    
-    if (check_exists_query.next())
+      // Ok, something is different from last insert, let's insert him if he's not
+      // already in the db.
+      //
+
+      // Check if patient is already present in the db
+      // TODO: maybe add birthdate check for extra safety
+      checkPatientExistsQuery.prepare ( "SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?" );
+      checkPatientExistsQuery.bindValue ( 0, patientID );
+      checkPatientExistsQuery.bindValue ( 1, patientsName );
+      d->loggedExec(checkPatientExistsQuery);
+
+      if (checkPatientExistsQuery.next())
       {
-      patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();
+        // we found him
+        dbPatientID = checkPatientExistsQuery.value(checkPatientExistsQuery.record().indexOf("UID")).toInt();
       }
-    else
+      else
       {
-      // Insert it
-      QSqlQuery statement ( d->Database );
-      statement.prepare ( "INSERT INTO Patients ('UID', 'PatientsName', 'PatientID', 'PatientsBirthDate', 'PatientsBirthTime', 'PatientsSex', 'PatientsAge', 'PatientsComments' ) values ( NULL, ?, ?, ?, ?, ?, ?, ? )" );
-      statement.bindValue ( 0, QString ( patientsName.c_str() ) );
-      statement.bindValue ( 1, QString ( patientID.c_str() ) );
-      statement.bindValue ( 2, QString ( patientsBirthDate.c_str() ) );
-      statement.bindValue ( 3, QString ( patientsBirthTime.c_str() ) );
-      statement.bindValue ( 4, QString ( patientsSex.c_str() ) );
-      // TODO: shift patient's age to study, since this is not a patient level attribute in images
-      // statement.bindValue ( 5, QString ( patientsAge.c_str() ) );
-      statement.bindValue ( 6, QString ( patientComments.c_str() ) );
-      statement.exec ();
-      patientUID = statement.lastInsertId().toInt();
-      logger.debug ( "New patient inserted: " + QString().setNum ( patientUID ) );
+        // Insert it
+        QSqlQuery insertPatientStatement ( d->Database );
+        insertPatientStatement.prepare ( "INSERT INTO Patients ('UID', 'PatientsName', 'PatientID', 'PatientsBirthDate', 'PatientsBirthTime', 'PatientsSex', 'PatientsAge', 'PatientsComments' ) values ( NULL, ?, ?, ?, ?, ?, ?, ? )" );
+        insertPatientStatement.bindValue ( 0, patientsName );
+        insertPatientStatement.bindValue ( 1, patientID );
+        insertPatientStatement.bindValue ( 2, patientsBirthDate );
+        insertPatientStatement.bindValue ( 3, patientsBirthTime );
+        insertPatientStatement.bindValue ( 4, patientsSex );
+        // TODO: shift patient's age to study, since this is not a patient level attribute in images
+        // insertPatientStatement.bindValue ( 5, patientsAge );
+        insertPatientStatement.bindValue ( 6, patientComments );
+        d->loggedExec(insertPatientStatement);
+        dbPatientID = insertPatientStatement.lastInsertId().toInt();
+        logger.debug ( "New patient inserted: " + QString().setNum ( dbPatientID ) );
+
       }
+      /// keep this for the next image
+      d->lastPatientUID = dbPatientID;
+      d->lastPatientID = patientID;
+      d->lastPatientsBirthDate = patientsBirthDate;
+      d->lastPatientsName = patientsName;
     }
 
-  if ( studyInstanceUID != "" )
+    // Patient is in now. Let's continue with the study
+
+    if ( studyInstanceUID != "" && d->lastStudyInstanceUID != studyInstanceUID ) 
     {
-    check_exists_query.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" );
-    check_exists_query.bindValue ( 0, QString ( studyInstanceUID.c_str() ) );
-    check_exists_query.exec();
-    if(!check_exists_query.next())
+      QSqlQuery checkStudyExistsQuery (d->Database);
+      checkStudyExistsQuery.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" );
+      checkStudyExistsQuery.bindValue ( 0, studyInstanceUID );
+      checkStudyExistsQuery.exec();
+      if(!checkStudyExistsQuery.next())
       {
-      QSqlQuery statement ( d->Database );
-      statement.prepare ( "INSERT INTO Studies ( 'StudyInstanceUID', 'PatientsUID', 'StudyID', 'StudyDate', 'StudyTime', 'AccessionNumber', 'ModalitiesInStudy', 'InstitutionName', 'ReferringPhysician', 'PerformingPhysiciansName', 'StudyDescription' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
-      statement.bindValue ( 0, QString ( studyInstanceUID.c_str() ) );
-      statement.bindValue ( 1, patientUID );
-      statement.bindValue ( 2, QString ( studyID.c_str() ) );
-      statement.bindValue ( 3, QDate::fromString ( studyDate.c_str(), "yyyyMMdd" ) );
-      statement.bindValue ( 4, QString ( studyTime.c_str() ) );
-      statement.bindValue ( 5, QString ( accessionNumber.c_str() ) );
-      statement.bindValue ( 6, QString ( modalitiesInStudy.c_str() ) );
-      statement.bindValue ( 7, QString ( institutionName.c_str() ) );
-      statement.bindValue ( 8, QString ( referringPhysician.c_str() ) );
-      statement.bindValue ( 9, QString ( performingPhysiciansName.c_str() ) );
-      statement.bindValue ( 10, QString ( studyDescription.c_str() ) );
-      if ( !statement.exec() )
+        QSqlQuery insertStudyStatement ( d->Database );
+        insertStudyStatement.prepare ( "INSERT INTO Studies ( 'StudyInstanceUID', 'PatientsUID', 'StudyID', 'StudyDate', 'StudyTime', 'AccessionNumber', 'ModalitiesInStudy', 'InstitutionName', 'ReferringPhysician', 'PerformingPhysiciansName', 'StudyDescription' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
+        insertStudyStatement.bindValue ( 0, studyInstanceUID );
+        insertStudyStatement.bindValue ( 1, dbPatientID );
+        insertStudyStatement.bindValue ( 2, studyID );
+        insertStudyStatement.bindValue ( 3, QDate::fromString ( studyDate, "yyyyMMdd" ) );
+        insertStudyStatement.bindValue ( 4, studyTime );
+        insertStudyStatement.bindValue ( 5, accessionNumber );
+        insertStudyStatement.bindValue ( 6, modalitiesInStudy );
+        insertStudyStatement.bindValue ( 7, institutionName );
+        insertStudyStatement.bindValue ( 8, referringPhysician );
+        insertStudyStatement.bindValue ( 9, performingPhysiciansName );
+        insertStudyStatement.bindValue ( 10, studyDescription );
+        if ( !insertStudyStatement.exec() )
         {
-        logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );
+          logger.error ( "Error executing statament: " + insertStudyStatement.lastQuery() + " Error: " + insertStudyStatement.lastError().text() );
         }
+        else
+        {
+          d->lastStudyInstanceUID = studyInstanceUID;
+        }
+
       }
     }
 
-  if ( seriesInstanceUID != "" )
+    if ( seriesInstanceUID != "" && seriesInstanceUID != d->lastSeriesInstanceUID )
     {
-    check_exists_query.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" );
-    check_exists_query.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) );
-    logger.warn ( "Statement: " + check_exists_query.lastQuery() );
-    check_exists_query.exec();
-    if(!check_exists_query.next())
+      QSqlQuery checkSeriesExistsQuery (d->Database);
+      checkSeriesExistsQuery.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" );
+      checkSeriesExistsQuery.bindValue ( 0, seriesInstanceUID );
+      logger.warn ( "Statement: " + checkSeriesExistsQuery.lastQuery() );
+      d->loggedExec(checkSeriesExistsQuery);
+      if(!checkSeriesExistsQuery.next())
       {
-      QSqlQuery statement ( d->Database );
-      statement.prepare ( "INSERT INTO Series ( 'SeriesInstanceUID', 'StudyInstanceUID', 'SeriesNumber', 'SeriesDate', 'SeriesTime', 'SeriesDescription', 'BodyPartExamined', 'FrameOfReferenceUID', 'AcquisitionNumber', 'ContrastAgent', 'ScanningSequence', 'EchoNumber', 'TemporalPosition' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
-      statement.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) );
-      statement.bindValue ( 1, QString ( studyInstanceUID.c_str() ) );
-      statement.bindValue ( 2, static_cast<int>(seriesNumber) );
-      statement.bindValue ( 3, QString ( seriesDate.c_str() ) );
-      statement.bindValue ( 4, QDate::fromString ( seriesTime.c_str(), "yyyyMMdd" ) );
-      statement.bindValue ( 5, QString ( seriesDescription.c_str() ) );
-      statement.bindValue ( 6, QString ( bodyPartExamined.c_str() ) );
-      statement.bindValue ( 7, QString ( frameOfReferenceUID.c_str() ) );
-      statement.bindValue ( 8, static_cast<int>(acquisitionNumber) );
-      statement.bindValue ( 9, QString ( contrastAgent.c_str() ) );
-      statement.bindValue ( 10, QString ( scanningSequence.c_str() ) );
-      statement.bindValue ( 11, static_cast<int>(echoNumber) );
-      statement.bindValue ( 12, static_cast<int>(temporalPosition) );
-      if ( !statement.exec() )
+        QSqlQuery insertSeriesStatement ( d->Database );
+        insertSeriesStatement.prepare ( "INSERT INTO Series ( 'SeriesInstanceUID', 'StudyInstanceUID', 'SeriesNumber', 'SeriesDate', 'SeriesTime', 'SeriesDescription', 'BodyPartExamined', 'FrameOfReferenceUID', 'AcquisitionNumber', 'ContrastAgent', 'ScanningSequence', 'EchoNumber', 'TemporalPosition' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
+        insertSeriesStatement.bindValue ( 0, seriesInstanceUID );
+        insertSeriesStatement.bindValue ( 1, studyInstanceUID );
+        insertSeriesStatement.bindValue ( 2, static_cast<int>(seriesNumber) );
+        insertSeriesStatement.bindValue ( 3, seriesDate );
+        insertSeriesStatement.bindValue ( 4, QDate::fromString ( seriesTime, "yyyyMMdd" ) );
+        insertSeriesStatement.bindValue ( 5, seriesDescription );
+        insertSeriesStatement.bindValue ( 6, bodyPartExamined );
+        insertSeriesStatement.bindValue ( 7, frameOfReferenceUID );
+        insertSeriesStatement.bindValue ( 8, static_cast<int>(acquisitionNumber) );
+        insertSeriesStatement.bindValue ( 9, contrastAgent );
+        insertSeriesStatement.bindValue ( 10, scanningSequence );
+        insertSeriesStatement.bindValue ( 11, static_cast<int>(echoNumber) );
+        insertSeriesStatement.bindValue ( 12, static_cast<int>(temporalPosition) );
+        if ( !insertSeriesStatement.exec() )
         {
-        logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );
+          logger.error ( "Error executing statament: " + insertSeriesStatement.lastQuery() + " Error: " + insertSeriesStatement.lastError().text() );
+          d->lastSeriesInstanceUID = "";
         }
+        else
+        {
+          d->lastSeriesInstanceUID = seriesInstanceUID;
+        }
+
       }
     }
-  if ( !filename.isEmpty() )
+    // TODO: what to do with imported files
+    //
+    if ( !filename.isEmpty() )
     {
-    check_exists_query.prepare ( "SELECT * FROM Images WHERE Filename = ?" );
-    check_exists_query.bindValue ( 0, filename );
-    check_exists_query.exec();
-    if(!check_exists_query.next())
+      QSqlQuery checkImageExistsQuery (d->Database);
+      checkImageExistsQuery.prepare ( "SELECT * FROM Images WHERE Filename = ?" );
+      checkImageExistsQuery.bindValue ( 0, filename );
+      checkImageExistsQuery.exec();
+      if(!checkImageExistsQuery.next())
       {
-      QSqlQuery statement ( d->Database );
-      statement.prepare ( "INSERT INTO Images ( 'SOPInstanceUID', 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ?, ? )" );
-      statement.bindValue ( 0, QString ( sopInstanceUID.c_str() ) );
-      statement.bindValue ( 1, filename );
-      statement.bindValue ( 2, QString ( seriesInstanceUID.c_str() ) );
-      statement.bindValue ( 3, QDateTime::currentDateTime() );
-      statement.exec();
+        QSqlQuery insertImageStatement ( d->Database );
+        insertImageStatement.prepare ( "INSERT INTO Images ( 'SOPInstanceUID', 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ?, ? )" );
+        insertImageStatement.bindValue ( 0, sopInstanceUID );
+        insertImageStatement.bindValue ( 1, filename );
+        insertImageStatement.bindValue ( 2, seriesInstanceUID );
+        insertImageStatement.bindValue ( 3, QDateTime::currentDateTime() );
+        insertImageStatement.exec();
       }
     }
 
-  if(generateThumbnail){
-      if(d->thumbnailGenerator){
-        QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + QString(seriesInstanceUID.c_str());
+    /**
+     * old move/copy code from indexer insert
+     *
+
+     QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID;
+
+    //----------------------------------
+    //Move file to destination directory
+    //----------------------------------
+
+    QString finalFilePath(filePath);
+    if (!destinationDirectoryName.isEmpty())
+    {
+    QFile currentFile( filePath );
+    QDir destinationDir(destinationDirectoryName + "/dicom");
+    finalFilePath = sopInstanceUID;
+    if (createHierarchy)
+    {
+    destinationDir.mkpath(studySeriesDirectory);
+    finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
+    }
+    currentFile.copy(finalFilePath);
+    logger.debug( "Copy file from: " + filePath );
+    logger.debug( "Copy file to  : " + finalFilePath );
+    }
+    logger.debug(QString("finalFilePath: ") + finalFilePath);
+
+*/
+
+    if(generateThumbnail){
+      if(d->thumbnailGenerator)
+      {
+        QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID;
         //Create thumbnail here
         QString thumbnailPath = databaseDirectory() +
-                            "/thumbs/" + this->pathForDataset(dataset) + ".png";
-                            //QString(studyInstanceUID.c_str()) + "/" +
-                            //QString(seriesInstanceUID.c_str()) + "/" +
-                            //QString(sopInstanceUID.c_str()) + ".png";
+          "/thumbs/" + this->pathForDataset(ctkDataset) + ".png";
+        //studyInstanceUID + "/" +
+        //seriesInstanceUID + "/" +
+        //sopInstanceUID + ".png";
         QFileInfo thumbnailInfo(thumbnailPath);
         if(!(thumbnailInfo.exists() && (thumbnailInfo.lastModified() > QFileInfo(filename).lastModified()))){
-            QDir(databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory);
-            DicomImage dcmImage(QDir::toNativeSeparators(filename).toAscii());
-            d->thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath);
+          QDir(databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory);
+          DicomImage dcmImage(QDir::toNativeSeparators(filename).toAscii());
+          d->thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath);
         }
       }
-  }
+    }
 
-  if (isInMemory())
+    if (isInMemory())
     {
       emit databaseChanged();
     }
+  }
 }
 
+
 //------------------------------------------------------------------------------
 void ctkDICOMDatabase::insert ( const QString& filePath, bool storeFile, bool generateThumbnail, bool createHierarchy, const QString& destinationDirectoryName)
 {
-  Q_D(ctkDICOMDatabase);
   
   /// first we check if the file is already in the database
   if (fileExistsAndUpToDate(filePath))
@@ -680,324 +749,11 @@ void ctkDICOMDatabase::insert ( const QString& filePath, bool storeFile, bool ge
   std::string filename = filePath.toStdString();
 
   DcmFileFormat fileformat;
-  DcmDataset *dataset;
-
-  OFCondition status = fileformat.loadFile(filename.c_str());
-
-  dataset = fileformat.getDataset();
-
-  if (!status.good())
-  {
-    logger.error( "Could not load " + filePath );
-    logger.error( "DCMTK says: " + QString(status.text()) );
-    return;
-  }
-  
-  // ok, we have loaded a dataset
-
-
-  OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex,
-    patientComments, patientsAge;
-
-  OFString studyInstanceUID, studyID, studyDate, studyTime,
-    accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription;
-
-  OFString seriesInstanceUID, seriesDate, seriesTime,
-    seriesDescription, bodyPartExamined, frameOfReferenceUID,
-    contrastAgent, scanningSequence;
-  OFString instanceNumber, sopInstanceUID ;
-
-  Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
-
-  //The patient UID is a unique number within the database, generated by the sqlite autoincrement
-  //Thus, this is _not_ the DICOM Patient ID.
-  int patientUID = -1;
-
-  //If the following fields can not be evaluated, cancel evaluation of the DICOM file
-  if (!dataset->findAndGetOFString(DCM_PatientName, patientsName).good())
-  {
-    logger.error( "Could not read DCM_PatientName from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_StudyInstanceUID from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_SeriesInstanceUID from " + filePath );
-    return;
-  }
-
-  if (!dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID).good())
-  {
-    logger.error( "Could not read DCM_SOPInstanceUID from " + filePath );
-    return;
-  }
-  if (!dataset->findAndGetOFString(DCM_InstanceNumber, instanceNumber).good())
-  {
-    logger.error( "Could not read DCM_InstanceNumber from " + filePath );
-    return;
-  }
-
-
-  dataset->findAndGetOFString(DCM_PatientID, patientID);
-  dataset->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate);
-  dataset->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime);
-  dataset->findAndGetOFString(DCM_PatientSex, patientsSex);
-  dataset->findAndGetOFString(DCM_PatientAge, patientsAge);
-  dataset->findAndGetOFString(DCM_PatientComments, patientComments);
-  dataset->findAndGetOFString(DCM_StudyID, studyID);
-  dataset->findAndGetOFString(DCM_StudyDate, studyDate);
-  dataset->findAndGetOFString(DCM_StudyTime, studyTime);
-  dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
-  dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
-  dataset->findAndGetOFString(DCM_InstitutionName, institutionName);
-  dataset->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName);
-  dataset->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician);
-  dataset->findAndGetOFString(DCM_StudyDescription, studyDescription);
-
-  dataset->findAndGetOFString(DCM_SeriesDate, seriesDate);
-  dataset->findAndGetOFString(DCM_SeriesTime, seriesTime);
-  dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
-  dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
-  dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
-  dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
-  dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
-
-  dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
-  dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
-  dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber);
-  dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);
-
-  logger.debug( "Adding new items to database:" );
-  logger.debug( "studyID: " + QString(studyID.c_str()) );
-  logger.debug( "seriesInstanceUID: " + QString(seriesInstanceUID.c_str()) );
-  logger.debug( "Patient's Name: " + QString(patientsName.c_str()) );
-
-  //-----------------------
-  //Add Patient to Database
-  //-----------------------
-
-  //Speed up: Check if patient is the same as in last file; very probable, as all images belonging to a study have the same patient
-  bool patientExists = false;
-  if(d->lastPatientID.compare(patientID) || d->lastPatientsBirthDate.compare(patientsBirthDate) || d->lastPatientsName.compare(patientsName))
-  {
-    //Check if patient is already present in the db
-    QSqlQuery check_exists_query(database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Patients WHERE PatientID = '" << patientID << "'";
-    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    /// we check only patients with the same PatientID
-    /// PatientID is not unique in DICOM, so we also compare Name and BirthDate
-    /// and assume this is sufficient
-    while (check_exists_query.next())
-    {
-      if (
-          check_exists_query.record().value("PatientsName").toString() == patientsName.c_str() &&
-          check_exists_query.record().value("PatientsBirthDate").toString() == patientsBirthDate.c_str()
-         )
-      {
-        /// found it
-        patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();
-        patientExists = true;
-        break;
-      }
-    }
-    check_exists_query.finish();
-
-    if(!patientExists)
-    {
-
-      QSqlQuery insert_patient_query(database());
-
-      std::stringstream query_string;
-
-      query_string << "INSERT INTO Patients VALUES( NULL,'"
-      << patientsName << "','"
-      << patientID << "','"
-      << patientsBirthDate << "','"
-      << patientsBirthTime << "','"
-      << patientsSex << "','"
-      << patientsAge << "','"
-      << patientComments << "')";
-
-      d->loggedExec(insert_patient_query, query_string.str().c_str());
-
-      patientUID = insert_patient_query.lastInsertId().toInt();
-      insert_patient_query.finish();
-      QString patientUIDQString;
-      patientUIDQString.setNum(patientUID);
-      logger.debug( "New patient inserted: " + patientUIDQString );
-    }
-  }
-  else
-    {
-    patientUID = d->lastPatientUID;
-    }
-
-  /// keep this for the next image
-  d->lastPatientUID = patientUID;
-  d->lastPatientID = patientID;
-  d->lastPatientsBirthDate = patientsBirthDate;
-  d->lastPatientsName = patientsName;
-
-  //---------------------
-  //Add Study to Database
-  //---------------------
-
-  if(d->lastStudyInstanceUID.compare(studyInstanceUID))
-  {
-    QSqlQuery check_exists_query(database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Studies WHERE StudyInstanceUID = '" << studyInstanceUID << "'";
-    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    logger.debug( "Checking for study: " + QString(studyInstanceUID.c_str()) );
-
-    if(!check_exists_query.next())
-    {
-
-      QSqlQuery insert_query(database());
-      std::stringstream query_string;
-
-      // TODO: all INSERTS should be changed to use the prepare/bindValue methods
-      // to avoid quoting issues
-      insert_query.prepare("INSERT INTO Studies (StudyInstanceUID, PatientsUID, StudyID, StudyDate, StudyTime, AccessionNumber, ModalitiesInStudy, InstitutionName, ReferringPhysician, PerformingPhysiciansName, StudyDescription) VALUES (:StudyInstanceUID, :PatientsUID, :StudyID, :StudyDate, :StudyTime, :AccessionNumber, :ModalitiesInStudy, :InstitutionName, :ReferringPhysician, :PerformingPhysiciansName, :StudyDescription)");
-
-      insert_query.bindValue(":StudyInstanceUID", QString(studyInstanceUID.c_str()));
-      insert_query.bindValue(":PatientsUID", patientUID);
-      insert_query.bindValue(":StudyID", QString(studyID.c_str()));
-      insert_query.bindValue(":StudyDate", QDate::fromString(studyDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd"));
-      insert_query.bindValue(":StudyTime", QString(studyTime.c_str()));
-      insert_query.bindValue(":AccessionNumber", QString(accessionNumber.c_str()));
-      insert_query.bindValue(":ModalitiesInStudy", QString(modalitiesInStudy.c_str()));
-      insert_query.bindValue(":InstitutionName", QString(institutionName.c_str()));
-      insert_query.bindValue(":ReferringPhysician", QString(referringPhysician.c_str()));
-      insert_query.bindValue(":PerformingPhysiciansName", QString(performingPhysiciansName.c_str()));
-      insert_query.bindValue(":StudyDescription", QString(studyDescription.c_str()));
-
-      d->loggedExec(insert_query);
-      logger.debug( "Inserted study: " + QString(studyInstanceUID.c_str()) );
-    }
-  }
-
-  d->lastStudyInstanceUID = studyInstanceUID;
-
-  //----------------------
-  //Add Series to Database
-  //----------------------
-
-  if(d->lastSeriesInstanceUID.compare(seriesInstanceUID))
-  {
-
-    QSqlQuery check_exists_query(database());
-    std::stringstream check_exists_query_string;
-    check_exists_query_string << "SELECT * FROM Series WHERE SeriesInstanceUID = '" << seriesInstanceUID << "'";
-    d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-    logger.debug( "Checking series: " + QString(seriesInstanceUID.c_str()) );
-
-    if(!check_exists_query.next())
-    {
-
-      QSqlQuery insert_query(database());
-      std::stringstream query_string;
-
-      query_string << "INSERT INTO Series VALUES('"
-        << seriesInstanceUID << "','"
-        << studyInstanceUID << "','"
-        << static_cast<int>(seriesNumber) << "','"
-        << QDate::fromString(seriesDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd").toStdString() << "','"
-        << seriesTime << "','"
-        << seriesDescription << "','"
-        << bodyPartExamined << "','"
-        << frameOfReferenceUID << "','"
-        << static_cast<int>(acquisitionNumber) << "','"
-        << contrastAgent << "','"
-        << scanningSequence << "','"
-        << static_cast<int>(echoNumber) << "','"
-        << static_cast<int>(temporalPosition) << "')";
-
-      d->loggedExec(insert_query, query_string.str().c_str());
-      logger.debug( "Inserted series: " + QString(seriesInstanceUID.c_str()) );
-    }
-  }
-
-  d->lastSeriesInstanceUID = seriesInstanceUID;
-
-  QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str();
-
-  //----------------------------------
-  //Move file to destination directory
-  //----------------------------------
-
-  QString finalFilePath(filePath);
-  if (!destinationDirectoryName.isEmpty())
-  {
-    QFile currentFile( filePath );
-    QDir destinationDir(destinationDirectoryName + "/dicom");
-    finalFilePath = sopInstanceUID.c_str();
-    if (createHierarchy)
-    {
-      destinationDir.mkpath(studySeriesDirectory);
-      finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
-    }
-    currentFile.copy(finalFilePath);
-    logger.debug( "Copy file from: " + filePath );
-    logger.debug( "Copy file to  : " + finalFilePath );
-  }
-  logger.debug(QString("finalFilePath: ") + finalFilePath);
-
-  if (generateThumbnail)
-  {
-    if(d->thumbnailGenerator)
-    {
-      QString thumbnailBaseDir =  databaseDirectory() + "/thumbs/";
-      QString thumbnailFilename = thumbnailBaseDir + "/" + pathForDataset(dataset) + ".png";
-      QFileInfo thumbnailInfo(thumbnailFilename);
-      if ( ! ( thumbnailInfo.exists() && thumbnailInfo.lastModified() < QFileInfo(finalFilePath).lastModified() ) )
-      {
-        QDir(thumbnailBaseDir).mkpath(studySeriesDirectory);
-        DicomImage dcmtkImage(QDir::toNativeSeparators(finalFilePath).toStdString().c_str());
-        d->thumbnailGenerator->generateThumbnail(&dcmtkImage, thumbnailFilename);
-      }
-    }
-  }
-
-  //------------------------
-  //Add Filename to Database
-  //------------------------
-
-//    std::stringstream relativeFilePath;
-//    relativeFilePath << seriesInstanceUID.c_str() << "/" << currentFilePath.getFileName();
-
-  logger.debug(QString("Adding file path to dabase: ") + finalFilePath);
-
-  QSqlQuery check_exists_query(database());
-  std::stringstream check_exists_query_string;
-//    check_exists_query_string << "SELECT * FROM Images WHERE Filename = '" << relativeFilePath.str() << "'";
-  check_exists_query_string << "SELECT * FROM Images WHERE SOPInstanceUID = '" << sopInstanceUID << "'";
-  d->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
-
-  if(!check_exists_query.next())
-  {
-    QSqlQuery insert_query(database());
-    std::stringstream query_string;
-
-    //To save absolute path: destDirectoryPath.str()
-    query_string << "INSERT INTO Images VALUES('"
-      << sopInstanceUID << "','" << finalFilePath.toStdString() << "','" << seriesInstanceUID << "','" << QDateTime::currentDateTime().toString(Qt::ISODate).toStdString() << "')";
-
-    d->loggedExec(insert_query, query_string.str().c_str());
-    logger.debug(QString("added file path to dabase: ") + query_string.str().c_str());
-  }
+  ctkDICOMDataset ctkDataset;
 
+  ctkDataset.InitializeFromFile(filePath);
 
+  this->insert( ctkDataset, storeFile, generateThumbnail );
 
 }
 
@@ -1035,17 +791,18 @@ bool ctkDICOMDatabase::isInMemory() const
 }
 
 
-QString ctkDICOMDatabase::pathForDataset( DcmDataset *dataset)
+QString ctkDICOMDatabase::pathForDataset( const ctkDICOMDataset& ctkDataset)
 {
-  if (!dataset)
+    // TODO: this is not related to the database
+    // could be static, is it necessary?
+  if ( !ctkDataset.IsInitialized() )
     {
     return QString();
     }
-  OFString studyInstanceUID, seriesInstanceUID, sopInstanceUID;
-  dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
-  dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);
-  dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);
-
-  return QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str() + "/" + sopInstanceUID.c_str();
+  QString studyInstanceUID(ctkDataset.GetElementAsString(DCM_StudyInstanceUID) );
+  QString seriesInstanceUID(ctkDataset.GetElementAsString(DCM_SeriesInstanceUID) );
+  QString sopInstanceUID ( ctkDataset.GetElementAsString(DCM_SOPInstanceUID) );
+ 
+  return studyInstanceUID + "/" + seriesInstanceUID + "/" + sopInstanceUID;
 
 }

+ 3 - 1
Libs/DICOM/Core/ctkDICOMDatabase.h

@@ -26,6 +26,7 @@
 #include <QStringList>
 #include <QSqlDatabase>
 
+#include "ctkDICOMDataset.h"
 #include "ctkDICOMCoreExport.h"
 
 class ctkDICOMDatabasePrivate;
@@ -137,12 +138,13 @@ public:
   ///                  does only make sense if a full object is received.
   /// @param @generateThumbnail If true, a thumbnail is generated.
   ///
+  void insert( const ctkDICOMDataset& ctkDataset, bool storeFile, bool generateThumbnail);
   void insert ( DcmDataset *dataset, bool storeFile = true, bool generateThumbnail = true);
   void insert ( const QString& filePath, bool storeFile = true, bool generateThumbnail = true, bool createHierarchy = true, const QString& destinationDirectoryName = QString() );
   ///
   /// Helper method: get the path that should be used to store this image.
   ///
-  QString pathForDataset( DcmDataset *dataset);
+  QString pathForDataset( const ctkDICOMDataset& dataset);
   
   /// Check if file is already in database and up-to-date
   bool fileExistsAndUpToDate(const QString& filePath);