fw4spl
StructuredReport.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2016.
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/container/sr/DicomSRCodeNode.hpp"
8 #include "fwGdcmIO/container/sr/DicomSRContainerNode.hpp"
9 #include "fwGdcmIO/container/sr/DicomSRImageNode.hpp"
10 #include "fwGdcmIO/container/sr/DicomSRNumNode.hpp"
11 #include "fwGdcmIO/container/sr/DicomSRSCoord3DNode.hpp"
12 #include "fwGdcmIO/container/sr/DicomSRSCoordNode.hpp"
13 #include "fwGdcmIO/container/sr/DicomSRTextNode.hpp"
14 #include "fwGdcmIO/container/sr/DicomSRUIDRefNode.hpp"
15 #include "fwGdcmIO/helper/DicomDataReader.hxx"
16 #include "fwGdcmIO/helper/StructuredReport.hpp"
17 
18 namespace fwGdcmIO
19 {
20 namespace helper
21 {
22 
23 //------------------------------------------------------------------------------
24 
25 SPTR(::fwGdcmIO::container::sr::DicomSRContainerNode) StructuredReport::readSR(const ::gdcm::DataSet& dataset)
26 {
28 
29  // Value Type - Type 1
30  const std::string type = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa040 >(dataset);
31 
32  // Concept Name Code Sequence - Type 1C
33  const ::fwGdcmIO::container::DicomCodedAttribute& codedAttribute =
34  ::fwGdcmIO::helper::StructuredReport::readCodeSequence<0x0040, 0xa043>(dataset);
35 
36  if(type == "CONTAINER" && !codedAttribute.isEmpty())
37  {
38  result = std::make_shared< ::fwGdcmIO::container::sr::DicomSRContainerNode >(codedAttribute);
40  }
41 
42  return result;
43 }
44 
45 //------------------------------------------------------------------------------
46 
47 void StructuredReport::readSubNodeContainer(const ::gdcm::DataSet& dataset,
49 {
50  // Retrieve the content sequence
51  if(dataset.FindDataElement(::gdcm::Tag(0x0040, 0xa730)))
52  {
53  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence =
54  dataset.GetDataElement(::gdcm::Tag(0x0040, 0xa730)).GetValueAsSQ();
55 
56  for(unsigned int i = 1; i <= sequence->GetNumberOfItems(); ++i)
57  {
58  const ::gdcm::DataSet& itemDataset = sequence->GetItem(i).GetNestedDataSet();
60  }
61 
62  }
63 }
64 
65 //------------------------------------------------------------------------------
66 
67 void StructuredReport::readSubNode(const ::gdcm::DataSet& dataset,
69 {
71 
72  // Value Type - Type 1
73  const std::string type = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa040 >(dataset);
74 
75  // Concept Name Code Sequence - Type 1C
76  const ::fwGdcmIO::container::DicomCodedAttribute& codedAttribute =
77  ::fwGdcmIO::helper::StructuredReport::readCodeSequence<0x0040, 0xa043>(dataset);
78 
79  // Relationship Value - Type 1
80  const std::string relationship = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa010 >(dataset);
81 
82  if(type == "TEXT")
83  {
84  // Text Value - Type 1C
85  const std::string textValue = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa160 >(dataset);
86 
87  // Create Text Node
88  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRTextNode >(
89  codedAttribute, relationship, textValue);
90  }
91  else if(type == "NUM")
92  {
93  // Retrieve the measured value sequence
94  if(dataset.FindDataElement(::gdcm::Tag(0x0040, 0xa300)))
95  {
96  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence =
97  dataset.GetDataElement(::gdcm::Tag(0x0040, 0xa300)).GetValueAsSQ();
98  if(sequence->GetNumberOfItems() > 0)
99  {
100  const ::gdcm::DataSet& itemDataset = sequence->GetItem(1).GetNestedDataSet();
101 
102  // Numerical value - Type 1
103  const double numValue =
104  ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa30a, double >(itemDataset);
105 
106  // Measured units code sequence - Type 1
107  const ::fwGdcmIO::container::DicomCodedAttribute& measurementUnits =
108  ::fwGdcmIO::helper::StructuredReport::readCodeSequence<0x0040, 0x08ea>(itemDataset);
109 
110  // Create Num Node
111  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRNumNode >(
112  codedAttribute, relationship, numValue, measurementUnits);
113 
114  }
115  }
116  }
117  else if(type == "SCOORD")
118  {
119  // Graphic Data - Type 1C
120  ::gdcm::Attribute< 0x0070, 0x0022 > graphicDataAttribute;
121  graphicDataAttribute.SetFromDataElement(dataset.GetDataElement(::gdcm::Tag(0x0070, 0x0022)));
122  const float* graphicData = graphicDataAttribute.GetValues();
123 
124  // Graphic Type - Type 1
125  const std::string graphicType = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0070, 0x0023 >(dataset);
126 
127  if(graphicType == "POINT" && graphicDataAttribute.GetNumberOfValues() == 2)
128  {
129  // Create Text Node
130  std::vector<float> scoordVector(graphicData, graphicData + 2);
131  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoordNode >(
132  codedAttribute, relationship, graphicType, scoordVector);
133  }
134  else if(graphicType == "POLYLINE" && graphicDataAttribute.GetNumberOfValues() == 4)
135  {
136  // Create Text Node
137  std::vector<float> scoordVector(graphicData, graphicData + 4);
138  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoordNode >(
139  codedAttribute, relationship, graphicType, scoordVector);
140  }
141  else
142  {
143  SLM_WARN("Graphic type is not handled or data size doesn't match type. The SR node has been ignored.");
144  }
145 
146  }
147  else if(type == "SCOORD3D")
148  {
149  // Referenced Frame of Reference UID - Type 1
150  const std::string frameOfReferenceUID =
151  ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x3006, 0x0024 >(dataset);
152 
153  // Graphic Data - Type 1C
154  ::gdcm::Attribute< 0x0070, 0x0022 > graphicDataAttribute;
155  graphicDataAttribute.SetFromDataElement(dataset.GetDataElement(::gdcm::Tag(0x0070, 0x0022)));
156  const float* graphicData = graphicDataAttribute.GetValues();
157 
158  // Graphic Type - Type 1
159  const std::string graphicType = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0070, 0x0023 >(dataset);
160 
161  if(graphicType == "POINT" && graphicDataAttribute.GetNumberOfValues() == 3)
162  {
163  // Create Text Node
164  std::vector<float> scoordVector(graphicData, graphicData + 3);
165  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoord3DNode >(
166  codedAttribute, relationship, graphicType, scoordVector, frameOfReferenceUID);
167  }
168  else if(graphicType == "POLYLINE" && graphicDataAttribute.GetNumberOfValues() == 6)
169  {
170  // Create Text Node
171  std::vector<float> scoordVector(graphicData, graphicData + 6);
172  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRSCoord3DNode >(
173  codedAttribute, relationship, graphicType, scoordVector, frameOfReferenceUID);
174  }
175  else
176  {
177  SLM_WARN("Graphic type is not handled or data size doesn't match type. The SR node has been ignored.");
178  }
179 
180  }
181  else if(type == "IMAGE")
182  {
183  // Retrieve the referenced SOP sequence
184  if(dataset.FindDataElement(::gdcm::Tag(0x0008, 0x1199)))
185  {
186  ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence =
187  dataset.GetDataElement(::gdcm::Tag(0x0008, 0x1199)).GetValueAsSQ();
188  if(sequence->GetNumberOfItems() > 0)
189  {
190  const ::gdcm::DataSet& itemDataset = sequence->GetItem(1).GetNestedDataSet();
191 
192  // Referenced SOP Class UID - Type 1
193  const std::string sopClassUID = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0008, 0x1150 >(itemDataset);
194 
195  // Referenced SOP Instance UID - Type 1
196  const std::string sopInstanceUID =
197  ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0008, 0x1155 >(itemDataset);
198 
199  // Referenced Frame Number - Type 1C
200  int frameNumber = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0008, 0x1160, int >(itemDataset);
201 
202  // Create Num Node
203  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRImageNode >(
204  codedAttribute, relationship, sopClassUID, sopInstanceUID, frameNumber);
205 
206  }
207  }
208  }
209  else if(type == "CODE")
210  {
211  const ::fwGdcmIO::container::DicomCodedAttribute& codedEntry =
212  ::fwGdcmIO::helper::StructuredReport::readCodeSequence<0x0040, 0xa168>(dataset);
213 
214  // Create Code Node
215  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRCodeNode >(codedAttribute, relationship, codedEntry);
216 
217 
218  }
219  else if(type == "UIDREF")
220  {
221  // UID Value - Type 1C
222  const std::string uidValue = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0040, 0xa124 >(dataset);
223 
224  // Create UIDRef Node
225  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRUIDRefNode >(codedAttribute, relationship, uidValue);
226  }
227  else if(type == "CONTAINER")
228  {
229  // Create Container Node
230  node = std::make_shared< ::fwGdcmIO::container::sr::DicomSRContainerNode >(codedAttribute, relationship);
231  }
232 
233  if(node)
234  {
235  // Create children
237 
238  // Add node to parent
239  parent->addSubNode(node);
240  }
241 }
242 
243 //------------------------------------------------------------------------------
244 
246 {
247  out << "graph SR {" << std::endl;
248  int index = 0;
249  StructuredReport::dumpSRNode(root, out, index);
250  out << "}" << std::endl;
251 }
252 
253 //------------------------------------------------------------------------------
254 
256  std::ostream& out,
257  int& index)
258 {
259  // Write node
260  out << "\t" << index << "[label=\"" << (*root) << "\"][shape=box];" << std::endl;
261 
262  const int parentIndex = index;
263  for(const SPTR(::fwGdcmIO::container::sr::DicomSRNode)& child : root->getSubNodeContainer())
264  {
265  // Write edge
266  out << "\t" << parentIndex << "--" << (index+1) << "[label=\""
267  << child->getRelationship() << "\"];" << std::endl;
268 
269  // Write child
270  StructuredReport::dumpSRNode(child, out, ++index);
271 
272 
273  }
274 }
275 
276 //------------------------------------------------------------------------------
277 
278 } //namespace helper
279 
280 } //namespace fwGdcmIO
281 
#define SPTR(_cls_)
static FWGDCMIO_API void dumpSR(const std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > &root, std::ostream &out=std::cout)
Dump the SR in graphviz format.
const SubNodeContainer & getSubNodeContainer() const
Get Sub node container.
Definition: DicomSRNode.hpp:53
static void readSubNode(const ::gdcm::DataSet &dataset, std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > parent)
Read a sub node and add it as a child to the parent node.
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
#define SLM_WARN(message)
Definition: spyLog.hpp:261
static void readSubNodeContainer(const ::gdcm::DataSet &dataset, std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > parent)
Read all sub nodes and add it as children to the parent node.
This class defines a node in a SR document.
Definition: DicomSRNode.hpp:27
This class defines a CONTAINER node in a SR document.
FWGDCMIO_API void addSubNode(const std::shared_ptr< DicomSRNode > &node)
Add a sub node.
Definition: DicomSRNode.cpp:37
This class contains helpers for DICOM Structured Reporting (SR).
static FWGDCMIO_API void dumpSRNode(const std::shared_ptr< ::fwGdcmIO::container::sr::DicomSRNode > &node, std::ostream &out, int &index)
Dump an SR node in graphviz format.