Ejemplo n.º 1
0
int main(int argc, char** argv)
{
  // Check whether host and port are given
  if (argc < 3)
  {
    print_usage();
    return 2;
  } 
  
  std::string host = argv[1];
  unsigned int port = atoi(argv[2]);
  std::string peerAET  = "";
  if (argc > 3)
  {
    peerAET = argv[3];
  }
    
  // Setup SCU
  DcmSCU scu;
  scu.setPeerHostName(host);
  scu.setPeerPort(port);
  OFString verificationSOP = UID_VerificationSOPClass;
  OFList<OFString> ts;
  ts.push_back(UID_LittleEndianExplicitTransferSyntax);
  ts.push_back(UID_BigEndianExplicitTransferSyntax);  
  ts.push_back(UID_LittleEndianImplicitTransferSyntax);
  scu.addPresentationContext(verificationSOP, ts);
  if (peerAET != "")
  {
    scu.setPeerAETitle(peerAET);
  }
  OFCondition result = scu.initNetwork();
  if (result.bad())
  {
    std::cerr << "Error setting up SCU: " << result.text() << "\n";
    return 2;
  }
  
  // Negotiate association
  result = scu.negotiateAssociation();
  if (result.bad())
  {
    std::cerr << "Error negotiating association: " << result.text() << "\n";
    return 2;
  }
  
  // Issue ECHO request and let scu find presentation context itself (0)
  result = scu.sendECHORequest(0);
  if (result.bad())
  { 
    std::cerr << "Error issuing ECHO request or received rejecting response: " << result.text() << "\n";
    return 2;
  }
  std::cout << "Successfully sent DICOM Echo to host " << argv[1] << " on port " << argv[2] << "\n";
  return 0;
  
}
Ejemplo n.º 2
0
// Load our vtkImageData object from a list of DICOM image filenames...
// http://www.vtk.org/pipermail/vtkusers/2007-August/042635.html
void vtkDicom::load_dcmFiles(QStringList dcm_fileList) {
    DcmFileFormat dcm;
    std::string imgFname;
    std::cout << "vtkdicom: Files/Images(?): " << dcm_fileList.size() << "\n";
    for (int sei = 0; sei < dcm_fileList.size(); ++sei) {
        imgFname = dcm_fileList.at(sei).toLocal8Bit().constData();
        OFCondition status = dcm.loadFile(imgFname.c_str());
        if (!status.good()) {
            std::cout << "    vtkdicom: Error: cannot read file (" << status.text() << ")" << "\n";
            return;
        }
        if (sei == 0) {
            OFString acquisitionNumber, instanceNumber, imagePositionPatient, patientsName;
            DcmDataset *dcmDs = dcm.getDataset();
            dcmDs->findAndGetOFStringArray(DCM_ImagePositionPatient, imagePositionPatient);
            dcmDs->findAndGetOFString(DCM_AcquisitionNumber, acquisitionNumber);
            dcmDs->findAndGetOFString(DCM_InstanceNumber, instanceNumber);
            dcmDs->findAndGetOFString(DCM_PatientName, patientsName);
            std::cout << "vtkdicom: I#, IPP: " << instanceNumber << " - " << imagePositionPatient << "\n";
        }
        dcm.loadAllDataIntoMemory();
        const unsigned short* p = NULL;
        dcm.getDataset()->findAndGetUint16Array(DCM_PixelData, p);

    }
}
Ejemplo n.º 3
0
Series::InstanceUIDContainer Series::toSeriesInstanceUIDContainer(OFList< QRResponse* > responses)
{
    InstanceUIDContainer instanceUIDContainer;

    OFIterator< QRResponse* > it;
    DcmDataset dataset;
    OFCondition result;
    // Every while loop run will get all image for a specific study
    for (it = responses.begin(); it != responses.end(); ++it)
    {
        // Be sure we are not in the last response which does not have a dataset
        if ((*it)->m_dataset != NULL)
        {
            OFString seriesInstanceUID;
            result = (*it)->m_dataset->findAndGetOFStringArray(DCM_SeriesInstanceUID, seriesInstanceUID);
            // Only try to get study if we actually have study instance uid, otherwise skip it
            if (result.good())
            {
                instanceUIDContainer.push_back(seriesInstanceUID.c_str());
            }
            else
            {
                const std::string msg = "There is no \"SeriersInstanceUID\" tag in the selected series :"
                                        + std::string(result.text());
                throw ::fwPacsIO::exceptions::TagMissing(msg);
            }
        }
    }


    return instanceUIDContainer;
}
Ejemplo n.º 4
0
void
LocalService::SolveFile( 
  const boost::filesystem::path & fileName, const boost::filesystem::path & path,
  ResultSet &result)
{
  OFString ofStr;

  DcmFileFormat dfile;
  OFCondition cond = dfile.loadFile( fileName.string().data());
  if (! cond.good())
  {
    LOG( "Loading of " << fileName << " failed. ("  << cond.text() << ")" );
    return;
  }

  DcmDataset *dataSet = dfile.getDataset();

  TableRow row;
  SerieInfo serInfo;

  // load data and check if it is already in tree
  CheckDataSet( dataSet, serInfo, row, path.string());

  // look if this row is already in resultSet
  FoundStudiesSet::iterator found = m_alreadyFoundInRun.find(row.studyID);
  // if not, add it
  if( found == m_alreadyFoundInRun.end() )
  {
    m_alreadyFoundInRun.insert( FoundStudiesSet::value_type( row.studyID) );
    result.push_back( row);
  }
}
Ejemplo n.º 5
0
  OFCondition Internals::findScp(T_ASC_Association * assoc, 
                                 T_DIMSE_Message * msg, 
                                 T_ASC_PresentationContextID presID,
                                 IFindRequestHandler* findHandler,
                                 IWorklistRequestHandler* worklistHandler,
                                 const std::string& remoteIp,
                                 const std::string& remoteAet,
                                 const std::string& calledAet)
  {
    FindScpData data;
    data.lastRequest_ = NULL;
    data.findHandler_ = findHandler;
    data.worklistHandler_ = worklistHandler;
    data.remoteIp_ = &remoteIp;
    data.remoteAet_ = &remoteAet;
    data.calledAet_ = &calledAet;

    OFCondition cond = DIMSE_findProvider(assoc, presID, &msg->msg.CFindRQ, 
                                          FindScpCallback, &data,
                                          /*opt_blockMode*/ DIMSE_BLOCKING, 
                                          /*opt_dimse_timeout*/ 0);

    // if some error occured, dump corresponding information and remove the outfile if necessary
    if (cond.bad())
    {
      OFString temp_str;
      LOG(ERROR) << "Find SCP Failed: " << cond.text();
    }

    return cond;
  }
Ejemplo n.º 6
0
    bool DicomdirLoader::load(const std::string &studyinstanceuid, const Glib::ustring &dicomdir) {
        DcmDicomDir dir(dicomdir.c_str());
        OFCondition ret;

        if (busy() ) {
            return false;
        }

        if ( (ret=dir.error()) != EC_Normal ) {
            std::cout << "DicomdirLoader::load Error: " << ret.text() << std::endl;
            return false;
        }

        // Open DICOMDIR and look for StudyInstanceUID
        // Add all IMAGE record types to m_FileList and fill cache
        // FileLoader::Start
        DcmDirectoryRecord *studyRec = find_study(studyinstanceuid, dir);
        if ( !studyRec ) {
            std::cout << "DicomdirLoader::load Error: cannot find study" << std::endl;
            return false;
        }

        m_filelist = new std::list< Glib::ustring >;
        m_cache.clear();
        if ( !scan_study(studyinstanceuid, studyRec, dicomdir) ) {
            std::cout << "DicomdirLoader::load: no visible images" << std::endl;
            return false;
        }

        FileLoader::start();

        return true;

    }
