Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Toolbox/DicomStructureSet2.cpp @ 1834:126522623e20
replaced OrthancStone::DicomPath by new class Orthanc::DicomPath from orthanc framework
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 10 Jun 2021 12:07:04 +0200 |
parents | 946eb7200b82 |
children | f6eaf617d8e8 |
comparison
equal
deleted
inserted
replaced
1833:3c0996f028a1 | 1834:126522623e20 |
---|---|
29 #include <Logging.h> | 29 #include <Logging.h> |
30 #include <OrthancException.h> | 30 #include <OrthancException.h> |
31 #include <Toolbox.h> | 31 #include <Toolbox.h> |
32 #include <DicomFormat/DicomTag.h> | 32 #include <DicomFormat/DicomTag.h> |
33 | 33 |
34 #include <FullOrthancDataset.h> | 34 #include "DicomStructure2.h" |
35 #include <DicomDatasetReader.h> | 35 #include "GenericToolbox.h" |
36 #include "OrthancDatasets/DicomDatasetReader.h" | |
36 | 37 |
37 namespace OrthancStone | 38 namespace OrthancStone |
38 { | 39 { |
39 static const OrthancPlugins::DicomTag DICOM_TAG_CONTOUR_GEOMETRIC_TYPE(0x3006, 0x0042); | 40 static const Orthanc::DicomTag DICOM_TAG_CONTOUR_GEOMETRIC_TYPE(0x3006, 0x0042); |
40 static const OrthancPlugins::DicomTag DICOM_TAG_CONTOUR_IMAGE_SEQUENCE(0x3006, 0x0016); | 41 static const Orthanc::DicomTag DICOM_TAG_CONTOUR_IMAGE_SEQUENCE(0x3006, 0x0016); |
41 static const OrthancPlugins::DicomTag DICOM_TAG_CONTOUR_SEQUENCE(0x3006, 0x0040); | 42 static const Orthanc::DicomTag DICOM_TAG_CONTOUR_SEQUENCE(0x3006, 0x0040); |
42 static const OrthancPlugins::DicomTag DICOM_TAG_CONTOUR_DATA(0x3006, 0x0050); | 43 static const Orthanc::DicomTag DICOM_TAG_CONTOUR_DATA(0x3006, 0x0050); |
43 static const OrthancPlugins::DicomTag DICOM_TAG_NUMBER_OF_CONTOUR_POINTS(0x3006, 0x0046); | 44 static const Orthanc::DicomTag DICOM_TAG_NUMBER_OF_CONTOUR_POINTS(0x3006, 0x0046); |
44 static const OrthancPlugins::DicomTag DICOM_TAG_REFERENCED_SOP_INSTANCE_UID(0x0008, 0x1155); | 45 static const Orthanc::DicomTag DICOM_TAG_REFERENCED_SOP_INSTANCE_UID(0x0008, 0x1155); |
45 static const OrthancPlugins::DicomTag DICOM_TAG_ROI_CONTOUR_SEQUENCE(0x3006, 0x0039); | 46 static const Orthanc::DicomTag DICOM_TAG_ROI_CONTOUR_SEQUENCE(0x3006, 0x0039); |
46 static const OrthancPlugins::DicomTag DICOM_TAG_ROI_DISPLAY_COLOR(0x3006, 0x002a); | 47 static const Orthanc::DicomTag DICOM_TAG_ROI_DISPLAY_COLOR(0x3006, 0x002a); |
47 static const OrthancPlugins::DicomTag DICOM_TAG_ROI_NAME(0x3006, 0x0026); | 48 static const Orthanc::DicomTag DICOM_TAG_ROI_NAME(0x3006, 0x0026); |
48 static const OrthancPlugins::DicomTag DICOM_TAG_RT_ROI_INTERPRETED_TYPE(0x3006, 0x00a4); | 49 static const Orthanc::DicomTag DICOM_TAG_RT_ROI_INTERPRETED_TYPE(0x3006, 0x00a4); |
49 static const OrthancPlugins::DicomTag DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE(0x3006, 0x0080); | 50 static const Orthanc::DicomTag DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE(0x3006, 0x0080); |
50 static const OrthancPlugins::DicomTag DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE(0x3006, 0x0020); | 51 static const Orthanc::DicomTag DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE(0x3006, 0x0020); |
51 | 52 |
52 static inline uint8_t ConvertAndClipToByte(double v) | 53 static inline uint8_t ConvertAndClipToByte(double v) |
53 { | 54 { |
54 if (v < 0) | 55 if (v < 0) |
55 { | 56 { |
64 return static_cast<uint8_t>(v); | 65 return static_cast<uint8_t>(v); |
65 } | 66 } |
66 } | 67 } |
67 | 68 |
68 static bool ReadDicomToVector(Vector& target, | 69 static bool ReadDicomToVector(Vector& target, |
69 const OrthancPlugins::IDicomDataset& dataset, | 70 const IDicomDataset& dataset, |
70 const OrthancPlugins::DicomPath& tag) | 71 const Orthanc::DicomPath& tag) |
71 { | 72 { |
72 std::string value; | 73 std::string value; |
73 return (dataset.GetStringValue(value, tag) && | 74 return (dataset.GetStringValue(value, tag) && |
74 GenericToolbox::FastParseVector(target, value)); | 75 GenericToolbox::FastParseVector(target, value)); |
75 } | 76 } |
76 | 77 |
77 | 78 |
78 void DicomPathToString(std::string& s, const OrthancPlugins::DicomPath& dicomPath) | 79 void DicomPathToString(std::string& s, const Orthanc::DicomPath& dicomPath) |
79 { | 80 { |
80 std::stringstream tmp; | 81 std::stringstream tmp; |
81 for (size_t i = 0; i < dicomPath.GetPrefixLength(); ++i) | 82 for (size_t i = 0; i < dicomPath.GetPrefixLength(); ++i) |
82 { | 83 { |
83 OrthancPlugins::DicomTag tag = dicomPath.GetPrefixTag(i); | 84 Orthanc::DicomTag tag = dicomPath.GetPrefixTag(i); |
84 | 85 |
85 // We use this other object to be able to use GetMainTagsName | 86 // We use this other object to be able to use GetMainTagsName |
86 // and Format | 87 // and Format |
87 Orthanc::DicomTag tag2(tag.GetGroup(), tag.GetElement()); | 88 Orthanc::DicomTag tag2(tag.GetGroup(), tag.GetElement()); |
88 size_t index = dicomPath.GetPrefixIndex(i); | 89 size_t index = dicomPath.GetPrefixIndex(i); |
89 tmp << tag2.GetMainTagsName() << " (" << tag2.Format() << ") [" << index << "] / "; | 90 tmp << tag2.GetMainTagsName() << " (" << tag2.Format() << ") [" << index << "] / "; |
90 } | 91 } |
91 const OrthancPlugins::DicomTag& tag = dicomPath.GetFinalTag(); | 92 const Orthanc::DicomTag& tag = dicomPath.GetFinalTag(); |
92 Orthanc::DicomTag tag2(tag.GetGroup(), tag.GetElement()); | 93 Orthanc::DicomTag tag2(tag.GetGroup(), tag.GetElement()); |
93 tmp << tag2.GetMainTagsName() << " (" << tag2.Format() << ")"; | 94 tmp << tag2.GetMainTagsName() << " (" << tag2.Format() << ")"; |
94 s = tmp.str(); | 95 s = tmp.str(); |
95 } | 96 } |
96 | 97 |
97 std::ostream& operator<<(std::ostream& s, const OrthancPlugins::DicomPath& dicomPath) | 98 std::ostream& operator<<(std::ostream& s, const Orthanc::DicomPath& dicomPath) |
98 { | 99 { |
99 std::string tmp; | 100 std::string tmp; |
100 DicomPathToString(tmp, dicomPath); | 101 DicomPathToString(tmp, dicomPath); |
101 s << tmp; | 102 s << tmp; |
102 return s; | 103 return s; |
112 DicomStructureSet2::~DicomStructureSet2() | 113 DicomStructureSet2::~DicomStructureSet2() |
113 { | 114 { |
114 | 115 |
115 } | 116 } |
116 | 117 |
117 void DicomStructureSet2::SetContents(const OrthancPlugins::FullOrthancDataset& tags) | 118 void DicomStructureSet2::SetContents(const FullOrthancDataset& tags) |
118 { | 119 { |
119 FillStructuresFromDataset(tags); | 120 FillStructuresFromDataset(tags); |
120 ComputeDependentProperties(); | 121 ComputeDependentProperties(); |
121 } | 122 } |
122 | 123 |
126 { | 127 { |
127 structures_[i].ComputeDependentProperties(); | 128 structures_[i].ComputeDependentProperties(); |
128 } | 129 } |
129 } | 130 } |
130 | 131 |
131 void DicomStructureSet2::FillStructuresFromDataset(const OrthancPlugins::FullOrthancDataset& tags) | 132 void DicomStructureSet2::FillStructuresFromDataset(const FullOrthancDataset& tags) |
132 { | 133 { |
133 OrthancPlugins::DicomDatasetReader reader(tags); | 134 DicomDatasetReader reader(tags); |
134 | 135 |
135 // a few sanity checks | 136 // a few sanity checks |
136 size_t count = 0, tmp = 0; | 137 size_t count = 0, tmp = 0; |
137 | 138 |
138 // DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE (0x3006, 0x0080); | 139 // DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE (0x3006, 0x0080); |
139 // DICOM_TAG_ROI_CONTOUR_SEQUENCE (0x3006, 0x0039); | 140 // DICOM_TAG_ROI_CONTOUR_SEQUENCE (0x3006, 0x0039); |
140 // DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE (0x3006, 0x0020); | 141 // DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE (0x3006, 0x0020); |
141 if (!tags.GetSequenceSize(count, DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE) || | 142 if (!tags.GetSequenceSize(count, Orthanc::DicomPath(DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE)) || |
142 !tags.GetSequenceSize(tmp, DICOM_TAG_ROI_CONTOUR_SEQUENCE) || | 143 !tags.GetSequenceSize(tmp, Orthanc::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE)) || |
143 tmp != count || | 144 tmp != count || |
144 !tags.GetSequenceSize(tmp, DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE) || | 145 !tags.GetSequenceSize(tmp, Orthanc::DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE)) || |
145 tmp != count) | 146 tmp != count) |
146 { | 147 { |
147 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 148 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
148 } | 149 } |
149 | 150 |
150 // let's now parse the structures stored in the dicom file | 151 // let's now parse the structures stored in the dicom file |
155 structures_.resize(count); | 156 structures_.resize(count); |
156 for (size_t i = 0; i < count; i++) | 157 for (size_t i = 0; i < count; i++) |
157 { | 158 { |
158 // (0x3006, 0x0080)[i]/(0x3006, 0x00a4) | 159 // (0x3006, 0x0080)[i]/(0x3006, 0x00a4) |
159 structures_[i].interpretation_ = reader.GetStringValue | 160 structures_[i].interpretation_ = reader.GetStringValue |
160 (OrthancPlugins::DicomPath(DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE, i, | 161 (Orthanc::DicomPath(DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE, i, |
161 DICOM_TAG_RT_ROI_INTERPRETED_TYPE), | 162 DICOM_TAG_RT_ROI_INTERPRETED_TYPE), |
162 "No interpretation"); | 163 "No interpretation"); |
163 | 164 |
164 // (0x3006, 0x0020)[i]/(0x3006, 0x0026) | 165 // (0x3006, 0x0020)[i]/(0x3006, 0x0026) |
165 structures_[i].name_ = reader.GetStringValue | 166 structures_[i].name_ = reader.GetStringValue |
166 (OrthancPlugins::DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE, i, | 167 (Orthanc::DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE, i, |
167 DICOM_TAG_ROI_NAME), | 168 DICOM_TAG_ROI_NAME), |
168 "No name"); | 169 "No name"); |
169 | 170 |
170 Vector color; | 171 Vector color; |
171 // (0x3006, 0x0039)[i]/(0x3006, 0x002a) | 172 // (0x3006, 0x0039)[i]/(0x3006, 0x002a) |
172 if (ReadDicomToVector(color, tags, OrthancPlugins::DicomPath( | 173 if (ReadDicomToVector(color, tags, Orthanc::DicomPath( |
173 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_ROI_DISPLAY_COLOR)) | 174 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_ROI_DISPLAY_COLOR)) |
174 && color.size() == 3) | 175 && color.size() == 3) |
175 { | 176 { |
176 structures_[i].red_ = ConvertAndClipToByte(color[0]); | 177 structures_[i].red_ = ConvertAndClipToByte(color[0]); |
177 structures_[i].green_ = ConvertAndClipToByte(color[1]); | 178 structures_[i].green_ = ConvertAndClipToByte(color[1]); |
178 structures_[i].blue_ = ConvertAndClipToByte(color[2]); | 179 structures_[i].blue_ = ConvertAndClipToByte(color[2]); |
179 } | 180 } |
185 } | 186 } |
186 | 187 |
187 size_t countSlices; | 188 size_t countSlices; |
188 // DICOM_TAG_ROI_CONTOUR_SEQUENCE (0x3006, 0x0039); | 189 // DICOM_TAG_ROI_CONTOUR_SEQUENCE (0x3006, 0x0039); |
189 // DICOM_TAG_CONTOUR_SEQUENCE (0x3006, 0x0040); | 190 // DICOM_TAG_CONTOUR_SEQUENCE (0x3006, 0x0040); |
190 if (!tags.GetSequenceSize(countSlices, OrthancPlugins::DicomPath( | 191 if (!tags.GetSequenceSize(countSlices, Orthanc::DicomPath( |
191 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_CONTOUR_SEQUENCE))) | 192 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, DICOM_TAG_CONTOUR_SEQUENCE))) |
192 { | 193 { |
193 LOG(WARNING) << "DicomStructureSet2::SetContents | structure \"" << structures_[i].name_ << "\" has no slices!"; | 194 LOG(WARNING) << "DicomStructureSet2::SetContents | structure \"" << structures_[i].name_ << "\" has no slices!"; |
194 countSlices = 0; | 195 countSlices = 0; |
195 } | 196 } |
196 | 197 |
197 LOG(INFO) << "New RT structure: \"" << structures_[i].name_ | 198 LOG(INFO) << "New RT structure: \"" << structures_[i].name_ |
198 << "\" with interpretation \"" << structures_[i].interpretation_ | 199 << "\" with interpretation \"" << structures_[i].interpretation_ |
199 << "\" containing " << countSlices << " slices (color: " | 200 << "\" containing " << countSlices << " slices (color: " |
200 << static_cast<int>(structures_[i].red_) << "," | 201 << static_cast<int>(structures_[i].red_) << "," |
201 << static_cast<int>(structures_[i].green_) << "," | 202 << static_cast<int>(structures_[i].green_) << "," |
202 << static_cast<int>(structures_[i].blue_) << ")"; | 203 << static_cast<int>(structures_[i].blue_) << ")"; |
203 | 204 |
204 // These temporary variables avoid allocating many vectors in the loop below | 205 // These temporary variables avoid allocating many vectors in the loop below |
205 | 206 |
206 // (0x3006, 0x0039)[i]/(0x3006, 0x0040)[0]/(0x3006, 0x0046) | 207 // (0x3006, 0x0039)[i]/(0x3006, 0x0040)[0]/(0x3006, 0x0046) |
207 OrthancPlugins::DicomPath countPointsPath( | 208 Orthanc::DicomPath countPointsPath( |
208 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, | 209 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, |
209 DICOM_TAG_CONTOUR_SEQUENCE, 0, | 210 DICOM_TAG_CONTOUR_SEQUENCE, 0, |
210 DICOM_TAG_NUMBER_OF_CONTOUR_POINTS); | 211 DICOM_TAG_NUMBER_OF_CONTOUR_POINTS); |
211 | 212 |
212 OrthancPlugins::DicomPath geometricTypePath( | 213 Orthanc::DicomPath geometricTypePath( |
213 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, | 214 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, |
214 DICOM_TAG_CONTOUR_SEQUENCE, 0, | 215 DICOM_TAG_CONTOUR_SEQUENCE, 0, |
215 DICOM_TAG_CONTOUR_GEOMETRIC_TYPE); | 216 DICOM_TAG_CONTOUR_GEOMETRIC_TYPE); |
216 | 217 |
217 OrthancPlugins::DicomPath imageSequencePath( | 218 Orthanc::DicomPath imageSequencePath( |
218 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, | 219 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, |
219 DICOM_TAG_CONTOUR_SEQUENCE, 0, | 220 DICOM_TAG_CONTOUR_SEQUENCE, 0, |
220 DICOM_TAG_CONTOUR_IMAGE_SEQUENCE); | 221 DICOM_TAG_CONTOUR_IMAGE_SEQUENCE); |
221 | 222 |
222 // (3006,0039)[i] / (0x3006, 0x0040)[0] / (0x3006, 0x0016)[0] / (0x0008, 0x1155) | 223 // (3006,0039)[i] / (0x3006, 0x0040)[0] / (0x3006, 0x0016)[0] / (0x0008, 0x1155) |
223 OrthancPlugins::DicomPath referencedInstancePath( | 224 Orthanc::DicomPath referencedInstancePath( |
224 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, | 225 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, |
225 DICOM_TAG_CONTOUR_SEQUENCE, 0, | 226 DICOM_TAG_CONTOUR_SEQUENCE, 0, |
226 DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0, | 227 DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0, |
227 DICOM_TAG_REFERENCED_SOP_INSTANCE_UID); | 228 DICOM_TAG_REFERENCED_SOP_INSTANCE_UID); |
228 | 229 |
229 OrthancPlugins::DicomPath contourDataPath( | 230 Orthanc::DicomPath contourDataPath( |
230 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, | 231 DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, |
231 DICOM_TAG_CONTOUR_SEQUENCE, 0, | 232 DICOM_TAG_CONTOUR_SEQUENCE, 0, |
232 DICOM_TAG_CONTOUR_DATA); | 233 DICOM_TAG_CONTOUR_DATA); |
233 | 234 |
234 for (size_t j = 0; j < countSlices; j++) | 235 for (size_t j = 0; j < countSlices; j++) |
270 contourDataPath.SetPrefixIndex(1, j); | 271 contourDataPath.SetPrefixIndex(1, j); |
271 std::string slicesData = reader.GetMandatoryStringValue(contourDataPath); | 272 std::string slicesData = reader.GetMandatoryStringValue(contourDataPath); |
272 | 273 |
273 Vector points; | 274 Vector points; |
274 if (!GenericToolbox::FastParseVector(points, slicesData) || | 275 if (!GenericToolbox::FastParseVector(points, slicesData) || |
275 points.size() != 3 * countPoints) | 276 points.size() != 3 * countPoints) |
276 { | 277 { |
277 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 278 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
278 } | 279 } |
279 | 280 |
280 // seen in real world | 281 // seen in real world |