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  typename TProjectionsReaderType::OutputImageSizeType upperCrop, lowerCrop;
230  upperCrop.Fill(0);
231  lowerCrop.Fill(0);
232  for (unsigned int i = 0; i < args_info.lowercrop_given; i++)
233  lowerCrop[i] = args_info.lowercrop_arg[i];
234  reader->SetLowerBoundaryCropSize(lowerCrop);
235  for (unsigned int i = 0; i < args_info.uppercrop_given; i++)
236  upperCrop[i] = args_info.uppercrop_arg[i];
237  reader->SetUpperBoundaryCropSize(upperCrop);
238 
239  // Conditional median
240  typename TProjectionsReaderType::MedianRadiusType medianRadius;
241  medianRadius.Fill(0);
242  for (unsigned int i = 0; i < args_info.radius_given; i++)
243  medianRadius[i] = args_info.radius_arg[i];
244  reader->SetMedianRadius(medianRadius);
245  if (args_info.multiplier_given)
246  reader->SetConditionalMedianThresholdMultiplier(args_info.multiplier_arg);
247 
248  // Shrink / Binning
249  typename TProjectionsReaderType::ShrinkFactorsType binFactors;
250  binFactors.Fill(1);
251  for (unsigned int i = 0; i < args_info.binning_given; i++)
252  binFactors[i] = args_info.binning_arg[i];
253  reader->SetShrinkFactors(binFactors);
254 
255  // Boellaard scatter correction
256  if (args_info.spr_given)
257  reader->SetScatterToPrimaryRatio(args_info.spr_arg);
258  if (args_info.nonneg_given)
259  reader->SetNonNegativityConstraintThreshold(args_info.nonneg_arg);
260  if (args_info.airthres_given)
261  reader->SetAirThreshold(args_info.airthres_arg);
262 
263  // I0 and IDark
264  if (args_info.i0_given)
265  reader->SetI0(args_info.i0_arg);
266  reader->SetIDark(args_info.idark_arg);
267 
268  // Line integral flag
269  if (args_info.nolineint_flag)
270  reader->ComputeLineIntegralOff();
271 
272  // Water precorrection
273  if (args_info.wpc_given)
274  {
275  std::vector<double> coeffs;
276  coeffs.assign(args_info.wpc_arg, args_info.wpc_arg + args_info.wpc_given);
277  reader->SetWaterPrecorrectionCoefficients(coeffs);
278  }
279 
280  // Pass list to projections reader
281  reader->SetFileNames(fileNames);
282  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation());
283 }
284 
293 template <class TArgsInfo, class TIterativeReconstructionFilter>
294 void
295 SetBackProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)
296 {
297  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;
298  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;
299  if (args_info.attenuationmap_given)
300  {
301  // Read an existing image to initialize the attenuation map
302  attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);
303  }
304 
305  switch (args_info.bp_arg)
306  {
307  case (-1): // bp__NULL, keep default
308  break;
309  case (0): // bp_arg_VoxelBasedBackProjection
310  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_VOXELBASED);
311  break;
312  case (1): // bp_arg_Joseph
313  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPH);
314  break;
315  case (2): // bp_arg_CudaVoxelBased
316  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDAVOXELBASED);
317  break;
318  case (3): // bp_arg_CudaRayCast
319  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDARAYCAST);
320  if (args_info.step_given)
321  recon->SetStepSize(args_info.step_arg);
322  break;
323  case (4): // bp_arg_JosephAttenuated
324  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPHATTENUATED);
325  if (args_info.attenuationmap_given)
326  recon->SetAttenuationMap(attenuationMap);
327  break;
328  case (5): // bp_arg_RotationBased
329  recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_ZENG);
330  if (args_info.sigmazero_given)
331  recon->SetSigmaZero(args_info.sigmazero_arg);
332  if (args_info.alphapsf_given)
333  recon->SetAlphaPSF(args_info.alphapsf_arg);
334  if (args_info.attenuationmap_given)
335  recon->SetAttenuationMap(attenuationMap);
336  break;
337  }
338 }
339 
348 template <class TArgsInfo, class TIterativeReconstructionFilter>
349 void
350 SetForwardProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)
351 {
352  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;
353  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;
354  if (args_info.attenuationmap_given)
355  {
356  // Read an existing image to initialize the attenuation map
357  attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);
358  }
360  typename ClipImageType::Pointer inferiorClipImage, superiorClipImage;
361  if (args_info.inferiorclipimage_given)
362  {
363  // Read an existing image to initialize the attenuation map
364  inferiorClipImage = itk::ReadImage<ClipImageType>(args_info.inferiorclipimage_arg);
365  }
366  if (args_info.superiorclipimage_given)
367  {
368  // Read an existing image to initialize the attenuation map
369  superiorClipImage = itk::ReadImage<ClipImageType>(args_info.superiorclipimage_arg);
370  }
371 
372  switch (args_info.fp_arg)
373  {
374  case (-1): // fp__NULL, keep default
375  break;
376  case (0): // fp_arg_Joseph
377  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPH);
378  if (args_info.superiorclipimage_given)
379  recon->SetSuperiorClipImage(superiorClipImage);
380  if (args_info.inferiorclipimage_given)
381  recon->SetInferiorClipImage(inferiorClipImage);
382  break;
383  case (1): // fp_arg_CudaRayCast
384  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_CUDARAYCAST);
385  if (args_info.step_given)
386  recon->SetStepSize(args_info.step_arg);
387  break;
388  case (2): // fp_arg_JosephAttenuated
389  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPHATTENUATED);
390  if (args_info.superiorclipimage_given)
391  recon->SetSuperiorClipImage(superiorClipImage);
392  if (args_info.inferiorclipimage_given)
393  recon->SetInferiorClipImage(inferiorClipImage);
394  if (args_info.attenuationmap_given)
395  recon->SetAttenuationMap(attenuationMap);
396  break;
397  case (3): // fp_arg_RotationBased
398  recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_ZENG);
399  if (args_info.sigmazero_given)
400  recon->SetSigmaZero(args_info.sigmazero_arg);
401  if (args_info.alphapsf_given)
402  recon->SetAlphaPSF(args_info.alphapsf_arg);
403  if (args_info.attenuationmap_given)
404  recon->SetAttenuationMap(attenuationMap);
405  break;
406  }
407 }
408 
409 } // namespace rtk
410 
411 #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:93