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::Read(const std::string & filename)
148 #if GDCM_MAJOR_VERSION == 2
150 reader.SetFileName(filename.c_str());
153 const gdcm::File & file = reader.GetFile();
154 const gdcm::DataSet & ds = file.GetDataSet();
157 //Verify if the file is a RT-Structure-Set dicom file
158 gdcm::MediaStorage ms;
159 ms.SetFromFile(file);
160 if( ms != gdcm::MediaStorage::RTStructureSetStorage )
162 std::cerr << "Error. the file " << filename
163 << " 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])"
168 gdcm::Attribute<0x8,0x60> modality;
169 modality.SetFromDataSet( ds );
170 if( modality.GetValue() != "RTSTRUCT" )
172 std::cerr << "Error. the file " << filename
173 << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
179 gdcm::Attribute<0x20,0x10> studyid;
180 studyid.SetFromDataSet( ds );
181 gdcm::Attribute<0x8,0x20> studytime;
182 studytime.SetFromDataSet( ds );
183 gdcm::Attribute<0x8,0x30> studydate;
184 studydate.SetFromDataSet( ds );
185 gdcm::Attribute<0x3006,0x02> label;
186 label.SetFromDataSet( ds );
187 gdcm::Attribute<0x3006,0x04> atname;
188 atname.SetFromDataSet( ds );
189 gdcm::Attribute<0x3006,0x09> time;
190 time.SetFromDataSet( ds );
192 mStudyID = studyid.GetValue();
193 mStudyTime = studytime.GetValue();
194 mStudyDate = studydate.GetValue();
195 mLabel = label.GetValue();
196 mName = atname.GetValue();
197 mTime = time.GetValue();
199 //----------------------------------
200 // Read all ROI Names and number
201 // 0x3006,0x0020 = [ Structure Set ROI Sequence ]
202 gdcm::Tag tssroisq(0x3006,0x0020);
203 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
204 gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ssroisq.GetValueAsSQ();
205 assert(roi_seq); // TODO error message
206 for(unsigned int ridx = 0; ridx < roi_seq->GetNumberOfItems(); ++ridx)
208 gdcm::Item & item = roi_seq->GetItem( ridx + 1); // Item starts at 1
209 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
211 gdcm::Attribute<0x3006,0x26> roiname;
212 roiname.SetFromDataSet( nestedds );
213 std::string name = roiname.GetValue(); // 0x3006,0x0026 = [ROI Name]
214 gdcm::Attribute<0x3006,0x0022> roinumber;
215 roinumber.SetFromDataSet( nestedds );
216 int nb = roinumber.GetValue(); // 0x3006,0x0022 = [ROI Number]
217 // Change number if needed
221 // Check if such a number already exist
222 if (mMapOfROIName.find(nb) != mMapOfROIName.end()) {
223 std::cerr << "WARNING. A Roi already exist with the number "
224 << nb << ". I replace." << std::endl;
227 mMapOfROIName[nb] = name;
229 // DD(mMapOfROIName.size());
231 //----------------------------------
233 // 0x3006,0x0039 = [ ROI Contour Sequence ]
234 gdcm::Tag troicsq(0x3006,0x0039);
235 const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
236 gdcm::SmartPointer<gdcm::SequenceOfItems> roi_contour_seq = roicsq.GetValueAsSQ();
237 assert(roi_contour_seq); // TODO error message
239 for(unsigned int ridx = 0; ridx < roi_contour_seq->GetNumberOfItems(); ++ridx)
241 gdcm::Item & item = roi_contour_seq->GetItem( ridx + 1); // Item starts at 1
243 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
244 roi->Read(mMapOfROIName, item);
245 mListOfROI.push_back(roi);
246 mMapOfROIIndex[roi->GetROINumber()] = n;
252 reader.SetFileName(filename.c_str());
253 reader.SetMaxSizeLoadEntry(16384); // Needed ...
254 reader.SetLoadMode(gdcm::LD_NOSHADOW); // don't load shadow tags (in order to save memory)
258 //Verify if the file is a RT-Structure-Set dicom file
259 if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0016),"1.2.840.10008.5.1.4.1.1.481.3")) { //SOP clas UID
260 std::cerr << "Error. the file " << filename
261 << " 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])"
265 if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0060),"RTSTRUCT")) { //SOP clas UID
266 std::cerr << "Error. the file " << filename
267 << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
273 mStudyID = reader.GetValEntry(0x0020,0x0010)->GetValue();
274 mStudyTime = reader.GetValEntry(0x008,0x0020)->GetValue();
275 mStudyDate = reader.GetValEntry(0x008,0x0030)->GetValue();
276 mLabel = reader.GetValEntry(0x3006,0x002)->GetValue();
277 if (!reader.GetValEntry(0x3006,0x004)) {
281 mName = reader.GetValEntry(0x3006,0x004)->GetValue();
283 mTime = reader.GetValEntry(0x3006,0x009)->GetValue();
285 //----------------------------------
286 // Read all ROI Names and number
287 // 0x3006,0x0020 = [ Structure Set ROI Sequence ]
288 gdcm::SeqEntry * roi_seq=reader.GetSeqEntry(0x3006,0x0020);
289 assert(roi_seq); // TODO error message
290 for (gdcm::SQItem* r=roi_seq->GetFirstSQItem(); r!=0; r=roi_seq->GetNextSQItem()) {
291 std::string name = r->GetEntryValue(0x3006,0x0026); // 0x3006,0x0026 = [ROI Name]
292 int nb = atoi(r->GetEntryValue(0x3006,0x0022).c_str()); // 0x3006,0x0022 = [ROI Number]
293 // Change number if needed
297 // Check if such a number already exist
298 if (mMapOfROIName.find(nb) != mMapOfROIName.end()) {
299 std::cerr << "WARNING. A Roi already exist with the number "
300 << nb << ". I replace." << std::endl;
303 mMapOfROIName[nb] = name;
305 // DD(mMapOfROIName.size());
307 //----------------------------------
309 // 0x3006,0x0039 = [ ROI Contour Sequence ]
310 gdcm::SeqEntry * roi_contour_seq=reader.GetSeqEntry(0x3006,0x0039);
311 assert(roi_contour_seq); // TODO error message
313 for (gdcm::SQItem* r=roi_contour_seq->GetFirstSQItem(); r!=0; r=roi_contour_seq->GetNextSQItem()) {
314 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
315 roi->Read(mMapOfROIName, r);
316 mListOfROI.push_back(roi);
317 mMapOfROIIndex[roi->GetROINumber()] = n;
323 //--------------------------------------------------------------------
326 //--------------------------------------------------------------------
327 int clitk::DicomRT_StructureSet::AddBinaryImageAsNewROI(vvImage * im, std::string n)
329 //DD("AddBinaryImageAsNewROI");
330 // Search max ROI number
332 for(unsigned int i=0; i<mListOfROI.size(); i++) {
333 if (mListOfROI[i]->GetROINumber() > max)
334 max = mListOfROI[i]->GetROINumber();
341 std::ostringstream oss;
342 oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(n));
343 // << "_roi_" << max << vtksys::SystemTools::GetFilenameLastExtension(n);
345 mMapOfROIName[max] = oss.str();
348 std::vector<double> color;
354 DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
355 roi->SetFromBinaryImage(im, max, oss.str(), color, n);
356 mListOfROI.push_back(roi);
357 mMapOfROIIndex[mListOfROI.size()-1] = max;
358 //DD(mMapOfROIIndex[mListOfROI.size()-1]);
361 //--------------------------------------------------------------------