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]);