Hello, and thank you for any insight you may provide. I am new to AFNI, and have limited linux/scripting experience, so hopefully this (3-part) question will be something someone has tried before and knows how to do.
Background: I am working with a dataset with an anatomical underlay, and a data overlay thresholded to approximately 95%, viewing just the first sub-brick (#0, strongest signal component).
I want to take a 2D slice of a 3D view (axial, sagittal, coronal) and create an automation script to print out the total number of surviving voxels (after thresholding) in that slice, then repeat for all slices in that view. Hopefully, this will give me a list (or three, one for each view) I can input into Matlab (or similar) and create a graph showing (for example) how the number of thresholded voxels changes as I move through the brain.
So far, I’ve been closest to success while playing around with
3dmaskdump –cmask [not too sure on correct options] followed by
3droistats –mask [maskname] –nzvoxels
This doesn’t seem to be working too well, or at least, I can’t figure out the options I need. I’m also not sure 3dmaskdump is the correct program to begin with, since it creates an output dataset and not a proper mask, but 3dautomask doesn’t seem to have the options I need, and this doesn’t really write the result to a file. I see that
3dmaskdump –[view] [name] –expr 1-bool(k-slicenumber) should give me a single-slice dataset, but the output doesn’t seem to want to pass nicely into 3dROIstats when I’m trying to script it out, so I’m not sure that this is the method I want to use.
Equally importantly, I’m not sure how to automate / script this process for all slices in a dataset to give me a single nice file with a table of values at the end of the script running. I haven’t gotten there yet since I’m trying to get a single slice working right now, but automating this to run to give me a single file with all slice values for a single-view single-subject analysis will be vital.
Eventually, instead of doing the above for whole-brain slices, I’d like to do this to graph the number of thresholded voxels slice-by-slice in a hemisphere, quadrant, or even a cluster. If I can get the mask working properly in #1 to select a single slice, I imagine setting the range appropriately to a single hemisphere or quadrant would be a fairly straightforward extension of the original mask range options. I’m not sure, however, if it is possible to integrate this with 3dclustsim results to give me slice-by-slice results for a single cluster?
Finally, is there any way to run AFNI such that I can input commands into the terminal while AFNI is running and be able to view the results in real-time in the running program? This would be a great help when debugging and testing scripts, but when running AFNI via GUI, it does not seem to accept any terminal commands not already pre-typed-out in a script (i.e. I cannot ‘test’ afni automation scripts by typing them out into the program manually). I suspect this is more a ‘linux’ question than an ‘AFNI’ question.
Thank you for your help,
I think I’d probably do this with 3dZcutup to cut the dataset up into slices and 3dBrickStat -count to count voxels. The input dataset may have a range selector, or you can use a mask dataset.
Ah, I hadn’t run into either of those two utilities before - I’ll try them out and report back.
I’ve got 3dZcutup working with a for loop to give me a sliced dataset in an appropriate directory, and 3dBrickStat -count gives me the number of voxels in the slice.
What I think I need to do now is to create a mask thresholded at 95% of just sub-brick 0, then apply this mask before I use 3dZcutup. What is the best way to do this?
The closest I’ve found would be 3dcalc -a ‘dataset’ -expr ‘ispositive(a-threshold)’ -prefix mask
then to use the mask as the input to 3dZcutup. This works if I only need positive values, and I know the exact threshold value. However, I can’t figure out how to get 3dcalc to use a percentage threshold value of 0.95 (95%) rather than a fixed threshold. For this particular dataset, for example, a 0.95 threshold for me corresponds to about -0.0013 to 0.0013 but 1) I’m not sure how to put a range of values into 3dcalc and 2) more importantly, other datasets have a different range for this percentage threshold, and I’m not sure how to use a percentage value for a 3dcalc mask?
So. How do i create a mask with a 95% threshold of sub-brick 0? If I should use 3dcalc, what -expr value should I use?
Use abs(a) in your expression for the absolute value. 3dBrickStat can also give percentile values.
Is there no way to get a percentile value with 3dcalc? If absolutely needed I could determine the actual value for the percentile threshold of each dataset and edit my script accordingly, but it would be much easier if I could just use a percentile in the script. I can’t use a percentile value post-mask/cutup with 3dBrickStat becuase it would be using a mask, and would be a percentile of the slice, rather than of the whole dataset.
No, 3dcalc can’t do this by itself (calculate percentile values on another dataset), but you can calculate variables on the whole volume and pass it to 3dcalc. Consider these commands:
% 3dBrickStat -percentile 97.5 1 97.5 func_slim+orig’’
% set perctop =
3dBrickStat -percentile 97.5 1 97.5 func_slim+orig''
% set percbot =
3dBrickStat -percentile 2.5 1 2.5 func_slim+orig''
% echo $percbot
% echo $perctop
% echo “$perctop”
% echo “$perctop”
% 3dcalc -prefix test_5perc -a func_slim+orig’’ -expr “a*not(within(a,$percbot,$perctop))” -overwrite
++ 3dcalc: AFNI version=AFNI_17.1.05 (May 12 2017) [64-bit]
++ Authored by: A cast of thousands
++ Output dataset ./test_5perc+orig.BRIK
% 3dBrickStat -min -max -count -non-zero -slow func_slim+orig’’
-24.9387 37.3858 210073
% 3dBrickStat -min -max -count -non-zero -slow test_5perc+orig.
-24.9387 37.3858 10560
This didn’t quite work out as planned, since the threshold I needed was within the 3dClustSim results. However, setting up a script to configure and open AFNI, then saving the mask from 3dClustSim manually and using that as an input in a second script worked fine. Thank you for the previous scripting commands though; I was able to modify similar commands later in the script to set and retrieve variables as needed.