1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================*/
18 /*=========================================================================
20 Program: GDCM (Grassroots DICOM). A DICOM library
22 Copyright (c) 2006-2011 Mathieu Malaterre
24 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
26 This software is distributed WITHOUT ANY WARRANTY; without even
27 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
28 PURPOSE. See the above copyright notice for more information.
30 =========================================================================*/
31 #include "vtkGDCMPolyDataReader.h"
33 #include "vtkObjectFactory.h"
34 #include "vtkInformation.h"
35 #include "vtkInformationVector.h"
36 #include "vtkPolyData.h"
37 #include "vtkStreamingDemandDrivenPipeline.h"
38 #include "vtkDoubleArray.h"
39 #include "vtkCellArray.h"
40 #include "vtkCellData.h"
41 #include "vtkMedicalImageProperties.h"
42 #include "vtkRTStructSetProperties.h"
44 #include "gdcmReader.h"
45 #include "gdcmSmartPointer.h"
46 #include "gdcmAttribute.h"
47 #include "gdcmSequenceOfItems.h"
49 vtkCxxRevisionMacro(vtkGDCMPolyDataReader, "$Revision: 1.1 $")
50 vtkStandardNewMacro(vtkGDCMPolyDataReader)
52 //----------------------------------------------------------------------------
53 vtkGDCMPolyDataReader::vtkGDCMPolyDataReader()
55 this->FileName = NULL;
56 this->SetNumberOfInputPorts(0);
57 this->MedicalImageProperties = vtkMedicalImageProperties::New();
58 this->RTStructSetProperties = vtkRTStructSetProperties::New();
61 //----------------------------------------------------------------------------
62 vtkGDCMPolyDataReader::~vtkGDCMPolyDataReader()
65 this->MedicalImageProperties->Delete();
66 this->RTStructSetProperties->Delete();
69 //----------------------------------------------------------------------------
70 // inline keyword is needed since GetStringValueFromTag was copy/paste from vtkGDCMImageReader
71 // FIXME: need to restructure code to avoid copy/paste
72 inline const char *GetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
74 static std::string buffer;
75 buffer = ""; // cleanup previous call
77 if( ds.FindDataElement( t ) )
79 const gdcm::DataElement& de = ds.GetDataElement( t );
80 const gdcm::ByteValue *bv = de.GetByteValue();
81 if( bv ) // Can be Type 2
83 buffer = std::string( bv->GetPointer(), bv->GetLength() );
84 // Will be padded with at least one \0
88 // Since return is a const char* the very first \0 will be considered
89 return buffer.c_str();
92 //----------------------------------------------------------------------------
93 void vtkGDCMPolyDataReader::FillMedicalImageInformation(const gdcm::Reader &reader)
95 const gdcm::File &file = reader.GetFile();
96 const gdcm::DataSet &ds = file.GetDataSet();
98 this->RTStructSetProperties->SetStructureSetLabel( GetStringValueFromTag( gdcm::Tag(0x3006,0x0002), ds) );
99 this->RTStructSetProperties->SetStructureSetName( GetStringValueFromTag( gdcm::Tag(0x3006,0x0004), ds) );
100 this->RTStructSetProperties->SetStructureSetDate( GetStringValueFromTag( gdcm::Tag(0x3006,0x0008), ds) );
101 this->RTStructSetProperties->SetStructureSetTime( GetStringValueFromTag( gdcm::Tag(0x3006,0x0009), ds) );
102 this->RTStructSetProperties->SetSOPInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0008,0x0018), ds) );
103 this->RTStructSetProperties->SetStudyInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000d), ds) );
104 this->RTStructSetProperties->SetSeriesInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000e), ds) );
106 // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h
107 // For ex: DICOM (0010,0010) = DOE,JOHN
108 this->MedicalImageProperties->SetPatientName( GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds) );
109 // For ex: DICOM (0010,0020) = 1933197
110 this->MedicalImageProperties->SetPatientID( GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds) );
111 // For ex: DICOM (0010,1010) = 031Y
112 this->MedicalImageProperties->SetPatientAge( GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds) );
113 // For ex: DICOM (0010,0040) = M
114 this->MedicalImageProperties->SetPatientSex( GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
115 // For ex: DICOM (0010,0030) = 19680427
116 this->MedicalImageProperties->SetPatientBirthDate( GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
117 #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
118 // For ex: DICOM (0008,0020) = 20030617
119 this->MedicalImageProperties->SetStudyDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds) );
121 // For ex: DICOM (0008,0022) = 20030617
122 this->MedicalImageProperties->SetAcquisitionDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds) );
123 #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
124 // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012
125 this->MedicalImageProperties->SetStudyTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds) );
127 // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012
128 this->MedicalImageProperties->SetAcquisitionTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds) );
129 // For ex: DICOM (0008,0023) = 20030617
130 this->MedicalImageProperties->SetImageDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds) );
131 // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012
132 this->MedicalImageProperties->SetImageTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds) );
133 // For ex: DICOM (0020,0013) = 1
134 this->MedicalImageProperties->SetImageNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds) );
135 // For ex: DICOM (0020,0011) = 902
136 this->MedicalImageProperties->SetSeriesNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
137 // For ex: DICOM (0008,103e) = SCOUT
138 this->MedicalImageProperties->SetSeriesDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
139 // For ex: DICOM (0020,0010) = 37481
140 this->MedicalImageProperties->SetStudyID( GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
141 // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
142 this->MedicalImageProperties->SetStudyDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
143 // For ex: DICOM (0008,0060)= CT
144 this->MedicalImageProperties->SetModality( GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
145 // For ex: DICOM (0008,0070) = Siemens
146 this->MedicalImageProperties->SetManufacturer( GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds) );
147 // For ex: DICOM (0008,1090) = LightSpeed QX/i
148 this->MedicalImageProperties->SetManufacturerModelName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds) );
149 // For ex: DICOM (0008,1010) = LSPD_OC8
150 this->MedicalImageProperties->SetStationName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds) );
151 // For ex: DICOM (0008,0080) = FooCity Medical Center
152 this->MedicalImageProperties->SetInstitutionName( GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds) );
153 // For ex: DICOM (0018,1210) = Bone
154 this->MedicalImageProperties->SetConvolutionKernel( GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds) );
155 // For ex: DICOM (0018,0050) = 0.273438
156 this->MedicalImageProperties->SetSliceThickness( GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds) );
157 // For ex: DICOM (0018,0060) = 120
158 this->MedicalImageProperties->SetKVP( GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds) );
159 // For ex: DICOM (0018,1120) = 15
160 this->MedicalImageProperties->SetGantryTilt( GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds) );
161 // For ex: DICOM (0018,0081) = 105
162 this->MedicalImageProperties->SetEchoTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds) );
163 // For ex: DICOM (0018,0091) = 35
164 this->MedicalImageProperties->SetEchoTrainLength( GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds) );
165 // For ex: DICOM (0018,0080) = 2040
166 this->MedicalImageProperties->SetRepetitionTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds) );
167 // For ex: DICOM (0018,1150) = 5
168 this->MedicalImageProperties->SetExposureTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds) );
169 // For ex: DICOM (0018,1151) = 400
170 this->MedicalImageProperties->SetXRayTubeCurrent( GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds) );
171 // For ex: DICOM (0018,1152) = 114
172 this->MedicalImageProperties->SetExposure( GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds) );
174 // virtual void AddWindowLevelPreset(double w, double l);
175 // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter
176 // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth
177 gdcm::Tag twindowcenter(0x0028,0x1050);
178 gdcm::Tag twindowwidth(0x0028,0x1051);
179 if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) )
181 const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter );
182 const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth );
183 const gdcm::ByteValue *bvwc = windowcenter.GetByteValue();
184 const gdcm::ByteValue *bvww = windowwidth.GetByteValue();
185 if( bvwc && bvww ) // Can be Type 2
187 //gdcm::Attributes<0x0028,0x1050> at;
188 gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elwc;
189 std::stringstream ss1;
190 std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() );
192 gdcm::VR vr = gdcm::VR::DS;
193 unsigned int vrsize = vr.GetSizeof();
194 unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), swc.size());
195 elwc.SetLength( count * vrsize );
197 std::stringstream ss2;
198 std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() );
200 gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elww;
201 elww.SetLength( count * vrsize );
203 //assert( elww.GetLength() == elwc.GetLength() );
204 for(unsigned int i = 0; i < elwc.GetLength(); ++i)
206 this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) );
210 gdcm::Tag twindowexplanation(0x0028,0x1055);
211 if( ds.FindDataElement( twindowexplanation ) )
213 const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation );
214 const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue();
215 if( bvwe ) // Can be Type 2
217 int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets();
218 gdcm::Element<gdcm::VR::LO,gdcm::VM::VM1_n> elwe; // window explanation
219 gdcm::VR vr = gdcm::VR::LO;
220 std::stringstream ss;
222 std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() );
223 unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), swe.size()); (void)count;
224 // I found a case with only one W/L but two comments: WINDOW1\WINDOW2
225 // SIEMENS-IncompletePixelData.dcm
226 //assert( count >= (unsigned int)n );
227 elwe.SetLength( /*count*/ n * vr.GetSizeof() );
230 for(int i = 0; i < n; ++i)
232 this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() );
238 // gdcmData/JDDICOM_Sample4.dcm
239 // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality
240 gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage;
241 ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality );
242 gdcm::MediaStorage ms2;
243 ms2.SetFromFile( reader.GetFile() );
244 if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage )
246 vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality()
247 << " Will be set instead to the known one: " << ms2.GetModality() )
248 this->MedicalImageProperties->SetModality( ms2.GetModality() );
256 //(3006,0022) ?? (IS) [2 ] # 2,1 ROI Number
257 //(3006,0024) ?? (UI) [2.16.840.1.114362.1.759508.1251415878280.193] # 44,1 Referenced Frame of Reference UID
258 //(3006,0026) ?? (LO) [Bladder ] # 8,1 ROI Name
259 //(3006,0036) ?? (CS) [MANUAL] # 6,1 ROI Generation Algorithm
261 int vtkGDCMPolyDataReader::RequestData_RTStructureSetStorage(gdcm::Reader const &reader,
262 vtkInformationVector *outputVector)
264 // This is done in RequestInformation
265 // gdcm::MediaStorage ms;
266 // ms.SetFromFile( reader.GetFile() );
267 // //std::cout << ms << std::endl;
268 // if( ms != gdcm::MediaStorage::RTStructureSetStorage )
273 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
274 // (3006,0010) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedFrameOfReferenceSequence
275 // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
276 // (3006,0039) SQ (Sequence with explicit length #=4) # 24216, 1 ROIContourSequence
277 gdcm::Tag troicsq(0x3006,0x0039);
278 if( !ds.FindDataElement( troicsq ) )
282 gdcm::Tag tssroisq(0x3006,0x0020);
283 if( !ds.FindDataElement( tssroisq ) )
287 gdcm::Tag trefframerefsq(0x3006,0x0010);
288 if( !ds.FindDataElement( trefframerefsq ) )
292 const gdcm::DataElement &refframerefsq = ds.GetDataElement( trefframerefsq );
293 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0 = refframerefsq.GetValueAsSQ();
294 if( !sqi0 || !sqi0->GetNumberOfItems() )
298 assert( sqi0->GetNumberOfItems() == 1 );
299 for(unsigned int pd = 0; pd < sqi0->GetNumberOfItems(); ++pd)
301 const gdcm::Item & item = sqi0->GetItem(pd+1); // Item start at #1
302 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
303 // (3006,0012) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedStudySequence
304 gdcm::Attribute<0x0020,0x052> frameofreferenceuid;
305 frameofreferenceuid.SetFromDataSet( nestedds );
306 this->RTStructSetProperties->SetReferenceFrameOfReferenceUID(
307 frameofreferenceuid.GetValue() );
308 gdcm::Tag trtrefstudysq(0x3006,0x0012);
309 if( !nestedds.FindDataElement( trtrefstudysq) )
313 const gdcm::DataElement &rtrefstudysq = nestedds.GetDataElement( trtrefstudysq );
314 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi00 = rtrefstudysq.GetValueAsSQ();
315 if( !sqi00 || !sqi00->GetNumberOfItems() )
319 assert( sqi00->GetNumberOfItems() == 1 );
320 for(unsigned int pd0 = 0; pd0 < sqi00->GetNumberOfItems(); ++pd0)
322 const gdcm::Item & item = sqi00->GetItem(pd0+1); // Item start at #1
323 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
325 // (3006,0014) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedSeriesSequence
326 gdcm::Tag trtrefseriessq(0x3006,0x0014);
327 if( !nestedds.FindDataElement( trtrefseriessq) )
331 const gdcm::DataElement &rtrefseriessq = nestedds.GetDataElement( trtrefseriessq);
333 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi000 = rtrefseriessq.GetValueAsSQ();
334 if( !sqi000 || !sqi000->GetNumberOfItems() )
338 assert( sqi000->GetNumberOfItems() == 1 );
339 for(unsigned int pd00 = 0; pd00 < sqi000->GetNumberOfItems(); ++pd00)
341 const gdcm::Item & item = sqi000->GetItem(pd00+1); // Item start at #1
342 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
344 gdcm::Attribute<0x0020,0x000e> seriesinstanceuid;
345 seriesinstanceuid.SetFromDataSet( nestedds );
346 this->RTStructSetProperties->SetReferenceSeriesInstanceUID(
347 seriesinstanceuid.GetValue() );
350 // (3006,0016) SQ (Sequence with undefined length #=162) # u/l, 1 ContourImageSequence
351 gdcm::Tag tcontourimageseq(0x3006,0x0016);
352 if( !nestedds.FindDataElement( tcontourimageseq) )
356 const gdcm::DataElement &contourimageseq = nestedds.GetDataElement( tcontourimageseq );
357 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0000 = contourimageseq.GetValueAsSQ();
358 if( !sqi0000 || !sqi0000->GetNumberOfItems() )
363 assert( sqi0000->GetNumberOfItems() != 1 );
364 for(unsigned int pd000 = 0; pd000 < sqi0000->GetNumberOfItems(); ++pd000)
366 const gdcm::Item & item = sqi0000->GetItem(pd000+1); // Item start at #1
367 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
368 gdcm::Attribute<0x0008,0x1150> refsopclassuid;
369 refsopclassuid.SetFromDataSet( nestedds );
370 gdcm::Attribute<0x0008,0x1155> refinstanceuid;
371 refinstanceuid.SetFromDataSet( nestedds );
372 this->RTStructSetProperties->AddReferencedFrameOfReference( refsopclassuid.GetValue().c_str(),
373 refinstanceuid.GetValue().c_str() );
381 const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
382 //std::cout << roicsq << std::endl;
383 //const gdcm::SequenceOfItems *sqi_debug = roicsq.GetSequenceOfItems();
384 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = roicsq.GetValueAsSQ();
385 if( !sqi || !sqi->GetNumberOfItems() )
389 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
390 //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems();
391 gdcm::SmartPointer<gdcm::SequenceOfItems> ssqi = ssroisq.GetValueAsSQ();
392 if( !ssqi || !ssqi->GetNumberOfItems() )
397 // For each Item in the DataSet create a vtkPolyData
398 for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd)
400 //StructureSetROI structuresetroi;
401 // get the info object
402 vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
405 vtkPolyData *output = vtkPolyData::SafeDownCast(
406 outInfo1->Get(vtkDataObject::DATA_OBJECT()));
409 const gdcm::Item & item = sqi->GetItem(pd+1); // Item start at #1
410 //std::cout << item << std::endl;
411 const gdcm::Item & sitem = ssqi->GetItem(pd+1); // Item start at #1
412 const gdcm::DataSet& snestedds = sitem.GetNestedDataSet();
413 // (3006,0026) ?? (LO) [date] # 4,1 ROI Name
414 gdcm::Tag stcsq(0x3006,0x0026);
415 if( !snestedds.FindDataElement( stcsq ) )
419 const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq );
420 std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
421 //structuresetroi.ROIName = s;
422 gdcm::Attribute<0x3006,0x0022> roinumber;
423 roinumber.SetFromDataSet( snestedds );
424 //structuresetroi.ROINumber = roinumber.GetValue();
425 gdcm::Attribute<0x3006,0x0024> refframeuid;
426 refframeuid.SetFromDataSet( snestedds );
427 //structuresetroi.RefFrameRefUID = refframeuid.GetValue();
428 gdcm::Attribute<0x3006,0x0026> roiname;
429 roiname.SetFromDataSet( snestedds );
430 assert( s == roiname.GetValue() );
431 gdcm::Attribute<0x3006,0x0036> roigenalg;
432 roigenalg.SetFromDataSet( snestedds );
433 //structuresetroi.ROIGenerationAlgorithm = roigenalg.GetValue();
434 //structuresetrois.push_back( structuresetroi );
436 this->RTStructSetProperties->AddStructureSetROI(
437 roinumber.GetValue(),
438 refframeuid.GetValue(),
443 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
444 //std::cout << nestedds << std::endl;
445 //(3006,002a) IS [255\192\96] # 10,3 ROI Display Color
446 gdcm::Tag troidc(0x3006,0x002a);
447 gdcm::Attribute<0x3006,0x002a> color = {};
448 if( nestedds.FindDataElement( troidc) )
450 const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc );
451 color.SetFromDataElement( decolor );
452 //std::cout << "color:" << color[0] << "," << color[1] << "," << color[2] << std::endl;
454 //(3006,0040) SQ (Sequence with explicit length #=8) # 4326, 1 ContourSequence
455 gdcm::Tag tcsq(0x3006,0x0040);
456 if( !nestedds.FindDataElement( tcsq ) )
460 const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq );
461 //std::cout << csq << std::endl;
463 //const gdcm::SequenceOfItems *sqi2 = csq.GetSequenceOfItems();
464 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi2 = csq.GetValueAsSQ();
465 if( !sqi2 || !sqi2->GetNumberOfItems() )
469 unsigned int nitems = sqi2->GetNumberOfItems();
470 //std::cout << nitems << std::endl;
471 //this->SetNumberOfOutputPorts(nitems);
472 vtkDoubleArray *scalars = vtkDoubleArray::New();
473 scalars->SetNumberOfComponents(3);
475 vtkPoints *newPts = vtkPoints::New();
476 //std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
477 //std::cout << s << std::endl;
478 //newPts->GetData()->SetName( s.c_str() );
479 // In VTK there is no API to specify the name of a vtkPolyData, you can only specify Name
480 // for the scalars (pointdata or celldata), so let's do that...
481 //scalars->SetName( structuresetroi.ROIName.c_str() );
482 scalars->SetName( roiname.GetValue().c_str() );
483 vtkCellArray *polys = vtkCellArray::New();
484 for(unsigned int i = 0; i < nitems; ++i)
486 const gdcm::Item & item2 = sqi2->GetItem(i+1); // Item start at #1
488 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet();
489 //std::cout << nestedds2 << std::endl;
490 // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData
491 gdcm::Tag tcontourdata(0x3006,0x0050);
492 const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata );
493 //std::cout << contourdata << std::endl;
495 //const gdcm::ByteValue *bv = contourdata.GetByteValue();
496 gdcm::Attribute<0x3006,0x0042> contgeotype;
497 contgeotype.SetFromDataSet( nestedds2 );
498 assert( contgeotype.GetValue() == "CLOSED_PLANAR " );
500 gdcm::Attribute<0x3006,0x0046> numcontpoints;
501 numcontpoints.SetFromDataSet( nestedds2 );
503 gdcm::Attribute<0x3006,0x0050> at;
504 at.SetFromDataElement( contourdata );
507 assert( nestedds2.FindDataElement( gdcm::Tag(0x3006,0x0016) ) );
508 const gdcm::DataElement &contourimagesequence = nestedds2.GetDataElement( gdcm::Tag(0x3006,0x0016) );
509 gdcm::SmartPointer<gdcm::SequenceOfItems> contourimagesequence_sqi = contourimagesequence.GetValueAsSQ();
510 assert( contourimagesequence_sqi && contourimagesequence_sqi->GetNumberOfItems() == 1 );
511 const gdcm::Item & theitem = contourimagesequence_sqi->GetItem(1);
512 const gdcm::DataSet& nestedds = theitem.GetNestedDataSet();
514 gdcm::Attribute<0x0008,0x1150> classat;
515 classat.SetFromDataSet( nestedds );
516 gdcm::Attribute<0x0008,0x1155> instat;
517 instat.SetFromDataSet( nestedds );
519 this->RTStructSetProperties->AddContourReferencedFrameOfReference( pd,
520 classat.GetValue(), instat.GetValue() );
523 //newPts->SetNumberOfPoints( at.GetNumberOfValues() / 3 );
524 //assert( at.GetNumberOfValues() % 3 == 0); // FIXME
525 const double* pts = at.GetValues();
526 vtkIdType buffer[256];
528 unsigned int npts = at.GetNumberOfValues() / 3;
529 assert( npts == numcontpoints.GetValue() );
532 ptIds = new vtkIdType[npts];
538 for(unsigned int i = 0; i < npts * 3; i+=3)
544 vtkIdType ptId = newPts->InsertNextPoint( x );
547 // Each Contour Data is in fact a Cell:
548 vtkIdType cellId = polys->InsertNextCell( npts , ptIds);
549 scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0);
555 output->SetPoints(newPts);
557 output->SetPolys(polys);
559 output->GetCellData()->SetScalars(scalars);
563 // Add the Observations:
564 // we can only be doing it here once all RT are loaded, since we will
565 // attach observation to *existing* rtstruct
566 gdcm::Tag trtroiobssq(0x3006,0x0080);
567 if( !ds.FindDataElement( trtroiobssq ) )
571 const gdcm::DataElement &rtroiobssq = ds.GetDataElement( trtroiobssq );
572 gdcm::SmartPointer<gdcm::SequenceOfItems> rtroiobssqsqi = rtroiobssq.GetValueAsSQ();
573 if( !rtroiobssqsqi || !rtroiobssqsqi->GetNumberOfItems() )
577 for(unsigned int obs = 0; obs < rtroiobssqsqi->GetNumberOfItems(); ++obs)
579 const gdcm::Item & item = rtroiobssqsqi->GetItem(obs+1); // Item start at #1
580 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
581 gdcm::Attribute<0x3006,0x0082> observationnumber;
582 observationnumber.SetFromDataSet( nestedds );
583 gdcm::Attribute<0x3006,0x0084> referencedroinumber;
584 referencedroinumber.SetFromDataSet( nestedds );
585 gdcm::Attribute<0x3006,0x00a4> rtroiinterpretedtype;
586 rtroiinterpretedtype.SetFromDataSet( nestedds );
587 gdcm::Attribute<0x3006,0x00a6> roiinterpreter;
588 roiinterpreter.SetFromDataSet( nestedds );
589 this->RTStructSetProperties->
590 AddStructureSetROIObservation( referencedroinumber.GetValue(),
591 observationnumber.GetValue(),
592 rtroiinterpretedtype.GetValue(),
593 roiinterpreter.GetValue() );
599 int vtkGDCMPolyDataReader::RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader,
600 vtkInformationVector *outputVector)
602 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
603 // (5400,0100) SQ (Sequence with undefined length #=1) # u/l, 1 WaveformSequence
604 gdcm::Tag twsq(0x5400,0x0100);
605 if( !ds.FindDataElement( twsq) )
609 const gdcm::DataElement &wsq = ds.GetDataElement( twsq );
610 //std::cout << wsq << std::endl;
611 //const gdcm::SequenceOfItems *sqi = wsq.GetSequenceOfItems();
612 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = wsq.GetValueAsSQ();
613 if( !sqi || !sqi->GetNumberOfItems() )
618 const gdcm::Item & item = sqi->GetItem(1); // Item start at #1
619 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
621 // (5400,1004) US 16 # 2, 1 WaveformBitsAllocated
622 gdcm::Tag twba(0x5400,0x1004);
623 if( !nestedds.FindDataElement( twba ) )
627 const gdcm::DataElement &wba= nestedds.GetDataElement( twba );
629 //std::cout << wba << std::endl;
630 // (5400,1006) CS [SS] # 2, 1 WaveformSampleInterpretation
631 // (5400,1010) OW 00ba\0030\ff76\ff8b\00a2\ffd3\ffae\ff50\0062\00c4\011e\00c2\00ba... # 57600, 1 WaveformData
632 gdcm::Tag twd(0x5400,0x1010);
633 if( !nestedds.FindDataElement( twd ) )
637 const gdcm::DataElement &wd = nestedds.GetDataElement( twd );
638 const gdcm::ByteValue *bv = wd.GetByteValue();
639 size_t len = bv->GetLength();
640 int16_t *p = (int16_t*)bv;
642 // get the info object
644 vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
647 vtkPolyData *output = vtkPolyData::SafeDownCast(
648 outInfo1->Get(vtkDataObject::DATA_OBJECT()));
650 vtkPoints *newPts = vtkPoints::New();
651 size_t npts = len / 2;
652 //npts = 10; // DEBUG !
653 for(size_t i = 0; i < npts; ++i )
656 x[0] = (float)p[i] / 8800;
657 //std::cout << p[i] << std::endl;
660 vtkIdType ptId = newPts->InsertNextPoint( x );
662 output->SetPoints(newPts);
665 vtkCellArray* lines = vtkCellArray::New();
666 for ( int i = 0; i < newPts->GetNumberOfPoints() - 1; ++i )
671 lines->InsertNextCell( 2, topol );
674 output->SetLines(lines);
676 output->BuildCells();
677 //output->GetCellData()->SetScalars(scalars);
683 //----------------------------------------------------------------------------
684 int vtkGDCMPolyDataReader::RequestData(
685 vtkInformation *vtkNotUsed(request),
686 vtkInformationVector **vtkNotUsed(inputVector),
687 vtkInformationVector *outputVector)
689 vtkInformation *outInfo = outputVector->GetInformationObject(0);
690 //vtkPoints *newPts, *mergedPts;
691 //vtkCellArray *newPolys, *mergedPolys;
692 //vtkFloatArray *newScalars=0, *mergedScalars=0;
694 // All of the data in the first piece.
695 if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
700 if ( !this->FileName || !*this->FileName )
702 vtkErrorMacro(<<"A FileName must be specified.");
707 reader.SetFileName( this->FileName );
713 gdcm::MediaStorage ms;
714 ms.SetFromFile( reader.GetFile() );
717 if( ms == gdcm::MediaStorage::RTStructureSetStorage )
719 ret = this->RequestData_RTStructureSetStorage(reader, outputVector);
721 else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
723 ret = this->RequestData_HemodynamicWaveformStorage(reader, outputVector);
727 // not handled assume error
734 int vtkGDCMPolyDataReader::RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader)
736 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
737 // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
738 gdcm::Tag tssroisq(0x3006,0x0020);
739 if( !ds.FindDataElement( tssroisq ) )
744 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
745 //const gdcm::SequenceOfItems *sqi = ssroisq.GetSequenceOfItems();
746 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = ssroisq.GetValueAsSQ();
747 if( !sqi || !sqi->GetNumberOfItems() )
751 unsigned int npds = sqi->GetNumberOfItems();
753 //std::cout << "Nb pd:" << npds << std::endl;
754 this->SetNumberOfOutputPorts( npds );
757 for(unsigned int i = 1; i < npds; ++i) // first output is allocated for us
759 vtkPolyData *output2 = vtkPolyData::New();
760 this->GetExecutive()->SetOutputData(i, output2);
766 int vtkGDCMPolyDataReader::RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader)
771 //----------------------------------------------------------------------------
772 int vtkGDCMPolyDataReader::RequestInformation(
773 vtkInformation *vtkNotUsed(request),
774 vtkInformationVector **vtkNotUsed(inputVector),
775 vtkInformationVector *outputVector)
777 // get the info object
778 // vtkInformation *outInfo = outputVector->GetInformationObject(0);
780 // outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
783 reader.SetFileName( this->FileName );
789 gdcm::MediaStorage ms;
790 ms.SetFromFile( reader.GetFile() );
793 if( ms == gdcm::MediaStorage::RTStructureSetStorage )
795 ret = this->RequestInformation_RTStructureSetStorage(reader);
797 else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
799 ret = this->RequestInformation_HemodynamicWaveformStorage(reader);
803 // not handled assume error
809 // Ok let's fill in the 'extra' info:
810 this->FillMedicalImageInformation(reader);
817 //----------------------------------------------------------------------------
818 void vtkGDCMPolyDataReader::PrintSelf(ostream& os, vtkIndent indent)
820 this->Superclass::PrintSelf(os,indent);
822 os << indent << "File Name: "
823 << (this->FileName ? this->FileName : "(none)") << "\n";