// Caller is responsible for deallocating returned object
AnnotationCollection* DcmModel::ReadAnnotationCollectionFromFile(const std::string& fileName){
	DcmModelInternal dcmModelInternal(_uidPrefix);

	AnnotationCollection* pCollection = NULL;
	try
	{
		OFCondition ofCondition = dcmModelInternal.ReadDocFromFile(&pCollection, fileName);
		if (!ofCondition.good())
		{
			if (pCollection){
				delete pCollection;
				pCollection = NULL;
			}
			std::string err = std::string("Failed to load SR from file <").append(fileName).append(">:");
			err += ofCondition.text();
			dcmModelInternal.printDebug(std::string(__FILE__).append(": ").append(err).c_str());
		}
	}
	catch(const std::exception& ex)
	{
		std::string err = std::string("Error loading SR from file<").append(fileName).append(">:");
		err += ex.what();
		dcmModelInternal.printDebug(err.c_str());
	}
	return pCollection;
}
PACSRequestStatus::RetrieveRequestStatus RetrieveDICOMFilesFromPACS::retrieve(const QString &studyInstanceUID, const QString &seriesInstanceUID, const QString &sopInstanceUID)
{
    T_ASC_PresentationContextID presentationContextID;
    T_DIMSE_C_MoveRSP moveResponse;
    DcmDataset *statusDetail = NULL;
    m_pacsConnection = new PACSConnection(m_pacs);
    PACSRequestStatus::RetrieveRequestStatus retrieveRequestStatus;
    MoveSCPCallbackData moveSCPCallbackData;
    DcmDataset *dcmDatasetToRetrieve = getDcmDatasetOfImagesToRetrieve(studyInstanceUID, seriesInstanceUID, sopInstanceUID);
    m_numberOfImagesRetrieved = 0;

    // TODO S'hauria de comprovar que es tracti d'un PACS amb el servei de retrieve configurat
    if (!m_pacsConnection->connectToPACS(PACSConnection::RetrieveDICOMFiles))
    {
        ERROR_LOG("S'ha produit un error al intentar connectar al PACS per fer un retrieve. AE Title: " + m_pacs.getAETitle());
        return PACSRequestStatus::RetrieveCanNotConnectToPACS;
    }

    // Which presentation context should be used, It's important that the connection has MoveStudyRoot level
    T_ASC_Association *association = m_pacsConnection->getConnection();
    presentationContextID = ASC_findAcceptedPresentationContextID(association, MoveAbstractSyntax);
    if (presentationContextID == 0)
    {
        ERROR_LOG("No s'ha trobat cap presentation context valid");
        return PACSRequestStatus::RetrieveFailureOrRefused;
    }

    moveSCPCallbackData.association = association;
    moveSCPCallbackData.presentationContextId = presentationContextID;
    moveSCPCallbackData.retrieveDICOMFilesFromPACS = this;

    // Set the destination of the images to us
    T_DIMSE_C_MoveRQ moveRequest = getConfiguredMoveRequest(association);
    ASC_getAPTitles(association->params, moveRequest.MoveDestination, NULL, NULL);

    OFCondition condition = DIMSE_moveUser(association, presentationContextID, &moveRequest, dcmDatasetToRetrieve, moveCallback, &moveSCPCallbackData,
                                           DIMSE_BLOCKING, 0, m_pacsConnection->getNetwork(), subOperationCallback, this, &moveResponse, &statusDetail,
                                           NULL /*responseIdentifiers*/);

    if (condition.bad())
    {
        ERROR_LOG(QString("El metode descarrega no ha finalitzat correctament. Codi error: %1, descripcio error: %2").arg(condition.code())
                     .arg(condition.text()));
    }

    m_pacsConnection->disconnect();

    retrieveRequestStatus = getDIMSEStatusCodeAsRetrieveRequestStatus(moveResponse.DimseStatus);
    processServiceClassProviderResponseStatus(moveResponse.DimseStatus, statusDetail);
    
    // Dump status detail information if there is some
    if (statusDetail != NULL)
    {
        delete statusDetail;
    }

    delete dcmDatasetToRetrieve;

    return retrieveRequestStatus;
}
Ejemplo n.º 9
0
  OFCondition Internals::moveScp(T_ASC_Association * assoc, 
                                 T_DIMSE_Message * msg, 
                                 T_ASC_PresentationContextID presID,
                                 IMoveRequestHandler& handler,
                                 const std::string& remoteIp,
                                 const std::string& remoteAet,
                                 const std::string& calledAet)
  {
    MoveScpData data;
    data.target_ = std::string(msg->msg.CMoveRQ.MoveDestination);
    data.lastRequest_ = NULL;
    data.handler_ = &handler;
    data.remoteIp_ = &remoteIp;
    data.remoteAet_ = &remoteAet;
    data.calledAet_ = &calledAet;

    OFCondition cond = DIMSE_moveProvider(assoc, presID, &msg->msg.CMoveRQ, 
                                          MoveScpCallback, &data,
                                          /*opt_blockMode*/ DIMSE_BLOCKING, 
                                          /*opt_dimse_timeout*/ 0);

    // if some error occured, dump corresponding information and remove the outfile if necessary
    if (cond.bad())
    {
      OFString temp_str;
      LOG(ERROR) << "Move SCP Failed: " << cond.text();
    }

    return cond;
  }
Ejemplo n.º 10
0
    OFCondition AssociationCleanup(T_ASC_Association *assoc)
    {
      OFString temp_str;
      OFCondition cond = ASC_dropSCPAssociation(assoc);
      if (cond.bad())
      {
        LOG(FATAL) << cond.text();
        return cond;
      }

      cond = ASC_destroyAssociation(&assoc);
      if (cond.bad())
      {
        LOG(FATAL) << cond.text();
        return cond;
      }

      return cond;
    }
Ejemplo n.º 11
0
void ctkDICOMDataset::Deserialize()
{
  Q_D(ctkDICOMDataset);
  // read attribute m_ctkDICOMDataset
  // construct a DcmDataset from it
  // calls InitializeData(DcmDataset*)

  // this method can be called both from sub-classes when they get the InitializeData signal from the persistence framework
  // and from EnsureDcmDataSetIsInitialized() when a GetElement.. or SetElement.. method is called.

  if (d->m_DICOMDataSetInitialized) return; // only need to do this once

  QString stringbuffer = this->GetStoredSerialization();
  if ( stringbuffer.isEmpty() )
  {
    d->m_DICOMDataSetInitialized = true;
    return; // TODO nicer: hold three states: newly created / loaded but not initialized / restored from DB
  }


  //std::cerr << "** " << (void*)this << " ctkDICOMDataset: Deserialize Dataset from string of size " << stringbuffer.size() << "\n" << stringbuffer.toStdString() << std::endl;

  QByteArray qtArray = QByteArray::fromBase64( stringbuffer.toAscii() );
  //std::cerr << "** " << (void*)this << " ctkDICOMDataset: Deserialize Dataset from byte array of size " << qtArray.size() << std::endl;

  DcmInputBufferStream dcmbuffer;
  dcmbuffer.setBuffer( qtArray.data(), qtArray.size() );
  //std::cerr << "** Buffer state: " << dcmbuffer.status().code() << " " <<  dcmbuffer.good() << " " << dcmbuffer.eos() << " tell " << dcmbuffer.tell() << " avail " << dcmbuffer.avail() << std::endl;

  DcmDataset dataset;
  dataset.transferInit();
  //std::cerr << "** Dataset state: " << dataset.transferState() << std::endl << std::endl;
  OFCondition condition = dataset.read( dcmbuffer, EXS_LittleEndianImplicit );
  dataset.transferEnd();

  // do this in all cases, even when reading reported an error
  this->InitializeFromDataset(&dataset);

  if ( condition.bad() )
  {
    std::cerr << "** Condition code of Dataset::read() is "
              << condition.code() << std::endl;
    std::cerr << "** Buffer state: " << dcmbuffer.status().code()
              << " " <<  dcmbuffer.good()
              << " " << dcmbuffer.eos()
              << " tell " << dcmbuffer.tell()
              << " avail " << dcmbuffer.avail() << std::endl;
    std::cerr << "** Dataset state: "
              << static_cast<int>(dataset.transferState()) << std::endl;
    std::cerr << "Could not DcmDataset::read(..): "
              << condition.text() << std::endl;
    //throw std::invalid_argument( std::string("Could not DcmDataset::read(..): ") + condition.text() );
  }
}
bool DicomSurfaceSegmentationLoad::_loadDataset()
{
  bool success = false;

  SmartPtr_DCMDataSet newDataset(new DcmDataset());
  _datasetPointer = newDataset;

  const OFCondition status = _datasetPointer->loadFile(_filename.c_str(), EXS_LittleEndianExplicit);

	if(status.bad()) 
  {
    std::cerr << "Loading the dataset failed: " << status.text() << std::endl;
		throw std::exception(status.text());
	}
  else
  {
    success = true;
  }

  return success;
}
Status ConvertDicomToLittleEndian::convert(QString inputFile, QString outputFile)
{
    DcmFileFormat fileformat;
    DcmDataset *dataset = fileformat.getDataset();
    OFCondition error;
    Status state;
    // Transfer Syntax del fitxer d'entrada
    E_TransferSyntax opt_ixfer = EXS_Unknown;
    E_FileReadMode opt_readMode = ERM_autoDetect;
    E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit;
    QString descriptionError;
    E_EncodingType opt_oenctype = EET_ExplicitLength;
    E_GrpLenEncoding opt_oglenc = EGL_recalcGL;
    E_PaddingEncoding opt_opadenc = EPD_noChange;
    OFCmdUnsignedInt opt_filepad = 0;
    OFCmdUnsignedInt opt_itempad = 0;
    E_FileWriteMode writeMode = EWM_fileformat;

    error = fileformat.loadFile(qPrintable(QDir::toNativeSeparators(inputFile)), opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);

    if (error.bad())
    {
        ERROR_LOG(QString("No s'ha pogut obrir el fitxer a convertir LittleEndian %1, descripcio error: %2").arg(inputFile, error.text()));
        return state.setStatus(error);
    }
    dataset->loadAllDataIntoMemory();

    DcmXfer opt_oxferSyn(opt_oxfer);

    dataset->chooseRepresentation(opt_oxfer, NULL);

    if (!dataset->canWriteXfer(opt_oxfer))
    {
        descriptionError = "Error: no conversion to transfer syntax " + QString(opt_oxferSyn.getXferName()) + " possible";
        state.setStatus(qPrintable(descriptionError), false, 1300);
        ERROR_LOG(descriptionError);
        return state;
    }

    error = fileformat.saveFile(qPrintable(QDir::toNativeSeparators(outputFile)), opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc,
                                OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), writeMode);

    if (!error.good())
    {
        ERROR_LOG(QString("S'ha produit un error al intentar gravar la imatge %1 convertida a LittleEndian al path %2, descripcio error: %3")
                     .arg(inputFile, outputFile, error.text()));
    }

    return state.setStatus(error);
}
Ejemplo n.º 14
0
    OFCondition EchoScp( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID)
    {
      OFString temp_str;
      LOG(INFO) << "Received Echo Request";
      //LOG(DEBUG) << DIMSE_dumpMessage(temp_str, msg->msg.CEchoRQ, DIMSE_INCOMING, NULL, presID));

      /* the echo succeeded !! */
      OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, &msg->msg.CEchoRQ, STATUS_Success, NULL);
      if (cond.bad())
      {
        LOG(ERROR) << "Echo SCP Failed: " << cond.text();
      }
      return cond;
    }
Ejemplo n.º 15
0
 // print an error message to the console (stderr) that something went wrong with an attribute
 static void printAttributeErrorMessage(const DcmTagKey &key,
                                        const OFCondition &error,
                                        const char *operation)
 {
   if (error.bad())
   {
     OFString str;
     if (operation != NULL)
     {
       str = "cannot ";
       str += operation;
       str += " ";
     }
     LOG(ERROR) << error.text() << ": " << str << DcmTag(key).getTagName() << " " << key;
   }
 }
Ejemplo n.º 16
0
void vtkDicom::dumpDicomFile(std::string imgFname)
{
    DcmFileFormat dfile;
    OFCondition status = dfile.loadFile(imgFname.c_str());
    if (status.good()) {
        OFString acquisitionNumber, instanceNumber, imagePositionPatient, patientsName;
        dfile.loadAllDataIntoMemory();
        DcmDataset *dcmDs = dfile.getDataset();
        dcmDs->findAndGetOFStringArray(DCM_ImagePositionPatient, imagePositionPatient);
        dcmDs->findAndGetOFString(DCM_AcquisitionNumber, acquisitionNumber);
        dcmDs->findAndGetOFString(DCM_InstanceNumber, instanceNumber);
        dcmDs->findAndGetOFString(DCM_PatientName, patientsName);
        std::cout << "    " << instanceNumber << " - " << imagePositionPatient << "\n";
    } else {
        std::cout << "    Error: cannot read file (" << status.text() << ")" << "\n";
    }
}
Ejemplo n.º 17
0
void
LocalService::SolveFileGET( const boost::filesystem::path & fileName,
  const std::string &patientID,
	const std::string &studyID,
	const std::string &serieID,
  DicomObjSet &result,
  const std::string &path)
{
  OFString ofStr;

  DcmFileFormat dfile;
  OFCondition cond = dfile.loadFile( fileName.string().data());
  if (! cond.good())
  {
    LOG( "Loading of " << fileName << " failed. ("  << cond.text() << ")" );
    return;
  }

  DcmDataset *dataSet = dfile.getDataset();

  TableRow row;
  SerieInfo serInfo;

  // load data and check if it is already in tree
  CheckDataSet( dataSet, serInfo, row, path);

  // compare with wantend ones
  if( row.patientID == patientID
    && row.studyID == studyID
    && serInfo.id == serieID)
  {
    // if it mathes, insert new image into result
    DicomObj buddy;
    result.push_back( buddy);

    // copy dataset reference & init
    DicomObj *newOne = &result.back();
    newOne->Load( fileName.string() );
    newOne->Init();
  }
}
Ejemplo n.º 18
0
void ctkDICOMDataset::InitializeFromFile(const QString& filename,
                                         const E_TransferSyntax readXfer,
                                         const E_GrpLenEncoding groupLength,
                                         const Uint32 maxReadLength,
                                         const E_FileReadMode readMode)
{
  DcmDataset *dataset;

  DcmFileFormat fileformat;
  OFCondition status = fileformat.loadFile(filename.toAscii().data(), readXfer, groupLength, maxReadLength, readMode);
  dataset = fileformat.getAndRemoveDataset();

  if (!status.good())
  {
    qDebug() << "Could not load " << filename << "\nDCMTK says: " << status.text();
    delete dataset;
    return;
  }

  InitializeFromDataset(dataset, true);
}
Ejemplo n.º 19
0
OFCondition Association::SendEchoRequest()
{
        DIC_US status;
        DcmDataset *statusDetail = NULL;

        if (Stopped()) {
                return DUL_NETWORKCLOSED;
        }

        OFCondition cond = DIMSE_echoUser(assoc, ++msgId, DIMSE_BLOCKING, 0, &status, &statusDetail);
        if (cond.good()) {
                LOG_DEBUG(ambitolog, "DIMSE ECHO completed. Status: " << DU_cstoreStatusString(status));
        } else {
                LOG_DEBUG(ambitolog, "DIMSE ECHO Failed: " << cond.text());
        }

        if (statusDetail != NULL) {
                delete statusDetail;
        }

        return cond;
}
Ejemplo n.º 20
0
  void DicomServer::Stop()
  {
    if (continue_)
    {
      continue_ = false;

      if (pimpl_->thread_.joinable())
      {
        pimpl_->thread_.join();
      }

      pimpl_->workers_.reset(NULL);

      /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */
      /* is the counterpart of ASC_initializeNetwork(...) which was called above. */
      OFCondition cond = ASC_dropNetwork(&pimpl_->network_);
      if (cond.bad())
      {
        LOG(ERROR) << "Error while dropping the network: " << cond.text();
      }
    }
  }
Ejemplo n.º 21
0
    void open_dicomdir_series(const std::string& studyinstanceuid, const Glib::ustring& dicomdir, const sigc::slot< void, const Glib::RefPtr< ImagePool::Series >& >& resultslot) {
        DcmDicomDir dir(dicomdir.c_str());
        DcmDirectoryRecord *patRec;
        DcmDirectoryRecord *studyRec;
        DcmDirectoryRecord *seriesRec;
        OFCondition ret;

        if ( dir.error() != ECC_Normal ) {
            std::cout << "DICOMDIR Error: " << ret.text() << std::endl;
            return;
        }

        DcmDirectoryRecord &root = dir.getRootRecord();
        for ( patRec = root.nextSub(NULL); patRec!=NULL; patRec = root.nextSub(patRec) ) {
            switch ( patRec->getRecordType() ) {
            case ERT_Patient:
                for ( studyRec=patRec->nextSub(NULL); studyRec; studyRec = patRec->nextSub(studyRec) ) {
                    if ( studyRec->getRecordType()==ERT_Study ) {
                        OFString uid;
                        if ( studyRec->findAndGetOFString(DCM_StudyInstanceUID, uid)==ECC_Normal ) {
                            if ( studyinstanceuid == uid.c_str() ) {
                                open_dicomdir_series_result(dicomdir, patRec, studyRec, resultslot);
                                return;
                            }
                        }
                    }
                }
                break;
            case ERT_HangingProtocol:
                // FALLTHROUGH
            case ERT_Private:
                break;
            default:
                break;
            }
        }
        std::cout << "WARNING: study[" << studyinstanceuid << "] not found in DICOMDIR\n";
    }
