Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkRTStructureSetReaderService.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include "mitkDicomRTIOMimeTypes.h"
16 #include <mitkDICOMIOHelper.h>
17 #include <mitkDICOMTagPath.h>
19 
20 #include "dcmtk/dcmrt/drtstrct.h"
21 
22 namespace mitk
23 {
24  RTStructureSetReaderService::RTStructureSetReaderService() : AbstractFileReader(CustomMimeType(mitk::DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_NAME()), mitk::DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_DESCRIPTION()) {
25  m_FileReaderServiceReg = RegisterService();
26  }
27 
29  {
30  }
31 
33 
34  RTStructureSetReaderService::RoiEntry::RoiEntry()
35  {
36  Number = 0;
37  DisplayColor[0] = 1.0;
38  DisplayColor[1] = 0.0;
39  DisplayColor[2] = 0.0;
41  }
42 
43  RTStructureSetReaderService::RoiEntry::RoiEntry(const RoiEntry& src)
44  {
45  Number = src.Number;
46  Name = src.Name;
47  Description = src.Description;
48  DisplayColor[0] = src.DisplayColor[0];
49  DisplayColor[1] = src.DisplayColor[1];
50  DisplayColor[2] = src.DisplayColor[2];
52  SetPolyData(src.ContourModelSet);
53  }
54 
55  RTStructureSetReaderService::RoiEntry::~RoiEntry() {}
56 
57  RTStructureSetReaderService::RoiEntry& RTStructureSetReaderService::
58  RoiEntry::operator =(const RoiEntry& src)
59  {
60  Number = src.Number;
61  Name = src.Name;
62  Description = src.Description;
63  DisplayColor[0] = src.DisplayColor[0];
64  DisplayColor[1] = src.DisplayColor[1];
65  DisplayColor[2] = src.DisplayColor[2];
66  SetPolyData(src.ContourModelSet);
67  return (*this);
68  }
69 
70  void RTStructureSetReaderService::RoiEntry::
71  SetPolyData(mitk::ContourModelSet::Pointer roiPolyData)
72  {
73  if (roiPolyData == this->ContourModelSet)
74  {
75  return;
76  }
77 
78  this->ContourModelSet = roiPolyData;
79  }
80 
81  size_t RTStructureSetReaderService::GetNumberOfROIs() const
82  {
83  return this->ROISequenceVector.size();
84  }
85 
86  RTStructureSetReaderService::RoiEntry* RTStructureSetReaderService::
87  FindRoiByNumber(unsigned int roiNum)
88  {
89  for (unsigned int i = 0; i < this->ROISequenceVector.size(); ++i)
90  {
91  if (this->ROISequenceVector[i].Number == roiNum)
92  {
93  return &this->ROISequenceVector[i];
94  }
95  }
96 
97  return nullptr;
98  }
99 
100  std::vector<itk::SmartPointer<BaseData> > RTStructureSetReaderService::Read()
101  {
102  std::vector<itk::SmartPointer<mitk::BaseData> > result;
103 
104  std::string location = GetInputLocation();
105 
107  auto tagsOfInterest = DICOMTagsOfInterestService->GetTagsOfInterest();
108  DICOMTagPathList tagsOfInterestList;
109  for (const auto& tag : tagsOfInterest) {
110  tagsOfInterestList.push_back(tag.first);
111  }
112 
113  mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
114  scanner->SetInputFiles({ location });
115  scanner->AddTagPaths(tagsOfInterestList);
116  scanner->Scan();
117 
118  mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList();
119  if (frames.empty()) {
120  MITK_ERROR << "Error reading the RTSTRUCT file" << std::endl;
121  return result;
122  }
123 
124  auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames);
125 
126  DcmFileFormat file;
127  OFCondition output = file.loadFile(location.c_str(), EXS_Unknown);
128 
129  if (output.bad())
130  {
131  MITK_ERROR << "Can't read the file" << std::endl;
132  return result;
133  }
134 
135  DcmDataset* dataset = file.getDataset();
136 
137  DRTStructureSetIOD structureSetObject;
138  OFCondition outp = structureSetObject.read(*dataset);
139 
140  if (!outp.good())
141  {
142  MITK_ERROR << "Error reading the file" << std::endl;
143  return result;
144  }
145 
146  DRTStructureSetROISequence& roiSequence =
147  structureSetObject.getStructureSetROISequence();
148 
149  if (!roiSequence.gotoFirstItem().good())
150  {
151  MITK_ERROR << "Error reading the structure sequence" << std::endl;
152  return result;
153  }
154 
155  do
156  {
157  DRTStructureSetROISequence::Item& currentSequence =
158  roiSequence.getCurrentItem();
159 
160  if (!currentSequence.isValid())
161  {
162  continue;
163  }
164 
165  OFString roiName;
166  OFString roiDescription;
167  Sint32 roiNumber;
168  RoiEntry roi;
169 
170  currentSequence.getROIName(roiName);
171  currentSequence.getROIDescription(roiDescription);
172  currentSequence.getROINumber(roiNumber);
173 
174  roi.Name = roiName.c_str();
175  roi.Description = roiDescription.c_str();
176  roi.Number = roiNumber;
177 
178  this->ROISequenceVector.push_back(roi);
179  } while (roiSequence.gotoNextItem().good());
180 
181  Sint32 refRoiNumber;
182  DRTROIContourSequence& roiContourSeqObject =
183  structureSetObject.getROIContourSequence();
184 
185  if (!roiContourSeqObject.gotoFirstItem().good())
186  {
187  MITK_ERROR << "Error reading the contour sequence" << std::endl;
188  return result;
189  }
190 
191  do
192  {
194  DRTROIContourSequence::Item& currentRoiObject =
195  roiContourSeqObject.getCurrentItem();
196 
197  if (!currentRoiObject.isValid())
198  {
199  continue;
200  }
201 
202  currentRoiObject.getReferencedROINumber(refRoiNumber);
203  DRTContourSequence& contourSeqObject =
204  currentRoiObject.getContourSequence();
205 
206  if (contourSeqObject.getNumberOfItems() > 0 && contourSeqObject.gotoFirstItem().good())
207  {
208  do
209  {
210  DRTContourSequence::Item& contourItem =
211  contourSeqObject.getCurrentItem();
212 
213  if (!contourItem.isValid())
214  {
215  continue;
216  }
217 
218  OFString contourNumber;
219  OFString numberOfPoints;
220  OFVector<Float64> contourData_LPS;
221  mitk::ContourModel::Pointer contourSequence =
223 
224  contourItem.getContourNumber(contourNumber);
225  contourItem.getNumberOfContourPoints(numberOfPoints);
226  contourItem.getContourData(contourData_LPS);
227 
228  for (unsigned int i = 0; i < contourData_LPS.size() / 3; i++)
229  {
230  mitk::Point3D point;
231  point[0] = contourData_LPS.at(3 * i);
232  point[1] = contourData_LPS.at(3 * i + 1);
233  point[2] = contourData_LPS.at(3 * i + 2);
234  contourSequence->AddVertex(point);
235  }
236 
237  contourSequence->Close();
238  contourSet->AddContourModel(contourSequence);
239  } while (contourSeqObject.gotoNextItem().good());
240  }
241  else
242  {
243  MITK_WARN << "contourSeqObject has no items in sequence. Object is neglected and not read. Struct name: " << this->FindRoiByNumber(refRoiNumber)->Name << std::endl;
244  }
245 
246  RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber);
247 
248  if (refROI == nullptr)
249  {
250  MITK_ERROR << "Can not find references ROI" << std::endl;
251  continue;
252  }
253 
254  Sint32 roiColor;
255 
256  for (unsigned int j = 0; j < 3; j++)
257  {
258  currentRoiObject.getROIDisplayColor(roiColor, j);
259  refROI->DisplayColor[j] = roiColor / 255.0;
260  }
261 
262  refROI->ContourModelSet = contourSet;
263  contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name));
264  contourSet->SetProperty("contour.color", mitk::ColorProperty::New(
265  refROI->DisplayColor[0],
266  refROI->DisplayColor[1],
267  refROI->DisplayColor[2]));
268 
269  } while (roiContourSeqObject.gotoNextItem().good());
270 
271  for (auto const& aROI : ROISequenceVector)
272  {
273  result.push_back(aROI.ContourModelSet.GetPointer());
274  result.at(result.size() - 1)->SetProperty("name", aROI.ContourModelSet->GetProperty("name"));
275  result.at(result.size() - 1)->SetProperty("color", aROI.ContourModelSet->GetProperty("contour.color"));
276  result.at(result.size() - 1)->SetProperty("contour.color", aROI.ContourModelSet->GetProperty("contour.color"));
277  SetProperties(result.at(result.size() - 1).GetPointer(), findings);
278  }
279 
280  return result;
281  }
282 
283  RTStructureSetReaderService* RTStructureSetReaderService::Clone() const
284  {
285  return new RTStructureSetReaderService(*this);
286  }
287 
288 }
MITKDICOMREADER_EXPORT FindingsListVectorType ExtractPathsOfInterest(const DICOMTagPathList &pathsOfInterest, const DICOMDatasetAccessingImageFrameList &frames)
std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
#define MITK_ERROR
Definition: mitkLogMacros.h:20
static Pointer New()
DataCollection - Class to facilitate loading/accessing structured data.
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
us::ServiceRegistration< IFileReader > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define MITK_WARN
Definition: mitkLogMacros.h:19
static Pointer New()
std::vector< DICOMTagPath > DICOMTagPathList
MITKDICOMREADER_EXPORT void SetProperties(BaseDataPointer image, const FindingsListVectorType &findings)
std::vector< DICOMDatasetAccessingImageFrameInfo::Pointer > DICOMDatasetAccessingImageFrameList
DICOMTagPathMapType GetTagsOfInterest() const override
Base class for creating mitk::BaseData objects from files or streams.
MITKDICOMREADER_EXPORT mitk::IDICOMTagsOfInterest * GetDicomTagsOfInterestService()
static Pointer New()
std::string GetInputLocation() const override
Get the current input location.
static Pointer New()