-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy pathrtkfourdconjugategradient.cxx
More file actions
136 lines (115 loc) · 5.78 KB
/
Copy pathrtkfourdconjugategradient.cxx
File metadata and controls
136 lines (115 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*=========================================================================
*
* Copyright RTK Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#include "rtkfourdconjugategradient_ggo.h"
#include "rtkGgoFunctions.h"
#include "rtkFourDConjugateGradientConeBeamReconstructionFilter.h"
#include "rtkReorderProjectionsImageFilter.h"
#include "rtkSignalToInterpolationWeights.h"
#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#ifdef RTK_USE_CUDA
# include "itkCudaImage.h"
#endif
#include <itkImageFileWriter.h>
int
main(int argc, char * argv[])
{
GGO(rtkfourdconjugategradient, args_info);
using OutputPixelType = float;
#ifdef RTK_USE_CUDA
using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;
using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;
#else
using VolumeSeriesType = itk::Image<OutputPixelType, 4>;
using ProjectionStackType = itk::Image<OutputPixelType, 3>;
#endif
// Projections reader
using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;
auto reader = ReaderType::New();
rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfourdconjugategradient>(reader, args_info);
TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateLargestPossibleRegion())
// Geometry
if (args_info.verbose_flag)
std::cout << "Reading geometry information from " << args_info.geometry_arg << "..." << std::endl;
rtk::ThreeDCircularProjectionGeometry::Pointer geometry;
TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));
// Create input: either an existing volume read from a file or a blank image
itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;
if (args_info.input_given)
{
// Read an existing image to initialize the volume
auto inputReader = itk::ImageFileReader<VolumeSeriesType>::New();
inputReader->SetFileName(args_info.input_arg);
inputFilter = inputReader;
}
else
{
// Create new empty volume
using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;
auto constantImageSource = ConstantImageSourceType::New();
rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfourdconjugategradient>(
constantImageSource, args_info);
// GenGetOpt can't handle default arguments for multiple arguments like size or spacing.
// The only default it accepts is to set all components of a multiple argument to the same value.
// Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable
// value which is why a "frames" argument is introduced
auto inputSize = itk::MakeSize(constantImageSource->GetSize()[0],
constantImageSource->GetSize()[1],
constantImageSource->GetSize()[2],
args_info.frames_arg);
constantImageSource->SetSize(inputSize);
inputFilter = constantImageSource;
}
TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())
inputFilter->ReleaseDataFlagOn();
// Re-order geometry and projections
// In the new order, projections with identical phases are packed together
std::vector<double> signal = rtk::ReadSignalFile(args_info.signal_arg);
auto reorder = rtk::ReorderProjectionsImageFilter<ProjectionStackType>::New();
reorder->SetInput(reader->GetOutput());
reorder->SetInputGeometry(geometry);
reorder->SetInputSignal(signal);
TRY_AND_EXIT_ON_ITK_EXCEPTION(reorder->Update())
// Release the memory holding the stack of original projections
reader->GetOutput()->ReleaseData();
// Compute the interpolation weights
auto signalToInterpolationWeights = rtk::SignalToInterpolationWeights::New();
signalToInterpolationWeights->SetSignal(reorder->GetOutputSignal());
signalToInterpolationWeights->SetNumberOfReconstructedFrames(
inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));
TRY_AND_EXIT_ON_ITK_EXCEPTION(signalToInterpolationWeights->Update())
// Set the forward and back projection filters to be used
using ConjugateGradientFilterType =
rtk::FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;
auto conjugategradient = ConjugateGradientFilterType::New();
SetForwardProjectionFromGgo(args_info, conjugategradient.GetPointer());
SetBackProjectionFromGgo(args_info, conjugategradient.GetPointer());
conjugategradient->SetInputVolumeSeries(inputFilter->GetOutput());
conjugategradient->SetNumberOfIterations(args_info.niterations_arg);
conjugategradient->SetCudaConjugateGradient(args_info.cudacg_flag);
conjugategradient->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);
// Set the newly ordered arguments
conjugategradient->SetInputProjectionStack(reorder->GetOutput());
conjugategradient->SetGeometry(reorder->GetOutputGeometry());
conjugategradient->SetWeights(signalToInterpolationWeights->GetOutput());
conjugategradient->SetSignal(reorder->GetOutputSignal());
REPORT_ITERATIONS(conjugategradient, ConjugateGradientFilterType, VolumeSeriesType);
TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update())
// Write
TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(conjugategradient->GetOutput(), args_info.output_arg))
return EXIT_SUCCESS;
}