|
Size: 8479
Comment: Linked DICOM.
|
Size: 6526
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 1: | Line 1: |
| #pragma section-numbers on | [[FreeSurferWiki|top]] |
| Line 3: | Line 3: |
| = Index = | = FreeSurfer Coordinate Systems = |
| Line 5: | Line 5: |
| [[Navigation(children)]] [[TableOfContents]] |
The "official" FreeSurfer Coordinate definitions can be found in the following power-points slides ('''SEE THESE FIRST'''): |
| Line 8: | Line 7: |
| = Coordinate systems = | * '''[[attachment:fscoordinates.ppt|FS Coordinates (PowerPoint)|&do=get]]''' |
| Line 10: | Line 9: |
| Freesurfer uses at least 4 voxel coordinate systems and 4 "RAS" coordinate systems. {{{ 0. Stored in volume file original volume ========> RAS ("scanner RAS", c_(r,a,s)!=0 in general) | | | 1. calculated | identity | | V 2. calculated V conformed volume ========> RAS (to have the same c_(r,a,s) as above) L^3 with S mm voxel | | | | identity | 3. calculated (translation) | | V 4. fixed(standard) V conformed volume ========> SurfaceRAS with c_(r,a,s) = 0 L^3 with S mm voxel }}} |
or PDF: |
| Line 28: | Line 11: |
| The functional analysis stream uses another coordinate system to map from the src volume. | * '''[[attachment:fscoordinates.pdf|FS Coordinates (PDF)|&do=get]]''' |
| Line 30: | Line 13: |
| {{{ original volume ========> RAS ("scanner RAS", c_(r,a,s) != 0 in general) | | | identity | calculated V 5. fixed("standard") V original volume ========> tkregRAS where c_(r,a,s) = 0 | | | 6. calculated | mri2fmri (registration will give this) | | V 7. fixed("standard") V overlay volume ========> fRAS where c_(r,a,s) = 0 }}} All these coordinate systems make it a rather difficult task to trace to the original source volume voxel index from surface or functional index. If you can follow the arrows, you can get the necessary transforms easily. |
This also includes a little intro to Affine Transformations. |
| Line 44: | Line 15: |
| The transform 2 (CORONAL coordinates) is calculated so that the following equation holds. That is, the direction cosine part is fixed, but not the translation part. In this way, the conformed volume always in the CORONAL orientation. | See also: '''[[attachment:vox2ras.pdf|VOX2RAS(PDF)|&do=get]]''' |
| Line 46: | Line 17: |
| {{{ [-1 0 0 s1][S 0 0 0][L/2] [c_r] s1 = c_r + S*L/2 [ 0 0 1 s2][0 S 0 0][L/2] = [c_a] ==> s2 = c_a - S*L/2 [ 0 -1 0 s3][0 0 S 0][L/2] [c_s] s3 = c_s + S*L/2 [ 0 0 0 1][0 0 0 1][ 1 ] [ 1 ] }}} where c_(r,a,s) is from the "scanner RAS". This "scanner RAS" has the physical meaning of "Right-Anterior-Superior" directions of the head. |
== Transformations between Freesurfer Surfaces and TrackVis == * FreeSurferTrackVisTransforms '''Also see:''' [[http://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferTrackVisTransforms|TrackVis Transforms]] '''<--- !!!''' |
| Line 54: | Line 21: |
| The transform 4 (surface``RAS``From``Conformed``Voxel) is fixed as | == Use Cases == |
| Line 56: | Line 23: |
| {{{ [-1 0 0 S*L/2][S 0 0 0] [ 0 0 1 -S*L/2][0 S 0 0] [ 0 -1 0 S*L/2][0 0 S 0] [ 0 0 0 1 ][0 0 0 1] }}} |
Below are several cases in which someone has a coordinate in one coordinate system and wants to transform it to some other coordinate system (eg, a point on the surface to MNI305 space). Each computation shows the matrices needed and how to get them as well as a check using tkmedit/tksurfer. The equations are based on those in '''[[attachment:fscoordinates.ppt|FS Coordinates (PowerPoint)|&do=get]]'''. The checks assume you have run tkmedit and tksurfer in the following way: |
| Line 63: | Line 25: |
| The transform 1 (conformed``Voxel``From``Voxel) is calculated by (in a matrix sense) | tkmedit subject orig.mgz -reg register.dat -ov mov.nii -surfs |
| Line 65: | Line 27: |
| {{{ xform1 = inv(xform2) * xform0 = [1/S 0 0 0][-1 0 0 s1] * xform0 [ 0 1/S 0 0][ 0 0 -1 s3] [ 0 0 1/S 0][ 0 1 0 -s2] [ 0 0 0 1][ 0 0 0 1 ] }}} The transform 3(Surface``RAS``From``RAS) is calculated by (in a matrix sense). Note that it is independent of conformed voxel size S and the length L: |
tksurfer subject lh inflated -reg register.dat -ov mov.nii |
| Line 73: | Line 29: |
| {{{ xform3 = xform4 * inv(xform2) = [ 1 0 0 -c_r] [ 0 1 0 -c_a] [ 0 0 1 -c_s] [ 0 0 0 1 ] }}} Because of the xform3 (changing only translation part), it is easy to calculate Surface``RAS``From``Voxel (xform3*xform0) and is given by {{{ SurfaceRASFromVoxel = [ 3x3 part (t1 - c_r)] [ same as (t2 - c_a)] [ xform0 (t3 - c_s)] [ 0 1 ] }}} where t1,t2,t3 are the translation part of xform0. The transform 5 and the transform 7 are calculated by the requirement {{{ [-1 0 0 s1][xsize 0 0 0][width/2 ] [0] [ 0 0 1 s2][ 0 ysize 0 0][height/2] = [0] [ 0 -1 0 s3][ 0 0 zsize 0][depth/2 ] [0] [ 0 0 0 1][ 0 0 0 1][ 1 ] [1] }}} Here the name "RAS" lost the meaning completely. This "RAS" is just to be used for alignment purpose only. The width/height/depth are for the appropriate volume. The reason is that the original volume could be sagittal or horizontal. = Relationship between lores and hires surfaceRAS = {{{ conformed vol -------------> surfRAS | | | | surfRASToRAS V V high res ------------> RAS | | | | Xfm V V low res ------------> RAS | | | | RASToSurfRAS V V conformed vol -------------> surfRAS }}} Therefore, the map from the high res surfaceRAS to the low res surfaceRAS is given by {{{ highresSurfRASTolowresSurfRAS = RASTosurfRAS(lowres) * Xfm * sufRASToRAS(highres) }}} which is not equal to Xfm. In fact, {{{ RASTosurfRAS(lowres) = 1 0 0 -c_r(lowres) surfRASTORAS(highres) = 1 0 0 c_r(highres) 0 1 0 -c_a(lowres) 0 1 0 c_a(highres) 0 0 1 -c_s(lowres) 0 0 1 c_s(highres) 0 0 0 1 0 0 0 1 }}} or write these as {{{ RASToSurfRAS(lowres) = [ 1 -C(lowres)] surfRASToRAS(highres) = [ 1 C(highres)] [ 0 1 ] [ 0 1 ] Xfm = [ R T ] [ 0 1 ] }}} Then, {{{ highresSurfRASTolowresSurfRAS = [ 1 -C(lowres)] x [ R T ] x [ 1 C(highres)] [ 0 1 ] [ 0 1 ] [ 0 1 ] = [ R R*C(highres)-C(lowres) + T ] [ 0 1 ] }}} The conclusion is that the transform is non-trivial. Even when R = 1 and T = 0 (no rotation), we have {{{ highresSurfRASTolowresSurfRAS = [ 1 C(highres)-C(lowres)] [ 0 1 ] }}} Therefore, when translating highres vertex positions into lowres vertex position, we must make sure that c_(ras) for highres and lowres must match exactly. |
Note on Talairach: FreeSurfer does not report true "Talairach" coordinates. The coordinates listed unter "Talairach" are actually based on Matthew Brett's 10/8/98 non-linear transform from MNI305 space (see http://www.mrc-cbu.cam.ac.uk/Imaging/mnispace.html). FreeSurfer also reports "Talairach MNI" coordinates. These are MNI305 space. |
| Line 154: | Line 32: |
| = Direction cosines = Each volume format stores information in each own way. COR volume (COR-001, ...) stores it in COR-.info file. ["DICOM"] stores it in the file. Note that Analyze file (.img)stores it in .mat file, meanwhile bflort (.bfloat or .bshort) stores it in .bhdr file. For these formats it is essential to have these files. |
== Transforms within a subject's anatomical space == |
| Line 157: | Line 34: |
| ------------------------------------------------------------------ 1. I have a point on the surface and want to compute the CRS for voxel in the orig.mgz that corresponds to this point: |
|
| Line 158: | Line 38: |
| = MNI Talairach in tkmedit = ["tkmedit"] shows a non-identity Talairach even though talairach.xfm is an identity matrix. The reason is described in [http://www.mrc-cbu.cam.ac.uk/Imaging/Common/mnispace.shtml Cambride Imagers-MNI space]. ["tkmedit"] uses Approach 2 described in the web page. |
VoxCRS = inv(Torig)*[tkrR tkrA tkrS 1]' |
| Line 161: | Line 40: |
| There are two talairach transformed used in ["tksurfer"]. One is MNI talairach and the other is modified talairach. The modified talairach is done in `tksurfer.c conv_initialize()`: | where [tkrR tkrA tkrS] is your point on the RAS on the surface is in the "tkregister space" (eg, the "Volume coordinate" in tksurfer) and Torig is the Vox2tkrRAS obtained from "mri_info --vox2ras-tkr orig.mgz" (note: this is the same for all orig volumes). |
| Line 163: | Line 45: |
| {{{ For Z < 0: |
Test: click on a point in tksurfer. Use "Vertex RAS" to compute Vox2CRS. Round Vox2CRS to the nearest integer. Hit Save Point in tksurfer. In tkmedit, Goto Saved Point. Compare VoxCRS to "Volume Index". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match. |
| Line 166: | Line 51: |
| conv_mnital_to_tal_m_ltz = MatrixIdentity (4, NULL); stuff_four_by_four (conv_mnital_to_tal_m_ltz, 0.99, 0, 0, 0, 0.00, 0.9688, 0.042, 0, 0.00, -0.0485, 0.839, 0, 0.00, 0, 0, 1); }}} |
------------------------------------------------------------------ 2. I have a point on the surface and want to compute the MNI305 RAS that corresponds to this point: |
| Line 174: | Line 55: |
| {{{ For Z > 0: conv_mnital_to_tal_m_gtz = MatrixIdentity (4, NULL); stuff_four_by_four (conv_mnital_to_tal_m_gtz, 0.99, 0, 0, 0, 0.00, 0.9688, 0.046, 0, 0.00, -0.0485, 0.9189, 0, 0.00, 0, 0, 1); }}} |
MNI305RAS = TalXFM*Norig*inv(Torig)*[tkrR tkrA tkrS 1]' TalXFM: subject/orig/transforms/talairach.xfm Norig: mri_info --vox2ras orig.mgz Torig: mri_info --vox2ras-tkr orig.mgz Test: click on a point in tksurfer. Use "Vertex RAS" to compute MNI305RAS. Compare MNI305RAS to "Vertex MNI Talairach". Also, hit Save Point in tksurfer. In tkmedit, Goto Saved Point, compare MNI305RAS to "MNI Coordinates". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match. ------------------------------------------------------------------ 3. I have a point on the surface and want to compute the Scanner RAS from the point in orig.mgz that corresponds to this point: ScannerRAS = Norig*inv(Torig)*[tkrR tkrA tkrS 1]' Norig: mri_info --vox2ras orig.mgz Torig: mri_info --vox2ras-tkr orig.mgz Test: click on a point in tksurfer. Use "Vertex RAS" to compute ScannerRAS. Save Point. In tkmedit, Goto Saved Point, compare ScannerRAS to "Volume Scanner Coordinates". ---------------------------------------------------------------- 4. I have a CRS from a voxel in the orig.mgz volume and want to compute the RAS in surface space (tkrRAS) for this point: tkrRAS = Torig*[C R S 1]' Torig: mri_info --vox2ras-tkr orig.mgz Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Volume index" to compute tkrRAS. It "Save Point" in tkmedit. In tksurfer, Goto Saved Point. Compare tkrRAS to "Vertex RAS". It might not be exactly the same because you might not have clicked exactly on a vertex in tkmedit. == Transforms within subject across imaging modalities == ------------------------------------------------------------------ 5. I have a point on the surface and want to compute the CRS for the corresponding voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume: movCRS = inv(Tmov)*Reg*[tkrR tkrA tkrS 1]' Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat tkregister2 --mov mov.nii --reg register.dat Test: click on a point in tksurfer and hit Save Point. Compute movCRS using the "Vertex RAS". Round movCRS to the nearest integer. In tkmedit, Goto Saved Point. Compare movCRS to "Functional Overlay Index Coordinates". -------------------------------------------------------------- 6. I have a CRS from a voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume and want to compute the CRS for the corresponding point in the orig.mgz: origCRS = Torig * inv(Reg) * inv(Tmov) * [movC movR movS 1]' Torig: mri_info --vox2ras-tkr orig.mgz Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat tkregister2 --mov mov.nii --reg register.dat Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Functional Overlay Index Coordinates" to compute origCRS (round to the nearest integer). Compare origCRS to the "Volume index". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match. -------------------------------------------------------------- 7. I have a CRS from a voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume and want to compute the tkrRAS for the corresponding point on the surface: tkrRAS = inv(Reg) * Tmov * [movC movR movS 1]' Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat tkregister2 --mov mov.nii --reg register.dat Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Functional Overlay Index Coordinates" to compute tkrRAS. Hit "Save Point" in tkmedit. In tksurfer, hit "Goto Saveed Point". Compare tkrRAS to "Vertex RAS". It might not be exactly the same because you might not have clicked exactly on a vertex in tkmedit. |
FreeSurfer Coordinate Systems
The "official" FreeSurfer Coordinate definitions can be found in the following power-points slides (SEE THESE FIRST):
or PDF:
This also includes a little intro to Affine Transformations.
See also: VOX2RAS(PDF)
Transformations between Freesurfer Surfaces and TrackVis
Also see: TrackVis Transforms <--- !!!
Use Cases
Below are several cases in which someone has a coordinate in one coordinate system and wants to transform it to some other coordinate system (eg, a point on the surface to MNI305 space). Each computation shows the matrices needed and how to get them as well as a check using tkmedit/tksurfer. The equations are based on those in FS Coordinates (PowerPoint). The checks assume you have run tkmedit and tksurfer in the following way:
tkmedit subject orig.mgz -reg register.dat -ov mov.nii -surfs
tksurfer subject lh inflated -reg register.dat -ov mov.nii
Note on Talairach: FreeSurfer does not report true "Talairach" coordinates. The coordinates listed unter "Talairach" are actually based on Matthew Brett's 10/8/98 non-linear transform from MNI305 space (see http://www.mrc-cbu.cam.ac.uk/Imaging/mnispace.html). FreeSurfer also reports "Talairach MNI" coordinates. These are MNI305 space.
Transforms within a subject's anatomical space
1. I have a point on the surface and want to compute the CRS for voxel in the orig.mgz that corresponds to this point:
VoxCRS = inv(Torig)*[tkrR tkrA tkrS 1]'
where [tkrR tkrA tkrS] is your point on the RAS on the surface is in the "tkregister space" (eg, the "Volume coordinate" in tksurfer) and Torig is the Vox2tkrRAS obtained from "mri_info --vox2ras-tkr orig.mgz" (note: this is the same for all orig volumes).
Test: click on a point in tksurfer. Use "Vertex RAS" to compute Vox2CRS. Round Vox2CRS to the nearest integer. Hit Save Point in tksurfer. In tkmedit, Goto Saved Point. Compare VoxCRS to "Volume Index". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match.
2. I have a point on the surface and want to compute the MNI305 RAS that corresponds to this point:
MNI305RAS = TalXFM*Norig*inv(Torig)*[tkrR tkrA tkrS 1]'
- TalXFM: subject/orig/transforms/talairach.xfm Norig: mri_info --vox2ras orig.mgz Torig: mri_info --vox2ras-tkr orig.mgz
Test: click on a point in tksurfer. Use "Vertex RAS" to compute MNI305RAS. Compare MNI305RAS to "Vertex MNI Talairach". Also, hit Save Point in tksurfer. In tkmedit, Goto Saved Point, compare MNI305RAS to "MNI Coordinates". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match.
3. I have a point on the surface and want to compute the Scanner RAS from the point in orig.mgz that corresponds to this point:
ScannerRAS = Norig*inv(Torig)*[tkrR tkrA tkrS 1]'
- Norig: mri_info --vox2ras orig.mgz Torig: mri_info --vox2ras-tkr orig.mgz
Test: click on a point in tksurfer. Use "Vertex RAS" to compute ScannerRAS. Save Point. In tkmedit, Goto Saved Point, compare ScannerRAS to "Volume Scanner Coordinates".
4. I have a CRS from a voxel in the orig.mgz volume and want to compute the RAS in surface space (tkrRAS) for this point:
tkrRAS = Torig*[C R S 1]'
- Torig: mri_info --vox2ras-tkr orig.mgz
Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Volume index" to compute tkrRAS. It "Save Point" in tkmedit. In tksurfer, Goto Saved Point. Compare tkrRAS to "Vertex RAS". It might not be exactly the same because you might not have clicked exactly on a vertex in tkmedit.
Transforms within subject across imaging modalities
5. I have a point on the surface and want to compute the CRS for the corresponding voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume:
movCRS = inv(Tmov)*Reg*[tkrR tkrA tkrS 1]'
- Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat
- tkregister2 --mov mov.nii --reg register.dat
Test: click on a point in tksurfer and hit Save Point. Compute movCRS using the "Vertex RAS". Round movCRS to the nearest integer. In tkmedit, Goto Saved Point. Compare movCRS to "Functional Overlay Index Coordinates".
6. I have a CRS from a voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume and want to compute the CRS for the corresponding point in the orig.mgz:
origCRS = Torig * inv(Reg) * inv(Tmov) * [movC movR movS 1]'
- Torig: mri_info --vox2ras-tkr orig.mgz Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat
- tkregister2 --mov mov.nii --reg register.dat
Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Functional Overlay Index Coordinates" to compute origCRS (round to the nearest integer). Compare origCRS to the "Volume index". Note: you may need to use the "Volume RAS" from tkmedit in the computation above to get an exact match.
7. I have a CRS from a voxel in my functional/diffusion/ASL/rawavg/etc "mov" volume and want to compute the tkrRAS for the corresponding point on the surface:
tkrRAS = inv(Reg) * Tmov * [movC movR movS 1]'
- Tmov: mri_info --vox2ras-tkr mov.nii Reg: register.dat
- tkregister2 --mov mov.nii --reg register.dat
Test: click on a point in tkmedit very close to the left hemi white surface. Use the "Functional Overlay Index Coordinates" to compute tkrRAS. Hit "Save Point" in tkmedit. In tksurfer, hit "Goto Saveed Point". Compare tkrRAS to "Vertex RAS". It might not be exactly the same because you might not have clicked exactly on a vertex in tkmedit.
