I am trying to convert a set of RAS coordinates (.fcsv) exported from slicer, into voxel units. Ideally, I would like to do this on python as part of a workflow…
I’m using matmul with the coordinates [X,Y,Z] and the affine from the .nii file header of my registered image…
voxel_coords = [np.round(np.linalg.inv(affine) @ np.array(ras_coord).T) for ras_coord in ras_vals]
The coordinates are correctly spaced and seem to even be on the same plane , but there is some misalignment with the original image. Seems to be a translational problem, I’m thinking it has to do with the last row of my affine matrix, or a field of view issue? Or did I miss a step?
Pay attention to the coordinate system used in the file. In current Slicer versions it is LPS by default, so you can directly use it with the IJK to LPS matrix that is stored in the image header. If markup points are in RAS then you need to convert.
I would not recommend using fcsv files. They are not standard CSV. Best is to save as markup json instead, as you can reead/parse the file with a single line of code and you get easy access to all point coordinates a d all metadata in a Python object. If you want to process using Excel macros (not recommended) you can save as proper CSV by exporting the markups to a table node first (in Markups module).
Hi Andras. Appreciate your help on this. I will export as .json
My markups are in LPS format, I used the inv(affine) matrix which I got from the nifti file — nib.load(‘file.nii’).affine — is this the image header matrix you are referring to? This gave me the offset result in the screenshot
Regarding the script snippet you linked me: how do I create a volumeNode object in python? I have been looking around and it looks like I may need to use slicer.ScriptedLoadableModule or slicer.utils in this step? I assume I need to pass the .nii file
It would be helpful to know volumeNode.GetRASToIJKMatrix(volumeRasToIjk)
NIFTI format is very problematic. There are two ways to define IJK to LPS transformation (sform and qform) and not always clear which one should be used and how. Also, NIFTI uses RAS internally, so depending on what library you use to read the header and what options, you might get IJK to RAS.
To eliminate one source of error, I would recommend to save as NRRD format instead.
You can get IJK from LPS in a NRRD file using Python (outside Slicer’s Python environment) as shown here.