MLEstimateComponentBasedNormalisation refactor#1499
MLEstimateComponentBasedNormalisation refactor#1499robbietuk wants to merge 36 commits intoUCL:masterfrom
Conversation
|
Thus far, I have not (intentionally) changed any of the functionality of the The only new introduction is |
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
src/recon_buildblock/ML_estimate_component_based_normalisation.cxx
Outdated
Show resolved
Hide resolved
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
KrisThielemans
left a comment
There was a problem hiding this comment.
some initial comments. I didn't review everything.
I'm not sure if we should provide access to the efficiencies_sptr etc. shared_ptr are nice, but to be avoided when we can. If we have a const auto get_efficiencies() member, there seems tobe no point in making efficiencies etc into a shared_ptr.
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
src/recon_buildblock/ML_estimate_component_based_normalisation.cxx
Outdated
Show resolved
Hide resolved
src/recon_buildblock/ML_estimate_component_based_normalisation.cxx
Outdated
Show resolved
Hide resolved
src/recon_buildblock/ML_estimate_component_based_normalisation.cxx
Outdated
Show resolved
Hide resolved
src/include/stir/recon_buildblock/ML_estimate_component_based_normalisation.h
Outdated
Show resolved
Hide resolved
there are tests in the |
|
At this point, I want to add an interface with apply_normfactors3D uses streams to set these valuesSTIR/src/utilities/apply_normfactors3D.cxx Lines 71 to 83 in 33a0106 |
| const ProjData& measured_projdata_v, | ||
| const ProjData& model_projdata_v, |
There was a problem hiding this comment.
Should there be a check that these ProjData are the same "shape". Are there any tests for that?
There was a problem hiding this comment.
They should be. Not sure if it's checked anywhere.
Adds has_processed_data to MLEstimateComponentBasedNormalisation
I was just running out of time... Note that On another note, the "block" stuff really doesn't work and shouldn't be used. It was intended to cope with timing-alignment factors (for many scanners these are per block) but it introduces too much freedom (which I didn't know when I wrote that code). Timing alignment should be parametrised by 1 factor per block, not a norm-factor for every block-pair. Just saying that such that you don't spend too much time on that (i.e. maybe don't expose it) |
| void | ||
| BinNormalisationPETFromComponents::allocate(shared_ptr<const ProjDataInfo> pdi_sptr, MLEstimateComponentBasedNormalisation& normalization_estimator) | ||
| { | ||
| if (!normalization_estimator.has_processed_data()) | ||
| { | ||
| error("BinNormalisationPETFromComponents: internal error: allocate called on MLEstimateComponentBasedNormalisation " | ||
| "without it having processed the data"); | ||
| } | ||
| this->proj_data_info_sptr = pdi_sptr; | ||
| this->efficiencies = *normalization_estimator.get_efficiencies(); | ||
| this->geo_data = *normalization_estimator.get_geo_data(); | ||
| this->block_data = *normalization_estimator.get_block_data(); | ||
| this->_already_allocated = true; | ||
| } |
There was a problem hiding this comment.
I believe this is the cleanest way to implement all these changes. Here is a use case from my cpp program.
MLEstimateComponentBasedNormalisation ml_estimator(out_filename_tmp, *measured_projdata, *model_activity_projdata,
num_eff_iterations, num_iterations, do_geo, do_block,
do_symmetry_per_block, do_KL, do_display, do_save_to_file);
ml_estimator.process();
// Apply the normalization factors
BinNormalisationPETFromComponents bin_normalisation;
bin_normalisation.allocate(measured_projdata->get_proj_data_info_sptr(), ml_estimator);
bin_normalisation.set_up(measured_projdata->get_exam_info_sptr(), measured_projdata->get_proj_data_info_sptr());
// Compute the projdata
ProjDataInMemory normalization_projdata(*measured_projdata);
normalization_projdata.fill(1.F);
bin_normalisation.undo(normalization_projdata);There was a problem hiding this comment.
I acknowledge #1498 (comment), however this does work and provides an alternative allocation of the data.
There was a problem hiding this comment.
I'd rather do it the other way around I'm afraid. Your way is very different from anything else in STIR.
I very much prefer to let MLEstimateComponentBasedNormalisation have a shared_ptr<BinNormalisationPETFromComponents> normalisation_sptr member, which we can get via get_output() (returning a shared_ptr<const BinNorm...>). The MLEstimateComponentBasedNormalisation::get_efficiencies() would then just forward to normalisation_sptr->get_efficiencies() (note that I wouldn't let those return shared_ptr then, but references). Any reason not to do it this way?
|
Infinities tend to come from 1/0. A candidate would be the |
|
Note that you'll have to rename class and file to |
The The issue is when the I am not a huge fan of trimming the projdata with SSRB. I am trying to understand the code to figure out why the |
|
It's not the efficiencies themselves that are the problem, but the STIR/src/buildblock/ML_norm.cxx Lines 745 to 746 in e168b07 Moreover, there's plenty of loops doing This isn't going to be so easy to fix. |
|
Note that #1430 updates the |
|
I am not up to date with the theory in the papers. Do you expect any issue if I fix the fan data by removing the |
This allows the test to pass and ignores the to ignore even num_tangential_poss issue
|
I changed the scanner to "Discovery 690", with an odd number of tangential positions ( The previous issue with |
robbietuk
left a comment
There was a problem hiding this comment.
A few check before I believe this is done.
| sprintf(in_filename, "%s_%s_%d_%d.out", in_filename_prefix.c_str(), "eff", iter_num, eff_iter_num); | ||
| std::ifstream in(in_filename); | ||
| in >> norm.crystal_efficiencies(); | ||
| in >> norm.get_crystal_efficiencies(); |
There was a problem hiding this comment.
Returns by reference. This allows backwards compatibility with this code snippet but in general get_crystal_efficiencies() method returning the efficiencies object by reference might be dangerous?
There was a problem hiding this comment.
const & would do the trick
src/include/stir/recon_buildblock/MLEstimateComponentBasedNormalisation.h
Show resolved
Hide resolved
src/include/stir/recon_buildblock/MLEstimateComponentBasedNormalisation.h
Outdated
Show resolved
Hide resolved
|
Pretty sure this PR is ready for review. I can't find any more outstanding issues. #1511 covers the other issue with the fan data and even numbers. Ill add to the release notes. |
…based_normalisation_redesign
|
This should be merged into v6.3. I have been using a branch derived from here for a while with no major issues. |
KrisThielemans
left a comment
There was a problem hiding this comment.
Small changes required, but unfortunately quite a lot of them.
We cannot rename functions/files in 6.3, so I've flagged those up. Deprecations need to be listed in the release notes.
| efficiencies = eff; | ||
| } | ||
|
|
||
| DetectorEfficiencies& get_crystal_efficiencies() |
There was a problem hiding this comment.
ok for changing to get/set pair, but then I think we should have
| DetectorEfficiencies& get_crystal_efficiencies() | |
| const DetectorEfficiencies& get_crystal_efficiencies() const |
or would this break something?
However, cannot change backwards compatibility in a minor version update, so keep
#if STIR_VERSION < 070000
STIR_DEPRECATED DetectorEfficiencies& crystal_efficiencies()
...
#endif
Obviously the same for the others.| geo_data = geo; | ||
| } | ||
|
|
||
| GeoData3D& get_geometric_factors() |
| block_data = block; | ||
| } | ||
|
|
||
| BlockData3D& get_block_factors() |
| /*! | ||
| \file | ||
| \ingroup recon_buildblock | ||
| \brief Declaration of stir::ML_estimate_component_based_normalisation |
There was a problem hiding this comment.
| \brief Declaration of stir::ML_estimate_component_based_normalisation | |
| \brief Declaration of stir::ML_estimate_component_based_normalisation and | |
| stir::MLEstimateComponentBasedNormalisation |
There was a problem hiding this comment.
obviously, need to adjust when keeping ML_estimate_component_based_normalisation in its original file.
| \param do_display_v Whether to display the progress of the algorithm. | ||
| \param do_save_to_file_v Whether to save the each iteration of the efficiencies, geo data and block data to file. | ||
| */ | ||
| MLEstimateComponentBasedNormalisation(std::string out_filename_prefix_v, |
There was a problem hiding this comment.
generally STIR uses const std::string&
| \ingroup recon_test | ||
| \brief Test program to ensure MLEstimateComponentBasedNormalisation works as expected and | ||
| produces the correct normalization factors from components. | ||
| This is a very basic test that ensure the basic functionality. |
There was a problem hiding this comment.
| This is a very basic test that ensure the basic functionality. | |
| This is a test on basic functionality only. |
| const auto scanner = std::make_shared<Scanner>(*Scanner::get_scanner_from_name("Discovery 690")); | ||
| const auto exam_info = std::make_shared<ExamInfo>(ImagingModality::PT); |
There was a problem hiding this comment.
rename to scanner_sptr and exam_info_sptr
| const auto exam_info = std::make_shared<ExamInfo>(ImagingModality::PT); | ||
| exam_info->patient_position = PatientPosition(PatientPosition::HFS); | ||
|
|
||
| const shared_ptr<ProjDataInfo> projdata_info(ProjDataInfo::ProjDataInfoCTI( |
There was a problem hiding this comment.
use ProjDataInfo::construct_proj_data_info (same signature)
| /*views*/ scanner->get_num_detectors_per_ring() / 2, | ||
| /*tang_pos*/ scanner->get_default_num_arccorrected_bins(), | ||
| /*arc_corrected*/ false, | ||
| /*tof_mash_factor*/ -1)); |
There was a problem hiding this comment.
why -1? Set to 0 for non-TOF.
| const auto model_projdata = std::make_shared<ProjDataInMemory>(*measured_projdata); | ||
| model_projdata->fill(2.F); | ||
|
|
||
| constexpr int num_eff_iterations = 6; |
There was a problem hiding this comment.
Can we make this smaller (to run faster)?
|
Also, you'll need to run |
|
@robbietuk where are we with this? I think it might be best to postpone for after 6.3, as that needs to be completed soon. |
|
Postpone for now unless you can handle the review items. Sorry, I don't have much free time for this |

Changes in this pull request
WIP
Refactor of
ML_estimate_component_based_normalisation.Remaining tasks
get_efficiencies(),get_norm_geo_data()andget_norm_block_data()do_geo,do_block,do_symmetry_per_block,do_KL,do_display,do_save_to_fileefficiencies,norm_geo_data,norm_block_datavariables (even after all this work I am still slightly confused).Testing performed
Added a new unit test for basic functionality.
Related issues
Fixes #1498
Checklist before requesting a review
documentation/release_XXX.mdhas been updated with any functionality change (if applicable)