1 /*=========================================================================
3 Program: GDCM (Grassroots DICOM). A DICOM library
5 Copyright (c) 2006-2011 Mathieu Malaterre
7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
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 above copyright notice for more information.
13 =========================================================================*/
14 #include "vtkGDCMPolyDataReader.h"
16 #include "vtkObjectFactory.h"
17 #include "vtkInformation.h"
18 #include "vtkInformationVector.h"
19 #include "vtkPolyData.h"
20 #include "vtkStreamingDemandDrivenPipeline.h"
21 #include "vtkDoubleArray.h"
22 #include "vtkCellArray.h"
23 #include "vtkCellData.h"
24 #include "vtkMedicalImageProperties.h"
25 #include "vtkRTStructSetProperties.h"
27 #include "gdcmReader.h"
28 #include "gdcmSmartPointer.h"
29 #include "gdcmAttribute.h"
30 #include "gdcmSequenceOfItems.h"
32 vtkCxxRevisionMacro(vtkGDCMPolyDataReader, "$Revision: 1.1 $")
33 vtkStandardNewMacro(vtkGDCMPolyDataReader)
35 //----------------------------------------------------------------------------
36 vtkGDCMPolyDataReader::vtkGDCMPolyDataReader()
38 this->FileName = NULL;
39 this->SetNumberOfInputPorts(0);
40 this->MedicalImageProperties = vtkMedicalImageProperties::New();
41 this->RTStructSetProperties = vtkRTStructSetProperties::New();
44 //----------------------------------------------------------------------------
45 vtkGDCMPolyDataReader::~vtkGDCMPolyDataReader()
48 this->MedicalImageProperties->Delete();
49 this->RTStructSetProperties->Delete();
52 //----------------------------------------------------------------------------
53 // inline keyword is needed since GetStringValueFromTag was copy/paste from vtkGDCMImageReader
54 // FIXME: need to restructure code to avoid copy/paste
55 inline const char *GetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
57 static std::string buffer;
58 buffer = ""; // cleanup previous call
60 if( ds.FindDataElement( t ) )
62 const gdcm::DataElement& de = ds.GetDataElement( t );
63 const gdcm::ByteValue *bv = de.GetByteValue();
64 if( bv ) // Can be Type 2
66 buffer = std::string( bv->GetPointer(), bv->GetLength() );
67 // Will be padded with at least one \0
71 // Since return is a const char* the very first \0 will be considered
72 return buffer.c_str();
75 //----------------------------------------------------------------------------
76 void vtkGDCMPolyDataReader::FillMedicalImageInformation(const gdcm::Reader &reader)
78 const gdcm::File &file = reader.GetFile();
79 const gdcm::DataSet &ds = file.GetDataSet();
81 this->RTStructSetProperties->SetStructureSetLabel( GetStringValueFromTag( gdcm::Tag(0x3006,0x0002), ds) );
82 this->RTStructSetProperties->SetStructureSetName( GetStringValueFromTag( gdcm::Tag(0x3006,0x0004), ds) );
83 this->RTStructSetProperties->SetStructureSetDate( GetStringValueFromTag( gdcm::Tag(0x3006,0x0008), ds) );
84 this->RTStructSetProperties->SetStructureSetTime( GetStringValueFromTag( gdcm::Tag(0x3006,0x0009), ds) );
85 this->RTStructSetProperties->SetSOPInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0008,0x0018), ds) );
86 this->RTStructSetProperties->SetStudyInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000d), ds) );
87 this->RTStructSetProperties->SetSeriesInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000e), ds) );
89 // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h
90 // For ex: DICOM (0010,0010) = DOE,JOHN
91 this->MedicalImageProperties->SetPatientName( GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds) );
92 // For ex: DICOM (0010,0020) = 1933197
93 this->MedicalImageProperties->SetPatientID( GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds) );
94 // For ex: DICOM (0010,1010) = 031Y
95 this->MedicalImageProperties->SetPatientAge( GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds) );
96 // For ex: DICOM (0010,0040) = M
97 this->MedicalImageProperties->SetPatientSex( GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
98 // For ex: DICOM (0010,0030) = 19680427
99 this->MedicalImageProperties->SetPatientBirthDate( GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
100 #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
101 // For ex: DICOM (0008,0020) = 20030617
102 this->MedicalImageProperties->SetStudyDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds) );
104 // For ex: DICOM (0008,0022) = 20030617
105 this->MedicalImageProperties->SetAcquisitionDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds) );
106 #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
107 // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012
108 this->MedicalImageProperties->SetStudyTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds) );
110 // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012
111 this->MedicalImageProperties->SetAcquisitionTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds) );
112 // For ex: DICOM (0008,0023) = 20030617
113 this->MedicalImageProperties->SetImageDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds) );
114 // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012
115 this->MedicalImageProperties->SetImageTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds) );
116 // For ex: DICOM (0020,0013) = 1
117 this->MedicalImageProperties->SetImageNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds) );
118 // For ex: DICOM (0020,0011) = 902
119 this->MedicalImageProperties->SetSeriesNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
120 // For ex: DICOM (0008,103e) = SCOUT
121 this->MedicalImageProperties->SetSeriesDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
122 // For ex: DICOM (0020,0010) = 37481
123 this->MedicalImageProperties->SetStudyID( GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
124 // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
125 this->MedicalImageProperties->SetStudyDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
126 // For ex: DICOM (0008,0060)= CT
127 this->MedicalImageProperties->SetModality( GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
128 // For ex: DICOM (0008,0070) = Siemens
129 this->MedicalImageProperties->SetManufacturer( GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds) );
130 // For ex: DICOM (0008,1090) = LightSpeed QX/i
131 this->MedicalImageProperties->SetManufacturerModelName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds) );
132 // For ex: DICOM (0008,1010) = LSPD_OC8
133 this->MedicalImageProperties->SetStationName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds) );
134 // For ex: DICOM (0008,0080) = FooCity Medical Center
135 this->MedicalImageProperties->SetInstitutionName( GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds) );
136 // For ex: DICOM (0018,1210) = Bone
137 this->MedicalImageProperties->SetConvolutionKernel( GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds) );
138 // For ex: DICOM (0018,0050) = 0.273438
139 this->MedicalImageProperties->SetSliceThickness( GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds) );
140 // For ex: DICOM (0018,0060) = 120
141 this->MedicalImageProperties->SetKVP( GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds) );
142 // For ex: DICOM (0018,1120) = 15
143 this->MedicalImageProperties->SetGantryTilt( GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds) );
144 // For ex: DICOM (0018,0081) = 105
145 this->MedicalImageProperties->SetEchoTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds) );
146 // For ex: DICOM (0018,0091) = 35
147 this->MedicalImageProperties->SetEchoTrainLength( GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds) );
148 // For ex: DICOM (0018,0080) = 2040
149 this->MedicalImageProperties->SetRepetitionTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds) );
150 // For ex: DICOM (0018,1150) = 5
151 this->MedicalImageProperties->SetExposureTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds) );
152 // For ex: DICOM (0018,1151) = 400
153 this->MedicalImageProperties->SetXRayTubeCurrent( GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds) );
154 // For ex: DICOM (0018,1152) = 114
155 this->MedicalImageProperties->SetExposure( GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds) );
157 // virtual void AddWindowLevelPreset(double w, double l);
158 // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter
159 // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth
160 gdcm::Tag twindowcenter(0x0028,0x1050);
161 gdcm::Tag twindowwidth(0x0028,0x1051);
162 if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) )
164 const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter );
165 const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth );
166 const gdcm::ByteValue *bvwc = windowcenter.GetByteValue();
167 const gdcm::ByteValue *bvww = windowwidth.GetByteValue();
168 if( bvwc && bvww ) // Can be Type 2
170 //gdcm::Attributes<0x0028,0x1050> at;
171 gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elwc;
172 std::stringstream ss1;
173 std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() );
175 gdcm::VR vr = gdcm::VR::DS;
176 unsigned int vrsize = vr.GetSizeof();
177 unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), swc.size());
178 elwc.SetLength( count * vrsize );
180 std::stringstream ss2;
181 std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() );
183 gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elww;
184 elww.SetLength( count * vrsize );
186 //assert( elww.GetLength() == elwc.GetLength() );
187 for(unsigned int i = 0; i < elwc.GetLength(); ++i)
189 this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) );
193 gdcm::Tag twindowexplanation(0x0028,0x1055);
194 if( ds.FindDataElement( twindowexplanation ) )
196 const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation );
197 const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue();
198 if( bvwe ) // Can be Type 2
200 int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets();
201 gdcm::Element<gdcm::VR::LO,gdcm::VM::VM1_n> elwe; // window explanation
202 gdcm::VR vr = gdcm::VR::LO;
203 std::stringstream ss;
205 std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() );
206 unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), swe.size()); (void)count;
207 // I found a case with only one W/L but two comments: WINDOW1\WINDOW2
208 // SIEMENS-IncompletePixelData.dcm
209 //assert( count >= (unsigned int)n );
210 elwe.SetLength( /*count*/ n * vr.GetSizeof() );
213 for(int i = 0; i < n; ++i)
215 this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() );
221 // gdcmData/JDDICOM_Sample4.dcm
222 // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality
223 gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage;
224 ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality );
225 gdcm::MediaStorage ms2;
226 ms2.SetFromFile( reader.GetFile() );
227 if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage )
229 vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality()
230 << " Will be set instead to the known one: " << ms2.GetModality() )
231 this->MedicalImageProperties->SetModality( ms2.GetModality() );
239 //(3006,0022) ?? (IS) [2 ] # 2,1 ROI Number
240 //(3006,0024) ?? (UI) [2.16.840.1.114362.1.759508.1251415878280.193] # 44,1 Referenced Frame of Reference UID
241 //(3006,0026) ?? (LO) [Bladder ] # 8,1 ROI Name
242 //(3006,0036) ?? (CS) [MANUAL] # 6,1 ROI Generation Algorithm
244 int vtkGDCMPolyDataReader::RequestData_RTStructureSetStorage(gdcm::Reader const &reader,
245 vtkInformationVector *outputVector)
247 // This is done in RequestInformation
248 // gdcm::MediaStorage ms;
249 // ms.SetFromFile( reader.GetFile() );
250 // //std::cout << ms << std::endl;
251 // if( ms != gdcm::MediaStorage::RTStructureSetStorage )
256 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
257 // (3006,0010) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedFrameOfReferenceSequence
258 // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
259 // (3006,0039) SQ (Sequence with explicit length #=4) # 24216, 1 ROIContourSequence
260 gdcm::Tag troicsq(0x3006,0x0039);
261 if( !ds.FindDataElement( troicsq ) )
265 gdcm::Tag tssroisq(0x3006,0x0020);
266 if( !ds.FindDataElement( tssroisq ) )
270 gdcm::Tag trefframerefsq(0x3006,0x0010);
271 if( !ds.FindDataElement( trefframerefsq ) )
275 const gdcm::DataElement &refframerefsq = ds.GetDataElement( trefframerefsq );
276 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0 = refframerefsq.GetValueAsSQ();
277 if( !sqi0 || !sqi0->GetNumberOfItems() )
281 assert( sqi0->GetNumberOfItems() == 1 );
282 for(unsigned int pd = 0; pd < sqi0->GetNumberOfItems(); ++pd)
284 const gdcm::Item & item = sqi0->GetItem(pd+1); // Item start at #1
285 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
286 // (3006,0012) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedStudySequence
287 gdcm::Attribute<0x0020,0x052> frameofreferenceuid;
288 frameofreferenceuid.SetFromDataSet( nestedds );
289 this->RTStructSetProperties->SetReferenceFrameOfReferenceUID(
290 frameofreferenceuid.GetValue() );
291 gdcm::Tag trtrefstudysq(0x3006,0x0012);
292 if( !nestedds.FindDataElement( trtrefstudysq) )
296 const gdcm::DataElement &rtrefstudysq = nestedds.GetDataElement( trtrefstudysq );
297 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi00 = rtrefstudysq.GetValueAsSQ();
298 if( !sqi00 || !sqi00->GetNumberOfItems() )
302 assert( sqi00->GetNumberOfItems() == 1 );
303 for(unsigned int pd0 = 0; pd0 < sqi00->GetNumberOfItems(); ++pd0)
305 const gdcm::Item & item = sqi00->GetItem(pd0+1); // Item start at #1
306 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
308 // (3006,0014) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedSeriesSequence
309 gdcm::Tag trtrefseriessq(0x3006,0x0014);
310 if( !nestedds.FindDataElement( trtrefseriessq) )
314 const gdcm::DataElement &rtrefseriessq = nestedds.GetDataElement( trtrefseriessq);
316 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi000 = rtrefseriessq.GetValueAsSQ();
317 if( !sqi000 || !sqi000->GetNumberOfItems() )
321 assert( sqi000->GetNumberOfItems() == 1 );
322 for(unsigned int pd00 = 0; pd00 < sqi000->GetNumberOfItems(); ++pd00)
324 const gdcm::Item & item = sqi000->GetItem(pd00+1); // Item start at #1
325 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
327 gdcm::Attribute<0x0020,0x000e> seriesinstanceuid;
328 seriesinstanceuid.SetFromDataSet( nestedds );
329 this->RTStructSetProperties->SetReferenceSeriesInstanceUID(
330 seriesinstanceuid.GetValue() );
333 // (3006,0016) SQ (Sequence with undefined length #=162) # u/l, 1 ContourImageSequence
334 gdcm::Tag tcontourimageseq(0x3006,0x0016);
335 if( !nestedds.FindDataElement( tcontourimageseq) )
339 const gdcm::DataElement &contourimageseq = nestedds.GetDataElement( tcontourimageseq );
340 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0000 = contourimageseq.GetValueAsSQ();
341 if( !sqi0000 || !sqi0000->GetNumberOfItems() )
346 assert( sqi0000->GetNumberOfItems() != 1 );
347 for(unsigned int pd000 = 0; pd000 < sqi0000->GetNumberOfItems(); ++pd000)
349 const gdcm::Item & item = sqi0000->GetItem(pd000+1); // Item start at #1
350 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
351 gdcm::Attribute<0x0008,0x1150> refsopclassuid;
352 refsopclassuid.SetFromDataSet( nestedds );
353 gdcm::Attribute<0x0008,0x1155> refinstanceuid;
354 refinstanceuid.SetFromDataSet( nestedds );
355 this->RTStructSetProperties->AddReferencedFrameOfReference( refsopclassuid.GetValue().c_str(),
356 refinstanceuid.GetValue().c_str() );
364 const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
365 //std::cout << roicsq << std::endl;
366 //const gdcm::SequenceOfItems *sqi_debug = roicsq.GetSequenceOfItems();
367 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = roicsq.GetValueAsSQ();
368 if( !sqi || !sqi->GetNumberOfItems() )
372 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
373 //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems();
374 gdcm::SmartPointer<gdcm::SequenceOfItems> ssqi = ssroisq.GetValueAsSQ();
375 if( !ssqi || !ssqi->GetNumberOfItems() )
380 // For each Item in the DataSet create a vtkPolyData
381 for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd)
383 //StructureSetROI structuresetroi;
384 // get the info object
385 vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
388 vtkPolyData *output = vtkPolyData::SafeDownCast(
389 outInfo1->Get(vtkDataObject::DATA_OBJECT()));
392 const gdcm::Item & item = sqi->GetItem(pd+1); // Item start at #1
393 //std::cout << item << std::endl;
394 const gdcm::Item & sitem = ssqi->GetItem(pd+1); // Item start at #1
395 const gdcm::DataSet& snestedds = sitem.GetNestedDataSet();
396 // (3006,0026) ?? (LO) [date] # 4,1 ROI Name
397 gdcm::Tag stcsq(0x3006,0x0026);
398 if( !snestedds.FindDataElement( stcsq ) )
402 const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq );
403 std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
404 //structuresetroi.ROIName = s;
405 gdcm::Attribute<0x3006,0x0022> roinumber;
406 roinumber.SetFromDataSet( snestedds );
407 //structuresetroi.ROINumber = roinumber.GetValue();
408 gdcm::Attribute<0x3006,0x0024> refframeuid;
409 refframeuid.SetFromDataSet( snestedds );
410 //structuresetroi.RefFrameRefUID = refframeuid.GetValue();
411 gdcm::Attribute<0x3006,0x0026> roiname;
412 roiname.SetFromDataSet( snestedds );
413 assert( s == roiname.GetValue() );
414 gdcm::Attribute<0x3006,0x0036> roigenalg;
415 roigenalg.SetFromDataSet( snestedds );
416 //structuresetroi.ROIGenerationAlgorithm = roigenalg.GetValue();
417 //structuresetrois.push_back( structuresetroi );
419 this->RTStructSetProperties->AddStructureSetROI(
420 roinumber.GetValue(),
421 refframeuid.GetValue(),
426 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
427 //std::cout << nestedds << std::endl;
428 //(3006,002a) IS [255\192\96] # 10,3 ROI Display Color
429 gdcm::Tag troidc(0x3006,0x002a);
430 gdcm::Attribute<0x3006,0x002a> color = {};
431 if( nestedds.FindDataElement( troidc) )
433 const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc );
434 color.SetFromDataElement( decolor );
435 //std::cout << "color:" << color[0] << "," << color[1] << "," << color[2] << std::endl;
437 //(3006,0040) SQ (Sequence with explicit length #=8) # 4326, 1 ContourSequence
438 gdcm::Tag tcsq(0x3006,0x0040);
439 if( !nestedds.FindDataElement( tcsq ) )
443 const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq );
444 //std::cout << csq << std::endl;
446 //const gdcm::SequenceOfItems *sqi2 = csq.GetSequenceOfItems();
447 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi2 = csq.GetValueAsSQ();
448 if( !sqi2 || !sqi2->GetNumberOfItems() )
452 unsigned int nitems = sqi2->GetNumberOfItems();
453 //std::cout << nitems << std::endl;
454 //this->SetNumberOfOutputPorts(nitems);
455 vtkDoubleArray *scalars = vtkDoubleArray::New();
456 scalars->SetNumberOfComponents(3);
458 vtkPoints *newPts = vtkPoints::New();
459 //std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
460 //std::cout << s << std::endl;
461 //newPts->GetData()->SetName( s.c_str() );
462 // In VTK there is no API to specify the name of a vtkPolyData, you can only specify Name
463 // for the scalars (pointdata or celldata), so let's do that...
464 //scalars->SetName( structuresetroi.ROIName.c_str() );
465 scalars->SetName( roiname.GetValue().c_str() );
466 vtkCellArray *polys = vtkCellArray::New();
467 for(unsigned int i = 0; i < nitems; ++i)
469 const gdcm::Item & item2 = sqi2->GetItem(i+1); // Item start at #1
471 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet();
472 //std::cout << nestedds2 << std::endl;
473 // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData
474 gdcm::Tag tcontourdata(0x3006,0x0050);
475 const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata );
476 //std::cout << contourdata << std::endl;
478 //const gdcm::ByteValue *bv = contourdata.GetByteValue();
479 gdcm::Attribute<0x3006,0x0042> contgeotype;
480 contgeotype.SetFromDataSet( nestedds2 );
481 assert( contgeotype.GetValue() == "CLOSED_PLANAR " );
483 gdcm::Attribute<0x3006,0x0046> numcontpoints;
484 numcontpoints.SetFromDataSet( nestedds2 );
486 gdcm::Attribute<0x3006,0x0050> at;
487 at.SetFromDataElement( contourdata );
490 assert( nestedds2.FindDataElement( gdcm::Tag(0x3006,0x0016) ) );
491 const gdcm::DataElement &contourimagesequence = nestedds2.GetDataElement( gdcm::Tag(0x3006,0x0016) );
492 gdcm::SmartPointer<gdcm::SequenceOfItems> contourimagesequence_sqi = contourimagesequence.GetValueAsSQ();
493 assert( contourimagesequence_sqi && contourimagesequence_sqi->GetNumberOfItems() == 1 );
494 const gdcm::Item & theitem = contourimagesequence_sqi->GetItem(1);
495 const gdcm::DataSet& nestedds = theitem.GetNestedDataSet();
497 gdcm::Attribute<0x0008,0x1150> classat;
498 classat.SetFromDataSet( nestedds );
499 gdcm::Attribute<0x0008,0x1155> instat;
500 instat.SetFromDataSet( nestedds );
502 this->RTStructSetProperties->AddContourReferencedFrameOfReference( pd,
503 classat.GetValue(), instat.GetValue() );
506 //newPts->SetNumberOfPoints( at.GetNumberOfValues() / 3 );
507 //assert( at.GetNumberOfValues() % 3 == 0); // FIXME
508 const double* pts = at.GetValues();
509 vtkIdType buffer[256];
511 unsigned int npts = at.GetNumberOfValues() / 3;
512 assert( npts == numcontpoints.GetValue() );
515 ptIds = new vtkIdType[npts];
521 for(unsigned int i = 0; i < npts * 3; i+=3)
527 vtkIdType ptId = newPts->InsertNextPoint( x );
530 // Each Contour Data is in fact a Cell:
531 vtkIdType cellId = polys->InsertNextCell( npts , ptIds);
532 scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0);
538 output->SetPoints(newPts);
540 output->SetPolys(polys);
542 output->GetCellData()->SetScalars(scalars);
546 // Add the Observations:
547 // we can only be doing it here once all RT are loaded, since we will
548 // attach observation to *existing* rtstruct
549 gdcm::Tag trtroiobssq(0x3006,0x0080);
550 if( !ds.FindDataElement( trtroiobssq ) )
554 const gdcm::DataElement &rtroiobssq = ds.GetDataElement( trtroiobssq );
555 gdcm::SmartPointer<gdcm::SequenceOfItems> rtroiobssqsqi = rtroiobssq.GetValueAsSQ();
556 if( !rtroiobssqsqi || !rtroiobssqsqi->GetNumberOfItems() )
560 for(unsigned int obs = 0; obs < rtroiobssqsqi->GetNumberOfItems(); ++obs)
562 const gdcm::Item & item = rtroiobssqsqi->GetItem(obs+1); // Item start at #1
563 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
564 gdcm::Attribute<0x3006,0x0082> observationnumber;
565 observationnumber.SetFromDataSet( nestedds );
566 gdcm::Attribute<0x3006,0x0084> referencedroinumber;
567 referencedroinumber.SetFromDataSet( nestedds );
568 gdcm::Attribute<0x3006,0x00a4> rtroiinterpretedtype;
569 rtroiinterpretedtype.SetFromDataSet( nestedds );
570 gdcm::Attribute<0x3006,0x00a6> roiinterpreter;
571 roiinterpreter.SetFromDataSet( nestedds );
572 this->RTStructSetProperties->
573 AddStructureSetROIObservation( referencedroinumber.GetValue(),
574 observationnumber.GetValue(),
575 rtroiinterpretedtype.GetValue(),
576 roiinterpreter.GetValue() );
582 int vtkGDCMPolyDataReader::RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader,
583 vtkInformationVector *outputVector)
585 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
586 // (5400,0100) SQ (Sequence with undefined length #=1) # u/l, 1 WaveformSequence
587 gdcm::Tag twsq(0x5400,0x0100);
588 if( !ds.FindDataElement( twsq) )
592 const gdcm::DataElement &wsq = ds.GetDataElement( twsq );
593 //std::cout << wsq << std::endl;
594 //const gdcm::SequenceOfItems *sqi = wsq.GetSequenceOfItems();
595 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = wsq.GetValueAsSQ();
596 if( !sqi || !sqi->GetNumberOfItems() )
601 const gdcm::Item & item = sqi->GetItem(1); // Item start at #1
602 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
604 // (5400,1004) US 16 # 2, 1 WaveformBitsAllocated
605 gdcm::Tag twba(0x5400,0x1004);
606 if( !nestedds.FindDataElement( twba ) )
610 const gdcm::DataElement &wba= nestedds.GetDataElement( twba );
612 //std::cout << wba << std::endl;
613 // (5400,1006) CS [SS] # 2, 1 WaveformSampleInterpretation
614 // (5400,1010) OW 00ba\0030\ff76\ff8b\00a2\ffd3\ffae\ff50\0062\00c4\011e\00c2\00ba... # 57600, 1 WaveformData
615 gdcm::Tag twd(0x5400,0x1010);
616 if( !nestedds.FindDataElement( twd ) )
620 const gdcm::DataElement &wd = nestedds.GetDataElement( twd );
621 const gdcm::ByteValue *bv = wd.GetByteValue();
622 size_t len = bv->GetLength();
623 int16_t *p = (int16_t*)bv;
625 // get the info object
627 vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
630 vtkPolyData *output = vtkPolyData::SafeDownCast(
631 outInfo1->Get(vtkDataObject::DATA_OBJECT()));
633 vtkPoints *newPts = vtkPoints::New();
634 size_t npts = len / 2;
635 //npts = 10; // DEBUG !
636 for(size_t i = 0; i < npts; ++i )
639 x[0] = (float)p[i] / 8800;
640 //std::cout << p[i] << std::endl;
643 vtkIdType ptId = newPts->InsertNextPoint( x );
645 output->SetPoints(newPts);
648 vtkCellArray* lines = vtkCellArray::New();
649 for ( int i = 0; i < newPts->GetNumberOfPoints() - 1; ++i )
654 lines->InsertNextCell( 2, topol );
657 output->SetLines(lines);
659 output->BuildCells();
660 //output->GetCellData()->SetScalars(scalars);
666 //----------------------------------------------------------------------------
667 int vtkGDCMPolyDataReader::RequestData(
668 vtkInformation *vtkNotUsed(request),
669 vtkInformationVector **vtkNotUsed(inputVector),
670 vtkInformationVector *outputVector)
672 vtkInformation *outInfo = outputVector->GetInformationObject(0);
673 //vtkPoints *newPts, *mergedPts;
674 //vtkCellArray *newPolys, *mergedPolys;
675 //vtkFloatArray *newScalars=0, *mergedScalars=0;
677 // All of the data in the first piece.
678 if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
683 if ( !this->FileName || !*this->FileName )
685 vtkErrorMacro(<<"A FileName must be specified.");
690 reader.SetFileName( this->FileName );
696 gdcm::MediaStorage ms;
697 ms.SetFromFile( reader.GetFile() );
700 if( ms == gdcm::MediaStorage::RTStructureSetStorage )
702 ret = this->RequestData_RTStructureSetStorage(reader, outputVector);
704 else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
706 ret = this->RequestData_HemodynamicWaveformStorage(reader, outputVector);
710 // not handled assume error
717 int vtkGDCMPolyDataReader::RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader)
719 const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
720 // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
721 gdcm::Tag tssroisq(0x3006,0x0020);
722 if( !ds.FindDataElement( tssroisq ) )
727 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
728 //const gdcm::SequenceOfItems *sqi = ssroisq.GetSequenceOfItems();
729 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = ssroisq.GetValueAsSQ();
730 if( !sqi || !sqi->GetNumberOfItems() )
734 unsigned int npds = sqi->GetNumberOfItems();
736 //std::cout << "Nb pd:" << npds << std::endl;
737 this->SetNumberOfOutputPorts( npds );
740 for(unsigned int i = 1; i < npds; ++i) // first output is allocated for us
742 vtkPolyData *output2 = vtkPolyData::New();
743 this->GetExecutive()->SetOutputData(i, output2);
749 int vtkGDCMPolyDataReader::RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader)
754 //----------------------------------------------------------------------------
755 int vtkGDCMPolyDataReader::RequestInformation(
756 vtkInformation *vtkNotUsed(request),
757 vtkInformationVector **vtkNotUsed(inputVector),
758 vtkInformationVector *outputVector)
760 // get the info object
761 // vtkInformation *outInfo = outputVector->GetInformationObject(0);
763 // outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
766 reader.SetFileName( this->FileName );
772 gdcm::MediaStorage ms;
773 ms.SetFromFile( reader.GetFile() );
776 if( ms == gdcm::MediaStorage::RTStructureSetStorage )
778 ret = this->RequestInformation_RTStructureSetStorage(reader);
780 else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
782 ret = this->RequestInformation_HemodynamicWaveformStorage(reader);
786 // not handled assume error
792 // Ok let's fill in the 'extra' info:
793 this->FillMedicalImageInformation(reader);
800 //----------------------------------------------------------------------------
801 void vtkGDCMPolyDataReader::PrintSelf(ostream& os, vtkIndent indent)
803 this->Superclass::PrintSelf(os,indent);
805 os << indent << "File Name: "
806 << (this->FileName ? this->FileName : "(none)") << "\n";