feat: Add body-part aware initial guesses for IVIM fitting (Feature #87)#149
feat: Add body-part aware initial guesses for IVIM fitting (Feature #87)#149Devguru-codes wants to merge 3 commits intoOSIPI:mainfrom
Conversation
…SIPI#87) Add literature-sourced default initial guesses, bounds, and thresholds for 8 anatomical regions: brain, liver, kidney, prostate, pancreas, head_and_neck, breast, placenta. New files: - src/wrappers/ivim_body_part_defaults.py: lookup table module with get_body_part_defaults() and get_available_body_parts() - tests/IVIMmodels/unit_tests/test_body_part_defaults.py: 22 unit tests Modified files: - src/wrappers/OsipiBase.py: add body_part parameter to __init__(), support initial_guess as string (e.g. initial_guess='liver') API usage: OsipiBase(algorithm='X', bvalues=b, body_part='liver') OsipiBase(algorithm='X', bvalues=b, initial_guess='brain') 100% backward compatible: body_part=None uses original generic defaults. User-provided bounds/initial_guess always take priority. No regressions: 1127 passed, 167 skipped, 22 xfailed, 6 xpassed.
oliverchampion
left a comment
There was a problem hiding this comment.
Hey DevGuru, thanks for implementing this! Some general comments. As some of these implementation also requiere expert input and consensus (bounds, initial guesses) I have asked the community to comment too.
|
I will make all updates at once when the expert's review will come. |
| IVIM_BODY_PART_DEFAULTS = { | ||
| "brain": { | ||
| "initial_guess": {"S0": 1.0, "f": 0.05, "Dp": 0.01, "D": 0.0008}, | ||
| "bounds": { |
There was a problem hiding this comment.
How the comment above works out for the bounds then I'm not completely sure. However, I suppose it's better to be safe and use 'wide' margins for the bounds. I would opt for bounds wider than they are implemented here. This might be an impactful decision (since it can be used as base for fitting pipelines down the line), does it require some discussion @oliverchampion ?.
If let's say we were to use 4 SDs from the mean value reported in the Sigmund et al. review paper, and clip the values to the original bounds (f: [0, 100], D to [0, 0.005] and D* to [0.005, 0.2]) we would end up with bounds like:
with f in %, D in mm^2/s and D* in mm^2/s
{
"brain": {
"D": [0.00055, 0.00111],
"Dp": [0.005, 0.03],
"f": [0.0, 20.28]
},
"kidney": {
"D": [0.00129, 0.00249],
"Dp": [0.005, 0.11905],
"f": [0.0, 43.80]
},
"liver": {
"D": [0.00041, 0.00177],
"Dp": [0.005, 0.19406],
"f": [0.0, 56.97]
},
"muscle": {
"D": [0.00035, 0.00259],
"Dp": [0.005, 0.18760],
"f": [0.0, 34.02]
},
"breast_benign": {
"D": [0.0, 0.00291],
"Dp": [0.005, 0.16633],
"f": [0.0, 23.88]
},
"breast_malignant": {
"D": [0.0, 0.00225],
"Dp": [0.005, 0.11424],
"f": [0.0, 29.35]
},
"pancreas_benign": {
"D": [0.0, 0.00429],
"Dp": [0.005, 0.08015],
"f": [0.0, 51.99]
},
"pancreas_malignant": {
"D": [0.0, 0.00332],
"Dp": [0.005, 0.07348],
"f": [0.0, 32.27]
}
}
There was a problem hiding this comment.
I agree that we should have wide bounds. We should be careful as we're often looking for lesions, which means we are looking for values that deviate from healthy tissue (which are the easiest values to find in literature). We cannot have bounds that removes/reduces this desired contrast.
I'd be in favor of being careful and go for physical/theoretical bounds. In the liver bounds that Daan has cooked up with the SD's for example (or many of the examples provided in the PR). Is there really no chance of having diffusivity values between 0.0018 and 0.005? That's currently the forbidden gap between D and D* in bounds that are generated that way. With bounds like these, we're not really allowing the algorithms to interpret the signal.
There was a problem hiding this comment.
Hi Ivan, just discussed this within TF6.3. We agree with your point of view. Summarizing, we'd propose to:
- Use wide bounds and be on the safe side
- Make a distinction in bounds between brain and body (what they will be needs to be determined still)
- initial guess can be organ-specific (based on the reported healthy tissue means in the IVIM review paper)
There was a problem hiding this comment.
Hello @DKuppens and @IvanARashid sir. Thank you for the review. Based on consensus, there is what i am thinking -
- Organ List & Initial Guesses: - I will update the lookup table to strictly mirror the expected healthy tissue means from the upcoming Sigmund et al. consensus paper. This includes adding Muscle, splitting Breast and Pancreas into benign/malignant, removing Prostate and Head/Neck, and updating all the DOIs to match the citations you provided.
- Bounds (Brain vs. Body): - I will discard the 4-SD calculated bounds in favor of wide, physical bounds to ensure algorithms can freely interpret the signal (especially for lesions).
I have 1 doubt regarding the bounds. @DKuppens sir mentioned making a distinction between brain and body ("what they will be needs to be determined still"). Since the 4-SD bounds calculated above (f: 20%, D: 0.001, etc.) are no longer the plan, I will wait for you to finalize those wide physical limits for Brain vs Body (or I propose a set of wide physical limits for you to review? like - D: [0, 0.005], f: [0, 1] for body.
After this, I will work on updates. Thank you.
There was a problem hiding this comment.
Okay, I would suggest:
1: Initial guesses follow recommendation paper.
2: bounds stay broad and physical and are not organ-specific for now. But we keep the organ specific bounds structure, so at a later stage we can start implementing organ-spicific bounds by changing these numbers.
{"S0" : [0.5, 1.5], "f" : [0, 1.0], "Dp" : [0.005, 0.2], "D" : [0, 0.005]}
3: whenever organ-specific is selected, a warning message appears stating initial guesses are based on healthy tissue (and refs), and that bounds are currently set broad.
There was a problem hiding this comment.
Ok, I will start implementing this. Thank you.
This comment was marked as duplicate.
This comment was marked as duplicate.
|
I have updated the file. Updates are -
|
|
Hello @oliverchampion sir ,the CI tests failed because they have older initial guess values in the tests. This caused the tests to fail. I am going to update the test file that is test_body_part_defaults.py. Now, coming to values are - Liver: Kidney: Bounds Updated (to match the Broad Physical Bounds logic): Normalization Test Updated (Removed Organs): I will wait to update it. I want your thoughts on these values. Thank you. |
|
@Devguru-codes Thanks, this is a good improvement. I do see failing tests so those should be fixed too. |
Ok @etpeterson sir, @DKuppens sir, @IvanARashid sir, @oliverchampion sir, I just need confirmation on the values i am going to use. I have mentioned the values above. Thank you |
Looks good! |
Thank you @IvanARashid sir for confirming the values. I have now updated those values. Thank you. |
|
I have update the values and when i checked those values with the updated bounds, the test cases passed. The tests failed cause they still have the old values present in them. Please review it @oliverchampion sir. Thank you. |
|
Sir, I researched on it and used AI to figure why CI unit test cases were failing only for macos-
These changes are required in unit_test.yml which I think I will need your permission before I update it in this PR. Thank you. |
Hello @etpeterson - I saw no updates were made on this issue so I worked on it. If there is need of improvement, comment it and i will update this pr.
Description
Closes #87. Adds organ-specific initial guesses, bounds, and thresholds for IVIM fitting, sourced from peer-reviewed literature. This enables faster convergence, reduced local minima, and more physiologically plausible results when scanning specific body parts.
Problem
The current generic defaults (
f=0.1, D=0.001, Dp=0.01) are reasonable for the brain but significantly off for other organs:Solution: Literature-Sourced Lookup Table
Each body part also includes organ-specific bounds (tighter than the generic ones) to constrain the optimizer to physiologically plausible regions.
Justification for chosen values:
Changes Made
src/wrappers/ivim_body_part_defaults.pyget_body_part_defaults(),get_available_body_parts()src/wrappers/OsipiBase.pybody_partparam to__init__(), supportinitial_guessas stringtests/.../test_body_part_defaults.pyAPI Usage
Testing
body_part="liver"produced near-perfect results:Known Issue (Pre-existing, Not Introduced by This PR)
When using
body_part=together withalgorithm="IAR_LU_biexp", theIAR_LU_biexpalgorithm's internalset_bounds()crashes withKeyError: 0because it expects bounds as list-of-lists (bounds[0],bounds[1]) but receives dict-format bounds. This is the same bug onmainthat is already documented in Issue #86 and fixed in PR #142 — it reproduces identically withbody_part=None(generic defaults). Once PR #142 is merged, this will work seamlessly.Backward Compatibility
body_part=None(default) → identical to current behaviorinitial_guess=dict→ identical to current behaviorbounds/initial_guessalways override body-part defaultsChecklist
tests/IVIMmodels/unit_tests/test_body_part_defaults.pynumpy,scipyalready required)