Ejemplo n.º 22
0
void ctkDICOMDataset::Serialize()
{
  Q_D(ctkDICOMDataset);
  EnsureDcmDataSetIsInitialized();

  // store content of current DcmDataset (our parent) as QByteArray into m_ctkDICOMDataset
  Uint32 buffersize = 1024*1024; // reserve 1MB
  char* writebuffer = new char[buffersize];

  // write into buffer
  DcmOutputBufferStream dcmbuffer(writebuffer, buffersize);
  d->m_DcmDataset->transferInit();
  OFCondition condition = d->m_DcmDataset->write(dcmbuffer, EXS_LittleEndianImplicit, EET_UndefinedLength, NULL );
  d->m_DcmDataset->transferEnd();
  if ( condition.bad() )
  {
    std::cerr << "Could not DcmDataset::write(..): " << condition.text() << std::endl;
  }

  // get written contents of buffer
  offile_off_t datasetsize = 0;
  void* readbuffer = NULL;
  dcmbuffer.flushBuffer(readbuffer, datasetsize);

  //std::cerr << "** " << (void*)this << " ctkDICOMDataset: Serializing Dataset into " << datasetsize << " bytes" << std::endl;

  // construct Qt type from that contents
  QByteArray qtArray = QByteArray::fromRawData( static_cast<const char*>(readbuffer), datasetsize );
  //std::cerr << "** Buffer size: " << qtArray.size() << std::endl;
  QString stringbuffer = QString::fromAscii(qtArray.toBase64());

  //std::cerr << "** String of size " << stringbuffer.size() << " looks like this:\n" << stringbuffer.toStdString() << std::endl << std::endl;

  this->SetStoredSerialization( stringbuffer );

  delete[] writebuffer;
}
Ejemplo n.º 23
0
bool IODicom<T>::GetAttributes(PGCore::MetaData<T>& oMetaDataObject, const std::string &iFilePath)
{
#ifdef _DEBUG
    LOG0("{ IODicom::GetAttributes");
#endif

    if (iFilePath.empty())
    {
        LOG0("IO/IODicom::GetAttributes Empty filename");
        return false;
    }

#ifdef _PG_GDDCM_


#else
    OFCondition status = m_fileformat.loadFile(iFilePath.c_str());
    if (!status.good())
    {
        LOG2("IO/IODicom::GetAttributes: Cannot read dicom file %s: (%s).", iFilePath.c_str(), status.text());
        return false;
    }

#ifdef _DEBUG
    LOG2("\tIODicom::GetAttributes: Successfully read dicom file %s: (%s).", iFilePath.c_str(), status.text());
#endif

    // read the meta file here
    //LOG1("IO/IOBase::ReadMetaData: File: %s", iMetaFileName.c_str());

    DcmDataset *dataset = m_fileformat.getDataset();
    if (dataset==NULL)
    {
        return false;
    }

    // patient name
    OFString patientsName;
    bool res = dataset->findAndGetOFString(DCM_PatientsName, patientsName).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Cannot fetch patient name");
        return false;
    }
    oMetaDataObject.SetPatientName(std::string(patientsName.c_str()));

#ifdef _DEBUG
    LOG1("\tIODicom::Read: Successfully read PatientName: (%s).", patientsName.c_str());
#endif

    // modality
    OFString modalityStr;
    res = dataset->findAndGetOFString(DCM_Modality, modalityStr).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Cannot fetch modality");
        return false;
    }
    PGCore::ePGModality modality = 	PGCore::MetaData<T>::StrToModality(modalityStr.c_str());
    oMetaDataObject.SetModality(modality);
#ifdef _DEBUG
    LOG1("\tIODicom::Read: Successfully read Modality: (%s).", modalityStr.c_str());
#endif



    // SOP Class UID
    OFString sopClassUIDStr;
    DcmMetaInfo *metaInfo = m_fileformat.getMetaInfo();
    if (metaInfo)
    {
        metaInfo->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClassUIDStr);
        PGCore::ePGSOPClass sopClass = 	PGCore::MetaData<T>::StrToSOPClass(sopClassUIDStr.c_str());
        oMetaDataObject.SetSOPClass(sopClass);


        // DCM_TransferSyntaxUID
        OFString transferSyntaxStr;
        res = metaInfo->findAndGetOFString(DCM_TransferSyntaxUID, transferSyntaxStr).good();
        if (!res)
        {
            LOG0("IO/IODicom::Read:Warning: Cannot fetch TransferSyntaxUID");
        } else
        {

            if (!strcmp(kPgTransferSyntaxUIDRawImplicitVRLittleEndian, transferSyntaxStr.c_str()))
            {

                oMetaDataObject.SetMSBFirst(0);

            } else if (!strcmp(kPgTransferSyntaxUIDRawExplicitVRLittle, transferSyntaxStr.c_str()))
            {

                oMetaDataObject.SetMSBFirst(0);

            } else if (!strcmp(kPgTransferSyntaxUIDRawExplicitVRLittle, transferSyntaxStr.c_str()))
            {

                oMetaDataObject.SetMSBFirst(1);

            } else if (!strcmp(kPgTransferSyntaxUIDLossLessRLE, transferSyntaxStr.c_str()))
            {
                LOG0("IO/IODicom::Read: Cannot read RLE compressed images yet");
                return false;

            } else
            {
                std::string tstr(transferSyntaxStr.c_str());
                std::string filterStr(kPgTransferSyntaxUIDJPEG);
                PGCore::ToUpper(tstr);
                PGCore::ToUpper(filterStr);

                size_t found=tstr.find(filterStr);
                bool isJPEG = (found!=string::npos);
                if (isJPEG)
                {
                    LOG0("IO/IODicom::Read: Cannot read JPEG images yet");
                    return false;
                }
            }
        }
    }

    DcmItem *ditem = OFstatic_cast(DcmItem *, dataset);
    if (!ditem)
    {
        LOG0("IO/IODicom::Read: Cannot fetch ditem");
        return false;
    }

    // Samples Per Pixel
    Uint16 samplesPerPixel = 0;
    res = ditem->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Warning: Cannot fetch SamplesPerPixel");
    } else if (samplesPerPixel > sizeof(T))
    {
        LOG2("IO/IODicom::Read: Cannot read SamplesPerPixel: %d, target resolution smaller: %d yet", samplesPerPixel, sizeof(T));
        return false;
    }

    oMetaDataObject.SetSamplesPerPixel(samplesPerPixel);


    // DCM_PhotometricInterpretation
    OFString photoInterpretationStr;
    res = metaInfo->findAndGetOFString(DCM_PhotometricInterpretation, photoInterpretationStr).good();
    if (!res)
    {
#ifdef _DEBUG
        LOG0("IO/IODicom::Read:Warning Cannot fetch PhotometricInterpretation");
#endif

    } else if (strcmp(kPgPhotometricRepresentationMChrome2, photoInterpretationStr.c_str()))
    {
#ifdef _DEBUG
        LOG1("IO/IODicom::Read: Cannot read PhotometricInterpretation %s", photoInterpretationStr.c_str());
#endif
        return false;
    }

    // DCM_NumberOfFrames
    long numFrames = 1;
    res = dataset->findAndGetLongInt(DCM_NumberOfFrames, numFrames).good();
    if (!res)
    {
#ifdef _DEBUG
        LOG0("IO/IODicom::Read: Warning: Cannot fetch NumberOfFrames");
#endif
        oMetaDataObject.SetFrameCount(1);
    } else
    {
        oMetaDataObject.SetFrameCount(numFrames);
    }

    // size
    Uint16 imageRows = 0;
    Uint16 imageColumns = 0;
    res = ditem->findAndGetUint16(DCM_Rows, imageRows).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Cannot fetch rows");
        return false;
    }
    res = ditem->findAndGetUint16(DCM_Columns, imageColumns).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Cannot fetch columns");
        return false;
    }
    oMetaDataObject.SetSize(PGMath::Vector3D<int>(imageColumns, imageRows, 1));
#ifdef _DEBUG
    LOG2("\tIODicom::Read: Size: Rows: %d, Columns: %d", imageRows, imageColumns);
#endif

    // number of bits
    Uint16 imageBitsAllocated = 0;
    res = ditem->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read: Cannot fetch bits allocated");
        return false;
    }
    oMetaDataObject.SetNumberOfBits(imageBitsAllocated);
#ifdef _DEBUG
    LOG1("\tIODicom::Read: bits allocated: %d", imageBitsAllocated);
#endif

    // spacing
    Float64 sx=1, sy=1;
    DcmElement *elem = 0;
    OFCondition	cond = dataset->findAndGetElement(DCM_PixelSpacing, elem);
    if(!cond.good())
    {
        LOG1("IO/IODicom::Read:Warning Cannot fetch pixel spacing (%s)", cond.text());
    } else
    {
        cond = elem->getFloat64(sx, 0);
        if(!cond.good())
        {
            LOG1("IO/IODicom::Read:Warning Cannot fetch pixel X spacing (%s)", cond.text());
        }
        cond = elem->getFloat64(sy, 1);
        if(!cond.good())
        {
            LOG1("IO/IODicom::Read:Warning Cannot fetch pixel Y spacing (%s)", cond.text());
        }
    }

    if (sx!=sy)
    {
        LOG2("IO/IODicom::Read:Warning: X/Y spacings (%3.2f, %3.2f) mismatch. Ignoring anisotrpy", sx, sy);
        sy = sx;
    }

