I am returning to Slicer after several years, and I’m finding that the Fiducials interface does not properly acquire the coordinates the selected point. Everything that I acquire shows RAS coordinates set to 0.0, 0.0, 0.0. Is there something that I need to be doing to acquire proper Landmark coordinates?
“New fiducial” button in the advanced section of Markups module creates a markup in the (0,0,0) position. To create a point in a specific position, click on the “Place fiducial” button on the toolbar then click in a viewer to place it.
I am using the Fiducials to initialize a deformable surface model, and the code for this model seems to operate in voxel coordinates rather than world coordinates. Can you tell me if I can save in the Fiducials in voxel coordinates?
Fiducials are not linked to a particular volume, so you cannot save them relative to a particular volume’s IJK coordinate system. I don’t remember this having come up as a need ever, since volumes are defined in physical coordinate system, too.
It did come up. I googled " fiducials slicer voxel coordinates". In fact, it came up with my former student Rabia Haq, but she is not providing much in terms of support, so I’m having to redo the same legwork now.
I cannot follow what they did. I need to have a simple solution in just a few lines, not several threads with the keywords I am looking for. I merely pointed them out to show you that the issue has come up before.
Fiducial points are linked to the volume for which the slice on which
they’ve placed, via
GetNthFiducialAssociatedNodeID
I’d started to work on the Get method for IJK but didn’t finish it - the
use case was for sending it to CLI modules via the storage node.
If you get the RAS to IJK transform of the volume you’re working with and
create a new transform node with that transform, you can place your world/
RAS coordinates fiducial list under it and then harden it to get the IJK
coordinates (or just display them in the Markups module by clicking the
Transformed checkbox).
WARNING: This snippets posted below are not production ready and will most likely break in the future
Fiducial and coordinate system
It is indeed possible to choose the coordinate system when using the python console (there is not yet a UI to select the output coordinate system). The default is LPS.
Here is a code snipped allowing to save fiducials from the python console.
IJK is already a valid format, the only “issue” is that the writer doesn’t implement it yet:
Exporting fiducial to IJK (aka voxel coordinates): A draft implementation
If I recall properly, the reason why this is not yet implemented is because the IJKToRAS matrix is associated with the volume and there is no obvious linkage between the volume and the fiducial.
That said, you could do the following:
def exportFiducials(markupNode, outputFileName, outputCoordinates, associatedVolumeNode=None):
"""Export fiducials to `outputFileName` considering the `outputCoordinates`.
Supported outputCoordinates are `LPS`, `RAS` and `IJK`.
Specifying `IJK` requires `associatedVolumeNode` to be specified.
"""
# Create temporary node
savedMarkupNode = slicer.vtkMRMLMarkupsFiducialNode()
savedMarkupNode.Copy(markupNode)
snode = slicer.vtkMRMLMarkupsFiducialStorageNode()
snode.SetFileName(outputFileName)
savedMarkupNode.SetAndObserveStorageNodeID(snode.GetID())
io = slicer.app.ioManager()
fileFormat = io.completeSlicerWritableFileNameSuffix(markupNode)
snode.SetWriteFileFormat(fileFormat)
snode.SetCoordinateSystem(outputCoordinates)
if outputCoordinates == slicer.vtkMRMLMarkupsStorageNode.IJK:
if associatedVolumeNode is None:
print("Can not save markup node with IJK coordinate system without a valid volume node")
return
# Get RAStoIJK matrix associated with the volume
rasToIJK = vtk.vtkMatrix4x4()
associatedVolumeNode.GetRASToIJKMatrix(rasToIJK)
# Convert from RAS to IJK
for idx in range(savedMarkupNode.GetNumberOfFiducials()):
rasCoord = [0.] * 4
savedMarkupNode.GetNthFiducialWorldCoordinates(idx, rasCoord)
ijkCoord = [0.] * 4
rasToIJK.MultiplyPoint(rasCoord, ijkCoord)
savedMarkupNode.SetNthFiducialWorldCoordinates(idx, ijkCoord)
snode.WriteData(node)
# Prerequisites
# (1) Download MRHead
# (2) Place a fiducial
# Download sampledata
volume = slicer.util.getNode("MRHead")
# Get Markup (aka fiducial)
node = slicer.util.getNode("vtkMRMLMarkupsFiducialNode1")
# Output filename
fileName = "/tmp/markups.fcsv"
exportFiducials(node, fileName, slicer.vtkMRMLMarkupsStorageNode.IJK, volume)
The file will then indicate CoordinateSystem = 2 which correspond to IJK