def __init__( self, stepid ): self.initialize( stepid ) self.setName( '5. Place Screws' ) self.setDescription( 'Load screw models and change orientation using sliders' ) self.screwPath = None self.screwName = None self.coords = [0,0,0] self.matrix1 = vtk.vtkMatrix3x3() self.matrix2 = vtk.vtkMatrix3x3() self.matrix3 = vtk.vtkMatrix3x3() self.matrixScrew = vtk.vtkMatrix4x4() self.fiduciallist = [] self.screwSummary = [] self.screwList = [] self.currentFidIndex = 0 self.currentFidLabel = None self.fidNode = slicer.vtkMRMLMarkupsFiducialNode() self.valueTemp1 = 0 self.valueTemp2 = 0 self.driveTemp = 0 self.__loadScrewButton = None self.__parent = super( ScrewStep, self ) self.timer = qt.QTimer() self.timer.setInterval(2) self.timer.connect('timeout()', self.driveScrew) self.timer2 = qt.QTimer() self.timer2.setInterval(2) self.timer2.connect('timeout()', self.reverseScrew) self.screwInsert = 0.0
def transformScrewComposite(self, inputMatrix): transformFid = slicer.mrmlScene.GetFirstNodeByName( 'Transform-%s' % self.currentFidLabel) matrixScrew = transformFid.GetMatrixTransformToParent() newMatrix = vtk.vtkMatrix3x3() outputMatrix = vtk.vtkMatrix3x3() newMatrix.SetElement(0, 0, matrixScrew.GetElement(0, 0)) newMatrix.SetElement(0, 1, matrixScrew.GetElement(0, 1)) newMatrix.SetElement(0, 2, matrixScrew.GetElement(0, 2)) newMatrix.SetElement(1, 0, matrixScrew.GetElement(1, 0)) newMatrix.SetElement(1, 1, matrixScrew.GetElement(1, 1)) newMatrix.SetElement(1, 2, matrixScrew.GetElement(1, 2)) newMatrix.SetElement(2, 0, matrixScrew.GetElement(2, 0)) newMatrix.SetElement(2, 1, matrixScrew.GetElement(2, 1)) newMatrix.SetElement(2, 2, matrixScrew.GetElement(2, 2)) vtk.vtkMatrix3x3.Multiply3x3(newMatrix, inputMatrix, outputMatrix) #coords = [0,0,0] #self.fid.GetFiducialCoordinates(coords) matrixScrew.SetElement(0, 0, outputMatrix.GetElement(0, 0)) matrixScrew.SetElement(0, 1, outputMatrix.GetElement(0, 1)) matrixScrew.SetElement(0, 2, outputMatrix.GetElement(0, 2)) #matrixScrew.SetElement(0,3,self.coords[0]) matrixScrew.SetElement(1, 0, outputMatrix.GetElement(1, 0)) matrixScrew.SetElement(1, 1, outputMatrix.GetElement(1, 1)) matrixScrew.SetElement(1, 2, outputMatrix.GetElement(1, 2)) #matrixScrew.SetElement(1,3,self.coords[1]) matrixScrew.SetElement(2, 0, outputMatrix.GetElement(2, 0)) matrixScrew.SetElement(2, 1, outputMatrix.GetElement(2, 1)) matrixScrew.SetElement(2, 2, outputMatrix.GetElement(2, 2)) #matrixScrew.SetElement(2,3,self.coords[2]) matrixScrew.SetElement(3, 0, 0) matrixScrew.SetElement(3, 1, 0) matrixScrew.SetElement(3, 2, 0) matrixScrew.SetElement(3, 3, 1) transformFid.SetMatrixTransformToParent(matrixScrew) transformFid.UpdateScene(slicer.mrmlScene)
def transformScrewComposite(self, inputMatrix): transformFid = slicer.util.getNode('Transform-%s' % self.currentFidLabel) matrixScrew = transformFid.GetMatrixTransformToParent() newMatrix = vtk.vtkMatrix3x3() outputMatrix = vtk.vtkMatrix3x3() newMatrix.SetElement(0,0,matrixScrew.GetElement(0,0)) newMatrix.SetElement(0,1,matrixScrew.GetElement(0,1)) newMatrix.SetElement(0,2,matrixScrew.GetElement(0,2)) newMatrix.SetElement(1,0,matrixScrew.GetElement(1,0)) newMatrix.SetElement(1,1,matrixScrew.GetElement(1,1)) newMatrix.SetElement(1,2,matrixScrew.GetElement(1,2)) newMatrix.SetElement(2,0,matrixScrew.GetElement(2,0)) newMatrix.SetElement(2,1,matrixScrew.GetElement(2,1)) newMatrix.SetElement(2,2,matrixScrew.GetElement(2,2)) vtk.vtkMatrix3x3.Multiply3x3(newMatrix, inputMatrix, outputMatrix) #coords = [0,0,0] #self.fid.GetFiducialCoordinates(coords) matrixScrew.SetElement(0,0,outputMatrix.GetElement(0,0)) matrixScrew.SetElement(0,1,outputMatrix.GetElement(0,1)) matrixScrew.SetElement(0,2,outputMatrix.GetElement(0,2)) #matrixScrew.SetElement(0,3,self.coords[0]) matrixScrew.SetElement(1,0,outputMatrix.GetElement(1,0)) matrixScrew.SetElement(1,1,outputMatrix.GetElement(1,1)) matrixScrew.SetElement(1,2,outputMatrix.GetElement(1,2)) #matrixScrew.SetElement(1,3,self.coords[1]) matrixScrew.SetElement(2,0,outputMatrix.GetElement(2,0)) matrixScrew.SetElement(2,1,outputMatrix.GetElement(2,1)) matrixScrew.SetElement(2,2,outputMatrix.GetElement(2,2)) #matrixScrew.SetElement(2,3,self.coords[2]) matrixScrew.SetElement(3,0,0) matrixScrew.SetElement(3,1,0) matrixScrew.SetElement(3,2,0) matrixScrew.SetElement(3,3,1) transformFid.SetMatrixTransformToParent(matrixScrew) transformFid.UpdateScene(slicer.mrmlScene)
def getVTKMatrixFromNumpyMatrix(self, numpyMatrix): dimensions = len(numpyMatrix) - 1 if dimensions == 2: vtkMatrix = vtk.vtkMatrix3x3() elif dimensions == 3: vtkMatrix = vtk.vtkMatrix4x4() else: raise ValueError('Unknown matrix dimensions.') for row in range(dimensions + 1): for col in range(dimensions + 1): vtkMatrix.SetElement(row, col, numpyMatrix[row, col]) return vtkMatrix
def driveScrew(self): if self.screwInsert < int(self.__diameter): value = self.screwInsert # attempt to rotate with driving angle3 = math.pi / 180.0 * 72 #((360/2.5)*self.screwInsert) matrix3 = vtk.vtkMatrix3x3() matrix3.DeepCopy([ math.cos(angle3), 0, -math.sin(angle3), 0, 1, 0, math.sin(angle3), 0, math.cos(angle3) ]) self.transformScrewComposite(matrix3) value = value * -1 transformFid = slicer.mrmlScene.GetFirstNodeByName( 'Transform-%s' % self.currentFidLabel) matrixScrew = transformFid.GetMatrixTransformToParent() newVal = value - self.driveTemp drive1 = matrixScrew.GetElement(0, 1) drive2 = matrixScrew.GetElement(1, 1) drive3 = matrixScrew.GetElement(2, 1) coord1 = drive1 * newVal + matrixScrew.GetElement(0, 3) coord2 = drive2 * newVal + matrixScrew.GetElement(1, 3) coord3 = drive3 * newVal + matrixScrew.GetElement(2, 3) matrixScrew.SetElement(0, 3, coord1) matrixScrew.SetElement(1, 3, coord2) matrixScrew.SetElement(2, 3, coord3) transformFid.SetMatrixTransformToParent(matrixScrew) #transformFid.UpdateScene(slicer.mrmlScene) #self.delayDisplay(transformFid.UpdateScene(slicer.mrmlScene), 2000) self.driveTemp = value self.screwInsert += 1 else: self.timer.stop() self.screwInsert = 0.0 self.driveTemp = 0 '''
def driveScrew(self): if self.screwInsert < int(self.__diameter): value = self.screwInsert #print(value) # attempt to rotate with driving angle3 = math.pi / 180.0 * 72 #((360/2.5)*self.screwInsert) matrix3 = vtk.vtkMatrix3x3() matrix3.DeepCopy([ math.cos(angle3), 0, -math.sin(angle3), 0, 1, 0, math.sin(angle3), 0, math.cos(angle3)]) self.transformScrewComposite(matrix3) value = value*-1 transformFid = slicer.util.getNode('Transform-%s' % self.currentFidLabel) matrixScrew = transformFid.GetMatrixTransformToParent() newVal = value - self.driveTemp print(newVal) drive1 = matrixScrew.GetElement(0,1) drive2 = matrixScrew.GetElement(1,1) drive3 = matrixScrew.GetElement(2,1) coord1 = drive1 * newVal + matrixScrew.GetElement(0,3) coord2 = drive2 * newVal + matrixScrew.GetElement(1,3) coord3 = drive3 * newVal + matrixScrew.GetElement(2,3) matrixScrew.SetElement(0,3,coord1) matrixScrew.SetElement(1,3,coord2) matrixScrew.SetElement(2,3,coord3) transformFid.SetMatrixTransformToParent(matrixScrew) #transformFid.UpdateScene(slicer.mrmlScene) #self.delayDisplay(transformFid.UpdateScene(slicer.mrmlScene), 2000) self.driveTemp = value self.screwInsert += 1 else: self.timer.stop() self.screwInsert = 0.0 self.driveTemp = 0 '''
def transformSlider2ValueChanged(self, value): print(value) newValue = value - self.valueTemp2 angle2 = math.pi / 180.0 * newValue * -1 # Match screw direction matrix2 = vtk.vtkMatrix3x3() matrix2.DeepCopy([ math.cos(angle2), -math.sin(angle2), 0, math.sin(angle2), math.cos(angle2), 0, 0, 0, 1]) self.transformScrewComposite(matrix2) self.valueTemp2 = value temp = self.screwList[self.currentFidIndex] temp[5] = str(value) self.screwList[self.currentFidIndex] = temp print self.screwList
def transformSlider2ValueChanged(self, value): logging.debug("Transform slider 2 changed: {0}".format(value)) newValue = value - self.valueTemp2 angle2 = math.pi / 180.0 * newValue * -1 # Match screw direction matrix2 = vtk.vtkMatrix3x3() matrix2.DeepCopy([ math.cos(angle2), -math.sin(angle2), 0, math.sin(angle2), math.cos(angle2), 0, 0, 0, 1]) self.transformScrewComposite(matrix2) self.valueTemp2 = value temp = self.screwList[self.currentFidIndex] temp[5] = str(value) self.screwList[self.currentFidIndex] = temp logging.debug("Screw list: {0}".format(self.screwList))
def sampleVolumeParameters(self): """Calculate the dictionary of substitutions for the current state of the volume node in a form for substitution into the sampleVolume shader function TODO: this would probably be better as uniforms, but that requires doing a lot of parsing and data management in C++ """ rasToIJK = vtk.vtkMatrix4x4() self.node.GetRASToIJKMatrix(rasToIJK) transformNode = self.node.GetParentTransformNode() if transformNode: if transformNode.IsTransformToWorldLinear(): rasToRAS = vtk.vtkMatrix4x4() transformNode.GetMatrixTransformToWorld(rasToRAS) rasToRAS.Invert() rasToRAS.Multiply4x4(rasToIJK, rasToRAS, rasToIJK) else: error.warn('Cannot handle nonlinear transforms') # dimensions are number of pixels in (row, column, slice) # which maps to 0-1 space of S, T, P dimensions = self.node.GetImageData().GetDimensions() ijkToSTP = vtk.vtkMatrix4x4() ijkToSTP.Identity() for diagonal in range(3): ijkToSTP.SetElement(diagonal,diagonal, 1./dimensions[diagonal]) rasToSTP = vtk.vtkMatrix4x4() ijkToSTP.Multiply4x4(ijkToSTP, rasToIJK, rasToSTP) parameters = {} rows = ('rasToS', 'rasToT', 'rasToP') for row in range(3): rowKey = rows[row] parameters[rowKey] = "" for col in range(4): element = rasToSTP.GetElement(row,col) parameters[rowKey] += "%f," % element parameters[rowKey] = parameters[rowKey][:-1] # clear trailing comma # since texture is 0-1, take into account both pixel spacing # and dimension as layed out in memory so that the normals # is calculated in a uniform space spacings = self.node.GetSpacing() parameters['mmToS'] = spacings[0] / dimensions[0] parameters['mmToT'] = spacings[1] / dimensions[1] parameters['mmToP'] = spacings[2] / dimensions[2] # the inverse transpose of the upper 3x3 of the stpToRAS matrix, # which is the transpose of the upper 3x3 of the rasTSTP matrix normalSTPToRAS = vtk.vtkMatrix3x3(); for row in range(3): for column in range(3): normalSTPToRAS.SetElement(row,column, rasToSTP.GetElement(row,column)); normalSTPToRAS.Transpose() parameters['normalSTPToRAS'] = '' for column in range(3): for row in range(3): # write in column-major order for glsl mat3 constructor parameters['normalSTPToRAS'] += "%f," % normalSTPToRAS.GetElement(row,column) parameters['normalSTPToRAS'] = parameters['normalSTPToRAS'][:-1] # clear trailing comma return parameters
def getPlaneIntersectionPoint(self, axialNode, ortho1Node, ortho2Node): # Compute the center of rotation (common intersection point of the three planes) # http://mathworld.wolfram.com/Plane-PlaneIntersection.html #axialNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed') #ortho1Node = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeYellow') #ortho2Node = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeGreen') axialSliceToRas = axialNode.GetSliceToRAS() n1 = [axialSliceToRas.GetElement(0,2),axialSliceToRas.GetElement(1,2),axialSliceToRas.GetElement(2,2)] x1 = [axialSliceToRas.GetElement(0,3),axialSliceToRas.GetElement(1,3),axialSliceToRas.GetElement(2,3)] ortho1SliceToRas = ortho1Node.GetSliceToRAS() n2 = [ortho1SliceToRas.GetElement(0,2),ortho1SliceToRas.GetElement(1,2),ortho1SliceToRas.GetElement(2,2)] x2 = [ortho1SliceToRas.GetElement(0,3),ortho1SliceToRas.GetElement(1,3),ortho1SliceToRas.GetElement(2,3)] ortho2SliceToRas = ortho2Node.GetSliceToRAS() n3 = [ortho2SliceToRas.GetElement(0,2),ortho2SliceToRas.GetElement(1,2),ortho2SliceToRas.GetElement(2,2)] x3 = [ortho2SliceToRas.GetElement(0,3),ortho2SliceToRas.GetElement(1,3),ortho2SliceToRas.GetElement(2,3)] # Computed intersection point of all planes x = [0,0,0] n2_xp_n3 = [0,0,0] x1_dp_n1 = vtk.vtkMath.Dot(x1,n1) vtk.vtkMath.Cross(n2,n3,n2_xp_n3) vtk.vtkMath.MultiplyScalar(n2_xp_n3, x1_dp_n1) vtk.vtkMath.Add(x,n2_xp_n3,x) n3_xp_n1 = [0,0,0] x2_dp_n2 = vtk.vtkMath.Dot(x2,n2) vtk.vtkMath.Cross(n3,n1,n3_xp_n1) vtk.vtkMath.MultiplyScalar(n3_xp_n1, x2_dp_n2) vtk.vtkMath.Add(x,n3_xp_n1,x) n1_xp_n2 = [0,0,0] x3_dp_n3 = vtk.vtkMath.Dot(x3,n3) vtk.vtkMath.Cross(n1,n2,n1_xp_n2) vtk.vtkMath.MultiplyScalar(n1_xp_n2, x3_dp_n3) vtk.vtkMath.Add(x,n1_xp_n2,x) normalMatrix = vtk.vtkMatrix3x3() normalMatrix.SetElement(0,0,n1[0]) normalMatrix.SetElement(1,0,n1[1]) normalMatrix.SetElement(2,0,n1[2]) normalMatrix.SetElement(0,1,n2[0]) normalMatrix.SetElement(1,1,n2[1]) normalMatrix.SetElement(2,1,n2[2]) normalMatrix.SetElement(0,2,n3[0]) normalMatrix.SetElement(1,2,n3[1]) normalMatrix.SetElement(2,2,n3[2]) normalMatrixDeterminant = normalMatrix.Determinant() if abs(normalMatrixDeterminant)>0.01: # there is an intersection point vtk.vtkMath.MultiplyScalar(x, 1/normalMatrixDeterminant) else: # no intersection point can be determined, use just the position of the axial slice x = x1 return x
def getPlaneIntersectionPoint(axialNode, ortho1Node, ortho2Node): """ Compute the center of rotation (common intersection point of the three planes) http://mathworld.wolfram.com/Plane-PlaneIntersection.html Copied from ValveViewLogic to remove dependency on SlicerHeart extension. """ axialSliceToRas = axialNode.GetSliceToRAS() n1 = [ axialSliceToRas.GetElement(0, 2), axialSliceToRas.GetElement(1, 2), axialSliceToRas.GetElement(2, 2) ] x1 = [ axialSliceToRas.GetElement(0, 3), axialSliceToRas.GetElement(1, 3), axialSliceToRas.GetElement(2, 3) ] ortho1SliceToRas = ortho1Node.GetSliceToRAS() n2 = [ ortho1SliceToRas.GetElement(0, 2), ortho1SliceToRas.GetElement(1, 2), ortho1SliceToRas.GetElement(2, 2) ] x2 = [ ortho1SliceToRas.GetElement(0, 3), ortho1SliceToRas.GetElement(1, 3), ortho1SliceToRas.GetElement(2, 3) ] ortho2SliceToRas = ortho2Node.GetSliceToRAS() n3 = [ ortho2SliceToRas.GetElement(0, 2), ortho2SliceToRas.GetElement(1, 2), ortho2SliceToRas.GetElement(2, 2) ] x3 = [ ortho2SliceToRas.GetElement(0, 3), ortho2SliceToRas.GetElement(1, 3), ortho2SliceToRas.GetElement(2, 3) ] # Computed intersection point of all planes x = [0, 0, 0] n2_xp_n3 = [0, 0, 0] x1_dp_n1 = vtk.vtkMath.Dot(x1, n1) vtk.vtkMath.Cross(n2, n3, n2_xp_n3) vtk.vtkMath.MultiplyScalar(n2_xp_n3, x1_dp_n1) vtk.vtkMath.Add(x, n2_xp_n3, x) n3_xp_n1 = [0, 0, 0] x2_dp_n2 = vtk.vtkMath.Dot(x2, n2) vtk.vtkMath.Cross(n3, n1, n3_xp_n1) vtk.vtkMath.MultiplyScalar(n3_xp_n1, x2_dp_n2) vtk.vtkMath.Add(x, n3_xp_n1, x) n1_xp_n2 = [0, 0, 0] x3_dp_n3 = vtk.vtkMath.Dot(x3, n3) vtk.vtkMath.Cross(n1, n2, n1_xp_n2) vtk.vtkMath.MultiplyScalar(n1_xp_n2, x3_dp_n3) vtk.vtkMath.Add(x, n1_xp_n2, x) normalMatrix = vtk.vtkMatrix3x3() normalMatrix.SetElement(0, 0, n1[0]) normalMatrix.SetElement(1, 0, n1[1]) normalMatrix.SetElement(2, 0, n1[2]) normalMatrix.SetElement(0, 1, n2[0]) normalMatrix.SetElement(1, 1, n2[1]) normalMatrix.SetElement(2, 1, n2[2]) normalMatrix.SetElement(0, 2, n3[0]) normalMatrix.SetElement(1, 2, n3[1]) normalMatrix.SetElement(2, 2, n3[2]) normalMatrixDeterminant = normalMatrix.Determinant() if abs(normalMatrixDeterminant) > 0.01: # there is an intersection point vtk.vtkMath.MultiplyScalar(x, 1 / normalMatrixDeterminant) else: # no intersection point can be determined, use just the position of the axial slice x = x1 return x
def getPlaneIntersectionPoint(self, axialNode, ortho1Node, ortho2Node): # Compute the center of rotation (common intersection point of the three planes) # http://mathworld.wolfram.com/Plane-PlaneIntersection.html #axialNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed') #ortho1Node = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeYellow') #ortho2Node = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeGreen') axialSliceToRas = axialNode.GetSliceToRAS() n1 = [ axialSliceToRas.GetElement(0, 2), axialSliceToRas.GetElement(1, 2), axialSliceToRas.GetElement(2, 2) ] x1 = [ axialSliceToRas.GetElement(0, 3), axialSliceToRas.GetElement(1, 3), axialSliceToRas.GetElement(2, 3) ] ortho1SliceToRas = ortho1Node.GetSliceToRAS() n2 = [ ortho1SliceToRas.GetElement(0, 2), ortho1SliceToRas.GetElement(1, 2), ortho1SliceToRas.GetElement(2, 2) ] x2 = [ ortho1SliceToRas.GetElement(0, 3), ortho1SliceToRas.GetElement(1, 3), ortho1SliceToRas.GetElement(2, 3) ] ortho2SliceToRas = ortho2Node.GetSliceToRAS() n3 = [ ortho2SliceToRas.GetElement(0, 2), ortho2SliceToRas.GetElement(1, 2), ortho2SliceToRas.GetElement(2, 2) ] x3 = [ ortho2SliceToRas.GetElement(0, 3), ortho2SliceToRas.GetElement(1, 3), ortho2SliceToRas.GetElement(2, 3) ] # Computed intersection point of all planes x = [0, 0, 0] n2_xp_n3 = [0, 0, 0] x1_dp_n1 = vtk.vtkMath.Dot(x1, n1) vtk.vtkMath.Cross(n2, n3, n2_xp_n3) vtk.vtkMath.MultiplyScalar(n2_xp_n3, x1_dp_n1) vtk.vtkMath.Add(x, n2_xp_n3, x) n3_xp_n1 = [0, 0, 0] x2_dp_n2 = vtk.vtkMath.Dot(x2, n2) vtk.vtkMath.Cross(n3, n1, n3_xp_n1) vtk.vtkMath.MultiplyScalar(n3_xp_n1, x2_dp_n2) vtk.vtkMath.Add(x, n3_xp_n1, x) n1_xp_n2 = [0, 0, 0] x3_dp_n3 = vtk.vtkMath.Dot(x3, n3) vtk.vtkMath.Cross(n1, n2, n1_xp_n2) vtk.vtkMath.MultiplyScalar(n1_xp_n2, x3_dp_n3) vtk.vtkMath.Add(x, n1_xp_n2, x) normalMatrix = vtk.vtkMatrix3x3() normalMatrix.SetElement(0, 0, n1[0]) normalMatrix.SetElement(1, 0, n1[1]) normalMatrix.SetElement(2, 0, n1[2]) normalMatrix.SetElement(0, 1, n2[0]) normalMatrix.SetElement(1, 1, n2[1]) normalMatrix.SetElement(2, 1, n2[2]) normalMatrix.SetElement(0, 2, n3[0]) normalMatrix.SetElement(1, 2, n3[1]) normalMatrix.SetElement(2, 2, n3[2]) normalMatrixDeterminant = normalMatrix.Determinant() if abs(normalMatrixDeterminant) > 0.01: # there is an intersection point vtk.vtkMath.MultiplyScalar(x, 1 / normalMatrixDeterminant) else: # no intersection point can be determined, use just the position of the axial slice x = x1 return x
def sampleVolumeParameters(self): """Calculate the dictionary of substitutions for the current state of the volume node in a form for substitution into the sampleVolume shader function TODO: this would probably be better as uniforms, but that requires doing a lot of parsing and data management in C++ """ rasToIJK = vtk.vtkMatrix4x4() self.node.GetRASToIJKMatrix(rasToIJK) transformNode = self.node.GetParentTransformNode() if transformNode: if transformNode.IsTransformToWorldLinear(): rasToRAS = vtk.vtkMatrix4x4() transformNode.GetMatrixTransformToWorld(rasToRAS) rasToRAS.Invert() rasToRAS.Multiply4x4(rasToIJK, rasToRAS, rasToIJK) else: error.warn('Cannot handle nonlinear transforms') # dimensions are number of pixels in (row, column, slice) # which maps to 0-1 space of S, T, P dimensions = self.node.GetImageData().GetDimensions() ijkToSTP = vtk.vtkMatrix4x4() ijkToSTP.Identity() for diagonal in range(3): ijkToSTP.SetElement(diagonal, diagonal, 1. / dimensions[diagonal]) rasToSTP = vtk.vtkMatrix4x4() ijkToSTP.Multiply4x4(ijkToSTP, rasToIJK, rasToSTP) parameters = {} rows = ('rasToS', 'rasToT', 'rasToP') for row in range(3): rowKey = rows[row] parameters[rowKey] = "" for col in range(4): element = rasToSTP.GetElement(row, col) parameters[rowKey] += "%f," % element parameters[rowKey] = parameters[rowKey][: -1] # clear trailing comma # since texture is 0-1, take into account both pixel spacing # and dimension as layed out in memory so that the normals # is calculated in a uniform space spacings = self.node.GetSpacing() parameters['mmToS'] = spacings[0] / dimensions[0] parameters['mmToT'] = spacings[1] / dimensions[1] parameters['mmToP'] = spacings[2] / dimensions[2] # the inverse transpose of the upper 3x3 of the stpToRAS matrix, # which is the transpose of the upper 3x3 of the rasTSTP matrix normalSTPToRAS = vtk.vtkMatrix3x3() for row in range(3): for column in range(3): normalSTPToRAS.SetElement(row, column, rasToSTP.GetElement(row, column)) normalSTPToRAS.Transpose() parameters['normalSTPToRAS'] = '' for column in range(3): for row in range(3): # write in column-major order for glsl mat3 constructor parameters[ 'normalSTPToRAS'] += "%f," % normalSTPToRAS.GetElement( row, column) parameters['normalSTPToRAS'] = parameters[ 'normalSTPToRAS'][:-1] # clear trailing comma return parameters