Mercurial > hg > orthanc
comparison OrthancServer/OrthancFindRequestHandler.cpp @ 1759:e268412adcf1 db-changes
removal of old implementation of search
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 28 Oct 2015 12:59:18 +0100 |
parents | 318c2e83c2bd |
children | 4f01c9d73f02 |
comparison
equal
deleted
inserted
replaced
1758:318c2e83c2bd | 1759:e268412adcf1 |
---|---|
28 * You should have received a copy of the GNU General Public License | 28 * You should have received a copy of the GNU General Public License |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | 29 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
30 **/ | 30 **/ |
31 | 31 |
32 | 32 |
33 #define USE_LOOKUP_RESOURCE 1 | |
34 | |
35 | |
36 | |
37 #include "PrecompiledHeadersServer.h" | 33 #include "PrecompiledHeadersServer.h" |
38 #include "OrthancFindRequestHandler.h" | 34 #include "OrthancFindRequestHandler.h" |
39 | 35 |
36 #include "../Core/DicomFormat/DicomArray.h" | |
40 #include "../Core/Logging.h" | 37 #include "../Core/Logging.h" |
41 #include "../Core/DicomFormat/DicomArray.h" | 38 #include "FromDcmtkBridge.h" |
39 #include "OrthancInitialization.h" | |
40 #include "Search/LookupResource.h" | |
42 #include "ServerToolbox.h" | 41 #include "ServerToolbox.h" |
43 #include "OrthancInitialization.h" | |
44 #include "FromDcmtkBridge.h" | |
45 | |
46 #include "ResourceFinder.h" | |
47 #include "DicomFindQuery.h" | |
48 #include "Search/LookupResource.h" | |
49 | 42 |
50 #include <boost/regex.hpp> | 43 #include <boost/regex.hpp> |
51 | 44 |
52 | 45 |
53 namespace Orthanc | 46 namespace Orthanc |
93 answers.Add(result); | 86 answers.Add(result); |
94 } | 87 } |
95 } | 88 } |
96 | 89 |
97 | 90 |
98 namespace | |
99 { | |
100 class CFindQuery : public DicomFindQuery | |
101 { | |
102 private: | |
103 DicomFindAnswers& answers_; | |
104 ServerIndex& index_; | |
105 const DicomArray& query_; | |
106 bool hasModalitiesInStudy_; | |
107 std::set<std::string> modalitiesInStudy_; | |
108 | |
109 public: | |
110 CFindQuery(DicomFindAnswers& answers, | |
111 ServerIndex& index, | |
112 const DicomArray& query) : | |
113 answers_(answers), | |
114 index_(index), | |
115 query_(query), | |
116 hasModalitiesInStudy_(false) | |
117 { | |
118 } | |
119 | |
120 void SetModalitiesInStudy(const std::string& value) | |
121 { | |
122 hasModalitiesInStudy_ = true; | |
123 | |
124 std::vector<std::string> tmp; | |
125 Toolbox::TokenizeString(tmp, value, '\\'); | |
126 | |
127 for (size_t i = 0; i < tmp.size(); i++) | |
128 { | |
129 modalitiesInStudy_.insert(tmp[i]); | |
130 } | |
131 } | |
132 | |
133 virtual bool HasMainDicomTagsFilter(ResourceType level) const | |
134 { | |
135 if (DicomFindQuery::HasMainDicomTagsFilter(level)) | |
136 { | |
137 return true; | |
138 } | |
139 | |
140 return (level == ResourceType_Study && | |
141 hasModalitiesInStudy_); | |
142 } | |
143 | |
144 virtual bool FilterMainDicomTags(const std::string& resourceId, | |
145 ResourceType level, | |
146 const DicomMap& mainTags) const | |
147 { | |
148 if (!DicomFindQuery::FilterMainDicomTags(resourceId, level, mainTags)) | |
149 { | |
150 return false; | |
151 } | |
152 | |
153 if (level != ResourceType_Study || | |
154 !hasModalitiesInStudy_) | |
155 { | |
156 return true; | |
157 } | |
158 | |
159 try | |
160 { | |
161 // We are considering a single study, and the | |
162 // "MODALITIES_IN_STUDY" tag is set in the C-Find. Check | |
163 // whether one of its child series matches one of the | |
164 // modalities. | |
165 | |
166 Json::Value study; | |
167 if (index_.LookupResource(study, resourceId, ResourceType_Study)) | |
168 { | |
169 // Loop over the series of the considered study. | |
170 for (Json::Value::ArrayIndex j = 0; j < study["Series"].size(); j++) | |
171 { | |
172 Json::Value series; | |
173 if (index_.LookupResource(series, study["Series"][j].asString(), ResourceType_Series)) | |
174 { | |
175 // Get the modality of this series | |
176 if (series["MainDicomTags"].isMember("Modality")) | |
177 { | |
178 std::string modality = series["MainDicomTags"]["Modality"].asString(); | |
179 if (modalitiesInStudy_.find(modality) != modalitiesInStudy_.end()) | |
180 { | |
181 // This series of the considered study matches one | |
182 // of the required modalities. Take the study into | |
183 // consideration for future filtering. | |
184 return true; | |
185 } | |
186 } | |
187 } | |
188 } | |
189 } | |
190 } | |
191 catch (OrthancException&) | |
192 { | |
193 // This resource has probably been deleted during the find request | |
194 } | |
195 | |
196 return false; | |
197 } | |
198 | |
199 virtual bool HasInstanceFilter() const | |
200 { | |
201 return true; | |
202 } | |
203 | |
204 virtual bool FilterInstance(const std::string& instanceId, | |
205 const Json::Value& content) const | |
206 { | |
207 bool ok = DicomFindQuery::FilterInstance(instanceId, content); | |
208 | |
209 if (ok) | |
210 { | |
211 // Add this resource to the answers | |
212 AddAnswer(answers_, content, query_); | |
213 } | |
214 | |
215 return ok; | |
216 } | |
217 }; | |
218 } | |
219 | |
220 | |
221 | |
222 bool OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, | 91 bool OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, |
223 const DicomMap& input, | 92 const DicomMap& input, |
224 const std::string& remoteIp, | 93 const std::string& remoteIp, |
225 const std::string& remoteAet) | 94 const std::string& remoteAet) |
226 { | 95 { |
279 | 148 |
280 /** | 149 /** |
281 * Build up the query object. | 150 * Build up the query object. |
282 **/ | 151 **/ |
283 | 152 |
284 #if USE_LOOKUP_RESOURCE == 1 | |
285 LookupResource finder(level); | 153 LookupResource finder(level); |
286 #else | 154 |
287 CFindQuery findQuery(answers, context_.GetIndex(), query); | |
288 findQuery.SetLevel(level); | |
289 #endif | |
290 | |
291 for (size_t i = 0; i < query.GetSize(); i++) | 155 for (size_t i = 0; i < query.GetSize(); i++) |
292 { | 156 { |
293 const DicomTag tag = query.GetElement(i).GetTag(); | 157 const DicomTag tag = query.GetElement(i).GetTag(); |
294 | 158 |
295 if (query.GetElement(i).GetValue().IsNull() || | 159 if (query.GetElement(i).GetValue().IsNull() || |
304 { | 168 { |
305 // An empty string corresponds to a "*" wildcard constraint, so we ignore it | 169 // An empty string corresponds to a "*" wildcard constraint, so we ignore it |
306 continue; | 170 continue; |
307 } | 171 } |
308 | 172 |
309 #if USE_LOOKUP_RESOURCE == 1 | |
310 | |
311 ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag); | 173 ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag); |
312 | 174 |
175 // DICOM specifies that searches must be case sensitive, except | |
176 // for tags with a PN value representation | |
313 bool sensitive = true; | 177 bool sensitive = true; |
314 if (vr == ValueRepresentation_PatientName) | 178 if (vr == ValueRepresentation_PatientName) |
315 { | 179 { |
316 sensitive = caseSensitivePN; | 180 sensitive = caseSensitivePN; |
317 } | 181 } |
318 | 182 |
319 finder.AddDicomConstraint(tag, value, sensitive); | 183 finder.AddDicomConstraint(tag, value, sensitive); |
320 #else | |
321 | |
322 if (tag == DICOM_TAG_MODALITIES_IN_STUDY) | |
323 { | |
324 findQuery.SetModalitiesInStudy(value); | |
325 } | |
326 else | |
327 { | |
328 findQuery.SetConstraint(tag, value, caseSensitivePN); | |
329 } | |
330 #endif | |
331 } | 184 } |
332 | 185 |
333 | 186 |
334 /** | 187 /** |
335 * Run the query. | 188 * Run the query. |
336 **/ | 189 **/ |
337 | 190 |
338 #if USE_LOOKUP_RESOURCE != 1 | |
339 ResourceFinder finder(context_); | |
340 | |
341 switch (level) | |
342 { | |
343 case ResourceType_Patient: | |
344 case ResourceType_Study: | |
345 case ResourceType_Series: | |
346 finder.SetMaxResults(maxResults_); | |
347 break; | |
348 | |
349 case ResourceType_Instance: | |
350 finder.SetMaxResults(maxInstances_); | |
351 break; | |
352 | |
353 default: | |
354 throw OrthancException(ErrorCode_InternalError); | |
355 } | |
356 #else | |
357 size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; | 191 size_t maxResults = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; |
358 | 192 |
359 #endif | |
360 | |
361 #if USE_LOOKUP_RESOURCE == 1 | |
362 std::vector<std::string> resources, instances; | 193 std::vector<std::string> resources, instances; |
363 context_.GetIndex().FindCandidates(resources, instances, finder); | 194 context_.GetIndex().FindCandidates(resources, instances, finder); |
364 | 195 |
365 assert(resources.size() == instances.size()); | 196 assert(resources.size() == instances.size()); |
366 bool finished = true; | 197 bool finished = true; |
383 AddAnswer(answers, dicom, query); | 214 AddAnswer(answers, dicom, query); |
384 } | 215 } |
385 } | 216 } |
386 } | 217 } |
387 | 218 |
388 #else | |
389 std::list<std::string> tmp; | |
390 bool finished = finder.Apply(tmp, findQuery); | |
391 #endif | |
392 | |
393 LOG(INFO) << "Number of matching resources: " << answers.GetSize(); | 219 LOG(INFO) << "Number of matching resources: " << answers.GetSize(); |
394 | 220 |
395 return finished; | 221 return finished; |
396 } | 222 } |
397 } | 223 } |