From 8a64ec2644d84daa33fb51a6b9d5b536011e9514 Mon Sep 17 00:00:00 2001 From: Sadhana Ravikumar Date: Mon, 16 Jun 2025 13:54:24 -0400 Subject: [PATCH 1/2] Center scaling transform on photoscan centroid (#372) --- .../OpenLIFUTransducerTracker.py | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py b/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py index 40a4dfa9..0bee3bca 100644 --- a/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py +++ b/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py @@ -639,19 +639,8 @@ def setupTransformNode(self): self.wizard().photoscanMarkupPage.facial_landmarks_fiducial_node.SetAndObserveTransformNodeID(self.photoscan_to_volume_transform_node.GetID()) # Set the center of the transformation to the center of the photocan model node - bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - self.wizard().photoscan.model_node.GetRASBounds(bounds) - center_world = [ - (bounds[0] + bounds[1]) / 2, - (bounds[2] + bounds[3]) / 2, - (bounds[4] + bounds[5]) / 2 - ] - - center_local = [0.0,0.0,0.0] - transform_from_world = vtk.vtkGeneralTransform() - self.photoscan_to_volume_transform_node.GetTransformFromWorld(transform_from_world) - transform_from_world.TransformPoint(center_world,center_local ) - self.photoscan_to_volume_transform_node.SetCenterOfTransformation(center_local) + centroid_local = self.getPhotoscanCentroidRAS() + self.photoscan_to_volume_transform_node.SetCenterOfTransformation(centroid_local) self.photoscan_to_volume_transform_node.SetAndObserveTransformNodeID(self.scaling_transform_node.GetID()) # Add observer after setup @@ -737,11 +726,41 @@ def disable_manual_registration(self): self.update_runICPRegistrationPV_button() def updateScaledTransformNode(self): + """Creates a composite transform that scales the photoscan from the centroid of the model, applying the scaling value + set using the the sliding widget""" + compositeTransform = vtk.vtkTransform() + compositeTransform.Identity() + centroid_local = self.getPhotoscanCentroidRAS() + compositeTransform.Translate(-centroid_local[0], -centroid_local[1], -centroid_local[2]) # Translate the centroid to the origin + scaling_value = self.ui.scalingTransformMRMLSliderWidget.value - scaling_matrix = np.diag([scaling_value, scaling_value, scaling_value, 1]) - # Need to also update the origin of the scaling transform - self.scaling_transform_node.SetMatrixTransformToParent(numpy_to_vtk_4x4(scaling_matrix)) + compositeTransform.Scale(scaling_value, scaling_value, scaling_value) # apply scaling + + compositeTransform.Translate(centroid_local[0], centroid_local[1], centroid_local[2]) + + finalMatrix = vtk.vtkMatrix4x4() + compositeTransform.GetMatrix(finalMatrix) + + self.scaling_transform_node.SetMatrixTransformToParent(finalMatrix) + + def getPhotoscanCentroidRAS(self): + """Calculates the centroid of the photoscan model node""" + + bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + self.wizard().photoscan.model_node.GetRASBounds(bounds) + center_world = [ + (bounds[0] + bounds[1]) / 2, + (bounds[2] + bounds[3]) / 2, + (bounds[4] + bounds[5]) / 2 + ] + + center_local = [0.0,0.0,0.0] + transform_from_world = vtk.vtkGeneralTransform() + self.photoscan_to_volume_transform_node.GetTransformFromWorld(transform_from_world) + transform_from_world.TransformPoint(center_world,center_local ) + + return center_local def isComplete(self): """" Determines if the 'Next' button should be enabled""" From 9caa542104d40582bd12d92193aded37d21a3aca Mon Sep 17 00:00:00 2001 From: Sadhana Ravikumar Date: Tue, 17 Jun 2025 11:55:06 -0400 Subject: [PATCH 2/2] Improve clarity of variable and function names (#372) --- .../OpenLIFUTransducerTracker.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py b/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py index 0bee3bca..2ddbb266 100644 --- a/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py +++ b/OpenLIFUTransducerTracker/OpenLIFUTransducerTracker.py @@ -639,8 +639,8 @@ def setupTransformNode(self): self.wizard().photoscanMarkupPage.facial_landmarks_fiducial_node.SetAndObserveTransformNodeID(self.photoscan_to_volume_transform_node.GetID()) # Set the center of the transformation to the center of the photocan model node - centroid_local = self.getPhotoscanCentroidRAS() - self.photoscan_to_volume_transform_node.SetCenterOfTransformation(centroid_local) + photoscan_centroid = self.getTransformedPhotoscanCentroid() + self.photoscan_to_volume_transform_node.SetCenterOfTransformation(photoscan_centroid) self.photoscan_to_volume_transform_node.SetAndObserveTransformNodeID(self.scaling_transform_node.GetID()) # Add observer after setup @@ -731,36 +731,39 @@ def updateScaledTransformNode(self): compositeTransform = vtk.vtkTransform() compositeTransform.Identity() - centroid_local = self.getPhotoscanCentroidRAS() - compositeTransform.Translate(-centroid_local[0], -centroid_local[1], -centroid_local[2]) # Translate the centroid to the origin + photoscan_centroid = self.getTransformedPhotoscanCentroid() + compositeTransform.Translate(-photoscan_centroid[0], -photoscan_centroid[1], -photoscan_centroid[2]) # Translate the centroid to the origin scaling_value = self.ui.scalingTransformMRMLSliderWidget.value compositeTransform.Scale(scaling_value, scaling_value, scaling_value) # apply scaling - compositeTransform.Translate(centroid_local[0], centroid_local[1], centroid_local[2]) + compositeTransform.Translate(photoscan_centroid[0], photoscan_centroid[1], photoscan_centroid[2]) finalMatrix = vtk.vtkMatrix4x4() compositeTransform.GetMatrix(finalMatrix) self.scaling_transform_node.SetMatrixTransformToParent(finalMatrix) - def getPhotoscanCentroidRAS(self): - """Calculates the centroid of the photoscan model node""" + def getTransformedPhotoscanCentroid(self): + """Returns the centroid of the photoscan model node. + The centroid is initially calculated in the photoscan's native RAS coordinate + system and then transformed into the volume's coordinate space + using the `photoscan_to_volume_transform_node`.""" bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] self.wizard().photoscan.model_node.GetRASBounds(bounds) - center_world = [ + centroid_world = [ (bounds[0] + bounds[1]) / 2, (bounds[2] + bounds[3]) / 2, (bounds[4] + bounds[5]) / 2 ] - center_local = [0.0,0.0,0.0] + centroid_transformed = [0.0,0.0,0.0] transform_from_world = vtk.vtkGeneralTransform() self.photoscan_to_volume_transform_node.GetTransformFromWorld(transform_from_world) - transform_from_world.TransformPoint(center_world,center_local ) + transform_from_world.TransformPoint(centroid_world,centroid_transformed) - return center_local + return centroid_transformed def isComplete(self): """" Determines if the 'Next' button should be enabled"""