RTK  2.7.0
Reconstruction Toolkit
rtkGgoFunctions.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright RTK Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * https://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 
19 // #ifndef RTKGGOFUNCTIONS_H
20 // #define RTKGGOFUNCTIONS_H
21 
22 #ifndef rtkGgoFunctions_h
23 #define rtkGgoFunctions_h
24 
25 #include "rtkMacro.h"
26 #include "rtkConstantImageSource.h"
27 #include "rtkIOFactories.h"
28 #include "rtkProjectionsReader.h"
30 #include <itksys/RegularExpression.hxx>
31 
32 namespace rtk
33 {
34 
48 template <class TConstantImageSourceType, class TArgsInfo>
49 void
50 SetConstantImageSourceFromGgo(TConstantImageSourceType * source, const TArgsInfo & args_info)
51 {
52  using ImageType = typename TConstantImageSourceType::OutputImageType;
53 
54  const unsigned int Dimension = ImageType::GetImageDimension();
55 
56  typename ImageType::SizeType imageSize;
57  if (args_info.dimension_given && !args_info.size_given)
58  {
59  itkGenericOutputMacro(
60  "Warning: --dimension is deprecated and will be removed in a future release. Use --size instead.");
61  imageSize.Fill(args_info.dimension_arg[0]);
62  for (unsigned int i = 0; i < std::min(args_info.dimension_given, Dimension); i++)
63  {
64  imageSize[i] = args_info.dimension_arg[i];
65  }
66  }
67  else
68  {
69  imageSize.Fill(args_info.size_arg[0]);
70  for (unsigned int i = 0; i < std::min(args_info.size_given, Dimension); i++)
71  imageSize[i] = args_info.size_arg[i];
72  }
73 
74  typename ImageType::SpacingType imageSpacing;
75  imageSpacing.Fill(args_info.spacing_arg[0]);
76  for (unsigned int i = 0; i < std::min(args_info.spacing_given, Dimension); i++)
77  imageSpacing[i] = args_info.spacing_arg[i];
78 
79  typename ImageType::PointType imageOrigin;
80  for (unsigned int i = 0; i < Dimension; i++)
81  imageOrigin[i] = imageSpacing[i] * (imageSize[i] - 1) * -0.5;
82  for (unsigned int i = 0; i < std::min(args_info.origin_given, Dimension); i++)
83  imageOrigin[i] = args_info.origin_arg[i];
84 
85  typename ImageType::DirectionType imageDirection;
86  if (args_info.direction_given)
87  for (unsigned int i = 0; i < Dimension; i++)
88  for (unsigned int j = 0; j < Dimension; j++)
89  imageDirection[i][j] = args_info.direction_arg[i * Dimension + j];
90  else
91  imageDirection.SetIdentity();
92 
93  source->SetOrigin(imageOrigin);
94  source->SetSpacing(imageSpacing);
95  source->SetDirection(imageDirection);
96  source->SetSize(imageSize);
97  source->SetConstant({});
98 
99  // Copy output image information from an existing file, if requested
100  // Overwrites parameters given in command line, if any
101  if (args_info.like_given)
102  {
103  using LikeReaderType = itk::ImageFileReader<ImageType>;
104  auto likeReader = LikeReaderType::New();
105  likeReader->SetFileName(args_info.like_arg);
106  TRY_AND_EXIT_ON_ITK_EXCEPTION(likeReader->UpdateOutputInformation());
107  source->SetInformationFromImage(likeReader->GetOutput());
108  }
109 
110  TRY_AND_EXIT_ON_ITK_EXCEPTION(source->UpdateOutputInformation());
111 }
112 
128 template <class TArgsInfo>
129 const std::vector<std::string>
130 GetProjectionsFileNamesFromGgo(const TArgsInfo & args_info)
131 {
132  // Generate file names
134  names->SetDirectory(args_info.path_arg);
135  names->SetNumericSort(args_info.nsort_flag);
136  names->SetRegularExpression(args_info.regexp_arg);
137  names->SetSubMatch(args_info.submatch_arg);
138 
139  if (args_info.verbose_flag)
140  std::cout << "Regular expression matches " << names->GetFileNames().size() << " file(s)..." << std::endl;
141 
142  // Check submatch in file names
143  if (args_info.submatch_given)
144  {
145  // Check that the submatch number returns something relevant
146  itksys::RegularExpression reg;
147  if (!reg.compile(args_info.regexp_arg))
148  {
149  itkGenericExceptionMacro(<< "Error compiling regular expression " << args_info.regexp_arg);
150  }
151 
152  // Store the full filename and the selected sub expression match
153  for (const std::string & name : names->GetFileNames())
154  {
155  reg.find(name);
156  if (reg.match(args_info.submatch_arg) == std::string(""))
157  {
158  itkGenericExceptionMacro(<< "Cannot find submatch " << args_info.submatch_arg << " in " << name
159  << " from regular expression " << args_info.regexp_arg);
160  }
161  }
162  }
163 
164  std::vector<std::string> fileNames = names->GetFileNames();
166  std::vector<size_t> idxtopop;
167  size_t i = 0;
168  for (const auto & fn : fileNames)
169  {
170  itk::ImageIOBase::Pointer imageio =
172 
173  if (imageio.IsNull())
174  {
175  std::cerr << "Ignoring file: " << fn << "\n";
176  idxtopop.push_back(i);
177  }
178  i++;
179  }
180  std::reverse(idxtopop.begin(), idxtopop.end());
181  for (const auto & id : idxtopop)
182  {
183  fileNames.erase(fileNames.begin() + id);
184  }
185 
186  return fileNames;
187 }
188 
189 template <class TProjectionsReaderType, class TArgsInfo>
190 void
191 SetProjectionsReaderFromGgo(TProjectionsReaderType * reader, const TArgsInfo & args_info)
192 {
193  const std::vector<std::string> fileNames = GetProjectionsFileNamesFromGgo(args_info);
194 
195  // Vector component extraction
196  if (args_info.component_given)
197  {
198  reader->SetVectorComponent(args_info.component_arg);
199  }
200 
201  // Change image information
202  const unsigned int Dimension = TProjectionsReaderType::OutputImageType::GetImageDimension();
203  typename TProjectionsReaderType::OutputImageDirectionType direction;
204  if (args_info.newdirection_given)
205  {
206  direction.Fill(args_info.newdirection_arg[0]);
207  for (unsigned int i = 0; i < args_info.newdirection_given; i++)
208  direction[i / Dimension][i % Dimension] = args_info.newdirection_arg[i];
209  reader->SetDirection(direction);
210  }
211  typename TProjectionsReaderType::OutputImageSpacingType spacing;
212  if (args_info.newspacing_given)
213  {
214  spacing.Fill(args_info.newspacing_arg[0]);
215  for (unsigned int i = 0; i < args_info.newspacing_given; i++)
216  spacing[i] = args_info.newspacing_arg[i];
217  reader->SetSpacing(spacing);
218  }
219  typename TProjectionsReaderType::OutputImagePointType origin;
220  if (args_info.neworigin_given)
221  {
222  origin.Fill(args_info.neworigin_arg[0]);
223  for (unsigned int i = 0; i < args_info.neworigin_given; i++)
224  origin[i] = args_info.neworigin_arg[i];
225  reader->SetOrigin(origin);
226  }
227 
228  // Crop boundaries
229  auto lowerCrop = itk::MakeFilled<typename TProjectionsReaderType::OutputImageSizeType>(0);
230  for (unsigned int i = 0; i < args_info.lowercrop_given; i++)
231  lowerCrop[i] = args_info.lowercrop_arg[i];
232  if (args_info.lowercrop_given)
233  reader->SetLowerBoundaryCropSize(lowerCrop);
234 
235  auto upperCrop = itk::MakeFilled<typename TProjectionsReaderType::OutputImageSizeType>(0);
236  for (unsigned int i = 0; i < args_info.uppercrop_given; i++)
237  upperCrop[i] = args_info.uppercrop_arg[i];
238  if (args_info.uppercrop_given)
239  reader->SetUpperBoundaryCropSize(upperCrop);
240 
241  // Conditional median
242  typename TProjectionsReaderType::MedianRadiusType medianRadius;
243  medianRadius.Fill(0);
244  for (unsigned int i = 0; i < args_info.radius_given; i++)
245  medianRadius[i] = args_info.radius_arg[i];
246  reader->SetMedianRadius(medianRadius);
247  if (args_info.multiplier_given)
248  reader->SetConditionalMedianThresholdMultiplier(args_info.multiplier_arg);
249 
250  // Shrink / Binning
251  typename TProjectionsReaderType::ShrinkFactorsType binFactors;
252  binFactors.Fill(1);
253  for (unsigned int i = 0; i < args_info.binning_given; i++)
254  binFactors[i] = args_info.binning_arg[i];
255  reader->SetShrinkFactors(binFactors);
256 
257  // Boellaard scatter correction
258  if (args_info.spr_given)
259  reader->SetScatterToPrimaryRatio(args_info.spr_arg);
260  if (args_info.nonneg_given)
261  reader->SetNonNegativityConstraintThreshold(args_info.nonneg_arg);
262  if (args_info.airthres_given)
263  reader->SetAirThreshold(args_info.airthres_arg);
264 
265  // I0 and IDark
266  if (args_info.i0_given)
267  reader->SetI0(args_info.i0_arg);
268  reader->SetIDark(args_info.idark_arg);
269 
270  // Line integral flag
271  if (args_info.nolineint_flag)
272  reader->ComputeLineIntegralOff();
273 
274  // Water precorrection
275  if (args_info.wpc_given)
276  {
277  std::vector<double> coeffs;
278  coeffs.assign(args_info.wpc_arg, args_info.wpc_arg + args_info.wpc_given);
279  reader->SetWaterPrecorrectionCoefficients(coeffs);
280  }
281 
282  // Pass list to projections reader
283  reader->SetFileNames(fileNames);
284  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation());
285 }
286 
295 template <class TArgsInfo, class TIterativeReconstructionFilter>
296 void
297 SetBackProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)
298 {
299  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;
300  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;
301  if (args_info.attenuationmap_given)
302  {
303  // Read an existing image to initialize the attenuation map
304  attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);
305  }
306 
307  switch (args_info.bp_arg)
308  {
309  case (-1): // bp__NULL, keep default
310  break;
311  case (0): // bp_arg_VoxelBasedBackProjection
312  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_VOXELBASED);
313  break;
314  case (1): // bp_arg_Joseph
315  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPH);
316  break;
317  case (2): // bp_arg_CudaVoxelBased
318  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDAVOXELBASED);
319  break;
320  case (3): // bp_arg_CudaRayCast
321  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDARAYCAST);
322  if (args_info.step_given)
323  recon->SetStepSize(args_info.step_arg);
324  break;
325  case (4): // bp_arg_JosephAttenuated
326  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPHATTENUATED);
327  if (args_info.attenuationmap_given)
328  recon->SetAttenuationMap(attenuationMap);
329  break;
330  case (5): // bp_arg_RotationBased
331  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_ZENG);
332  if (args_info.sigmazero_given)
333  recon->SetSigmaZero(args_info.sigmazero_arg);
334  if (args_info.alphapsf_given)
335  recon->SetAlphaPSF(args_info.alphapsf_arg);
336  if (args_info.attenuationmap_given)
337  recon->SetAttenuationMap(attenuationMap);
338  break;
339  }
340 }
341 
350 template <class TArgsInfo, class TIterativeReconstructionFilter>
351 void
352 SetForwardProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)
353 {
354  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;
355  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;
356  if (args_info.attenuationmap_given)
357  {
358  // Read an existing image to initialize the attenuation map
359  attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);
360  }
362  typename ClipImageType::Pointer inferiorClipImage, superiorClipImage;
363  if (args_info.inferiorclipimage_given)
364  {
365  // Read an existing image to initialize the attenuation map
366  inferiorClipImage = itk::ReadImage<ClipImageType>(args_info.inferiorclipimage_arg);
367  }
368  if (args_info.superiorclipimage_given)
369  {
370  // Read an existing image to initialize the attenuation map
371  superiorClipImage = itk::ReadImage<ClipImageType>(args_info.superiorclipimage_arg);
372  }
373 
374  switch (args_info.fp_arg)
375  {
376  case (-1): // fp__NULL, keep default
377  break;
378  case (0): // fp_arg_Joseph
379  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPH);
380  if (args_info.superiorclipimage_given)
381  recon->SetSuperiorClipImage(superiorClipImage);
382  if (args_info.inferiorclipimage_given)
383  recon->SetInferiorClipImage(inferiorClipImage);
384  break;
385  case (1): // fp_arg_CudaRayCast
386  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_CUDARAYCAST);
387  if (args_info.step_given)
388  recon->SetStepSize(args_info.step_arg);
389  break;
390  case (2): // fp_arg_JosephAttenuated
391  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPHATTENUATED);
392  if (args_info.superiorclipimage_given)
393  recon->SetSuperiorClipImage(superiorClipImage);
394  if (args_info.inferiorclipimage_given)
395  recon->SetInferiorClipImage(inferiorClipImage);
396  if (args_info.attenuationmap_given)
397  recon->SetAttenuationMap(attenuationMap);
398  break;
399  case (3): // fp_arg_RotationBased
400  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_ZENG);
401  if (args_info.sigmazero_given)
402  recon->SetSigmaZero(args_info.sigmazero_arg);
403  if (args_info.alphapsf_given)
404  recon->SetAlphaPSF(args_info.alphapsf_arg);
405  if (args_info.attenuationmap_given)
406  recon->SetAttenuationMap(attenuationMap);
407  break;
408  }
409 }
410 
411 } // namespace rtk
412 
413 #endif // rtkGgoFunctions_h
static ImageIOBasePointer CreateImageIO(const char *path, IOFileModeEnum mode)
const std::vector< std::string > GetProjectionsFileNamesFromGgo(const TArgsInfo &args_info)
Read a stack of 2D projections from gengetopt specifications.
void SetBackProjectionFromGgo(const TArgsInfo &args_info, TIterativeReconstructionFilter *recon)
Set the correct RTK backprojection type from gengetopt Given a gengetopt bp_arg option from the rtkpr...
void SetForwardProjectionFromGgo(const TArgsInfo &args_info, TIterativeReconstructionFilter *recon)
Set the correct RTK forward projection type from gengetopt Given a gengetopt fp_arg option from the r...
void SetConstantImageSourceFromGgo(TConstantImageSourceType *source, const TArgsInfo &args_info)
Create 3D image from gengetopt specifications.
void SetProjectionsReaderFromGgo(TProjectionsReaderType *reader, const TArgsInfo &args_info)
void RTK_EXPORT RegisterIOFactories()
#define TRY_AND_EXIT_ON_ITK_EXCEPTION(execFunc)
Update a filter and catching/displaying exceptions.
Definition: rtkMacro.h:88