#ifdef _DEBUG
    LOG2("\tIODicom::Read: pixel X and Y spacings (%3.5f %3.5f)",sx, sy);
#endif

    oMetaDataObject.SetSpacing(PGMath::Vector3D<float>(sx, sy, 1));

    // STUDY UID
    OFString studyUIDStr;
    res = dataset->findAndGetOFString(DCM_StudyInstanceUID, studyUIDStr).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read:Warning Cannot fetch StudyUID");
    } else
    {
        oMetaDataObject.SetStudyUID(std::string(studyUIDStr.c_str()));
    }

    // series UID
    OFString seriesUIDStr;
    res = dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesUIDStr).good();
    if (!res)
    {
        LOG0("IO/IODicom::Read:Warning Cannot fetch seriesUID");
    } else
    {
        oMetaDataObject.SetSeriesUID(std::string(seriesUIDStr.c_str()));
        //LOG1("IO/IODicom::Read:seriesUID : %s", oMetaDataObject.GetSeriesUID().c_str());
    }


    // orientation
    Float64 rowOr[3] = { 1.0f, 0.0f, 0.0f }, colOr[3] = { 0.0f, 1.0f, 0.0f };
    std::vector<PGMath::Vector3D<float> > orXs;
    std::vector<PGMath::Vector3D<float> > orYs;
    cond = dataset->findAndGetElement(DCM_ImageOrientationPatient, elem);
    if(!cond.good())
    {
        LOG1("IO/IODicom::Read:Warning Cannot fetch DCM_ImageOrientationPatient (%s)", cond.text());
    } else
    {
        elem->getFloat64(rowOr[0], 0);
        elem->getFloat64(rowOr[1], 1);
        elem->getFloat64(rowOr[2], 2);
        elem->getFloat64(colOr[0], 3);
        elem->getFloat64(colOr[1], 4);
        elem->getFloat64(colOr[2], 5);
    }

    orXs.push_back(PGMath::Vector3D<float>(rowOr[0], rowOr[1], rowOr[2]));
    oMetaDataObject.SetImageOrientationsPatientX(orXs);
#ifdef _DEBUG
    LOG3("\tIODicom::Read: Image Row vector orientation (%3.5f %3.5f %3.5f)", rowOr[0], rowOr[1], rowOr[2]);
#endif
    orYs.push_back(PGMath::Vector3D<float>(colOr[0], colOr[1], colOr[2]));
    oMetaDataObject.SetImageOrientationsPatientY(orYs);
#ifdef _DEBUG
    LOG3("\tIODicom::Read: Image Col vector orientation (%3.5f %3.5f %3.5f)", colOr[0], colOr[1], colOr[2]);
#endif

    // position
    Float64 imgPos[3] = { 0.0f, 0.0f, 0.0f };
    std::vector<PGMath::Vector3D<float> > positions;
    cond = dataset->findAndGetElement(DCM_ImagePositionPatient, elem);
    if(!cond.good())
    {
        LOG1("IO/IODicom::Read:Warning Cannot fetch DCM_ImagePositionPatient (%s)", cond.text());
    } else
    {
        elem->getFloat64(imgPos[0], 0);
        elem->getFloat64(imgPos[1], 1);
        elem->getFloat64(imgPos[2], 2);
    }
    positions.push_back(PGMath::Vector3D<float>(imgPos[0], imgPos[1], imgPos[2]));
    oMetaDataObject.SetImagePositionsPatient(positions);
#ifdef _DEBUG
    LOG3("\tIODicom::Read: Image Position (%3.5f %3.5f %3.5f)", imgPos[0], imgPos[1], imgPos[2]);
#endif

    // slope / intercept
    if (modality==PGCore::kPGModalityCT || modality==PGCore::kPGModalityPT)
    {
        Float64 slope = -999.0f;
        cond = dataset->findAndGetElement(DCM_RescaleSlope, elem);
        if(!cond.good())
        {
            LOG1("IO/IODicom::Read:Warning Cannot fetch DCM_RescaleSlope (%s)", cond.text());
        } else
        {
            cond = elem->getFloat64(slope, 0);
            if(cond.good())
                //if (dataset->findAndGetFloat64(DCM_RescaleIntercept, slope) == EC_Normal)
            {
                oMetaDataObject.SetSlope(slope);
                //LOG1("IO/IODicom::Read: Cannot fetch pixel Y spacing (%s)", cond.text());
            }
        }

        Float64 intercept = -999.0f;
        //dataset->findAndGetFloat64(DCM_RescaleIntercept, intercept);
        cond = dataset->findAndGetElement(DCM_RescaleIntercept, elem);
        if(!cond.good())
        {
            LOG1("IO/IODicom::Read:Warning Cannot fetch DCM_RescaleIntercept (%s)", cond.text());
        } else
        {
            cond = elem->getFloat64(intercept, 0);
            if(cond.good())
                //if (dataset->findAndGetFloat64(DCM_RescaleIntercept, intercept) == EC_Normal)
            {
                oMetaDataObject.SetIntercept(intercept);
            }
        }
    }
    /*
    Uint16 imageBytesAllocated = 0;
    Uint16 imagePlanarConfiguration = 0;
    Uint16 imageSamplesPerPixel = 0;

    Sint32 imageFrames = 1;
    Uint16 imageBitsAllocated = 0;


    if (result.good()) result = ditem->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated);
    res = ditem->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel);

    // slope / intercept

    // high bit

    // planar configuration

    // endianness
    oMetaData->SetMSBFirst(getValueI(iStr,std::string(kPGTagMSBFirst)));
    */
#endif

#ifdef _DEBUG
    LOG0("} IODicom::GetAttributes");
#endif

    return true;

}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
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();
    }
}
Ejemplo n.º 26
0
/* Helper function to write a DICOM file using C++ */
static int write_dcm_cpp(const char *path, const Image *const im,
        const Dcm_meta *const meta, const float max_val) {

#define BUF_LEN 1024
        char buf[BUF_LEN];

        // Ensure the image is monochromatic
        if (im->nc != 1) {
                SIFT3D_ERR("write_dcm_cpp: image %s has %d channels. "
                        "Currently only signle-channel images are supported.\n",
                         path, im->nc);
                return SIFT3D_FAILURE;
        }

        // If no metadata was provided, initialize default metadata
        Dcm_meta meta_new;
        set_meta_defaults(meta, &meta_new);

        // Create a new fileformat object
        DcmFileFormat fileFormat;

        // Set the file type to derived
        DcmDataset *const dataset = fileFormat.getDataset();
        OFCondition status = dataset->putAndInsertString(DCM_ImageType, 
                                                         "DERIVED");
        if (status.bad()) {
                std::cerr << "write_dcm_cpp: Failed to set the image type" <<
                        std::endl;
                return SIFT3D_FAILURE;
        }

        // Set the class UID
        dataset->putAndInsertString(DCM_SOPClassUID, 
                UID_CTImageStorage);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the SOPClassUID\n");
                return SIFT3D_FAILURE;
        }

        // Set the photometric interpretation
        const char *photoInterp;
        if (im->nc == 1) {
                photoInterp = "MONOCHROME2";
        } else if (im->nc == 3) {
                photoInterp = "RGB";
        } else {
                SIFT3D_ERR("write_dcm_cpp: failed to determine the "
                        "photometric representation for %d channels \n", 
                        im->nc);
                return SIFT3D_FAILURE;
        }
        dataset->putAndInsertString(DCM_PhotometricInterpretation,
                photoInterp);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the photometric "
                        "interpretation \n");
                return SIFT3D_FAILURE;
        }

        // Set the pixel representation to unsigned
        dataset->putAndInsertUint16(DCM_PixelRepresentation, 0);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel "
                        "representation \n");
                return SIFT3D_FAILURE;
        }

        // Set the number of channels (Samples Per Pixel) and set the planar
        // configuration to interlaced pixels
        assert(SIFT3D_IM_GET_IDX(im, 0, 0, 0, 1) == 
                SIFT3D_IM_GET_IDX(im, 0, 0, 0, 0) + 1);
        snprintf(buf, BUF_LEN, "%d", im->nc);
        dataset->putAndInsertString(DCM_SamplesPerPixel, buf);
        dataset->putAndInsertString(DCM_PlanarConfiguration, "0");

        // Set the bits allocated and stored, in big endian format 
        const unsigned int dcm_high_bit = dcm_bit_width - 1;
        dataset->putAndInsertUint16(DCM_BitsAllocated, dcm_bit_width);
        dataset->putAndInsertUint16(DCM_BitsStored, dcm_bit_width);
        dataset->putAndInsertUint16(DCM_HighBit, dcm_high_bit);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the bit widths \n");
                return SIFT3D_FAILURE;
        }

        // Set the patient name
        status = dataset->putAndInsertString(DCM_PatientName, 
                meta_new.patient_name);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the patient name\n");
                return SIFT3D_FAILURE;
        }

        // Set the patient ID
        status = dataset->putAndInsertString(DCM_PatientID,
                meta_new.patient_id);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the patient ID \n");
                return SIFT3D_FAILURE;
        }

        // Set the study UID
        status = dataset->putAndInsertString(DCM_StudyInstanceUID,
                meta_new.study_uid);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the "
                        "StudyInstanceUID \n");
                return SIFT3D_FAILURE;
        }

        // Set the series UID
        status = dataset->putAndInsertString(DCM_SeriesInstanceUID,
                meta_new.series_uid);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the "
                        "SeriesInstanceUID \n");
                return SIFT3D_FAILURE;
        }

        // Set the series description
        status = dataset->putAndInsertString(DCM_SeriesDescription,
                meta_new.series_descrip);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the series "
                        "description \n");
                return SIFT3D_FAILURE;
        }

        // Set the instance UID
        status = dataset->putAndInsertString(DCM_SOPInstanceUID, 
                meta_new.instance_uid);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: failed to set the "
                        "SOPInstanceUID \n");
                return SIFT3D_FAILURE;
        }

        // Set the dimensions
        OFCondition xstatus = dataset->putAndInsertUint16(DCM_Rows, im->ny); 
        OFCondition ystatus = dataset->putAndInsertUint16(DCM_Columns, im->nx);
        snprintf(buf, BUF_LEN, "%d", im->nz);
        OFCondition zstatus = dataset->putAndInsertString(DCM_NumberOfFrames,
                buf);
        if (xstatus.bad() || ystatus.bad() || zstatus.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the dimensions \n");
                return SIFT3D_FAILURE;
        }

        // Set the instance number
        snprintf(buf, BUF_LEN, "%u", meta_new.instance_num);
        status = dataset->putAndInsertString(DCM_InstanceNumber, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the instance "
                        "number \n");
                return SIFT3D_FAILURE;
        }

        // Set the ImagePositionPatient vector
        const double imPosX = static_cast<double>(im->nx - 1) * im->ux;
        const double imPosY = static_cast<double>(im->ny - 1) * im->uy;
        const double imPosZ = static_cast<double>(meta_new.instance_num) * 
                              im->uz;
        snprintf(buf, BUF_LEN, "%f\\%f\\%f", imPosX, imPosY, imPosZ);
        status = dataset->putAndInsertString(DCM_ImagePositionPatient, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the "
                        "ImagePositionPatient vector \n");
                return SIFT3D_FAILURE;
        }

        // Set the slice location
        snprintf(buf, BUF_LEN, "%f", imPosZ);
        status = dataset->putAndInsertString(DCM_SliceLocation, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the slice "
                        "location \n");
                return SIFT3D_FAILURE;
        }

        // Set the pixel spacing
        snprintf(buf, BUF_LEN, "%f\\%f", im->ux, im->uy);
        status = dataset->putAndInsertString(DCM_PixelSpacing, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel "
                        "spacing \n");
                return SIFT3D_FAILURE;
        }

        // Set the aspect ratio
        snprintf(buf, BUF_LEN, "%f\\%f", im->ux, im->uy);
        status = dataset->putAndInsertString(DCM_PixelAspectRatio, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel aspect "
                        "aspect ratio \n");
                return SIFT3D_FAILURE;
        }

        // Set the slice thickness
        snprintf(buf, BUF_LEN, "%f", im->uz);
        status = dataset->putAndInsertString(DCM_SliceThickness, buf);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: Failed to set the slice "
                                "thickness \n");
                return SIFT3D_FAILURE;
        }

        // Count the number of pixels in the image
        unsigned long numPixels = im->dims[0];
        for (int i = 1; i < IM_NDIMS; i++) {
                numPixels *= im->dims[i];
        }

        // Get the image scaling factor
        const float dcm_max_val = static_cast<float>(1 << dcm_bit_width) - 1.0f;
        const float im_max = max_val < 0.0f ? im_max_abs(im) : max_val;
        const float scale = im_max == 0.0f ? 1.0f : dcm_max_val / im_max;

        // Render the data to an 8-bit unsigned integer array
        assert(dcm_bit_width == 8);
        assert(fabsf(dcm_max_val - 255.0f) < FLT_EPSILON);
        uint8_t *pixelData = new uint8_t[numPixels];
        int x, y, z, c;
        SIFT3D_IM_LOOP_START_C(im, x, y, z, c)

                const float vox = SIFT3D_IM_GET_VOX(im, x, y, z, c);

                if (vox < 0.0f) {
                        SIFT3D_ERR("write_dcm_cpp: Image cannot be "
                                "negative \n");
                        return SIFT3D_FAILURE;
                }

                pixelData[c + x + y * im->nx + z * im->nx * im->ny] =
                        static_cast<uint8_t>(vox * scale);
        SIFT3D_IM_LOOP_END_C

        // Write the data
        status = dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, 
                numPixels);
        delete[] pixelData;
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: failed to set the pixel data \n");
                return SIFT3D_FAILURE;
        }

        // Choose the encoding format
#if 0
        DJEncoderRegistration::registerCodecs();
        const E_TransferSyntax xfer = EXS_JPEGProcess14SV1TransferSyntax;
        DJ_RPLossless rp_lossless;
        status = dataset->chooseRepresentation(xfer, &rp_lossless);
#else
        const E_TransferSyntax xfer = EXS_LittleEndianExplicit;
        dataset->chooseRepresentation(xfer, NULL);
#endif
        if (!dataset->canWriteXfer(xfer)) {
                SIFT3D_ERR("write_dcm_cpp: Failed to choose the encoding "
                        "format \n");
                return SIFT3D_FAILURE;
        }

        // Force the media storage UIDs to be re-generated by removing them
        dataset->remove(DCM_MediaStorageSOPClassUID);
        dataset->remove(DCM_MediaStorageSOPInstanceUID);

        // Save the file
        status = fileFormat.saveFile(path, xfer);
        if (status.bad()) {
                SIFT3D_ERR("write_dcm_cpp: failed to write file %s (%s) \n",
                        path, status.text());
                return SIFT3D_FAILURE;
        }

        return SIFT3D_SUCCESS;
