Mercurial > hg > orthanc-stone
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, |