1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
3 Main authors : XX XX XX
6 - University of LYON http://www.universite-lyon.fr/
7 - Léon Bérard cancer center http://www.centreleonberard.fr
8 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the copyright notices for more information.
14 It is distributed under dual licence
15 - BSD http://www.opensource.org/licenses/bsd-license.php
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
18 =========================================================================*/
20 #include "clitkDicomRT_StructureSet.h"
21 #include <vtksys/SystemTools.hxx>
23 #if GDCM_MAJOR_VERSION == 2
24 #include "gdcmReader.h"
25 #include "gdcmAttribute.h"
28 //--------------------------------------------------------------------
29 clitk::DicomRT_StructureSet::DicomRT_StructureSet()
31 mStudyID = "NoStudyID";
32 mStudyTime = "NoStudyTime";
33 mStudyDate = "NoStudyDate";
39 //--------------------------------------------------------------------
42 //--------------------------------------------------------------------
43 clitk::DicomRT_StructureSet::~DicomRT_StructureSet()
46 //--------------------------------------------------------------------
49 //--------------------------------------------------------------------
50 const std::string & clitk::DicomRT_StructureSet::GetStudyID() const
54 //--------------------------------------------------------------------
57 //--------------------------------------------------------------------
58 const std::string & clitk::DicomRT_StructureSet::GetStudyTime() const
62 //--------------------------------------------------------------------
65 //--------------------------------------------------------------------
66 const std::string & clitk::DicomRT_StructureSet::GetStudyDate() const
70 //--------------------------------------------------------------------
73 //--------------------------------------------------------------------
74 const std::string & clitk::DicomRT_StructureSet::GetLabel() const
78 //--------------------------------------------------------------------
81 //--------------------------------------------------------------------
82 const std::string & clitk::DicomRT_StructureSet::GetName() const
86 //--------------------------------------------------------------------
89 //--------------------------------------------------------------------
90 const std::string & clitk::DicomRT_StructureSet::GetDate() const
94 //--------------------------------------------------------------------
97 //--------------------------------------------------------------------
98 const std::string & clitk::DicomRT_StructureSet::GetTime() const
102 //--------------------------------------------------------------------
105 //--------------------------------------------------------------------
106 const std::vector<clitk::DicomRT_ROI::Pointer> & clitk::DicomRT_StructureSet::GetListOfROI() const
110 //--------------------------------------------------------------------
113 //--------------------------------------------------------------------
114 clitk::DicomRT_ROI* clitk::DicomRT_StructureSet::GetROI(int n)
116 if (mMapOfROIIndex.find(n) == mMapOfROIIndex.end()) {
117 std::cerr << "No ROI number " << n << std::endl;
120 // DD(mListOfROI[mMapOfROIIndex[n]]->GetName());
121 //DD(mListOfROI[mMapOfROIIndex[n]]->GetROINumber());
122 return mListOfROI[mMapOfROIIndex[n]];
124 //--------------------------------------------------------------------
127 //--------------------------------------------------------------------
128 void clitk::DicomRT_StructureSet::Print(std::ostream & os) const
130 os << "Study ID = " << mStudyID << std::endl
131 << "Study Date = " << mStudyDate << std::endl
132 << "Study Time = " << mStudyTime << std::endl
133 << "Struct Label = " << mLabel << std::endl
134 << "Struct Name = " << mName << std::endl
135 << "Struct Time = " << mTime << std::endl
136 << "Number of ROI = " << mListOfROI.size() << std::endl;
137 for(unsigned int i=0; i<mListOfROI.size(); i++) {
138 mListOfROI[i]->Print(os);
141 //--------------------------------------------------------------------
144 //--------------------------------------------------------------------
145 void clitk::DicomRT_StructureSet::Write(const std::string & filename)
147 #if GDCM_MAJOR_VERSION == 2
150 FATAL("Sorry not compatible with GDCM1, use GDCM2");
153 //--------------------------------------------------------------------
156 //--------------------------------------------------------------------
157 void clitk::DicomRT_StructureSet::Read(const std::string & filename)
160 #if GDCM_MAJOR_VERSION == 2
162 reader.SetFileName(filename.c_str());
165 const gdcm::File & file = reader.GetFile();
166 const gdcm::DataSet & ds = file.GetDataSet();
169 //Verify if the file is a RT-Structure-Set dicom file
170 gdcm::MediaStorage ms;
171 ms.SetFromFile(file);
172 if( ms != gdcm::MediaStorage::RTStructureSetStorage )
174 std::cerr << "Error. the file " << filename
175 << " is not a Dicom Struct ? (must have a SOP Class UID [0008|0016] = 1.2.840.10008.5.1.4.1.1.481.3 ==> [RT Structure Set Storage])"
180 gdcm::Attribute<0x8,0x60> modality;
181 modality.SetFromDataSet( ds );
182 if( modality.GetValue() != "RTSTRUCT" )
184 std::cerr << "Error. the file " << filename
185 << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
191 gdcm::Attribute<0x20,0x10> studyid;
192 studyid.SetFromDataSet( ds );
193 gdcm::Attribute<0x8,0x20> studytime;
194 studytime.SetFromDataSet( ds );
195 gdcm::Attribute<0x8,0x30> studydate;
196 studydate.SetFromDataSet( ds );
197 gdcm::Attribute<0x3006,0x02> label;
198 label.SetFromDataSet( ds );
199 gdcm::Attribute<0x3006,0x04> atname;
200 atname.SetFromDataSet( ds );
201 gdcm::Attribute<0x3006,0x09> time;
202 time.SetFromDataSet( ds );
204 mStudyID = studyid.GetValue();
205 mStudyTime = studytime.GetValue();
206 mStudyDate = studydate.GetValue();
207 mLabel = label.GetValue();
208 mName = atname.GetValue();
209 mTime = time.GetValue();
211 //----------------------------------
212 // Read all ROI Names and number
213 // 0x3006,0x0020 = [ Structure Set ROI Sequence ]
214 gdcm::Tag tssroisq(0x3006,0x0020);
215 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
216 gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ssroisq.GetValueAsSQ();
217 assert(roi_seq); // TODO error message
218 for(unsigned int ridx = 0; ridx < roi_seq->GetNumberOfItems(); ++ridx)
220 gdcm::Item & item = roi_seq->GetItem( ridx + 1); // Item starts at 1
221 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
223 gdcm::Attribute<0x3006,0x26> roiname;
224 roiname.SetFromDataSet( nestedds );
225 std::string name = roiname.GetValue(); // 0x3006,0x0026 = [ROI Name]
226 gdcm::Attribute<0x3006,0x0022> roinumber;
227 roinumber.SetFromDataSet( nestedds );
228 int nb = roinumber.GetValue(); // 0x3006,0x0022 = [ROI Number]
229 // Change number if needed
233 // Check if such a number already exist
234 if (mMapOfROIName.find(nb) != mMapOfROIName.end()) {
235 std::cerr << "WARNING. A Roi already exist with the number "
236 << nb << ". I replace." << std::endl;
239 mMapOfROIName[nb] = name;
241 // DD(mMapOfROIName.size());
243 //----------------------------------
245 // 0x3006,0x0039 = [ ROI Contour Sequence ]
246 gdcm::Tag troicsq(0x3006,0x0039);
247 const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
248 gdcm::SmartPointer<gdcm::SequenceOfItems> roi_contour_seq = roicsq.GetValueAsSQ();
249 assert(roi_contour_seq); // TODO error message
251 for(unsigned int ridx = 0; ridx < roi_contour_seq->GetNumberOfItems(); ++ridx)
253 gdcm::Item & item = roi_contour_seq->GetItem( ridx + 1); // Item starts at 1
255 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
256 roi->Read(mMapOfROIName, item);
257 mListOfROI.push_back(roi);
258 mMapOfROIIndex[roi->GetROINumber()] = n;
264 reader.SetFileName(filename.c_str());
265 reader.SetMaxSizeLoadEntry(16384); // Needed ...
266 reader.SetLoadMode(gdcm::LD_NOSHADOW); // don't load shadow tags (in order to save memory)
270 //Verify if the file is a RT-Structure-Set dicom file
271 if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0016),"1.2.840.10008.5.1.4.1.1.481.3")) { //SOP clas UID
272 std::cerr << "Error. the file " << filename
273 << " is not a Dicom Struct ? (must have a SOP Class UID [0008|0016] = 1.2.840.10008.5.1.4.1.1.481.3 ==> [RT Structure Set Storage])"
277 if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0060),"RTSTRUCT")) { //SOP clas UID
278 std::cerr << "Error. the file " << filename
279 << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
285 mStudyID = reader.GetValEntry(0x0020,0x0010)->GetValue();
286 mStudyTime = reader.GetValEntry(0x008,0x0020)->GetValue();
287 mStudyDate = reader.GetValEntry(0x008,0x0030)->GetValue();
288 mLabel = reader.GetValEntry(0x3006,0x002)->GetValue();
289 if (!reader.GetValEntry(0x3006,0x004)) {
293 mName = reader.GetValEntry(0x3006,0x004)->GetValue();
295 mTime = reader.GetValEntry(0x3006,0x009)->GetValue();
297 //----------------------------------
298 // Read all ROI Names and number
299 // 0x3006,0x0020 = [ Structure Set ROI Sequence ]
300 gdcm::SeqEntry * roi_seq=reader.GetSeqEntry(0x3006,0x0020);
301 assert(roi_seq); // TODO error message
302 for (gdcm::SQItem* r=roi_seq->GetFirstSQItem(); r!=0; r=roi_seq->GetNextSQItem()) {
303 std::string name = r->GetEntryValue(0x3006,0x0026); // 0x3006,0x0026 = [ROI Name]
304 int nb = atoi(r->GetEntryValue(0x3006,0x0022).c_str()); // 0x3006,0x0022 = [ROI Number]
305 // Change number if needed
309 // Check if such a number already exist
310 if (mMapOfROIName.find(nb) != mMapOfROIName.end()) {
311 std::cerr << "WARNING. A Roi already exist with the number "
312 << nb << ". I replace." << std::endl;
315 mMapOfROIName[nb] = name;
317 // DD(mMapOfROIName.size());
319 //----------------------------------
321 // 0x3006,0x0039 = [ ROI Contour Sequence ]
322 gdcm::SeqEntry * roi_contour_seq=reader.GetSeqEntry(0x3006,0x0039);
323 assert(roi_contour_seq); // TODO error message
325 for (gdcm::SQItem* r=roi_contour_seq->GetFirstSQItem(); r!=0; r=roi_contour_seq->GetNextSQItem()) {
326 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
327 roi->Read(mMapOfROIName, r);
328 mListOfROI.push_back(roi);
329 mMapOfROIIndex[roi->GetROINumber()] = n;
335 //--------------------------------------------------------------------
338 //--------------------------------------------------------------------
339 int clitk::DicomRT_StructureSet::AddBinaryImageAsNewROI(vvImage * im, std::string n)
341 //DD("AddBinaryImageAsNewROI");
342 // Search max ROI number
344 for(unsigned int i=0; i<mListOfROI.size(); i++) {
345 if (mListOfROI[i]->GetROINumber() > max)
346 max = mListOfROI[i]->GetROINumber();
353 std::ostringstream oss;
354 oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(n));
355 // << "_roi_" << max << vtksys::SystemTools::GetFilenameLastExtension(n);
357 mMapOfROIName[max] = oss.str();
360 std::vector<double> color;
366 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
367 roi->SetFromBinaryImage(im, max, oss.str(), color, n);
368 mListOfROI.push_back(roi);
369 mMapOfROIIndex[mListOfROI.size()-1] = max;
370 //DD(mMapOfROIIndex[mListOfROI.size()-1]);
373 //--------------------------------------------------------------------