#undef BUF_LEN
}
Ejemplo n.º 27
0
/* Load the data from a DICOM file */
Dicom::Dicom(std::string path) : filename(path), valid(false) {

        // Load the image as a DcmFileFormat 
        DcmFileFormat fileFormat;
        OFCondition status = fileFormat.loadFile(path.c_str());
        if (status.bad()) {
                SIFT3D_ERR("Dicom.Dicom: failed to read DICOM file %s (%s)\n",
                        path.c_str(), status.text());
                return;
        }

        // Get the dataset
        DcmDataset *const data = fileFormat.getDataset();

        // Get the series UID 
        const char *seriesUIDStr;
        status = data->findAndGetString(DCM_SeriesInstanceUID, seriesUIDStr);
        if (status.bad() || seriesUIDStr == NULL) {
                SIFT3D_ERR("Dicom.Dicom: failed to get SeriesInstanceUID "
                        "from file %s (%s)\n", path.c_str(), status.text());
                return;
        }
        seriesUID = std::string(seriesUIDStr); 

#if 0
        // Read the patient position
        const char *patientPosStr;
        status = data->findAndGetString(DCM_PatientPosition, patientPosStr);
        if (status.bad() || patientPosStr == NULL) {
                std::cerr << "Dicom.Dicom: failed to get PatientPosition " <<
                        "from file " << path << " (" << status.text() << ")" <<
                        std::endl;
                return;
        }

        // Interpret the patient position to give the sign of the z axis
        double zSign;
        switch (patientPosStr[0]) {
        case 'H':
                zSign = -1.0;
                break;
        case 'F':
                zSign = 1.0;
                break;
        default:
                std::cerr << "Dicom.Dicom: unrecognized patient position: " <<
                        patientPosStr << std::endl;
                return;
        }
#else
        //TODO: Is this needed?
        const double zSign = 1.0;
#endif

        // Read the image position patient vector
        const char *imPosPatientStr;
        status = data->findAndGetString(DCM_ImagePositionPatient, 
                imPosPatientStr);
        if (status.bad() || imPosPatientStr == NULL) {
                SIFT3D_ERR("Dicom.Dicom: failed to get ImagePositionPatient "
                        "from file %s (%s)\n", path.c_str(), status.text());
                return;
        }

        // Parse the image position patient vector to get the z coordinate
        double imPosZ;
        if (sscanf(imPosPatientStr, "%*f\\%*f\\%lf", &imPosZ) != 1) {
                SIFT3D_ERR("Dicom.Dicom: failed to parse "
                        "ImagePositionPatient tag %s from file %s\n", 
                        imPosPatientStr, path.c_str());
                return;
        }

        // Compute the z-location of the upper-left corner, in feet-first 
        // coordinates
        z = zSign * imPosZ;

        // Load the DicomImage object
        DicomImage dicomImage(path.c_str());
        if (dicomImage.getStatus() != EIS_Normal) {
                SIFT3D_ERR("Dicom.Dicom: failed to open image %s (%s)\n",
                        path.c_str(), 
                        DicomImage::getString(dicomImage.getStatus()));
                return;
        }

        // Check for color images
        if (!dicomImage.isMonochrome()) {
                SIFT3D_ERR("Dicom.Dicom: reading of color DICOM images is "
                        "not supported at this time \n");
                return;
        }
        nc = 1;

        // Read the dimensions
        nx = dicomImage.getWidth();
        ny = dicomImage.getHeight();
        nz = dicomImage.getFrameCount();
        if (nx < 1 || ny < 1 || nz < 1) {
                SIFT3D_ERR("Dicom.Dicom: invalid dimensions for file %s "
                        "(%d, %d, %d)\n", path.c_str(), nx, ny, nz);
                return;
        }

        // Read the pixel spacing
        const char *pixelSpacingStr;
        status = data->findAndGetString(DCM_PixelSpacing, pixelSpacingStr);
        if (status.bad()) {
                SIFT3D_ERR("Dicom.Dicom: failed to get pixel spacing from "
                        "file %s (%s)\n", path.c_str(), status.text());
                return;
        }
        if (sscanf(pixelSpacingStr, "%lf\\%lf", &ux, &uy) != 2) {
                SIFT3D_ERR("Dicom.Dicom: unable to parse pixel spacing from "
                        "file %s \n", path.c_str());
                return;
        }
        if (ux <= 0.0 || uy <= 0.0) {
                SIFT3D_ERR("Dicom.Dicom: file %s has invalid pixel spacing "
                        "[%f, %f]\n", path.c_str(), ux, uy);
                return;
        }

        // Read the slice thickness 
        Float64 sliceThickness;
        status = data->findAndGetFloat64(DCM_SliceThickness, sliceThickness);
        if (!status.good()) {
                SIFT3D_ERR("Dicom.Dicom: failed to get slice thickness from "
                        "file %s (%s)\n", path.c_str(), status.text());
                return;
        }

        // Convert to double 
        uz = sliceThickness;
        if (uz <= 0.0) {
                SIFT3D_ERR("Dicom.Dicom: file %s has invalid slice "
                        "thickness: %f \n", path.c_str(), uz);
                return;
        }
        
        // Set the window 
        dicomImage.setMinMaxWindow();

        valid = true;
}
Ejemplo n.º 28
0
    CommandDispatcher* AcceptAssociation(const DicomServer& server, T_ASC_Network *net)
    {
      DcmAssociationConfiguration asccfg;
      char buf[BUFSIZ];
      T_ASC_Association *assoc;
      OFCondition cond;
      OFString sprofile;
      OFString temp_str;

      std::vector<const char*> knownAbstractSyntaxes;

      // For C-STORE
      if (server.HasStoreRequestHandlerFactory())
      {
        knownAbstractSyntaxes.push_back(UID_VerificationSOPClass);
      }

      // For C-FIND
      if (server.HasFindRequestHandlerFactory())
      {
        knownAbstractSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel);
        knownAbstractSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel);
      }

      // For C-MOVE
      if (server.HasMoveRequestHandlerFactory())
      {
        knownAbstractSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel);
      }

      const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
      int numTransferSyntaxes = 0;

      cond = ASC_receiveAssociation(net, &assoc, 
                                    /*opt_maxPDU*/ ASC_DEFAULTMAXPDU, 
                                    NULL, NULL,
                                    /*opt_secureConnection*/ OFFalse,
                                    DUL_NOBLOCK, 1);

      if (cond == DUL_NOASSOCIATIONREQUEST)
      {
        // Timeout
        AssociationCleanup(assoc);
        return NULL;
      }

      // if some kind of error occured, take care of it
      if (cond.bad())
      {
        LOG(ERROR) << "Receiving Association failed: " << cond.text();
        // no matter what kind of error occurred, we need to do a cleanup
        AssociationCleanup(assoc);
        return NULL;
      }

      LOG(INFO) << "Association Received";

      transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
      transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
      transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
      numTransferSyntaxes = 3;

      /* accept the Verification SOP Class if presented */
      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), transferSyntaxes, numTransferSyntaxes);
      if (cond.bad())
      {
        LOG(INFO) << cond.text();
        AssociationCleanup(assoc);
        return NULL;
      }

      /* the array of Storage SOP Class UIDs comes from dcuid.h */
      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes);
      if (cond.bad())
      {
        LOG(INFO) << cond.text();
        AssociationCleanup(assoc);
        return NULL;
      }

      /* set our app title */
      ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str());

      /* acknowledge or reject this association */
      cond = ASC_getApplicationContextName(assoc->params, buf);
      if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0)
      {
        /* reject: the application context name is not supported */
        T_ASC_RejectParameters rej =
          {
            ASC_RESULT_REJECTEDPERMANENT,
            ASC_SOURCE_SERVICEUSER,
            ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED
          };

        LOG(INFO) << "Association Rejected: Bad Application Context Name: " << buf;
        cond = ASC_rejectAssociation(assoc, &rej);
        if (cond.bad())
        {
          LOG(INFO) << cond.text();
        }
        AssociationCleanup(assoc);
        return NULL;
      }
  
      /* check the AETs */
      {
        DIC_AE callingTitle_C;
        DIC_AE calledTitle_C;
        DIC_AE callingIP_C;
        DIC_AE calledIP_C;
        if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() ||
            ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad())
        {
          T_ASC_RejectParameters rej =
            {
              ASC_RESULT_REJECTEDPERMANENT,
              ASC_SOURCE_SERVICEUSER,
              ASC_REASON_SU_NOREASON
            };
          ASC_rejectAssociation(assoc, &rej);
          AssociationCleanup(assoc);
          return NULL;
        }

        std::string callingIP(/*OFSTRING_GUARD*/(callingIP_C));
        std::string callingTitle(/*OFSTRING_GUARD*/(callingTitle_C));
        std::string calledTitle(/*OFSTRING_GUARD*/(calledTitle_C));
        Toolbox::ToUpperCase(callingIP);
        Toolbox::ToUpperCase(callingTitle);
        Toolbox::ToUpperCase(calledTitle);

        if (server.HasCalledApplicationEntityTitleCheck() &&
            calledTitle != server.GetApplicationEntityTitle())
        {
          T_ASC_RejectParameters rej =
            {
              ASC_RESULT_REJECTEDPERMANENT,
              ASC_SOURCE_SERVICEUSER,
              ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED
            };
          ASC_rejectAssociation(assoc, &rej);
          AssociationCleanup(assoc);
          return NULL;
        }

        if (server.HasApplicationEntityFilter() &&
            !server.GetApplicationEntityFilter().IsAllowed(callingIP, callingTitle))
        {
          T_ASC_RejectParameters rej =
            {
              ASC_RESULT_REJECTEDPERMANENT,
              ASC_SOURCE_SERVICEUSER,
              ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED
            };
          ASC_rejectAssociation(assoc, &rej);
          AssociationCleanup(assoc);
          return NULL;
        }
      }

      if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0)
      {
        /* reject: the no implementation Class UID provided */
        T_ASC_RejectParameters rej =
          {
            ASC_RESULT_REJECTEDPERMANENT,
            ASC_SOURCE_SERVICEUSER,
            ASC_REASON_SU_NOREASON
          };

        LOG(INFO) << "Association Rejected: No Implementation Class UID provided";
        cond = ASC_rejectAssociation(assoc, &rej);
        if (cond.bad())
        {
          LOG(INFO) << cond.text();
        }
        AssociationCleanup(assoc);
        return NULL;
      }

      {
        cond = ASC_acknowledgeAssociation(assoc);
        if (cond.bad())
        {
          LOG(ERROR) << cond.text();
          AssociationCleanup(assoc);
          return NULL;
        }
        LOG(INFO) << "Association Acknowledged (Max Send PDV: " << assoc->sendPDVLength << ")";
        if (ASC_countAcceptedPresentationContexts(assoc->params) == 0)
          LOG(INFO) << "    (but no valid presentation contexts)";
      }

      return new CommandDispatcher(server, assoc);
    }
