def testStorageValue(self, logic): print " Test storage of Values: " bool = True arrayValue = vtk.vtkDoubleArray() arrayMask = vtk.vtkDoubleArray() for i in range(0, 1000, 2): arrayValue.InsertNextValue(i) arrayValue.InsertNextValue(i) arrayMask.InsertNextValue(0.0) arrayMask.InsertNextValue(0.0) listOfRandomNumber = list() del listOfRandomNumber[:] for i in range(0, 250): listOfRandomNumber.append(randint(0, 998)) listOfRandomNumber = set(listOfRandomNumber) listOfRandomNumber = sorted(listOfRandomNumber) for index in listOfRandomNumber: arrayMask.SetValue(index, 1.0) array = logic.defineArray(arrayValue, arrayMask) array = sorted(array) a = 0 for i in listOfRandomNumber: if arrayValue.GetValue(i) != array[a]: bool = False print " Failed", a, array[a], i, arrayValue.GetValue(i) break a += 1 if bool: print " Passed"
def testStorageValue(self): logic = MeshStatisticsLogic() print " Test storage of Values: " arrayValue = vtk.vtkDoubleArray() arrayMask = vtk.vtkDoubleArray() for i in range(0, 1000, 2): arrayValue.InsertNextValue(i) arrayValue.InsertNextValue(i) arrayMask.InsertNextValue(0.0) arrayMask.InsertNextValue(0.0) listOfRandomNumber = list() del listOfRandomNumber[:] for i in range(0, 250): listOfRandomNumber.append(randint(0, 998)) listOfRandomNumber = list(set(listOfRandomNumber)) listOfRandomNumber = sorted(listOfRandomNumber) for index in listOfRandomNumber: arrayMask.SetValue(index, 1.0) bool, array = logic.defineArray(arrayValue, arrayMask) array = sorted(array) a = 0 for i in listOfRandomNumber: if arrayValue.GetValue(i) != array[a]: print " Failed", a, array[a], i, arrayValue.GetValue(i) return False a += 1 print " Passed" return True
def testStorageValue(self): logic = MeshStatisticsLogic() print ' Test storage of Values: ' arrayValue = vtk.vtkDoubleArray() arrayMask = vtk.vtkDoubleArray() for i in range(0, 1000, 2): arrayValue.InsertNextValue(i) arrayValue.InsertNextValue(i) arrayMask.InsertNextValue(0.0) arrayMask.InsertNextValue(0.0) listOfRandomNumber = list() del listOfRandomNumber[:] for i in range(0, 250): listOfRandomNumber.append(randint(0, 998)) listOfRandomNumber = list(set(listOfRandomNumber)) listOfRandomNumber = sorted(listOfRandomNumber) for index in listOfRandomNumber: arrayMask.SetValue(index, 1.0) bool, array = logic.defineArray(arrayValue, arrayMask) array = sorted(array) a = 0 for i in listOfRandomNumber: if arrayValue.GetValue(i) != array[a]: print ' Failed', a, array[a], i, arrayValue.GetValue(i) return False a += 1 print ' Passed' return True
def defineArrays(self, logic, firstValue, lastValue): arrayValue = vtk.vtkDoubleArray() ROIArray = vtk.vtkDoubleArray() for i in range(firstValue, lastValue): arrayValue.InsertNextValue(i) ROIArray.InsertNextValue(1.0) array = logic.defineArray(arrayValue, ROIArray) return array
def defineArrays(self, logic, firstValue, lastValue): arrayValue = vtk.vtkDoubleArray() ROIArray = vtk.vtkDoubleArray() for i in range(firstValue, lastValue): arrayValue.InsertNextValue(i) ROIArray.InsertNextValue(1.0) bool, array = logic.defineArray(arrayValue, ROIArray) if bool: return array return False
def populateChart(self): # strip elements from 2nd 3d view # and add our own chart renderer to it self.aModeImageNode = slicer.util.getNode('Image_NeedleTip') if self.aModeImageNode is None: logging.debug( "Cannot locate Image_NeedleTip, can't visualize chart") return self.imageData = self.aModeImageNode.GetImageData() if not self.table is None: # We already have created all of the things, don't recreate self.view.GetInteractor().Initialize() self.chart.RecalculateBounds() return self.table = vtk.vtkTable() self.chart = vtk.vtkChartXY() self.line = self.chart.AddPlot(0) self.view = vtk.vtkContextView() self.signalArray = vtk.vtkDoubleArray() self.signalArray.SetName("RF Signal") self.distanceArray = vtk.vtkDoubleArray() self.distanceArray.SetName("Distance (mm)") self.imageDimensions = self.imageData.GetDimensions() self.signalArray.SetNumberOfTuples(self.imageDimensions[0]) self.distanceArray.SetNumberOfTuples(self.imageDimensions[0]) self.table.AddColumn(self.distanceArray) self.table.AddColumn(self.signalArray) self.line = self.chart.AddPlot(0) self.line.SetInputData(self.table, 0, 1) self.line.SetColor(0, 255, 0, 255) self.line.SetWidth(1.0) inc = 1000 * 1480 / ( 2 * 420e6 ) # distance in mm. The delay distance is added to the increments. (2e-6*1480/2) + distanceDelay = 1000 * 2e-6 * 1480 / 2 for i in range(self.imageDimensions[0]): self.distanceArray.SetComponent(i, 0, distanceDelay + inc * i) self.view.GetRenderer().SetBackground(1.0, 1.0, 1.0) self.view.GetRenderWindow().SetSize(400, 300) # self.contextScene = vtk.vtkContextScene() # self.contextScene.AddItem(self.chart) # self.contextActor = vtk.vtkContextActor() self.view.GetScene().AddItem(self.chart) self.view.GetRenderWindow().SetMultiSamples(0) # self.layoutManager.threeDWidget(1).threeDView.renderWindow().GetRenderer().GetFirstRenderer().AddActor(self.contextActor) self.view.GetInteractor().Initialize()
def ConvertTextureToPointAttribute(modelNode, textureImageNode): polyData=modelNode.GetPolyData() textureImageFlipVert=vtk.vtkImageFlip() textureImageFlipVert.SetFilteredAxis(1) textureImageFlipVert.SetInputConnection(textureImageNode.GetImageDataConnection()) textureImageFlipVert.Update() textureImageData=textureImageFlipVert.GetOutput() pointData=polyData.GetPointData() tcoords=pointData.GetTCoords() numOfPoints=pointData.GetNumberOfTuples() assert numOfPoints==tcoords.GetNumberOfTuples(), "Number of texture coordinates does not equal number of points" textureSamplingPointsUv=vtk.vtkPoints() textureSamplingPointsUv.SetNumberOfPoints(numOfPoints) for pointIndex in xrange(numOfPoints): uv=tcoords.GetTuple2(pointIndex) textureSamplingPointsUv.SetPoint(pointIndex, uv[0], uv[1], 0) textureSamplingPointDataUv=vtk.vtkPolyData() uvToXyz=vtk.vtkTransform() textureImageDataSpacingSpacing=textureImageData.GetSpacing() textureImageDataSpacingOrigin=textureImageData.GetOrigin() textureImageDataSpacingDimensions=textureImageData.GetDimensions() uvToXyz.Scale(textureImageDataSpacingDimensions[0]/textureImageDataSpacingSpacing[0], textureImageDataSpacingDimensions[1]/textureImageDataSpacingSpacing[1], 1) uvToXyz.Translate(textureImageDataSpacingOrigin) textureSamplingPointDataUv.SetPoints(textureSamplingPointsUv) transformPolyDataToXyz=vtk.vtkTransformPolyDataFilter() transformPolyDataToXyz.SetInputData(textureSamplingPointDataUv) transformPolyDataToXyz.SetTransform(uvToXyz) probeFilter=vtk.vtkProbeFilter() probeFilter.SetInputConnection(transformPolyDataToXyz.GetOutputPort()) probeFilter.SetSourceData(textureImageData) probeFilter.Update() rgbPoints=probeFilter.GetOutput().GetPointData().GetArray('ImageScalars') colorArrayRed=vtk.vtkDoubleArray() colorArrayRed.SetName('ColorRed') colorArrayRed.SetNumberOfTuples(numOfPoints) colorArrayGreen=vtk.vtkDoubleArray() colorArrayGreen.SetName('ColorGreen') colorArrayGreen.SetNumberOfTuples(numOfPoints) colorArrayBlue=vtk.vtkDoubleArray() colorArrayBlue.SetName('ColorBlue') colorArrayBlue.SetNumberOfTuples(numOfPoints) for pointIndex in xrange(numOfPoints): rgb=rgbPoints.GetTuple3(pointIndex) colorArrayRed.SetValue(pointIndex,rgb[0]) colorArrayGreen.SetValue(pointIndex,rgb[1]) colorArrayBlue.SetValue(pointIndex,rgb[2]) colorArrayRed.Modified() colorArrayGreen.Modified() colorArrayBlue.Modified() pointData.AddArray(colorArrayRed) pointData.AddArray(colorArrayGreen) pointData.AddArray(colorArrayBlue) pointData.Modified() polyData.Modified()
def CalculatePlane( self, inPoints, base, dir1, dir2, normal ): # Create arrays for the dataset points2D = vtk.vtkPoints() arrayX = vtk.vtkDoubleArray() arrayX.SetNumberOfComponents( 1 ) arrayX.SetName ( 'X' ) arrayY = vtk.vtkDoubleArray() arrayY.SetNumberOfComponents( 1 ) arrayY.SetName ( 'Y' ) arrayZ = vtk.vtkDoubleArray() arrayZ.SetNumberOfComponents( 1 ) arrayZ.SetName ( 'Z' ) # Add the points to the table for i in range( 0, inPoints.GetNumberOfPoints() ): currPoint = [ 0, 0, 0 ] inPoints.GetPoint( i, currPoint ) arrayX.InsertNextValue( currPoint[ 0 ] ) arrayY.InsertNextValue( currPoint[ 1 ] ) arrayZ.InsertNextValue( currPoint[ 2 ] ) # Create a table for the dataset table = vtk.vtkTable() table.AddColumn( arrayX ) table.AddColumn( arrayY ) table.AddColumn( arrayZ ) # Setting up the PCA pca = vtk.vtkPCAStatistics() pca.SetInputData( vtk.vtkStatisticsAlgorithm.INPUT_DATA, table ) pca.SetColumnStatus( 'X', 1 ) pca.SetColumnStatus( 'Y', 1 ) pca.SetColumnStatus( 'Z', 1 ) pca.RequestSelectedColumns() pca.SetDeriveOption( True ) pca.Update() eigvec = vtk.vtkDoubleArray() pca.GetEigenvectors( eigvec ) eigvec.GetTuple( 0, dir1 ) eigvec.GetTuple( 1, dir2 ) eigvec.GetTuple( 2, normal ) mean = self.CalculateMean( inPoints ) base[0] = mean[0] base[1] = mean[1] base[2] = mean[2]
def importFunction(self): # check if the output container exists mvNode = self.outputSelector.currentNode() #print(mvNode) if mvNode == None: self.__status.text = 'Status: Select output node!' return fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = '' frameFileListAttr = '' dicomTagNameAttr = self.__dicomTag.text dicomTagUnitsAttr = self.__veLabel.text teAttr = self.__te.text trAttr = self.__tr.text faAttr = self.__fa.text # each frame is saved as a separate volume # first filter valid file names and sort alphabetically frames = [] frame0 = None inputDir = self.__fDialog.directory print(inputDir)
def performPostProcessing(self, snrThreshold, distanceMinimumValue, distanceMaximumValue): # Create new vtkPolyData newPoints = vtk.vtkPoints() newVertices = vtk.vtkCellArray() newPolyData = vtk.vtkPolyData() newPolyData.SetPoints(newPoints) newPolyData.SetVerts(newVertices) colorArray = vtk.vtkDoubleArray() colorArray.SetNumberOfComponents(4) colorArray.SetName('Colors') newPolyData.GetPointData().SetScalars(colorArray) # Filter accordingly to the input parameters recordedDataBufferFiltered = [] for idx in range(len(self.recordedDataBuffer)): d = self.recordedDataBuffer[idx][3] snr = self.recordedDataBuffer[idx][4] if (snr > snrThreshold and d < distanceMaximumValue and d > distanceMinimumValue): recordedDataBufferFiltered.append(self.recordedDataBuffer[idx]) self.addPointToPolyData(newPolyData, self.recordedDataBuffer[idx][0:3]) # Update recorded model and buffer self.recordedModelNode.GetPolyData().DeepCopy(newPolyData) self.recordedModelNode.GetPolyData().Modified() self.recordedDataBuffer = recordedDataBufferFiltered
def getArrayFromTable(self, outputTable, arrayName): distanceArray = outputTable.GetTable().GetColumnByName(arrayName) if distanceArray: return distanceArray newArray = vtk.vtkDoubleArray() newArray.SetName(arrayName) outputTable.GetTable().AddColumn(newArray) return newArray
def clearPointsInRecordedModel(self): self.recordedDataBuffer = [] newPoints = vtk.vtkPoints() newVertices = vtk.vtkCellArray() newPolyData = vtk.vtkPolyData() newPolyData.SetPoints(newPoints) newPolyData.SetVerts(newVertices) colorArray = vtk.vtkDoubleArray() colorArray.SetNumberOfComponents(4) colorArray.SetName('Colors') newPolyData.GetPointData().SetScalars(colorArray) self.recordedModelNode.GetPolyData().DeepCopy(newPolyData) self.recordedModelNode.GetPolyData().Modified()
def undoPostProcessing(self): # Create new vtkPolyData newPoints = vtk.vtkPoints() newVertices = vtk.vtkCellArray() newPolyData = vtk.vtkPolyData() newPolyData.SetPoints(newPoints) newPolyData.SetVerts(newVertices) colorArray = vtk.vtkDoubleArray() colorArray.SetNumberOfComponents(4) colorArray.SetName('Colors') newPolyData.GetPointData().SetScalars(colorArray) # Filter accordingly to the input parameters recordedDataBufferFiltered = [] for idx in range(len(self.recordedDataBufferDefault)): self.addPointToPolyData(newPolyData, self.recordedDataBufferDefault[idx][0:3]) # Update recorded model and buffer self.recordedModelNode.GetPolyData().DeepCopy(newPolyData) self.recordedModelNode.GetPolyData().Modified() self.recordedDataBuffer = self.recordedDataBufferDefault
def onImportButtonClicked(self): # check if the output container exists mvNode = self.__mvSelector.currentNode() if mvNode == None: self.__status.text = 'Status: Select output node!' return modeIdx = self.__modeSelector.currentIndex processingMode = self.__processingModes[modeIdx] # There are two options: # 1. DICOM series in a directory, with either predefined or custom parse tag # 2. Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() if modeIdx < len(self.__processingModes)-1: # DICOM series # get logic logic = slicer.modules.multivolumeexplorer.logic() # create a clean temporary directory tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') if not os.path.exists(tmpDir): os.mkdir(tmpDir) tmpDir = tmpDir+'/MultiVolumeImporter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) else: # clean it up print("tmpDir: %s" % tmpDir) oldFileNames = os.listdir(tmpDir) for f in oldFileNames: print("%s will be unlinked" % f) os.unlink(tmpDir+'/'+f) nFrames = logic.ProcessDICOMSeries(self.__fDialog.directory, tmpDir, self.__dicomTag.text, volumeLabels) self.__status.text = 'Series processed OK, '+str(nFrames)+' volumes identified' print("Location of files: %s" % tmpDir) for f in os.listdir(tmpDir): if not f.startswith('.'): fileNames.append(f) fileNames.sort() frameFolder = tmpDir else: # each frame is saved as a separate volume for f in os.listdir(self.__fDialog.directory): if not f.startswith('.'): fileNames.append(f) fileNames.sort() frameFolder = self.__fDialog.directory nFrames = len(fileNames) volumeLabels.SetNumberOfTuples(nFrames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(nFrames) for i in range(len(fileNames)): frameId = self.__veInitial.value+self.__veStep.value*i volumeLabels.SetComponent(i, 0, frameId) # read the first frame to get the extent for DWI node fullName = frameFolder+'/'+fileNames[0] volumesLogic = slicer.modules.volumes.logic() frame = volumesLogic.AddArchetypeVolume(fullName, processingMode[3]+' Frame 0', 0) frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1]*frameExtent[3]*frameExtent[5] nFrames = len(fileNames) mvImage = vtk.vtkImageData() mvImage.SetExtent(frameExtent) mvImage.SetNumberOfScalarComponents(nFrames) mvImage.AllocateScalars() mvImageArray = vtk.util.numpy_support.vtk_to_numpy(mvImage.GetPointData().GetScalars()) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) self.annihilateScalarNode(frame) for frameId in range(0,nFrames): fullName = frameFolder+'/'+fileNames[frameId] print("Processing frame %d: %s" % (frameId, fullName)) frame = volumesLogic.AddArchetypeVolume(fullName, 'Frame'+str(frameId), 0) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray self.annihilateScalarNode(frame) mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) slicer.mrmlScene.AddNode(mvNode) mvNode.SetReferenceCount(mvNode.GetReferenceCount()-1) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) print("MultiVolume node setup complete !") Helper.SetBgFgVolumes(mvNode.GetID(),None)
def onImportButtonClicked(self): # check if the output container exists mvNode = self.__mvSelector.currentNode() if mvNode == None: self.__status.text = 'Status: Select output node!' return # Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = '' frameFileListAttr = '' dicomTagNameAttr = self.__dicomTag.text dicomTagUnitsAttr = self.__veLabel.text teAttr = self.__te.text trAttr = self.__tr.text faAttr = self.__fa.text # each frame is saved as a separate volume for f in os.listdir(self.__fDialog.directory): if not f.startswith('.'): fileNames.append(f) frameFileListAttr += f + ',' fileNames.sort() frameFileListAttr = frameFileListAttr[:-1] frameFolder = self.__fDialog.directory nFrames = len(fileNames) volumeLabels.SetNumberOfTuples(nFrames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(nFrames) for i in range(len(fileNames)): frameId = self.__veInitial.value + self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + ',' frameLabelsAttr = frameLabelsAttr[:-1] # read the first frame to get the extent fullName = frameFolder + '/' + fileNames[0] volumesLogic = slicer.modules.volumes.logic() frame = self.readFrame(fullName) frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1] * frameExtent[3] * frameExtent[5] nFrames = len(fileNames) mvImage = vtk.vtkImageData() mvImage.SetExtent(frameExtent) mvImage.SetNumberOfScalarComponents(nFrames) mvImage.AllocateScalars() mvImageArray = vtk.util.numpy_support.vtk_to_numpy( mvImage.GetPointData().GetScalars()) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) for frameId in range(0, nFrames): fullName = frameFolder + '/' + fileNames[frameId] print("Processing frame %d: %s" % (frameId, fullName)) frame = self.readFrame(fullName) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy( frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', dicomTagNameAttr) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', dicomTagUnitsAttr) if dicomTagNameAttr == 'TriggerTime' or dicomTagNameAttr == 'AcquisitionTime': if teTag != '': mvNode.SetAttribute('MultiVolume.DICOM.EchoTime', teTag) if trTag != '': mvNode.SetAttribute('MultiVolume.DICOM.RepetitionTime', trTag) if faTag != '': mvNode.SetAttribute('MultiVolume.DICOM.FlipAngle', faTag) mvNode.SetName(str(nFrames) + ' frames MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(), None)
def read4DNIfTI(self, mvNode, fileName): """Try to read a 4D nifti file as a multivolume""" print('trying to read %s' % fileName) # use the vtk reader which seems to handle most nifti variants well reader = vtk.vtkNIFTIImageReader() reader.SetFileName(fileName) reader.SetTimeAsVector(True) reader.Update() header = reader.GetNIFTIHeader() qFormMatrix = reader.GetQFormMatrix() if not qFormMatrix: print('Warning: %s does not have a QFormMatrix - using Identity') qFormMatrix = vtk.vtkMatrix4x4() spacing = reader.GetOutputDataObject(0).GetSpacing() timeSpacing = reader.GetTimeSpacing() nFrames = reader.GetTimeDimension() if header.GetIntentCode() != header.IntentTimeSeries: intentName = header.GetIntentName() if not intentName: intentName = 'Nothing' print( f'Warning: {fileName} does not have TimeSeries intent, instead it has \"{intentName}\"' ) print('Trying to read as TimeSeries anyway') units = header.GetXYZTUnits() # try to account for some of the unit options # (Note: no test data available but we hope these are right) if units & header.UnitsMSec == header.UnitsMSec: timeSpacing /= 1000. if units & header.UnitsUSec == header.UnitsUSec: timeSpacing /= 1000. / 1000. spaceScaling = 1. if units & header.UnitsMeter == header.UnitsMeter: spaceScaling *= 1000. if units & header.UnitsMicron == header.UnitsMicron: spaceScaling /= 1000. spacing = [e * spaceScaling for e in spacing] # create frame labels using the timing info from the file # but use the advanced info so user can specify offset and scale volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(nFrames) frameLabelsAttr = '' for i in range(nFrames): frameId = self.__veInitial.value + timeSpacing * self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + ',' frameLabelsAttr = frameLabelsAttr[:-1] # create the display node mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() # spacing and origin are in the ijkToRAS, so clear them from image data imageChangeInformation = vtk.vtkImageChangeInformation() imageChangeInformation.SetInputConnection(reader.GetOutputPort()) imageChangeInformation.SetOutputSpacing(1, 1, 1) imageChangeInformation.SetOutputOrigin(0, 0, 0) imageChangeInformation.Update() # QForm includes directions and origin, but not spacing so add that # here by multiplying by a diagonal matrix with the spacing scaleMatrix = vtk.vtkMatrix4x4() for diag in range(3): scaleMatrix.SetElement(diag, diag, spacing[diag]) ijkToRAS = vtk.vtkMatrix4x4() ijkToRAS.DeepCopy(qFormMatrix) vtk.vtkMatrix4x4.Multiply4x4(ijkToRAS, scaleMatrix, ijkToRAS) mvNode.SetIJKToRASMatrix(ijkToRAS) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData( imageChangeInformation.GetOutputDataObject(0)) mvNode.SetNumberOfFrames(nFrames) # set the labels and other attributes, then display the volume mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', '') mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', '') mvNode.SetName(str(nFrames) + ' frames NIfTI MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(), None)
def __init__(self): # Member variables self.outputLabels = None self.recordedDataBuffer = [] self.record = False self.reset = False self.outputObserverTag = -1 self.rigidBodyToTrackerTransformNode = None self.measurementToMeasurerTransformNode = None self.parametersToMeasurerTransformNode = None self.plus = None self.m = vtk.vtkMatrix4x4() self.direction = -1 self.ras = [0, 0, 0, 1] self.d = 0.0 self.snr = 0 self.total = 0 self.LABEL_UPDATE_RATE = 10 self.labelUpdateCount = 0 self.snrThreshold = 40 self.distanceMaximumValue = 1000.0 self.distanceMinimumValue = 0.0 self.lensMaxDistance = 0.0 self.lensMinDistance = 0.0 self.normalizingConstant = 0.0 self.min = -1000.0 self.addColours = True import Viewpoint # Viewpoint self.viewpointLogic = Viewpoint.ViewpointLogic() self.stopWatch = None # StopWatch # Create style sheets self.errorStyleSheet = "QLabel { color : #FF0000; \ font: bold 14px}" self.defaultStyleSheet = "QLabel { color : #000000; \ font: bold 14px}" # Create rainbow colour table self.colorTable=slicer.vtkMRMLColorTableNode() self.colorTable.SetTypeToRainbow () # Add MeasurementPoint self.measurementPointMarkupsFiducialNode = slicer.util.getNode('MeasurementPoint') if not self.measurementPointMarkupsFiducialNode: self.measurementPointMarkupsFiducialNode = slicer.vtkMRMLMarkupsFiducialNode() self.measurementPointMarkupsFiducialNode.SetName('MeasurementPoint') self.measurementPointMarkupsFiducialNode.AddFiducial(0, 0, 0) self.measurementPointMarkupsFiducialNode.SetNthFiducialLabel(0, '') slicer.mrmlScene.AddNode(self.measurementPointMarkupsFiducialNode) self.measurementPointMarkupsFiducialNode.GetDisplayNode().SetGlyphScale(2.0) self.measurementPointMarkupsFiducialNode.GetDisplayNode().SetGlyphType(13) # Sphere3D self.measurementPointMarkupsFiducialNode.GetDisplayNode().SetSelectedColor(1, 0, 0) # Add RecordedModel self.recordedModelNode = slicer.util.getNode('RecordedModel') if not self.recordedModelNode: recordedPoints = vtk.vtkPoints() recordedVertices = vtk.vtkCellArray() recordedPolyData = vtk.vtkPolyData() recordedPolyData.SetPoints(recordedPoints) recordedPolyData.SetVerts(recordedVertices) self.recordedModelNode = self.addModelToScene(recordedPolyData, "RecordedModel") self.recordedModelNode.GetModelDisplayNode().SetPointSize(3) # Set up coloured scalars colorArray = vtk.vtkDoubleArray() colorArray.SetNumberOfComponents(4) colorArray.SetName('Colors') self.recordedModelNode.GetPolyData().GetPointData().SetScalars(colorArray) # Create share directory self.pathToCreatedSaveDir = self.createShareDirectory() # Post-Processing default (for undo) self.recordedDataBufferDefault = []
def onImportButtonClicked(self): # check if the output container exists mvNode = self.__mvSelector.currentNode() if mvNode == None: self.__status.text = "Status: Select output node!" return print("Before processing: " + mvNode.GetID()) # Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = "" frameFileListAttr = "" dicomTagNameAttr = self.__dicomTag.text dicomTagUnitsAttr = self.__veLabel.text teAttr = self.__te.text trAttr = self.__tr.text faAttr = self.__fa.text # each frame is saved as a separate volume for f in os.listdir(self.__fDialog.directory): if not f.startswith("."): fileNames.append(f) frameFileListAttr += f + "," fileNames.sort() frameFileListAttr = frameFileListAttr[:-1] frameFolder = self.__fDialog.directory nFrames = len(fileNames) volumeLabels.SetNumberOfTuples(nFrames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(nFrames) for i in range(len(fileNames)): frameId = self.__veInitial.value + self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + "," frameLabelsAttr = frameLabelsAttr[:-1] # read the first frame to get the extent fullName = frameFolder + "/" + fileNames[0] volumesLogic = slicer.modules.volumes.logic() frame = self.readFrame(fullName) frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1] * frameExtent[3] * frameExtent[5] nFrames = len(fileNames) mvImage = vtk.vtkImageData() mvImage.SetExtent(frameExtent) mvImage.SetNumberOfScalarComponents(nFrames) mvImage.AllocateScalars() mvImageArray = vtk.util.numpy_support.vtk_to_numpy(mvImage.GetPointData().GetScalars()) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) for frameId in range(0, nFrames): fullName = frameFolder + "/" + fileNames[frameId] print("Processing frame %d: %s" % (frameId, fullName)) frame = self.readFrame(fullName) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLMultiVolumeDisplayNode") mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute("MultiVolume.FrameFileList", frameFileListAttr) mvNode.SetAttribute("MultiVolume.FrameLabels", frameLabelsAttr) mvNode.SetAttribute("MultiVolume.NumberOfFrames", str(nFrames)) mvNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagName", dicomTagNameAttr) mvNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagUnits", dicomTagUnitsAttr) if dicomTagNameAttr == "TriggerTime" or dicomTagNameAttr == "AcquisitionTime": if teTag != "": mvNode.SetAttribute("MultiVolume.DICOM.EchoTime", teTag) if trTag != "": mvNode.SetAttribute("MultiVolume.DICOM.RepetitionTime", trTag) if faTag != "": mvNode.SetAttribute("MultiVolume.DICOM.FlipAngle", faTag) print("MultiVolume node setup complete !") Helper.SetBgFgVolumes(mvNode.GetID(), None) print("After processing: " + mvNode.GetID())
def onImportButtonClicked(self): # check if the output container exists mvNode = self.__mvSelector.currentNode() if mvNode == None: self.__status.text = 'Status: Select output node!' return # Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = '' frameFileListAttr = '' dicomTagNameAttr = self.__dicomTag.text dicomTagUnitsAttr = self.__veLabel.text teAttr = self.__te.text trAttr = self.__tr.text faAttr = self.__fa.text # each frame is saved as a separate volume # first filter valid file names and sort alphabetically frames = [] frame0 = None inputDir = self.__fDialog.directory for f in os.listdir(inputDir): if not f.startswith('.'): fileName = inputDir + '/' + f fileNames.append(fileName) self.humanSort(fileNames) # check for nifti file that may be 4D as special case niftiFiles = [] for fileName in fileNames: if fileName.lower().endswith( '.nii.gz') or fileName.lower().endswith('.nii'): niftiFiles.append(fileName) if len(niftiFiles) == 1: self.read4DNIfTI(mvNode, niftiFiles[0]) return # not 4D nifti, so keep trying for fileName in fileNames: (s, f) = self.readFrame(fileName) if s: if not frame0: frame0 = f frame0Image = frame0.GetImageData() frame0Extent = frame0Image.GetExtent() else: frameImage = f.GetImageData() frameExtent = frameImage.GetExtent() if frameExtent[1] != frame0Extent[1] or frameExtent[ 3] != frame0Extent[3] or frameExtent[ 5] != frame0Extent[5]: continue frames.append(f) nFrames = len(frames) print('Successfully read ' + str(nFrames) + ' frames') if nFrames == 1: print('Single frame dataset - not reading as multivolume!') return # convert seconds data to milliseconds, which is expected by pkModeling.cxx line 81 if dicomTagUnitsAttr == 's': frameIdMultiplier = 1000.0 dicomTagUnitsAttr = 'ms' else: frameIdMultiplier = 1.0 volumeLabels.SetNumberOfComponents(1) volumeLabels.SetNumberOfTuples(nFrames) for i in range(nFrames): frameId = frameIdMultiplier * (self.__veInitial.value + self.__veStep.value * i) volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + ',' frameLabelsAttr = frameLabelsAttr[:-1] # allocate multivolume mvImage = vtk.vtkImageData() mvImage.SetExtent(frame0Extent) mvImage.AllocateScalars(frame0.GetImageData().GetScalarType(), nFrames) extent = frame0.GetImageData().GetExtent() numPixels = float(extent[1] + 1) * (extent[3] + 1) * (extent[5] + 1) * nFrames scalarType = frame0.GetImageData().GetScalarType() print('Will now try to allocate memory for ' + str(numPixels) + ' pixels of VTK scalar type ' + str(scalarType)) print('Memory allocated successfully') mvImageArray = vtk.util.numpy_support.vtk_to_numpy( mvImage.GetPointData().GetScalars()) mat = vtk.vtkMatrix4x4() frame0.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame0.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) for frameId in range(nFrames): # TODO: check consistent size and orientation! frame = frames[frameId] frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy( frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', dicomTagNameAttr) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', dicomTagUnitsAttr) if dicomTagNameAttr == 'TriggerTime' or dicomTagNameAttr == 'AcquisitionTime': if teAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.EchoTime', teAttr) if trAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.RepetitionTime', trAttr) if faAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.FlipAngle', faAttr) mvNode.SetName(str(nFrames) + ' frames MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(), None)
def onImportButtonClicked(self): # check if the output container exists vcNode = self.__vcSelector.currentNode() if vcNode == None: self.__status.text = 'Status: Select output node!' return modeIdx = self.__modeSelector.currentIndex processingMode = self.__processingModes[modeIdx] # There are two options: # 1. DICOM series in a directory, with either predefined or custom parse tag # 2. Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() if modeIdx < len(self.__processingModes)-1: # DICOM series # get logic logic = slicer.modules.multivolumeexplorer.logic() # create a clean temporary directory tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') if not os.path.exists(tmpDir): os.mkdir(tmpDir) tmpDir = tmpDir+'/MultiVolumeImporter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) else: # clean it up print 'tmpDir = '+tmpDir fileNames = os.listdir(tmpDir) for f in fileNames: print f,' will be unlinked' os.unlink(tmpDir+'/'+f) nFrames = logic.ProcessDICOMSeries(self.__fDialog.directory, tmpDir, self.__dicomTag.text, volumeLabels) self.__status.text = 'Series processed OK, '+str(nFrames)+' volumes identified' Helper.Info('Location of files:'+tmpDir) fileNames = os.listdir(tmpDir) fileNames.sort() frameFolder = tmpDir else: # each frame is saved as a separate volume fileNames = os.listdir(self.__fDialog.directory) fileNames.sort() frameFolder = self.__fDialog.directory nFrames = len(fileNames) volumeLabels.SetNumberOfTuples(nFrames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(nFrames) for i in range(len(fileNames)): frameId = self.__veInitial.value+self.__veStep.value*i volumeLabels.SetComponent(i, 0, frameId) # read the first frame to get the extent for DWI node fullName = frameFolder+'/'+fileNames[0] volumesLogic = slicer.modules.volumes.logic() frame = volumesLogic.AddArchetypeVolume(fullName, processingMode[3]+' Frame 0', 0) frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1]*frameExtent[3]*frameExtent[5] nFrames = len(fileNames) dwiImage = vtk.vtkImageData() dwiImage.SetExtent(frameExtent) dwiImage.SetNumberOfScalarComponents(nFrames) dwiImage.AllocateScalars() dwiImageArray = vtk.util.numpy_support.vtk_to_numpy(dwiImage.GetPointData().GetScalars()) # create and initialize a blank DWI node bValues = vtk.vtkDoubleArray() bValues.Allocate(nFrames) bValues.SetNumberOfComponents(1) bValues.SetNumberOfTuples(nFrames) gradients = vtk.vtkDoubleArray() gradients.Allocate(nFrames*3) gradients.SetNumberOfComponents(3) gradients.SetNumberOfTuples(nFrames) bValuesArray = vtk.util.numpy_support.vtk_to_numpy(bValues) gradientsArray = vtk.util.numpy_support.vtk_to_numpy(gradients) bValuesArray[:] = 0 gradientsArray[:] = 1 dwiNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLDiffusionWeightedVolumeNode') dwiNode.SetName(processingMode[3]+'DisplayVolume') dwiNode.SetScene(slicer.mrmlScene) dwiNode.SetBValues(bValues) dwiNode.SetDiffusionGradients(gradients) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) dwiNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) dwiNode.SetIJKToRASMatrix(mat) self.annihilateScalarNode(frame) for frameId in range(0,nFrames): fullName = frameFolder+'/'+fileNames[frameId] Helper.Info('Processing frame '+str(frameId)+': '+fullName) frame = volumesLogic.AddArchetypeVolume(fullName, 'Frame'+str(frameId), 0) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) dwiImageArray.T[frameId] = frameImageArray self.annihilateScalarNode(frame) dwiDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLDiffusionWeightedVolumeDisplayNode') dwiDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(dwiDisplayNode) dwiDisplayNode.SetDefaultColorMap() dwiNode.SetAndObserveDisplayNodeID(dwiDisplayNode.GetID()) dwiNode.SetAndObserveImageData(dwiImage) slicer.mrmlScene.AddNode(dwiNode) Helper.Info('DWI node added to the scene') vcNode.SetDWVNodeID(dwiNode.GetID()) vcNode.SetLabelArray(volumeLabels) vcNode.SetLabelName(self.__veLabel.text) Helper.Info('VC node setup complete!') Helper.SetBgFgVolumes(dwiNode.GetID(),None)
def setup(self): # Instantiate and connect widgets ... if self.developerMode: # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "VolumeProbe Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test All") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # reload and run specific tests scenarios = ("Three Volume", "View Watcher", "ROIManager",) for scenario in scenarios: button = qt.QPushButton("Reload and Test %s" % scenario) self.reloadAndTestButton.toolTip = "Reload this module and then run the %s self test." % scenario reloadFormLayout.addWidget(button) button.connect('clicked()', lambda s=scenario: self.onReloadAndTest(scenario=s)) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) """ # # target volume selector # self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = ( ("vtkMRMLVolumeNode"), "" ) self.inputSelector.selectNodeUponCreation = True self.inputSelector.addEnabled = False self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = False self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = True self.inputSelector.setMRMLScene( slicer.mrmlScene ) self.inputSelector.setToolTip( "Pick the input to the algorithm." ) parametersFormLayout.addRow("Target Volume: ", self.inputSelector) """ # # Add ROI # self.drawROICheck = qt.QCheckBox() parametersFormLayout.addRow("Draw ROI", self.drawROICheck) self.drawROICheck.connect("toggled(bool)", self.onDrawROIToggled) self.ROIRadiusSlider = ctk.ctkSliderWidget() #self.ROIRadiusSlider.setMinimum(1) #self.ROIRadiusSlider.setMaximum(100) self.ROIRadiusSlider.setValue(self.ROIRadius) parametersFormLayout.addRow("ROI Radius", self.ROIRadiusSlider) self.ROIRadiusSlider.connect("valueChanged(double)", self.onROIRadiusChanged) # # Add Histogram self.numBins = qt.QSpinBox() self.numBins.setRange(0, 200) self.numBins.setEnabled(1) self.numBins.setValue(20) parametersFormLayout.addRow("Number of Bins", self.numBins) self.histogramArray = vtk.vtkDoubleArray() self.histogramArray.SetNumberOfComponents(1) self.histogramArray.SetNumberOfTuples(0) self.histogram = ctk.ctkVTKHistogram() self.histogram.setDataArray(self.histogramArray) self.histogram.numberOfBins = self.numBins.value self.histogramView = ctk.ctkTransferFunctionView() self.histogramItem = ctk.ctkTransferFunctionBarsItem(self.histogram) self.histogramItem.barWidth = 0.7 self.histogramView.scene().addItem(self.histogramItem) parametersFormLayout.addRow("Histogram", self.histogramView) self.histogramView.show() self.minField = qt.QSpinBox() self.minField.setRange(-100000, 100000) self.minField.setEnabled(0) parametersFormLayout.addRow("Min Value", self.minField) self.maxField = qt.QSpinBox() self.maxField.setRange(-100000, 100000) self.maxField.setEnabled(0) parametersFormLayout.addRow("Max Value", self.maxField) self.meanField = qt.QSpinBox() self.meanField.setRange(-100000, 100000) self.meanField.setEnabled(0) parametersFormLayout.addRow("Mean Value", self.meanField) self.medianField = qt.QSpinBox() self.medianField.setRange(-100000, 100000) self.medianField.setEnabled(0) parametersFormLayout.addRow("Median Value", self.medianField) self.stdField = qt.QSpinBox() self.stdField.setRange(-100000, 100000) self.stdField.setEnabled(0) parametersFormLayout.addRow("STD Value", self.stdField) # Add vertical spacer self.layout.addStretch(1)
def convertTextureToPointAttribute(self, modelNode, textureImageNode, colorAsVector): polyData = modelNode.GetPolyData() textureImageFlipVert = vtk.vtkImageFlip() textureImageFlipVert.SetFilteredAxis(1) textureImageFlipVert.SetInputConnection( textureImageNode.GetImageDataConnection()) textureImageFlipVert.Update() textureImageData = textureImageFlipVert.GetOutput() pointData = polyData.GetPointData() tcoords = pointData.GetTCoords() numOfPoints = pointData.GetNumberOfTuples() assert numOfPoints == tcoords.GetNumberOfTuples( ), "Number of texture coordinates does not equal number of points" textureSamplingPointsUv = vtk.vtkPoints() textureSamplingPointsUv.SetNumberOfPoints(numOfPoints) for pointIndex in range(numOfPoints): uv = tcoords.GetTuple2(pointIndex) textureSamplingPointsUv.SetPoint(pointIndex, uv[0], uv[1], 0) textureSamplingPointDataUv = vtk.vtkPolyData() uvToXyz = vtk.vtkTransform() textureImageDataSpacingSpacing = textureImageData.GetSpacing() textureImageDataSpacingOrigin = textureImageData.GetOrigin() textureImageDataSpacingDimensions = textureImageData.GetDimensions() uvToXyz.Scale( textureImageDataSpacingDimensions[0] / textureImageDataSpacingSpacing[0], textureImageDataSpacingDimensions[1] / textureImageDataSpacingSpacing[1], 1) uvToXyz.Translate(textureImageDataSpacingOrigin) textureSamplingPointDataUv.SetPoints(textureSamplingPointsUv) transformPolyDataToXyz = vtk.vtkTransformPolyDataFilter() transformPolyDataToXyz.SetInputData(textureSamplingPointDataUv) transformPolyDataToXyz.SetTransform(uvToXyz) probeFilter = vtk.vtkProbeFilter() probeFilter.SetInputConnection(transformPolyDataToXyz.GetOutputPort()) probeFilter.SetSourceData(textureImageData) probeFilter.Update() rgbPoints = probeFilter.GetOutput().GetPointData().GetArray( 'ImageScalars') if colorAsVector: colorArray = vtk.vtkDoubleArray() colorArray.SetName('Color') colorArray.SetNumberOfComponents(3) colorArray.SetNumberOfTuples(numOfPoints) for pointIndex in range(numOfPoints): rgb = rgbPoints.GetTuple3(pointIndex) colorArray.SetTuple3(pointIndex, rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) colorArray.Modified() pointData.AddArray(colorArray) else: colorArrayRed = vtk.vtkDoubleArray() colorArrayRed.SetName('ColorRed') colorArrayRed.SetNumberOfTuples(numOfPoints) colorArrayGreen = vtk.vtkDoubleArray() colorArrayGreen.SetName('ColorGreen') colorArrayGreen.SetNumberOfTuples(numOfPoints) colorArrayBlue = vtk.vtkDoubleArray() colorArrayBlue.SetName('ColorBlue') colorArrayBlue.SetNumberOfTuples(numOfPoints) for pointIndex in range(numOfPoints): rgb = rgbPoints.GetTuple3(pointIndex) colorArrayRed.SetValue(pointIndex, rgb[0]) colorArrayGreen.SetValue(pointIndex, rgb[1]) colorArrayBlue.SetValue(pointIndex, rgb[2]) colorArrayRed.Modified() colorArrayGreen.Modified() colorArrayBlue.Modified() pointData.AddArray(colorArrayRed) pointData.AddArray(colorArrayGreen) pointData.AddArray(colorArrayBlue) pointData.Modified() polyData.Modified()
def calcApproachScore(self, point, skinPolyData, obstacleBspTree, skinModelNode=None): pTarget = point polyData = skinPolyData nPoints = polyData.GetNumberOfPoints() nCells = polyData.GetNumberOfCells() pSurface = [0.0, 0.0, 0.0] minDistancePoint = [0.0, 0.0, 0.0] tolerance = 0.001 t = vtk.mutable(0.0) x = [0.0, 0.0, 0.0] pcoords = [0.0, 0.0, 0.0] subId = vtk.mutable(0) #print ("nPoints = %d" % (nPoints)) #print ("nCells = %d" % (nCells)) # Map surface model if skinModelNode != None: pointValue = vtk.vtkDoubleArray() pointValue.SetName("Colors") pointValue.SetNumberOfComponents(1) pointValue.SetNumberOfTuples(nPoints) pointValue.Reset() pointValue.FillComponent(0, 0.0) bspTree = obstacleBspTree cp0 = [0.0, 0.0, 0.0] cp1 = [0.0, 0.0, 0.0] cp2 = [0.0, 0.0, 0.0] accessibleArea = 0.0 inaccessibleArea = 0.0 ids = vtk.vtkIdList() minDistance = -1 for index in range(nCells): cell = polyData.GetCell(index) if cell.GetCellType() == vtk.VTK_TRIANGLE: area = cell.ComputeArea() polyData.GetCellPoints(index, ids) polyData.GetPoint(ids.GetId(0), cp0) polyData.GetPoint(ids.GetId(1), cp1) polyData.GetPoint(ids.GetId(2), cp2) vtk.vtkTriangle.TriangleCenter(cp0, cp1, cp2, pSurface) iD = bspTree.IntersectWithLine(pSurface, pTarget, tolerance, t, x, pcoords, subId) if iD < 1: if skinModelNode != None: d = vtk.vtkMath.Distance2BetweenPoints( pSurface, pTarget) d = math.sqrt(d) if d < minDistance or minDistance < 0: minDistance = d minDistancePoint = [ pSurface[0], pSurface[1], pSurface[2] ] v = d + 101 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) accessibleArea = accessibleArea + area else: if skinModelNode != None: v = -1.0 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) inaccessibleArea = inaccessibleArea + area else: print("ERROR: Non-triangular cell.") score = accessibleArea / (accessibleArea + inaccessibleArea) if skinModelNode != None: skinModelNode.AddPointScalars(pointValue) skinModelNode.SetActivePointScalars( "Colors", vtk.vtkDataSetAttributes.SCALARS) skinModelNode.Modified() displayNode = skinModelNode.GetModelDisplayNode() displayNode.SetActiveScalarName("Colors") displayNode.SetScalarRange(0.0, 200.0) return (score, minDistance, minDistancePoint)
def calcApproachScore(self, point, skinPolyData, obstacleBspTree, skinModelNode=None): pTarget = point polyData = skinPolyData nPoints = polyData.GetNumberOfPoints() nCells = polyData.GetNumberOfCells() pSurface=[0.0, 0.0, 0.0] minDistancePoint = [0.0, 0.0, 0.0] tolerance = 0.001 t = vtk.mutable(0.0) x = [0.0, 0.0, 0.0] pcoords = [0.0, 0.0, 0.0] subId = vtk.mutable(0) #print ("nPoints = %d" % (nPoints)) #print ("nCells = %d" % (nCells)) # Map surface model if skinModelNode != None: pointValue = vtk.vtkDoubleArray() pointValue.SetName("Colors") pointValue.SetNumberOfComponents(1) pointValue.SetNumberOfTuples(nPoints) pointValue.Reset() pointValue.FillComponent(0,0.0); bspTree = obstacleBspTree cp0=[0.0, 0.0, 0.0] cp1=[0.0, 0.0, 0.0] cp2=[0.0, 0.0, 0.0] accessibleArea = 0.0 inaccessibleArea = 0.0 ids=vtk.vtkIdList() minDistance = -1; for index in range(nCells): cell = polyData.GetCell(index) if cell.GetCellType() == vtk.VTK_TRIANGLE: area = cell.ComputeArea() polyData.GetCellPoints(index, ids) polyData.GetPoint(ids.GetId(0), cp0) polyData.GetPoint(ids.GetId(1), cp1) polyData.GetPoint(ids.GetId(2), cp2) vtk.vtkTriangle.TriangleCenter(cp0, cp1, cp2, pSurface) iD = bspTree.IntersectWithLine(pSurface, pTarget, tolerance, t, x, pcoords, subId) if iD < 1: if skinModelNode != None: d = vtk.vtkMath.Distance2BetweenPoints(pSurface, pTarget) d = math.sqrt(d) if d < minDistance or minDistance < 0: minDistance = d minDistancePoint = [pSurface[0],pSurface[1],pSurface[2]] v = d+101 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) accessibleArea = accessibleArea + area else: if skinModelNode != None: v = -1.0 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) inaccessibleArea = inaccessibleArea + area else: print ("ERROR: Non-triangular cell.") score = accessibleArea / (accessibleArea + inaccessibleArea) if skinModelNode != None: skinModelNode.AddPointScalars(pointValue) skinModelNode.SetActivePointScalars("Colors", vtk.vtkDataSetAttributes.SCALARS) skinModelNode.Modified() displayNode = skinModelNode.GetModelDisplayNode() displayNode.SetActiveScalarName("Colors") displayNode.SetScalarRange(0.0,200.0) return (score, minDistance, minDistancePoint)
def loadDevelopmentalAtlas(self): # get the header - this reader doesn't support 4D # but can query the header. reader = vtk.vtkNIFTIImageReader() reader.SetFileName(self.developmentalPath) reader.Update() niftiHeader = reader.GetNIFTIHeader() print(self.developmentalPath) if niftiHeader.GetDataType() != 16: print (niftiHeader.GetDataType()) raise Exception('Can only load float data') # create the correct size and shape vtkImageData columns = niftiHeader.GetDim(1) rows = niftiHeader.GetDim(2) slices = niftiHeader.GetDim(3) frames = niftiHeader.GetDim(4) fp = open(self.developmentalPath, 'rb') headerThrowaway = fp.read(niftiHeader.GetVoxOffset()) niiArray = numpy.fromfile(fp, numpy.dtype('float32')) niiShape = (frames, slices, rows, columns) niiArray = niiArray.reshape(niiShape) image = vtk.vtkImageData() image.SetDimensions(columns, rows, slices) image.AllocateScalars(vtk.VTK_FLOAT, frames) from vtk.util.numpy_support import vtk_to_numpy imageShape = (slices, rows, columns, frames) imageArray = vtk_to_numpy(image.GetPointData().GetScalars()).reshape(imageShape) # copy the data from numpy to vtk (need to shuffle frames to components) for frame in range(frames): imageArray[:,:,:,frame] = niiArray[frame] # create the multivolume node and display it multiVolumeNode = slicer.vtkMRMLMultiVolumeNode() volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(frames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(frames) for frame in xrange(frames): volumeLabels.SetComponent(frame,0,self.agesInYears[frame]) multiVolumeNode.SetScene(slicer.mrmlScene) multiVolumeDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') multiVolumeDisplayNode.SetReferenceCount(multiVolumeDisplayNode.GetReferenceCount()-1) multiVolumeDisplayNode.SetScene(slicer.mrmlScene) multiVolumeDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(multiVolumeDisplayNode) multiVolumeNode.SetAndObserveDisplayNodeID(multiVolumeDisplayNode.GetID()) multiVolumeNode.SetAndObserveImageData(image) multiVolumeNode.SetNumberOfFrames(frames) multiVolumeNode.SetName("DevelopmentalAtlas") multiVolumeNode.SetLabelArray(volumeLabels) multiVolumeNode.SetLabelName("Years") multiVolumeNode.SetAttribute("MultiVolume.FrameLabels", str(self.agesInYears)[1:-1]) multiVolumeNode.SetAttribute("MultiVolume.NumberOfFrames", str(frames)) multiVolumeNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagName", "Age") multiVolumeNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagUnits", "(Years)") slicer.mrmlScene.AddNode(multiVolumeNode) return multiVolumeNode
def registrarButton(self): mvNode = self.outputRegSelector.currentNode() inputVolume = self.inputRegSelector.currentNode() """ Run the actual algorithm """ #se obtiene la escena y se obtiene el volumen 4D a partir del Volumen 4D de #entrada de la ventana desplegable escena = slicer.mrmlScene imagenvtk4D = inputVolume.GetImageData() #Se obtiene el número de volúmenes que tiene el volumen 4D numero_imagenes = inputVolume.GetNumberOfFrames() print('imagenes: ' + str(numero_imagenes)) #filtro vtk para descomponer un volumen 4D extract1 = vtk.vtkImageExtractComponents() extract1.SetInputData(imagenvtk4D) #matriz de transformación ras2ijk = vtk.vtkMatrix4x4() ijk2ras = vtk.vtkMatrix4x4() #le solicitamos al volumen original que nos devuelva sus matrices inputVolume.GetRASToIJKMatrix(ras2ijk) inputVolume.GetIJKToRASMatrix(ijk2ras) #creo un volumen nuevo volumenFijo = slicer.vtkMRMLScalarVolumeNode() volumenSalida = slicer.vtkMRMLMultiVolumeNode() #le asigno las transformaciones volumenFijo.SetRASToIJKMatrix(ras2ijk) volumenFijo.SetIJKToRASMatrix(ijk2ras) #le asigno el volumen 3D fijo imagen_fija = extract1.SetComponents(0) extract1.Update() volumenFijo.SetName('fijo') volumenFijo.SetAndObserveImageData(extract1.GetOutput()) #anado el nuevo volumen a la escena escena.AddNode(volumenFijo) #se crea un vector para guardar el número del volumen que tenga un #desplazamiento de mas de 4mm en cualquier dirección v = [] #se hace un ciclo for para registrar todos los demás volúmenes del volumen 4D #con el primer volumen que se definió como fijo frameLabelsAttr = '' frames = [] volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(numero_imagenes) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(numero_imagenes) for i in range(numero_imagenes): # extraigo la imagen móvil en la posición i+1 ya que el primero es el fijo imagen_movil = extract1.SetComponents( i + 1) #Seleccionar un volumen i+1 extract1.Update() #Creo el volumen móvil, y realizo el mismo procedimiento que con el fijo volumenMovil = slicer.vtkMRMLScalarVolumeNode() volumenMovil.SetRASToIJKMatrix(ras2ijk) volumenMovil.SetIJKToRASMatrix(ijk2ras) volumenMovil.SetAndObserveImageData(extract1.GetOutput()) volumenMovil.SetName('movil ' + str(i + 1)) escena.AddNode(volumenMovil) #creamos la transformada para alinear los volúmenes transformadaSalida = slicer.vtkMRMLLinearTransformNode() transformadaSalida.SetName('Transformadaderegistro' + str(i + 1)) slicer.mrmlScene.AddNode(transformadaSalida) #parámetros para la operación de registro parameters = {} #parameters['InitialTransform'] = transI.GetID() parameters['fixedVolume'] = volumenFijo.GetID() parameters['movingVolume'] = volumenMovil.GetID() parameters['transformType'] = 'Rigid' parameters['outputTransform'] = transformadaSalida.GetID() frames.append(volumenMovil) ## parameters['outputVolume']=volumenSalida.GetID() #Realizo el registro cliNode = slicer.cli.run(slicer.modules.brainsfit, None, parameters, wait_for_completion=True) #obtengo la transformada lineal que se usó en el registro transformada = escena.GetFirstNodeByName('Transformadaderegistro' + str(i + 1)) #Obtengo la matriz de la transformada, esta matriz es de dimensiones 4x4 #en la cual estan todos los desplazamientos y rotaciones que se hicieron #en la transformada, a partir de ella se obtienen los volumenes que se #desplazaron mas de 4mm en cualquier direccion hm = vtk.vtkMatrix4x4() transformadaSalida.GetMatrixTransformToWorld(hm) volumenMovil.ApplyTransformMatrix(hm) volumenMovil.SetAndObserveTransformNodeID(None) frameId = i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + ',' ## Matriz=transformada.GetMatrixTransformToParent() ## LR=Matriz.GetElement(0,3)#dirección izquierda o derecha en la fila 1, columna 4 ## PA=Matriz.GetElement(1,3)#dirección anterior o posterior en la fila 2, columna 4 ## IS=Matriz.GetElement(2,3)#dirección inferior o superior en la fila 3, columna 4 ## #Se mira si el volumen "i" en alguna dirección tuvo un desplazamiento ## #mayor a 4mm, en caso de ser cierto se guarda en el vector "v" ## if abs(LR)>4: ## v.append(i+2) ## elif abs(PA)>4: ## v.append(i+2) ## elif abs(IS)>4: ## v.append(i+2) ## print("MovilExtent: "+str(volumenMovil.GetImageData().GetExtent())) #### print("valor de f: "+ str(volumenMovil)) ## frameLabelsAttr = frameLabelsAttr[:-1] mvImage = vtk.vtkImageData() mvImage.SetExtent(volumenMovil.GetImageData().GetExtent() ) ##Se le asigna la dimensión del miltuvolumen mvImage.AllocateScalars( volumenMovil.GetImageData().GetScalarType(), numero_imagenes ) ##Se le asigna el tipo y número de cortes al multivolumen mvImageArray = vtk.util.numpy_support.vtk_to_numpy( mvImage.GetPointData().GetScalars() ) ## Se crea la matriz de datos donde va a ir la imagen mat = vtk.vtkMatrix4x4() ##Se hace la conversión y se obtiene la matriz de transformación del nodo volumenMovil.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) volumenMovil.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) print("frameId: " + str(frameId)) print("# imag: " + str(numero_imagenes)) ## print("Long frame1: "+str(len(frame))) print("Long frames: " + str(len(frames))) ## for frameId in range(numero_imagenes): # TODO: check consistent size and orientation! frame = frames[frameId] frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy( frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray ##Se crea el nodo del multivolumen mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(numero_imagenes) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName('na') mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(numero_imagenes)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', 'NA') mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', 'na') mvNode.SetName('MultiVolume Registrado') Helper.SetBgFgVolumes(mvNode.GetID(), None) print('Registro completo') #al terminar el ciclo for con todos los volúmenes registrados se genera una #ventana emergente con un mensaje("Registro completo!") y mostrando los #volúmenes que se desplazaron mas de 4mm qt.QMessageBox.information(slicer.util.mainWindow(), 'Slicer Python', 'Registro completo') return True
def clipSurfaceAtEndPoints( self, networkPolyData, surfacePolyData ): ''' Clips the surfacePolyData on the endpoints identified using the networkPolyData. Returns a tupel of the form [clippedPolyData, endpointsPoints] ''' # import the vmtk libraries try: import vtkvmtkComputationalGeometryPython as vtkvmtkComputationalGeometry import vtkvmtkMiscPython as vtkvmtkMisc except ImportError: logging.error("Unable to import the SlicerVmtk libraries") cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData( networkPolyData ) cleaner.Update() network = cleaner.GetOutput() network.BuildCells() network.BuildLinks( 0 ) endpointIds = vtk.vtkIdList() radiusArray = network.GetPointData().GetArray( 'Radius' ) endpoints = vtk.vtkPolyData() endpointsPoints = vtk.vtkPoints() endpointsRadius = vtk.vtkDoubleArray() endpointsRadius.SetName( 'Radius' ) endpoints.SetPoints( endpointsPoints ) endpoints.GetPointData().AddArray( endpointsRadius ) radiusFactor = 1.2 minRadius = 0.01 for i in range( network.GetNumberOfCells() ): numberOfCellPoints = network.GetCell( i ).GetNumberOfPoints() pointId0 = network.GetCell( i ).GetPointId( 0 ) pointId1 = network.GetCell( i ).GetPointId( numberOfCellPoints - 1 ) pointCells = vtk.vtkIdList() network.GetPointCells( pointId0, pointCells ) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId( pointId0 ) if pointId == numberOfEndpoints: point = network.GetPoint( pointId0 ) radius = radiusArray.GetValue( pointId0 ) radius = max( radius, minRadius ) endpointsPoints.InsertNextPoint( point ) endpointsRadius.InsertNextValue( radiusFactor * radius ) pointCells = vtk.vtkIdList() network.GetPointCells( pointId1, pointCells ) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId( pointId1 ) if pointId == numberOfEndpoints: point = network.GetPoint( pointId1 ) radius = radiusArray.GetValue( pointId1 ) radius = max( radius, minRadius ) endpointsPoints.InsertNextPoint( point ) endpointsRadius.InsertNextValue( radiusFactor * radius ) polyBall = vtkvmtkComputationalGeometry.vtkvmtkPolyBall() #polyBall.SetInputData( endpoints ) polyBall.SetInput( endpoints ) polyBall.SetPolyBallRadiusArrayName( 'Radius' ) clipper = vtk.vtkClipPolyData() clipper.SetInputData( surfacePolyData ) clipper.SetClipFunction( polyBall ) clipper.Update() connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputData( clipper.GetOutput() ) connectivityFilter.ColorRegionsOff() connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() clippedSurface = connectivityFilter.GetOutput() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy( clippedSurface ) return [outPolyData, endpointsPoints]
def initMultiVolumes(self, files, prescribedTags=None): tag2ValueFileList = {} multivolumes = [] if prescribedTags == None: consideredTags = self.multiVolumeTags.keys() else: consideredTags = prescribedTags # iterate over all files for file in files: # iterate over the tags that can be used to separate individual frames for frameTag in consideredTags: try: tagValue2FileList = tag2ValueFileList[frameTag] except: tagValue2FileList = {} tag2ValueFileList[frameTag] = tagValue2FileList tagValueStr = slicer.dicomDatabase.fileValue(file,self.tags[frameTag]) if tagValueStr == '': # not found? continue if frameTag == 'AcquisitionTime' or frameTag == 'SeriesTime': # extra parsing is needed to convert from DICOM TM VR into ms tagValue = self.tm2ms(tagValueStr) # convert to ms else: tagValue = float(tagValueStr) try: tagValue2FileList[tagValue].append(file) except: tagValue2FileList[tagValue] = [file] # iterate over the parsed items and decide which ones can qualify as mv for frameTag in self.multiVolumeTags.keys(): try: tagValue2FileList = tag2ValueFileList[frameTag] except: # didn't find the tag continue if len(tagValue2FileList)<2: # not enough frames for this tag to be a multivolume continue tagValues = tagValue2FileList.keys() # sort the frames tagValues.sort() firstFrameSize = len(tagValue2FileList[tagValues[0]]) frameInvalid = False for tagValue in tagValues: if len(tagValue2FileList[tagValue]) != firstFrameSize: # number of frames does not match frameInvalid = True if frameInvalid == True: continue # TODO: add a check to confirm individual frames have the same geometry # (check pixel dimensions, orientation, position) # now this looks like a serious mv! # initialize the needed attributes for a new mvNode frameFileListStr = "" frameLabelsStr = "" frameLabelsArray = vtk.vtkDoubleArray() tagValue0 = tagValues[0] for tagValue in tagValues: frameFileList = tagValue2FileList[tagValue] for file in frameFileList: frameFileListStr = frameFileListStr+file+',' frameLabelsStr = frameLabelsStr+str(tagValue)+',' # if mv was parsed by series time, probably makes sense to start from # 0 if frameTag == 'SeriesTime': frameLabelsArray.InsertNextValue(tagValue-tagValue0) else: frameLabelsArray.InsertNextValue(tagValue) #print 'File list: ',frameFileList #print 'Labels: ',frameLabelsStr frameFileListStr = frameFileListStr[:-1] frameLabelsStr = frameLabelsStr[:-1] mvNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeNode') mvNode.SetReferenceCount(mvNode.GetReferenceCount()-1) mvNode.SetScene(slicer.mrmlScene) mvNode.SetAttribute("MultiVolume.FrameFileList",frameFileListStr) mvNode.SetAttribute("MultiVolume.FrameLabels",frameLabelsStr) mvNode.SetAttribute("MultiVolume.FrameIdentifyingDICOMTagName",frameTag) mvNode.SetAttribute('MultiVolume.NumberOfFrames',str(len(tagValue2FileList))) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits',self.multiVolumeTagsUnits[frameTag]) mvNode.SetNumberOfFrames(len(tagValue2FileList)) mvNode.SetLabelName(self.multiVolumeTagsUnits[frameTag]) mvNode.SetLabelArray(frameLabelsArray) if frameTag == 'TriggerTime' or frameTag == 'AcquisitionTime': # this is DCE, so let's keep the tag values that will be needed for # the analysis firstFile = frameFileList[0] echoTime = slicer.dicomDatabase.fileValue(firstFile, self.tags['EchoTime']) repetitionTime = slicer.dicomDatabase.fileValue(firstFile, self.tags['RepetitionTime']) flipAngle = slicer.dicomDatabase.fileValue(firstFile, self.tags['FlipAngle']) mvNode.SetAttribute('MultiVolume.DICOM.EchoTime',echoTime) mvNode.SetAttribute('MultiVolume.DICOM.RepetitionTime',repetitionTime) mvNode.SetAttribute('MultiVolume.DICOM.FlipAngle',flipAngle) # add the node multivolumes.append(mvNode) return multivolumes
def loadDevelopmentalAtlas(self): # get the header - this reader doesn't support 4D # but can query the header. reader = vtk.vtkNIFTIImageReader() reader.SetFileName(self.developmentalPath) reader.Update() niftiHeader = reader.GetNIFTIHeader() print(self.developmentalPath) if niftiHeader.GetDataType() != 16: print(niftiHeader.GetDataType()) raise Exception('Can only load float data') # create the correct size and shape vtkImageData columns = niftiHeader.GetDim(1) rows = niftiHeader.GetDim(2) slices = niftiHeader.GetDim(3) frames = niftiHeader.GetDim(4) fp = open(self.developmentalPath, 'rb') headerThrowaway = fp.read(niftiHeader.GetVoxOffset()) niiArray = numpy.fromfile(fp, numpy.dtype('float32')) niiShape = (frames, slices, rows, columns) niiArray = niiArray.reshape(niiShape) image = vtk.vtkImageData() image.SetDimensions(columns, rows, slices) image.AllocateScalars(vtk.VTK_FLOAT, frames) from vtk.util.numpy_support import vtk_to_numpy imageShape = (slices, rows, columns, frames) imageArray = vtk_to_numpy( image.GetPointData().GetScalars()).reshape(imageShape) # copy the data from numpy to vtk (need to shuffle frames to components) for frame in range(frames): imageArray[:, :, :, frame] = niiArray[frame] # create the multivolume node and display it multiVolumeNode = slicer.vtkMRMLMultiVolumeNode() volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(frames) volumeLabels.SetNumberOfComponents(1) volumeLabels.Allocate(frames) for frame in xrange(frames): volumeLabels.SetComponent(frame, 0, self.agesInYears[frame]) multiVolumeNode.SetScene(slicer.mrmlScene) multiVolumeDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') multiVolumeDisplayNode.SetReferenceCount( multiVolumeDisplayNode.GetReferenceCount() - 1) multiVolumeDisplayNode.SetScene(slicer.mrmlScene) multiVolumeDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(multiVolumeDisplayNode) multiVolumeNode.SetAndObserveDisplayNodeID( multiVolumeDisplayNode.GetID()) multiVolumeNode.SetAndObserveImageData(image) multiVolumeNode.SetNumberOfFrames(frames) multiVolumeNode.SetName("DevelopmentalAtlas") multiVolumeNode.SetLabelArray(volumeLabels) multiVolumeNode.SetLabelName("Years") multiVolumeNode.SetAttribute("MultiVolume.FrameLabels", str(self.agesInYears)[1:-1]) multiVolumeNode.SetAttribute("MultiVolume.NumberOfFrames", str(frames)) multiVolumeNode.SetAttribute( "MultiVolume.FrameIdentifyingDICOMTagName", "Age") multiVolumeNode.SetAttribute( "MultiVolume.FrameIdentifyingDICOMTagUnits", "(Years)") slicer.mrmlScene.AddNode(multiVolumeNode) return multiVolumeNode
def updateCurve(self): if self.AutomaticUpdate == False: return if self.SourceNode and self.DestinationNode: if self.SourceNode.GetNumberOfFiducials() < 2: if self.CurvePoly != None: self.CurvePoly.Initialize() self.CurveLength = 0.0 else: if self.CurvePoly == None: self.CurvePoly = vtk.vtkPolyData() if self.DestinationNode.GetDisplayNodeID() == None: modelDisplayNode = slicer.vtkMRMLModelDisplayNode() modelDisplayNode.SetColor(self.ModelColor) slicer.mrmlScene.AddNode(modelDisplayNode) self.DestinationNode.SetAndObserveDisplayNodeID( modelDisplayNode.GetID()) if self.InterpolationMethod == 0: if self.RingMode > 0: self.nodeToPoly(self.SourceNode, self.CurvePoly, True) else: self.nodeToPoly(self.SourceNode, self.CurvePoly, False) elif self.InterpolationMethod == 1: # Cardinal Spline if self.RingMode > 0: self.nodeToPolyCardinalSpline(self.SourceNode, self.CurvePoly, True) else: self.nodeToPolyCardinalSpline(self.SourceNode, self.CurvePoly, False) elif self.InterpolationMethod == 2: # Hermite Spline if self.RingMode > 0: self.nodeToPolyHermiteSpline(self.SourceNode, self.CurvePoly, True) else: self.nodeToPolyHermiteSpline(self.SourceNode, self.CurvePoly, False) self.CurveLength = self.calculateLineLength(self.CurvePoly) tubeFilter = vtk.vtkTubeFilter() curvatureValues = vtk.vtkDoubleArray() if self.Curvature: ## If the curvature option is ON, calculate the curvature along the curve. (meanKappa, minKappa, maxKappa) = self.computeCurvatures(self.CurvePoly, curvatureValues) self.CurvePoly.GetPointData().AddArray(curvatureValues) self.curvatureMeanKappa = meanKappa self.curvatureMinKappa = minKappa self.curvatureMaxKappa = maxKappa else: self.curvatureMeanKappa = None self.curvatureMinKappa = None self.curvatureMaxKappa = None tubeFilter.SetInputData(self.CurvePoly) tubeFilter.SetRadius(self.TubeRadius) tubeFilter.SetNumberOfSides(20) tubeFilter.CappingOn() tubeFilter.Update() # self.DestinationNode.SetAndObservePolyData(tubeFilter.GetOutput()) self.DestinationNode.SetAndObservePolyData(self.CurvePoly) self.DestinationNode.Modified() if self.DestinationNode.GetScene() == None: slicer.mrmlScene.AddNode(self.DestinationNode) displayNode = self.DestinationNode.GetDisplayNode() if displayNode: if self.Curvature: displayNode.SetActiveScalarName('Curvature') else: displayNode.SetActiveScalarName('')
def updateCurve(self): if self.AutomaticUpdate == False: return if self.SourceNode and self.DestinationNode: if self.SourceNode.GetNumberOfFiducials() < 2: if self.CurvePoly != None: self.CurvePoly.Initialize() self.CurveLength = 0.0 else: if self.CurvePoly == None: self.CurvePoly = vtk.vtkPolyData() if self.DestinationNode.GetDisplayNodeID() == None: modelDisplayNode = slicer.vtkMRMLModelDisplayNode() modelDisplayNode.SetColor(self.ModelColor) slicer.mrmlScene.AddNode(modelDisplayNode) self.DestinationNode.SetAndObserveDisplayNodeID(modelDisplayNode.GetID()) if self.InterpolationMethod == 0: if self.RingMode > 0: self.nodeToPoly(self.SourceNode, self.CurvePoly, True) else: self.nodeToPoly(self.SourceNode, self.CurvePoly, False) elif self.InterpolationMethod == 1: # Cardinal Spline if self.RingMode > 0: self.nodeToPolyCardinalSpline(self.SourceNode, self.CurvePoly, True) else: self.nodeToPolyCardinalSpline(self.SourceNode, self.CurvePoly, False) elif self.InterpolationMethod == 2: # Hermite Spline if self.RingMode > 0: self.nodeToPolyHermiteSpline(self.SourceNode, self.CurvePoly, True) else: self.nodeToPolyHermiteSpline(self.SourceNode, self.CurvePoly, False) self.CurveLength = self.calculateLineLength(self.CurvePoly) tubeFilter = vtk.vtkTubeFilter() curvatureValues = vtk.vtkDoubleArray() if self.Curvature: ## If the curvature option is ON, calculate the curvature along the curve. (meanKappa, minKappa, maxKappa) = self.computeCurvatures(self.CurvePoly, curvatureValues) self.CurvePoly.GetPointData().AddArray(curvatureValues) self.curvatureMeanKappa = meanKappa self.curvatureMinKappa = minKappa self.curvatureMaxKappa = maxKappa else: self.curvatureMeanKappa = None self.curvatureMinKappa = None self.curvatureMaxKappa = None tubeFilter.SetInputData(self.CurvePoly) tubeFilter.SetRadius(self.TubeRadius) tubeFilter.SetNumberOfSides(20) tubeFilter.CappingOn() tubeFilter.Update() self.DestinationNode.SetAndObservePolyData(tubeFilter.GetOutput()) self.DestinationNode.Modified() if self.DestinationNode.GetScene() == None: slicer.mrmlScene.AddNode(self.DestinationNode) displayNode = self.DestinationNode.GetDisplayNode() if displayNode: if self.Curvature: displayNode.SetActiveScalarName('Curvature') else: displayNode.SetActiveScalarName('')
def onImportButtonClicked(self): # check if the output container exists mvNode = self.__mvSelector.currentNode() if mvNode == None: self.__status.text = 'Status: Select output node!' return # Series of frames alpha-ordered, all in the input directory # Assume here that the last mode in the list is for parsing a list of # non-DICOM frames fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = '' frameFileListAttr = '' dicomTagNameAttr = self.__dicomTag.text dicomTagUnitsAttr = self.__veLabel.text teAttr = self.__te.text trAttr = self.__tr.text faAttr = self.__fa.text # each frame is saved as a separate volume # first filter valid file names and sort alphabetically frames = [] frame0 = None inputDir = self.__fDialog.directory for f in os.listdir(inputDir): if not f.startswith('.'): fileName = inputDir+'/'+f fileNames.append(fileName) self.humanSort(fileNames) # check for nifti file that may be 4D as special case niftiFiles = [] for fileName in fileNames: if fileName.lower().endswith('.nii.gz') or fileName.lower().endswith('.nii'): niftiFiles.append(fileName) if len(niftiFiles) == 1: self.read4DNIfTI(mvNode, niftiFiles[0]) return # not 4D nifti, so keep trying for fileName in fileNames: (s,f) = self.readFrame(fileName) if s: if not frame0: frame0 = f frame0Image = frame0.GetImageData() frame0Extent = frame0Image.GetExtent() else: frameImage = f.GetImageData() frameExtent = frameImage.GetExtent() if frameExtent[1]!=frame0Extent[1] or frameExtent[3]!=frame0Extent[3] or frameExtent[5]!=frame0Extent[5]: continue frames.append(f) nFrames = len(frames) print('Successfully read '+str(nFrames)+' frames') if nFrames == 1: print('Single frame dataset - not reading as multivolume!') return # convert seconds data to milliseconds, which is expected by pkModeling.cxx line 81 if dicomTagUnitsAttr == 's': frameIdMultiplier = 1000.0 dicomTagUnitsAttr = 'ms' else: frameIdMultiplier = 1.0 volumeLabels.SetNumberOfComponents(1) volumeLabels.SetNumberOfTuples(nFrames) for i in range(nFrames): frameId = frameIdMultiplier*(self.__veInitial.value+self.__veStep.value*i) volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId)+',' frameLabelsAttr = frameLabelsAttr[:-1] # allocate multivolume mvImage = vtk.vtkImageData() mvImage.SetExtent(frame0Extent) if vtk.VTK_MAJOR_VERSION <= 5: mvImage.SetNumberOfScalarComponents(nFrames) mvImage.SetScalarType(frame0.GetImageData().GetScalarType()) mvImage.AllocateScalars() else: mvImage.AllocateScalars(frame0.GetImageData().GetScalarType(), nFrames) extent = frame0.GetImageData().GetExtent() numPixels = float(extent[1]+1)*(extent[3]+1)*(extent[5]+1)*nFrames scalarType = frame0.GetImageData().GetScalarType() print('Will now try to allocate memory for '+str(numPixels)+' pixels of VTK scalar type '+str(scalarType)) print('Memory allocated successfully') mvImageArray = vtk.util.numpy_support.vtk_to_numpy(mvImage.GetPointData().GetScalars()) mat = vtk.vtkMatrix4x4() frame0.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame0.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) for frameId in range(nFrames): # TODO: check consistent size and orientation! frame = frames[frameId] frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels',frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames',str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName',dicomTagNameAttr) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits',dicomTagUnitsAttr) if dicomTagNameAttr == 'TriggerTime' or dicomTagNameAttr == 'AcquisitionTime': if teAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.EchoTime',teAttr) if trAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.RepetitionTime',trAttr) if faAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.FlipAngle',faAttr) mvNode.SetName(str(nFrames)+' frames MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(),None)
def clipSurfaceAtEndPoints(self, networkPolyData, surfacePolyData): ''' Clips the surfacePolyData on the endpoints identified using the networkPolyData. Returns a tupel of the form [clippedPolyData, endpointsPoints] ''' # import the vmtk libraries try: from libvtkvmtkComputationalGeometryPython import * from libvtkvmtkMiscPython import * except ImportError: print "FAILURE: Unable to import the SlicerVmtk4 libraries!" cleaner = vtk.vtkCleanPolyData() cleaner.SetInput(networkPolyData) cleaner.Update() network = cleaner.GetOutput() network.BuildCells() network.BuildLinks(0) endpointIds = vtk.vtkIdList() radiusArray = network.GetPointData().GetArray('Radius') endpoints = vtk.vtkPolyData() endpointsPoints = vtk.vtkPoints() endpointsRadius = vtk.vtkDoubleArray() endpointsRadius.SetName('Radius') endpoints.SetPoints(endpointsPoints) endpoints.GetPointData().AddArray(endpointsRadius) radiusFactor = 1.2 minRadius = 0.01 for i in range(network.GetNumberOfCells()): numberOfCellPoints = network.GetCell(i).GetNumberOfPoints() pointId0 = network.GetCell(i).GetPointId(0) pointId1 = network.GetCell(i).GetPointId(numberOfCellPoints - 1) pointCells = vtk.vtkIdList() network.GetPointCells(pointId0, pointCells) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId(pointId0) if pointId == numberOfEndpoints: point = network.GetPoint(pointId0) radius = radiusArray.GetValue(pointId0) radius = max(radius, minRadius) endpointsPoints.InsertNextPoint(point) endpointsRadius.InsertNextValue(radiusFactor * radius) pointCells = vtk.vtkIdList() network.GetPointCells(pointId1, pointCells) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId(pointId1) if pointId == numberOfEndpoints: point = network.GetPoint(pointId1) radius = radiusArray.GetValue(pointId1) radius = max(radius, minRadius) endpointsPoints.InsertNextPoint(point) endpointsRadius.InsertNextValue(radiusFactor * radius) polyBall = vtkvmtkPolyBall() polyBall.SetInput(endpoints) polyBall.SetPolyBallRadiusArrayName('Radius') clipper = vtk.vtkClipPolyData() clipper.SetInput(surfacePolyData) clipper.SetClipFunction(polyBall) clipper.Update() connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInput(clipper.GetOutput()) connectivityFilter.ColorRegionsOff() connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() clippedSurface = connectivityFilter.GetOutput() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy(clippedSurface) outPolyData.Update() return [outPolyData, endpointsPoints]
def read4DNIfTI(self, mvNode, fileName): """Try to read a 4D nifti file as a multivolume""" print('trying to read %s' % fileName) # use the vtk reader which seems to handle most nifti variants well reader = vtk.vtkNIFTIImageReader() reader.SetFileName(fileName) reader.SetTimeAsVector(True) reader.Update() header = reader.GetNIFTIHeader() qFormMatrix = reader.GetQFormMatrix() if not qFormMatrix: print('Warning: %s does not have a QFormMatrix - using Identity') qFormMatrix = vtk.vtkMatrix4x4() spacing = reader.GetOutputDataObject(0).GetSpacing() timeSpacing = reader.GetTimeSpacing() nFrames = reader.GetTimeDimension() if header.GetIntentCode() != header.IntentTimeSeries: intentName = header.GetIntentName() if not intentName: intentName = 'Nothing' print('Warning: %s does not have TimeSeries intent, instead it has \"%s\"' % (fileName,intentName)) print('Trying to read as TimeSeries anyway') units = header.GetXYZTUnits() # try to account for some of the unit options # (Note: no test data available but we hope these are right) if units & header.UnitsMSec: timeSpacing /= 1000. if units & header.UnitsUSec: timeSpacing /= 1000. / 1000. spaceScaling = 1. if units & header.UnitsMeter: spaceScaling *= 1000. if units & header.UnitsMicron: spaceScaling /= 1000. spacing = map(lambda e: e * spaceScaling, spacing) # create frame labels using the timing info from the file # but use the advanced info so user can specify offset and scale volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(nFrames) frameLabelsAttr = '' for i in range(nFrames): frameId = self.__veInitial.value + timeSpacing * self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId)+',' frameLabelsAttr = frameLabelsAttr[:-1] # create the display node mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetDefaultColorMap() # spacing and origin are in the ijkToRAS, so clear them from image data imageChangeInformation = vtk.vtkImageChangeInformation() imageChangeInformation.SetInputConnection(reader.GetOutputPort()) imageChangeInformation.SetOutputSpacing( 1, 1, 1 ) imageChangeInformation.SetOutputOrigin( 0, 0, 0 ) imageChangeInformation.Update() # QForm includes directions and origin, but not spacing so add that # here by multiplying by a diagonal matrix with the spacing scaleMatrix = vtk.vtkMatrix4x4() for diag in range(3): scaleMatrix.SetElement(diag, diag, spacing[diag]) ijkToRAS = vtk.vtkMatrix4x4() ijkToRAS.DeepCopy(qFormMatrix) vtk.vtkMatrix4x4.Multiply4x4(ijkToRAS, scaleMatrix, ijkToRAS) mvNode.SetIJKToRASMatrix(ijkToRAS) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(imageChangeInformation.GetOutputDataObject(0)) mvNode.SetNumberOfFrames(nFrames) # set the labels and other attributes, then display the volume mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels',frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames',str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName','') mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits','') mvNode.SetName(str(nFrames)+' frames NIfTI MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(),None)
def importFunction(self): self.__dicomTag = 'NA' self.__veLabel = 'na' self.__veInitial = 0 self.__veStep = 1 self.__te = 1 self.__tr = 1 self.__fa = 1 nameFrame = self.__nameFrame.text inputVolume = self.inputSelector.currentNode() # check if the output container exists mvNode = self.outputSelector.currentNode() ## if mvNode == None: ## self.__status.text = 'Status: Select output node!' ## return fileNames = [] # file names on disk frameList = [] # frames as MRMLScalarVolumeNode's frameFolder = "" volumeLabels = vtk.vtkDoubleArray() frameLabelsAttr = '' frameFileListAttr = '' dicomTagNameAttr = self.__dicomTag dicomTagUnitsAttr = self.__veLabel teAttr = self.__te trAttr = self.__tr faAttr = self.__fa # each frame is saved as a separate volume # first filter valid file names and sort alphabetically frames = [] frame0 = None inputDir = self.__fDialog.directory metadatos = [] print('hola' + str(len(os.listdir(inputDir)))) for f in os.listdir(inputDir): if not f.startswith('.'): fileName = inputDir + '/' + f fileName1 = str(inputDir + '/' + f) metadato = dicom.read_file(fileName1) metadatos.append(metadato) fileNames.append(fileName) self.humanSort(fileNames) n = 0 for fileName in fileNames: #f: información de cada scalar volume de cada corte (s, f) = self.readFrame(fileName) if s: if not frame0: ## print("valor de f: "+ str(f)); frame0 = f ## print("frame0: "+str(frame0)); frame0Image = frame0.GetImageData() frame0Extent = frame0Image.GetExtent() ## print("frame0Extent: " + str(frame0Extent)); else: ## print("valor de f1: "+ str(f)) frameImage = f.GetImageData() ## print("frameImage: "+str(frameImage)) frameExtent = frameImage.GetExtent() ## print("frameExtent: " + str(frameExtent)); if frameExtent[1] != frame0Extent[1] or frameExtent[ 3] != frame0Extent[3] or frameExtent[ 5] != frame0Extent[5]: continue ## n=n+1 ## print("for: "+str(n)) frames.append(f) nFrames = len(frames) ## print("nFrames: "+str(nFrames)) print('Successfully read ' + str(nFrames) + ' frames') if nFrames == 1: print('Single frame dataset - not reading as multivolume!') return # convert seconds data to milliseconds, which is expected by pkModeling.cxx line 81 if dicomTagUnitsAttr == 's': frameIdMultiplier = 1000.0 dicomTagUnitsAttr = 'ms' else: frameIdMultiplier = 1.0 ## print("volumeLabelsAntes: "+ str(volumeLabels)) volumeLabels.SetNumberOfTuples(nFrames) ## print("volumeLabelsIntermedio: "+ str(volumeLabels)) volumeLabels.SetNumberOfComponents(1) ## print("volumeLabelsDespues: "+ str(volumeLabels)) volumeLabels.Allocate(nFrames) ## print("volumeLabelsTotal: "+ str(volumeLabels)) ### Después de los 3 pasos el único cambio es size, en vez de 0 pasa a ser nFrames for i in range(nFrames): frameId = frameIdMultiplier * (self.__veInitial + self.__veStep * i) ## print("frameId: "+str(frameId)) volumeLabels.SetComponent(i, 0, frameId) ##no hay necesidad #### print("volumeLabelsTotal: "+ str(volumeLabels))##Aparentemente no hay cambio en volumeLabels frameLabelsAttr += str(frameId) + ',' ## print("frameLabelsAttr: "+str(frameLabelsAttr)) frameLabelsAttr = frameLabelsAttr[:-1] ##No hay cambio ## print("frameLabelsAttrTOTAL: "+str(frameLabelsAttr)) # allocate multivolume mvImage = vtk.vtkImageData() ## print("mvImage: "+str(mvImage)) mvImage.SetExtent(frame0Extent) ## print("mvImageExtent: "+str(mvImage)) ## print("vtk.VTK_MAJOR_VERSION: "+str(vtk.VTK_MAJOR_VERSION)) if vtk.VTK_MAJOR_VERSION <= 5: ##Versión 7 mvImage.SetNumberOfScalarComponents(nFrames) print("mvImageSC: " + str(mvImage)) mvImage.SetScalarType(frame0.GetImageData().GetScalarType()) print("mvImageST: " + str(mvImage)) mvImage.AllocateScalars() print("mvImageAllocate: " + str(mvImage)) else: mvImage.AllocateScalars(frame0.GetImageData().GetScalarType(), nFrames) ## print("mvImageElse: "+str(mvImage)) extent = frame0.GetImageData().GetExtent() numPixels = float(extent[1] + 1) * (extent[3] + 1) * (extent[5] + 1) * nFrames scalarType = frame0.GetImageData().GetScalarType() print('Will now try to allocate memory for ' + str(numPixels) + ' pixels of VTK scalar type' + str(scalarType)) print('Memory allocated successfully') mvImageArray = vtk.util.numpy_support.vtk_to_numpy( mvImage.GetPointData().GetScalars()) ## print("mvImageEArray: "+str(mvImageArray)) ## print("mvImage.GetPointData().GetScalars(): " + str(mvImage.GetPointData().GetScalars())); ## print("ID mvImagearray " + str(id(mvImageArray))); ## print("ID 2: " + str(mvImage.GetPointData().GetScalars())); ## print("Que es frame0: " + str(frame0)); ##EMPIEZA A FORMARCE EL VOLUMEN############### mat = vtk.vtkMatrix4x4() frame0.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame0.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) print("frameId: " + str(frameId)) print("# imag: " + str(nFrames)) ## print("Long frame: "+str(len(frame))) for frameId in range(nFrames): # TODO: check consistent size and orientation! frame = frames[frameId] frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy( frameImage.GetPointData().GetScalars()) mvImageArray.T[frameId] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel) mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', dicomTagNameAttr) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', dicomTagUnitsAttr) if dicomTagNameAttr == 'TriggerTime' or dicomTagNameAttr == 'AcquisitionTime': if teAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.EchoTime', teAttr) if trAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.RepetitionTime', trAttr) if faAttr != '': mvNode.SetAttribute('MultiVolume.DICOM.FlipAngle', faAttr) mvNode.SetName(nameFrame) NameFrame = nameFrame self.Diccionario = { NameFrame: metadato } print(self.Diccionario.get(NameFrame)) Helper.SetBgFgVolumes(mvNode.GetID(), None)
def calcApproachScore(self, targetPointNode, skinPolyData, obstacleBspTree, skinModelNode=None): #pTargetA = targetPointNode.GetMarkupPointVector(0, 0) tListNumber = targetPointNode.GetNumberOfFiducials() #pTargetA = pointA #pTargetB = pointB #pTargetC = pointC polyData = skinPolyData nPoints = polyData.GetNumberOfPoints() nCells = polyData.GetNumberOfCells() pSurface = [0.0, 0.0, 0.0] minDistancePoint = [0.0, 0.0, 0.0] tolerance = 0.001 t = vtk.mutable(0.0) x = [0.0, 0.0, 0.0] pcoords = [0.0, 0.0, 0.0] subId = vtk.mutable(0) #print ("nPoints = %d" % (nPoints)) #print ("nCells = %d" % (nCells)) # Map surface model if skinModelNode != None: pointValue = vtk.vtkDoubleArray() pointValue.SetName("Colors") pointValue.SetNumberOfComponents(1) pointValue.SetNumberOfTuples(nPoints) pointValue.Reset() pointValue.FillComponent(0, 0.0) bspTree = obstacleBspTree cp0 = [0.0, 0.0, 0.0] cp1 = [0.0, 0.0, 0.0] cp2 = [0.0, 0.0, 0.0] accessibleArea = 0.0 inaccessibleArea = 0.0 ids = vtk.vtkIdList() minDistance = -1 #iDA = 0 #iDAFlag = 0 #d = 0 for index in range(nCells): iDA = 0 iDAFlag = 0 d = 0 i = 0 j = 0 cell = polyData.GetCell(index) if cell.GetCellType() == vtk.VTK_TRIANGLE: area = cell.ComputeArea() polyData.GetCellPoints(index, ids) polyData.GetPoint(ids.GetId(0), cp0) polyData.GetPoint(ids.GetId(1), cp1) polyData.GetPoint(ids.GetId(2), cp2) vtk.vtkTriangle.TriangleCenter(cp0, cp1, cp2, pSurface) ##### for i in range(0, tListNumber, 1): pTargetA = targetPointNode.GetMarkupPointVector(i, 0) iDA = bspTree.IntersectWithLine(pSurface, pTargetA, tolerance, t, x, pcoords, subId) if iDA >= 1: iDAFlag = 10 ##### if iDAFlag < 1: if skinModelNode != None: for j in range(0, tListNumber, 1): pTargetA = targetPointNode.GetMarkupPointVector( j, 0) d += (vtk.vtkMath.Distance2BetweenPoints( pSurface, pTargetA)) d = d / tListNumber d = math.sqrt(d) if 100 < d < 240: if d < minDistance or minDistance < 0: minDistance = d minDistancePoint = [ pSurface[0], pSurface[1], pSurface[2] ] v = d + 51 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) accessibleArea = accessibleArea + area else: v = -1.0 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) inaccessibleArea = inaccessibleArea + area else: if skinModelNode != None: v = -1.0 pointValue.InsertValue(ids.GetId(0), v) pointValue.InsertValue(ids.GetId(1), v) pointValue.InsertValue(ids.GetId(2), v) inaccessibleArea = inaccessibleArea + area else: print("ERROR: Non-triangular cell.") score = accessibleArea if skinModelNode != None: skinModelNode.AddPointScalars(pointValue) skinModelNode.SetActivePointScalars( "Colors", vtk.vtkDataSetAttributes.SCALARS) skinModelNode.Modified() displayNode = skinModelNode.GetModelDisplayNode() displayNode.SetActiveScalarName("Colors") displayNode.SetScalarRange(0.0, 200.0) return (score, minDistance, minDistancePoint)