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
dwi2tensor: add wls #1542
dwi2tensor: add wls #1542
Conversation
I'm ok with extra algorithms, but I'd like the default behaviour to remain unchanged. Can you briefly elaborate on what's essentially changed (don't have much time now to go through all the code changes)? |
...or of course extra options, etc.. essentially allowing for new functionality, whether that's labelled "new algo" or not. All good on that front; I'm more interested in what is or remains the default behaviour. |
Yep, I'll freely admit that was pretty lite on justification... I'll edit the main post with the details. |
OK, justification for changes now documented in main post.
Hopefully these edits will answer that question. But in essence: yes, there is a change in the default behaviour, this would initialise the IWLS with a WLS fit rather than the current OLS fit. |
OK, coming back to this discussion about changing Input data was fairly low-grade b=1300, 32 direction data. current master:default: initial OLS + 2x IWLS
|
Can I propose some changes to the documentation? There's a bit of nuance in the description of exactly how the fit is done, so I think this could do with a reasonably verbose explanation in the Description section; and possibly also redirecting some of the explanation currently tied to specific command-line options into the Description section. Currently we have:
Maybe something like this would be clearer:
|
This is all I really mostly care about; i.e., the old and new default. All the other option combinations made possible are entirely fine: it's up to the users to use them responsibly, but they do exactly what they say on the box.
So this is what I'd like to be sure of we get across the board. In the example you provides it's surely fine. Not much changes, but what does change is mostly for the better. It does show that it can also act the other way around for a few individual voxels though.
Would be happy to see an example of that; this is referring to the (kind of) data that initially motivated the change in default, correct? As mentioned above, I'd concentrate on the difference between old and new default. So essentially (in case of your data above), these figures (old / new / difference): Thinking a bit about this myself, I'm getting more and more convinced this should be for the better though. Just being careful (and thus naturally critical). |
Happy with the change in description - I admittedly didn't invest a huge amount of effort into that side of things... Otherwise, I'll get a few more examples of the difference on multi-shell data when I get the chance next week. |
As discussed in #1542.
OK, results for the BATMAN data (following all the pre-processing in the tutorial) - as before, FA for old / new / diff (windowed [-0.01 0.01]): As before, most differences in the CSF regions, but a touch of a difference in some regions of the WM too. Biggest differences observed in WM is of the order of 1.5% (with new > old). Neonatal data from the dHCP cohort, same as before: Note the few glitches in the old OLS-initialised results near the brainstem / temporal pole, which you don't see in the WLS-initialised results (this is the kind of issue that prompted this in the first place). Difference between new & old is again of the order of 1-2% in the WM, typically with new > old (at least on FA). If everyone is happy with that, I suggest we merge...? |
Can't fault it given the data and as far as I got with my thinking about it. 👍 I'll keep an eye on it though, just in case I see something funny pop up in the future. But having the |
Did some extra testing from |
👍 |
This follows recent bits of experimentation and discussions with @bjeurissen. Just making sure it's up for discussion and inclusion in RC4...
[EDIT]
These changes follow an observation by @dchristiaens of strange behaviour on some of our multi-shell data: we ended up with negative ADCs in some voxels, particularly where it would be expected to be fast. Digging into it further, we figured what happened was that the initial OLS fit was dominated by the noisy DW signals, which at that stage aren't down-weighted in any way. When you have relatively few b=0 images, it essentially ends up ignoring them and trying to fit primarily to the noise - and due to the log transform, the noise can rapidly swamp the fitting. At this point, because the next iteration uses the predicted signal to compute the weights, the b=0 signals end up down-weighted even further relative to the DW signals, further compounding the problem.
To minimise this issue, I thought we could initialise with a weighted least-square fit, with the weights driven by the measured signal rather than its prediction - which does indeed sort out the problem we were having. So in this PR, that's now the default behaviour. I can't remember whether it made any meaningful difference in those parts where the current approach actually converged - I'd need to double-check that, but from memory whatever differences there might have been were negligible.
I then looked a bit into the literature, and was surprised to (re)discover that the WLS approach is what had originally been proposed for the fit by Peter Basser back in his original 1994 paper... So I thought we should at least offer it as an option in
dwi2tensor
.So the proposed changes try to rationalise all this by offering a choice of initial fitting (WLS by default, or OLS), followed by a user-specified number of iteratively re-weighted LS (IWLS) with weights determined by the signal predictions. Means you can pick either OLS or WLS for the direct fit (set
-iter
to zero) or as initialisation for however many rounds of IWLS you want.