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; }
// 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); } }
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; }
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); } }
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; }
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; }
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; }
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; }
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); }
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; }
// 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; } }
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"; } }
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(); } }
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); }
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; }
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(); } } }
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"; }
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; }
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; }
//------------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------------ 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(); } }
/* 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 }
/* 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; }
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); }
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; }
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; }