]> Creatis software - clitk.git/blob - common/clitkDicomRT_StructureSet.cxx
Add Write function (still to be defined)
[clitk.git] / common / clitkDicomRT_StructureSet.cxx
1 /*=========================================================================
2   Program:         vv http://www.creatis.insa-lyon.fr/rio/vv
3   Main authors :   XX XX XX
4
5   Authors belongs to:
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
9
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.
13
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
17
18   =========================================================================*/
19
20 #include "clitkDicomRT_StructureSet.h"
21 #include <vtksys/SystemTools.hxx>
22 #include "gdcmFile.h"
23 #if GDCM_MAJOR_VERSION == 2
24 #include "gdcmReader.h"
25 #include "gdcmAttribute.h"
26 #endif
27
28 //--------------------------------------------------------------------
29 clitk::DicomRT_StructureSet::DicomRT_StructureSet()
30 {
31   mStudyID = "NoStudyID";
32   mStudyTime = "NoStudyTime";
33   mStudyDate = "NoStudyDate";
34   mLabel = "NoLabel";
35   mName = "NoName";
36   mDate = "NoDate";
37   mTime = "NoTime";
38 }
39 //--------------------------------------------------------------------
40
41
42 //--------------------------------------------------------------------
43 clitk::DicomRT_StructureSet::~DicomRT_StructureSet()
44 {
45 }
46 //--------------------------------------------------------------------
47
48
49 //--------------------------------------------------------------------
50 const std::string & clitk::DicomRT_StructureSet::GetStudyID() const
51 {
52   return mStudyID;
53 }
54 //--------------------------------------------------------------------
55
56
57 //--------------------------------------------------------------------
58 const std::string & clitk::DicomRT_StructureSet::GetStudyTime() const
59 {
60   return mStudyTime;
61 }
62 //--------------------------------------------------------------------
63
64
65 //--------------------------------------------------------------------
66 const std::string & clitk::DicomRT_StructureSet::GetStudyDate() const
67 {
68   return mStudyDate;
69 }
70 //--------------------------------------------------------------------
71
72
73 //--------------------------------------------------------------------
74 const std::string & clitk::DicomRT_StructureSet::GetLabel() const
75 {
76   return mLabel;
77 }
78 //--------------------------------------------------------------------
79
80
81 //--------------------------------------------------------------------
82 const std::string & clitk::DicomRT_StructureSet::GetName() const
83 {
84   return mName;
85 }
86 //--------------------------------------------------------------------
87
88
89 //--------------------------------------------------------------------
90 const std::string & clitk::DicomRT_StructureSet::GetDate() const
91 {
92   return mDate;
93 }
94 //--------------------------------------------------------------------
95
96
97 //--------------------------------------------------------------------
98 const std::string & clitk::DicomRT_StructureSet::GetTime() const
99 {
100   return mTime;
101 }
102 //--------------------------------------------------------------------
103
104
105 //--------------------------------------------------------------------
106 const std::vector<clitk::DicomRT_ROI::Pointer> & clitk::DicomRT_StructureSet::GetListOfROI() const
107 {
108   return mListOfROI;
109 }
110 //--------------------------------------------------------------------
111
112
113 //--------------------------------------------------------------------
114 clitk::DicomRT_ROI* clitk::DicomRT_StructureSet::GetROI(int n)
115 {
116   if (mMapOfROIIndex.find(n) == mMapOfROIIndex.end()) {
117     std::cerr << "No ROI number " << n << std::endl;
118     return NULL;
119   }
120   //  DD(mListOfROI[mMapOfROIIndex[n]]->GetName());
121   //DD(mListOfROI[mMapOfROIIndex[n]]->GetROINumber());
122   return mListOfROI[mMapOfROIIndex[n]];
123 }
124 //--------------------------------------------------------------------
125
126
127 //--------------------------------------------------------------------
128 void clitk::DicomRT_StructureSet::Print(std::ostream & os) const
129 {
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);
139   }
140 }
141 //--------------------------------------------------------------------
142
143
144 //--------------------------------------------------------------------
145 void clitk::DicomRT_StructureSet::Write(const std::string & filename)
146 {
147 #if GDCM_MAJOR_VERSION == 2
148   DD("WRITE TODO");
149 #else
150   FATAL("Sorry not compatible with GDCM1, use GDCM2");
151 #endif
152 }
153 //--------------------------------------------------------------------
154
155
156 //--------------------------------------------------------------------
157 void clitk::DicomRT_StructureSet::Read(const std::string & filename)
158 {
159   // Open DICOM
160 #if GDCM_MAJOR_VERSION == 2
161   gdcm::Reader reader;
162   reader.SetFileName(filename.c_str());
163   reader.Read();
164
165   const gdcm::File & file = reader.GetFile();
166   const gdcm::DataSet & ds = file.GetDataSet();
167
168   // Check file type
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 )
173     {
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])"
176               << std::endl;
177     exit(0);
178     }
179
180   gdcm::Attribute<0x8,0x60> modality;
181   modality.SetFromDataSet( ds );
182   if( modality.GetValue() != "RTSTRUCT" )
183     {
184     std::cerr << "Error. the file " << filename
185               << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
186               << std::endl;
187     exit(0);
188     }
189
190   // Read global info
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 );
203
204   mStudyID   = studyid.GetValue();
205   mStudyTime = studytime.GetValue();
206   mStudyDate = studydate.GetValue();
207   mLabel     = label.GetValue();
208   mName      = atname.GetValue();
209   mTime      = time.GetValue();
210
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)
219     {
220     gdcm::Item & item = roi_seq->GetItem( ridx + 1); // Item starts at 1
221     const gdcm::DataSet& nestedds = item.GetNestedDataSet();
222
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
230
231     //TODO
232
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;
237     }
238     // Add in map
239     mMapOfROIName[nb] = name;
240     }
241   // DD(mMapOfROIName.size());
242
243   //----------------------------------
244   // Read all ROI
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
250   int n=0;
251   for(unsigned int ridx = 0; ridx < roi_contour_seq->GetNumberOfItems(); ++ridx)
252     {
253     gdcm::Item & item = roi_contour_seq->GetItem( ridx + 1); // Item starts at 1
254
255     DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
256     roi->Read(mMapOfROIName, item);
257     mListOfROI.push_back(roi);
258     mMapOfROIIndex[roi->GetROINumber()] = n;
259     n++;
260     }
261
262 #else
263   gdcm::File reader;
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)
267   reader.Load();
268
269   // Check file type
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])"
274               << std::endl;
275     exit(0);
276   }
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])"
280               << std::endl;
281     exit(0);
282   }
283
284   // Read global info
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)) {
290     mName = "Anonymous";
291   }
292   else {
293     mName = reader.GetValEntry(0x3006,0x004)->GetValue();
294   }
295   mTime      = reader.GetValEntry(0x3006,0x009)->GetValue();
296
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
306
307     //TODO
308
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;
313     }
314     // Add in map
315     mMapOfROIName[nb] = name;
316   }
317   // DD(mMapOfROIName.size());
318
319   //----------------------------------
320   // Read all ROI
321   // 0x3006,0x0039 = [ ROI Contour Sequence ]
322   gdcm::SeqEntry * roi_contour_seq=reader.GetSeqEntry(0x3006,0x0039);
323   assert(roi_contour_seq); // TODO error message
324   int n=0;
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;
330     n++;
331   }
332
333 #endif
334 }
335 //--------------------------------------------------------------------
336
337
338 //--------------------------------------------------------------------
339 int clitk::DicomRT_StructureSet::AddBinaryImageAsNewROI(vvImage * im, std::string n)
340 {
341   //DD("AddBinaryImageAsNewROI");
342   // Search max ROI number
343   int max = -1;
344   for(unsigned int i=0; i<mListOfROI.size(); i++) {
345     if (mListOfROI[i]->GetROINumber() > max)
346       max = mListOfROI[i]->GetROINumber();
347   }
348   //  DD(max);
349   ++max;
350   //DD(max);
351
352   // Compute name
353   std::ostringstream oss;
354   oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(n));
355   //      << "_roi_" << max << vtksys::SystemTools::GetFilenameLastExtension(n);
356   //DD(oss.str());
357   mMapOfROIName[max] = oss.str();
358
359   // Set color
360   std::vector<double> color;
361   color.push_back(1);
362   color.push_back(0);
363   color.push_back(0);
364
365   // Create ROI
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]);
371   return max;
372 }
373 //--------------------------------------------------------------------
374
375