Feature #640 hadamard decoding#840
Conversation
|
Ok I checked everything with Amnah's data and it creates these nice Volumes (with Hadamard4, so we only have 3 TIs) and actually two repetitions. 3TI * 8TEs * 2Rep = 48 volumes However, at the end of the xASL_wrp_ResampleASL, there's this part where some averages are made, and of course it doesn't work for Hadamard. Should we skip it or just adapt it? |
|
Moreover, I added an output to the decoding function (ASL_im) because we need to save it for both Standard and MNI space (see lin 238) In red we have the TimeEncoded part and in blue we have the normal data procedure. |
I mean, I know how to fix these things, but you guys probably need to agree on how these things should be fixed first.
Again, we probably need the expertise from @jan-petr on this. |
HenkMutsaerts
left a comment
There was a problem hiding this comment.
Nice work! Some questions, most comments are on redesigning your new function so it becomes readable and understandable, take a look at other existing functions as a template (e.g., xASL_system that I just wrote in #845).
| numberTIs = xASL_str2num(jsonOut.SeriesDescription(startDetails+3:startDetails+4)); | ||
| numberTEs = xASL_str2num(jsonOut.SeriesDescription(startDetails+10:startDetails+11)); | ||
| fprintf('FME sequence, Hadamard-%d encoded images, %d TIs, %d TEs\n', jsonOut.TimeEncodedMatrixSize, numberTIs, numberTEs); | ||
| jsonOut.TimeEncodedEchoTimes = numberTEs; |
There was a problem hiding this comment.
@MichaelStritt @jan-petr does it make sense to replace these variable names with BIDS field names, so these scripts are easier to debug?
There was a problem hiding this comment.
So just...
timEncodedInversionTimes = xASL_str2num(jsonOut.SeriesDescription(startDetails+3:startDetails+4));
timEncodedEchoTimes = xASL_str2num(jsonOut.SeriesDescription(startDetails+10:startDetails+11));
jsonOut.TimeEncodedEchoTimes = timEncodedEchoTimes;
...?
Sure, we can, don't see a huge benefit, but it's easy to do.
| function [imASL_reorder] = xASL_quant_HadamardDecoding(Encoded_ASL, xDecodingFields, NumberEchoTimes) | ||
| %xASL_im_HadamardDecoding Hadamard-4 & Hadamard-8 Decoding | ||
| % | ||
| % FORMAT: [Decoded_ASL] = xASL_im_HadamardDecoding(HadamardType, sec) |
There was a problem hiding this comment.
@BeatrizPadrela this doesn't fit with the function line above?
what does sec mean? It says here that it is an output from another function, but it would be nicer to have a longer variable name that is directly interpretable
There was a problem hiding this comment.
just change it to this:
function [imASL_reorder] = xASL_quant_HadamardDecoding(Encoded_ASL, xDecodingFields, NumberEchoTimes)
%xASL_quant_HadamardDecodingHadamard-4 & Hadamard-8 Decoding
%
% FORMAT: [imASL_reorder] = xASL_quant_HadamardDecoding(Encoded_ASL, xDecodingFields, NumberEchoTimes)|
|
||
| % Decoding Fields | ||
|
|
||
| TimeEncodedMatrixType = xDecodingFields.TimeEncodedMatrixType; |
There was a problem hiding this comment.
What happens if this field doesn't exist? :)
Same for the other fields. You can check them, and give warnings if they are missing. This should of course not happen, but if it happens for whatever reason — e.g., there is something going wrong somewhere else in another function — then you are notified nicely, which can save you time in debugging later.
Also, an input field check is lacking, like:
if margin<3 || isempty('variable name')
Check other functions on how this should be done. Also, in the header you should note if an input is REQUIRED or OPTIONAL, and if OPTIONAL, what the default value is. See also in other functions.
There was a problem hiding this comment.
Valid point, we never really know if those exist if the data is a bit different. We could optimize this in a second PR where we also support the data of Koen though, because there those things will probably "break".
I'd suggest just to add some...
if nargin ...
if isfield(...)
etc.... for now and then we improve the logic within the Koen PR.
| DecodingMatrix_input = []; | ||
| end | ||
|
|
||
| % #### For Walsh Decoding Matrix #### |
There was a problem hiding this comment.
Also here, ### is the same as %%% but for a non-Matlab language ;)
There was a problem hiding this comment.
Please check xASL_system which I just created as a template, also for splitting the function in steps that are then easy to read, and that are listed in the function header.
There was a problem hiding this comment.
Yeah, but again, xASL_system was created in the meantime. Let's improve those in the next PR with Koens data, then we don't have to do that much cherry-picking and so on.
| end | ||
|
|
||
| % #### For Hadamard Decoding Matrix #### | ||
| elseif strcmp(TimeEncodedMatrixType,'Hadamard') |
There was a problem hiding this comment.
what happens if this field is not Hadamard or Walsh? Then there should be a warning right?
Also, you can use strcmpi to make your life easier. If you then accidentally typed hadamard instead of Hadamard it will still work.
There was a problem hiding this comment.
Let's do it 100% correctly like this:
switch lower(TimeEncodedMatrixType)
case 'walsh'
...
case 'hadamard'
...
otherwise
...
end
| if xASL_exist(x.dir.studyPar,'file') | ||
| studyPar = spm_jsonread(x.dir.studyPar); | ||
| if isfield(studyPar,'TimeEncodedMatrixSize') && ~isempty(studyPar,'TimeEncodedMatrixSize') || ... % Should be 4, 8 or 12 | ||
| if isfield(studyPar,'TimeEncodedMatrixSize') && ~isempty(studyPar.TimeEncodedMatrixSize) || ... % Should be 4, 8 or 12 |
There was a problem hiding this comment.
Do we need a warning or feedback here?
There was a problem hiding this comment.
Let's not change this too much, because it was already modified/renamed etc. in another PR. Keep it like it is for now 👍
| @@ -159,7 +159,7 @@ | |||
|
|
|||
| if xASL_exist(x.dir.studyPar,'file') | |||
There was a problem hiding this comment.
For a json file, exist works as well as xASL_exist
There was a problem hiding this comment.
Let's not change this too much, because it was already modified/renamed etc. in another PR. Keep it like it is for now 👍
Modules/xASL_module_ASL.m
Outdated
| %% TimeEncoded parsing | ||
|
|
||
| % Check if TimeEncoded is defined | ||
| if isfield(x,'TimeEncodedMatrixType') || ~isempty(x.TimeEncodedMatrixType) |
There was a problem hiding this comment.
Should this be || or && / :) Same below!
There was a problem hiding this comment.
yes of course sorry, done
| else | ||
|
|
||
| % Decoding of TimeEncoded data =================== | ||
| elseif x.modules.asl.bTimeEncoded |
There was a problem hiding this comment.
Is this the correct position for this function? So it occurs after motion correction, but before quantification? Should the function then be called quant or is it rather im?
There was a problem hiding this comment.
Maybe im is better 👍
| @@ -222,7 +227,18 @@ function xASL_wrp_ResampleASL(x) | |||
| elseif round(dim4/2)~=dim4/2 | |||
There was a problem hiding this comment.
Can this be the case for Hadamard or Walsh?
There was a problem hiding this comment.
So I guess @amahroo is checking for uneven numbers here 🤔
There was a problem hiding this comment.
I didn't make any changes in the resample function, no idea :/
There was a problem hiding this comment.
Ahhh true, no one changed the code here. Is this one of your "teaching" questions @HenkMutsaerts ?
There was a problem hiding this comment.
since we have multiples of 4 and 8, this should not be the case for Hadamard/Walsh
| if nargin<3 && isempty(Encoded_ASL) | ||
| warning('Encoded_ASL input is empty'); | ||
| end | ||
|
|
||
| if nargin<3 && isempty(xDecodingFields) | ||
| warning('xDecodingFields input is empty'); | ||
| end | ||
|
|
||
| if nargin<3 && isempty(NumberEchoTimes) | ||
| warning('NumberEchoTimes input is empty'); | ||
| end |
There was a problem hiding this comment.
@BeatrizPadrela I think I'm distracting you too much 😆 try nargin<1, nargin<2, ... 😉
… with Amnahs code
…ons for TimeEncoded data
7979b73 to
188554d
Compare


Linked issue
Required: mention the issue number of the linked feature or bug here
How to test
Required: if not defined in the linked issue, add a simple test description here
Comments
Optional: add helpful comments for the reviewers here