| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 | /*=========================================================================  Library:   CTK   Copyright (c) 2010  Kitware Inc.  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License.  You may obtain a copy of the License at      http://www.commontk.org/LICENSE  Unless required by applicable law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and  limitations under the License. =========================================================================*/// Qt includes#include <QSqlQuery>#include <QSqlRecord>#include <QSqlError>#include <QVariant>#include <QDate>#include <QStringList>#include <QSet>#include <QFile>#include <QDirIterator>#include <QFileInfo>#include <QDebug>// ctkDICOM includes#include "ctkDICOMIndexerBase.h"#include "ctkLogger.h"// DCMTK includes#ifndef WIN32#define HAVE_CONFIG_H #endif#include <dcmtk/dcmdata/dcfilefo.h>#include <dcmtk/dcmdata/dcfilefo.h>#include <dcmtk/dcmdata/dcdeftag.h>#include <dcmtk/dcmdata/dcdatset.h>#include <dcmtk/ofstd/ofcond.h>#include <dcmtk/ofstd/ofstring.h>#include <dcmtk/ofstd/ofstd.h>        /* for class OFStandard */#include <dcmtk/dcmdata/dcddirif.h>   /* for class DicomDirInterface */static ctkLogger logger ( "org.commontk.dicom.DICOMIndexerBase" );//------------------------------------------------------------------------------class ctkDICOMIndexerBasePrivate: public ctkPrivate<ctkDICOMIndexerBase>{public:  ctkDICOMIndexerBasePrivate();  ~ctkDICOMIndexerBasePrivate();  QSqlDatabase db;};//------------------------------------------------------------------------------// ctkDICOMIndexerBasePrivate methods//------------------------------------------------------------------------------ctkDICOMIndexerBasePrivate::ctkDICOMIndexerBasePrivate(){}//------------------------------------------------------------------------------ctkDICOMIndexerBasePrivate::~ctkDICOMIndexerBasePrivate(){}//------------------------------------------------------------------------------// ctkDICOMIndexerBase methods//------------------------------------------------------------------------------ctkDICOMIndexerBase::ctkDICOMIndexerBase(){}//------------------------------------------------------------------------------ctkDICOMIndexerBase::~ctkDICOMIndexerBase(){}void ctkDICOMIndexerBase::setDatabase ( QSqlDatabase database ) {  CTK_D(ctkDICOMIndexerBase);  d->db = database;}const QSqlDatabase& ctkDICOMIndexerBase::database () const {  CTK_D(const ctkDICOMIndexerBase);  return d->db;}void ctkDICOMIndexerBase::insert ( DcmDataset *dataset ) {  this->insert ( dataset, QString() );}void ctkDICOMIndexerBase::insert ( DcmDataset *dataset, QString filename ) {  CTK_D(ctkDICOMIndexerBase);  // Check to see if the file has already been loaded  QSqlQuery fileExists ( d->db );  fileExists.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");   fileExists.bindValue(0,filename);  fileExists.exec();  if ( fileExists.next() && QFileInfo(filename).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) )    {    logger.debug ( "File " + filename + " 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_PatientsName, patientsName);  dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);  dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);  dataset->findAndGetOFString(DCM_PatientID, patientID);  dataset->findAndGetOFString(DCM_PatientsBirthDate, patientsBirthDate);  dataset->findAndGetOFString(DCM_PatientsBirthTime, patientsBirthTime);  dataset->findAndGetOFString(DCM_PatientsSex, patientsSex);  dataset->findAndGetOFString(DCM_PatientsAge, 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_PerformingPhysiciansName, performingPhysiciansName);  dataset->findAndGetOFString(DCM_ReferringPhysiciansName, 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);  QSqlQuery check_exists_query(d->db);  //The patient UID is a unique number within the database, generated by the sqlite autoincrement  int patientUID = -1;  if ( patientID != "" && 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())      {      patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt();      }    else      {      // Insert it      QSqlQuery statement ( d->db );      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() ) );      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 ) );      }    }  if ( 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 statement ( d->db );      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() )        {        logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );        }      }    }  if ( seriesInstanceUID != "" )    {    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 statement ( d->db );      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() )        {        logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() );        }      }    }  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 statement ( d->db );      statement.prepare ( "INSERT INTO Images ( 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ? )" );      statement.bindValue ( 0, filename );      statement.bindValue ( 1, QString ( seriesInstanceUID.c_str() ) );      statement.bindValue ( 2, QDateTime::currentDateTime() );      statement.exec();      }    }}
 |