Closed mvdoc closed 4 years ago
It seems that this is just an issue with the code
field in the header (which probably should be fixed). Have you tried loading them in the same viewer and assessing the coregistration?
@chrisfilo yes, the coregistration looks fine in FSLEyes. but it's impossible to visualize the coregistration in AFNI because of the different template spaces
Here's the header info:
anat
contematto@head1 /data/famface_angles/derivatives103/fmriprep/sub-sid000005/ses-famfirst/anat (master) $ fslhd sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc.nii.gz | grep form
qform_name Aligned Anat
qform_code 2
qform_xorient Left-to-Right
qform_yorient Posterior-to-Anterior
qform_zorient Inferior-to-Superior
sform_name Scanner Anat
sform_code 1
sform_xorient Left-to-Right
sform_yorient Posterior-to-Anterior
sform_zorient Inferior-to-Superior
func
contematto@head1 /data/famface_angles/derivatives103/fmriprep/sub-sid000005/ses-famfirst/anat (master) $ fslhd ../func/sub-sid000005_ses-famfirst_task-fam1back_run-01_bold_space-T1w_preproc.nii.gz | grep form
qform_name Aligned Anat
qform_code 2
qform_xorient Left-to-Right
qform_yorient Posterior-to-Anterior
qform_zorient Inferior-to-Superior
sform_name Aligned Anat
sform_code 2
sform_xorient Left-to-Right
sform_yorient Posterior-to-Anterior
sform_zorient Inferior-to-Superior
descrip xform matrices modified by FixHeaderApplyTransforms (niworkflows v0.2.4).
Thanks for reporting. Obviously it's problematic if the images don't work with AFNI viewers. Could you verify that changing sform_code to 2 in func fixes this issue (without breaking things with regards to FSL)?
@effigies you might want to have a look at this as well.
So one issue there is that the qform code in your T1w_preproc should probably be 1, as well. I doubt that will make a difference to your problem, but for consistent treatment across software, we try keep the qforms and sforms synced.
The bigger issue is that AFNI doesn't respectNIFTI_XFORM_ALIGNED_ANAT
. We run into this issue when using AFNI tools, because they convert to BRIK+HEAD, operate, and then make a wild stab at reconstructing NIFTI affines because it threw that information out in the conversion.
If I'm not mistaken, AFNI treats every space other than ORIG as non-oblique, right? And I think the only way to get that from a NIFTI is to use NIFTI_XFORM_SCANNER_ANAT, which means to get this to work, we'd need to declare all preprocessed outputs as unaligned. While this may not break other software packages, it certainly would be standard-non-conformant.
Please correct me if I'm wrong.
@effigies setting qform
and sform
to 1 doesn't let me overlay the EPI on top of the anatomical, because of the different template spaces.
I'm not sure about AFNI considering all non-ORIG spaces as non-oblique. The info from the files that I pasted above show that the TLRC is plumb (non-oblique). (EDIT: I meant to say that I can de-oblique the ORIG anyway, while preserving the template space as ORIG...my head is spinning).
The way I found to make AFNI happy wrt alignment (and thus visualize it co-registered) is
sform_code
in the anatomical and set it to 23dWarp -deoblique anat.nii.gz
Only doing 1. lets me overlay epi to anat, but they look off. Doing both 1. and 2. makes the co-registration look fine in both FSLEyes and AFNI. I'm not sure though if deobliquing is reslicing stuff, and thus it makes the alignment to the surfaces off now.
I think deobliquing is reslicing - so we should avoid it.
However if we could combine deobliquing with other transformations (without adding additional interpolation steps) that would be fine.
I don't think it should affect the alignment to the surfaces; it presumably compensates for the rotation in the affine matrix. The surfaces are defined in RAS space, not with respect to a particular set of voxels.
To be clear, you set the qform and sform to 1 in the BOLD or the anatomical? If the anatomical, I meant you should try it on the BOLD. If the BOLD, then I have zero clue how template spaces work in AFNI. The qform and sform codes are, as far as I understood, the NIFTI equivalent of the template spaces, so setting both to 1 should declare everything ORIG. (Whether ORIG is a common template space is another question...)
@effigies to be clear I did the following
Short script for reproducibility and output follows
#!/bin/bash
ANAT=sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc.nii
FUNC=sub-sid000005_ses-famfirst_task-fam1back_run-01_bold_space-T1w_preproc.nii
# Show qform and sform for anat
echo "ANAT qform/sform"
nifti_tool -disp_hdr -infiles $ANAT | grep form_code
echo "FUNC qform/sform"
nifti_tool -disp_hdr -infiles $FUNC | grep form_code
# Set sform/qform of anat to 1
echo "Setting sform/qform of ANAT to 1 (Scanner)"
ANATFIX="${ANAT/preproc/preproc_fixhdr1}"
cp -v $ANAT $ANATFIX
nifti_tool -mod_hdr -overwrite -infiles $ANATFIX -mod_field sform_code 1 -mod_field qform_code 1
echo "ANAT qform/sform"
nifti_tool -disp_hdr -infiles $ANATFIX | grep form_code
# Set sform/qform of anat to 2
echo "Setting sform/qform of ANAT to 2 (Aligned)"
ANATFIX="${ANAT/preproc/preproc_fixhdr2}"
cp -v $ANAT $ANATFIX
nifti_tool -mod_hdr -overwrite -infiles $ANATFIX -mod_field sform_code 2 -mod_field qform_code 2
echo "ANAT qform/sform"
nifti_tool -disp_hdr -infiles $ANATFIX | grep form_code
# Set functional to 1
echo "Setting sform/qform of ANAT to 1 (Scanner)"
FUNCFIX="${FUNC/preproc/preproc_fixhdr1}"
cp -v $FUNC $FUNCFIX
nifti_tool -mod_hdr -overwrite -infiles $FUNCFIX -mod_field sform_code 1 -mod_field qform_code 1
echo "FUNC qform/sform"
nifti_tool -disp_hdr -infiles $FUNCFIX | grep form_code
Output:
ANAT qform/sform
qform_code 252 1 2
sform_code 254 1 1
FUNC qform/sform
qform_code 252 1 2
sform_code 254 1 2
Setting sform/qform of ANAT to 1 (Scanner)
sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc.nii -> sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc_fixhdr1.nii
ANAT qform/sform
qform_code 252 1 1
sform_code 254 1 1
Setting sform/qform of ANAT to 2 (Aligned)
sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc.nii -> sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc_fixhdr2.nii
ANAT qform/sform
qform_code 252 1 2
sform_code 254 1 2
Setting sform/qform of ANAT to 1 (Scanner)
sub-sid000005_ses-famfirst_task-fam1back_run-01_bold_space-T1w_preproc.nii -> sub-sid000005_ses-famfirst_task-fam1back_run-01_bold_space-T1w_preproc_fixhdr1.nii
FUNC qform/sform
qform_code 252 1 1
sform_code 254 1 1
Apologies for jumping in, and this doesn't resolve the larger issue with the qform/sform codes, but if you're sure the data are coregistered as desired then you can use 3drefit -deoblique anat.nii.gz
instead of 3dWarp -deoblique anat.nii.gz
. The latter, as mentioned, reslices the data (and can change the dimensions), but the former only modifies the transformation matrix in the header (changing the srow_*
and quatern_*
values), which may be warranted under certain circumstances.
Wrt to @effigies:
If I'm not mistaken, AFNI treats every space other than ORIG as non-oblique, right?
Not necessarily. You can reset the space to a non-ORIG option (in AFNI terminology: ANAT, TLRC, or MNI) and still have an oblique dataset. It would just be rare to have reset the qform/sform codes on a dataset without applying ANY transform to it, and any transform should reslice (thereby deoblique-ing) the dataset.
I did try with 3drefit -deoblique
, but in this case the func and anat are not aligned :( So I wonder what FSLEyes is doing to show them co-registered (or conversely, what AFNI is not doing...)
Okay. I was skeptical that modifying the affines without reslicing the data will keep our images in register, and it seems I was right.
I did run into a similar issue in the Connectome Workbench a while back, with datasets with an oblique anatomical image. They just have a checkbox, which I suppose means that it resamples the image on-the-fly to make overlaying possible. Perhaps AFNI just doesn't do that?
So after some tests and reasoning, I think it's an AFNI issue (or feature?). Here's my reasoning, please correct me if I'm wrong.
For AFNI, an oblique dataset is a dataset that has a rotation with respect to the cardinal axes (scanner coordinates). By looking at the AFNI source code, it computes obliquity based on the affine. The s/qform_code
are only used to figure out what the template space is (ORIG/TRLC).
My anatomical scans have a rotation right off the scanner because of how the scanner is placing the box. FMRIPREP of course doesn't touch the orientation of the anatomical, but aligns the EPI to the anatomical. The resulting aligned EPI is "plumb" in AFNI terminology (i.e. the affine is not a rotation).
The AFNI viewer seems to load the volume without applying the affine first, thus it assumes that whatever is loaded must be already aligned to cardinal axes (scanner coordinates). If it detects a mismatch between the sform_code
of the underlay and overlay (thus inferring different template spaces), it won't let overlay them.
Loading the images both with FSLEyes and nibabel shows that the anat and func are indeed aligned in ijk space without further reslicing.
At this point, I'm not sure if this is on you guys. Solving the problem for AFNI would mean that the anatomical needs to be "de-obliqued" at the beginning of the pipeline (with 3dWarp -deoblique
), but as @chrisfilo pointed out this implies reslicing the anatomical. For me, this issue can be closed, as in my mind it mostly depends on AFNI's behavior.
I agree this sounds like an AFNI problem, though if it's something they won't fix, we may still want to consider it.
De-obliquing the anatomical might not be too big a deal, at least in theory. Assuming we want to give FreeSurfer the un-de-obliqued image, there could be some trickiness, since we also feed in the skull-stripped image after autorecon1. (Might actually already be solved since we register the T1.mgz and T1w_preproc.nii.gz.)
Related poldracklab/niworkflows#221
UPDATE: I figured out a pipeline to make AFNI see the anatomical and the EPIs aligned. It requires deobliquing the anatomical, that is reslicing. But at least now I can visualize everything in AFNI :-)
3dWarp -deoblique -prefix anat_deoblique.nii anat.nii.gz
3drefit -view tlrc anat_deoblique.nii
( --> for some reason AFNI still thinks this is orig, so step 3. is necessary)nifti_tool -mod_hdr -mod_field qform_code 2 -mod_field sform_code 2 -infile anat_deoblique.nii -prefix anat_deoblique_tlrc.nii
Maybe we can fake this - I wonder what changes to the header steps 1 and 2 make.
Thanks for the question @chrisfilo :-) it made me realize that step 2 didn't really do anything, so all is needed is a) deobliquing (i.e., reslicing to cardinal coordinates, no rotation) and b) setting qform and sform to 2 in the anatomical after deobliquing.
It would be interesting to see the pre/post deobliquing diff of headers.
there you go :)
$ diff anat_hdr.txt anat_deoblique_hdr.txt
2c2
< N-1 header file '../../fmriprep/sub-sid000005/ses-famfirst/anat/sub-sid000005_ses-famfirst_acq-MPRAGE_T1w_preproc.nii.gz', num_fields = 43
---
> N-1 header file 'anat_deoblique.nii', num_fields = 43
14c14
< dim 40 8 3 192 256 256 1 1 1 1
---
> dim 40 8 3 197 350 351 1 1 1 1
22,24c22,24
< pixdim 76 8 1.0 0.900004 0.9375 0.9375 0.0 0.0 0.0 0.0
< vox_offset 108 1 352.0
< scl_slope 112 1 1.0
---
> pixdim 76 8 1.0 0.900004 0.900004 0.900004 0.0 0.0 0.0 0.0
> vox_offset 108 1 3360.0
> scl_slope 112 1 0.0
37c37
< qform_code 252 1 2
---
> qform_code 252 1 1
39,47c39,47
< quatern_b 256 1 -0.193777
< quatern_c 260 1 0.006661
< quatern_d 264 1 -0.00283
< qoffset_x 268 1 -85.690247
< qoffset_y 272 1 -126.7146
< qoffset_z 276 1 -95.06398
< srow_x 280 4 0.89991 0.002785 0.01328 -85.690247
< srow_y 296 4 -0.00732 0.867079 0.356401 -126.7146
< srow_z 312 4 -0.010775 -0.356471 0.867011 -95.06398
---
> quatern_b 256 1 0.0
> quatern_c 260 1 0.0
> quatern_d 264 1 1.0
> qoffset_x 268 1 90.49987
> qoffset_y 272 1 185.630844
> qoffset_z 276 1 -188.499954
> srow_x 280 4 -0.900004 -0.0 -0.0 90.49987
> srow_y 296 4 -0.0 -0.900004 -0.0 185.630844
> srow_z 312 4 0.0 0.0 0.900004 -188.499954
Ok - one thing I can think of trying is to zero non diagonal elements of the affine matrix of the T1w image prior to coregistration with the BOLD image (and save that as T1w_preproc). This should 'fake' deobliquing without the need for interpolation.
I wonder what @afni-rwcox thinks would be the best way to do this.
Was any further progress ever made on this? What is the current recommendation for those of us who want to view fmriprep output in AFNI?
Hi @pjkohler, we have not modified the way that T1w images are produced. I don't believe we have a current recommendation, but if AFNI is not displaying your images correctly, I would probably recommend using another tool like freeview or FSLeyes.
Just to ping that @afni-rickr might have thoughts here on the best way to go about this !
Hi @mvdoc and @emdupre, Yes, this is a long-term aspect of the afni GUI that never been dealt with. The GUI does not resample the data (to apply an obliquity transformation) live. We should do that (suma does, afni does not). So in this case, since the anat is oblique, the obliquity transformation should actually be applied. For example: 3dWarp -deoblique -prefix dset_card.nii.gz dset_oblique.nii.gz The result will cardinal, but with the data where it belongs. Sorry for the confusion.
@afni-rickr To be clear, 3dWarp -deoblique
will reslice the data to ensure the same RAS coordinates refer to the same values (modulo interpolation), but with RAS now aligned with (some permutation of) IJK?
I ask because I feel like I've seen some cases where "deoblique" is used to mean diagonalizing the affine matrix without modifying the data, which would be changing the space.
@effigies That is right, 3dWarp -deoblique
actually moves the data around (according to the oblique transformation) and resamples it on the (originallly approximated) cardinal grid. The notion of deobliquing where the data is not modified is what 3drefit -deoblique
would do, just truncating any oblique angles to the nearest cardinal grid (which is what the GUI was doing).
In the afni GUI, oblique data is shown with an ijk->xyz transformation using the closest cardinal transformation. The data will appear "untilted". As Rick said, there are few operations available:
Replace the oblique transformation in the header with the closest cardinal matrix 3drefit -deoblique mydset There is no difference in the view inside the afni GUI, but there would be a difference in suma's display.
Transform the data so that the cardinal data is accurate, i.e. cardinalize the data. The data will appear tilted with zeros around the original volumes. 3dWarp -deoblique -prefix mycarddset mydset
Transform oblique or cardinal data to match another dataset's cardinal grid where each dataset may be differently oblique. The visual result depends on the target dataset's obliquity. 3dWarp -card2oblique target_oblique_dset -prefix myobldset mydset
You can see this webpage for some examples: https://sscc.nimh.nih.gov/sscc/dglen/Obliquity
In general, I compare anatomical and EPI datasets using the third method. This is, in fact, what the align_epi_anat.py script uses to compute transformations before fine tuning alignment.
Hm, @afni-dglen and @afni-rickr, I am still a little confused here. Allow me to get extremely concrete:
I am trying to compare two files: (1) the nifti surface volume sub-xx_SurfVol.nii, generated by applying @SUMA_Make_Spec -NIFTI -sid sub-xx to the freesurfer output of fmriprep. (2) a functional file generated by fmriprep, sub-xx_blah_space-T1w_preproc.nii.gz. I can view both files in fsleyes and they appear perfectly aligned.
However, it is not possible to view the files together in the AFNI viewer, because the Template Space of sub-xx_SurfVol.nii, as viewed by 3dinfo, is ORIG, while the Template Space of sub-xx_blah_space-T1w_preproc.nii.gz is TLRC. Note that the 'space-T1w' part of the filename indicates that the file is not in TLRC space. I have tried the 3 options outlined by @afni-dglen, with sub-xx_SurfVol.nii as target_oblique_dset and sub-xx_blah_space-T1w_preproc.nii.gz as mydset, and none of them changes the header of the functional file to ORIG, or otherwise make it possible to view the files together.
Am I missing something here?
I think I understand now that only option 3 really makes sense if I want to modify the functional file from being in cardinal space (TLRC) to being in oblique space (ORIG), apologies for not getting that before.
If I use option 3 to convert my functional file to test3+tlrc, and then run 3drefit -view orig test3+tlrc., the result test3+orig can be viewed with the surface volume in the AFNI viewer, and looks aligned. However, 'Template Space' in the header of test3+orig is still TLRC, and if I convert to .nii.gz with 3dAFNItoNIFTI, the resulting file reverts to TLRC and cannot be viewed with the surface volume.
3drefit -view orig -space ORIG test3+tlrc
followed by 3dAFNItoNIFTI did the trick, generated a nifti file that could be viewed in the AFNI viewer. However, simply applying 3drefit to the original functional data:
3drefit -view orig -space ORIG sub-xx_blah_space-T1w_preproc.nii.gz
accomplished the same thing. The output of 3drefit is identical to the output of 3dWarp+3drefit+3dAFNItoNIFTI in both the afni viewer and fsleyes, and both are identical to the original functional data in fsleyes.
This would seem to suggest that the only issue is that afni interprets the fmriprep output as being in TLRC space, so simply correcting that with 3drefit is enough. It would still be great to understand why this is happening.
Hope this is helpful to someone other than me.
/Peter
@mvdoc, pretty sure 3drefit used as described above will resolve your original issue as well.
Does this mean we could achieve compatibility with AFNI viewers without adding extra interpolation to T1w outputs by adding additional affine to the combine transformation applied to space-T1w preprocessed bold outputs?
not sure I know the answer, but here's 3dinfo before running 3drefit -view orig -space ORIG:
Dataset File: sub-00XX_blah_bold_space-T1w_preproc.nii.gz Identifier Code: NII_jKkr6ZYQUBjQi47n4aVHdg Creation Date: Wed Oct 24 16:20:37 2018 Template Space: TLRC Dataset Type: Echo Planar (-epan) Byte Order: LSB_FIRST {assumed} [this CPU native = LSB_FIRST] Storage Mode: NIFTI Storage Space: 213,085,200 (213 million [mega]) bytes Geometry String: "MATRIX(-2,0,0,68.278,0,-2,0,85.67899,0,0,2,-91.67909):71,82,75" Data Axes Tilt: Plumb Data Axes Orientation: first (x) = Left-to-Right second (y) = Posterior-to-Anterior third (z) = Inferior-to-Superior [-orient LPI] R-to-L extent: -71.722 [R] -to- 68.278 [L] -step- 2.000 mm [ 71 voxels] A-to-P extent: -76.321 [A] -to- 85.679 [P] -step- 2.000 mm [ 82 voxels] I-to-S extent: -91.679 [I] -to- 56.321 [S] -step- 2.000 mm [ 75 voxels] Number of time steps = 122 Time step = 2.00000s Origin = 0.00000s -- At sub-brick #0 '?' datum type is float -- At sub-brick #1 '?' datum type is float -- At sub-brick #2 '?' datum type is float For info on all 122 sub-bricks, use '3dinfo -verb'
and after:
Dataset File: test4.nii.gz Identifier Code: AFN_GNGdPDWC2YyDPdT3nJ6nwA Creation Date: Wed Oct 24 16:19:02 2018 Template Space: ORIG Dataset Type: Echo Planar (-epan) Byte Order: LSB_FIRST {assumed} [this CPU native = LSB_FIRST] Storage Mode: NIFTI Storage Space: 213,085,200 (213 million [mega]) bytes Geometry String: "MATRIX(-2,0,0,68.278,0,-2,0,85.67899,0,0,2,-91.67909):71,82,75" Data Axes Tilt: Plumb Data Axes Orientation: first (x) = Left-to-Right second (y) = Posterior-to-Anterior third (z) = Inferior-to-Superior [-orient LPI] R-to-L extent: -71.722 [R] -to- 68.278 [L] -step- 2.000 mm [ 71 voxels] A-to-P extent: -76.321 [A] -to- 85.679 [P] -step- 2.000 mm [ 82 voxels] I-to-S extent: -91.679 [I] -to- 56.321 [S] -step- 2.000 mm [ 75 voxels] Number of time steps = 122 Time step = 2.00000s Origin = 0.00000s -- At sub-brick #0 '?' datum type is float: -3493.93 to 84119.1 -- At sub-brick #1 '?' datum type is float: -3065.35 to 63797.2 -- At sub-brick #2 '?' datum type is float: -3107.67 to 64309.6 For info on all 122 sub-bricks, use '3dinfo -verb'
The second file is compatible with the AFNI viewer.
header info before:
fslhd sub-00XX_blah_bold_space-T1w_preproc.nii.gz | grep form qform_name Aligned Anat qform_code 2 qform_xorient Left-to-Right qform_yorient Posterior-to-Anterior qform_zorient Inferior-to-Superior sform_name Aligned Anat sform_code 2 sform_xorient Left-to-Right sform_yorient Posterior-to-Anterior sform_zorient Inferior-to-Superior descrip xform matrices modified by FixHeaderApplyTransforms (niworkflows v0.3.4).
and after 3drefit:
fslhd test4.nii.gz | grep form qform_name Scanner Anat qform_code 1 qform_xorient Left-to-Right qform_yorient Posterior-to-Anterior qform_zorient Inferior-to-Superior sform_name Scanner Anat sform_code 1 sform_xorient Left-to-Right sform_yorient Posterior-to-Anterior sform_zorient Inferior-to-Superior
and after 3dWarp+3drefit+3dAFNItoNIFTI:
fslhd test3.nii.gz | grep form qform_name Scanner Anat qform_code 1 qform_xorient Right-to-Left qform_yorient Anterior-to-Posterior qform_zorient Inferior-to-Superior sform_name Scanner Anat sform_code 1 sform_xorient Right-to-Left sform_yorient Anterior-to-Posterior sform_zorient Inferior-to-Superior
The 3 files are aligned and appear identical in fsleyes.
In the afni_proc.py and align_epi_anat.py, we concatenate the transformations including this obliquity transformation. Note that in some cases, the obliquity info is sometimes wrong, and alignment between EPI and anatomical can be computed without considering obliquity at all. We almost always consider the outputs of the processing pipelines to be cardinal, and the datasets are marked as cardinal with the equivalent C function to "3drefit -deoblique"
Hi @pjkohler. In this case, the data seems to start out as cardinal, and so running 3dWarp should really have no effect. The need to match the spaces is due to the original intention of the afni GUI being to provide the mechanism to go from orig to standard space. That ability is really obsolete or mostly unnecessary now, so we will have been planning to relax the restriction. But it currently stands.
On the flip side, if 2 datasets are aligned, why are they listed as being in different spaces? Ah, the confusion is due to sform_code 2 changing to 1. For that you can set AFNI_NIFTI_VIEW to orig.
yes, adding the line
AFNI_NIFTI_VIEW = orig
to the ~/.afnirc made the afni viewer treat the functional files as orig rather than tlrc without doing anything to the files. Thanks, @afni-rickr. Still unclear to me whether this is the same issue or different from what @mvdoc was experiencing.
@pjkohler The issue with @mvdoc, which I have not had the chance to read the updates to, was about obliquity, at least last I knew. It is possible this could apply as a secondary issue. I'll look it over tomorrow. Thanks.
Okay, sorry @pjkohler, I hadn't realized the issue @mvdoc had was in this thread. :) Anyway, hopefully that is resolved. Moving forward, we might have the afni GUI effectively run 3dWarp -deoblique under the hood, which is presumably what other packages are doing. We'll see. The downside might be that oblique data would not be shown without interpolation.
Hi all, maybe I'm confused, but I would expect the EPIs in
space-T1w
to be aligned to theT1w_preproc.nii.gz
. However, according to AFNI this is not the case, because the T1w is oblique (and hasTemplate Space
equal toORIG
) , while the EPIs are de-obliqued (Template Space = TLRC
). Am I missing something obvious here? Thanks!The preprocessing was run with fmriprep 1.0.3, with time-slicing correction and fieldmap correction.
This is the output of
3dinfo
for the preprocessed anatomical:And this for one of the functionals:
This is the output of
3dinfo
on the original filesanatomical:
functional: