fw4spl
writer/ie/SpatialFiducials.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwGdcmIO/writer/ie/SpatialFiducials.hpp"
8 
9 #include "fwGdcmIO/helper/DicomDataTools.hpp"
10 #include "fwGdcmIO/helper/DicomDataWriter.hxx"
11 
12 #include <fwData/Image.hpp>
13 #include <fwData/Point.hpp>
14 #include <fwData/PointList.hpp>
15 #include <fwData/String.hpp>
16 #include <fwData/Vector.hpp>
17 
18 #include <fwDataTools/fieldHelper/Image.hpp>
19 
20 #include <fwTools/dateAndTime.hpp>
21 
22 #include <boost/foreach.hpp>
23 
24 #include <gdcmUIDGenerator.h>
25 
26 namespace fwGdcmIO
27 {
28 namespace writer
29 {
30 namespace ie
31 {
32 
33 //------------------------------------------------------------------------------
34 
35 SpatialFiducials::SpatialFiducials(const SPTR(::gdcm::Writer)& writer,
36  const SPTR(::fwGdcmIO::container::DicomInstance)& instance,
37  const ::fwData::Image::csptr& image,
38  const ::fwLog::Logger::sptr& logger,
39  ProgressCallback progress,
40  CancelRequestedCallback cancel) :
41  ::fwGdcmIO::writer::ie::InformationEntity< ::fwData::Image >(writer, instance, image,
42  logger, progress, cancel)
43 {
44 }
45 
46 //------------------------------------------------------------------------------
47 
49 {
50 }
51 
52 //------------------------------------------------------------------------------
53 
55 {
56  // Retrieve dataset
57  ::gdcm::DataSet& dataset = m_writer->GetFile().GetDataSet();
58 
59  ::boost::posix_time::ptime ptime = boost::posix_time::second_clock::local_time();
60 
61  // Content Date - Type 1 - FIXME: Keep series date ?
62  std::string date = ::fwTools::getDate(ptime);
63  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x0023 >(date, dataset);
64 
65  // Content Time - Type 1 - FIXME: Keep series time ?
66  std::string time = ::fwTools::getTime(ptime);
67  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x0033 >(time, dataset);
68 
69  // Instance Number - Type 1
70  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< unsigned int, 0x0020, 0x0013 >(0, dataset);
71 
72  // Content Label - Type 1
73  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x0080 >("SF", dataset);
74 
75  // Content Description - Type 2
76  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x0081 >("Spatial Fiducials", dataset);
77 
78  // Content Creator's Name - Type 2 - TODO: Set fiducial creator name ?
79  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x0084 >("Unknown^Unknown", dataset);
80 
81  // Fiducial Set Sequence - Type 1
82  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > fiducialSetSequence = new ::gdcm::SequenceOfItems();
83  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0070, 0x031C >(fiducialSetSequence, dataset);
84 
85  // Create Fiducial Sequence Item
86  ::gdcm::Item fiducialSetItem;
87  fiducialSetItem.SetVLToUndefined();
88  ::gdcm::DataSet& fiducialSetItemDataset = fiducialSetItem.GetNestedDataSet();
89 
90  // Referenced Image Sequence - Type 1C
91  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedImageSequence = new ::gdcm::SequenceOfItems();
92  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x1140 >(referencedImageSequence,
93  fiducialSetItemDataset);
94 
95  // Add all referenced image
96  for(unsigned int index = 0; index < m_instance->getSOPInstanceUIDContainer().size(); ++index)
97  {
98  ::gdcm::Item referencedImageItem;
99  referencedImageItem.SetVLToUndefined();
100  ::gdcm::DataSet& referencedImageItemDataset = referencedImageItem.GetNestedDataSet();
101 
102  // Referenced Frame Number - Type 1C
103  int frameNumber = index + 1;
104  ::fwGdcmIO::helper::DicomDataWriter::setTagValues< int, 0x0008, 0x1160 >(&frameNumber, 1,
105  referencedImageItemDataset);
106 
107  // Referenced SOP Class UID - Type 1
108  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1150 >(m_instance->getSOPClassUID(),
109  referencedImageItemDataset);
110 
111  // Referenced SOP Instance UID - Type 1
112  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1155 >(
113  m_instance->getSOPInstanceUIDContainer()[index],
114  referencedImageItemDataset);
115 
116  // Add referenced image to sequence
117  referencedImageSequence->AddItem(referencedImageItem);
118 
119  }
120 
121  // Fiducial Sequence - Type 1
122  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > fiducialSequence = new ::gdcm::SequenceOfItems();
123  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0070, 0x031E >(fiducialSequence,
124  fiducialSetItemDataset);
125 
126  // Write landmarks
127  this->writeLandmarks(fiducialSequence);
128 
129  // Add Fiducial Set to sequence
130  fiducialSetSequence->AddItem(fiducialSetItem);
131 
132 }
133 
134 //------------------------------------------------------------------------------
135 
136 void SpatialFiducials::writeLandmarks(::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence)
138 {
139  ::fwData::PointList::sptr pointList =
141  if (pointList)
142  {
143  unsigned int index = 0;
144  for(const ::fwData::Point::sptr& point : pointList->getPoints())
145  {
146  ::gdcm::Item fiducialItem;
147  fiducialItem.SetVLToUndefined();
148  ::gdcm::DataSet& fiducialItemDataset = fiducialItem.GetNestedDataSet();
149 
150  // Fiducial Identifier - Type 1
151  std::stringstream ssIdentifier;
152  ssIdentifier << "landmark-" << index;
153  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x0310 >(ssIdentifier.str(), fiducialItemDataset);
154 
155  // Fiducial Description - Type 3
156  std::string label =
158  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x030F >(label, fiducialItemDataset);
159 
160  // Shape Type - Type 1
161  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0070, 0x0306 >("POINT", fiducialItemDataset);
162 
163  // Graphic Coordinates Data Sequence - Type 1C
164  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > graphicCoodinatesDataSequence =
165  new ::gdcm::SequenceOfItems();
166  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0070, 0x0318 >(graphicCoodinatesDataSequence,
167  fiducialItemDataset);
168 
169  ::gdcm::Item graphicDataItem;
170  graphicDataItem.SetVLToUndefined();
171  ::gdcm::DataSet& graphicDataItemDataset = graphicDataItem.GetNestedDataSet();
172 
173  // Graphic Data - Type 1
174  float coordinates[2];
175  coordinates[0] = static_cast<float>(point->getCoord()[0]);
176  coordinates[1] = static_cast<float>(point->getCoord()[1]);
177  ::fwGdcmIO::helper::DicomDataWriter::setTagValues< float, 0x0070, 0x0022 >(coordinates, 2,
178  graphicDataItemDataset);
179  OSLM_TRACE("WRITE NEW POINT : [" << label << "] " << coordinates[0] << " / " << coordinates[1]);
180 
181  // Referenced Image Sequence - Type 1
182  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedImageSequence = new ::gdcm::SequenceOfItems();
183  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x1140 >(referencedImageSequence,
184  graphicDataItemDataset);
185 
186  int frameNumber =
188  point));
189  this->addReferencedImage(frameNumber, referencedImageSequence);
190 
191  // Add graphic data to sequence
192  graphicCoodinatesDataSequence->AddItem(graphicDataItem);
193 
194  // Add Fiducial to sequence
195  sequence->AddItem(fiducialItem);
196 
197  // Increase index
198  ++index;
199  }
200  }
201 }
202 
203 //------------------------------------------------------------------------------
204 
206 {
207  // Retrieve dataset
208  ::gdcm::DataSet& dataset = m_writer->GetFile().GetDataSet();
209 
210  // Referenced Series Sequence - Type 1C
211  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedSeriesSequence = new ::gdcm::SequenceOfItems();
212  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x1115 >(referencedSeriesSequence, dataset);
213 
214  // Create Referenced Series
215  ::gdcm::Item referencedSeriesItem;
216  referencedSeriesItem.SetVLToUndefined();
217  ::gdcm::DataSet& referencedSeriesItemDataset = referencedSeriesItem.GetNestedDataSet();
218 
219  // Series Instance UID - Type 1
220  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0020, 0x000E >(
221  m_instance->getSeriesInstanceUID(),
222  referencedSeriesItemDataset);
223 
224  // Referenced Instance Sequence - Type 1
225  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedInstanceSequence = new ::gdcm::SequenceOfItems();
226  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x114A >(referencedInstanceSequence,
227  referencedSeriesItemDataset);
228 
229  // Add all referenced image
230  for(unsigned int index = 0; index < m_instance->getSOPInstanceUIDContainer().size(); ++index)
231  {
232  ::gdcm::Item referencedInstanceItem;
233  referencedInstanceItem.SetVLToUndefined();
234  ::gdcm::DataSet& referencedInstanceItemDataset = referencedInstanceItem.GetNestedDataSet();
235 
236  // Referenced SOP Class UID - Type 1
237  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1150 >(m_instance->getSOPClassUID(),
238  referencedInstanceItemDataset);
239 
240  // Referenced SOP Instance UID - Type 1
241  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1155 >(
242  m_instance->getSOPInstanceUIDContainer()[index],
243  referencedInstanceItemDataset);
244 
245  // Add referenced image to sequence
246  referencedInstanceSequence->AddItem(referencedInstanceItem);
247  }
248 
249  referencedSeriesSequence->AddItem(referencedSeriesItem);
250 
251  // Studies Containing Other Referenced Instances Sequence - Type 1C
252  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > studiesSequence = new ::gdcm::SequenceOfItems();
253  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x1200 >(studiesSequence, dataset);
254 
255  ::gdcm::Item studiesItem;
256  studiesItem.SetVLToUndefined();
257  ::gdcm::DataSet& studiesItemDataset = studiesItem.GetNestedDataSet();
258 
259  // Study Instance UID - Type 1
260  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0020, 0x000D >(m_instance->getStudyInstanceUID(),
261  studiesItemDataset);
262 
263  // Referenced Series Sequence - Type 1
264  ::fwGdcmIO::helper::DicomDataWriter::setSequenceTagValue< 0x0008, 0x1115 >(referencedSeriesSequence,
265  studiesItemDataset);
266 
267  studiesSequence->AddItem(studiesItem);
268 }
269 
270 //------------------------------------------------------------------------------
271 
273 {
274  // Retrieve dataset
275  ::gdcm::DataSet& dataset = m_writer->GetFile().GetDataSet();
276 
277  // SOP Class UID
278  std::string sopClassUID = ::gdcm::MediaStorage::GetMSString(::gdcm::MediaStorage::SpacialFiducialsStorage);
279  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x0016 >(sopClassUID, dataset);
280 
281  // SOP Instance UID
282  ::gdcm::UIDGenerator uidGenerator;
283  std::string sopInstanceUID = uidGenerator.Generate();
284  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x0018 >(sopInstanceUID, dataset);
285 }
286 
287 //------------------------------------------------------------------------------
288 
290  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedImageSequence)
292 {
293  ::gdcm::Item referencedImageItem;
294  referencedImageItem.SetVLToUndefined();
295  ::gdcm::DataSet& referencedImageItemDataset = referencedImageItem.GetNestedDataSet();
296 
297  // Referenced Frame Number - Type 1C
298  ::fwGdcmIO::helper::DicomDataWriter::setTagValues< int, 0x0008, 0x1160 >(&frameNumber, 1,
299  referencedImageItemDataset);
300 
301  // Referenced SOP Class UID - Type 1
302  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1150 >(m_instance->getSOPClassUID(),
303  referencedImageItemDataset);
304 
305  // Referenced SOP Instance UID - Type 1
306  ::fwGdcmIO::helper::DicomDataWriter::setTagValue< 0x0008, 0x1155 >(
307  m_instance->getSOPInstanceUIDContainer()[frameNumber-1], referencedImageItemDataset);
308 
309  // Add referenced image to sequence
310  referencedImageSequence->AddItem(referencedImageItem);
311 }
312 
313 //------------------------------------------------------------------------------
314 
315 } // namespace ie
316 } // namespace writer
317 } // namespace fwGdcmIO
virtual FWGDCMIO_API ~SpatialFiducials()
Destructor.
#define SPTR(_cls_)
void addReferencedImage(int frameNumber,::gdcm::SmartPointer< ::gdcm::SequenceOfItems > referencedImageSequence)
Add a frame number to the referenced image sequence.
InformationEntity base class used to write modules.
This class defines a DICOM SOP instance. It is useful during the whole writing process. This class allows to share data between module writers.
virtual FWGDCMIO_API void writeSOPCommonModule()
Write SOP Common Module tags.
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
Implements a failed exception class for fwGdcmIO.
std::shared_ptr< ::fwGdcmIO::container::DicomInstance > m_instance
DICOM Instance.
FWGDCMIO_API SpatialFiducials(const std::shared_ptr< ::gdcm::Writer > &writer, const std::shared_ptr< ::fwGdcmIO::container::DicomInstance > &instance, const ::fwData::Image::csptr &series, const ::fwLog::Logger::sptr &logger=nullptr, ProgressCallback progress=nullptr, CancelRequestedCallback cancel=nullptr)
Constructor.
void writeLandmarks(::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence)
Write image landmarks into sequence.
virtual FWGDCMIO_API void writeCommonInstanceReferenceModule()
Write Common Instance Reference Module tags.
static FWDATATOOLS_API const std::string m_labelId
to assign a label
This class defines a list of points.
virtual FWGDCMIO_API void writeSpatialFiducialsModule()
Write Spatial Fiducials Module tags.
Contains the representation of the data objects used in the framework.
std::shared_ptr< const ::fwData::Image > m_object
FW4SPL Object.
static FWGDCMIO_API std::size_t convertPointToFrameNumber(const ::fwData::Image::csptr &image, const ::fwData::Point::csptr &point)
Convert a 3D point to the closest frame number index.
This class contains an std::string value.