ctkDICOMIndexerBase.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) 2010 Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.commontk.org/LICENSE
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QSqlQuery>
  16. #include <QSqlRecord>
  17. #include <QSqlError>
  18. #include <QVariant>
  19. #include <QDate>
  20. #include <QStringList>
  21. #include <QSet>
  22. #include <QFile>
  23. #include <QDirIterator>
  24. #include <QFileInfo>
  25. #include <QDebug>
  26. // ctkDICOM includes
  27. #include "ctkDICOMIndexerBase.h"
  28. #include "ctkLogger.h"
  29. // DCMTK includes
  30. #ifndef WIN32
  31. #define HAVE_CONFIG_H
  32. #endif
  33. #include <dcmtk/dcmdata/dcfilefo.h>
  34. #include <dcmtk/dcmdata/dcfilefo.h>
  35. #include <dcmtk/dcmdata/dcdeftag.h>
  36. #include <dcmtk/dcmdata/dcdatset.h>
  37. #include <dcmtk/ofstd/ofcond.h>
  38. #include <dcmtk/ofstd/ofstring.h>
  39. #include <dcmtk/ofstd/ofstd.h> /* for class OFStandard */
  40. #include <dcmtk/dcmdata/dcddirif.h> /* for class DicomDirInterface */
  41. static ctkLogger logger ( "org.commontk.dicom.DICOMIndexerBase" );
  42. //------------------------------------------------------------------------------
  43. class ctkDICOMIndexerBasePrivate: public ctkPrivate<ctkDICOMIndexerBase>
  44. {
  45. public:
  46. ctkDICOMIndexerBasePrivate();
  47. ~ctkDICOMIndexerBasePrivate();
  48. QSqlDatabase db;
  49. };
  50. //------------------------------------------------------------------------------
  51. // ctkDICOMIndexerBasePrivate methods
  52. //------------------------------------------------------------------------------
  53. ctkDICOMIndexerBasePrivate::ctkDICOMIndexerBasePrivate()
  54. {
  55. }
  56. //------------------------------------------------------------------------------
  57. ctkDICOMIndexerBasePrivate::~ctkDICOMIndexerBasePrivate()
  58. {
  59. }
  60. //------------------------------------------------------------------------------
  61. // ctkDICOMIndexerBase methods
  62. //------------------------------------------------------------------------------
  63. ctkDICOMIndexerBase::ctkDICOMIndexerBase()
  64. {
  65. }
  66. //------------------------------------------------------------------------------
  67. ctkDICOMIndexerBase::~ctkDICOMIndexerBase()
  68. {
  69. }
  70. void ctkDICOMIndexerBase::setDatabase ( QSqlDatabase database ) {
  71. CTK_D(ctkDICOMIndexerBase);
  72. d->db = database;
  73. }
  74. const QSqlDatabase& ctkDICOMIndexerBase::database () const {
  75. CTK_D(const ctkDICOMIndexerBase);
  76. return d->db;
  77. }
  78. void ctkDICOMIndexerBase::insert ( DcmDataset *dataset ) {
  79. this->insert ( dataset, QString() );
  80. }
  81. void ctkDICOMIndexerBase::insert ( DcmDataset *dataset, QString filename ) {
  82. CTK_D(ctkDICOMIndexerBase);
  83. // Check to see if the file has already been loaded
  84. QSqlQuery fileExists ( d->db );
  85. fileExists.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");
  86. fileExists.bindValue(0,filename);
  87. fileExists.exec();
  88. if ( fileExists.next() && QFileInfo(filename).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) )
  89. {
  90. logger.debug ( "File " + filename + " already added" );
  91. return;
  92. }
  93. OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex,
  94. patientComments, patientsAge;
  95. OFString studyInstanceUID, studyID, studyDate, studyTime,
  96. accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription;
  97. OFString seriesInstanceUID, seriesDate, seriesTime,
  98. seriesDescription, bodyPartExamined, frameOfReferenceUID,
  99. contrastAgent, scanningSequence;
  100. OFString instanceNumber;
  101. Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
  102. //If the following fields can not be evaluated, cancel evaluation of the DICOM file
  103. dataset->findAndGetOFString(DCM_PatientsName, patientsName);
  104. dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
  105. dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);
  106. dataset->findAndGetOFString(DCM_PatientID, patientID);
  107. dataset->findAndGetOFString(DCM_PatientsBirthDate, patientsBirthDate);
  108. dataset->findAndGetOFString(DCM_PatientsBirthTime, patientsBirthTime);
  109. dataset->findAndGetOFString(DCM_PatientsSex, patientsSex);
  110. dataset->findAndGetOFString(DCM_PatientsAge, patientsAge);
  111. dataset->findAndGetOFString(DCM_PatientComments, patientComments);
  112. dataset->findAndGetOFString(DCM_StudyID, studyID);
  113. dataset->findAndGetOFString(DCM_StudyDate, studyDate);
  114. dataset->findAndGetOFString(DCM_StudyTime, studyTime);
  115. dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
  116. dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
  117. dataset->findAndGetOFString(DCM_InstitutionName, institutionName);
  118. dataset->findAndGetOFString(DCM_PerformingPhysiciansName, performingPhysiciansName);
  119. dataset->findAndGetOFString(DCM_ReferringPhysiciansName, referringPhysician);
  120. dataset->findAndGetOFString(DCM_StudyDescription, studyDescription);
  121. dataset->findAndGetOFString(DCM_SeriesDate, seriesDate);
  122. dataset->findAndGetOFString(DCM_SeriesTime, seriesTime);
  123. dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
  124. dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
  125. dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
  126. dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
  127. dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
  128. dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
  129. dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
  130. dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber);
  131. dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);
  132. QSqlQuery check_exists_query(d->db);
  133. //The patient UID is a unique number within the database, generated by the sqlite autoincrement
  134. int patientUID = -1;
  135. if ( patientID != "" && patientsName != "" )
  136. {
  137. //Check if patient is already present in the db
  138. check_exists_query.prepare ( "SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?" );
  139. check_exists_query.bindValue ( 0, QString ( patientID.c_str() ) );
  140. check_exists_query.bindValue ( 1, QString ( patientsName.c_str() ) );
  141. check_exists_query.exec();
  142. if (check_exists_query.next())
  143. {
  144. patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();
  145. }
  146. else
  147. {
  148. // Insert it
  149. QSqlQuery statement ( d->db );
  150. statement.prepare ( "INSERT INTO Patients ('UID', 'PatientsName', 'PatientID', 'PatientsBirthDate', 'PatientsBirthTime', 'PatientsSex', 'PatientsAge', 'PatientsComments' ) values ( NULL, ?, ?, ?, ?, ?, ?, ? )" );
  151. statement.bindValue ( 0, QString ( patientsName.c_str() ) );
  152. statement.bindValue ( 1, QString ( patientID.c_str() ) );
  153. statement.bindValue ( 2, QString ( patientsBirthDate.c_str() ) );
  154. statement.bindValue ( 3, QString ( patientsBirthTime.c_str() ) );
  155. statement.bindValue ( 4, QString ( patientsSex.c_str() ) );
  156. statement.bindValue ( 5, QString ( patientsAge.c_str() ) );
  157. statement.bindValue ( 6, QString ( patientComments.c_str() ) );
  158. statement.exec ();
  159. patientUID = statement.lastInsertId().toInt();
  160. logger.debug ( "New patient inserted: " + QString().setNum ( patientUID ) );
  161. }
  162. }
  163. if ( studyInstanceUID != "" )
  164. {
  165. check_exists_query.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" );
  166. check_exists_query.bindValue ( 0, QString ( studyInstanceUID.c_str() ) );
  167. check_exists_query.exec();
  168. if(!check_exists_query.next())
  169. {
  170. QSqlQuery statement ( d->db );
  171. statement.prepare ( "INSERT INTO Studies ( 'StudyInstanceUID', 'PatientsUID', 'StudyID', 'StudyDate', 'StudyTime', 'AccessionNumber', 'ModalitiesInStudy', 'InstitutionName', 'ReferringPhysician', 'PerformingPhysiciansName', 'StudyDescription' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
  172. statement.bindValue ( 0, QString ( studyInstanceUID.c_str() ) );
  173. statement.bindValue ( 1, patientUID );
  174. statement.bindValue ( 2, QString ( studyID.c_str() ) );
  175. statement.bindValue ( 3, QDate::fromString ( studyDate.c_str(), "yyyyMMdd" ) );
  176. statement.bindValue ( 4, QString ( studyTime.c_str() ) );
  177. statement.bindValue ( 5, QString ( accessionNumber.c_str() ) );
  178. statement.bindValue ( 6, QString ( modalitiesInStudy.c_str() ) );
  179. statement.bindValue ( 7, QString ( institutionName.c_str() ) );
  180. statement.bindValue ( 8, QString ( referringPhysician.c_str() ) );
  181. statement.bindValue ( 9, QString ( performingPhysiciansName.c_str() ) );
  182. statement.bindValue ( 10, QString ( studyDescription.c_str() ) );
  183. if ( !statement.exec() )
  184. {
  185. logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );
  186. }
  187. }
  188. }
  189. if ( seriesInstanceUID != "" )
  190. {
  191. check_exists_query.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" );
  192. check_exists_query.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) );
  193. logger.warn ( "Statement: " + check_exists_query.lastQuery() );
  194. check_exists_query.exec();
  195. if(!check_exists_query.next())
  196. {
  197. QSqlQuery statement ( d->db );
  198. statement.prepare ( "INSERT INTO Series ( 'SeriesInstanceUID', 'StudyInstanceUID', 'SeriesNumber', 'SeriesDate', 'SeriesTime', 'SeriesDescription', 'BodyPartExamined', 'FrameOfReferenceUID', 'AcquisitionNumber', 'ContrastAgent', 'ScanningSequence', 'EchoNumber', 'TemporalPosition' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" );
  199. statement.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) );
  200. statement.bindValue ( 1, QString ( studyInstanceUID.c_str() ) );
  201. statement.bindValue ( 2, static_cast<int>(seriesNumber) );
  202. statement.bindValue ( 3, QString ( seriesDate.c_str() ) );
  203. statement.bindValue ( 4, QDate::fromString ( seriesTime.c_str(), "yyyyMMdd" ) );
  204. statement.bindValue ( 5, QString ( seriesDescription.c_str() ) );
  205. statement.bindValue ( 6, QString ( bodyPartExamined.c_str() ) );
  206. statement.bindValue ( 7, QString ( frameOfReferenceUID.c_str() ) );
  207. statement.bindValue ( 8, static_cast<int>(acquisitionNumber) );
  208. statement.bindValue ( 9, QString ( contrastAgent.c_str() ) );
  209. statement.bindValue ( 10, QString ( scanningSequence.c_str() ) );
  210. statement.bindValue ( 11, static_cast<int>(echoNumber) );
  211. statement.bindValue ( 12, static_cast<int>(temporalPosition) );
  212. if ( !statement.exec() )
  213. {
  214. logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );
  215. }
  216. }
  217. }
  218. if ( !filename.isEmpty() )
  219. {
  220. check_exists_query.prepare ( "SELECT * FROM Images WHERE Filename = ?" );
  221. check_exists_query.bindValue ( 0, filename );
  222. check_exists_query.exec();
  223. if(!check_exists_query.next())
  224. {
  225. QSqlQuery statement ( d->db );
  226. statement.prepare ( "INSERT INTO Images ( 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ? )" );
  227. statement.bindValue ( 0, filename );
  228. statement.bindValue ( 1, QString ( seriesInstanceUID.c_str() ) );
  229. statement.bindValue ( 2, QDateTime::currentDateTime() );
  230. statement.exec();
  231. }
  232. }
  233. }