ANIMA  4.0
animaTransformSeriesReader.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 #include <tinyxml2.h>
5 
6 #include <itkTransformFileReader.h>
7 #include <itkImageFileReader.h>
8 
9 #include <itkMatrixOffsetTransformBase.h>
10 #include <itkStationaryVelocityFieldTransform.h>
11 #include <rpiDisplacementFieldTransform.h>
12 #include <animaVelocityUtils.h>
13 
14 namespace anima
15 {
16 
17 template <class TScalarType, unsigned int NDimensions>
20 {
21  m_OutputTransform = NULL;
22  m_InvertTransform = false;
23 
24  m_ExponentiationOrder = 1;
25  m_NumberOfThreads = itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads();
26 }
27 
28 template <class TScalarType, unsigned int NDimensions>
31 {
32 
33 }
34 
35 template <class TScalarType, unsigned int NDimensions>
36 void
39 {
40  m_OutputTransform = OutputTransformType::New();
41  std::vector <TransformInformation> transformationList;
42 
43  tinyxml2::XMLDocument doc;
44  tinyxml2::XMLError loadOk = doc.LoadFile(m_Input.c_str());
45 
46  if (loadOk != tinyxml2::XML_SUCCESS)
47  {
48  std::string error("Unable to read input summary file: ");
49  error += m_Input;
50  throw itk::ExceptionObject(__FILE__, __LINE__,error,ITK_LOCATION);
51  }
52 
53  // Read XML file into transform information vector
54  tinyxml2::XMLElement *rootNode = doc.FirstChildElement( "TransformationList" );
55 
56  if (rootNode)
57  {
58  tinyxml2::XMLElement *trsfNode = rootNode->FirstChildElement("Transformation");
59 
60  while (trsfNode)
61  {
62  TransformInformation infoTrsf;
63  tinyxml2::XMLElement *typeNode = trsfNode->FirstChildElement("Type");
64  if (!typeNode)
65  throw itk::ExceptionObject(__FILE__, __LINE__,"Type of transformation not found for a transform in the list",ITK_LOCATION);
66 
67  std::string typeStr = typeNode->GetText();
68  typeStr = typeStr.substr(typeStr.find_first_not_of(" \n\r\t"));
69  typeStr.erase(typeStr.find_last_not_of(" \n\r\t")+1);
70 
71  if (typeStr == "linear")
72  infoTrsf.trType = LINEAR;
73  else if (typeStr == "svf")
74  infoTrsf.trType = SVF_FIELD;
75  else if (typeStr == "dense")
76  infoTrsf.trType = DENSE_FIELD;
77  else
78  {
79  std::string error("Transformation type ");
80  error += typeStr;
81  error += " not supported...";
82  throw itk::ExceptionObject(__FILE__, __LINE__,error,ITK_LOCATION);
83  }
84 
85  tinyxml2::XMLElement *invertNode = trsfNode->FirstChildElement("Inversion");
86  if (invertNode)
87  {
88  std::string invertValue = invertNode->GetText();
89  infoTrsf.invert = (invertValue != "0");
90  }
91  else
92  infoTrsf.invert = false;
93 
94  if (m_InvertTransform)
95  infoTrsf.invert = !infoTrsf.invert;
96 
97  tinyxml2::XMLElement *fileNode = trsfNode->FirstChildElement("Path");
98  if (!fileNode)
99  throw itk::ExceptionObject(__FILE__, __LINE__,"File name not found for a transform in the list",ITK_LOCATION);
100 
101  infoTrsf.fileName = fileNode->GetText();
102  infoTrsf.fileName = infoTrsf.fileName.substr(infoTrsf.fileName.find_first_not_of(" \n\r\t"));
103  infoTrsf.fileName.erase(infoTrsf.fileName.find_last_not_of(" \n\r\t")+1);
104 
105  transformationList.push_back(infoTrsf);
106 
107  trsfNode = trsfNode->NextSiblingElement("Transformation");
108  }
109  }
110 
111  // Now really load and handle global and local transform serie inversion
112  // The fact that you have to apply transforms in the reverse order than the one in text file
113  // is handled by the general transform
114 
115  if (m_InvertTransform)
116  {
117  for (int i = transformationList.size() - 1;i >= 0;--i)
118  {
119  switch (transformationList[i].trType)
120  {
121  case LINEAR:
122  this->addLinearTransformation(transformationList[i].fileName,transformationList[i].invert);
123  break;
124 
125  case SVF_FIELD:
126  this->addSVFTransformation(transformationList[i].fileName,transformationList[i].invert);
127  break;
128 
129  case DENSE_FIELD:
130  default:
131  this->addDenseTransformation(transformationList[i].fileName,transformationList[i].invert);
132  break;
133  }
134  }
135  }
136  else
137  {
138  for (unsigned int i = 0;i < transformationList.size();++i)
139  {
140  switch (transformationList[i].trType)
141  {
142  case LINEAR:
143  this->addLinearTransformation(transformationList[i].fileName,transformationList[i].invert);
144  break;
145 
146  case SVF_FIELD:
147  this->addSVFTransformation(transformationList[i].fileName,transformationList[i].invert);
148  break;
149 
150  case DENSE_FIELD:
151  default:
152  this->addDenseTransformation(transformationList[i].fileName,transformationList[i].invert);
153  break;
154  }
155  }
156  }
157 
158  std::cout << "Loaded " << m_OutputTransform->GetNumberOfTransforms() << " transformations from transform list file: " << m_Input << std::endl;
159 }
160 
161 template <class TScalarType, unsigned int NDimensions>
162 void
164 ::addLinearTransformation(std::string &fileName,bool invert)
165 {
166  typedef itk::MatrixOffsetTransformBase <TScalarType,NDimensions> MatrixTransformType;
167  typedef typename MatrixTransformType::Pointer MatrixTransformPointer;
168 
169  itk::TransformFileReader::Pointer reader = itk::TransformFileReader::New();
170  reader->SetFileName(fileName);
171  reader->Update();
172 
173  const itk::TransformFileReader::TransformListType *trsfList = reader->GetTransformList();
174  itk::TransformFileReader::TransformListType::const_iterator tr_it = trsfList->begin();
175 
176  MatrixTransformPointer trsf = dynamic_cast <MatrixTransformType *> ((*tr_it).GetPointer());
177 
178  if (invert)
179  {
180  MatrixTransformPointer tmpInvert = MatrixTransformType::New();
181  trsf->GetInverse(tmpInvert);
182 
183  trsf = tmpInvert;
184  }
185 
186  m_OutputTransform->AddTransform(trsf);
187 }
188 
189 template <class TScalarType, unsigned int NDimensions>
190 void
192 ::addDenseTransformation(std::string &fileName, bool invert)
193 {
194  typedef rpi::DisplacementFieldTransform <TScalarType,NDimensions> DenseTransformType;
195  typedef typename DenseTransformType::Pointer DenseTransformPointer;
196  typedef typename DenseTransformType::VectorFieldType DisplacementFieldType;
197 
198  typedef itk::ImageFileReader<DisplacementFieldType> DispReaderType;
199  typename DispReaderType::Pointer trReader = DispReaderType::New();
200  trReader->SetFileName(fileName);
201  trReader->Update();
202 
203  DenseTransformPointer dispTrsf = DenseTransformType::New();
204  dispTrsf->SetParametersAsVectorField(trReader->GetOutput());
205 
206  if (invert)
207  {
208  DenseTransformPointer tmpInvert = DenseTransformType::New();
209  dispTrsf->GetInverse(tmpInvert);
210 
211  dispTrsf = tmpInvert;
212  }
213 
214  m_OutputTransform->AddTransform(dispTrsf);
215 }
216 
217 template <class TScalarType, unsigned int NDimensions>
218 void
220 ::addSVFTransformation(std::string &fileName, bool invert)
221 {
222  typedef itk::StationaryVelocityFieldTransform <TScalarType,NDimensions> SVFTransformType;
223  typedef typename SVFTransformType::Pointer SVFTransformPointer;
224  typedef typename SVFTransformType::VectorFieldType VelocityFieldType;
225 
226  typedef rpi::DisplacementFieldTransform <TScalarType,NDimensions> DenseTransformType;
227  typedef typename DenseTransformType::Pointer DenseTransformPointer;
228 
229  typedef itk::ImageFileReader<VelocityFieldType> SVFReaderType;
230  typename SVFReaderType::Pointer trReader = SVFReaderType::New();
231  trReader->SetFileName(fileName);
232  trReader->Update();
233 
234  SVFTransformPointer svfPointer = SVFTransformType::New();
235  svfPointer->SetParametersAsVectorField(trReader->GetOutput());
236 
237  DenseTransformPointer dispTrsf = DenseTransformType::New();
238  anima::GetSVFExponential(svfPointer.GetPointer(),dispTrsf.GetPointer(),m_ExponentiationOrder,m_NumberOfThreads,invert);
239 
240  m_OutputTransform->AddTransform(dispTrsf);
241 }
242 
243 } // end of namespace anima
void addLinearTransformation(std::string &fileName, bool invert)
void addSVFTransformation(std::string &fileName, bool invert)
void GetSVFExponential(itk::StationaryVelocityFieldTransform< ScalarType, NDimensions > *baseTrsf, rpi::DisplacementFieldTransform< ScalarType, NDimensions > *resultTransform, unsigned int exponentiationOrder, unsigned int numThreads, bool invert)
void addDenseTransformation(std::string &fileName, bool invert)