Mercurial > hg > orthanc
diff OrthancServer/DicomProtocol/DicomUserConnection.cpp @ 1805:f08978b1f45b worklists
c-find scu for modality worklists
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 20 Nov 2015 17:56:31 +0100 |
parents | ec66a16aa398 |
children | 3dcf5c0734c9 |
line wrap: on
line diff
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp Fri Nov 20 16:42:49 2015 +0100 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp Fri Nov 20 17:56:31 2015 +0100 @@ -353,7 +353,8 @@ struct FindPayload { DicomFindAnswers* answers; - std::string level; + const char* level; + bool isWorklist; }; } @@ -371,15 +372,23 @@ if (responseIdentifiers != NULL) { - DicomMap m; - FromDcmtkBridge::Convert(m, *responseIdentifiers); - - if (!m.HasTag(DICOM_TAG_QUERY_RETRIEVE_LEVEL)) + if (payload.isWorklist) + { + ParsedDicomFile answer(*responseIdentifiers); + payload.answers->Add(answer); + } + else { - m.SetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL, payload.level); + DicomMap m; + FromDcmtkBridge::Convert(m, *responseIdentifiers); + + if (!m.HasTag(DICOM_TAG_QUERY_RETRIEVE_LEVEL)) + { + m.SetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL, payload.level); + } + + payload.answers->Add(m); } - - payload.answers->Add(m); } } @@ -474,6 +483,52 @@ } + static void ExecuteFind(DicomFindAnswers& answers, + T_ASC_Association* association, + DcmDataset* dataset, + const char* sopClass, + bool isWorklist, + const char* level, + uint32_t dimseTimeout) + { + assert(isWorklist ^ (level != NULL)); + + FindPayload payload; + payload.answers = &answers; + payload.level = level; + payload.isWorklist = isWorklist; + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(association, sopClass); + if (presID == 0) + { + throw OrthancException(ErrorCode_DicomFindUnavailable); + } + + T_DIMSE_C_FindRQ request; + memset(&request, 0, sizeof(request)); + request.MessageID = association->nextMsgID++; + strcpy(request.AffectedSOPClassUID, sopClass); + request.DataSetType = DIMSE_DATASET_PRESENT; + request.Priority = DIMSE_PRIORITY_MEDIUM; + + T_DIMSE_C_FindRSP response; + DcmDataset* statusDetail = NULL; + OFCondition cond = DIMSE_findUser(association, presID, &request, dataset, + FindCallback, &payload, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ dimseTimeout, + &response, &statusDetail); + + if (statusDetail) + { + delete statusDetail; + } + + Check(cond); + } + + void DicomUserConnection::Find(DicomFindAnswers& result, ResourceType level, const DicomMap& originalFields) @@ -483,34 +538,32 @@ CheckIsOpen(); - FindPayload payload; - payload.answers = &result; + std::auto_ptr<DcmDataset> dataset(ConvertQueryFields(fields, manufacturer_)); + const char* clevel = NULL; + const char* sopClass = NULL; - std::auto_ptr<DcmDataset> dataset(ConvertQueryFields(fields, manufacturer_)); - - const char* sopClass; switch (level) { case ResourceType_Patient: - payload.level = "PATIENT"; + clevel = "PATIENT"; DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; break; case ResourceType_Study: - payload.level = "STUDY"; + clevel = "STUDY"; DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; break; case ResourceType_Series: - payload.level = "SERIES"; + clevel = "SERIES"; DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; break; case ResourceType_Instance: - payload.level = "INSTANCE"; + clevel = "INSTANCE"; if (manufacturer_ == ModalityManufacturer_ClearCanvas || manufacturer_ == ModalityManufacturer_Dcm4Chee) { @@ -565,34 +618,8 @@ throw OrthancException(ErrorCode_ParameterOutOfRange); } - // Figure out which of the accepted presentation contexts should be used - int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); - if (presID == 0) - { - throw OrthancException(ErrorCode_DicomFindUnavailable); - } - - T_DIMSE_C_FindRQ request; - memset(&request, 0, sizeof(request)); - request.MessageID = pimpl_->assoc_->nextMsgID++; - strcpy(request.AffectedSOPClassUID, sopClass); - request.DataSetType = DIMSE_DATASET_PRESENT; - request.Priority = DIMSE_PRIORITY_MEDIUM; - - T_DIMSE_C_FindRSP response; - DcmDataset* statusDetail = NULL; - OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(), - FindCallback, &payload, - /*opt_blockMode*/ DIMSE_BLOCKING, - /*opt_dimse_timeout*/ pimpl_->dimseTimeout_, - &response, &statusDetail); - - if (statusDetail) - { - delete statusDetail; - } - - Check(cond); + assert(clevel != NULL && sopClass != NULL); + ExecuteFind(result, pimpl_->assoc_, dataset.get(), sopClass, false, clevel, pimpl_->dimseTimeout_); } @@ -685,13 +712,14 @@ defaultStorageSOPClasses_.clear(); // Copy the short list of storage SOP classes from DCMTK, making - // room for the 4 SOP classes reserved for C-ECHO, C-FIND, C-MOVE. + // room for the 5 SOP classes reserved for C-ECHO, C-FIND, C-MOVE at (**). std::set<std::string> uncommon; uncommon.insert(UID_BlendingSoftcopyPresentationStateStorage); uncommon.insert(UID_GrayscaleSoftcopyPresentationStateStorage); uncommon.insert(UID_ColorSoftcopyPresentationStateStorage); uncommon.insert(UID_PseudoColorSoftcopyPresentationStateStorage); + uncommon.insert(UID_XAXRFGrayscaleSoftcopyPresentationStateStorage); // Add the storage syntaxes for C-STORE for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs - 1; i++) @@ -721,11 +749,12 @@ pimpl_->params_ = NULL; pimpl_->assoc_ = NULL; - // SOP classes for C-ECHO, C-FIND and C-MOVE + // SOP classes for C-ECHO, C-FIND and C-MOVE (**) reservedStorageSOPClasses_.push_back(UID_VerificationSOPClass); reservedStorageSOPClasses_.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); reservedStorageSOPClasses_.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); reservedStorageSOPClasses_.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); + reservedStorageSOPClasses_.push_back(UID_FINDModalityWorklistInformationModel); ResetStorageSOPClasses(); } @@ -1101,4 +1130,15 @@ CheckStorageSOPClassesInvariant(); } + + void DicomUserConnection::FindWorklist(DicomFindAnswers& result, + ParsedDicomFile& query) + { + CheckIsOpen(); + + DcmDataset* dataset = query.GetDcmtkObject().getDataset(); + const char* sopClass = UID_FINDModalityWorklistInformationModel; + + ExecuteFind(result, pimpl_->assoc_, dataset, sopClass, true, NULL, pimpl_->dimseTimeout_); + } }