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 Series::releaseResponses(OFList< QRResponse* > responses) { while (!responses.empty()) { delete responses.front(); responses.pop_front(); } }
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; }
//------------------------------------------------------------------------------ void ctkDICOMIndexer::addDirectory(ctkDICOMDatabase& ctkDICOMDatabase, const QString& directoryName, const QString& destinationDirectoryName) { Q_D(ctkDICOMIndexer); const std::string src_directory(directoryName.toStdString()); std::string dcmFilePath = directoryName.toStdString() + "/DICOMDIR"; const char* dcmDirFilePath = dcmFilePath.c_str(); //if(OFStandard::fileExists(dcmDirFilePath)) //{ // //this->addFromDICOMDIR(ctkDICOMDatabase, directoryName, destinationDirectoryName); //}else{ OFList<OFString> originalDcmtkFileNames; OFList<OFString> dcmtkFileNames; OFStandard::searchDirectoryRecursively( QDir::toNativeSeparators(src_directory.c_str()).toAscii().data(), originalDcmtkFileNames, "", ""); int totalNumberOfFiles = originalDcmtkFileNames.size(); // hack to reverse list of filenames (not neccessary when image loading works correctly) for ( OFListIterator(OFString) iter = originalDcmtkFileNames.begin(); iter != originalDcmtkFileNames.end(); ++iter ) { dcmtkFileNames.push_front( *iter ); } OFListIterator(OFString) iter = dcmtkFileNames.begin(); OFListIterator(OFString) last = dcmtkFileNames.end(); if(iter == last) return; emit foundFilesToIndex(totalNumberOfFiles); /* iterate over all input filenames */ int fileNumber = 0; int currentProgress = -1; d->Canceled = false; while (iter != last) { if (d->Canceled) { break; } emit indexingFileNumber(++fileNumber); int newProgress = ( fileNumber * 100 ) / totalNumberOfFiles; if (newProgress != currentProgress) { currentProgress = newProgress; emit progress( currentProgress ); } QString filePath((*iter).c_str()); this->addFile(ctkDICOMDatabase, filePath, destinationDirectoryName); ++iter; } //} }
//------------------------------------------------------------------------------ ctkDICOMRetrievePrivate::ctkDICOMRetrievePrivate(ctkDICOMRetrieve& obj) : q_ptr(&obj) { this->Database = QSharedPointer<ctkDICOMDatabase> (0); this->WasCanceled = false; this->KeepAssociationOpen = true; this->ConnectionParamsChanged = false; this->LastRetrieveType = RetrieveNone; // 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(); logger.info ( "Setting Transfer Syntaxes" ); OFList<OFString> transferSyntaxes; transferSyntaxes.push_back ( UID_LittleEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_BigEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_LittleEndianImplicitTransferSyntax ); this->SCU.addPresentationContext ( UID_MOVEStudyRootQueryRetrieveInformationModel, transferSyntaxes ); this->SCU.addPresentationContext ( UID_GETStudyRootQueryRetrieveInformationModel, transferSyntaxes ); for (Uint16 i = 0; i < numberOfDcmLongSCUStorageSOPClassUIDs; i++) { this->SCU.addPresentationContext(dcmLongSCUStorageSOPClassUIDs[i], transferSyntaxes, ASC_SC_ROLE_SCP); } }
//------------------------------------------------------------------------------ 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; }
Series::DicomSeriesContainer Series::toFwMedData(OFList< QRResponse* > responses) { DicomSeriesContainer seriesContainer; OFIterator< QRResponse* > it; 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 data; // Create series ::fwMedData::DicomSeries::sptr series = ::fwMedData::DicomSeries::New(); ::fwMedData::Patient::sptr patient = ::fwMedData::Patient::New(); ::fwMedData::Study::sptr study = ::fwMedData::Study::New(); ::fwMedData::Equipment::sptr equipment = ::fwMedData::Equipment::New(); // Set informations to series series->setPatient(patient); series->setStudy(study); series->setEquipment(equipment); // ================================== // Series // ================================== result = (*it)->m_dataset->findAndGetOFStringArray(DCM_SeriesInstanceUID, data); series->setInstanceUID(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_Modality, data); series->setModality(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_SeriesDate, data); series->setDate(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_SeriesTime, data); series->setTime(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_SeriesDescription, data); series->setDescription(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PerformingPhysicianName, data); ::fwMedData::DicomValuesType performingPhysiciansName; performingPhysiciansName.push_back(data.c_str()); series->setPerformingPhysiciansName(performingPhysiciansName); // ================================== // Patient // ================================== result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PatientName, data); patient->setName(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PatientID, data); patient->setPatientId(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PatientBirthDate, data); patient->setBirthdate(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PatientSex, data); patient->setSex(data.c_str()); // ================================== // Study // ================================== result = (*it)->m_dataset->findAndGetOFStringArray(DCM_StudyInstanceUID, data); study->setInstanceUID(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_StudyDate, data); study->setDate(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_StudyTime, data); study->setTime(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_ReferringPhysicianName, data); study->setReferringPhysicianName(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_StudyDescription, data); study->setDescription(data.c_str()); result = (*it)->m_dataset->findAndGetOFStringArray(DCM_PatientAge, data); study->setPatientAge(data.c_str()); // ================================== // Equipment // ================================== (*it)->m_dataset->findAndGetOFStringArray(DCM_InstitutionName, data); equipment->setInstitutionName(data.c_str()); // ================================== // Number of instances // ================================== long int nbinstances; (*it)->m_dataset->findAndGetLongInt(DCM_NumberOfSeriesRelatedInstances, nbinstances); series->setNumberOfInstances(nbinstances); // Add series to container seriesContainer.push_back(series); } } return seriesContainer; }
//------------------------------------------------------------------------------ bool ctkDICOMRetrievePrivate::get ( const QString& studyInstanceUID, const QString& seriesInstanceUID, const RetrieveType retrieveType ) { Q_Q(ctkDICOMRetrieve); DcmDataset *retrieveParameters = new DcmDataset(); if (! this->initializeSCU(studyInstanceUID, seriesInstanceUID, retrieveType, retrieveParameters) ) { delete retrieveParameters; return false; } // Issue request logger.debug ( "Sending Get Request" ); emit q->progress("Sending Get Request"); emit q->progress(0); OFList<RetrieveResponse*> responses; T_ASC_PresentationContextID presID = this->SCU.findPresentationContextID( UID_GETStudyRootQueryRetrieveInformationModel, "" /* don't care about transfer syntax */ ); if (presID == 0) { logger.error ( "GET Request failed: No valid Study Root GET Presentation Context available" ); if (!this->KeepAssociationOpen) { this->SCU.closeAssociation(DCMSCU_RELEASE_ASSOCIATION); } delete retrieveParameters; return false; } emit q->progress("Found Presentation Context"); emit q->progress(1); // do the actual move request OFCondition status = this->SCU.sendCGETRequest ( presID, retrieveParameters, &responses ); emit q->progress("Sent Get Request"); emit q->progress(2); // Close association if we do not want to explicitly keep it open if (!this->KeepAssociationOpen) { this->SCU.closeAssociation(DCMSCU_RELEASE_ASSOCIATION); } // Free some (little) memory delete retrieveParameters; // If we do not receive a single response, something is fishy if ( responses.begin() == responses.end() ) { logger.error ( "No responses received at all! (at least one empty response always expected)" ); //throw std::runtime_error( std::string("No responses received from server!") ); emit q->progress("No Responses from Server!"); return false; } emit q->progress("Got Responses"); emit q->progress(3); /* The server is permitted to acknowledge every image that was received, or * to send a single move response. * If there is only a single response, this can mean the following: * 1) No images to transfer (Status Success and Number of Completed Subops = 0) * 2) All images transferred (Status Success and Number of Completed Subops > 0) * 3) Error code, i.e. no images transferred * 4) Warning (one or more failures, i.e. some images transferred) */ if ( responses.size() == 1 ) { RetrieveResponse* rsp = *responses.begin(); logger.debug ( "GET response receveid with status: " + QString(DU_cmoveStatusString(rsp->m_status)) ); if ( (rsp->m_status == STATUS_Success) || (rsp->m_status == STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures)) { if (rsp->m_numberOfCompletedSubops == 0) { logger.error ( "No images transferred by PACS!" ); //throw std::runtime_error( std::string("No images transferred by PACS!") ); return false; } } else { logger.error("GET request failed, server does report error"); QString statusDetail("No details"); if (rsp->m_statusDetail != NULL) { std::ostringstream out; rsp->m_statusDetail->print(out); statusDetail = "Status Detail: " + statusDetail.fromStdString(out.str()); } statusDetail.prepend("GET request failed: "); logger.error(statusDetail); //throw std::runtime_error( statusDetail.toStdString() ); return false; } } // Select the last GET response to output meaningful status information OFIterator<RetrieveResponse*> it = responses.begin(); Uint32 numResults = responses.size(); for (Uint32 i = 1; i < numResults; i++) { it++; } logger.debug ( "GET responses report for study: " + studyInstanceUID +"\n" + QString::number(static_cast<unsigned int>((*it)->m_numberOfCompletedSubops)) + " images transferred, and\n" + QString::number(static_cast<unsigned int>((*it)->m_numberOfWarningSubops)) + " images transferred with warning, and\n" + QString::number(static_cast<unsigned int>((*it)->m_numberOfFailedSubops)) + " images transfers failed"); emit q->progress("Finished Get"); emit q->progress(100); return true; }
void I2DOutputPlugSC::supportedSOPClassUIDs(OFList<OFString> suppSOPs) { suppSOPs.push_back(UID_SecondaryCaptureImageStorage); }