Getting null coordinates for newly acquired Fiducials

Hello,

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?

image

Best wishes

Michel Audette

“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.

Hi. I cannot find the Place Fiducial button. Which toolbar do you mean?

Never mind. I found it. Thanks for your support.

This should help illustrate: https://www.slicer.org/wiki/Documentation/4.8/SlicerApplication/MainApplicationGUI#Mouse_Modes

Hi again,

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?

Best wishes,

Michel

Fiducial positions are displayed and saved in physical coordinates (in mm).

Yes, I know. Hence the question. Is there a flag that I can use to save in IJK, or must I get the IJK-RAS transformation from the mrml file?

I was under the impression that saving in IJK format was feasible with a resource flag set somehow.

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 guess you’ve found how to get IJK positions from the saved fiducial positions, but if not then let us know.

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).

What would you like to achieve? Run a Matlab function using inputs provided by Slicer?

This post is a follow up of http://slicer-users-archive.65878.n3.nabble.com/convert-fiducials-in-slicer-to-world-coordinates-td4026776.html

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.

node = slicer.util.getNode("vtkMRMLMarkupsFiducialNode1")

fileName = "/tmp/markups.fcsv"

io = slicer.app.ioManager()
snode = io.createAndAddDefaultStorageNode(node)
snode.SetFileName(fileName)

fileFormat = io.completeSlicerWritableFileNameSuffix(node)
snode.SetWriteFileFormat(fileFormat)

snode.SetCoordinateSystem(slicer.vtkMRMLMarkupsStorageNode.RAS)

snode.WriteData(node)

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

# Markups fiducial file version = 4.8
# CoordinateSystem = 2
# columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID
vtkMRMLMarkupsFiducialNode_0,-2.1452,-27.7047,-48.6402,0,0,0,1,1,1,0,F-1,,vtkMRMLScalarVolumeNode1

Thanks for your support, gents. Warm wishes, Michel

1 Like

Hi andras,
Is there a way to convert ijk points to ras world coordinates.

Thank you

Regards,
Saima Safdar

See here: https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_markup_fiducial_RAS_coordinates_from_volume_voxel_coordinates