Beispiel #1
0
//------------------------------------------------------------------------------
void ctkDICOMDatabase::insert ( const QString& filePath, bool storeFile, bool generateThumbnail, bool createHierarchy, const QString& destinationDirectoryName)
{
  Q_D(ctkDICOMDatabase);
  Q_UNUSED(createHierarchy);
  Q_UNUSED(destinationDirectoryName);

  /// first we check if the file is already in the database
  if (fileExistsAndUpToDate(filePath))
  {
    logger.debug( "File " + filePath + " already added.");
    return;
  }

  logger.debug( "Processing " + filePath );

  std::string filename = filePath.toStdString();

  DcmFileFormat fileformat;
  ctkDICOMDataset ctkDataset;

  ctkDataset.InitializeFromFile(filePath);
  if ( ctkDataset.IsInitialized() )
  {
    d->insert( ctkDataset, filePath, storeFile, generateThumbnail );
  }
  else
  {
    logger.warn(QString("Could not read DICOM file:") + filePath);
  }
}
Beispiel #2
0
//------------------------------------------------------------------------------
bool ctkDICOMRetrievePrivate::initializeSCU( const QString& studyInstanceUID,
                                         const QString& seriesInstanceUID,
                                         const RetrieveType retrieveType,
                                         DcmDataset *retrieveParameters)
{
  if ( !this->Database )
    {
    logger.error ( "No Database for retrieve transaction" );
    return false;
    }

  // If we like to query another server than before, be sure to disconnect first
  if (this->SCU.isConnected() && this->ConnectionParamsChanged)
  {
    this->SCU.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
  }
  // Connect to server if not already connected
  if (!this->SCU.isConnected())
    {
    // Check and initialize networking parameters in DCMTK
    if ( !this->SCU.initNetwork().good() )
      {
      logger.error ( "Error initializing the network" );
      return false;
      }
    // Negotiate (i.e. start the) association
    logger.debug ( "Negotiating Association" );

    if ( !this->SCU.negotiateAssociation().good() )
      {
      logger.error ( "Error negotiating association" );
      return false;;
      }
    }

  this->ConnectionParamsChanged = false;
  // Setup query about what to be received from the PACS
  logger.debug ( "Setting Retrieve Parameters" );
  if ( retrieveType == RetrieveSeries )
    {
    retrieveParameters->putAndInsertString ( DCM_QueryRetrieveLevel, "SERIES" );
    retrieveParameters->putAndInsertString ( DCM_SeriesInstanceUID, 
                                                seriesInstanceUID.toStdString().c_str() );
    // Always required to send all highler level unique keys, so add study here (we are in Study Root)
    retrieveParameters->putAndInsertString ( DCM_StudyInstanceUID, 
                                                studyInstanceUID.toStdString().c_str() );  //TODO
    }
  else
    {
    retrieveParameters->putAndInsertString ( DCM_QueryRetrieveLevel, "STUDY" );
    retrieveParameters->putAndInsertString ( DCM_StudyInstanceUID, 
                                                studyInstanceUID.toStdString().c_str() );
    }
  return true;
}
// --------------------------------------------------------------------------
void ctkWorkflowGroupBox::updateGroupBox(ctkWorkflowStep* currentStep)
{
  Q_D(ctkWorkflowGroupBox);

  d->StepShownPreviously = d->StepShownCurrently;
  d->StepShownCurrently = currentStep;

  if (currentStep)
    { 
    this->setTitle(currentStep->name());
    this->setSubTitle(currentStep->description());
    this->setErrorText(currentStep->statusText());

    // don't show textual elements if they are empty
    d->SubTitleTextBrowser->setVisible(!this->subTitle().isEmpty());
    d->PreTextBrowser->setVisible(!this->preText().isEmpty());
    d->PostTextBrowser->setVisible(!this->postText().isEmpty());
    d->ErrorTextBrowser->setVisible(!this->errorText().isEmpty());
    }

  // disable/hide the previously shown step
  if (ctkWorkflowWidgetStep* prevStep = dynamic_cast<ctkWorkflowWidgetStep*>(d->StepShownPreviously))
    {
    logger.debug(QString("updateClientArea - hiding %1").arg(prevStep->name()));
    if (QWidget* stepArea = prevStep->stepArea())
      {
      stepArea->setEnabled(false);
      if (d->HideWidgetsOfNonCurrentSteps)
        {
        stepArea->hide();
        }
      }
    }
  
  ctkWorkflowWidgetStep* currentWidgetStep = dynamic_cast<ctkWorkflowWidgetStep*>(currentStep);
  // show/enable the current step
  if (currentWidgetStep)
    {
    currentWidgetStep->showUserInterface();

    if (QWidget* stepArea = currentWidgetStep->stepArea())
      {
      // add the step's client area to the widget if we haven't before
      if (!this->isAncestorOf(stepArea))
        {
        d->ClientAreaLayout->addWidget(stepArea);
        }

      stepArea->setEnabled(true);
      stepArea->show();
      }
      }
    
}
Beispiel #4
0
//------------------------------------------------------------------------------
void ctkDICOMDatabasePrivate::registerCompressionLibraries(){
    logger.debug("Register compression libraries");
    // Register the JPEG libraries in case we need them
    //   (registration only happens once, so it's okay to call repeatedly)
    // register global JPEG decompression codecs
    DJDecoderRegistration::registerCodecs();
    // register global JPEG compression codecs
    DJEncoderRegistration::registerCodecs();
    // register RLE compression codec
    DcmRLEEncoderRegistration::registerCodecs();
    // register RLE decompression codec
    DcmRLEDecoderRegistration::registerCodecs();
}
Beispiel #5
0
//------------------------------------------------------------------------------
bool ctkDICOMDatabasePrivate::loggedExec(QSqlQuery& query, const QString& queryString)
{
  bool success;
  if (queryString.compare(""))
    {
    success = query.exec(queryString);
    }
  else
    {
    success = query.exec();
    }
  if (!success)
    {
    QSqlError sqlError = query.lastError();
    logger.debug( "SQL failed\n Bad SQL: " + query.lastQuery());
    logger.debug( "Error text: " + sqlError.text());
    }
  else
    {
  logger.debug( "SQL worked!\n SQL: " + query.lastQuery());
    }
  return (success);
}
Beispiel #6
0
// -------------------------------------------------------------------------
void ctkDICOMDatasetView::displayImage(int imageIndex){
  Q_D(ctkDICOMDatasetView);

  if(d->CurrentImageIndex.isValid())
    {
      QModelIndex seriesIndex = d->CurrentImageIndex.parent();
      ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(seriesIndex.model()));

      if(model)
        {
          if(imageIndex >= 0 && imageIndex < model->rowCount(seriesIndex))
            {
            this->onModelSelected(model->index(imageIndex, 0, seriesIndex));
            }
          else
            {
            logger.debug("out of index");
            }
        }
    }
}
//----------------------------------------------------------------------------
void ctkDICOMThumbnailListWidgetPrivate
::addThumbnailWidget(const QModelIndex& imageIndex,
                     const QModelIndex& sourceIndex, const QString &text)
{
  ctkDICOMModel* model = const_cast<ctkDICOMModel*>(
    qobject_cast<const ctkDICOMModel*>(imageIndex.model()));

  if(!model)
    {
    return;
    }
  QModelIndex seriesIndex = imageIndex.parent();
  QModelIndex studyIndex = seriesIndex.parent();

  QString thumbnailPath = this->DatabaseDirectory +
                          "/thumbs/" + model->data(studyIndex ,ctkDICOMModel::UIDRole).toString() + "/" +
                          model->data(seriesIndex ,ctkDICOMModel::UIDRole).toString() + "/" +
                          model->data(imageIndex, ctkDICOMModel::UIDRole).toString() + ".png";
  if(!QFileInfo(thumbnailPath).exists())
    {
    return;
    }
  ctkThumbnailLabel* widget = new ctkThumbnailLabel(this->ScrollAreaContentWidget);

  QString widgetLabel = text;
  widget->setText( widgetLabel );
  QPixmap pix(thumbnailPath);
  logger.debug("Setting pixmap to " + thumbnailPath);
  if(this->ThumbnailSize.isValid())
    {
    widget->setFixedSize(this->ThumbnailSize);
    }
  widget->setPixmap(pix);

  QVariant var;
  var.setValue(QPersistentModelIndex(sourceIndex));
  widget->setProperty("sourceIndex", var);

  this->addThumbnail(widget);
}
//----------------------------------------------------------------------------
void ctkDICOMThumbnailListWidgetPrivate
::addSeriesThumbnails(const QModelIndex &index)
{
  QModelIndex studyIndex = index.parent();
  QModelIndex seriesIndex = index;

  ctkDICOMModel* model = const_cast<ctkDICOMModel*>(qobject_cast<const ctkDICOMModel*>(index.model()));

  if (!model)
    {
    return;
    }
  model->fetchMore(seriesIndex);

  const int imageCount = model->rowCount(seriesIndex);
  logger.debug(QString("Thumbs: %1").arg(imageCount));
  for (int i = 0 ; i < imageCount ; i++ )
    {
    QModelIndex imageIndex = seriesIndex.child(i,0);

    this->addThumbnailWidget(imageIndex, imageIndex, QString("Image %1").arg(i));
    }
}
Beispiel #9
0
//------------------------------------------------------------------------------
bool ctkDICOMRetrievePrivate::retrieve ( QString UID, RetrieveType retriveType ) {

  if ( !this->RetrieveDatabase )
    {
    logger.error ( "Must have RetrieveDatabase for retrieve transaction" );
    return false;
    }

  // Register the JPEG libraries in case we need them
  //   (registration only happens once, so it's okay to call repeatedly)
  // register global JPEG decompression codecs
  DJDecoderRegistration::registerCodecs();
  // register global JPEG compression codecs
  DJEncoderRegistration::registerCodecs();
  // register RLE compression codec
  DcmRLEEncoderRegistration::registerCodecs();
  // register RLE decompression codec
  DcmRLEDecoderRegistration::registerCodecs();

  // Set the DCMTK log level
  log4cplus::Logger rootLogger = log4cplus::Logger::getRoot();
  rootLogger.setLogLevel(log4cplus::DEBUG_LOG_LEVEL);

  // TODO: use this->SCU instead ?
  DcmSCU scu;
  scu.setAETitle ( OFString(this->CallingAETitle.toStdString().c_str()) );
  scu.setPort ( this->CallingPort );
  scu.setPeerAETitle ( OFString(this->CalledAETitle.toStdString().c_str()) );
  scu.setPeerHostName ( OFString(this->Host.toStdString().c_str()) );
  scu.setPeerPort ( this->CalledPort );
  scu.setMoveDestinationAETitle ( OFString(this->MoveDestinationAETitle.toStdString().c_str()) );

  logger.info ( "Setting Transfer Syntaxes" );
  OFList<OFString> transferSyntaxes;
  transferSyntaxes.push_back ( UID_LittleEndianExplicitTransferSyntax );
  transferSyntaxes.push_back ( UID_BigEndianExplicitTransferSyntax );
  transferSyntaxes.push_back ( UID_LittleEndianImplicitTransferSyntax );
  scu.addPresentationContext ( UID_FINDStudyRootQueryRetrieveInformationModel, transferSyntaxes );
  scu.addPresentationContext ( UID_MOVEStudyRootQueryRetrieveInformationModel, transferSyntaxes );

  if ( !scu.initNetwork().good() ) 
    {
    logger.error ( "Error initializing the network" );
    return false;
    }
  logger.debug ( "Negotiating Association" );
  if ( !scu.negotiateAssociation().good() )
    {
    logger.error ( "Error negotiating association" );
    return false;;
    }

  logger.debug ( "Setting Parameters" );
  // Clear the query
  unsigned long elements = this->parameters->card();
  // Clean it out
  for ( unsigned long i = 0; i < elements; i++ ) 
    {
    this->parameters->remove ( 0ul );
    }
  if ( retriveType == RetrieveSeries )
    {
    this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "SERIES" );
    this->parameters->putAndInsertString ( DCM_SeriesInstanceUID, UID.toStdString().c_str() );
    } 
  else
    {
    this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "STUDY" );
    this->parameters->putAndInsertString ( DCM_StudyInstanceUID, UID.toStdString().c_str() );  
    }

  logger.debug ( "Sending Move Request" );
  MOVEResponses *responses = new MOVEResponses();
  OFCondition status = scu.sendMOVERequest ( 0, this->parameters, responses );
  if (!status.good())
    {
    logger.error ( "MOVE Request failed: " + QString ( status.text() ) );
    return false;
    }

  logger.debug ( "Find succeded" );

  logger.debug ( "Making Output Directory" );
  QDir directory = QDir( RetrieveDatabase->databaseDirectory() );

  if ( responses->begin() == responses->end() )
    {
    logger.error ( "No responses!" );
    throw std::runtime_error( std::string("No responses!") );
    }

  // Write the responses out to disk
  for ( OFListIterator(FINDResponse*) it = responses->begin(); it != responses->end(); it++ )
    {
    DcmDataset *dataset = (*it)->m_dataset;
    if ( dataset != NULL )
      {
      logger.debug ( "Got a valid dataset" );
      // Save in correct directory
      E_TransferSyntax output_transfersyntax = dataset->getOriginalXfer();
      dataset->chooseRepresentation( output_transfersyntax, NULL );
        
      if ( !dataset->canWriteXfer( output_transfersyntax ) )
        {
        // Pick EXS_LittleEndianExplicit as our default
        output_transfersyntax = EXS_LittleEndianExplicit;
        }
        
      DcmXfer opt_oxferSyn( output_transfersyntax );
      if ( !dataset->chooseRepresentation( opt_oxferSyn.getXfer(), NULL ).bad() )
        {
        DcmFileFormat* fileformat = new DcmFileFormat ( dataset );
          
        // Follow dcmdjpeg example
        fileformat->loadAllDataIntoMemory();
        OFString SOPInstanceUID;
        dataset->findAndGetOFString ( DCM_SOPInstanceUID, SOPInstanceUID );
        QFileInfo fi ( directory, QString ( SOPInstanceUID.c_str() ) );
        logger.debug ( "Saving file: " + fi.absoluteFilePath() );
        status = fileformat->saveFile ( fi.absoluteFilePath().toStdString().c_str(), opt_oxferSyn.getXfer() );
        if ( !status.good() )
          {
          logger.error ( "Error saving file: " + fi.absoluteFilePath() + " Error is " + status.text() );
          }

        RetrieveDatabase->insert( dataset, true );
          
        delete fileformat;
        }
      }
    }


  delete responses;
  //if ( !scu.dropNetwork().good() ) 
    //{
    //logger.error ( "Error dropping the network" );
    //return false;
    //}
  return true;
}
Beispiel #10
0
//------------------------------------------------------------------------------
void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool generateThumbnail)
{
  Q_D(ctkDICOMDatabase);

  if (!dataset)
    {
    return;
    }
  // Check to see if the file has already been loaded
  OFString sopInstanceUID ;
  dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);

  QSqlQuery fileExists ( d->Database );
  fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == ?");
  fileExists.bindValue(0,QString(sopInstanceUID.c_str()));
  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);

  // store the file if the database is not in memomry
  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();
    destinationDir.mkpath(studySeriesDirectory);

    filename = databaseDirectory() + "/dicom/" + pathForDataset(dataset);
    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;
      return;
      }
    delete fileformat;
  }


  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 != "" )
    {
    //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->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 ) );
      }
    }

  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->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() )
        {
        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->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() )
        {
        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->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();
      }
    }

  if(generateThumbnail){
      if(d->thumbnailGenerator){
        QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + QString(seriesInstanceUID.c_str());
        //Create thumbnail here
        QString thumbnailPath = databaseDirectory() +
                            "/thumbs/" + this->pathForDataset(dataset) + ".png";
                            //QString(studyInstanceUID.c_str()) + "/" +
                            //QString(seriesInstanceUID.c_str()) + "/" +
                            //QString(sopInstanceUID.c_str()) + ".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);
        }
      }
  }

  if (isInMemory())
    {
      emit databaseChanged();
    }
}
Beispiel #11
0
//------------------------------------------------------------------------------
bool ctkDICOMRetrievePrivate::get ( const QString& studyInstanceUID,
                                         const QString& seriesInstanceUID,
                                         const RetrieveType retrieveType )
{
  Q_Q(ctkDICOMRetrieve);

  DcmDataset *retrieveParameters = new DcmDataset();
  if (! this->initializeSCU(studyInstanceUID, seriesInstanceUID, retrieveType, retrieveParameters) )
    {
    delete retrieveParameters;
    return false;
    }

  // Issue request
  logger.debug ( "Sending Get Request" );
  emit q->progress("Sending Get Request");
  emit q->progress(0);
  OFList<RetrieveResponse*> responses;
  T_ASC_PresentationContextID presID = this->SCU.findPresentationContextID(
                                          UID_GETStudyRootQueryRetrieveInformationModel, 
                                          "" /* don't care about transfer syntax */ );
  if (presID == 0)
    {
    logger.error ( "GET Request failed: No valid Study Root GET Presentation Context available" );
    if (!this->KeepAssociationOpen)
      {
      this->SCU.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
      }
    delete retrieveParameters;
    return false;
    }

  emit q->progress("Found Presentation Context");
  emit q->progress(1);

  // do the actual move request
  OFCondition status = this->SCU.sendCGETRequest ( 
                          presID, retrieveParameters, &responses );

  emit q->progress("Sent Get Request");
  emit q->progress(2);

  // Close association if we do not want to explicitly keep it open
  if (!this->KeepAssociationOpen)
    {
    this->SCU.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
    }
  // Free some (little) memory
  delete retrieveParameters;

  // If we do not receive a single response, something is fishy
  if ( responses.begin() == responses.end() )
    {
    logger.error ( "No responses received at all! (at least one empty response always expected)" );
    //throw std::runtime_error( std::string("No responses received from server!") );
    emit q->progress("No Responses from Server!");
    return false;
    }

  emit q->progress("Got Responses");
  emit q->progress(3);

  /* The server is permitted to acknowledge every image that was received, or
   * to send a single move response.
   * If there is only a single response, this can mean the following:
   * 1) No images to transfer (Status Success and Number of Completed Subops = 0)
   * 2) All images transferred (Status Success and Number of Completed Subops > 0)
   * 3) Error code, i.e. no images transferred
   * 4) Warning (one or more failures, i.e. some images transferred)
   */
  if ( responses.size() == 1 )
    {
    RetrieveResponse* rsp = *responses.begin();
    logger.debug ( "GET response receveid with status: " + 
                      QString(DU_cmoveStatusString(rsp->m_status)) );

    if ( (rsp->m_status == STATUS_Success) 
            || (rsp->m_status == STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures))
      {
      if (rsp->m_numberOfCompletedSubops == 0)
        {
        logger.error ( "No images transferred by PACS!" );
        //throw std::runtime_error( std::string("No images transferred by PACS!") );
        return false;
        }
      }
    else
      {
      logger.error("GET request failed, server does report error");
      QString statusDetail("No details");
      if (rsp->m_statusDetail != NULL)
        {
         std::ostringstream out;
        rsp->m_statusDetail->print(out);
        statusDetail = "Status Detail: " + statusDetail.fromStdString(out.str());
        }
      statusDetail.prepend("GET request failed: ");
      logger.error(statusDetail);
      //throw std::runtime_error( statusDetail.toStdString() );
      return false;
      }
    }
  // Select the last GET response to output meaningful status information
  OFIterator<RetrieveResponse*> it = responses.begin();
  Uint32 numResults = responses.size();
  for (Uint32 i = 1; i < numResults; i++)
    {
    it++;
    }
  logger.debug ( "GET responses report for study: " + studyInstanceUID +"\n"
    + QString::number(static_cast<unsigned int>((*it)->m_numberOfCompletedSubops))
        + " images transferred, and\n"
    + QString::number(static_cast<unsigned int>((*it)->m_numberOfWarningSubops))
        + " images transferred with warning, and\n"
    + QString::number(static_cast<unsigned int>((*it)->m_numberOfFailedSubops))
        + " images transfers failed");

  emit q->progress("Finished Get");
  emit q->progress(100);

  return true;
}
Beispiel #12
0
bool ctkDICOMDatabase::removeSeries(const QString& seriesInstanceUID)
{
  Q_D(ctkDICOMDatabase);

  // get all images from series
  QSqlQuery fileExists ( d->Database );
  fileExists.prepare("SELECT Filename, SOPInstanceUID, StudyInstanceUID FROM Images,Series WHERE Series.SeriesInstanceUID = Images.SeriesInstanceUID AND Images.SeriesInstanceUID = :seriesID");
  fileExists.bindValue(":seriesID",seriesInstanceUID);
  bool success = fileExists.exec();
  if (!success)
  {
    logger.error("SQLITE ERROR: " + fileExists.lastError().driverText());
    return false;
  }

  QList< QPair<QString,QString> > removeList;
  while ( fileExists.next() )
  {
    QString dbFilePath = fileExists.value(fileExists.record().indexOf("Filename")).toString();
    QString sopInstanceUID = fileExists.value(fileExists.record().indexOf("SOPInstanceUID")).toString();
    QString studyInstanceUID = fileExists.value(fileExists.record().indexOf("StudyInstanceUID")).toString();
    QString internalFilePath = studyInstanceUID + "/" + seriesInstanceUID + "/" + sopInstanceUID;
    removeList << qMakePair(dbFilePath,internalFilePath);
  }

  QSqlQuery fileRemove ( d->Database );
  fileRemove.prepare("DELETE FROM Images WHERE SeriesInstanceUID == :seriesID");
  fileRemove.bindValue(":seriesID",seriesInstanceUID);
  logger.debug("SQLITE: removing seriesInstanceUID " + seriesInstanceUID);
  success = fileRemove.exec();
  if (!success)
  {
    logger.error("SQLITE ERROR: could not remove seriesInstanceUID " + seriesInstanceUID);
    logger.error("SQLITE ERROR: " + fileRemove.lastError().driverText());
  }
  
  QPair<QString,QString> fileToRemove;
  foreach (fileToRemove, removeList)
  {
    QString dbFilePath = fileToRemove.first;
    QString thumbnailToRemove = databaseDirectory() + "/thumbs/" + fileToRemove.second + ".png";

    // check that the file is below our internal storage
    if (dbFilePath.startsWith( databaseDirectory() + "/dicom/"))
    {
      if (!dbFilePath.endsWith(fileToRemove.second))
      {
        logger.error("Database inconsistency detected during delete!");
        continue;
      }
      if (QFile( dbFilePath ).remove())
      {
        logger.debug("Removed file " + dbFilePath );
      }
      else
      {
        logger.warn("Failed to remove file " + dbFilePath );
      }
    }
    if (QFile( thumbnailToRemove ).remove())
      {
        logger.debug("Removed thumbnail " + thumbnailToRemove);
      }
      else
      {
        logger.warn("Failed to remove thumbnail " + thumbnailToRemove);
      }
    }    
Beispiel #13
0
//------------------------------------------------------------------------------
void ctkDICOMDatabasePrivate::insert( const ctkDICOMDataset& ctkDataset, const QString& filePath, bool storeFile, bool generateThumbnail)
{
  Q_Q(ctkDICOMDatabase);

  // Check to see if the file has already been loaded
  // 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 ( Database );
  fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == :sopInstanceUID");
  fileExists.bindValue(":sopInstanceUID",sopInstanceUID);
  bool success = fileExists.exec();
  if (!success)
  {
    logger.error("SQLITE ERROR: " + fileExists.lastError().driverText());
    return;
  }
  qDebug() << "filename is: " << fileExists.value(1).toString();
  qDebug() << "modified date is: " << QFileInfo(fileExists.value(1).toString()).lastModified();
  qDebug() << "db mod date is: " << QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate);
  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;
  }

  //If the following fields can not be evaluated, cancel evaluation of the DICOM file
  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() && !patientID.isEmpty() )
  { // Use patient id as name if name is empty - can happen on anonymized datasets
    // see: http://www.na-mic.org/Bug/view.php?id=1643
    patientsName = patientID;
  }
  if ( patientsName.isEmpty() || studyInstanceUID.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 = filePath;
  if ( storeFile && !q->isInMemory() && !seriesInstanceUID.isEmpty() )
  {
    // QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID;
    QString destinationDirectoryName = q->databaseDirectory() + "/dicom/";
    QDir destinationDir(destinationDirectoryName);
    filename = destinationDirectoryName +
        studyInstanceUID + "/" +
        seriesInstanceUID + "/" +
        sopInstanceUID;

    destinationDir.mkpath(studyInstanceUID + "/" +
                          seriesInstanceUID);

    if(filePath.isEmpty())
    {
      logger.debug ( "Saving file: " + filename );

      if ( !ctkDataset.SaveToFile( filename) )
      {
        logger.error ( "Error saving file: " + filename );
        return;
      }
    }
    else
    {
      // we're inserting an existing file

      QFile currentFile( filePath );
      currentFile.copy(filename);
      logger.debug( "Copy file from: " + filePath );
      logger.debug( "Copy file to  : " + filename );
    }
  }

  QSqlQuery checkPatientExistsQuery(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;

  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 ( lastPatientID != patientID 
          || lastPatientsBirthDate != patientsBirthDate 
          || lastPatientsName != patientsName )
      {
      // 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 );
      loggedExec(checkPatientExistsQuery);

      if (checkPatientExistsQuery.next())
      {
        // we found him
        dbPatientID = checkPatientExistsQuery.value(checkPatientExistsQuery.record().indexOf("UID")).toInt();
      }
      else
        {
        // Insert it
        QSqlQuery insertPatientStatement ( 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 );
        loggedExec(insertPatientStatement);
        dbPatientID = insertPatientStatement.lastInsertId().toInt();
        logger.debug ( "New patient inserted: " + QString().setNum ( dbPatientID ) );
        }
      /// keep this for the next image
      lastPatientUID = dbPatientID;
      lastPatientID = patientID;
      lastPatientsBirthDate = patientsBirthDate;
      lastPatientsName = patientsName;
      }

    // Patient is in now. Let's continue with the study

    if ( studyInstanceUID != "" && lastStudyInstanceUID != studyInstanceUID )
    {
      QSqlQuery checkStudyExistsQuery (Database);
      checkStudyExistsQuery.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" );
      checkStudyExistsQuery.bindValue ( 0, studyInstanceUID );
      checkStudyExistsQuery.exec();
      if(!checkStudyExistsQuery.next())
      {
        QSqlQuery insertStudyStatement ( 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: " + insertStudyStatement.lastQuery() + " Error: " + insertStudyStatement.lastError().text() );
        }
        else
        {
          lastStudyInstanceUID = studyInstanceUID;
        }

      }
    }

    if ( seriesInstanceUID != "" && seriesInstanceUID != lastSeriesInstanceUID )
    {
      QSqlQuery checkSeriesExistsQuery (Database);
      checkSeriesExistsQuery.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" );
      checkSeriesExistsQuery.bindValue ( 0, seriesInstanceUID );
      logger.warn ( "Statement: " + checkSeriesExistsQuery.lastQuery() );
      loggedExec(checkSeriesExistsQuery);
      if(!checkSeriesExistsQuery.next())
      {
        QSqlQuery insertSeriesStatement ( 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: " 
            + insertSeriesStatement.lastQuery() 
            + " Error: " + insertSeriesStatement.lastError().text() );
          lastSeriesInstanceUID = "";
        }
        else
        {
          lastSeriesInstanceUID = seriesInstanceUID;
        }

      }
    }
    // TODO: what to do with imported files
    //
   if ( !filename.isEmpty() && !seriesInstanceUID.isEmpty() )
   {
     QSqlQuery checkImageExistsQuery (Database);
     checkImageExistsQuery.prepare ( "SELECT * FROM Images WHERE Filename = ?" );
     checkImageExistsQuery.bindValue ( 0, filename );
     checkImageExistsQuery.exec();
     if(!checkImageExistsQuery.next())
      {
        QSqlQuery insertImageStatement ( 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 && thumbnailGenerator && !seriesInstanceUID.isEmpty() )
      {
      QString studySeriesDirectory = studyInstanceUID + "/" + seriesInstanceUID;
      //Create thumbnail here
      QString thumbnailPath = q->databaseDirectory() +
        "/thumbs/" + studyInstanceUID + "/" + seriesInstanceUID 
        + "/" + sopInstanceUID + ".png";
      QFileInfo thumbnailInfo(thumbnailPath);
      if( !(thumbnailInfo.exists() 
            && (thumbnailInfo.lastModified() > QFileInfo(filename).lastModified())))
        {
        QDir(q->databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory);
        DicomImage dcmImage(QDir::toNativeSeparators(filename).toAscii());
        thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath);
        }
      }

    if (q->isInMemory())
      {
      emit q->databaseChanged();
      }
    }
}
Beispiel #14
0
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();
      }
    }
}
Beispiel #15
0
//------------------------------------------------------------------------------
void ctkDICOMIndexer::addFromDICOMDIR(ctkDICOMDatabase& ctkDICOMDatabase,
                                      const QString& directoryName,
                                      const QString& destinationDirectoryName
                                      )
{
    logger.debug( "############## addFromDICOMDIR ####################" );


    int fileNumber = 0;

    std::string dcmFilePath = directoryName.toStdString() + "/DICOMDIR";
    const char* dcmDirFilePath = dcmFilePath.c_str();

  // currently it is not supported to have multiple
  // parallel directory imports so the second call blocks
  //
  d->DirectoryImportWatcher.waitForFinished();

  const std::string src_directory(directoryName.toStdString());

    DcmDicomDir* dicomDir = new DcmDicomDir(dcmDirFilePath);
    DcmDirectoryRecord* rootRecord = &(dicomDir->getRootRecord());
    DcmDirectoryRecord* patientRecord = NULL;
    DcmDirectoryRecord* studyRecord = NULL;
    DcmDirectoryRecord* seriesRecord = NULL;
    DcmDirectoryRecord* fileRecord = NULL;


    QString finalFilePath=destinationDirectoryName + "/dicom";
    ////QDir destinationDir;
    ////QFile currentFile;

    ////Values to fill database
    //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, referencedFileName ;

    //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);
    ////int nrOfFiles(0);

    if(rootRecord != NULL)
    {
        //DcmDataset *patientDataset;

        while (((patientRecord = rootRecord->nextSub(patientRecord)) != NULL))
        {

            //if (patientRecord->findAndGetOFString(DCM_PatientName, patientsName).good()) {
            //    logger.debug( "Reading new Patients:" );
            //    logger.debug( "Patient's Name: " + QString(patientsName.c_str()) );

            //    patientDataset = new DcmDataset();

            //    patientRecord->findAndGetOFString(DCM_PatientID, patientID);
            //    patientRecord->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate);
            //    patientRecord->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime);
            //    patientRecord->findAndGetOFString(DCM_PatientSex, patientsSex);
            //    patientRecord->findAndGetOFString(DCM_PatientAge, patientsAge);
            //    patientRecord->findAndGetOFString(DCM_PatientComments, patientComments);

            //    patientDataset->putAndInsertOFStringArray(DCM_PatientName, patientsName);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientID, patientID);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientBirthDate, patientsBirthDate);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientBirthTime, patientsBirthTime);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientSex, patientsSex);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientAge, patientsAge);
            //    patientDataset->putAndInsertOFStringArray(DCM_PatientComments, patientComments);


            //}

            while (((studyRecord = patientRecord->nextSub(studyRecord)) != NULL))
            {

                //if (studyRecord->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID).good()) {
                //    logger.debug( "Reading new Studys:" );
                //    logger.debug( "Studies Name: " + QString(studyInstanceUID.c_str()) );

                //    studyRecord->findAndGetOFString(DCM_StudyID, studyID);
                //    studyRecord->findAndGetOFString(DCM_StudyDate, studyDate);
                //    studyRecord->findAndGetOFString(DCM_StudyTime, studyTime);
                //    studyRecord->findAndGetOFString(DCM_AccessionNumber, accessionNumber);
                //    studyRecord->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy);
                //    studyRecord->findAndGetOFString(DCM_InstitutionName, institutionName);
                //    studyRecord->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName);
                //    studyRecord->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician);
                //    studyRecord->findAndGetOFString(DCM_StudyDescription, studyDescription);

                //    patientDataset->putAndInsertOFStringArray(DCM_StudyInstanceUID, studyInstanceUID);
                //    patientDataset->putAndInsertOFStringArray(DCM_StudyID, studyID);
                //    patientDataset->putAndInsertOFStringArray(DCM_StudyDate, studyDate);
                //    patientDataset->putAndInsertOFStringArray(DCM_StudyTime, studyTime);
                //    patientDataset->putAndInsertOFStringArray(DCM_AccessionNumber, accessionNumber);
                //    patientDataset->putAndInsertOFStringArray(DCM_ModalitiesInStudy, modalitiesInStudy);
                //    patientDataset->putAndInsertOFStringArray(DCM_InstitutionName, institutionName);
                //    patientDataset->putAndInsertOFStringArray(DCM_PerformingPhysicianName, performingPhysiciansName);
                //    patientDataset->putAndInsertOFStringArray(DCM_ReferringPhysicianName, referringPhysician);
                //    patientDataset->putAndInsertOFStringArray(DCM_StudyDescription, studyDescription);

                    while (((seriesRecord = studyRecord->nextSub(seriesRecord)) != NULL))
                    {

                        //if (seriesRecord->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID).good()) {
                        //    logger.debug( "Reading new Series:" );
                        //    logger.debug( "Series Instance Name: " + QString(seriesInstanceUID.c_str()) );

                        //    seriesRecord->findAndGetOFString(DCM_SeriesDate, seriesDate);
                        //    seriesRecord->findAndGetOFString(DCM_SeriesTime, seriesTime);
                        //    seriesRecord->findAndGetOFString(DCM_SeriesDescription, seriesDescription);
                        //    seriesRecord->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined);
                        //    seriesRecord->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID);
                        //    seriesRecord->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent);
                        //    seriesRecord->findAndGetOFString(DCM_ScanningSequence, scanningSequence);
                        //    seriesRecord->findAndGetSint32(DCM_SeriesNumber, seriesNumber);
                        //    seriesRecord->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber);
                        //    seriesRecord->findAndGetSint32(DCM_EchoNumbers, echoNumber);
                        //    seriesRecord->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition);

                        //    patientDataset->putAndInsertOFStringArray(DCM_SeriesInstanceUID, seriesInstanceUID);
                        //    patientDataset->putAndInsertOFStringArray(DCM_SeriesDate, seriesDate);
                        //    patientDataset->putAndInsertOFStringArray(DCM_SeriesTime, seriesTime);
                        //    patientDataset->putAndInsertOFStringArray(DCM_SeriesDescription, seriesDescription);
                        //    patientDataset->putAndInsertOFStringArray(DCM_BodyPartExamined, bodyPartExamined);
                        //    patientDataset->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, frameOfReferenceUID);
                        //    patientDataset->putAndInsertOFStringArray(DCM_ContrastBolusAgent, contrastAgent);
                        //    patientDataset->putAndInsertOFStringArray(DCM_ScanningSequence, scanningSequence);
                        //    patientDataset->putAndInsertSint16(DCM_SeriesNumber, seriesNumber);
                        //    patientDataset->putAndInsertSint16(DCM_AcquisitionNumber, acquisitionNumber);
                        //    patientDataset->putAndInsertSint16(DCM_EchoNumbers, echoNumber);
                        //    patientDataset->putAndInsertSint16(DCM_TemporalPositionIdentifier, temporalPosition);

                        //}


                        while (((fileRecord = seriesRecord->nextSub(fileRecord)) != NULL))
                        {
                            //if (fileRecord->findAndGetOFStringArray(DCM_ReferencedSOPInstanceUIDInFile, sopInstanceUID).good()) {

                            //    fileRecord->findAndGetOFString(DCM_ReferencedFileID,referencedFileName);

                            //    patientDataset->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUIDInFile, sopInstanceUID);
                            //    patientDataset->putAndInsertOFStringArray(DCM_ReferencedFileID, referencedFileName);


                            //    const char* filename = fileRecord->getRecordsOriginFile();
                            //    if(filename)
                            //    {
                            //        this->addFile();
                            //    }

                            //}

                            
                            emit indexingFileNumber(++fileNumber);
                            //TODO insert Record into Database Info: the database.insert() interface must change.
                            //it must be possible to add records and dataset
                            //suggestion: change the interface to dcmItem
                        }

                    }
                }
            }

        emit foundFilesToIndex(fileNumber);
    }
    QString filePath((*iter).c_str());
    d->FilesToIndex << filePath;
    ++iter;
  }