comparison OrthancFramework/Sources/DicomFormat/DicomMap.cpp @ 5040:1c08cd68250a

removed the 'name' of MainDicomTags to simplify code -> DicomMap::ParseMainDicomTags has been deprecated and one should use DicomMap::FromDicomAsJson on 'full' formatted tags
author Alain Mazy <am@osimis.io>
date Mon, 27 Jun 2022 12:39:51 +0200
parents f8bea9c1c0fc
children 6fed78e13233
comparison
equal deleted inserted replaced
5039:28db9663fc2d 5040:1c08cd68250a
39 #include "../DicomParsing/FromDcmtkBridge.h" 39 #include "../DicomParsing/FromDcmtkBridge.h"
40 #endif 40 #endif
41 41
42 namespace Orthanc 42 namespace Orthanc
43 { 43 {
44 namespace
45 {
46 struct MainDicomTag
47 {
48 const DicomTag tag_;
49 const char* name_;
50 };
51 typedef std::vector<MainDicomTag> MainDicomTags;
52
53 }
54
55
56 // WARNING: the DEFAULT list of main dicom tags below are the list as they 44 // WARNING: the DEFAULT list of main dicom tags below are the list as they
57 // were in Orthanc 1.10 before we introduced the dynamic main dicom tags. 45 // were in Orthanc 1.10 before we introduced the dynamic main dicom tags.
58 // This list has not changed since Orthanc 1.4.2 and had a single change since 46 // This list has not changed since Orthanc 1.4.2 and had a single change since
59 // Orthanc 0.9.5. 47 // Orthanc 0.9.5.
60 // These lists have a specific signature. When a resource does not have 48 // These lists have a specific signature. When a resource does not have
61 // the metadata "MainDicomTagsSignature", we'll assume that they were stored 49 // the metadata "MainDicomTagsSignature", we'll assume that they were stored
62 // with an Orthanc prior to 1.11. It is therefore very important that you never 50 // with an Orthanc prior to 1.11. It is therefore very important that you never
63 // change these lists ! 51 // change these lists !
64 52
65 static const MainDicomTag DEFAULT_PATIENT_MAIN_DICOM_TAGS[] = 53 static const DicomTag DEFAULT_PATIENT_MAIN_DICOM_TAGS[] =
66 { 54 {
67 // { DicomTag(0x0010, 0x1010), "PatientAge" }, 55 // { DicomTag(0x0010, 0x1010), "PatientAge" },
68 // { DicomTag(0x0010, 0x1040), "PatientAddress" }, 56 // { DicomTag(0x0010, 0x1040), "PatientAddress" },
69 { DICOM_TAG_PATIENT_NAME, "PatientName" }, 57 DICOM_TAG_PATIENT_NAME,
70 { DICOM_TAG_PATIENT_BIRTH_DATE, "PatientBirthDate" }, 58 DICOM_TAG_PATIENT_BIRTH_DATE,
71 { DICOM_TAG_PATIENT_SEX, "PatientSex" }, 59 DICOM_TAG_PATIENT_SEX,
72 { DICOM_TAG_OTHER_PATIENT_IDS, "OtherPatientIDs" }, 60 DICOM_TAG_OTHER_PATIENT_IDS,
73 { DICOM_TAG_PATIENT_ID, "PatientID" } 61 DICOM_TAG_PATIENT_ID,
62
74 }; 63 };
75 64
76 static const MainDicomTag DEFAULT_STUDY_MAIN_DICOM_TAGS[] = 65 static const DicomTag DEFAULT_STUDY_MAIN_DICOM_TAGS[] =
77 { 66 {
78 // { DicomTag(0x0010, 0x1020), "PatientSize" }, 67 // { DicomTag(0x0010, 0x1020), "PatientSize" },
79 // { DicomTag(0x0010, 0x1030), "PatientWeight" }, 68 // { DicomTag(0x0010, 0x1030), "PatientWeight" },
80 { DICOM_TAG_STUDY_DATE, "StudyDate" }, 69 DICOM_TAG_STUDY_DATE,
81 { DICOM_TAG_STUDY_TIME, "StudyTime" }, 70 DICOM_TAG_STUDY_TIME,
82 { DICOM_TAG_STUDY_ID, "StudyID" }, 71 DICOM_TAG_STUDY_ID,
83 { DICOM_TAG_STUDY_DESCRIPTION, "StudyDescription" }, 72 DICOM_TAG_STUDY_DESCRIPTION,
84 { DICOM_TAG_ACCESSION_NUMBER, "AccessionNumber" }, 73 DICOM_TAG_ACCESSION_NUMBER,
85 { DICOM_TAG_STUDY_INSTANCE_UID, "StudyInstanceUID" }, 74 DICOM_TAG_STUDY_INSTANCE_UID,
86
87 // New in db v6 75 // New in db v6
88 { DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, "RequestedProcedureDescription" }, 76 DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION,
89 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" }, 77 DICOM_TAG_INSTITUTION_NAME,
90 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" }, 78 DICOM_TAG_REQUESTING_PHYSICIAN,
91 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" } 79 DICOM_TAG_REFERRING_PHYSICIAN_NAME
92 }; 80 };
93 81
94 static const MainDicomTag DEFAULT_SERIES_MAIN_DICOM_TAGS[] = 82 static const DicomTag DEFAULT_SERIES_MAIN_DICOM_TAGS[] =
95 { 83 {
96 // { DicomTag(0x0010, 0x1080), "MilitaryRank" }, 84 // { DicomTag(0x0010, 0x1080), "MilitaryRank" },
97 { DICOM_TAG_SERIES_DATE, "SeriesDate" }, 85 DICOM_TAG_SERIES_DATE,
98 { DICOM_TAG_SERIES_TIME, "SeriesTime" }, 86 DICOM_TAG_SERIES_TIME,
99 { DICOM_TAG_MODALITY, "Modality" }, 87 DICOM_TAG_MODALITY,
100 { DICOM_TAG_MANUFACTURER, "Manufacturer" }, 88 DICOM_TAG_MANUFACTURER,
101 { DICOM_TAG_STATION_NAME, "StationName" }, 89 DICOM_TAG_STATION_NAME,
102 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" }, 90 DICOM_TAG_SERIES_DESCRIPTION,
103 { DICOM_TAG_BODY_PART_EXAMINED, "BodyPartExamined" }, 91 DICOM_TAG_BODY_PART_EXAMINED,
104 { DICOM_TAG_SEQUENCE_NAME, "SequenceName" }, 92 DICOM_TAG_SEQUENCE_NAME,
105 { DICOM_TAG_PROTOCOL_NAME, "ProtocolName" }, 93 DICOM_TAG_PROTOCOL_NAME,
106 { DICOM_TAG_SERIES_NUMBER, "SeriesNumber" }, 94 DICOM_TAG_SERIES_NUMBER,
107 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImages" }, 95 DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES,
108 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" }, 96 DICOM_TAG_IMAGES_IN_ACQUISITION,
109 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" }, 97 DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS,
110 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" }, 98 DICOM_TAG_NUMBER_OF_SLICES,
111 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" }, 99 DICOM_TAG_NUMBER_OF_TIME_SLICES,
112 { DICOM_TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID" }, 100 DICOM_TAG_SERIES_INSTANCE_UID,
101
102 // New in db v6
103 DICOM_TAG_IMAGE_ORIENTATION_PATIENT,
104 DICOM_TAG_SERIES_TYPE,
105 DICOM_TAG_OPERATOR_NAME,
106 DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION,
107 DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION,
108 DICOM_TAG_CONTRAST_BOLUS_AGENT
109 };
110
111 static const DicomTag DEFAULT_INSTANCE_MAIN_DICOM_TAGS[] =
112 {
113 DICOM_TAG_INSTANCE_CREATION_DATE,
114 DICOM_TAG_INSTANCE_CREATION_TIME,
115 DICOM_TAG_ACQUISITION_NUMBER,
116 DICOM_TAG_IMAGE_INDEX,
117 DICOM_TAG_INSTANCE_NUMBER,
118 DICOM_TAG_NUMBER_OF_FRAMES,
119 DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER,
120 DICOM_TAG_SOP_INSTANCE_UID,
113 121
114 // New in db v6 122 // New in db v6
115 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" }, 123 DICOM_TAG_IMAGE_POSITION_PATIENT,
116 { DICOM_TAG_SERIES_TYPE, "SeriesType" }, 124 DICOM_TAG_IMAGE_COMMENTS,
117 { DICOM_TAG_OPERATOR_NAME, "OperatorsName" },
118 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" },
119 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" },
120 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgent" }
121 };
122
123 static const MainDicomTag DEFAULT_INSTANCE_MAIN_DICOM_TAGS[] =
124 {
125 { DICOM_TAG_INSTANCE_CREATION_DATE, "InstanceCreationDate" },
126 { DICOM_TAG_INSTANCE_CREATION_TIME, "InstanceCreationTime" },
127 { DICOM_TAG_ACQUISITION_NUMBER, "AcquisitionNumber" },
128 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" },
129 { DICOM_TAG_INSTANCE_NUMBER, "InstanceNumber" },
130 { DICOM_TAG_NUMBER_OF_FRAMES, "NumberOfFrames" },
131 { DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, "TemporalPositionIdentifier" },
132 { DICOM_TAG_SOP_INSTANCE_UID, "SOPInstanceUID" },
133
134 // New in db v6
135 { DICOM_TAG_IMAGE_POSITION_PATIENT, "ImagePositionPatient" },
136 { DICOM_TAG_IMAGE_COMMENTS, "ImageComments" },
137 125
138 /** 126 /**
139 * Main DICOM tags that are not part of any release of the 127 * Main DICOM tags that are not part of any release of the
140 * database schema yet, and that will be part of future db v7. In 128 * database schema yet, and that will be part of future db v7. In
141 * the meantime, the user must call "/tools/reconstruct" once to 129 * the meantime, the user must call "/tools/reconstruct" once to
142 * access these tags if the corresponding DICOM files where 130 * access these tags if the corresponding DICOM files where
143 * indexed in the database by an older version of Orthanc. 131 * indexed in the database by an older version of Orthanc.
144 **/ 132 **/
145 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2 133 DICOM_TAG_IMAGE_ORIENTATION_PATIENT // New in Orthanc 1.4.2
146 }; 134 };
147 135
148 136
149 namespace
150 {
151 class DicomTag2 : public DicomTag
152 {
153 public:
154 DicomTag2() :
155 DicomTag(0, 0) // To make std::map<> happy
156 {
157 }
158
159 explicit DicomTag2(const DicomTag& tag) :
160 DicomTag(tag)
161 {
162 }
163 };
164 }
165 137
166 138
167 class DicomMap::MainDicomTagsConfiguration 139 class DicomMap::MainDicomTagsConfiguration
168 { 140 {
169 private: 141 private:
170 friend DicomMap; 142 friend DicomMap;
171 143
172 // we keep many "copies" of the same data to guarantee quick access to organized data
173 // and avoid rebuilding it all the time.
174 std::map<DicomTag, std::string> patientsMainDicomTagsByTag_;
175 std::map<std::string, DicomTag2> patientsMainDicomTagsByName_;
176 std::set<DicomTag> patientsMainDicomTagsByLevel_; 144 std::set<DicomTag> patientsMainDicomTagsByLevel_;
177
178 std::map<DicomTag, std::string> studiesMainDicomTagsByTag_;
179 std::map<std::string, DicomTag2> studiesMainDicomTagsByName_;
180 std::set<DicomTag> studiesMainDicomTagsByLevel_; 145 std::set<DicomTag> studiesMainDicomTagsByLevel_;
181
182 std::map<DicomTag, std::string> seriesMainDicomTagsByTag_;
183 std::map<std::string, DicomTag2> seriesMainDicomTagsByName_;
184 std::set<DicomTag> seriesMainDicomTagsByLevel_; 146 std::set<DicomTag> seriesMainDicomTagsByLevel_;
185
186 std::map<DicomTag, std::string> instancesMainDicomTagsByTag_;
187 std::map<std::string, DicomTag2> instancesMainDicomTagsByName_;
188 std::set<DicomTag> instancesMainDicomTagsByLevel_; 147 std::set<DicomTag> instancesMainDicomTagsByLevel_;
189 148
190 std::set<DicomTag> allMainDicomTags_; 149 std::set<DicomTag> allMainDicomTags_;
191 150
192 std::map<ResourceType, std::string> signatures_; 151 std::map<ResourceType, std::string> signatures_;
197 ResetDefaultMainDicomTags(); 156 ResetDefaultMainDicomTags();
198 } 157 }
199 158
200 void ResetDefaultMainDicomTags() 159 void ResetDefaultMainDicomTags()
201 { 160 {
202 patientsMainDicomTagsByTag_.clear();
203 patientsMainDicomTagsByName_.clear();
204 patientsMainDicomTagsByLevel_.clear(); 161 patientsMainDicomTagsByLevel_.clear();
205
206 studiesMainDicomTagsByTag_.clear();
207 studiesMainDicomTagsByName_.clear();
208 studiesMainDicomTagsByLevel_.clear(); 162 studiesMainDicomTagsByLevel_.clear();
209
210 seriesMainDicomTagsByTag_.clear();
211 seriesMainDicomTagsByName_.clear();
212 seriesMainDicomTagsByLevel_.clear(); 163 seriesMainDicomTagsByLevel_.clear();
213
214 instancesMainDicomTagsByTag_.clear();
215 instancesMainDicomTagsByName_.clear();
216 instancesMainDicomTagsByLevel_.clear(); 164 instancesMainDicomTagsByLevel_.clear();
217 165
218 allMainDicomTags_.clear(); 166 allMainDicomTags_.clear();
219 167
220 // by default, initialize with the previous static list (up to 1.10.0) 168 // by default, initialize with the previous static list (up to 1.10.0)
243 return signatureText; 191 return signatureText;
244 } 192 }
245 193
246 void LoadDefaultMainDicomTags(ResourceType level) 194 void LoadDefaultMainDicomTags(ResourceType level)
247 { 195 {
248 const MainDicomTag* tags = NULL; 196 const DicomTag* tags = NULL;
249 size_t size; 197 size_t size;
250 198
251 switch (level) 199 switch (level)
252 { 200 {
253 case ResourceType_Patient: 201 case ResourceType_Patient:
254 tags = DEFAULT_PATIENT_MAIN_DICOM_TAGS; 202 tags = DEFAULT_PATIENT_MAIN_DICOM_TAGS;
255 size = sizeof(DEFAULT_PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); 203 size = sizeof(DEFAULT_PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag);
256 break; 204 break;
257 205
258 case ResourceType_Study: 206 case ResourceType_Study:
259 tags = DEFAULT_STUDY_MAIN_DICOM_TAGS; 207 tags = DEFAULT_STUDY_MAIN_DICOM_TAGS;
260 size = sizeof(DEFAULT_STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); 208 size = sizeof(DEFAULT_STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag);
261 break; 209 break;
262 210
263 case ResourceType_Series: 211 case ResourceType_Series:
264 tags = DEFAULT_SERIES_MAIN_DICOM_TAGS; 212 tags = DEFAULT_SERIES_MAIN_DICOM_TAGS;
265 size = sizeof(DEFAULT_SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); 213 size = sizeof(DEFAULT_SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag);
266 break; 214 break;
267 215
268 case ResourceType_Instance: 216 case ResourceType_Instance:
269 tags = DEFAULT_INSTANCE_MAIN_DICOM_TAGS; 217 tags = DEFAULT_INSTANCE_MAIN_DICOM_TAGS;
270 size = sizeof(DEFAULT_INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag); 218 size = sizeof(DEFAULT_INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag);
271 break; 219 break;
272 220
273 default: 221 default:
274 throw OrthancException(ErrorCode_ParameterOutOfRange); 222 throw OrthancException(ErrorCode_ParameterOutOfRange);
275 } 223 }
277 assert(tags != NULL && 225 assert(tags != NULL &&
278 size != 0); 226 size != 0);
279 227
280 for (size_t i = 0; i < size; i++) 228 for (size_t i = 0; i < size; i++)
281 { 229 {
282 AddMainDicomTag(tags[i].tag_, tags[i].name_, level); 230 AddMainDicomTag(tags[i], level);
283 } 231 }
284 232
285 } 233 }
286 234
287 std::map<DicomTag, std::string>& GetMainDicomTags(ResourceType level)
288 {
289 switch (level)
290 {
291 case ResourceType_Patient:
292 return patientsMainDicomTagsByTag_;
293
294 case ResourceType_Study:
295 return studiesMainDicomTagsByTag_;
296
297 case ResourceType_Series:
298 return seriesMainDicomTagsByTag_;
299
300 case ResourceType_Instance:
301 return instancesMainDicomTagsByTag_;
302
303 default:
304 throw OrthancException(ErrorCode_InternalError);
305 }
306 }
307
308 std::map<std::string, DicomTag2>& GetMainDicomTagsByName(ResourceType level)
309 {
310 switch (level)
311 {
312 case ResourceType_Patient:
313 return patientsMainDicomTagsByName_;
314
315 case ResourceType_Study:
316 return studiesMainDicomTagsByName_;
317
318 case ResourceType_Series:
319 return seriesMainDicomTagsByName_;
320
321 case ResourceType_Instance:
322 return instancesMainDicomTagsByName_;
323
324 default:
325 throw OrthancException(ErrorCode_InternalError);
326 }
327 }
328 235
329 std::set<DicomTag>& GetMainDicomTagsByLevel(ResourceType level) 236 std::set<DicomTag>& GetMainDicomTagsByLevel(ResourceType level)
330 { 237 {
331 switch (level) 238 switch (level)
332 { 239 {
353 { 260 {
354 static MainDicomTagsConfiguration parameters; 261 static MainDicomTagsConfiguration parameters;
355 return parameters; 262 return parameters;
356 } 263 }
357 264
358 void AddMainDicomTag(const DicomTag& tag, const std::string& name, ResourceType level) 265 void AddMainDicomTag(const DicomTag& tag, ResourceType level)
359 { 266 {
360 std::map<DicomTag, std::string>& byTag = GetMainDicomTags(level); 267 const std::set<DicomTag>& existingLevelTags = GetMainDicomTagsByLevel(level);
361 std::map<std::string, DicomTag2>& byName = GetMainDicomTagsByName(level);
362 268
363 if (byTag.find(tag) != byTag.end()) 269 if (existingLevelTags.find(tag) != existingLevelTags.end())
364 { 270 {
365 throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined"); 271 throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined");
366 } 272 }
367 273
368 if (byName.find(name) != byName.end()) 274
369 {
370 throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, name + " is already defined");
371 }
372
373 byTag[tag] = name;
374 byName[name] = DicomTag2(tag);
375 GetMainDicomTagsByLevel(level).insert(tag); 275 GetMainDicomTagsByLevel(level).insert(tag);
376 allMainDicomTags_.insert(tag); 276 allMainDicomTags_.insert(tag);
377 signatures_[level] = ComputeSignature(GetMainDicomTagsByLevel(level)); 277 signatures_[level] = ComputeSignature(GetMainDicomTagsByLevel(level));
378 } 278 }
379 279
473 { 373 {
474 return GetValue(DicomTag(group, element)); 374 return GetValue(DicomTag(group, element));
475 } 375 }
476 376
477 377
478 // MORE_TAGS: TODO: we can probably remove the std::string from MainDicomTags (not used here !!!)
479 static void ExtractTagsInternal(DicomMap& result, 378 static void ExtractTagsInternal(DicomMap& result,
480 const DicomMap::Content& source, 379 const DicomMap::Content& source,
481 const std::map<DicomTag, std::string>& mainDicomTags) 380 const std::set<DicomTag>& mainDicomTags)
482 { 381 {
483 result.Clear(); 382 result.Clear();
484 383
485 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); 384 for (std::set<DicomTag>::const_iterator itmt = mainDicomTags.begin();
486 itmt != mainDicomTags.end(); ++itmt) 385 itmt != mainDicomTags.end(); ++itmt)
487 { 386 {
488 DicomMap::Content::const_iterator it = source.find(itmt->first); 387 DicomMap::Content::const_iterator it = source.find(*itmt);
489 if (it != source.end()) 388 if (it != source.end())
490 { 389 {
491 result.SetValue(it->first, *it->second /* value will be cloned */); 390 result.SetValue(it->first, *it->second /* value will be cloned */);
492 } 391 }
493 } 392 }
508 } 407 }
509 } 408 }
510 409
511 void DicomMap::ExtractResourceInformation(DicomMap& result, ResourceType level) const 410 void DicomMap::ExtractResourceInformation(DicomMap& result, ResourceType level) const
512 { 411 {
513 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); 412 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(level);
514 ExtractTagsInternal(result, content_, mainDicomTags); 413 ExtractTagsInternal(result, content_, mainDicomTags);
515 } 414 }
516 415
517 void DicomMap::ExtractPatientInformation(DicomMap& result) const 416 void DicomMap::ExtractPatientInformation(DicomMap& result) const
518 { 417 {
622 Remove(*it); 521 Remove(*it);
623 } 522 }
624 } 523 }
625 524
626 static void SetupFindTemplate(DicomMap& result, 525 static void SetupFindTemplate(DicomMap& result,
627 const std::map<DicomTag, std::string>& mainDicomTags) 526 const std::set<DicomTag>& mainDicomTags)
628 { 527 {
629 result.Clear(); 528 result.Clear();
630 529
631 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); 530 for (std::set<DicomTag>::const_iterator itmt = mainDicomTags.begin();
632 itmt != mainDicomTags.end(); ++itmt) 531 itmt != mainDicomTags.end(); ++itmt)
633 { 532 {
634 result.SetValue(itmt->first, "", false); 533 result.SetValue(*itmt, "", false);
635 } 534 }
636 } 535 }
637 536
638 void DicomMap::SetupFindPatientTemplate(DicomMap& result) 537 void DicomMap::SetupFindPatientTemplate(DicomMap& result)
639 { 538 {
640 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Patient); 539 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(ResourceType_Patient);
641 SetupFindTemplate(result, mainDicomTags); 540 SetupFindTemplate(result, mainDicomTags);
642 } 541 }
643 542
644 void DicomMap::SetupFindStudyTemplate(DicomMap& result) 543 void DicomMap::SetupFindStudyTemplate(DicomMap& result)
645 { 544 {
646 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Study); 545 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(ResourceType_Study);
647 SetupFindTemplate(result, mainDicomTags); 546 SetupFindTemplate(result, mainDicomTags);
648 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 547 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
649 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 548 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
650 549
651 // These main DICOM tags are only indirectly related to the 550 // These main DICOM tags are only indirectly related to the
655 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION); 554 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION);
656 } 555 }
657 556
658 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) 557 void DicomMap::SetupFindSeriesTemplate(DicomMap& result)
659 { 558 {
660 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Series); 559 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(ResourceType_Series);
661 SetupFindTemplate(result, mainDicomTags); 560 SetupFindTemplate(result, mainDicomTags);
662 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 561 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
663 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 562 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
664 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 563 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
665 564
678 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT); 577 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT);
679 } 578 }
680 579
681 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) 580 void DicomMap::SetupFindInstanceTemplate(DicomMap& result)
682 { 581 {
683 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(ResourceType_Instance); 582 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(ResourceType_Instance);
684 SetupFindTemplate(result, mainDicomTags); 583 SetupFindTemplate(result, mainDicomTags);
685 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 584 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
686 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 585 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
687 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 586 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
688 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false); 587 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false);
699 } 598 }
700 599
701 600
702 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) 601 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level)
703 { 602 {
704 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); 603 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(level);
705 return mainDicomTags.find(tag) != mainDicomTags.end(); 604 return mainDicomTags.find(tag) != mainDicomTags.end();
706 } 605 }
707 606
708 bool DicomMap::IsMainDicomTag(const DicomTag& tag) 607 bool DicomMap::IsMainDicomTag(const DicomTag& tag)
709 { 608 {
810 const std::set<DicomTag>& DicomMap::GetAllMainDicomTags() 709 const std::set<DicomTag>& DicomMap::GetAllMainDicomTags()
811 { 710 {
812 return DicomMap::MainDicomTagsConfiguration::GetInstance().GetAllMainDicomTags(); 711 return DicomMap::MainDicomTagsConfiguration::GetInstance().GetAllMainDicomTags();
813 } 712 }
814 713
815 void DicomMap::AddMainDicomTag(const DicomTag& tag, const std::string& name, ResourceType level) 714 void DicomMap::AddMainDicomTag(const DicomTag& tag, ResourceType level)
816 { 715 {
817 DicomMap::MainDicomTagsConfiguration::GetInstance().AddMainDicomTag(tag, name, level); 716 DicomMap::MainDicomTagsConfiguration::GetInstance().AddMainDicomTag(tag, level);
818 } 717 }
819 718
820 void DicomMap::ResetDefaultMainDicomTags() 719 void DicomMap::ResetDefaultMainDicomTags()
821 { 720 {
822 DicomMap::MainDicomTagsConfiguration::GetInstance().ResetDefaultMainDicomTags(); 721 DicomMap::MainDicomTagsConfiguration::GetInstance().ResetDefaultMainDicomTags();
1427 return value->ParseDouble(result); 1326 return value->ParseDouble(result);
1428 } 1327 }
1429 } 1328 }
1430 1329
1431 1330
1432 void DicomMap::FromDicomAsJson(const Json::Value& dicomAsJson) 1331 void DicomMap::FromDicomAsJson(const Json::Value& dicomAsJson, bool append)
1433 { 1332 {
1434 if (dicomAsJson.type() != Json::objectValue) 1333 if (dicomAsJson.type() != Json::objectValue)
1435 { 1334 {
1436 throw OrthancException(ErrorCode_BadFileFormat); 1335 throw OrthancException(ErrorCode_BadFileFormat);
1437 } 1336 }
1438 1337
1439 Clear(); 1338 if (!append)
1339 {
1340 Clear();
1341 }
1440 1342
1441 Json::Value::Members tags = dicomAsJson.getMemberNames(); 1343 Json::Value::Members tags = dicomAsJson.getMemberNames();
1442 for (Json::Value::Members::const_iterator 1344 for (Json::Value::Members::const_iterator
1443 it = tags.begin(); it != tags.end(); ++it) 1345 it = tags.begin(); it != tags.end(); ++it)
1444 { 1346 {
1489 1391
1490 1392
1491 void DicomMap::MergeMainDicomTags(const DicomMap& other, 1393 void DicomMap::MergeMainDicomTags(const DicomMap& other,
1492 ResourceType level) 1394 ResourceType level)
1493 { 1395 {
1494 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); 1396 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(level);
1495 1397
1496 for (std::map<DicomTag, std::string>::const_iterator itmt = mainDicomTags.begin(); 1398 for (std::set<DicomTag>::const_iterator itmt = mainDicomTags.begin();
1497 itmt != mainDicomTags.end(); ++itmt) 1399 itmt != mainDicomTags.end(); ++itmt)
1498 { 1400 {
1499 Content::const_iterator found = other.content_.find(itmt->first); 1401 Content::const_iterator found = other.content_.find(*itmt);
1500 1402
1501 if (found != other.content_.end() && 1403 if (found != other.content_.end() &&
1502 content_.find(itmt->first) == content_.end()) 1404 content_.find(*itmt) == content_.end())
1503 { 1405 {
1504 assert(found->second != NULL); 1406 assert(found->second != NULL);
1505 content_[itmt->first] = found->second->Clone(); 1407 content_[*itmt] = found->second->Clone();
1506 } 1408 }
1507 } 1409 }
1508 } 1410 }
1509 1411
1510 1412
1772 1674
1773 1675
1774 void DicomMap::DumpMainDicomTags(Json::Value& target, 1676 void DicomMap::DumpMainDicomTags(Json::Value& target,
1775 ResourceType level) const 1677 ResourceType level) const
1776 { 1678 {
1777 const std::map<DicomTag, std::string>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTags(level); 1679 const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(level);
1778 1680
1779 target = Json::objectValue; 1681 target = Json::objectValue;
1780 1682
1781 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) 1683 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1782 { 1684 {
1783 assert(it->second != NULL); 1685 assert(it->second != NULL);
1784 1686
1785 if (!it->second->IsBinary() && 1687 if (!it->second->IsBinary() &&
1786 !it->second->IsNull()) 1688 !it->second->IsNull())
1787 { 1689 {
1788 std::map<DicomTag, std::string>::const_iterator found = mainDicomTags.find(it->first); 1690 std::set<DicomTag>::const_iterator found = mainDicomTags.find(it->first);
1789 1691
1790 if (found != mainDicomTags.end()) 1692 if (found != mainDicomTags.end())
1791 { 1693 {
1792 target[found->second] = it->second->GetContent(); 1694 #if ORTHANC_ENABLE_DCMTK == 1
1695 target[FromDcmtkBridge::GetTagName(*found, "")] = it->second->GetContent();
1696 #else
1697 target[found->Format()] = it->second->GetContent();
1698 #endif
1793 } 1699 }
1794 } 1700 }
1795 } 1701 }
1796 } 1702 }
1797 1703
1798 1704
1799 void DicomMap::ParseMainDicomTags(const Json::Value& source, 1705
1800 ResourceType level)
1801 {
1802 if (source.type() != Json::objectValue)
1803 {
1804 throw OrthancException(ErrorCode_BadFileFormat);
1805 }
1806
1807 const std::map<std::string, DicomTag2>& mainTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByName(level);
1808
1809 Json::Value::Members members = source.getMemberNames();
1810 for (size_t i = 0; i < members.size(); i++)
1811 {
1812 std::map<std::string, DicomTag2>::const_iterator found = mainTags.find(members[i]);
1813
1814 if (found != mainTags.end())
1815 {
1816 const Json::Value& value = source[members[i]];
1817 if (value.type() != Json::stringValue)
1818 {
1819 throw OrthancException(ErrorCode_BadFileFormat);
1820 }
1821 else
1822 {
1823 SetValue(found->second, value.asString(), false);
1824 }
1825 }
1826 }
1827 }
1828
1829 1706
1830 void DicomMap::Print(FILE* fp) const 1707 void DicomMap::Print(FILE* fp) const
1831 { 1708 {
1832 DicomArray a(*this); 1709 DicomArray a(*this);
1833 a.Print(fp); 1710 a.Print(fp);