# HG changeset patch # User Sebastien Jodogne # Date 1446030135 -3600 # Node ID 39c37a994b2fb39a241df3dfdab990ced9a3d336 # Parent 3a4f7dc00f491258bbc0d942253bc87b0e014e46 handling of DICOM_TAG_MODALITIES_IN_STUDY diff -r 3a4f7dc00f49 -r 39c37a994b2f Core/DicomFormat/DicomMap.cpp --- a/Core/DicomFormat/DicomMap.cpp Wed Oct 28 11:31:58 2015 +0100 +++ b/Core/DicomFormat/DicomMap.cpp Wed Oct 28 12:02:15 2015 +0100 @@ -69,7 +69,7 @@ //DicomTag(0x0010, 0x1080), // MilitaryRank DicomTag(0x0008, 0x0021), // SeriesDate DicomTag(0x0008, 0x0031), // SeriesTime - DicomTag(0x0008, 0x0060), // Modality + DICOM_TAG_MODALITY, DicomTag(0x0008, 0x0070), // Manufacturer DicomTag(0x0008, 0x1010), // StationName DICOM_TAG_SERIES_DESCRIPTION, diff -r 3a4f7dc00f49 -r 39c37a994b2f Core/DicomFormat/DicomTag.h --- a/Core/DicomFormat/DicomTag.h Wed Oct 28 11:31:58 2015 +0100 +++ b/Core/DicomFormat/DicomTag.h Wed Oct 28 12:02:15 2015 +0100 @@ -109,6 +109,7 @@ static const DicomTag DICOM_TAG_STUDY_DESCRIPTION(0x0008, 0x1030); static const DicomTag DICOM_TAG_SERIES_DESCRIPTION(0x0008, 0x103e); + static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060); // The following is used for "modify/anonymize" operations static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016); diff -r 3a4f7dc00f49 -r 39c37a994b2f OrthancServer/OrthancFindRequestHandler.cpp --- a/OrthancServer/OrthancFindRequestHandler.cpp Wed Oct 28 11:31:58 2015 +0100 +++ b/OrthancServer/OrthancFindRequestHandler.cpp Wed Oct 28 12:02:15 2015 +0100 @@ -307,17 +307,7 @@ } #if USE_LOOKUP_RESOURCE == 1 - if (tag == DICOM_TAG_MODALITIES_IN_STUDY) - { - // TODO SetModalitiesInStudy(value); - // findQuery.SetModalitiesInStudy(value); - printf("ICI\n"); - throw OrthancException(ErrorCode_NotImplemented); - } - else - { - finder.Add(tag, value, caseSensitivePN); - } + finder.AddDicomConstraint(tag, value, caseSensitivePN); #else if (tag == DICOM_TAG_MODALITIES_IN_STUDY) diff -r 3a4f7dc00f49 -r 39c37a994b2f OrthancServer/Search/LookupResource.cpp --- a/OrthancServer/Search/LookupResource.cpp Wed Oct 28 11:31:58 2015 +0100 +++ b/OrthancServer/Search/LookupResource.cpp Wed Oct 28 12:02:15 2015 +0100 @@ -309,6 +309,44 @@ { it->second->Apply(candidates, database); } + + if (level == ResourceType_Study && + modalitiesInStudy_.get() != NULL) + { + // There is a constraint on the "ModalitiesInStudy" DICOM + // extension. Check out whether one child series has one of the + // allowed modalities + std::list allStudies, matchingStudies; + candidates.Flatten(allStudies); + + for (std::list::const_iterator + study = allStudies.begin(); study != allStudies.end(); ++study) + { + std::list childrenSeries; + database.GetChildrenInternalId(childrenSeries, *study); + + for (std::list::const_iterator + series = childrenSeries.begin(); series != childrenSeries.end(); ++series) + { + DicomMap tags; + database.GetMainDicomTags(tags, *series); + + const DicomValue* value = tags.TestAndGetValue(DICOM_TAG_MODALITY); + if (value != NULL && + !value->IsNull() && + !value->IsBinary()) + { + if (modalitiesInStudy_->Match(value->GetContent())) + { + matchingStudies.push_back(*study); + break; + } + } + } + } + + candidates.Intersect(matchingStudies); + } } @@ -359,9 +397,24 @@ } - void LookupResource::Add(const DicomTag& tag, - const std::string& dicomQuery, - bool caseSensitivePN) + void LookupResource::SetModalitiesInStudy(const std::string& modalities) + { + modalitiesInStudy_.reset(new ListConstraint(DICOM_TAG_MODALITIES_IN_STUDY, + true /* case sensitive */)); + + std::vector items; + Toolbox::TokenizeString(items, modalities, '\\'); + + for (size_t i = 0; i < items.size(); i++) + { + modalitiesInStudy_->AddAllowedValue(items[i]); + } + } + + + void LookupResource::AddDicomConstraint(const DicomTag& tag, + const std::string& dicomQuery, + bool caseSensitivePN) { ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag); @@ -374,10 +427,14 @@ // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html - if ((vr == ValueRepresentation_Date || - vr == ValueRepresentation_DateTime || - vr == ValueRepresentation_Time) && - dicomQuery.find('-') != std::string::npos) + if (tag == DICOM_TAG_MODALITIES_IN_STUDY) + { + SetModalitiesInStudy(dicomQuery); + } + else if ((vr == ValueRepresentation_Date || + vr == ValueRepresentation_DateTime || + vr == ValueRepresentation_Time) && + dicomQuery.find('-') != std::string::npos) { /** * Range matching is only defined for TM, DA and DT value diff -r 3a4f7dc00f49 -r 39c37a994b2f OrthancServer/Search/LookupResource.h --- a/OrthancServer/Search/LookupResource.h Wed Oct 28 11:31:58 2015 +0100 +++ b/OrthancServer/Search/LookupResource.h Wed Oct 28 12:02:15 2015 +0100 @@ -32,7 +32,7 @@ #pragma once -#include "IFindConstraint.h" +#include "ListConstraint.h" #include "SetOfResources.h" #include @@ -66,9 +66,10 @@ typedef std::map Levels; - ResourceType level_; - Levels levels_; - Constraints unoptimizedConstraints_; + ResourceType level_; + Levels levels_; + Constraints unoptimizedConstraints_; + std::auto_ptr modalitiesInStudy_; bool AddInternal(ResourceType level, std::auto_ptr& constraint); @@ -87,11 +88,13 @@ return level_; } + void SetModalitiesInStudy(const std::string& modalities); + void Add(IFindConstraint* constraint); // Takes ownership - void Add(const DicomTag& tag, - const std::string& dicomQuery, - bool caseSensitivePN); + void AddDicomConstraint(const DicomTag& tag, + const std::string& dicomQuery, + bool caseSensitivePN); void FindCandidates(std::list& result, IDatabaseWrapper& database) const;