-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Moving SyneRBI-Challenge nema-data utilities to SIRF #1241
Conversation
I'm not 100% sure if this should be in C++ TBH. I think most people will never check the C++ code, while they might do for the Python side. However, of course we can have it in C++ and an equivalent in Python as illustration. Regarding the "incompatible projdata", if you post an error, I can try to help. |
@KrisThielemans
gives me
(note the difference in I tried different declarations of |
Cutting out some stuff std::string f_template = append_path(path, "mMR_template_span11_small.hs");
CREATE_OBJECT(STIRAcquisitionData, STIRAcquisitionDataInFile,
acq_data_template, templ_sptr, f_template.c_str());
...
converter.sinograms_and_randoms_from_listmode
(lm_data, 0, 10, acq_data_template, sinograms_sptr, randoms_sptr);
...
PETAttenuationModel::compute_ac_factors(templ_sptr, mu_map_sptr, acf_sptr, iacf_sptr); The last line seems incorrect. the template should no longer be used, as that doesn't know about bed positions, time frames etc actually used. Instead, use |
@KrisThielemans thanks a lot - seems to work ok now! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure about the direction this is going I'm afraid. Some more detail in the comments.
sino, rand = lm2sino.sinograms_and_randoms_from_listmode(lm_data, 0, 10, acq_data_template) | ||
print(sino.shape) | ||
print(sino.norm()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's rename sino
to prompts
. I'd prefer to rename rand
to randoms_estimate
(or at least, say that in a comment). They are not the randoms of course.
Also rename the function to get_prompts_and_randoms(...)
. However, I'm not a great fan of this I'm afraid. We have set_input
etc, and here a (presumably static) function that takes an lm_data and time-frame info. I don't see a good reason to have both interfaces. So, I suppose I suggest to have no arguments for this function (i.e. bunch of sets, a set_up(), and then call this). It raises the question why we have it, aside from having a one-liner.
We're mixing 2 kinds of interfaces here, which creates confusion.
If you don't like the set
functions. we could have a constructor function for Listmode2Sinograms
def __init__(self, list_file, interval, template)
Same comments will apply on the C++ side of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is just a one-line alternative to already available usage
lm2sino = pet.ListmodeToSinograms()
lm2sino.set_input(lm_data)
lm2sino.set_output_prefix("prompts")
...
But this PR is about adding Challenge nema-data utilities to SIRF, and all those utilities are one-liners, as can be seen in try_data_preparation.py
:
sinograms_and_randoms_from_listmode(listmode_filename, (0, 600), template_filename, sinograms_filename, randoms_filename)
ac_factors = acquisition_sensitivity_from_attenuation(siemens_attn_header, sinograms_filename, stir_attn_header, ac_sens_filename)
estimate_scatter(sinograms_filename, randoms_filename, stir_norm_header, stir_attn_header, ac_factors, scatter_filename)
mult_factors = create_multfactors(stir_norm_header, ac_factors, mult_factors_filename)
create_background_and_additive(randoms_filename, scatter_filename, mult_factors, background_filename, additive_term_filename)
So I tried to make respective SIRF one-liners, just replacing files with objects in memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of poluting class interfaces with multiple options to do the same thing (although we have a fair amount of that in SIRF already), but I suppose others might prefer oneliners. Nevertheless, I certainly don't want to have all the above one-liners in class interfaces (it wouldn't make sense anyway).
I still think this particular function has a few problem:
- it is PET specific (randoms don't exist in SPECT). This was already slightly problematic in
ListModeToSinograms
but at least people would have to explicitly callestimate_randoms
, which nobody in SPECT would do. - for dynamic PET, people might need to call
get_time_at_which_num_prompts_exceeds_threshold
first. To do that, they need to callset_input
first. It's contour-intuititive (and suboptimal) that this function then needs the listmode data again, so you'd need to remove thelm_data
argument. - it calls
set_time_interval
etc, so will modify the underlyingListModeToSinograms
object, which could be surprising, at least without documentation. - (as stated above, the name is wrong)
See general comment in the review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR introduces convenience functions for PET data preparation. In particular, it adds sirf.STIR.AcquisitionSensitivityModel.compute_attenuation_factors
and sirf.STIR.ListmodeToSinograms.prompts_and_randoms_from_listmode
(and corresponding C/C++ functions).
For the challenge, we could have just added them in the Challenge repo, but it's obviously better to have them in SIRF itself.
However, I think the current PR has several problems.
- it adds "one-liner" to class interfaces, introducing duplication in functionality
- most of it is PET specific but they are at "top-level" sirf.STIR.
sirf.STIR.AcquisitionSensitivityModel.compute_attenuation_factors
does not make sense for SPECT, where they attenuation image has to be entered explicitly in theAcquisitionModel
. So, that function (if we keep it) needs to be moved toPETAttenuationModel
(where it already is in C++).- randoms do not exist in SPECT
My preferred solution is to have sirf.STIR.PET_data_preparation
Python module (it could be on the C++ side as well of course, but more work) where these kind of one-liners are located (as functions, not as class members). I'm not sure if that's easy to do quickly though.
Possibly best things to do in this PR is to:
- move
sirf.STIR.AcquisitionSensitivityModel.compute_attenuation_factors
to a PET specific model. If that doesn't exist on the Python side, I'm afraid I would not add this to the class. - drop the list-mode one-liner
Aside from this, there are huge diffs in stir_x.h
, probably just due to moving things around. I haven't reviewed any of that.
sino, rand = lm2sino.sinograms_and_randoms_from_listmode(lm_data, 0, 10, acq_data_template) | ||
print(sino.shape) | ||
print(sino.norm()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of poluting class interfaces with multiple options to do the same thing (although we have a fair amount of that in SIRF already), but I suppose others might prefer oneliners. Nevertheless, I certainly don't want to have all the above one-liners in class interfaces (it wouldn't make sense anyway).
I still think this particular function has a few problem:
- it is PET specific (randoms don't exist in SPECT). This was already slightly problematic in
ListModeToSinograms
but at least people would have to explicitly callestimate_randoms
, which nobody in SPECT would do. - for dynamic PET, people might need to call
get_time_at_which_num_prompts_exceeds_threshold
first. To do that, they need to callset_input
first. It's contour-intuititive (and suboptimal) that this function then needs the listmode data again, so you'd need to remove thelm_data
argument. - it calls
set_time_interval
etc, so will modify the underlyingListModeToSinograms
object, which could be surprising, at least without documentation. - (as stated above, the name is wrong)
See general comment in the review.
So, current |
Listmode 2 sinograms wil work for SPECT as long as you don't ask for the randoms. |
So far as I can see, |
Can be an error I think, but yes, good plan |
@evgueni-ovtchinnikov let's try to finish this off and merge. Given above problems with Then add something to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, but although this last commit is fine, I don't like it. I find introducing multiple ways to the class interface to do something in the end less productive. How are we going to handle the randoms now? Add some other member to attempt a one liner? Where do we stop?
We need to move on, and we keep circling. so please abandon this PR and just add equivalent functions in the Challenge PR. Sorry.
We could pick it up later, but it'd need design decisions.
compute_ac_factors
- C++: it is a static function of
PETAttenuationModel
, that takes aPETAttenuationModel
as argument, that's pretty weird. - Python: move
sirf.STIR.AcquisitionSensitivityModel.compute_attenuation_factors
to asirf.STIR.PETAttenuationModel
. However, that doesn't exist on the Python side yet, so I don't know how much work that'd be. This would be worth doing though, as really the currentAcquisitionSensitivityModel
constructor taking anImageData
as argument should sit inPETAttenuationModel
. As that breaks backwards compatibility, it's for 4.0.
- C++: it is a static function of
- remove
prompts_*_from_listmode
completely. - remove
test_data_preparation.py
- change
CHANGES.md
to say you've added a convenience functioncompute_af_factors
- make sure that the attenuation model is NOT returned from
compute_af_factors
- rename
test7.cxx
to something that says what it's testing.
@@ -2,6 +2,11 @@ | |||
|
|||
## vx.x.x | |||
|
|||
* PET: | |||
- incorporated into SIRF data processing utilities from SyneRBI-Challenge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this won't make sense to users.
Right, I see this was merged. Please revert the merge. Sorry |
Revert "Moving SyneRBI-Challenge nema-data utilities to SIRF (#1241)"
Changes in this pull request
Testing performed
Related issues
Checklist before requesting a review
Contribution Notes
Please read and adhere to the contribution guidelines.
Please tick the following: