-
Notifications
You must be signed in to change notification settings - Fork 16
Computing the forward and or backward projections
This page details on how to separately compute the forward (Ax) and/or backward projections (A^T y) when using OMEGA.
When you are manually computing the forward and/or backward projections, it is recommended to use the forward_backward_projections_example.m
and modify it according to your specifications.
The initial part works very much like main_PET.m
, however, there are no adjustments for the reconstruction algorithms. You still need to input the necessary information (scanner properties, sinogram/raw data properties, corrections, etc.) before proceeding. For options.precompute_lor = true
you also need to perform the precomputation phase if it hasn’t been performed before. Note that if you want the measurement data to be precorrected, you need to do that manually. Corrections during reconstruction are applied automatically, though in some cases (such as randoms correction) you need to select the correction data when it is prompted.
For the reconstruction, implementations 1, 3 and 4 are supported with 3 recommended.
After the initial setup phase, there are two different ways to actually compute Ax
and A^Ty
. The first, recommended, method is by using a MATLAB/Octave class that is demonstrated in the initial examples in forward_backward_projections_example.m
, the second method is the old one using functions.
First is a class-based exampled computing OSEM/MLEM estimates (line 821) with the use of the special forward and backward projection operators. The major steps needed for class based use is the creation of the class object with forwardBackwardProject(options)
and the load of the measurement data. Sensitivity image can be obtained from the backprojection. PSF is applied automatically if selected.
You can also create the same class object as above without the need for any of the main-files, however, several features are then unavailable (such as corrections). This is achieved by inputting the required variables manually: A = forwardBackwardProject(Nx, Ny, Nz, FOVa_x, axial_fov, diameter, rings, cr_p, cr_pz, cryst_per_block, blocks_per_ring, det_per_ring, Ndist, Nang,NSinos, span, ring_difference, subsets, implementation, use_device, projector_type, tube_width_z, tube_radius, voxel_radius, use_psf, FWHM);
To use your own measurement data, replace load('Cylindrical_PET_example_cylpet_example_sinograms_combined_static_200x168x703_span3.mat','raw_SinM')
with your own custom load or simply run the code up to that and manually load your data (you can use loadMeasurementData
to load custom data, such as interfiles). You should either name your measurement data as raw_SinM
or rename all instances of raw_SinM
to the same name as your input measurement data (options.SinM
if you use loadMeasurementData
). Your input data needs to be oriented the same way as the measurement data used in OMEGA. For sinograms that is thus options.Ndist
x options.Nang
x options.NSinos
. Dynamic data needs to be manually correctly formatted.
The second class-based example computing Conjugate-gradient Least-squares (CGLS) utilizes the operator overloading. This means that after you have created the class (e.g. with A = forwardBackwardProject(options);
) you can then simply multiply this with the desired vector (e.g. A * x
or A * y
). Whether forward or backward projection is computed, is determined automatically from the dimensions of the input vector. Alternative, backprojection can be forced with A' * y
.
Other examples include LSQR, SA-WLS (includes TOF example), ATP-WLS, EM-PKMA with TV regularization and ADMM with TV. Of these, EM-PKMA and ADMM provide examples on how to use the built-in priors. Prepass functions must be run for the following priors:
MRP (options = computeOffsets(options);
)
Quadratic prior (options = computeWeights(options);
and options = quadWeights(options, options.empty_weight);
)
Huber prior (options = computeWeights(options);
and options = huberWeights(options);
)
L-filter (options = computeWeights(options);
, options = computeOffsets(options);
and options.a_L = lfilter_weights(options.Ndx, options.Ndy, options.Ndz, options.FOVa_x/options.Nx, options.FOVa_y/options.Ny, options.axial_fov/options.Nz, options.oneD_weights);
)
FMH (options = computeWeights(options);
, options = computeOffsets(options);
and options = fmhWeights(options);
)
Weighted mean (options = computeWeights(options);
and options = weightedWeights(options);
)
TV (options = TVPrepass(options);
, the following ONLY when options.TVtype = 3
: options = computeWeights(options);
, options = computeOffsets(options);
and options = quadWeights(options, options.empty_weight);
)
APLS (options = APLSPrepass(options);
)
NLM (options = NLMPrepass(options);
).
Furthermore, you can also obtain the (subset of the) system matrix from the same class object. This is demonstrated in the System matrix (OSEM) example between SA-WLS and ATP-WLS.
This is the very last example script in forward_backward_projections_example.m
. It is no longer recommended to compute the forward and/or backward projections this way.
You’ll need to run the index_maker.m
as specified to get the necessary subset indices. The line [gaussK, options] = PSFKernel(options);
is only applicable if PSF reconstruction is used as it creates the PSF kernel gaussK
.
To use your own measurement data, replace load('Cylindrical_PET_example_cylpet_example_sinograms_combined_static_200x168x703_span3.mat','raw_SinM')
with your own custom load or simply run the code up to that and manually load your data (you can use loadMeasurementData
to load custom data, such as interfiles). You should either name your measurement data as raw_SinM
or rename all instances of raw_SinM
to the same name as your input measurement data (options.SinM
if you use loadMeasurementData
). Your input data needs to be oriented the same way as the measurement data used in OMEGA. For sinograms that is thus options.Ndist
x options.Nang
x options.NSinos
. Dynamic data needs to be manually correctly formatted.
After the above steps, simply use the functions forward_project
and backproject
as you like. The example provided uses them the same way as in OSEM, but as they simply implement the operations y = Ax and x = A^Tb, respectively, you can implement any algorithm that uses these matrix-vector operations. An example of PSF reconstruction is included as well. Sensitivity image is obtained with backprojection, but can also be omitted by simply having only one output parameter.
All selected corrections are applied to the forward and/or backward projections. If you wish to use different projectors for the forward or backward projections, you need to manually set options.projector_type
between them. E.g. compute forward projection when options.projector_type = 2
and then set options.projector_type = 1
and compute backprojection. This, however, is untested and may especially not work when using implementation 1. If you wish to use different projectors, it is recommended to use implementation 3 and set options.precompute_lor = false
.
The optional PSF deblurring phase can also be performed and an example of that is also included.
There is also a "simplified" version of the forward/backward projection class. This simplified version accepts the detector coordinates for each coincidence as well as the FOV size and image size. The input structure is thus:
A = forwardBackwardProject(x, y, z, Nx, Ny, Nz, FOVtr, axial_fov, subsets, implementation, platform)
where x
, y
and z
are the detector coordinates corresponding to every element of the input measurement data (vector or matrix), Nx/y/z
are the image size in x/y/z-directions, FOVtr
the FOV size in transaxial direction (length of one side of the square), axial_fov
the size of the FOV in axial direction, subsets
is an optional number of subsets (can be omitted), implementation
the optional implementation that should be used (4 is default, can be omitted) and platform
the device platform for implementation 3 (default is 0, can be omitted, ignored when implementation 4 is used). Implementations 3 and 4 are currently supported.
When used like this, however, no corrections or PSF are supported. All these operations need to be done manually by the user. An example of this type of reconstruction is presented in Inveon_PET_main_listmode_example.m
.
- Home
- Installation help
- Getting started
- PET Tutorials
- CT Tutorials
- Useful information
- Function help
- Visualization
- Using GATE PET data
- Using GATE CT data
- Extracting GATE scatter, randoms and trues data
- Computing the forward and/or backward projections
- Using non-cylindrical PET scanners
- Custom detector coordinates and/or list mode reconstruction
- Using TOF data
- Extracting the system matrix
- Using Inveon PET data
- Using Inveon CT data
- Using Biograph PET data
- Using custom gradient-based priors
- Adding custom built-in algorithms
- Toolbox overview
- Contributing code to OMEGA
- Contact