# HG changeset patch # User Sebastien Jodogne # Date 1447954320 -3600 # Node ID 5e08a5fe6b27efe7eb9fba2280944a53341c2cc3 # Parent af6840eb23ee2d078a080cc703096b8ae19bf98e HierarchicalMatcher - extracting tags diff -r af6840eb23ee -r 5e08a5fe6b27 OrthancServer/Search/HierarchicalMatcher.cpp --- a/OrthancServer/Search/HierarchicalMatcher.cpp Thu Nov 19 17:41:22 2015 +0100 +++ b/OrthancServer/Search/HierarchicalMatcher.cpp Thu Nov 19 18:32:00 2015 +0100 @@ -35,6 +35,7 @@ #include "../../Core/OrthancException.h" #include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" #include @@ -84,6 +85,12 @@ } DicomTag tag(FromDcmtkBridge::Convert(element->getTag())); + if (tag == DICOM_TAG_SPECIFIC_CHARACTER_SET) + { + // Ignore this specific tag + continue; + } + ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag); if (constraints_.find(tag) != constraints_.end() || @@ -179,4 +186,139 @@ return s; } + + + bool HierarchicalMatcher::Match(ParsedDicomFile& dicom) const + { + return MatchInternal(*dicom.GetDcmtkObject().getDataset(), + dicom.GetEncoding()); + } + + + bool HierarchicalMatcher::MatchInternal(DcmItem& item, + Encoding encoding) const + { + for (Constraints::const_iterator it = constraints_.begin(); + it != constraints_.end(); ++it) + { + if (it->second != NULL) + { + DcmTagKey tag = ToDcmtkBridge::Convert(it->first); + + DcmElement* element = NULL; + if (!item.findAndGetElement(tag, element).good() || + element == NULL) + { + return false; + } + + std::auto_ptr value(FromDcmtkBridge::ConvertLeafElement + (*element, DicomToJsonFlags_None, encoding)); + + if (value->IsNull() || + value->IsBinary() || + !it->second->Match(value->GetContent())) + { + return false; + } + } + } + + for (Sequences::const_iterator it = sequences_.begin(); + it != sequences_.end(); ++it) + { + if (it->second != NULL) + { + DcmTagKey tag = ToDcmtkBridge::Convert(it->first); + + DcmSequenceOfItems* sequence = NULL; + if (!item.findAndGetSequence(tag, sequence).good() || + sequence == NULL) + { + return false; + } + + bool match = false; + + for (unsigned long i = 0; i < sequence->card(); i++) + { + if (it->second->MatchInternal(*sequence->getItem(i), encoding)) + { + match = true; + break; + } + } + + if (!match) + { + return false; + } + } + } + + return true; + } + + + DcmDataset* HierarchicalMatcher::ExtractInternal(DcmItem& item, + Encoding encoding) const + { + std::auto_ptr dataset(new DcmDataset); + + for (Constraints::const_iterator it = constraints_.begin(); + it != constraints_.end(); ++it) + { + DcmTagKey tag = ToDcmtkBridge::Convert(it->first); + + DcmElement* element = NULL; + if (item.findAndGetElement(tag, element).good() && + element != NULL) + { + std::auto_ptr cloned(FromDcmtkBridge::CreateElementForTag(it->first)); + cloned->copyFrom(*element); + dataset->insert(cloned.release()); + } + } + + for (Sequences::const_iterator it = sequences_.begin(); + it != sequences_.end(); ++it) + { + DcmTagKey tag = ToDcmtkBridge::Convert(it->first); + + DcmSequenceOfItems* sequence = NULL; + if (item.findAndGetSequence(tag, sequence).good() && + sequence != NULL) + { + std::auto_ptr cloned(new DcmSequenceOfItems(tag)); + + for (unsigned long i = 0; i < sequence->card(); i++) + { + if (it->second == NULL) + { + cloned->append(new DcmItem(*sequence->getItem(i))); + } + else if (it->second->MatchInternal(*sequence->getItem(i), encoding)) + { + cloned->append(it->second->ExtractInternal(*sequence->getItem(i), encoding)); + } + } + + dataset->insert(cloned.release()); + } + } + + return dataset.release(); + } + + + ParsedDicomFile* HierarchicalMatcher::Extract(ParsedDicomFile& dicom) const + { + std::auto_ptr dataset(ExtractInternal(*dicom.GetDcmtkObject().getDataset(), + dicom.GetEncoding())); + + std::auto_ptr result(new ParsedDicomFile(*dataset)); + result->SetEncoding(Encoding_Utf8); + + return result.release(); + } } diff -r af6840eb23ee -r 5e08a5fe6b27 OrthancServer/Search/HierarchicalMatcher.h --- a/OrthancServer/Search/HierarchicalMatcher.h Thu Nov 19 17:41:22 2015 +0100 +++ b/OrthancServer/Search/HierarchicalMatcher.h Thu Nov 19 18:32:00 2015 +0100 @@ -60,6 +60,12 @@ Setup(query, caseSensitivePN, encoding); } + bool MatchInternal(DcmItem& dicom, + Encoding encoding) const; + + DcmDataset* ExtractInternal(DcmItem& dicom, + Encoding encoding) const; + public: HierarchicalMatcher(ParsedDicomFile& query, bool caseSensitivePN); @@ -67,5 +73,9 @@ ~HierarchicalMatcher(); std::string Format(const std::string& prefix = "") const; + + bool Match(ParsedDicomFile& dicom) const; + + ParsedDicomFile* Extract(ParsedDicomFile& dicom) const; }; } diff -r af6840eb23ee -r 5e08a5fe6b27 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Thu Nov 19 17:41:22 2015 +0100 +++ b/OrthancServer/main.cpp Thu Nov 19 18:32:00 2015 +0100 @@ -107,6 +107,7 @@ const std::string& remoteIp, const std::string& remoteAet) { + printf("=====================================================================\n"); printf("Worklist\n"); bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false); @@ -114,6 +115,24 @@ std::cout << matcher.Format(); + for (unsigned int i = 1; i <= 10; i++) + { + std::string p = "/tmp/worklists/db/OFFIS/item" + boost::lexical_cast(i) + ".wl"; + std::string s; + Toolbox::ReadFile(s, p); + ParsedDicomFile f(s); + std::cout << p << " => " << matcher.Match(f) << std::endl; + + if (matcher.Match(f)) + { + std::auto_ptr e(matcher.Extract(f)); + + Json::Value v; + e->ToJson(v, DicomToJsonFormat_Short, DicomToJsonFlags_Default, 0); + std::cout << v; + } + } + return true; } };