ctkDICOMDatabase.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) 2010
  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.apache.org/licenses/LICENSE-2.0.txt
  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. #ifndef __ctkDICOMDatabase_h
  15. #define __ctkDICOMDatabase_h
  16. // Qt includes
  17. #include <QObject>
  18. #include <QStringList>
  19. #include <QSqlDatabase>
  20. #include "ctkDICOMItem.h"
  21. #include "ctkDICOMCoreExport.h"
  22. class QDateTime;
  23. class ctkDICOMDatabasePrivate;
  24. class DcmDataset;
  25. class ctkDICOMAbstractThumbnailGenerator;
  26. /// \ingroup DICOM_Core
  27. ///
  28. /// Class handling a database of DICOM objects. So far, an underlying
  29. /// SQLITE database is used for that. Usually, added DICOM objects are also
  30. /// stored within the file system.
  31. /// The SQLITE database file can be specified by the user. SQLITE (and this
  32. /// class) also support a special in memory mode, where no database file is created
  33. /// but the database is completely kept in memory (and after exiting the program,
  34. /// vanishes). If in "memory mode", the objects are not written to disk,
  35. /// otherwise they are stored in a subdirectory of the SQLITE database file
  36. /// directory called "dicom". Inside, a folder structure created which contains
  37. /// a directoy for each study, containing a directory for each series, containing
  38. /// a file for each object. The corresponding UIDs are used as filenames.
  39. /// Thumbnais for each image can be created; if so, they are stored in a directory
  40. /// parallel to "dicom" directory called "thumbs".
  41. class CTK_DICOM_CORE_EXPORT ctkDICOMDatabase : public QObject
  42. {
  43. Q_OBJECT
  44. Q_PROPERTY(bool isOpen READ isOpen)
  45. Q_PROPERTY(bool isInMemory READ isInMemory)
  46. Q_PROPERTY(QString lastError READ lastError)
  47. Q_PROPERTY(QString databaseFilename READ databaseFilename)
  48. Q_PROPERTY(QString databaseDirectory READ databaseDirectory)
  49. Q_PROPERTY(QStringList tagsToPrecache READ tagsToPrecache WRITE setTagsToPrecache)
  50. public:
  51. explicit ctkDICOMDatabase(QObject *parent = 0);
  52. explicit ctkDICOMDatabase(QString databaseFile);
  53. virtual ~ctkDICOMDatabase();
  54. const QSqlDatabase& database() const;
  55. const QString lastError() const;
  56. const QString databaseFilename() const;
  57. ///
  58. /// Returns the absolute path of the database directory
  59. /// (where the database file resides in) in OS-prefered path format.
  60. /// @return Absolute path to database directory
  61. const QString databaseDirectory() const;
  62. ///
  63. /// Should be checked after trying to open the database
  64. /// @Returns true if database is open
  65. bool isOpen() const;
  66. ///
  67. /// Returns whether the database only resides in memory, i.e. the
  68. /// SQLITE DB is not written to stored to disk and DICOM objects are not
  69. /// stored to the file system.
  70. /// @return True if in memory mode, false otherwise.
  71. bool isInMemory() const;
  72. ///
  73. /// set thumbnail generator object
  74. Q_INVOKABLE void setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator* generator);
  75. ///
  76. /// get thumbnail genrator object
  77. Q_INVOKABLE ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator();
  78. ///
  79. /// open the SQLite database in @param databaseFile . If the file does not
  80. /// exist, a new database is created and initialized with the
  81. /// default schema
  82. ///
  83. /// @param databaseFile The file to store the SQLITE database should be
  84. /// stored to. If specified with ":memory:", the database is not
  85. /// written to disk at all but instead only kept in memory (and
  86. /// thus expires after destruction of this object).
  87. /// @param connectionName The database connection name. If not specified
  88. /// then a random name is generated (reusing a connection name
  89. /// must be avoided as it breaks previously created database object
  90. /// that used the same connection name).
  91. /// @param update the schema if it is found to be out of date
  92. Q_INVOKABLE virtual void openDatabase(const QString databaseFile,
  93. const QString& connectionName = "");
  94. ///
  95. /// close the database. It must not be used afterwards.
  96. Q_INVOKABLE void closeDatabase();
  97. ///
  98. /// delete all data and (re-)initialize the database.
  99. Q_INVOKABLE bool initializeDatabase(const char* schemaFile = ":/dicom/dicom-schema.sql");
  100. /// updates the database schema and reinserts all existing files
  101. Q_INVOKABLE bool updateSchema(const char* schemaFile = ":/dicom/dicom-schema.sql");
  102. /// updates the database schema only if the versions don't match
  103. /// Returns true if schema was updated
  104. Q_INVOKABLE bool updateSchemaIfNeeded(const char* schemaFile = ":/dicom/dicom-schema.sql");
  105. /// returns the schema version needed by the current version of this code
  106. Q_INVOKABLE QString schemaVersion();
  107. /// returns the schema version for the currently open database
  108. /// in order to support schema updating
  109. Q_INVOKABLE QString schemaVersionLoaded();
  110. ///
  111. /// \brief database accessors
  112. Q_INVOKABLE QStringList patients ();
  113. Q_INVOKABLE QStringList studiesForPatient (const QString patientUID);
  114. Q_INVOKABLE QStringList seriesForStudy (const QString studyUID);
  115. Q_INVOKABLE QStringList instancesForSeries(const QString seriesUID);
  116. Q_INVOKABLE QString studyForSeries(QString seriesUID);
  117. Q_INVOKABLE QString patientForStudy(QString studyUID);
  118. Q_INVOKABLE QStringList filesForSeries (const QString seriesUID);
  119. Q_INVOKABLE QHash<QString,QString> descriptionsForFile(QString fileName);
  120. Q_INVOKABLE QString descriptionForSeries(const QString seriesUID);
  121. Q_INVOKABLE QString descriptionForStudy(const QString studyUID);
  122. Q_INVOKABLE QString nameForPatient(const QString patientUID);
  123. Q_INVOKABLE QString fileForInstance (const QString sopInstanceUID);
  124. Q_INVOKABLE QString seriesForFile (QString fileName);
  125. Q_INVOKABLE QString instanceForFile (const QString fileName);
  126. Q_INVOKABLE QDateTime insertDateTimeForInstance (const QString fileName);
  127. Q_INVOKABLE QStringList allFiles ();
  128. ///
  129. /// \brief load the header from a file and allow access to elements
  130. /// @param sopInstanceUID A string with the uid for a given instance
  131. /// (corresponding file will be found via database)
  132. /// @param fileName Full path to a dicom file to load.
  133. /// @param key A group,element tag in zero-filled hex
  134. Q_INVOKABLE void loadInstanceHeader (const QString sopInstanceUID);
  135. Q_INVOKABLE void loadFileHeader (const QString fileName);
  136. Q_INVOKABLE QStringList headerKeys ();
  137. Q_INVOKABLE QString headerValue (const QString key);
  138. ///
  139. /// \brief application-defined tags of interest
  140. /// This list of tags is added to the internal tag cache during import
  141. /// operations. The list should be prepared by the application as
  142. /// a hint to the database that these tags are likely to be accessed
  143. /// later. Internally, the database will cache the values of these
  144. /// tags so that subsequent calls to fileValue or instanceValue will
  145. /// be able to use the cache rather than re-reading the file.
  146. /// @param tags should be a list of ascii hex group/element tags
  147. /// like "0008,0008" as in the instanceValue and fileValue calls
  148. void setTagsToPrecache(const QStringList tags);
  149. const QStringList tagsToPrecache();
  150. /// Insert into the database if not already exsting.
  151. /// @param dataset The dataset to store into the database. Usually, this is
  152. /// is a complete DICOM object, like a complete image. However
  153. /// the database also inserts partial objects, like studyl
  154. /// information to the database, even if no image data is
  155. /// contained. This can be helpful to store results from
  156. /// querying the PACS for patient/study/series or image
  157. /// information, where a full hierarchy is only constructed
  158. /// after some queries.
  159. /// @param storeFile If store file is set (default), then the dataset will
  160. /// be stored to disk. Note that in case of a memory-only
  161. /// database, this flag is ignored. Usually, this flag
  162. /// does only make sense if a full object is received.
  163. /// @param @generateThumbnail If true, a thumbnail is generated.
  164. ///
  165. Q_INVOKABLE void insert( const ctkDICOMItem& ctkDataset,
  166. bool storeFile, bool generateThumbnail);
  167. void insert ( DcmItem *item,
  168. bool storeFile = true, bool generateThumbnail = true);
  169. Q_INVOKABLE void insert ( const QString& filePath,
  170. bool storeFile = true, bool generateThumbnail = true,
  171. bool createHierarchy = true,
  172. const QString& destinationDirectoryName = QString() );
  173. /// Reset cached item IDs to make sure previous
  174. /// inserts do not interfere with upcoming insert operations.
  175. /// Typically, it should be call just before a batch of files
  176. /// insertion is started.
  177. ///
  178. /// This has to be called before an insert() call if there is a chance
  179. /// that items have been deleted from the database since the
  180. /// the last insert() call. If there has been not been any insert() calls since
  181. /// connected to the database, then it should be called before the first
  182. /// insert().
  183. Q_INVOKABLE void prepareInsert();
  184. /// Check if file is already in database and up-to-date
  185. Q_INVOKABLE bool fileExistsAndUpToDate(const QString& filePath);
  186. /// remove the series from the database, including images and
  187. /// thumbnails
  188. Q_INVOKABLE bool removeSeries(const QString& seriesInstanceUID);
  189. Q_INVOKABLE bool removeStudy(const QString& studyInstanceUID);
  190. Q_INVOKABLE bool removePatient(const QString& patientID);
  191. Q_INVOKABLE bool cleanup();
  192. ///
  193. /// \brief access element values for given instance
  194. /// @param sopInstanceUID A string with the uid for a given instance
  195. /// (corresponding file will be found via database)
  196. /// @param fileName Full path to a dicom file to load.
  197. /// @param key A group,element tag in zero-filled hex
  198. /// @param group The group portion of the tag as an integer
  199. /// @param element The element portion of the tag as an integer
  200. /// @Returns empty string if element is missing
  201. Q_INVOKABLE QString instanceValue (const QString sopInstanceUID, const QString tag);
  202. Q_INVOKABLE QString instanceValue (const QString sopInstanceUID, const unsigned short group, const unsigned short element);
  203. Q_INVOKABLE QString fileValue (const QString fileName, const QString tag);
  204. Q_INVOKABLE QString fileValue (const QString fileName, const unsigned short group, const unsigned short element);
  205. Q_INVOKABLE bool tagToGroupElement (const QString tag, unsigned short& group, unsigned short& element);
  206. Q_INVOKABLE QString groupElementToTag (const unsigned short& group, const unsigned short& element);
  207. ///
  208. /// \brief store values of previously requested instance elements
  209. /// These are meant to be internal methods used by the instanceValue and fileValue
  210. /// methods, but they can be used by calling classes to populate or access
  211. /// instance tag values as needed.
  212. /// @param sopInstanceUID A string with the uid for a given instance
  213. /// (corresponding file will be found via database)
  214. /// @param key A group,element tag in zero-filled hex
  215. /// @Returns empty string if element for uid is missing from cache
  216. ///
  217. /// Lightweight check of tag cache existence (once db check per runtime)
  218. Q_INVOKABLE bool tagCacheExists ();
  219. /// Create a tagCache in the current database. Delete the existing one if it exists.
  220. Q_INVOKABLE bool initializeTagCache ();
  221. /// Return the value of a cached tag
  222. Q_INVOKABLE QString cachedTag (const QString sopInstanceUID, const QString tag);
  223. /// Insert an instance tag's value into to the cache
  224. Q_INVOKABLE bool cacheTag (const QString sopInstanceUID, const QString tag, const QString value);
  225. /// Insert lists of tags into the cache as a batch query operation
  226. Q_INVOKABLE bool cacheTags (const QStringList sopInstanceUIDs, const QStringList tags, const QStringList values);
  227. Q_SIGNALS:
  228. /// Things inserted to database.
  229. /// patientAdded arguments:
  230. /// - int: database index of patient (unique) within CTK database
  231. /// - QString: patient ID (not unique across institutions)
  232. /// - QString: patient Name (not unique)
  233. /// - QString: patient Birth Date (not unique)
  234. void patientAdded(int, QString, QString, QString);
  235. /// studyAdded arguments:
  236. /// - studyUID (unique)
  237. void studyAdded(QString);
  238. /// seriesAdded arguments:
  239. /// - seriesUID (unique)
  240. void seriesAdded(QString);
  241. /// instance UID is provided
  242. /// instanceAdded arguments:
  243. /// - instanceUID (unique)
  244. void instanceAdded(QString);
  245. /// Indicates that an in-memory database has been updated
  246. void databaseChanged();
  247. /// Indicates that the schema is about to be updated and how many files will be processed
  248. void schemaUpdateStarted(int);
  249. /// Indicates progress in updating schema (int is file number, string is file name)
  250. void schemaUpdateProgress(int);
  251. void schemaUpdateProgress(QString);
  252. /// Indicates schema update finished
  253. void schemaUpdated();
  254. protected:
  255. QScopedPointer<ctkDICOMDatabasePrivate> d_ptr;
  256. private:
  257. Q_DECLARE_PRIVATE(ctkDICOMDatabase);
  258. Q_DISABLE_COPY(ctkDICOMDatabase);
  259. };
  260. #endif