ANIMA  4.0
animaApplyTransformSerie.cxx
Go to the documentation of this file.
1 #include <tclap/CmdLine.h>
2 
3 #include <itkResampleImageFilter.h>
4 #include <itkMinimumMaximumImageFilter.h>
5 
6 #include <itkNearestNeighborInterpolateImageFunction.h>
7 #include <itkLinearInterpolateImageFunction.h>
8 #include <itkBSplineInterpolateImageFunction.h>
9 #include <itkWindowedSincInterpolateImageFunction.h>
10 #include <itkConstantBoundaryCondition.h>
11 #include <itkImageRegionIterator.h>
12 
13 #include <itkExtractImageFilter.h>
18 
20 #include <itkTransformToDisplacementFieldFilter.h>
21 
22 struct arguments
23 {
24  bool invert;
25  unsigned int exponentiationOrder;
26  unsigned int pthread;
28 
29 };
30 
31 void applyTransformationToGradients(std::string &inputGradientsFileName, std::string &outputGradientsFileName, const arguments &args)
32 {
33  typedef anima::TransformSeriesReader <double, 3> TransformSeriesReaderType;
34  typedef TransformSeriesReaderType::OutputTransformType TransformType;
35  TransformSeriesReaderType *trReader = new TransformSeriesReaderType;
36  trReader->SetInput(args.transfo);
37  trReader->SetInvertTransform(!args.invert);
38  trReader->SetExponentiationOrder(args.exponentiationOrder);
39  trReader->SetNumberOfWorkUnits(args.pthread);
40  trReader->Update();
41  typename TransformType::Pointer transfo = trReader->GetOutputTransform();
42 
43  if (!transfo->IsLinear())
44  throw itk::ExceptionObject(__FILE__,__LINE__,"Transformation is not globally linear",ITK_LOCATION);
45 
46  typedef itk::MatrixOffsetTransformBase <double, 3> LinearTransformType;
47  LinearTransformType::Pointer linearTrsf = LinearTransformType::New();
48  linearTrsf->SetIdentity();
49  for (unsigned int i = 0;i < transfo->GetNumberOfTransforms();++i)
50  linearTrsf->Compose(dynamic_cast <LinearTransformType *> (transfo->GetNthTransform(i).GetPointer()));
51 
52  LinearTransformType::MatrixType linearMatrix = linearTrsf->GetMatrix();
53 
54  typedef anima::GradientFileReader < vnl_vector_fixed <double,3>, double > GFReaderType;
55  GFReaderType gfReader;
56  gfReader.SetGradientFileName(inputGradientsFileName);
57  gfReader.SetGradientIndependentNormalization(false);
58  gfReader.Update();
59 
60  GFReaderType::GradientVectorType directions = gfReader.GetGradients();
61 
62  vnl_vector_fixed <double,3> tmpDir(0.0);
63  for (unsigned int i = 0;i < directions.size();++i)
64  {
65  double norm = 0;
66  double normAfter = 0;
67  for (unsigned int j = 0;j < 3;++j)
68  {
69  tmpDir[j] = 0;
70  for (unsigned int k = 0;k < 3;++k)
71  tmpDir[j] += linearMatrix(j,k) * directions[i][k];
72 
73  norm += directions[i][j] * directions[i][j];
74  normAfter += tmpDir[j] * tmpDir[j];
75  }
76 
77  if (normAfter != 0)
78  {
79  for (unsigned int j = 0;j < 3;++j)
80  tmpDir[j] *= std::sqrt(norm / normAfter);
81  }
82 
83  directions[i] = tmpDir;
84  }
85 
86  std::ofstream outputFile(outputGradientsFileName);
87  for (unsigned int i = 0;i < 3;++i)
88  {
89  for (unsigned int j = 0;j < directions.size();++j)
90  outputFile << directions[j][i] << " ";
91 
92  outputFile << std::endl;
93  }
94 
95  outputFile.close();
96 }
97 
98 template <class ImageType>
99 void
100 applyVectorTransfo(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
101 {
102  typedef itk::VectorImage<double, ImageType::ImageDimension> OutputType;
103 
105  typedef typename TransformSeriesReaderType::OutputTransformType TransformType;
106  TransformSeriesReaderType *trReader = new TransformSeriesReaderType;
107  trReader->SetInput(args.transfo);
108  trReader->SetInvertTransform(args.invert);
109  trReader->SetExponentiationOrder(args.exponentiationOrder);
110  trReader->SetNumberOfWorkUnits(args.pthread);
111  trReader->Update();
112  typename TransformType::Pointer transfo = trReader->GetOutputTransform();
113 
114  std::cout << "Image to transform is vector." << std::endl;
115 
116  typedef itk::ResampleImageFilter<ImageType, OutputType> ResampleFilterType;
117  typename ResampleFilterType::Pointer vectorResampler = ResampleFilterType::New();
118  typename itk::InterpolateImageFunction <ImageType>::Pointer interpolator;
119 
120  if(args.interpolation == "nearest")
121  interpolator = itk::NearestNeighborInterpolateImageFunction<ImageType>::New();
122  else if(args.interpolation == "linear")
123  interpolator = itk::LinearInterpolateImageFunction<ImageType>::New();
124  else
125  {
126  itk::ExceptionObject excp(__FILE__, __LINE__,
127  "bspline and sinc interpolation not suported for vector images yet.",
128  ITK_LOCATION);
129  throw excp;
130  }
131 
132  vectorResampler->SetTransform(transfo);
133  vectorResampler->SetInterpolator(interpolator);
134 
135  typename ImageType::SizeType size;
136  typename ImageType::PointType origin;
137  typename ImageType::SpacingType spacing;
138  typename ImageType::DirectionType direction;
139  direction.SetIdentity();
140  unsigned int imageIODimension = std::min(geometryImageIO->GetNumberOfDimensions(),ImageType::GetImageDimension());
141 
142  for (unsigned int i = 0;i < imageIODimension;++i)
143  {
144  size[i] = geometryImageIO->GetDimensions(i);
145  origin[i] = geometryImageIO->GetOrigin(i);
146  spacing[i] = geometryImageIO->GetSpacing(i);
147  for(unsigned int j = 0;j < imageIODimension;++j)
148  direction(i,j) = geometryImageIO->GetDirection(j)[i];
149  }
150 
151  // Fill the rest
152  for (unsigned int i = imageIODimension;i < ImageType::GetImageDimension();++i)
153  {
154  size[i] = 1;
155  origin[i] = 0;
156  spacing[i] = 1;
157  direction[i][i] = 1;
158  }
159 
160  vectorResampler->SetSize(size);
161  vectorResampler->SetOutputOrigin(origin);
162  vectorResampler->SetOutputSpacing(spacing);
163  vectorResampler->SetOutputDirection(direction);
164 
165  vectorResampler->SetInput(anima::readImage<ImageType>(args.input));
166  vectorResampler->SetNumberOfWorkUnits(args.pthread);
167  vectorResampler->Update();
168 
169  anima::writeImage<OutputType>(args.output, vectorResampler->GetOutput());
170 }
171 
172 template <class ImageType>
173 void
174 applyScalarTransfo4D(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
175 {
176  typedef itk::Image <double, ImageType::ImageDimension> OutputType;
177  const unsigned int InternalImageDimension = 3;
178  typedef itk::Image <double, InternalImageDimension> InternalImageType;
179 
180  typedef anima::TransformSeriesReader <double, InternalImageDimension> TransformSeriesReaderType;
181  typedef typename TransformSeriesReaderType::OutputTransformType TransformType;
182  TransformSeriesReaderType *trReader = new TransformSeriesReaderType;
183  trReader->SetInput(args.transfo);
184  trReader->SetInvertTransform(args.invert);
185  trReader->SetExponentiationOrder(args.exponentiationOrder);
186  trReader->SetNumberOfWorkUnits(args.pthread);
187  trReader->Update();
188  typename TransformType::Pointer transfo = trReader->GetOutputTransform();
189 
190  std::cout << "Image to transform is 4D scalar." << std::endl;
191  typename itk::InterpolateImageFunction <InternalImageType>::Pointer interpolator;
192 
193  if(args.interpolation == "nearest")
194  interpolator = itk::NearestNeighborInterpolateImageFunction<InternalImageType>::New();
195  else if(args.interpolation == "linear")
196  interpolator = itk::LinearInterpolateImageFunction<InternalImageType>::New();
197  else if(args.interpolation == "bspline")
198  interpolator = itk::BSplineInterpolateImageFunction<InternalImageType>::New();
199  else if(args.interpolation == "sinc")
200  {
201  const unsigned int WindowRadius = 4;
202  typedef itk::Function::HammingWindowFunction<WindowRadius> WindowFunctionType;
203  typedef itk::ConstantBoundaryCondition<InternalImageType> BoundaryConditionType;
204  interpolator = itk::WindowedSincInterpolateImageFunction
205  <InternalImageType, WindowRadius, WindowFunctionType, BoundaryConditionType, double >::New();
206  }
207 
208  typename OutputType::PointType origin;
209  typename OutputType::SpacingType spacing;
210  typename OutputType::DirectionType direction;
211  direction.SetIdentity();
212 
213  typename OutputType::RegionType outputRegion;
214  for (unsigned int i = 0;i < InternalImageDimension;++i)
215  {
216  outputRegion.SetIndex(i,0);
217  outputRegion.SetSize(i,geometryImageIO->GetDimensions(i));
218  origin[i] = geometryImageIO->GetOrigin(i);
219  spacing[i] = geometryImageIO->GetSpacing(i);
220  for(unsigned int j = 0;j < InternalImageDimension;++j)
221  direction(i,j) = geometryImageIO->GetDirection(j)[i];
222  }
223 
224  typename ImageType::Pointer inputImage = anima::readImage<ImageType> (args.input);
225  for (unsigned int i = InternalImageDimension;i < ImageType::GetImageDimension();++i)
226  {
227  outputRegion.SetIndex(i,0);
228  outputRegion.SetSize(i,inputImage->GetLargestPossibleRegion().GetSize()[i]);
229  origin[i] = inputImage->GetOrigin()[i];
230  spacing[i] = inputImage->GetSpacing()[i];
231  direction(i,i) = inputImage->GetDirection()(i,i);
232  }
233 
234  typename OutputType::Pointer outputImage = OutputType::New();
235  outputImage->Initialize();
236  outputImage->SetRegions(outputRegion);
237  outputImage->SetOrigin(origin);
238  outputImage->SetSpacing(spacing);
239  outputImage->SetDirection(direction);
240  outputImage->Allocate();
241 
242  typedef itk::MinimumMaximumImageFilter <ImageType> MinMaxFilterType;
243  typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
244  minMaxFilter->SetInput(inputImage);
245  minMaxFilter->SetNumberOfWorkUnits(args.pthread);
246  minMaxFilter->Update();
247 
248  double minImageValue = minMaxFilter->GetMinimum();
249  if (minImageValue < 0)
250  minImageValue = -1024;
251  else
252  minImageValue = 0;
253 
254  unsigned int numImages = inputImage->GetLargestPossibleRegion().GetSize()[InternalImageDimension];
255 
256  for (unsigned int i = 0;i < numImages;++i)
257  {
258  if (i == 0)
259  std::cout << "Resampling sub-image " << i+1 << "/" << numImages << std::flush;
260  else
261  std::cout<<"\033[K\rResampling sub-image " << i+1 << "/" << numImages << std::flush;
262 
264  typename ResampleFilterType::Pointer scalarResampler = ResampleFilterType::New();
265  scalarResampler->SetTransform(transfo);
266  scalarResampler->SetInterpolator(interpolator);
267 
268  typename InternalImageType::SizeType internalSize;
269  typename InternalImageType::PointType internalOrigin;
270  typename InternalImageType::SpacingType internalSpacing;
271  typename InternalImageType::DirectionType internalDirection;
272  internalDirection.SetIdentity();
273 
274  for (unsigned int j = 0;j < InternalImageDimension;++j)
275  {
276  internalSize[j] = geometryImageIO->GetDimensions(j);
277  internalOrigin[j] = geometryImageIO->GetOrigin(j);
278  internalSpacing[j] = geometryImageIO->GetSpacing(j);
279  for(unsigned int k = 0;k < InternalImageDimension;++k)
280  internalDirection(j,k) = geometryImageIO->GetDirection(k)[j];
281  }
282 
283  scalarResampler->SetSize(internalSize);
284  scalarResampler->SetOutputOrigin(internalOrigin);
285  scalarResampler->SetOutputSpacing(internalSpacing);
286  scalarResampler->SetOutputDirection(internalDirection);
287  scalarResampler->SetDefaultPixelValue(minImageValue);
288 
289  typedef itk::ExtractImageFilter <ImageType, InternalImageType> ExtractFilterType;
290  typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New();
291  extractFilter->SetInput(inputImage);
292  extractFilter->SetDirectionCollapseToGuess();
293 
294  typename ImageType::RegionType extractRegion = inputImage->GetLargestPossibleRegion();
295  extractRegion.SetIndex(InternalImageDimension,i);
296  extractRegion.SetSize(InternalImageDimension,0);
297 
298  extractFilter->SetExtractionRegion(extractRegion);
299  extractFilter->SetNumberOfWorkUnits(args.pthread);
300 
301  extractFilter->Update();
302 
303  scalarResampler->SetInput(extractFilter->GetOutput());
304  scalarResampler->SetNumberOfWorkUnits(args.pthread);
305  scalarResampler->Update();
306 
307  extractRegion.SetSize(InternalImageDimension,1);
308  for (unsigned int j = 0;j < InternalImageDimension;++j)
309  {
310  extractRegion.SetIndex(j,scalarResampler->GetOutput()->GetLargestPossibleRegion().GetIndex()[j]);
311  extractRegion.SetSize(j,scalarResampler->GetOutput()->GetLargestPossibleRegion().GetSize()[j]);
312  }
313 
314  itk::ImageRegionIterator <InternalImageType> internalOutItr(scalarResampler->GetOutput(),
315  scalarResampler->GetOutput()->GetLargestPossibleRegion());
316  itk::ImageRegionIterator <OutputType> outItr(outputImage,extractRegion);
317 
318  while (!outItr.IsAtEnd())
319  {
320  outItr.Set(internalOutItr.Get());
321 
322  ++internalOutItr;
323  ++outItr;
324  }
325  }
326 
327  std::cout << std::endl;
328 
329  anima::writeImage<OutputType>(args.output, outputImage);
330 
331 }
332 
333 // Transform application to 3D image or lower
334 template <class ImageType>
335 void
336 applyScalarTransfo(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
337 {
338  typedef itk::Image <double, ImageType::ImageDimension> OutputType;
339 
341  typedef typename TransformSeriesReaderType::OutputTransformType TransformType;
342  TransformSeriesReaderType *trReader = new TransformSeriesReaderType;
343  trReader->SetInput(args.transfo);
344  trReader->SetInvertTransform(args.invert);
345  trReader->SetExponentiationOrder(args.exponentiationOrder);
346  trReader->SetNumberOfWorkUnits(args.pthread);
347  trReader->Update();
348  typename TransformType::Pointer transfo = trReader->GetOutputTransform();
349 
350  std::cout << "Image to transform is scalar" << std::endl;
351  typedef anima::ResampleImageFilter<ImageType, OutputType> ResampleFilterType;
352  typename ResampleFilterType::Pointer scalarResampler = ResampleFilterType::New();
353  typename itk::InterpolateImageFunction <ImageType>::Pointer interpolator;
354 
355  if(args.interpolation == "nearest")
356  interpolator = itk::NearestNeighborInterpolateImageFunction<ImageType>::New();
357  else if(args.interpolation == "linear")
358  interpolator = itk::LinearInterpolateImageFunction<ImageType>::New();
359  else if(args.interpolation == "bspline")
360  interpolator = itk::BSplineInterpolateImageFunction<ImageType>::New();
361  else if(args.interpolation == "sinc")
362  {
363  const unsigned int WindowRadius = 4;
364  typedef itk::Function::HammingWindowFunction<WindowRadius> WindowFunctionType;
365  typedef itk::ConstantBoundaryCondition<ImageType> BoundaryConditionType;
366  interpolator = itk::WindowedSincInterpolateImageFunction
367  <ImageType, WindowRadius, WindowFunctionType, BoundaryConditionType, double >::New();
368  }
369 
370  scalarResampler->SetTransform(transfo);
371  scalarResampler->SetInterpolator(interpolator);
372 
373  typename ImageType::SizeType size;
374  typename ImageType::PointType origin;
375  typename ImageType::SpacingType spacing;
376  typename ImageType::DirectionType direction;
377  direction.SetIdentity();
378  unsigned int imageIODimension = std::min(geometryImageIO->GetNumberOfDimensions(),ImageType::GetImageDimension());
379 
380  for (unsigned int i = 0;i < imageIODimension;++i)
381  {
382  size[i] = geometryImageIO->GetDimensions(i);
383  origin[i] = geometryImageIO->GetOrigin(i);
384  spacing[i] = geometryImageIO->GetSpacing(i);
385  for(unsigned int j = 0; j < imageIODimension; ++j)
386  direction(i,j) = geometryImageIO->GetDirection(j)[i];
387  }
388 
389  // Fill the rest, just in case the geometry was under-dimensioned
390  for (unsigned int i = imageIODimension;i < ImageType::GetImageDimension();++i)
391  {
392  size[i] = 1;
393  origin[i] = 0;
394  spacing[i] = 1;
395  direction(i,i) = 1;
396  }
397 
398  scalarResampler->SetSize(size);
399  scalarResampler->SetOutputOrigin(origin);
400  scalarResampler->SetOutputSpacing(spacing);
401  scalarResampler->SetOutputDirection(direction);
402 
403  typename ImageType::Pointer inputImage = anima::readImage<ImageType>(args.input);
404 
405  typedef itk::MinimumMaximumImageFilter <ImageType> MinMaxFilterType;
406  typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
407  minMaxFilter->SetInput(inputImage);
408  minMaxFilter->SetNumberOfWorkUnits(args.pthread);
409  minMaxFilter->Update();
410 
411  double minImageValue = minMaxFilter->GetMinimum();
412  if (minImageValue < 0)
413  minImageValue = -1024;
414  else
415  minImageValue = 0;
416 
417  scalarResampler->SetDefaultPixelValue(minImageValue);
418  scalarResampler->SetInput(inputImage);
419  scalarResampler->SetNumberOfWorkUnits(args.pthread);
420  scalarResampler->Update();
421 
422  anima::writeImage<OutputType>(args.output, scalarResampler->GetOutput());
423 }
424 
425 template <class ComponentType, int Dimension>
426 void
427 checkIfComponentsAreVectors(itk::ImageIOBase::Pointer inputImageIO, itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
428 {
429  if (inputImageIO->GetNumberOfComponents() > 1)
430  {
431  if (Dimension > 3)
432  throw itk::ExceptionObject (__FILE__, __LINE__, "Number of dimensions not supported for vector image resampling", ITK_LOCATION);
433 
434  applyVectorTransfo < itk::VectorImage<ComponentType, 3> > (geometryImageIO, args);
435  }
436  else
437  {
438  if (Dimension < 4)
439  applyScalarTransfo < itk::Image<ComponentType, 3> > (geometryImageIO, args);
440  else
441  applyScalarTransfo4D < itk::Image<ComponentType, 4> > (geometryImageIO, args);
442  }
443 }
444 
445 template <class ComponentType>
446 void
447 retrieveNbDimensions(itk::ImageIOBase::Pointer inputImageIO, itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
448 {
449  if (inputImageIO->GetNumberOfDimensions() > 4)
450  throw itk::ExceptionObject(__FILE__, __LINE__, "Number of dimensions not supported.", ITK_LOCATION);
451 
452  if (inputImageIO->GetNumberOfDimensions() > 3)
453  checkIfComponentsAreVectors<ComponentType, 4> (inputImageIO, geometryImageIO, args);
454  else
455  checkIfComponentsAreVectors<ComponentType, 3> (inputImageIO, geometryImageIO, args);
456 }
457 
458 
459 int main(int ac, const char** av)
460 {
461  std::string descriptionMessage = "Resampler tool to apply a series of transformations to an image.\n"
462  "Input transform is an XML file describing all transforms to apply.\n"
463  "Such args file should look like this:\n"
464  "<TransformationList>\n"
465  "<Transformation>\n"
466  "<Type>linear</Type> (it can be svf or dense too)\n"
467  "<Path>FileName</Path>\n"
468  "<Inversion>0</Inversion>\n"
469  "</Transformation>\n"
470  "...\n"
471  "</TransformationList>\n"
472  "Note that only geometries and input with the same number of dimensions are supported for now.\n"
473  "The default interpolation method is linear, it can be [nearest, linear, bspline, sinc]."
474  "INRIA / IRISA - VisAGeS/Empenn Team";
475 
476  TCLAP::CmdLine cmd(descriptionMessage, ' ',ANIMA_VERSION);
477 
478  TCLAP::ValueArg<std::string> inArg("i","input","Input image",true,"","input image",cmd);
479  TCLAP::ValueArg<std::string> trArg("t","trsf","Transformations XML list",true,"","transformations list",cmd);
480  TCLAP::ValueArg<std::string> outArg("o","output","Output resampled image",true,"","output image",cmd);
481  TCLAP::ValueArg<std::string> geomArg("g","geometry","Geometry image",true,"","geometry image",cmd);
482 
483  TCLAP::ValueArg<std::string> outTrArg("T", "output_trsf", "Output resulting transformation field (dense not SVF)", false, "", "output transfo", cmd);
484  TCLAP::ValueArg<std::string> bvecArg("","grad","DWI gradient file",false,"","gradient file",cmd);
485  TCLAP::ValueArg<std::string> bvecOutArg("O","out-grad","Output gradient file",false,"","gradient file",cmd);
486 
487  TCLAP::ValueArg<unsigned int> expOrderArg("e","exp-order","Order of field exponentiation approximation (in between 0 and 1, default: 0)",false,0,"exponentiation order",cmd);
488  TCLAP::SwitchArg invertArg("I","invert","Invert the transformation series",cmd,false);
489  TCLAP::ValueArg<std::string> interpolationArg("n",
490  "interpolation",
491  "interpolation method to use [nearest, linear, bspline, sinc]",
492  false,
493  "linear",
494  "interpolation method",
495  cmd);
496 
497  TCLAP::ValueArg<unsigned int> nbpArg("p","numberofthreads","Number of threads to run on (default : all cores)",
498  false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),"number of threads",cmd);
499 
500  try
501  {
502  cmd.parse(ac,av);
503  }
504  catch (TCLAP::ArgException& e)
505  {
506  std::cerr << "Error: " << e.error() << "for argument " << e.argId() << std::endl;
507  return EXIT_FAILURE;
508  }
509 
510  // Find out the type of the image in file
511  itk::ImageIOBase::Pointer inputImageIO = itk::ImageIOFactory::CreateImageIO(inArg.getValue().c_str(),
512  itk::ImageIOFactory::ReadMode);
513  itk::ImageIOBase::Pointer geometryImageIO = itk::ImageIOFactory::CreateImageIO(geomArg.getValue().c_str(),
514  itk::ImageIOFactory::ReadMode);
515  if(!inputImageIO)
516  {
517  std::cerr << "Itk could not find suitable IO factory for the input." << std::endl;
518  return EXIT_FAILURE;
519  }
520  if(!geometryImageIO)
521  {
522  std::cerr << "Itk could not find suitable IO factory for the geometry image." << std::endl;
523  return EXIT_FAILURE;
524  }
525  if(inputImageIO->GetNumberOfDimensions() != geometryImageIO->GetNumberOfDimensions())
526  {
527  std::cerr << "Input and geometry images have to have the same number of dimensions." << std::endl;
528  return EXIT_FAILURE;
529  }
530 
531  // Now that we found the appropriate ImageIO class, ask it to read the meta data from the image file.
532  inputImageIO->SetFileName(inArg.getValue());
533  inputImageIO->ReadImageInformation();
534  geometryImageIO->SetFileName(geomArg.getValue());
535  geometryImageIO->ReadImageInformation();
536 
537  arguments args;
538  args.input = inArg.getValue();
539  args.output = outArg.getValue();
540  args.geometry = geomArg.getValue();
541  args.transfo = trArg.getValue();
542  args.invert = invertArg.getValue();
543  args.pthread = nbpArg.getValue();
544  args.exponentiationOrder = expOrderArg.getValue();
545  args.interpolation = interpolationArg.getValue();
546 
547  bool badInterpolation = true;
548  std::string interpolations[4] = {"nearest", "linear", "bspline", "sinc"};
549  for(int i = 0; i < 4; ++i)
550  {
551  if(args.interpolation == interpolations[i])
552  {
553  badInterpolation = false;
554  break;
555  }
556  }
557 
558  if (badInterpolation)
559  std::cerr << "Interpolation method not supported, it must be one of [nearest, linear, bspline, sinc]." << std::endl;
560 
561  try
562  {
563  ANIMA_RETRIEVE_COMPONENT_TYPE(inputImageIO,
565  inputImageIO,
566  geometryImageIO,
567  args)
568  }
569  catch ( itk::ExceptionObject & err )
570  {
571  std::cerr << "Can't apply transformation, be sure to use valid arguments..." << std::endl;
572  std::cerr << err << std::endl;
573  return EXIT_FAILURE;
574  }
575 
576  if (bvecArg.getValue() != "")
577  {
578  std::string outputGradientFileName = bvecOutArg.getValue();
579  if (outputGradientFileName == "")
580  {
581  outputGradientFileName = bvecArg.getValue();
582  outputGradientFileName = outputGradientFileName.erase(outputGradientFileName.find_first_of('.'));
583  outputGradientFileName += "_tr.bvec";
584  }
585 
586  try
587  {
588  applyTransformationToGradients(bvecArg.getValue(),outputGradientFileName,args);
589  }
590  catch (itk::ExceptionObject & err)
591  {
592  std::cerr << "Can't apply transformation to gradients, be sure to use valid arguments..." << std::endl;
593  std::cerr << err << std::endl;
594  return EXIT_FAILURE;
595  }
596  }
597 
598  // Generate the dense deformation field resulting from the composition of the transformations
599  if (outTrArg.getValue() != "")
600  {
601  typedef double CoordinateRepType;
602  typedef itk::Vector< CoordinateRepType, 3> VectorPixelType;
603  typedef itk::Image< VectorPixelType, 3> DisplacementFieldImageType;
604  typedef itk::TransformToDisplacementFieldFilter <DisplacementFieldImageType, CoordinateRepType> DisplacementFieldGeneratorType;
605 
606  DisplacementFieldGeneratorType::Pointer dispFieldGenerator = DisplacementFieldGeneratorType::New();
607  DisplacementFieldImageType::DirectionType dirMatrix;
608  DisplacementFieldImageType::SpacingType spacingVector;
609  DisplacementFieldImageType::PointType originVector;
610  DisplacementFieldImageType::SizeType sizeOutput;
611  DisplacementFieldImageType::IndexType indexOutput;
612 
613  typedef anima::TransformSeriesReader <CoordinateRepType, 3> TransformSeriesReaderType;
614  typedef TransformSeriesReaderType::OutputTransformType TransformType;
615  TransformSeriesReaderType *trReader = new TransformSeriesReaderType;
616  trReader->SetInput(args.transfo);
617  trReader->SetExponentiationOrder(args.exponentiationOrder);
618  trReader->SetInvertTransform(!args.invert);
619  trReader->Update();
620  typename TransformType::Pointer transfo = trReader->GetOutputTransform();
621 
622  for (unsigned int i = 0; i < 3; ++i)
623  {
624  originVector[i] = geometryImageIO->GetOrigin(i);
625  spacingVector[i] = geometryImageIO->GetSpacing(i);
626  indexOutput[i] = 0;
627  sizeOutput[i] = geometryImageIO->GetDimensions(i);
628 
629  for (unsigned int j = 0; j < 3; ++j)
630  dirMatrix(i,j) = geometryImageIO->GetDirection(j)[i];
631  }
632 
633  dispFieldGenerator->UseReferenceImageOff();
634  dispFieldGenerator->SetOutputDirection(dirMatrix);
635  dispFieldGenerator->SetOutputOrigin(originVector);
636  dispFieldGenerator->SetOutputSpacing(spacingVector);
637  dispFieldGenerator->SetOutputStartIndex(indexOutput);
638  dispFieldGenerator->SetSize(sizeOutput);
639 
640  dispFieldGenerator->SetTransform(transfo);
641  dispFieldGenerator->SetNumberOfWorkUnits(nbpArg.getValue());
642  dispFieldGenerator->Update();
643 
644  anima::writeImage <DisplacementFieldImageType>(outTrArg.getValue(), dispFieldGenerator->GetOutput());
645  }
646 
647  return EXIT_SUCCESS;
648 }
void applyScalarTransfo(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
void checkIfComponentsAreVectors(itk::ImageIOBase::Pointer inputImageIO, itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
std::string interpolation
std::string output
void retrieveNbDimensions(itk::ImageIOBase::Pointer inputImageIO, itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
int main(int ac, const char **av)
void applyTransformationToGradients(std::string &inputGradientsFileName, std::string &outputGradientsFileName, const arguments &args)
void SetGradientFileName(std::string fName)
#define ANIMA_RETRIEVE_COMPONENT_TYPE(imageIO, function,...)
void SetInput(std::string const &trListName)
unsigned int exponentiationOrder
std::string input
void applyVectorTransfo(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)
void applyScalarTransfo4D(itk::ImageIOBase::Pointer geometryImageIO, const arguments &args)