This version is 95% backwards compatible with STIR 4.0 for the user (see below). Developers might need to make code changes as detailed below.
ProjDataInfoSubsetByView class has been implemented which allows for subsets of projection data.
Previously, subset projections could only be stored in fully sampled ProjData. This is still possible, the implementation is backward compatible, and subset reconstructions such as OSMAPSOL have not been changed.
However, there is now an option to create subsets with ProjData::get_subset which only store a subset of views and so are more memory efficient when subsets might be handled separately.
ProjDataInfoSubsetByView currently does not support file I/O.
BinNormalisation derived class BinNormalisationWithCalibration;
Interfile now reads/writes isotope name and calibration factor. See PR 672.
This code was contributed by Daniel Deidda (NPL) and Kris Thielemans (UCL)Radionuclide and RadionuclideDB;
This code was contributed by Daniel Deidda (NPL) and Kris Thielemans (UCL)dynamic instead of runtime, resulting in faster performance.
Of course, there is also the usual code-cleanup and improvements to the documentation.
This release contains mainly code written by Kris Thielemans (UCL), Richard Brown (UCL), Parisa Khateri and Michael Roethlisberger (ETHZ), Robert Twyman (UCL), Daniel Deidda (NPL), Tahereh Nikjenad (PETsys), Palak Wadhwa (Univ of Leeds), Viet Ahn Dao (Univ of Leeds), Ashley Gillman (CSIRO), Georg Schramm (KUL), Markus Jehl (Positrigo), Gefei Chen (Univ of Macao)
get_phi() which could cause 180 degrees swapsScanner::get_default_intrinsic_tilt() has been renamed to get_intrinsic_azimuthal_tilt().(module_repeater_y * submodule_repeater_y * crystal_repeater_y) /2 - 1)
in the Cylindrical case, was subtracted from the crystalIDsquarter_of_detectors=get_num_detectors_per_ring()/4.offset (num of detectors) parameter in the `.hroot` and
and all underlying methodology has been removed.View offset (degrees) support described above.
See also the expanded section on ROOT data in the STIR User's guide.ProjDataInfo::ProjDataInfoCTI, use ProjDataInfo::construct_proj_data_info instead.
However, this now returns an object of the appropriate (derived) type as opposed to just
ProjDataInfo. This should be transparent, except apparently for testing equality of objects.
Scanner parameters:=
normal parameters...
Scanner geometry (BlocksOnCylindrical/Cylindrical/Generic) := BlocksOnCylindrical
Distance between crystals in axial direction (cm) := 0.22
Distance between crystals in transaxial direction (cm) := 0.22
Distance between blocks in axial direction (cm) := 0.22
Distance between blocks in transaxial direction (cm) := 3.3
end scanner parameters:=
Scatter and normalisation code are still pending changes.
Parallelproj. This will use the CUDA
version if available, otherwise will fall-back to the OpenMP version. Check the new sample files in
examples/samples and the section in the User's Guide.ProjDataInfoSubsetByView is backwards compatible and allows a new, memory efficient method for subset projections.
Subset projections are created with with ProjData::get_subset, which is the only addition to the ProjData class (additions are mostly in the aforementioned new Info class).
ProjDataInfoSubsetByView can be used to set up projectors, which will project only the subset.
ProjDataInfoSubsetByView currently does not support file I/O. Therefore, the interface is not yet accessible through parameter files, only through C++ interface.calculate_attenuation_coefficients utility now accepts an optional forward projection parameter file in the same format as the forward_project utility. Example usage has been added to src/recon_test_pack/simulate_data.sh.
LmToProjData
and list mode reconstructions will then put the LORs more accurately (at least when the ``virtual crystals"
roughly correspond to gaps between blocks). See the update .hroot file in examples/samples.HUToMuImageProcessor class (derived from DataProcessor.
This allows combining it with filtering etc, also from in Python. It means that the
ctac_to_mu_values.cxx utility itself is now obsolete, but it still exists in
this version. (Note that this functionality depends on an external
JSON library.)
BinNormalisationWithCalibration is a new class derived from BinNormalisation. This class allows to apply calibration factor from the scanner and save the information into the interfile header. To use this, a specific BinNormalisation class should be derived from BinNormalisationWithCalibration, the information about the calibration factor read, and the function get_uncalibrated_bin_efficiencies() needs to be overwritten. Note that also the isotope name and branching ratio can be set here (the latter will need to be set according to the isotope by reading into a radionuclide database, see below). BinNormalisationSPECT already reads Calibration factor and isotope name and apply the calibration factor read from interfile. Since not all SPECT scanner do quantitative reconstruction an option of setting the calibration factor from the parameter file is added. Factors for BinNormalisationECA8/ECAT7 and GEHDF5 are set to one at the moment as we need to double check on the meaning of cross calibration factor for ECAT and find out how to read them for GEHDF5. Documentation for this is pending and will be added in the following PR.
Radionuclide is a new class which contains radionuclide information such as halflife, branching ratio, energy etc. This class allows to propagate infrmation trough the reconstruction as it is now a member in the ExamInfo. It is populated from the information extracted from RadionuclideDB which allows to create a Radionuclide object from the information stored in the radionuclide_info.json in the STIR configuration directory. Different vendors, as we saw with SPECT, may have different standards for the isotope name. Three different ones were observed, therefore a lookup table has been added to allow the use of the data base for any different isotope name format. The lookup table is a JSON file stored in radionuclide_names.json.
Scanner has now a new static member get_names_of_predefined_scanners returning a list of names.
compute_total_ROI_values and ROIValues to Python/MATLAB via swig. Added python example ROI_demo.py to demonstrate usage.
ProjDataInfo and Scanner for future compatibility. However, this release still does not support TOF. (Check the GitHub site for the relevant PR).
BinNormalisation, ListModeData, LmToProjData, ProjectorByBinPair, ScatterSimulation, ScatterEstimation and a couple of support classes and functions to Python/MATLAB via swig. Added python example listmode_demo.py to demonstrate usage.
dynamic instead of runtime. On some machines, this was causing slower projection operations due to a static scheduler being selected by default. See Issue #935 for more details.
ProjDataInMemory are now much faster (it now uses an underlying 1D array).
ParametricDiscretisedDensity objects can now have an ExamInfo object
with multiple time frames (corresponding to the time frames of the data where the parametric image is derived from).
In some cases, there could only be a single time frame (start to end of the study).
find_ML_normfactors3D and apply_ML_normfactors3D can be used for scanner with virtual crystal (Only verified on mCT).
Contributed by Gefei Chen, see PR 833.
find_ML_normfactors3D. Otherwise, we use a block.
The use of an argument --for-symmetry-per-block in the find_ML_normfactors3D utility will use the symmetry size of a block.
CMAKE_CXX_STANDARD, see the CMake
documentation for supported values.find_package(STIR), your compiler will be set to use
at least C++-11 (via CMake's target_compile_features).ProjDataInterfile so renamed
the test to test_proj_data.
InterfilePDFSHeader now contain a shared_ptr<ProjDataInfo> instead of a raw pointer, removing a memory leak.shared_ptr:shared_ptr allowed unsafe access to
the objects (although this never happened in distributed STIR code). We now prevent this with changes to the class interface (although there is still work to do):
shared_ptr<ProjDataInfo> now contain a shared_ptr<const ProjDataInfo>, and similar for DiscretisedDensityget_proj_data_info_sptr used to return shared_ptr<ProjDataInfo>, but now returns shared_ptr<const ProjDataInfo>, similar for ExamInfo.set_up, that accept shared_ptr now take a shared_ptr to a const object.ProjData*::copy_to and fill_from now return the updated iterator (as opposed to the size). This is like std::copy, and more convenient for reusing it.
ModelMatrix::set_if_uncalibrated and ModelMatrix::get_if_uncalibrated renamed to ModelMatrix::set_is_uncalibrated and ModelMatrix::get_is_uncalibratedPlasmaData::set_if_decay_corrected and PlasmaData::get_if_decay_corrected renamed to PlasmaData::set_is_decay_corrected and PlasmaData::get_is_decay_correctedPatlakPlot::get_model_matrix, now it can only be called using class membersBinNormalisation::set_up() now need exam_info_sptr as input.BinNormalisation::apply() and undo now no longer accept start_time and end_time as they are taken from exam_info. To allow this to happen, class Bin has now an extra member time_frame(). Note that it defaults to 1. If this is incorrect, it has to be initialised explicitly (not via a constructor).DetectorCoordinateMapFromfile (used by SAFIR listmode files) has been renamed to DetectorCoordinateMap and moved from listmode to buildblock.Scanner now has a set_up() function. This needs to be called after
using any of the set_*() functions (except set_params). For the blocks/generic
scanners, this will fill in the detector maps etc.
You will get a run-time exception if you forgot to do this.
stir::copy_to and stir::fill_from in stir/copy_fill.h which
can be used to fill most STIR objects from an iterator range (or copy to).
The functions normally use stir_object.begin_all() but resort to stir_object::fill_from or copy_to for a few cases where no iterators exist. We use some specialisations to try and find the fastest version.
ProjData::standard_segment_sequence function returning 0,+1,-1,...,
as used by copy_to and fill_from
stir::read_from_file can now be called with a "node", e.g.
auto uptr = read_from_file<VoxelsOnCartesianGrid<float> >(filename);
To do this, we now need a typedef hierarchy_base_type at the top level, as otherwise
we would need multiple registries. However, this was already required by write_to_file anyway.
GeneralisedPrior and QuadraticPrior have a new method accumulate_Hessian_times_input(output, current_estimate, input). This computes the hessian of the prior at the current_image_estimate and multiplies this by input.
Before this, the add_multiplication_with_approximate_Hessian(output, input) method was used that assumed a quadratic function and therefore hessian = 1.
Exam_info, TimeFrameDefinition and PatientPosition have now a == operatorcompute_total_ROI_values and compute_ROI_values_per_plane functions to allow the passing of aVoxelsOnCartesianGrid object instead of a Shape3D as the ROI shape.
This allows the ROI volume to be constructed during preprocessing for multiple image analysis.
KeyParser::parameter_info() now outputs vectorised keys as well
DetectionPosition now has all comparison operators.
LOR classes now no longer require phi at input to be between 0 and pi,
nor psi to be between 0 and 2 pi. They will standardise the input automatically.
test_view_offset_root to ensure reliability between GATE and STIR voxel positions by
comparing center of mass of ROOT data LORs with the original STIR position.ProjDataInMemory in the same order as what is used by copy_to and fill_from. This enabled using straight-forward copy. (This change should not affect anyone, except if you relied on a specific order in the buffer before.)
generate_image by moving the GenerateImage class to its own
source and header files, enabling usage from other STIR utilities and tests.