Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Toolbox/DicomStructuredReport.cpp @ 2099:67db5afb305d
partial integration dicom-sr->mainline
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 08 Nov 2023 17:26:22 +0100 |
parents | 7c3d65166c26 |
children | 129cb165ea8d c23eef785569 |
comparison
equal
deleted
inserted
replaced
2095:ec676dbe85ac | 2099:67db5afb305d |
---|---|
116 } | 116 } |
117 | 117 |
118 | 118 |
119 namespace OrthancStone | 119 namespace OrthancStone |
120 { | 120 { |
121 void DicomStructuredReport::ReferencedInstance::AddFrame(unsigned int frame) | 121 void DicomStructuredReport::Structure::Copy(const Structure& other) |
122 { | 122 { |
123 if (frame == 0) | 123 if (other.HasFrameNumber()) |
124 { | |
125 SetFrameNumber(other.GetFrameNumber()); | |
126 } | |
127 | |
128 if (other.HasProbabilityOfCancer()) | |
129 { | |
130 SetProbabilityOfCancer(other.GetProbabilityOfCancer()); | |
131 } | |
132 } | |
133 | |
134 | |
135 DicomStructuredReport::Structure::Structure(const std::string& sopInstanceUid) : | |
136 sopInstanceUid_(sopInstanceUid), | |
137 hasFrameNumber_(false), | |
138 hasProbabilityOfCancer_(false) | |
139 { | |
140 } | |
141 | |
142 | |
143 void DicomStructuredReport::Structure::SetFrameNumber(unsigned int frame) | |
144 { | |
145 hasFrameNumber_ = true; | |
146 frameNumber_ = frame; | |
147 } | |
148 | |
149 | |
150 void DicomStructuredReport::Structure::SetProbabilityOfCancer(float probability) | |
151 { | |
152 if (probability < 0 || | |
153 probability > 100) | |
124 { | 154 { |
125 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 155 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
126 } | 156 } |
127 else | 157 else |
128 { | 158 { |
129 frames_.insert(frame - 1); | 159 hasProbabilityOfCancer_ = true; |
130 } | 160 probabilityOfCancer_ = probability; |
131 } | 161 } |
132 | 162 } |
133 | 163 |
134 class DicomStructuredReport::Structure : public boost::noncopyable | 164 |
135 { | 165 unsigned int DicomStructuredReport::Structure::GetFrameNumber() const |
136 private: | 166 { |
137 std::string sopInstanceUid_; | 167 if (hasFrameNumber_) |
138 bool hasFrameNumber_; | 168 { |
139 unsigned int frameNumber_; | 169 return frameNumber_; |
140 bool hasProbabilityOfCancer_; | 170 } |
141 float probabilityOfCancer_; | 171 else |
142 | 172 { |
143 public: | 173 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
144 Structure(const std::string& sopInstanceUid) : | 174 } |
145 sopInstanceUid_(sopInstanceUid), | 175 } |
146 hasFrameNumber_(false), | 176 |
147 hasProbabilityOfCancer_(false) | 177 float DicomStructuredReport::Structure::GetProbabilityOfCancer() const |
148 { | 178 { |
149 } | 179 if (hasProbabilityOfCancer_) |
150 | 180 { |
151 virtual ~Structure() | 181 return probabilityOfCancer_; |
152 { | 182 } |
153 } | 183 else |
154 | 184 { |
155 void SetFrameNumber(unsigned int frame) | 185 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
156 { | 186 } |
157 if (frame <= 0) | 187 } |
158 { | 188 |
159 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 189 |
160 } | 190 DicomStructuredReport::Point::Point(const std::string& sopInstanceUid, |
161 else | 191 double x, |
162 { | 192 double y) : |
163 hasFrameNumber_ = true; | 193 Structure(sopInstanceUid), |
164 frameNumber_ = frame - 1; | 194 point_(x, y) |
165 } | 195 { |
166 } | 196 } |
167 | 197 |
168 void SetProbabilityOfCancer(float probability) | 198 |
169 { | 199 DicomStructuredReport::Structure* DicomStructuredReport::Point::Clone() const |
170 if (probability < 0 || | 200 { |
171 probability > 100) | 201 std::unique_ptr<Point> cloned(new Point(GetSopInstanceUid(), point_.GetX(), point_.GetY())); |
172 { | 202 cloned->Copy(*this); |
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 203 return cloned.release(); |
174 } | 204 } |
175 else | 205 |
176 { | 206 |
177 hasProbabilityOfCancer_ = true; | 207 DicomStructuredReport::Polyline::Polyline(const std::string& sopInstanceUid, |
178 probabilityOfCancer_ = probability; | 208 const float* points, |
179 } | 209 unsigned long pointsCount) : |
180 } | 210 Structure(sopInstanceUid) |
181 | 211 { |
182 bool HasFrameNumber() const | 212 if (pointsCount % 2 != 0) |
183 { | 213 { |
184 return hasFrameNumber_; | 214 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
185 } | 215 } |
186 | 216 |
187 bool HasProbabilityOfCancer() const | 217 points_.reserve(pointsCount / 2); |
188 { | 218 |
189 return hasProbabilityOfCancer_; | 219 for (unsigned long i = 0; i < pointsCount; i += 2) |
190 } | 220 { |
191 | 221 points_.push_back(ScenePoint2D(points[i], points[i + 1])); |
192 unsigned int GetFrameNumber() const | 222 } |
193 { | 223 } |
194 if (hasFrameNumber_) | 224 |
195 { | 225 |
196 return frameNumber_; | 226 DicomStructuredReport::Polyline::Polyline(const std::string& sopInstanceUid, |
197 } | 227 const std::vector<ScenePoint2D>& points) : |
198 else | 228 Structure(sopInstanceUid), |
199 { | 229 points_(points) |
200 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 230 { |
201 } | 231 } |
202 } | 232 |
203 | 233 |
204 float GetProbabilityOfCancer() const | 234 DicomStructuredReport::Structure* DicomStructuredReport::Polyline::Clone() const |
205 { | 235 { |
206 if (hasProbabilityOfCancer_) | 236 std::unique_ptr<Polyline> cloned(new Polyline(GetSopInstanceUid(), points_)); |
207 { | 237 cloned->Copy(*this); |
208 return probabilityOfCancer_; | 238 return cloned.release(); |
209 } | 239 } |
210 else | 240 |
211 { | 241 |
212 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 242 const ScenePoint2D& DicomStructuredReport::Polyline::GetPoint(size_t i) const |
213 } | 243 { |
214 } | 244 if (i >= points_.size()) |
215 }; | 245 { |
216 | 246 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
217 | 247 } |
218 class DicomStructuredReport::Point : public Structure | 248 else |
219 { | 249 { |
220 private: | 250 return points_[i]; |
221 ScenePoint2D point_; | 251 } |
222 | 252 } |
223 public: | |
224 Point(const std::string& sopInstanceUid, | |
225 double x, | |
226 double y) : | |
227 Structure(sopInstanceUid), | |
228 point_(x, y) | |
229 { | |
230 } | |
231 | |
232 const ScenePoint2D& GetPoint() const | |
233 { | |
234 return point_; | |
235 } | |
236 }; | |
237 | |
238 | |
239 class DicomStructuredReport::Polyline : public Structure | |
240 { | |
241 private: | |
242 std::vector<ScenePoint2D> points_; | |
243 | |
244 public: | |
245 Polyline(const std::string& sopInstanceUid, | |
246 const float* points, | |
247 unsigned long pointsCount) : | |
248 Structure(sopInstanceUid) | |
249 { | |
250 if (pointsCount % 2 != 0) | |
251 { | |
252 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
253 } | |
254 | |
255 points_.reserve(pointsCount / 2); | |
256 | |
257 for (unsigned long i = 0; i < pointsCount; i += 2) | |
258 { | |
259 points_.push_back(ScenePoint2D(points[i], points[i + 1])); | |
260 } | |
261 } | |
262 | |
263 size_t GetSize() const | |
264 { | |
265 return points_.size(); | |
266 } | |
267 | |
268 const ScenePoint2D& GetPoint(size_t i) const | |
269 { | |
270 if (i >= points_.size()) | |
271 { | |
272 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
273 } | |
274 else | |
275 { | |
276 return points_[i]; | |
277 } | |
278 } | |
279 }; | |
280 | 253 |
281 | 254 |
282 void DicomStructuredReport::AddStructure(const std::string& sopInstanceUid, | 255 void DicomStructuredReport::AddStructure(const std::string& sopInstanceUid, |
283 DcmItem& group, | 256 DcmItem& group, |
284 bool hasFrameNumber, | 257 bool hasFrameNumber, |
502 Orthanc::Toolbox::SplitString(tokens, frames, '\\'); | 475 Orthanc::Toolbox::SplitString(tokens, frames, '\\'); |
503 | 476 |
504 for (size_t m = 0; m < tokens.size(); m++) | 477 for (size_t m = 0; m < tokens.size(); m++) |
505 { | 478 { |
506 uint32_t frame; | 479 uint32_t frame; |
507 if (!Orthanc::SerializationToolbox::ParseUnsignedInteger32(frame, tokens[m])) | 480 if (!Orthanc::SerializationToolbox::ParseUnsignedInteger32(frame, tokens[m]) || |
481 frame <= 0) | |
508 { | 482 { |
509 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 483 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
510 } | 484 } |
511 else | 485 else |
512 { | 486 { |
513 AddStructure(sopInstanceUid, group, true, frame, hasProbabilityOfCancer, probabilityOfCancer); | 487 AddStructure(sopInstanceUid, group, true, frame - 1, hasProbabilityOfCancer, probabilityOfCancer); |
514 instanceInformation->second->AddFrame(frame); | 488 instanceInformation->second->AddFrame(frame - 1); |
515 } | 489 } |
516 } | 490 } |
517 } | 491 } |
518 else | 492 else |
519 { | 493 { |
520 AddStructure(sopInstanceUid, group, false, 0, hasProbabilityOfCancer, probabilityOfCancer); | 494 AddStructure(sopInstanceUid, group, false, 0, hasProbabilityOfCancer, probabilityOfCancer); |
521 instanceInformation->second->AddFrame(1); | 495 instanceInformation->second->AddFrame(0); |
522 } | 496 } |
523 } | 497 } |
524 } | 498 } |
525 } | 499 } |
526 } | 500 } |
529 } | 503 } |
530 } | 504 } |
531 } | 505 } |
532 | 506 |
533 | 507 |
508 DicomStructuredReport::DicomStructuredReport(const DicomStructuredReport& other) : | |
509 studyInstanceUid_(other.studyInstanceUid_), | |
510 seriesInstanceUid_(other.seriesInstanceUid_), | |
511 sopInstanceUid_(other.sopInstanceUid_), | |
512 orderedInstances_(other.orderedInstances_) | |
513 { | |
514 for (std::map<std::string, ReferencedInstance*>::const_iterator | |
515 it = other.instancesInformation_.begin(); it != other.instancesInformation_.end(); ++it) | |
516 { | |
517 assert(it->second != NULL); | |
518 instancesInformation_[it->first] = new ReferencedInstance(*it->second); | |
519 } | |
520 | |
521 for (std::deque<Structure*>::const_iterator it = other.structures_.begin(); it != other.structures_.end(); ++it) | |
522 { | |
523 assert(*it != NULL); | |
524 structures_.push_back((*it)->Clone()); | |
525 } | |
526 } | |
527 | |
528 | |
534 DicomStructuredReport::~DicomStructuredReport() | 529 DicomStructuredReport::~DicomStructuredReport() |
535 { | 530 { |
536 for (std::list<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it) | 531 for (std::deque<Structure*>::iterator it = structures_.begin(); it != structures_.end(); ++it) |
537 { | 532 { |
538 assert(*it != NULL); | 533 assert(*it != NULL); |
539 delete *it; | 534 delete *it; |
540 } | 535 } |
541 | 536 |
596 orderedInstances_[i], | 591 orderedInstances_[i], |
597 found->second->GetSopClassUid(), *frame)); | 592 found->second->GetSopClassUid(), *frame)); |
598 } | 593 } |
599 } | 594 } |
600 } | 595 } |
601 } | 596 |
597 | |
598 const DicomStructuredReport::Structure& DicomStructuredReport::GetStructure(size_t index) const | |
599 { | |
600 if (index >= structures_.size()) | |
601 { | |
602 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
603 } | |
604 else | |
605 { | |
606 assert(structures_[index] != NULL); | |
607 return *structures_[index]; | |
608 } | |
609 } | |
610 } |