comparison Core/DicomFormat/DicomMap.cpp @ 3652:335611d2b6cd storage-commitment

integration mainline->storage-commitment
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 05 Feb 2020 13:24:48 +0100
parents 05df4860aea6 46cb00e4adbb
children cccd97333e3d
comparison
equal deleted inserted replaced
3649:05df4860aea6 3652:335611d2b6cd
53 const DicomTag tag_; 53 const DicomTag tag_;
54 const char* name_; 54 const char* name_;
55 }; 55 };
56 } 56 }
57 57
58 static const MainDicomTag PATIENT_MAIN_DICOM_TAGS_2[] = 58 static const MainDicomTag PATIENT_MAIN_DICOM_TAGS[] =
59 { 59 {
60 // { DicomTag(0x0010, 0x1010), "PatientAge" }, 60 // { DicomTag(0x0010, 0x1010), "PatientAge" },
61 // { DicomTag(0x0010, 0x1040), "PatientAddress" }, 61 // { DicomTag(0x0010, 0x1040), "PatientAddress" },
62 { DicomTag(0x0010, 0x0010), "PatientName" }, 62 { DicomTag(0x0010, 0x0010), "PatientName" },
63 { DicomTag(0x0010, 0x0030), "PatientBirthDate" }, 63 { DicomTag(0x0010, 0x0030), "PatientBirthDate" },
64 { DicomTag(0x0010, 0x0040), "PatientSex" }, 64 { DicomTag(0x0010, 0x0040), "PatientSex" },
65 { DicomTag(0x0010, 0x1000), "OtherPatientIDs" }, 65 { DicomTag(0x0010, 0x1000), "OtherPatientIDs" },
66 { DICOM_TAG_PATIENT_ID, "PatientID" } 66 { DICOM_TAG_PATIENT_ID, "PatientID" }
67 }; 67 };
68 68
69 static const MainDicomTag STUDY_MAIN_DICOM_TAGS_2[] = 69 static const MainDicomTag STUDY_MAIN_DICOM_TAGS[] =
70 { 70 {
71 // { DicomTag(0x0010, 0x1020), "PatientSize" }, 71 // { DicomTag(0x0010, 0x1020), "PatientSize" },
72 // { DicomTag(0x0010, 0x1030), "PatientWeight" }, 72 // { DicomTag(0x0010, 0x1030), "PatientWeight" },
73 { DICOM_TAG_STUDY_DATE, "StudyDate" }, 73 { DICOM_TAG_STUDY_DATE, "StudyDate" },
74 { DicomTag(0x0008, 0x0030), "StudyTime" }, 74 { DicomTag(0x0008, 0x0030), "StudyTime" },
82 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" }, 82 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" },
83 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" }, 83 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" },
84 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" } 84 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" }
85 }; 85 };
86 86
87 static const MainDicomTag SERIES_MAIN_DICOM_TAGS_2[] = 87 static const MainDicomTag SERIES_MAIN_DICOM_TAGS[] =
88 { 88 {
89 // { DicomTag(0x0010, 0x1080), "MilitaryRank" }, 89 // { DicomTag(0x0010, 0x1080), "MilitaryRank" },
90 { DicomTag(0x0008, 0x0021), "SeriesDate" }, 90 { DicomTag(0x0008, 0x0021), "SeriesDate" },
91 { DicomTag(0x0008, 0x0031), "SeriesTime" }, 91 { DicomTag(0x0008, 0x0031), "SeriesTime" },
92 { DICOM_TAG_MODALITY, "Modality" }, 92 { DICOM_TAG_MODALITY, "Modality" },
95 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" }, 95 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" },
96 { DicomTag(0x0018, 0x0015), "BodyPartExamined" }, 96 { DicomTag(0x0018, 0x0015), "BodyPartExamined" },
97 { DicomTag(0x0018, 0x0024), "SequenceName" }, 97 { DicomTag(0x0018, 0x0024), "SequenceName" },
98 { DicomTag(0x0018, 0x1030), "ProtocolName" }, 98 { DicomTag(0x0018, 0x1030), "ProtocolName" },
99 { DicomTag(0x0020, 0x0011), "SeriesNumber" }, 99 { DicomTag(0x0020, 0x0011), "SeriesNumber" },
100 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImage" }, 100 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImages" },
101 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" }, 101 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" },
102 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" }, 102 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" },
103 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" }, 103 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" },
104 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" }, 104 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" },
105 { DICOM_TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID" }, 105 { DICOM_TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID" },
106 106
107 // New in db v6 107 // New in db v6
108 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatientt" }, // TODO - Should have an unit test that fails 108 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" },
109 { DICOM_TAG_SERIES_TYPE, "SeriesType" }, 109 { DICOM_TAG_SERIES_TYPE, "SeriesType" },
110 { DICOM_TAG_OPERATOR_NAME, "OperatorName" }, 110 { DICOM_TAG_OPERATOR_NAME, "OperatorsName" },
111 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" }, 111 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" },
112 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" }, 112 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" },
113 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgen" } 113 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgent" }
114 }; 114 };
115 115
116 static const MainDicomTag INSTANCE_MAIN_DICOM_TAGS_2[] = 116 static const MainDicomTag INSTANCE_MAIN_DICOM_TAGS[] =
117 { 117 {
118 { DicomTag(0x0008, 0x0012), "InstanceCreationDate" }, 118 { DicomTag(0x0008, 0x0012), "InstanceCreationDate" },
119 { DicomTag(0x0008, 0x0013), "InstanceCreationTime" }, 119 { DicomTag(0x0008, 0x0013), "InstanceCreationTime" },
120 { DicomTag(0x0020, 0x0012), "AcquisitionNumber" }, 120 { DicomTag(0x0020, 0x0012), "AcquisitionNumber" },
121 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" }, 121 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" },
135 * access these tags if the corresponding DICOM files where 135 * access these tags if the corresponding DICOM files where
136 * indexed in the database by an older version of Orthanc. 136 * indexed in the database by an older version of Orthanc.
137 **/ 137 **/
138 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2 138 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2
139 }; 139 };
140 140
141 141
142 142 static void LoadMainDicomTags(const MainDicomTag*& tags,
143 static const DicomTag PATIENT_MAIN_DICOM_TAGS[] = 143 size_t& size,
144 { 144 ResourceType level)
145 //DicomTag(0x0010, 0x1010), // PatientAge
146 //DicomTag(0x0010, 0x1040) // PatientAddress
147 DicomTag(0x0010, 0x0010), // PatientName
148 DicomTag(0x0010, 0x0030), // PatientBirthDate
149 DicomTag(0x0010, 0x0040), // PatientSex
150 DicomTag(0x0010, 0x1000), // OtherPatientIDs
151 DICOM_TAG_PATIENT_ID
152 };
153
154 static const DicomTag STUDY_MAIN_DICOM_TAGS[] =
155 {
156 //DicomTag(0x0010, 0x1020), // PatientSize
157 //DicomTag(0x0010, 0x1030) // PatientWeight
158 DICOM_TAG_STUDY_DATE,
159 DicomTag(0x0008, 0x0030), // StudyTime
160 DicomTag(0x0020, 0x0010), // StudyID
161 DICOM_TAG_STUDY_DESCRIPTION,
162 DICOM_TAG_ACCESSION_NUMBER,
163 DICOM_TAG_STUDY_INSTANCE_UID,
164 DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, // New in db v6
165 DICOM_TAG_INSTITUTION_NAME, // New in db v6
166 DICOM_TAG_REQUESTING_PHYSICIAN, // New in db v6
167 DICOM_TAG_REFERRING_PHYSICIAN_NAME // New in db v6
168 };
169
170 static const DicomTag SERIES_MAIN_DICOM_TAGS[] =
171 {
172 //DicomTag(0x0010, 0x1080), // MilitaryRank
173 DicomTag(0x0008, 0x0021), // SeriesDate
174 DicomTag(0x0008, 0x0031), // SeriesTime
175 DICOM_TAG_MODALITY,
176 DicomTag(0x0008, 0x0070), // Manufacturer
177 DicomTag(0x0008, 0x1010), // StationName
178 DICOM_TAG_SERIES_DESCRIPTION,
179 DicomTag(0x0018, 0x0015), // BodyPartExamined
180 DicomTag(0x0018, 0x0024), // SequenceName
181 DicomTag(0x0018, 0x1030), // ProtocolName
182 DicomTag(0x0020, 0x0011), // SeriesNumber
183 DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES,
184 DICOM_TAG_IMAGES_IN_ACQUISITION,
185 DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS,
186 DICOM_TAG_NUMBER_OF_SLICES,
187 DICOM_TAG_NUMBER_OF_TIME_SLICES,
188 DICOM_TAG_SERIES_INSTANCE_UID,
189 DICOM_TAG_IMAGE_ORIENTATION_PATIENT, // New in db v6
190 DICOM_TAG_SERIES_TYPE, // New in db v6
191 DICOM_TAG_OPERATOR_NAME, // New in db v6
192 DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, // New in db v6
193 DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, // New in db v6
194 DICOM_TAG_CONTRAST_BOLUS_AGENT // New in db v6
195 };
196
197 static const DicomTag INSTANCE_MAIN_DICOM_TAGS[] =
198 {
199 DicomTag(0x0008, 0x0012), // InstanceCreationDate
200 DicomTag(0x0008, 0x0013), // InstanceCreationTime
201 DicomTag(0x0020, 0x0012), // AcquisitionNumber
202 DICOM_TAG_IMAGE_INDEX,
203 DICOM_TAG_INSTANCE_NUMBER,
204 DICOM_TAG_NUMBER_OF_FRAMES,
205 DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER,
206 DICOM_TAG_SOP_INSTANCE_UID,
207 DICOM_TAG_IMAGE_POSITION_PATIENT, // New in db v6
208 DICOM_TAG_IMAGE_COMMENTS, // New in db v6
209
210 /**
211 * Main DICOM tags that are not part of any release of the
212 * database schema yet, and that will be part of future db v7. In
213 * the meantime, the user must call "/tools/reconstruct" once to
214 * access these tags if the corresponding DICOM files where
215 * indexed in the database by an older version of Orthanc.
216 **/
217 DICOM_TAG_IMAGE_ORIENTATION_PATIENT // New in Orthanc 1.4.2
218 };
219
220
221 void DicomMap::LoadMainDicomTags(const DicomTag*& tags,
222 size_t& size,
223 ResourceType level)
224 { 145 {
225 switch (level) 146 switch (level)
226 { 147 {
227 case ResourceType_Patient: 148 case ResourceType_Patient:
228 tags = PATIENT_MAIN_DICOM_TAGS; 149 tags = PATIENT_MAIN_DICOM_TAGS;
229 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag); 150 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
230 break; 151 break;
231 152
232 case ResourceType_Study: 153 case ResourceType_Study:
233 tags = STUDY_MAIN_DICOM_TAGS; 154 tags = STUDY_MAIN_DICOM_TAGS;
234 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag); 155 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
235 break; 156 break;
236 157
237 case ResourceType_Series: 158 case ResourceType_Series:
238 tags = SERIES_MAIN_DICOM_TAGS; 159 tags = SERIES_MAIN_DICOM_TAGS;
239 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag); 160 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
240 break; 161 break;
241 162
242 case ResourceType_Instance: 163 case ResourceType_Instance:
243 tags = INSTANCE_MAIN_DICOM_TAGS; 164 tags = INSTANCE_MAIN_DICOM_TAGS;
244 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag); 165 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
245 break; 166 break;
246 167
247 default: 168 default:
248 throw OrthancException(ErrorCode_ParameterOutOfRange); 169 throw OrthancException(ErrorCode_ParameterOutOfRange);
249 } 170 }
250 } 171 }
251 172
252 173
253 void DicomMap::SetValue(uint16_t group, 174 static void LoadMainDicomTags(std::map<DicomTag, std::string>& target,
254 uint16_t element, 175 ResourceType level)
255 DicomValue* value) 176 {
177 const MainDicomTag* tags = NULL;
178 size_t size;
179 LoadMainDicomTags(tags, size, level);
180
181 assert(tags != NULL &&
182 size != 0);
183
184 for (size_t i = 0; i < size; i++)
185 {
186 assert(target.find(tags[i].tag_) == target.end());
187
188 target[tags[i].tag_] = tags[i].name_;
189 }
190 }
191
192
193 namespace
194 {
195 class DicomTag2 : public DicomTag
196 {
197 public:
198 DicomTag2() :
199 DicomTag(0, 0) // To make std::map<> happy
200 {
201 }
202
203 DicomTag2(const DicomTag& tag) :
204 DicomTag(tag)
205 {
206 }
207 };
208 }
209
210
211 static void LoadMainDicomTags(std::map<std::string, DicomTag2>& target,
212 ResourceType level)
213 {
214 const MainDicomTag* tags = NULL;
215 size_t size;
216 LoadMainDicomTags(tags, size, level);
217
218 assert(tags != NULL &&
219 size != 0);
220
221 for (size_t i = 0; i < size; i++)
222 {
223 assert(target.find(tags[i].name_) == target.end());
224
225 target[tags[i].name_] = tags[i].tag_;
226 }
227 }
228
229
230 void DicomMap::SetValueInternal(uint16_t group,
231 uint16_t element,
232 DicomValue* value)
256 { 233 {
257 DicomTag tag(group, element); 234 DicomTag tag(group, element);
258 Map::iterator it = map_.find(tag); 235 Content::iterator it = content_.find(tag);
259 236
260 if (it != map_.end()) 237 if (it != content_.end())
261 { 238 {
262 delete it->second; 239 delete it->second;
263 it->second = value; 240 it->second = value;
264 } 241 }
265 else 242 else
266 { 243 {
267 map_.insert(std::make_pair(tag, value)); 244 content_.insert(std::make_pair(tag, value));
268 } 245 }
269 }
270
271 void DicomMap::SetValue(DicomTag tag,
272 DicomValue* value)
273 {
274 SetValue(tag.GetGroup(), tag.GetElement(), value);
275 } 246 }
276 247
277 248
278 void DicomMap::Clear() 249 void DicomMap::Clear()
279 { 250 {
280 for (Map::iterator it = map_.begin(); it != map_.end(); ++it) 251 for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
281 { 252 {
282 assert(it->second != NULL); 253 assert(it->second != NULL);
283 delete it->second; 254 delete it->second;
284 } 255 }
285 256
286 map_.clear(); 257 content_.clear();
287 } 258 }
288 259
289 260
290 void DicomMap::ExtractTags(DicomMap& result, 261 static void ExtractTags(DicomMap& result,
291 const DicomTag* tags, 262 const DicomMap::Content& source,
292 size_t count) const 263 const MainDicomTag* tags,
264 size_t count)
293 { 265 {
294 result.Clear(); 266 result.Clear();
295 267
296 for (unsigned int i = 0; i < count; i++) 268 for (unsigned int i = 0; i < count; i++)
297 { 269 {
298 Map::const_iterator it = map_.find(tags[i]); 270 DicomMap::Content::const_iterator it = source.find(tags[i].tag_);
299 if (it != map_.end()) 271 if (it != source.end())
300 { 272 {
301 result.SetValue(it->first, it->second->Clone()); 273 result.SetValue(it->first, *it->second /* value will be cloned */);
302 } 274 }
303 } 275 }
304 } 276 }
305 277
306 278
307 void DicomMap::ExtractPatientInformation(DicomMap& result) const 279 void DicomMap::ExtractPatientInformation(DicomMap& result) const
308 { 280 {
309 ExtractTags(result, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 281 ExtractTags(result, content_, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
310 } 282 }
311 283
312 void DicomMap::ExtractStudyInformation(DicomMap& result) const 284 void DicomMap::ExtractStudyInformation(DicomMap& result) const
313 { 285 {
314 ExtractTags(result, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 286 ExtractTags(result, content_, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
315 } 287 }
316 288
317 void DicomMap::ExtractSeriesInformation(DicomMap& result) const 289 void DicomMap::ExtractSeriesInformation(DicomMap& result) const
318 { 290 {
319 ExtractTags(result, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 291 ExtractTags(result, content_, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
320 } 292 }
321 293
322 void DicomMap::ExtractInstanceInformation(DicomMap& result) const 294 void DicomMap::ExtractInstanceInformation(DicomMap& result) const
323 { 295 {
324 ExtractTags(result, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 296 ExtractTags(result, content_, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
325 } 297 }
326 298
327 299
328 300
329 DicomMap* DicomMap::Clone() const 301 DicomMap* DicomMap::Clone() const
330 { 302 {
331 std::auto_ptr<DicomMap> result(new DicomMap); 303 std::auto_ptr<DicomMap> result(new DicomMap);
332 304
333 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 305 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
334 { 306 {
335 result->map_.insert(std::make_pair(it->first, it->second->Clone())); 307 result->content_.insert(std::make_pair(it->first, it->second->Clone()));
336 } 308 }
337 309
338 return result.release(); 310 return result.release();
339 } 311 }
340 312
341 313
342 void DicomMap::Assign(const DicomMap& other) 314 void DicomMap::Assign(const DicomMap& other)
343 { 315 {
344 Clear(); 316 Clear();
345 317
346 for (Map::const_iterator it = other.map_.begin(); it != other.map_.end(); ++it) 318 for (Content::const_iterator it = other.content_.begin(); it != other.content_.end(); ++it)
347 { 319 {
348 map_.insert(std::make_pair(it->first, it->second->Clone())); 320 content_.insert(std::make_pair(it->first, it->second->Clone()));
349 } 321 }
350 } 322 }
351 323
352 324
353 const DicomValue& DicomMap::GetValue(const DicomTag& tag) const 325 const DicomValue& DicomMap::GetValue(const DicomTag& tag) const
365 } 337 }
366 338
367 339
368 const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const 340 const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const
369 { 341 {
370 Map::const_iterator it = map_.find(tag); 342 Content::const_iterator it = content_.find(tag);
371 343
372 if (it == map_.end()) 344 if (it == content_.end())
373 { 345 {
374 return NULL; 346 return NULL;
375 } 347 }
376 else 348 else
377 { 349 {
380 } 352 }
381 353
382 354
383 void DicomMap::Remove(const DicomTag& tag) 355 void DicomMap::Remove(const DicomTag& tag)
384 { 356 {
385 Map::iterator it = map_.find(tag); 357 Content::iterator it = content_.find(tag);
386 if (it != map_.end()) 358 if (it != content_.end())
387 { 359 {
388 delete it->second; 360 delete it->second;
389 map_.erase(it); 361 content_.erase(it);
390 } 362 }
391 } 363 }
392 364
393 365
394 static void SetupFindTemplate(DicomMap& result, 366 static void SetupFindTemplate(DicomMap& result,
395 const DicomTag* tags, 367 const MainDicomTag* tags,
396 size_t count) 368 size_t count)
397 { 369 {
398 result.Clear(); 370 result.Clear();
399 371
400 for (size_t i = 0; i < count; i++) 372 for (size_t i = 0; i < count; i++)
401 { 373 {
402 result.SetValue(tags[i], "", false); 374 result.SetValue(tags[i].tag_, "", false);
403 } 375 }
404 } 376 }
405 377
406 void DicomMap::SetupFindPatientTemplate(DicomMap& result) 378 void DicomMap::SetupFindPatientTemplate(DicomMap& result)
407 { 379 {
408 SetupFindTemplate(result, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 380 SetupFindTemplate(result, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
409 } 381 }
410 382
411 void DicomMap::SetupFindStudyTemplate(DicomMap& result) 383 void DicomMap::SetupFindStudyTemplate(DicomMap& result)
412 { 384 {
413 SetupFindTemplate(result, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 385 SetupFindTemplate(result, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
414 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 386 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
415 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 387 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
416 388
417 // These main DICOM tags are only indirectly related to the 389 // These main DICOM tags are only indirectly related to the
418 // General Study Module, remove them 390 // General Study Module, remove them
421 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION); 393 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION);
422 } 394 }
423 395
424 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) 396 void DicomMap::SetupFindSeriesTemplate(DicomMap& result)
425 { 397 {
426 SetupFindTemplate(result, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 398 SetupFindTemplate(result, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
427 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 399 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
428 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 400 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
429 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 401 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
430 402
431 // These tags are considered as "main" by Orthanc, but are not in the Series module 403 // These tags are considered as "main" by Orthanc, but are not in the Series module
443 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT); 415 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT);
444 } 416 }
445 417
446 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) 418 void DicomMap::SetupFindInstanceTemplate(DicomMap& result)
447 { 419 {
448 SetupFindTemplate(result, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag)); 420 SetupFindTemplate(result, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
449 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 421 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
450 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 422 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
451 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 423 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
452 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false); 424 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false);
453 } 425 }
463 } 435 }
464 436
465 437
466 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) 438 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level)
467 { 439 {
468 const DicomTag *tags = NULL; 440 const MainDicomTag *tags = NULL;
469 size_t size; 441 size_t size;
470 442 LoadMainDicomTags(tags, size, level);
471 switch (level)
472 {
473 case ResourceType_Patient:
474 tags = PATIENT_MAIN_DICOM_TAGS;
475 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag);
476 break;
477
478 case ResourceType_Study:
479 tags = STUDY_MAIN_DICOM_TAGS;
480 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag);
481 break;
482
483 case ResourceType_Series:
484 tags = SERIES_MAIN_DICOM_TAGS;
485 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag);
486 break;
487
488 case ResourceType_Instance:
489 tags = INSTANCE_MAIN_DICOM_TAGS;
490 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag);
491 break;
492
493 default:
494 throw OrthancException(ErrorCode_ParameterOutOfRange);
495 }
496 443
497 for (size_t i = 0; i < size; i++) 444 for (size_t i = 0; i < size; i++)
498 { 445 {
499 if (tags[i] == tag) 446 if (tags[i].tag_ == tag)
500 { 447 {
501 return true; 448 return true;
502 } 449 }
503 } 450 }
504 451
514 } 461 }
515 462
516 463
517 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level) 464 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level)
518 { 465 {
519 const DicomTag *tags = NULL; 466 const MainDicomTag *tags = NULL;
520 size_t size; 467 size_t size;
521 468 LoadMainDicomTags(tags, size, level);
522 switch (level)
523 {
524 case ResourceType_Patient:
525 tags = PATIENT_MAIN_DICOM_TAGS;
526 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(DicomTag);
527 break;
528
529 case ResourceType_Study:
530 tags = STUDY_MAIN_DICOM_TAGS;
531 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(DicomTag);
532 break;
533
534 case ResourceType_Series:
535 tags = SERIES_MAIN_DICOM_TAGS;
536 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(DicomTag);
537 break;
538
539 case ResourceType_Instance:
540 tags = INSTANCE_MAIN_DICOM_TAGS;
541 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(DicomTag);
542 break;
543
544 default:
545 throw OrthancException(ErrorCode_ParameterOutOfRange);
546 }
547 469
548 for (size_t i = 0; i < size; i++) 470 for (size_t i = 0; i < size; i++)
549 { 471 {
550 result.insert(tags[i]); 472 result.insert(tags[i].tag_);
551 } 473 }
552 } 474 }
553 475
554 476
555 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level) 477 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level)
571 493
572 void DicomMap::GetTags(std::set<DicomTag>& tags) const 494 void DicomMap::GetTags(std::set<DicomTag>& tags) const
573 { 495 {
574 tags.clear(); 496 tags.clear();
575 497
576 for (Map::const_iterator it = map_.begin(); 498 for (Content::const_iterator it = content_.begin();
577 it != map_.end(); ++it) 499 it != content_.end(); ++it)
578 { 500 {
579 tags.insert(it->first); 501 tags.insert(it->first);
580 } 502 }
581 } 503 }
582 504
1122 } 1044 }
1123 1045
1124 1046
1125 void DicomMap::Merge(const DicomMap& other) 1047 void DicomMap::Merge(const DicomMap& other)
1126 { 1048 {
1127 for (Map::const_iterator it = other.map_.begin(); 1049 for (Content::const_iterator it = other.content_.begin();
1128 it != other.map_.end(); ++it) 1050 it != other.content_.end(); ++it)
1129 { 1051 {
1130 assert(it->second != NULL); 1052 assert(it->second != NULL);
1131 1053
1132 if (map_.find(it->first) == map_.end()) 1054 if (content_.find(it->first) == content_.end())
1133 { 1055 {
1134 map_[it->first] = it->second->Clone(); 1056 content_[it->first] = it->second->Clone();
1135 } 1057 }
1136 } 1058 }
1137 } 1059 }
1138 1060
1139 1061
1140 void DicomMap::ExtractMainDicomTagsInternal(const DicomMap& other, 1062 void DicomMap::ExtractMainDicomTagsInternal(const DicomMap& other,
1141 ResourceType level) 1063 ResourceType level)
1142 { 1064 {
1143 const DicomTag* tags = NULL; 1065 const MainDicomTag* tags = NULL;
1144 size_t size = 0; 1066 size_t size = 0;
1145 1067
1146 LoadMainDicomTags(tags, size, level); 1068 LoadMainDicomTags(tags, size, level);
1147 assert(tags != NULL && size > 0); 1069 assert(tags != NULL && size > 0);
1148 1070
1149 for (size_t i = 0; i < size; i++) 1071 for (size_t i = 0; i < size; i++)
1150 { 1072 {
1151 Map::const_iterator found = other.map_.find(tags[i]); 1073 Content::const_iterator found = other.content_.find(tags[i].tag_);
1152 1074
1153 if (found != other.map_.end() && 1075 if (found != other.content_.end() &&
1154 map_.find(tags[i]) == map_.end()) 1076 content_.find(tags[i].tag_) == content_.end())
1155 { 1077 {
1156 assert(found->second != NULL); 1078 assert(found->second != NULL);
1157 map_[tags[i]] = found->second->Clone(); 1079 content_[tags[i].tag_] = found->second->Clone();
1158 } 1080 }
1159 } 1081 }
1160 } 1082 }
1161 1083
1162 1084
1175 // TODO - Speed up possible by making this std::set a global variable 1097 // TODO - Speed up possible by making this std::set a global variable
1176 1098
1177 std::set<DicomTag> mainDicomTags; 1099 std::set<DicomTag> mainDicomTags;
1178 GetMainDicomTags(mainDicomTags); 1100 GetMainDicomTags(mainDicomTags);
1179 1101
1180 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 1102 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1181 { 1103 {
1182 if (mainDicomTags.find(it->first) == mainDicomTags.end()) 1104 if (mainDicomTags.find(it->first) == mainDicomTags.end())
1183 { 1105 {
1184 return false; 1106 return false;
1185 } 1107 }
1191 1113
1192 void DicomMap::Serialize(Json::Value& target) const 1114 void DicomMap::Serialize(Json::Value& target) const
1193 { 1115 {
1194 target = Json::objectValue; 1116 target = Json::objectValue;
1195 1117
1196 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 1118 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1197 { 1119 {
1198 assert(it->second != NULL); 1120 assert(it->second != NULL);
1199 1121
1200 std::string tag = it->first.Format(); 1122 std::string tag = it->first.Format();
1201 1123
1221 for (size_t i = 0; i < tags.size(); i++) 1143 for (size_t i = 0; i < tags.size(); i++)
1222 { 1144 {
1223 DicomTag tag(0, 0); 1145 DicomTag tag(0, 0);
1224 1146
1225 if (!DicomTag::ParseHexadecimal(tag, tags[i].c_str()) || 1147 if (!DicomTag::ParseHexadecimal(tag, tags[i].c_str()) ||
1226 map_.find(tag) != map_.end()) 1148 content_.find(tag) != content_.end())
1227 { 1149 {
1228 throw OrthancException(ErrorCode_BadFileFormat); 1150 throw OrthancException(ErrorCode_BadFileFormat);
1229 } 1151 }
1230 1152
1231 std::auto_ptr<DicomValue> value(new DicomValue); 1153 std::auto_ptr<DicomValue> value(new DicomValue);
1232 value->Unserialize(source[tags[i]]); 1154 value->Unserialize(source[tags[i]]);
1233 1155
1234 map_[tag] = value.release(); 1156 content_[tag] = value.release();
1235 } 1157 }
1236 } 1158 }
1237 1159
1238 1160
1239 void DicomMap::FromDicomWeb(const Json::Value& source) 1161 void DicomMap::FromDicomWeb(const Json::Value& source)
1388 } 1310 }
1389 1311
1390 1312
1391 void DicomMap::RemoveBinaryTags() 1313 void DicomMap::RemoveBinaryTags()
1392 { 1314 {
1393 Map kept; 1315 Content kept;
1394 1316
1395 for (Map::iterator it = map_.begin(); it != map_.end(); ++it) 1317 for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
1396 { 1318 {
1397 assert(it->second != NULL); 1319 assert(it->second != NULL);
1398 1320
1399 if (!it->second->IsBinary() && 1321 if (!it->second->IsBinary() &&
1400 !it->second->IsNull()) 1322 !it->second->IsNull())
1405 { 1327 {
1406 delete it->second; 1328 delete it->second;
1407 } 1329 }
1408 } 1330 }
1409 1331
1410 map_ = kept; 1332 content_ = kept;
1333 }
1334
1335
1336 void DicomMap::DumpMainDicomTags(Json::Value& target,
1337 ResourceType level) const
1338 {
1339 std::map<DicomTag, std::string> mainTags; // TODO - Create a singleton to hold this map
1340 LoadMainDicomTags(mainTags, level);
1341
1342 target = Json::objectValue;
1343
1344 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1345 {
1346 assert(it->second != NULL);
1347
1348 if (!it->second->IsBinary() &&
1349 !it->second->IsNull())
1350 {
1351 std::map<DicomTag, std::string>::const_iterator found = mainTags.find(it->first);
1352
1353 if (found != mainTags.end())
1354 {
1355 target[found->second] = it->second->GetContent();
1356 }
1357 }
1358 }
1359 }
1360
1361
1362 void DicomMap::ParseMainDicomTags(const Json::Value& source,
1363 ResourceType level)
1364 {
1365 if (source.type() != Json::objectValue)
1366 {
1367 throw OrthancException(ErrorCode_BadFileFormat);
1368 }
1369
1370 Clear();
1371
1372 std::map<std::string, DicomTag2> mainTags; // TODO - Create a singleton to hold this map
1373 LoadMainDicomTags(mainTags, level);
1374
1375 Json::Value::Members members = source.getMemberNames();
1376 for (size_t i = 0; i < members.size(); i++)
1377 {
1378 std::map<std::string, DicomTag2>::const_iterator found = mainTags.find(members[i]);
1379
1380 if (found != mainTags.end())
1381 {
1382 const Json::Value& value = source[members[i]];
1383 if (value.type() != Json::stringValue)
1384 {
1385 throw OrthancException(ErrorCode_BadFileFormat);
1386 }
1387 else
1388 {
1389 SetValue(found->second, value.asString(), false);
1390 }
1391 }
1392 }
1411 } 1393 }
1412 1394
1413 1395
1414 void DicomMap::Print(FILE* fp) const 1396 void DicomMap::Print(FILE* fp) const
1415 { 1397 {