Ejemplo n.º 29
0
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::FiberBundleDicomReader::Read()
{

  std::vector<itk::SmartPointer<mitk::BaseData> > output_fibs;
  try
  {
    const std::string& locale = "C";
    const std::string& currLocale = setlocale( LC_ALL, nullptr );
    setlocale(LC_ALL, locale.c_str());

    std::string filename = this->GetInputLocation();

    OFCondition result;
    TrcTractographyResults *trc = nullptr;
    result = TrcTractographyResults::loadFile(filename.c_str(), trc);
    if (result.bad())
      mitkThrow() << "Unable to load tractography dicom file: " << result.text();

    OFString val = "-";
    trc->getPatient().getPatientName(val);
    MITK_INFO << "Patient Name: " <<  val; val = "-";
    trc->getStudy().getStudyInstanceUID(val);
    MITK_INFO << "Study       : " << val; val = "-";
    trc->getSeries().getSeriesInstanceUID(val);
    MITK_INFO << "Series      : " << val; val = "-";
    trc->getSOPCommon().getSOPInstanceUID(val);
    MITK_INFO << "Instance    : " << val; val = "-";
    MITK_INFO << "-------------------------------------------------------------------------";
    size_t numTrackSets = trc->getNumberOfTrackSets();
    OFVector<TrcTrackSet*>& sets = trc->getTrackSets();
    for (size_t ts = 0; ts < numTrackSets; ts++)
    {
      size_t numTracks = sets[ts]->getNumberOfTracks();
      MITK_INFO << "  Track Set #" << ts << ": " << numTracks << " Tracks, "
           << sets[ts]->getNumberOfTrackSetStatistics() << " Track Set Statistics, "
           << sets[ts]->getNumberOfTrackStatistics() << " Track Statistics, "
           << sets[ts]->getNumberOfMeasurements() << " Measurements ";

      vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
      vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();

      for (size_t t = 0; t < numTracks; t++)
      {
        vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
        TrcTrack* track = sets[ts]->getTracks()[t];
        const Float32* vals = nullptr;
        size_t numPoints = track->getTrackData(vals);

        for (size_t v = 0; v < numPoints; ++v)
        {
          vtkIdType id = vtkNewPoints->InsertNextPoint(vals[v*3],vals[v*3+1],vals[v*3+2]);
          container->GetPointIds()->InsertNextId(id);
        }

        vtkNewCells->InsertNextCell(container);
      }

      vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
      fiberPolyData->SetPoints(vtkNewPoints);
      fiberPolyData->SetLines(vtkNewCells);

//      // transform polydata from RAS (MRtrix) to LPS (MITK)
//      mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
//      vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New();
//      matrix->Identity();
//      matrix->SetElement(0,0,-matrix->GetElement(0,0));
//      matrix->SetElement(1,1,-matrix->GetElement(1,1));
//      geometry->SetIndexToWorldTransformByVtkMatrix(matrix);

//      vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
//      transformFilter->SetInputData(fiberPolyData);
//      transformFilter->SetTransform(geometry->GetVtkTransform());
//      transformFilter->Update();

      FiberBundle::Pointer fib = FiberBundle::New(fiberPolyData);

      CodeSequenceMacro* algoCode = sets[ts]->getTrackingAlgorithmIdentification().at(0);
      val = "-"; algoCode->getCodeValue(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.algo_code.value",val.c_str());
      val = "-"; algoCode->getCodeMeaning(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.algo_code.meaning",val.c_str());

      CodeSequenceMacro modelCode = sets[ts]->getDiffusionModelCode();
      val = "-"; modelCode.getCodeValue(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.model_code.value",val.c_str());
      val = "-"; modelCode.getCodeMeaning(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.model_code.meaning",val.c_str());

      CodeWithModifiers anatomy = sets[ts]->getTrackSetAnatomy();
      val = "-"; anatomy.getCodeValue(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.anatomy.value",val.c_str());
      val = "-"; anatomy.getCodeMeaning(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.anatomy.meaning",val.c_str());

      val = "-"; trc->getPatient().getPatientID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.patient_id",val.c_str());
      val = "-"; trc->getPatient().getPatientName(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.patient_name",val.c_str());
      val = "-"; trc->getStudy().getStudyInstanceUID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.study_instance_uid",val.c_str());
      val = "-"; trc->getSeries().getSeriesInstanceUID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.series_instance_uid",val.c_str());
      val = "-"; trc->getSOPCommon().getSOPInstanceUID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.sop_instance_uid",val.c_str());
      val = "-"; trc->getSOPCommon().getSOPClassUID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.sop_class_uid",val.c_str());
      val = "-"; trc->getFrameOfReference().getFrameOfReferenceUID(val);
      fib->GetPropertyList()->SetStringProperty("DICOM.frame_of_reference_uid",val.c_str());

      output_fibs.push_back(fib.GetPointer());
      MITK_INFO << "Fiber bundle read";
    }
    delete trc;

    setlocale(LC_ALL, currLocale.c_str());
    return output_fibs;
  }
  catch(...)
  {
    throw;
  }
  return output_fibs;
}
Ejemplo n.º 30
0
    bool CommandDispatcher::Step()
    /*
     * This function receives DIMSE commmands over the network connection
     * and handles these commands correspondingly. Note that in case of
     * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed.
     */
    {
      bool finished = false;

      // receive a DIMSE command over the network, with a timeout of 1 second
      DcmDataset *statusDetail = NULL;
      T_ASC_PresentationContextID presID = 0;
      T_DIMSE_Message msg;

      OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail);
      elapsedTimeSinceLastCommand_++;
    
      // if the command which was received has extra status
      // detail information, dump this information
      if (statusDetail != NULL)
      {
        //LOG4CPP_WARN(Internals::GetLogger(), "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail));
        delete statusDetail;
      }

      if (cond == DIMSE_OUTOFRESOURCES)
      {
        finished = true;
      }
      else if (cond == DIMSE_NODATAAVAILABLE)
      {
        // Timeout due to DIMSE_NONBLOCKING
        if (clientTimeout_ != 0 && 
            elapsedTimeSinceLastCommand_ >= clientTimeout_)
        {
          // This timeout is actually a client timeout
          finished = true;
        }
      }
      else if (cond == EC_Normal)
      {
        // Reset the client timeout counter
        elapsedTimeSinceLastCommand_ = 0;

        // in case we received a valid message, process this command
        // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ
        switch (msg.CommandField)
        {
        case DIMSE_C_ECHO_RQ:
          // process C-ECHO-Request
          cond = EchoScp(assoc_, &msg, presID);
          break;

        case DIMSE_C_STORE_RQ:
          // process C-STORE-Request
          if (server_.HasStoreRequestHandlerFactory())
          {
            std::auto_ptr<IStoreRequestHandler> handler
              (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler());
            cond = Internals::storeScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        case DIMSE_C_MOVE_RQ:
          // process C-MOVE-Request
          if (server_.HasMoveRequestHandlerFactory())
          {
            std::auto_ptr<IMoveRequestHandler> handler
              (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler());
            cond = Internals::moveScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        case DIMSE_C_FIND_RQ:
          // process C-FIND-Request
          if (server_.HasFindRequestHandlerFactory())
          {
            std::auto_ptr<IFindRequestHandler> handler
              (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler());
            cond = Internals::findScp(assoc_, &msg, presID, *handler);
          }
          else
            cond = DIMSE_BADCOMMANDTYPE;  // Should never happen
          break;

        default:
          // we cannot handle this kind of message
          cond = DIMSE_BADCOMMANDTYPE;
          LOG(ERROR) << "cannot handle command: 0x" << std::hex << msg.CommandField;
          break;
        }
      }
      else
      {
        // Bad status, which indicates the closing of the connection by
        // the peer or a network error
        finished = true;
      }
    
      if (finished)
      {
        if (cond == DUL_PEERREQUESTEDRELEASE)
        {
          LOG(INFO) << "Association Release";
          ASC_acknowledgeRelease(assoc_);
        }
        else if (cond == DUL_PEERABORTEDASSOCIATION)
        {
          LOG(INFO) << "Association Aborted";
        }
        else
        {
          OFString temp_str;
          LOG(ERROR) << "DIMSE failure (aborting association): " << cond.text();
          /* some kind of error so abort the association */
          ASC_abortAssociation(assoc_);
        }
      }

      return !finished;
    }