Screws spacial organize

Hi everyone,
I´ve segmented the screws of an intraoperative CBCT of one of my spinal surgeries.
This is the result:

I´ve used Segment Statistics to get each segment center and I want to iterate all of them.

My problem is that they are messed up in space. Is there any way to organize them in colums and rows to iterate them in logical order from upper left to botton right?

Thanks in advance!

Maybe you can give them names related to the level in the spine and then sort them in the resulting statistics table.

Hi Steve,
This is the main problem. I get all screws in a single segment and then I split it with Islands tool. They have no order at all and I want to rename them in an automated way by position in the space.
Thanks for your help!

Glad to help, but unfortunately I don’t think there’s any existing/reliable way to do this automatically. It would be possible to come up with a heuristic that would usually give you a reasonable answer but may not be correct if there is a lot of variability in the input. In the Segment Statistics advanced options you can enable calculation of centroids (in patient RAS space). You could break those into R, A, and S and probably sorting by R and S would be what you want.

@apparrilla what is your end goal? Would you like to simulate insertion (choose a screw and position/orient in a CT image)?

@lassoan , This is just what I want to do.

I have some peace of code that is working for me. Maybe usefull for anyone else:

def orderScrews (self, segmentationNode):
    import SegmentStatistics
    segStatLogic = SegmentStatistics.SegmentStatisticsLogic()
    segStatLogic.getParameterNode().SetParameter("Segmentation", segmentationNode.GetID())
    segStatLogic.getParameterNode().SetParameter("LabelmapSegmentStatisticsPlugin.centroid_ras.enabled", str(True))
    segStatLogic.computeStatistics()
    stats = segStatLogic.getStatistics()

    pointListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode","ScrewPoints")
    pointListNode.CreateDefaultDisplayNodes()
    for segmentId in stats["SegmentIDs"]:
      centroid_ras = stats[segmentId,"LabelmapSegmentStatisticsPlugin.centroid_ras"]
      segmentName = segmentationNode.GetSegmentation().GetSegment(segmentId).GetName()
      pointListNode.AddFiducialFromArray(centroid_ras, segmentName)

    nOfControlPoints = pointListNode.GetNumberOfControlPoints()
    points = np.zeros([nOfControlPoints,2])
    for i in range(0, nOfControlPoints):
      point = np.zeros(3)
      pointListNode.GetNthControlPointPosition(i, point)
      points[i,:] = (point[0],point[2])
    print("points: %s"%points)

    numberScrew = 1
    pointsMini = points
    while pointsMini.size > 2:
      s = pointsMini.sum(axis=1)
      diff = np.diff(pointsMini, axis=1)
      first = pointsMini[np.argmax(diff)]
      print("first: %s" % first)
      first_index = np.where(points == first)
      first_mini_index = np.where(pointsMini == first)
      segmentationNode.GetSegmentation().GetNthSegment(int(first_index[0][0])).SetName("Screw_%s"% numberScrew)
      numberScrew += 1
      second = pointsMini[np.argmax(s)]
      print("second: %s" % second)
      second_index = np.where(points == second)
      second_mini_index = np.where(pointsMini == second)
      segmentationNode.GetSegmentation().GetNthSegment(int(second_index[0][0])).SetName("Screw_%s"% numberScrew)
      numberScrew += 1
      pointsMini = np.delete(pointsMini, [first_mini_index[0][0],second_mini_index[0][0]], axis=0)
      print ("pointsMini: %s" % pointsMini)    
    print("pointsMini.size: %s" % pointsMini.size)
    if pointsMini.size ==2:
      print("pointsMini[0]: %s" %pointsMini[0])
      last_index = np.where(points == pointsMini[0])
      print("last_index: %s"%last_index[0][0])
      segmentationNode.GetSegmentation().GetNthSegment(int(last_index[0][0])).SetName("Screw_%s"% numberScrew)

My end goal is to speed up the intraoperative screw reviewing after control CBCT.

@lassoan .
I´ve found a problem with my code if “second” i the same point as “first” because I loose a screw.
I´ve tryied to fix it with:

second = pointsMini[np.argmax(s)]
if np.array_equal(first, second): continue

Slicer crash with this with no error in Python Interactor. I just have to close Slicer because it´s continuosly processing something (while loop… of couse).
I´ve also tried: (first==second).all() and np…array_equiv(first, second) but all of them block Slicer app.

Do you know what i´m doing worng?
Thanks in advance.