comparison OrthancStone/Sources/Toolbox/SortedFrames.cpp @ 1643:882e2253a90e

replacing SortedFrames::Instance by DicomInstanceParameters
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 10 Nov 2020 17:35:32 +0100
parents 960bb5fcc440
children 4a43106bc122
comparison
equal deleted inserted replaced
1642:5cc589bfb385 1643:882e2253a90e
28 #include <OrthancException.h> 28 #include <OrthancException.h>
29 #include <Toolbox.h> 29 #include <Toolbox.h>
30 30
31 namespace OrthancStone 31 namespace OrthancStone
32 { 32 {
33 SortedFrames::Instance::Instance(const Orthanc::DicomMap& tags) : 33 SortedFrames::Frame::Frame(const DicomInstanceParameters& instance,
34 geometry_(tags)
35 {
36 tags_.Assign(tags);
37
38 if (!tags.LookupStringValue(sopInstanceUid_, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false))
39 {
40 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
41 }
42
43 uint32_t tmp;
44 if (tags.ParseUnsignedInteger32(tmp, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES) &&
45 tmp > 0)
46 {
47 numberOfFrames_ = tmp;
48 }
49 else
50 {
51 numberOfFrames_ = 1;
52 }
53
54 std::string photometric;
55 if (tags.LookupStringValue(photometric, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, false))
56 {
57 Orthanc::Toolbox::StripSpaces(photometric);
58 monochrome1_ = (photometric == "MONOCHROME1");
59 }
60 else
61 {
62 monochrome1_ = false;
63 }
64
65 bool ok = false;
66
67 if (numberOfFrames_ > 1)
68 {
69 std::string offsets, increment;
70 if (tags.LookupStringValue(offsets, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, false) &&
71 tags.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false))
72 {
73 Orthanc::Toolbox::ToUpperCase(increment);
74 if (increment != "3004,000C")
75 {
76 LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image";
77 }
78 else if (LinearAlgebra::ParseVector(frameOffsets_, offsets))
79 {
80 if (frameOffsets_.size() == numberOfFrames_)
81 {
82 ok = true;
83 }
84 else
85 {
86 LOG(WARNING) << "The size of the GridFrameOffsetVector does not correspond to the number of frames";
87 }
88 }
89 else
90 {
91 LOG(WARNING) << "Cannot parse the GridFrameOffsetVector tag";
92 }
93 }
94 else
95 {
96 LOG(INFO) << "Missing the frame offset information in a multiframe image";
97 }
98 }
99
100 if (!ok)
101 {
102 frameOffsets_.resize(numberOfFrames_);
103 for (size_t i = 0; i < numberOfFrames_; i++)
104 {
105 frameOffsets_[i] = 0;
106 }
107 }
108 }
109
110
111 double SortedFrames::Instance::GetFrameOffset(unsigned int frame) const
112 {
113 assert(GetNumberOfFrames() == frameOffsets_.size());
114
115 if (frame >= GetNumberOfFrames())
116 {
117 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
118 }
119 else
120 {
121 return frameOffsets_[frame];
122 }
123 }
124
125
126 SortedFrames::Frame::Frame(const Instance& instance,
127 unsigned int frameNumber) : 34 unsigned int frameNumber) :
128 instance_(&instance), 35 instance_(&instance),
129 frameNumber_(frameNumber) 36 frameNumber_(frameNumber)
130 { 37 {
131 if (frameNumber >= instance.GetNumberOfFrames()) 38 if (frameNumber >= instance.GetNumberOfFrames())
133 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 40 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
134 } 41 }
135 } 42 }
136 43
137 44
138 const SortedFrames::Instance& SortedFrames::GetInstance(size_t instanceIndex) const 45 const DicomInstanceParameters& SortedFrames::GetInstance(size_t instanceIndex) const
139 { 46 {
140 if (instanceIndex >= instances_.size()) 47 if (instanceIndex >= instances_.size())
141 { 48 {
142 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 49 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
143 } 50 }
186 } 93 }
187 94
188 95
189 void SortedFrames::AddInstance(const Orthanc::DicomMap& tags) 96 void SortedFrames::AddInstance(const Orthanc::DicomMap& tags)
190 { 97 {
191 std::unique_ptr<Instance> instance(new Instance(tags)); 98 std::unique_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(tags));
192 99
193 std::string studyInstanceUid, seriesInstanceUid, sopInstanceUid;
194 if (!tags.LookupStringValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false) ||
195 !tags.LookupStringValue(seriesInstanceUid, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, false) ||
196 !tags.LookupStringValue(sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false))
197 {
198 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
199 }
200
201 if (instances_.empty()) 100 if (instances_.empty())
202 { 101 {
203 studyInstanceUid_ = studyInstanceUid; 102 studyInstanceUid_ = instance->GetStudyInstanceUid();
204 seriesInstanceUid_ = seriesInstanceUid; 103 seriesInstanceUid_ = instance->GetSeriesInstanceUid();
205 } 104 }
206 else 105 else
207 { 106 {
208 if (studyInstanceUid_ != studyInstanceUid || 107 if (studyInstanceUid_ != instance->GetStudyInstanceUid() ||
209 seriesInstanceUid_ != seriesInstanceUid) 108 seriesInstanceUid_ != instance->GetSeriesInstanceUid())
210 { 109 {
211 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, 110 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
212 "Mixing instances from different series"); 111 "Mixing instances from different series");
213 } 112 }
214 } 113 }
215 114
216 if (instancesIndex_.find(sopInstanceUid) != instancesIndex_.end()) 115 if (instancesIndex_.find(instance->GetSopInstanceUid()) != instancesIndex_.end())
217 { 116 {
218 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, 117 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
219 "Cannot register twice the same SOP Instance UID"); 118 "Cannot register twice the same SOP Instance UID");
220 } 119 }
221 120
222 instancesIndex_[sopInstanceUid] = instances_.size(); 121 instancesIndex_[instance->GetSopInstanceUid()] = instances_.size();
223 122
224 instances_.push_back(instance.release()); 123 instances_.push_back(instance.release());
225 sorted_ = false; 124 sorted_ = false;
226 frames_.clear(); 125 frames_.clear();
227 } 126 }
246 145
247 void SortedFrames::AddFramesOfInstance(std::set<size_t>& remainingInstances, 146 void SortedFrames::AddFramesOfInstance(std::set<size_t>& remainingInstances,
248 size_t instanceIndex) 147 size_t instanceIndex)
249 { 148 {
250 assert(instances_[instanceIndex] != NULL); 149 assert(instances_[instanceIndex] != NULL);
251 const Instance& instance = *instances_[instanceIndex]; 150 const DicomInstanceParameters& instance = *instances_[instanceIndex];
252 151
253 for (unsigned int i = 0; i < instance.GetNumberOfFrames(); i++) 152 for (unsigned int i = 0; i < instance.GetNumberOfFrames(); i++)
254 { 153 {
255 framesIndex_[std::make_pair(instance.GetSopInstanceUid(), i)] = frames_.size(); 154 framesIndex_[std::make_pair(instance.GetSopInstanceUid(), i)] = frames_.size();
256 frames_.push_back(Frame(instance, i)); 155 frames_.push_back(Frame(instance, i));
304 203
305 for (std::set<size_t>::const_iterator it = remainingInstances.begin(); 204 for (std::set<size_t>::const_iterator it = remainingInstances.begin();
306 it != remainingInstances.end(); ++it) 205 it != remainingInstances.end(); ++it)
307 { 206 {
308 assert(instances_[*it] != NULL); 207 assert(instances_[*it] != NULL);
309 const Instance& instance = *instances_[*it]; 208 const DicomInstanceParameters& instance = *instances_[*it];
310 209
311 int32_t value; 210 int32_t value;
312 std::string sopInstanceUid; 211 std::string sopInstanceUid;
313 if (instance.GetTags().ParseInteger32(value, tag) && 212 if (instance.GetTags().ParseInteger32(value, tag) &&
314 instance.GetTags().LookupStringValue( 213 instance.GetTags().LookupStringValue(
334 233
335 for (std::set<size_t>::const_iterator it = remainingInstances.begin(); 234 for (std::set<size_t>::const_iterator it = remainingInstances.begin();
336 it != remainingInstances.end(); ++it) 235 it != remainingInstances.end(); ++it)
337 { 236 {
338 assert(instances_[*it] != NULL); 237 assert(instances_[*it] != NULL);
339 const Instance& instance = *instances_[*it]; 238 const DicomInstanceParameters& instance = *instances_[*it];
340 239
341 std::string sopInstanceUid; 240 std::string sopInstanceUid;
342 if (instance.GetTags().LookupStringValue( 241 if (instance.GetTags().LookupStringValue(
343 sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) 242 sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false))
344 { 243 {
370 269
371 for (std::set<size_t>::const_iterator it = remainingInstances.begin(); 270 for (std::set<size_t>::const_iterator it = remainingInstances.begin();
372 it != remainingInstances.end(); ++it) 271 it != remainingInstances.end(); ++it)
373 { 272 {
374 assert(instances_[*it] != NULL); 273 assert(instances_[*it] != NULL);
375 const Instance& instance = *instances_[*it]; 274 const DicomInstanceParameters& instance = *instances_[*it];
376 275
377 if (instance.GetGeometry().IsValid()) 276 if (instance.GetGeometry().IsValid())
378 { 277 {
379 n += 1; 278 n += 1;
380 meanNormal += (instance.GetGeometry().GetNormal() - meanNormal) / static_cast<float>(n); 279 meanNormal += (instance.GetGeometry().GetNormal() - meanNormal) / static_cast<float>(n);
386 285
387 for (std::set<size_t>::const_iterator it = remainingInstances.begin(); 286 for (std::set<size_t>::const_iterator it = remainingInstances.begin();
388 it != remainingInstances.end(); ++it) 287 it != remainingInstances.end(); ++it)
389 { 288 {
390 assert(instances_[*it] != NULL); 289 assert(instances_[*it] != NULL);
391 const Instance& instance = *instances_[*it]; 290 const DicomInstanceParameters& instance = *instances_[*it];
392 291
393 std::string sopInstanceUid; 292 std::string sopInstanceUid;
394 if (instance.GetGeometry().IsValid() && 293 if (instance.GetGeometry().IsValid() &&
395 instance.GetTags().LookupStringValue( 294 instance.GetTags().LookupStringValue(
396 sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) 295 sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false))
426 325
427 326
428 CoordinateSystem3D SortedFrames::GetFrameGeometry(size_t frameIndex) const 327 CoordinateSystem3D SortedFrames::GetFrameGeometry(size_t frameIndex) const
429 { 328 {
430 const Frame& frame = GetFrame(frameIndex); 329 const Frame& frame = GetFrame(frameIndex);
431 CoordinateSystem3D geometry = frame.GetInstance().GetGeometry(); 330 return frame.GetInstance().GetFrameGeometry(frame.GetFrameNumberInInstance());
432
433 if (geometry.IsValid())
434 {
435 geometry.SetOrigin(geometry.GetOrigin() + geometry.GetNormal() *
436 frame.GetInstance().GetFrameOffset(frame.GetFrameNumberInInstance()));
437 return geometry;
438 }
439 else
440 {
441 return geometry;
442 }
443 } 331 }
444 332
445 333
446 bool SortedFrames::LookupFrame(size_t& frameIndex, 334 bool SortedFrames::LookupFrame(size_t& frameIndex,
447 const std::string& sopInstanceUid, 335 const std::string& sopInstanceUid,