# HG changeset patch # User Sebastien Jodogne # Date 1390581645 -3600 # Node ID 3bdb5db8e8398bd8498ff5a0ac36b9fc2dbd36e5 # Parent 28e4b3ec8afffa0df1dacc266849165fa10602ba generalization of query/retrieve diff -r 28e4b3ec8aff -r 3bdb5db8e839 Core/DicomFormat/DicomMap.cpp --- a/Core/DicomFormat/DicomMap.cpp Fri Jan 24 15:35:39 2014 +0100 +++ b/Core/DicomFormat/DicomMap.cpp Fri Jan 24 17:40:45 2014 +0100 @@ -386,4 +386,32 @@ GetMainDicomTagsInternal(result, ResourceType_Series); GetMainDicomTagsInternal(result, ResourceType_Instance); } + + + void DicomMap::ExtractMainDicomTagsForLevel(DicomMap& result, + ResourceType level) const + { + switch (level) + { + case ResourceType_Patient: + ExtractPatientInformation(result); + break; + + case ResourceType_Study: + ExtractStudyInformation(result); + break; + + case ResourceType_Series: + ExtractSeriesInformation(result); + break; + + case ResourceType_Instance: + ExtractInstanceInformation(result); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + } diff -r 28e4b3ec8aff -r 3bdb5db8e839 Core/DicomFormat/DicomMap.h --- a/Core/DicomFormat/DicomMap.h Fri Jan 24 15:35:39 2014 +0100 +++ b/Core/DicomFormat/DicomMap.h Fri Jan 24 17:40:45 2014 +0100 @@ -160,5 +160,8 @@ static void GetMainDicomTags(std::set& result, ResourceType level); static void GetMainDicomTags(std::set& result); + + void ExtractMainDicomTagsForLevel(DicomMap& result, + ResourceType level) const; }; } diff -r 28e4b3ec8aff -r 3bdb5db8e839 Core/DicomFormat/DicomTag.h --- a/Core/DicomFormat/DicomTag.h Fri Jan 24 15:35:39 2014 +0100 +++ b/Core/DicomFormat/DicomTag.h Fri Jan 24 17:40:45 2014 +0100 @@ -90,6 +90,8 @@ static const DicomTag DICOM_TAG_SERIES_INSTANCE_UID(0x0020, 0x000e); static const DicomTag DICOM_TAG_STUDY_INSTANCE_UID(0x0020, 0x000d); static const DicomTag DICOM_TAG_PIXEL_DATA(0x7fe0, 0x0010); + static const DicomTag DICOM_TAG_STUDY_DESCRIPTION(0x0008, 0x1030); + static const DicomTag DICOM_TAG_SERIES_DESCRIPTION(0x0008, 0x103e); static const DicomTag DICOM_TAG_IMAGE_INDEX(0x0054, 0x1330); static const DicomTag DICOM_TAG_INSTANCE_NUMBER(0x0020, 0x0013); diff -r 28e4b3ec8aff -r 3bdb5db8e839 OrthancServer/DicomProtocol/DicomUserConnection.cpp --- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp Fri Jan 24 15:35:39 2014 +0100 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp Fri Jan 24 17:40:45 2014 +0100 @@ -340,12 +340,10 @@ // This is a particular case for ClearCanvas, thanks to Peter Somlo . // https://groups.google.com/d/msg/orthanc-users/j-6C3MAVwiw/iolB9hclom8J // http://www.clearcanvas.ca/Home/Community/OldForums/tabid/526/aff/11/aft/14670/afv/topic/Default.aspx - printf("CLEAR CANVAS\n"); DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "IMAGE"); } else { - printf("GENERIC\n"); DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); } diff -r 28e4b3ec8aff -r 3bdb5db8e839 OrthancServer/OrthancFindRequestHandler.cpp --- a/OrthancServer/OrthancFindRequestHandler.cpp Fri Jan 24 15:35:39 2014 +0100 +++ b/OrthancServer/OrthancFindRequestHandler.cpp Fri Jan 24 17:40:45 2014 +0100 @@ -311,12 +311,142 @@ } + static bool LookupCandidateResourcesInternal(/* inout */ std::set& resources, + /* in */ bool alreadyFiltered, + /* in */ ServerIndex& index, + /* in */ ResourceType level, + /* in */ const DicomMap& query, + /* in */ DicomTag tag) + { + assert(alreadyFiltered || resources.size() == 0); + + if (!query.HasTag(tag)) + { + return alreadyFiltered; + } + + const DicomValue& value = query.GetValue(tag); + if (value.IsNull()) + { + return alreadyFiltered; + } + + std::string str = query.GetValue(tag).AsString(); + if (IsWildcard(str)) + { + return alreadyFiltered; + } + + std::list matches; + index.LookupTagValue(matches, tag, str/*, level*/); + + if (alreadyFiltered) + { + std::set previous = resources; + + for (std::list::const_iterator + it = matches.begin(); it != matches.end(); it++) + { + if (previous.find(*it) != previous.end()) + { + resources.insert(*it); + } + } + } + else + { + for (std::list::const_iterator + it = matches.begin(); it != matches.end(); it++) + { + resources.insert(*it); + } + } + + return true; + } + + + static bool LookupCandidateResourcesAtOneLevel(/* out */ std::set& resources, + /* in */ ServerIndex& index, + /* in */ ResourceType level, + /* in */ const DicomMap& fullQuery, + /* in */ ModalityManufacturer manufacturer) + { + DicomMap tmp; + fullQuery.ExtractMainDicomTagsForLevel(tmp, level); + DicomArray query(tmp); + + if (query.GetSize() == 0) + { + return false; + } + + for (size_t i = 0; i < query.GetSize(); i++) + { + const DicomTag tag = query.GetElement(i).GetTag(); + const DicomValue& value = query.GetElement(i).GetValue(); + if (!value.IsNull()) + { + // TODO TODO TODO + } + } + + printf(">>>>>>>>>>\n"); + query.Print(stdout); + printf("<<<<<<<<<<\n\n"); + return true; + } + + static void LookupCandidateResources(/* out */ std::list& resources, /* in */ ServerIndex& index, /* in */ ResourceType level, /* in */ const DicomMap& query, /* in */ ModalityManufacturer manufacturer) { +#if 1 + { + std::set s; + LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Patient, query, manufacturer); + LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Study, query, manufacturer); + LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Series, query, manufacturer); + LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Instance, query, manufacturer); + } + + std::set filtered; + bool isFiltered = false; + + // Filter by indexed tags, from most specific to least specific + //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_SOP_INSTANCE_UID); + isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_SERIES_INSTANCE_UID); + //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_STUDY_INSTANCE_UID); + //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_PATIENT_ID); + + resources.clear(); + + if (isFiltered) + { + for (std::set::const_iterator + it = filtered.begin(); it != filtered.end(); it++) + { + resources.push_back(*it); + } + } + else + { + // No indexed tag matches the query. Return all the resources at this query level. + Json::Value allResources; + index.GetAllUuids(allResources, level); + assert(allResources.type() == Json::arrayValue); + + for (Json::Value::ArrayIndex i = 0; i < allResources.size(); i++) + { + resources.push_back(allResources[i].asString()); + } + } + +#else + // TODO : Speed up using full querying against the MainDicomTags. resources.clear(); @@ -371,6 +501,7 @@ resources.push_back(allResources[i].asString()); } } +#endif } @@ -416,7 +547,8 @@ default: if (level != ResourceType_Patient && level != ResourceType_Study && - level != ResourceType_Series) + level != ResourceType_Series && + level != ResourceType_Instance) { throw OrthancException(ErrorCode_NotImplemented); } @@ -456,6 +588,8 @@ **/ DicomArray query(input); + query.Print(stdout); + for (std::list::const_iterator resource = resources.begin(); resource != resources.end(); ++resource) { diff -r 28e4b3ec8aff -r 3bdb5db8e839 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Fri Jan 24 15:35:39 2014 +0100 +++ b/OrthancServer/ServerIndex.cpp Fri Jan 24 17:40:45 2014 +0100 @@ -1575,4 +1575,55 @@ result.push_back(db_->GetPublicId(*it)); } } + + + // TODO IS IT USEFUL??? + void ServerIndex::LookupTagValue(std::set& result, + DicomTag tag, + const std::string& value, + ResourceType type) + { + std::list lst; + LookupTagValue(lst, tag, value, type); + + result.clear(); + for (std::list::const_iterator + it = lst.begin(); it != lst.end(); it++) + { + result.insert(*it); + } + } + + + // TODO IS IT USEFUL??? + void ServerIndex::LookupTagValue(std::set& result, + DicomTag tag, + const std::string& value) + { + std::list lst; + LookupTagValue(lst, tag, value); + + result.clear(); + for (std::list::const_iterator + it = lst.begin(); it != lst.end(); it++) + { + result.insert(*it); + } + } + + + // TODO IS IT USEFUL??? + void ServerIndex::LookupTagValue(std::set& result, + const std::string& value) + { + std::list lst; + LookupTagValue(lst, value); + + result.clear(); + for (std::list::const_iterator + it = lst.begin(); it != lst.end(); it++) + { + result.insert(*it); + } + } } diff -r 28e4b3ec8aff -r 3bdb5db8e839 OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Fri Jan 24 15:35:39 2014 +0100 +++ b/OrthancServer/ServerIndex.h Fri Jan 24 17:40:45 2014 +0100 @@ -213,5 +213,21 @@ void LookupTagValue(std::list& result, const std::string& value); + + + // TODO IS IT USEFUL??? + void LookupTagValue(std::set& result, + DicomTag tag, + const std::string& value, + ResourceType type); + + // TODO IS IT USEFUL??? + void LookupTagValue(std::set& result, + DicomTag tag, + const std::string& value); + + // TODO IS IT USEFUL??? + void LookupTagValue(std::set& result, + const std::string& value); }; } diff -r 28e4b3ec8aff -r 3bdb5db8e839 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Fri Jan 24 15:35:39 2014 +0100 +++ b/OrthancServer/main.cpp Fri Jan 24 17:40:45 2014 +0100 @@ -412,6 +412,29 @@ httpServer.Start(); dicomServer.Start(); + + { + DicomUserConnection c; + c.SetLocalApplicationEntityTitle("ORTHANC"); + c.SetDistantApplicationEntityTitle("ORTHANC"); + c.SetDistantHost("localhost"); + c.SetDistantPort(4343); + c.Open(); + + DicomMap m; // Delphine + m.SetValue(DICOM_TAG_PATIENT_ID, "5423962"); + m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1.2.840.113845.11.1000000001951524609.20121203131451.1457891"); + m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "1.2.840.113619.2.278.3.262930758.589.1354512768.115"); + m.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041613043195815872177"); + + DicomFindAnswers fnd; + c.FindInstance(fnd, m); + //c.FindSeries(fnd, m); + + printf("ok %d\n", fnd.GetSize()); + } + + LOG(WARNING) << "Orthanc has started"; Toolbox::ServerBarrier();