Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomFormat/DicomMap.cpp @ 4932:b7ce2bb6b881 more-tags
refactored the list of MainDicomTags to be able to change it dynamicaly. Unit tests and Integration tests ok
author | Alain Mazy <am@osimis.io> |
---|---|
date | Wed, 09 Mar 2022 11:17:08 +0100 |
parents | 43e613a7756b |
children | 312c6f4da888 |
comparison
equal
deleted
inserted
replaced
4930:1ce32c1ec4cf | 4932:b7ce2bb6b881 |
---|---|
42 struct MainDicomTag | 42 struct MainDicomTag |
43 { | 43 { |
44 const DicomTag tag_; | 44 const DicomTag tag_; |
45 const char* name_; | 45 const char* name_; |
46 }; | 46 }; |
47 } | 47 typedef std::vector<MainDicomTag> MainDicomTags; |
48 | 48 |
49 static const MainDicomTag PATIENT_MAIN_DICOM_TAGS[] = | 49 } |
50 | |
51 | |
52 static const MainDicomTag DEFAULT_PATIENT_MAIN_DICOM_TAGS[] = | |
50 { | 53 { |
51 // { DicomTag(0x0010, 0x1010), "PatientAge" }, | 54 // { DicomTag(0x0010, 0x1010), "PatientAge" }, |
52 // { DicomTag(0x0010, 0x1040), "PatientAddress" }, | 55 // { DicomTag(0x0010, 0x1040), "PatientAddress" }, |
53 { DicomTag(0x0010, 0x0010), "PatientName" }, | 56 { DICOM_TAG_PATIENT_NAME, "PatientName" }, |
54 { DicomTag(0x0010, 0x0030), "PatientBirthDate" }, | 57 { DICOM_TAG_PATIENT_BIRTH_DATE, "PatientBirthDate" }, |
55 { DicomTag(0x0010, 0x0040), "PatientSex" }, | 58 { DICOM_TAG_PATIENT_SEX, "PatientSex" }, |
56 { DicomTag(0x0010, 0x1000), "OtherPatientIDs" }, | 59 { DICOM_TAG_OTHER_PATIENT_IDS, "OtherPatientIDs" }, |
57 { DICOM_TAG_PATIENT_ID, "PatientID" } | 60 { DICOM_TAG_PATIENT_ID, "PatientID" } |
58 }; | 61 }; |
59 | 62 |
60 static const MainDicomTag STUDY_MAIN_DICOM_TAGS[] = | 63 static const MainDicomTag DEFAULT_STUDY_MAIN_DICOM_TAGS[] = |
61 { | 64 { |
62 // { DicomTag(0x0010, 0x1020), "PatientSize" }, | 65 // { DicomTag(0x0010, 0x1020), "PatientSize" }, |
63 // { DicomTag(0x0010, 0x1030), "PatientWeight" }, | 66 // { DicomTag(0x0010, 0x1030), "PatientWeight" }, |
64 { DICOM_TAG_STUDY_DATE, "StudyDate" }, | 67 { DICOM_TAG_STUDY_DATE, "StudyDate" }, |
65 { DicomTag(0x0008, 0x0030), "StudyTime" }, | 68 { DICOM_TAG_STUDY_TIME, "StudyTime" }, |
66 { DicomTag(0x0020, 0x0010), "StudyID" }, | 69 { DICOM_TAG_STUDY_ID, "StudyID" }, |
67 { DICOM_TAG_STUDY_DESCRIPTION, "StudyDescription" }, | 70 { DICOM_TAG_STUDY_DESCRIPTION, "StudyDescription" }, |
68 { DICOM_TAG_ACCESSION_NUMBER, "AccessionNumber" }, | 71 { DICOM_TAG_ACCESSION_NUMBER, "AccessionNumber" }, |
69 { DICOM_TAG_STUDY_INSTANCE_UID, "StudyInstanceUID" }, | 72 { DICOM_TAG_STUDY_INSTANCE_UID, "StudyInstanceUID" }, |
70 | 73 |
71 // New in db v6 | 74 // New in db v6 |
72 { DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, "RequestedProcedureDescription" }, | 75 { DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, "RequestedProcedureDescription" }, |
73 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" }, | 76 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" }, |
74 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" }, | 77 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" }, |
75 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" } | 78 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" } |
76 }; | 79 }; |
77 | 80 |
78 static const MainDicomTag SERIES_MAIN_DICOM_TAGS[] = | 81 static const MainDicomTag DEFAULT_SERIES_MAIN_DICOM_TAGS[] = |
79 { | 82 { |
80 // { DicomTag(0x0010, 0x1080), "MilitaryRank" }, | 83 // { DicomTag(0x0010, 0x1080), "MilitaryRank" }, |
81 { DicomTag(0x0008, 0x0021), "SeriesDate" }, | 84 { DICOM_TAG_SERIES_DATE, "SeriesDate" }, |
82 { DicomTag(0x0008, 0x0031), "SeriesTime" }, | 85 { DICOM_TAG_SERIES_TIME, "SeriesTime" }, |
83 { DICOM_TAG_MODALITY, "Modality" }, | 86 { DICOM_TAG_MODALITY, "Modality" }, |
84 { DicomTag(0x0008, 0x0070), "Manufacturer" }, | 87 { DICOM_TAG_MANUFACTURER, "Manufacturer" }, |
85 { DicomTag(0x0008, 0x1010), "StationName" }, | 88 { DICOM_TAG_STATION_NAME, "StationName" }, |
86 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" }, | 89 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" }, |
87 { DicomTag(0x0018, 0x0015), "BodyPartExamined" }, | 90 { DICOM_TAG_BODY_PART_EXAMINED, "BodyPartExamined" }, |
88 { DicomTag(0x0018, 0x0024), "SequenceName" }, | 91 { DICOM_TAG_SEQUENCE_NAME, "SequenceName" }, |
89 { DicomTag(0x0018, 0x1030), "ProtocolName" }, | 92 { DICOM_TAG_PROTOCOL_NAME, "ProtocolName" }, |
90 { DicomTag(0x0020, 0x0011), "SeriesNumber" }, | 93 { DICOM_TAG_SERIES_NUMBER, "SeriesNumber" }, |
91 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImages" }, | 94 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImages" }, |
92 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" }, | 95 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" }, |
93 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" }, | 96 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" }, |
94 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" }, | 97 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" }, |
95 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" }, | 98 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" }, |
101 { DICOM_TAG_OPERATOR_NAME, "OperatorsName" }, | 104 { DICOM_TAG_OPERATOR_NAME, "OperatorsName" }, |
102 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" }, | 105 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" }, |
103 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" }, | 106 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" }, |
104 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgent" } | 107 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgent" } |
105 }; | 108 }; |
106 | 109 |
107 static const MainDicomTag INSTANCE_MAIN_DICOM_TAGS[] = | 110 static const MainDicomTag DEFAULT_INSTANCE_MAIN_DICOM_TAGS[] = |
108 { | 111 { |
109 { DicomTag(0x0008, 0x0012), "InstanceCreationDate" }, | 112 { DICOM_TAG_INSTANCE_CREATION_DATE, "InstanceCreationDate" }, |
110 { DicomTag(0x0008, 0x0013), "InstanceCreationTime" }, | 113 { DICOM_TAG_INSTANCE_CREATION_TIME, "InstanceCreationTime" }, |
111 { DicomTag(0x0020, 0x0012), "AcquisitionNumber" }, | 114 { DICOM_TAG_ACQUISITION_NUMBER, "AcquisitionNumber" }, |
112 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" }, | 115 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" }, |
113 { DICOM_TAG_INSTANCE_NUMBER, "InstanceNumber" }, | 116 { DICOM_TAG_INSTANCE_NUMBER, "InstanceNumber" }, |
114 { DICOM_TAG_NUMBER_OF_FRAMES, "NumberOfFrames" }, | 117 { DICOM_TAG_NUMBER_OF_FRAMES, "NumberOfFrames" }, |
115 { DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, "TemporalPositionIdentifier" }, | 118 { DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, "TemporalPositionIdentifier" }, |
116 { DICOM_TAG_SOP_INSTANCE_UID, "SOPInstanceUID" }, | 119 { DICOM_TAG_SOP_INSTANCE_UID, "SOPInstanceUID" }, |
128 **/ | 131 **/ |
129 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2 | 132 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2 |
130 }; | 133 }; |
131 | 134 |
132 | 135 |
133 static void LoadMainDicomTags(const MainDicomTag*& tags, | |
134 size_t& size, | |
135 ResourceType level) | |
136 { | |
137 switch (level) | |
138 { | |
139 case ResourceType_Patient: | |
140 tags = PATIENT_MAIN_DICOM_TAGS; | |
141 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
142 break; | |
143 | |
144 case ResourceType_Study: | |
145 tags = STUDY_MAIN_DICOM_TAGS; | |
146 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
147 break; | |
148 | |
149 case ResourceType_Series: | |
150 tags = SERIES_MAIN_DICOM_TAGS; | |
151 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
152 break; | |
153 | |
154 case ResourceType_Instance: | |
155 tags = INSTANCE_MAIN_DICOM_TAGS; | |
156 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
157 break; | |
158 | |
159 default: | |
160 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
161 } | |
162 } | |
163 | |
164 | |
165 static void LoadMainDicomTags(std::map<DicomTag, std::string>& target, | |
166 ResourceType level) | |
167 { | |
168 const MainDicomTag* tags = NULL; | |
169 size_t size; | |
170 LoadMainDicomTags(tags, size, level); | |
171 | |
172 assert(tags != NULL && | |
173 size != 0); | |
174 | |
175 for (size_t i = 0; i < size; i++) | |
176 { | |
177 assert(target.find(tags[i].tag_) == target.end()); | |
178 | |
179 target[tags[i].tag_] = tags[i].name_; | |
180 } | |
181 } | |
182 | |
183 | |
184 namespace | 136 namespace |
185 { | 137 { |
186 class DicomTag2 : public DicomTag | 138 class DicomTag2 : public DicomTag |
187 { | 139 { |
188 public: | 140 public: |
197 } | 149 } |
198 }; | 150 }; |
199 } | 151 } |
200 | 152 |
201 | 153 |
202 static void LoadMainDicomTags(std::map<std::string, DicomTag2>& target, | 154 class DicomMap::MainDicomTagsConfiguration |
203 ResourceType level) | 155 { |
204 { | 156 private: |
205 const MainDicomTag* tags = NULL; | 157 friend DicomMap; |
206 size_t size; | 158 |
207 LoadMainDicomTags(tags, size, level); | 159 // we keep many "copies" of the same data to guarantee quick access to organized data |
208 | 160 // and avoid rebuilding it all the time. |
209 assert(tags != NULL && | 161 std::map<ResourceType, std::map<DicomTag, std::string> > mainDicomTagsByTag_; |
210 size != 0); | 162 std::map<ResourceType, std::map<std::string, DicomTag2> > mainDicomTagsByName_; |
211 | 163 std::map<ResourceType, std::set<DicomTag> > mainDicomTagsByLevel_; |
212 for (size_t i = 0; i < size; i++) | 164 std::set<DicomTag> allMainDicomTags_; |
213 { | 165 |
214 assert(target.find(tags[i].name_) == target.end()); | 166 MainDicomTagsConfiguration() |
215 | 167 { |
216 target[tags[i].name_] = DicomTag2(tags[i].tag_); | 168 ResetDefaultMainDicomTags(); |
217 } | 169 } |
218 } | 170 |
171 void ResetDefaultMainDicomTags() | |
172 { | |
173 mainDicomTagsByTag_.clear(); | |
174 mainDicomTagsByName_.clear(); | |
175 mainDicomTagsByLevel_.clear(); | |
176 allMainDicomTags_.clear(); | |
177 | |
178 // by default, initialize with the previous static list (up to 1.10.0) | |
179 LoadDefaultMainDicomTags(ResourceType_Patient); | |
180 LoadDefaultMainDicomTags(ResourceType_Study); | |
181 LoadDefaultMainDicomTags(ResourceType_Series); | |
182 LoadDefaultMainDicomTags(ResourceType_Instance); | |
183 } | |
184 | |
185 void LoadDefaultMainDicomTags(ResourceType level) | |
186 { | |
187 assert(mainDicomTagsByTag_.find(level) == mainDicomTagsByTag_.end()); | |
188 | |
189 const MainDicomTag* tags = NULL; | |
190 size_t size; | |
191 | |
192 switch (level) | |
193 { | |
194 case ResourceType_Patient: | |
195 tags = DEFAULT_PATIENT_MAIN_DICOM_TAGS; | |
196 size = sizeof(DEFAULT_PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
197 break; | |
198 | |
199 case ResourceType_Study: | |
200 tags = DEFAULT_STUDY_MAIN_DICOM_TAGS; | |
201 size = sizeof(DEFAULT_STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
202 break; | |
203 | |
204 case ResourceType_Series: | |
205 tags = DEFAULT_SERIES_MAIN_DICOM_TAGS; | |
206 size = sizeof(DEFAULT_SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
207 break; | |
208 | |
209 case ResourceType_Instance: | |
210 tags = DEFAULT_INSTANCE_MAIN_DICOM_TAGS; | |
211 size = sizeof(DEFAULT_INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); | |
212 break; | |
213 | |
214 default: | |
215 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
216 } | |
217 | |
218 assert(tags != NULL && | |
219 size != 0); | |
220 | |
221 for (size_t i = 0; i < size; i++) | |
222 { | |
223 AddMainDicomTag(tags[i].tag_, tags[i].name_, level); | |
224 } | |
225 | |
226 } | |
227 | |
228 public: | |
229 // Singleton pattern | |
230 static MainDicomTagsConfiguration& GetInstance() | |
231 { | |
232 static MainDicomTagsConfiguration parameters; | |
233 return parameters; | |
234 } | |
235 | |
236 void AddMainDicomTag(const DicomTag& tag, const std::string& name, ResourceType level) | |
237 { | |
238 if (mainDicomTagsByTag_[level].find(tag) != mainDicomTagsByTag_[level].end()) | |
239 { | |
240 throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined"); | |
241 } | |
242 | |
243 if (mainDicomTagsByName_[level].find(name) != mainDicomTagsByName_[level].end()) | |
244 { | |
245 throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, name + " is already defined"); | |
246 } | |
247 | |
248 mainDicomTagsByTag_[level][tag] = name; | |
249 mainDicomTagsByName_[level][name] = DicomTag2(tag); | |
250 mainDicomTagsByLevel_[level].insert(tag); | |
251 allMainDicomTags_.insert(tag); | |
252 } | |
253 | |
254 const std::map<DicomTag, std::string>& GetMainDicomTags(ResourceType level) const | |
255 { | |
256 assert(mainDicomTagsByTag_.find(level) != mainDicomTagsByTag_.end()); | |
257 | |
258 return mainDicomTagsByTag_.at(level); | |
259 } | |
260 | |
261 const std::map<std::string, DicomTag2>& GetMainDicomTagsByName(ResourceType level) const | |
262 { | |
263 assert(mainDicomTagsByName_.find(level) != mainDicomTagsByName_.end()); | |
264 | |
265 return mainDicomTagsByName_.at(level); | |
266 } | |
267 | |
268 const std::set<DicomTag>& GetMainDicomTagsByLevel(ResourceType level) const | |
269 { | |
270 assert(mainDicomTagsByLevel_.find(level) != mainDicomTagsByLevel_.end()); | |
271 | |
272 return mainDicomTagsByLevel_.at(level); | |
273 } | |
274 | |
275 const std::set<DicomTag>& GetAllMainDicomTags() const | |
276 { | |
277 return allMainDicomTags_; | |
278 } | |
279 }; | |
219 | 280 |
220 | 281 |
221 void DicomMap::SetValueInternal(uint16_t group, | 282 void DicomMap::SetValueInternal(uint16_t group, |
222 uint16_t element, | 283 uint16_t element, |
223 DicomValue* value) | 284 DicomValue* value) |
294 } | 355 } |
295 | 356 |
296 | 357 |
297 static void ExtractTags(DicomMap& result, | 358 static void ExtractTags(DicomMap& result, |
298 const DicomMap::Content& source, | 359 const DicomMap::Content& source, |
299 const MainDicomTag* tags, | 360 const std::map<DicomTag, std::string>& mainDicomTags) |
300 size_t count) | |
301 { | 361 { |
302 result.Clear(); | 362 result.Clear(); |
303 | 363 |
304 for (unsigned int i = 0; i < count; i++) | 364 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); |
305 { | 365 itmt != mainDicomTags.end(); itmt++) |
306 DicomMap::Content::const_iterator it = source.find(tags[i].tag_); | 366 { |
367 DicomMap::Content::const_iterator it = source.find(itmt->first); | |
307 if (it != source.end()) | 368 if (it != source.end()) |
308 { | 369 { |
309 result.SetValue(it->first, *it->second /* value will be cloned */); | 370 result.SetValue(it->first, *it->second /* value will be cloned */); |
310 } | 371 } |
311 } | 372 } |
312 } | 373 } |
313 | 374 |
314 | 375 |
315 void DicomMap::ExtractPatientInformation(DicomMap& result) const | 376 void DicomMap::ExtractPatientInformation(DicomMap& result) const |
316 { | 377 { |
317 ExtractTags(result, content_, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 378 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Patient); |
379 ExtractTags(result, content_, mainDicomTags); | |
318 } | 380 } |
319 | 381 |
320 void DicomMap::ExtractStudyInformation(DicomMap& result) const | 382 void DicomMap::ExtractStudyInformation(DicomMap& result) const |
321 { | 383 { |
322 ExtractTags(result, content_, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 384 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Study); |
385 ExtractTags(result, content_, mainDicomTags); | |
323 } | 386 } |
324 | 387 |
325 void DicomMap::ExtractSeriesInformation(DicomMap& result) const | 388 void DicomMap::ExtractSeriesInformation(DicomMap& result) const |
326 { | 389 { |
327 ExtractTags(result, content_, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 390 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Series); |
391 ExtractTags(result, content_, mainDicomTags); | |
328 } | 392 } |
329 | 393 |
330 void DicomMap::ExtractInstanceInformation(DicomMap& result) const | 394 void DicomMap::ExtractInstanceInformation(DicomMap& result) const |
331 { | 395 { |
332 ExtractTags(result, content_, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 396 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Instance); |
397 ExtractTags(result, content_, mainDicomTags); | |
333 } | 398 } |
334 | 399 |
335 | 400 |
336 DicomMap::~DicomMap() | 401 DicomMap::~DicomMap() |
337 { | 402 { |
413 } | 478 } |
414 } | 479 } |
415 | 480 |
416 | 481 |
417 static void SetupFindTemplate(DicomMap& result, | 482 static void SetupFindTemplate(DicomMap& result, |
418 const MainDicomTag* tags, | 483 const std::map<DicomTag, std::string>& mainDicomTags) |
419 size_t count) | |
420 { | 484 { |
421 result.Clear(); | 485 result.Clear(); |
422 | 486 |
423 for (size_t i = 0; i < count; i++) | 487 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); |
424 { | 488 itmt != mainDicomTags.end(); itmt++) |
425 result.SetValue(tags[i].tag_, "", false); | 489 { |
490 result.SetValue(itmt->first, "", false); | |
426 } | 491 } |
427 } | 492 } |
428 | 493 |
429 void DicomMap::SetupFindPatientTemplate(DicomMap& result) | 494 void DicomMap::SetupFindPatientTemplate(DicomMap& result) |
430 { | 495 { |
431 SetupFindTemplate(result, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 496 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Patient); |
497 SetupFindTemplate(result, mainDicomTags); | |
432 } | 498 } |
433 | 499 |
434 void DicomMap::SetupFindStudyTemplate(DicomMap& result) | 500 void DicomMap::SetupFindStudyTemplate(DicomMap& result) |
435 { | 501 { |
436 SetupFindTemplate(result, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 502 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Study); |
503 SetupFindTemplate(result, mainDicomTags); | |
437 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); | 504 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); |
438 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); | 505 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); |
439 | 506 |
440 // These main DICOM tags are only indirectly related to the | 507 // These main DICOM tags are only indirectly related to the |
441 // General Study Module, remove them | 508 // General Study Module, remove them |
444 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION); | 511 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION); |
445 } | 512 } |
446 | 513 |
447 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) | 514 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) |
448 { | 515 { |
449 SetupFindTemplate(result, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 516 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Series); |
517 SetupFindTemplate(result, mainDicomTags); | |
450 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); | 518 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); |
451 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); | 519 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); |
452 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); | 520 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); |
453 | 521 |
454 // These tags are considered as "main" by Orthanc, but are not in the Series module | 522 // These tags are considered as "main" by Orthanc, but are not in the Series module |
466 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT); | 534 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT); |
467 } | 535 } |
468 | 536 |
469 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) | 537 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) |
470 { | 538 { |
471 SetupFindTemplate(result, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag)); | 539 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Instance); |
540 SetupFindTemplate(result, mainDicomTags); | |
472 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); | 541 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); |
473 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); | 542 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); |
474 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); | 543 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); |
475 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false); | 544 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false); |
476 } | 545 } |
486 } | 555 } |
487 | 556 |
488 | 557 |
489 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) | 558 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) |
490 { | 559 { |
491 const MainDicomTag *tags = NULL; | 560 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); |
492 size_t size; | 561 return mainDicomTags.find(tag) != mainDicomTags.end(); |
493 LoadMainDicomTags(tags, size, level); | |
494 | |
495 for (size_t i = 0; i < size; i++) | |
496 { | |
497 if (tags[i].tag_ == tag) | |
498 { | |
499 return true; | |
500 } | |
501 } | |
502 | |
503 return false; | |
504 } | 562 } |
505 | 563 |
506 bool DicomMap::IsMainDicomTag(const DicomTag& tag) | 564 bool DicomMap::IsMainDicomTag(const DicomTag& tag) |
507 { | 565 { |
508 return (IsMainDicomTag(tag, ResourceType_Patient) || | 566 return (IsMainDicomTag(tag, ResourceType_Patient) || |
509 IsMainDicomTag(tag, ResourceType_Study) || | 567 IsMainDicomTag(tag, ResourceType_Study) || |
510 IsMainDicomTag(tag, ResourceType_Series) || | 568 IsMainDicomTag(tag, ResourceType_Series) || |
511 IsMainDicomTag(tag, ResourceType_Instance)); | 569 IsMainDicomTag(tag, ResourceType_Instance)); |
512 } | 570 } |
513 | 571 |
514 | 572 const std::set<DicomTag>& DicomMap::GetMainDicomTags(ResourceType level) |
515 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level) | 573 { |
516 { | 574 return DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(level); |
517 const MainDicomTag *tags = NULL; | 575 } |
518 size_t size; | 576 |
519 LoadMainDicomTags(tags, size, level); | 577 const std::set<DicomTag>& DicomMap::GetAllMainDicomTags() |
520 | 578 { |
521 for (size_t i = 0; i < size; i++) | 579 return DicomMap::MainDicomTagsConfiguration::GetInstance().GetAllMainDicomTags(); |
522 { | 580 } |
523 result.insert(tags[i].tag_); | 581 |
524 } | 582 void DicomMap::AddMainDicomTag(const DicomTag& tag, const std::string& name, ResourceType level) |
525 } | 583 { |
526 | 584 DicomMap::MainDicomTagsConfiguration::GetInstance().AddMainDicomTag(tag, name, level); |
527 | 585 } |
528 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level) | 586 |
529 { | 587 void DicomMap::ResetDefaultMainDicomTags() |
530 result.clear(); | 588 { |
531 GetMainDicomTagsInternal(result, level); | 589 DicomMap::MainDicomTagsConfiguration::GetInstance().ResetDefaultMainDicomTags(); |
532 } | 590 } |
533 | |
534 | |
535 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result) | |
536 { | |
537 result.clear(); | |
538 GetMainDicomTagsInternal(result, ResourceType_Patient); | |
539 GetMainDicomTagsInternal(result, ResourceType_Study); | |
540 GetMainDicomTagsInternal(result, ResourceType_Series); | |
541 GetMainDicomTagsInternal(result, ResourceType_Instance); | |
542 } | |
543 | |
544 | 591 |
545 void DicomMap::GetTags(std::set<DicomTag>& tags) const | 592 void DicomMap::GetTags(std::set<DicomTag>& tags) const |
546 { | 593 { |
547 tags.clear(); | 594 tags.clear(); |
548 | 595 |
1199 | 1246 |
1200 | 1247 |
1201 void DicomMap::MergeMainDicomTags(const DicomMap& other, | 1248 void DicomMap::MergeMainDicomTags(const DicomMap& other, |
1202 ResourceType level) | 1249 ResourceType level) |
1203 { | 1250 { |
1204 const MainDicomTag* tags = NULL; | 1251 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); |
1205 size_t size = 0; | 1252 |
1206 | 1253 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); |
1207 LoadMainDicomTags(tags, size, level); | 1254 itmt != mainDicomTags.end(); itmt++) |
1208 assert(tags != NULL && size > 0); | 1255 { |
1209 | 1256 Content::const_iterator found = other.content_.find(itmt->first); |
1210 for (size_t i = 0; i < size; i++) | |
1211 { | |
1212 Content::const_iterator found = other.content_.find(tags[i].tag_); | |
1213 | 1257 |
1214 if (found != other.content_.end() && | 1258 if (found != other.content_.end() && |
1215 content_.find(tags[i].tag_) == content_.end()) | 1259 content_.find(itmt->first) == content_.end()) |
1216 { | 1260 { |
1217 assert(found->second != NULL); | 1261 assert(found->second != NULL); |
1218 content_[tags[i].tag_] = found->second->Clone(); | 1262 content_[itmt->first] = found->second->Clone(); |
1219 } | 1263 } |
1220 } | 1264 } |
1221 } | 1265 } |
1222 | 1266 |
1223 | 1267 |
1231 } | 1275 } |
1232 | 1276 |
1233 | 1277 |
1234 bool DicomMap::HasOnlyMainDicomTags() const | 1278 bool DicomMap::HasOnlyMainDicomTags() const |
1235 { | 1279 { |
1236 // TODO - Speed up possible by making this std::set a global variable | 1280 const std::set<DicomTag>& allMainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetAllMainDicomTags(); |
1237 | |
1238 std::set<DicomTag> mainDicomTags; | |
1239 GetMainDicomTags(mainDicomTags); | |
1240 | 1281 |
1241 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) | 1282 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) |
1242 { | 1283 { |
1243 if (mainDicomTags.find(it->first) == mainDicomTags.end()) | 1284 if (allMainDicomTags.find(it->first) == allMainDicomTags.end()) |
1244 { | 1285 { |
1245 return false; | 1286 return false; |
1246 } | 1287 } |
1247 } | 1288 } |
1248 | 1289 |
1473 | 1514 |
1474 | 1515 |
1475 void DicomMap::DumpMainDicomTags(Json::Value& target, | 1516 void DicomMap::DumpMainDicomTags(Json::Value& target, |
1476 ResourceType level) const | 1517 ResourceType level) const |
1477 { | 1518 { |
1478 std::map<DicomTag, std::string> mainTags; // TODO - Create a singleton to hold this map | 1519 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); |
1479 LoadMainDicomTags(mainTags, level); | |
1480 | 1520 |
1481 target = Json::objectValue; | 1521 target = Json::objectValue; |
1482 | 1522 |
1483 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) | 1523 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) |
1484 { | 1524 { |
1485 assert(it->second != NULL); | 1525 assert(it->second != NULL); |
1486 | 1526 |
1487 if (!it->second->IsBinary() && | 1527 if (!it->second->IsBinary() && |
1488 !it->second->IsNull()) | 1528 !it->second->IsNull()) |
1489 { | 1529 { |
1490 std::map<DicomTag, std::string>::const_iterator found = mainTags.find(it->first); | 1530 std::map<DicomTag, std::string>::const_iterator found = mainDicomTags.find(it->first); |
1491 | 1531 |
1492 if (found != mainTags.end()) | 1532 if (found != mainDicomTags.end()) |
1493 { | 1533 { |
1494 target[found->second] = it->second->GetContent(); | 1534 target[found->second] = it->second->GetContent(); |
1495 } | 1535 } |
1496 } | 1536 } |
1497 } | 1537 } |
1504 if (source.type() != Json::objectValue) | 1544 if (source.type() != Json::objectValue) |
1505 { | 1545 { |
1506 throw OrthancException(ErrorCode_BadFileFormat); | 1546 throw OrthancException(ErrorCode_BadFileFormat); |
1507 } | 1547 } |
1508 | 1548 |
1509 std::map<std::string, DicomTag2> mainTags; // TODO - Create a singleton to hold this map | 1549 const std::map<std::string, DicomTag2>& mainTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByName(level); |
1510 LoadMainDicomTags(mainTags, level); | |
1511 | 1550 |
1512 Json::Value::Members members = source.getMemberNames(); | 1551 Json::Value::Members members = source.getMemberNames(); |
1513 for (size_t i = 0; i < members.size(); i++) | 1552 for (size_t i = 0; i < members.size(); i++) |
1514 { | 1553 { |
1515 std::map<std::string, DicomTag2>::const_iterator found = mainTags.find(members[i]); | 1554 std::map<std::string, DicomTag2>::const_iterator found = mainTags.find(members[i]); |