Difference between revisions of "Moffitt 2014"
From NAMIC Wiki
Line 53: | Line 53: | ||
input = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung/' | input = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung/' | ||
output = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung-png/' | output = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung-png/' | ||
− | for fn in range( | + | for fn in range(len(input)): |
− | flong = "%06i" % (fn | + | flong = "%06i" % (fn) |
print flong | print flong | ||
Image.open(input+str(fn)+'.pgm').save(output+flong+'.png') | Image.open(input+str(fn)+'.pgm').save(output+flong+'.png') | ||
+ | Once converted to PNG, run the following script to convert the label slices into 3d format: | ||
+ | import sys, os, slicer, vtk | ||
+ | <pre> | ||
+ | ''' | ||
+ | Usage: | ||
+ | Slicer.exe --no-splash --no-main-window --python-script converter.py <directory with DICOM files> <directory with segmentation files> <output directory> | ||
+ | |||
+ | ''' | ||
+ | |||
+ | dcmDir = sys.argv[1] | ||
+ | segDir = sys.argv[2] | ||
+ | outputDir = sys.argv[3] | ||
+ | |||
+ | print(dcmDir) | ||
+ | print(segDir) | ||
+ | print(outputDir) | ||
+ | |||
+ | # get lists of DICOM and seg files with full path names | ||
+ | # DICOM files fill be sorted by the slice positions for volume reconstruction | ||
+ | dcmList = [] | ||
+ | for dcm in os.listdir(dcmDir): | ||
+ | if len(dcm)-dcm.rfind('.dcm') == 4: | ||
+ | dcmList.append(dcmDir+'/'+dcm) | ||
+ | |||
+ | # segmentation files need to be sorted, | ||
+ | # assuming here that alphabetical sorting is consistent with the sorting | ||
+ | # applied to DICOM files | ||
+ | segList = [] | ||
+ | for seg in os.listdir(segDir): | ||
+ | # assume segmentations are saved in PNG format, change here if another one | ||
+ | segList.append(segDir+'/'+seg) | ||
+ | segList.sort() | ||
+ | segList.reverse() | ||
+ | |||
+ | print(str(segList)) | ||
+ | |||
+ | scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() | ||
+ | |||
+ | # index input DICOM series | ||
+ | indexer = ctk.ctkDICOMIndexer() | ||
+ | indexer.addDirectory(slicer.dicomDatabase, dcmDir) | ||
+ | indexer.waitForImportFinished() | ||
+ | |||
+ | loadables = scalarVolumePlugin.examine([dcmList]) | ||
+ | |||
+ | if len(loadables) == 0: | ||
+ | print 'Could not parse the DICOM Study!' | ||
+ | exit() | ||
+ | |||
+ | # load input DICOM volume | ||
+ | dcmVolume = scalarVolumePlugin.load(loadables[0]) | ||
+ | |||
+ | # save DICOM volume as single file nrrd format | ||
+ | dcmStorage = slicer.vtkMRMLVolumeArchetypeStorageNode() | ||
+ | dcmStorage.SetWriteFileFormat('nrrd') | ||
+ | dcmStorage.SetFileName(os.path.join(outputDir,'dcm_volume.nrrd')) | ||
+ | dcmStorage.WriteData(dcmVolume) | ||
+ | |||
+ | print('Before instantiating') | ||
+ | segStorage = slicer.vtkMRMLVolumeArchetypeStorageNode() | ||
+ | segStorage.ResetFileNameList() | ||
+ | for seg in segList: | ||
+ | segStorage.AddFileName(seg) | ||
+ | segStorage.SetFileName(segList[0]) | ||
+ | print(str(segList)) | ||
+ | segStorage.SetSingleFile(0) | ||
+ | segVolume = slicer.vtkMRMLScalarVolumeNode() | ||
+ | print('Before reading') | ||
+ | segStorage.ReadData(segVolume) | ||
+ | print('After reading') | ||
+ | |||
+ | # convert to unsigned short pixel type | ||
+ | cast = vtk.vtkImageCast() | ||
+ | if vtk.vtkVersion().GetVTKMajorVersion() < 6: | ||
+ | cast.SetInput(segVolume.GetImageData()) | ||
+ | else: | ||
+ | cast.SetInputData(segVolume.GetImageData()) | ||
+ | cast.SetOutputScalarTypeToShort() | ||
+ | cast.Update() | ||
+ | |||
+ | # assign segmentation the same geometry as the DICOM volume | ||
+ | ijkToRAS = vtk.vtkMatrix4x4() | ||
+ | dcmVolume.GetIJKToRASMatrix(ijkToRAS) | ||
+ | |||
+ | segVolume.SetIJKToRASMatrix(ijkToRAS) | ||
+ | segVolume.SetAndObserveImageData(cast.GetOutput()) | ||
+ | |||
+ | # save segmentation as a 3d volume in nrrd format | ||
+ | segStorage.SetWriteFileFormat('nrrd') | ||
+ | segStorage.SetFileName(os.path.join(outputDir,'seg_volume.nrrd')) | ||
+ | segStorage.WriteData(segVolume) | ||
+ | |||
+ | sys.exit() | ||
+ | </pre> | ||
Raul San Jose: Airway inspector development in Slicer: http://lmi.bwh.harvard.edu/~rjosest/ | Raul San Jose: Airway inspector development in Slicer: http://lmi.bwh.harvard.edu/~rjosest/ |
Revision as of 16:59, 22 December 2014
Home < Moffitt 2014Logistics
SPL personnel: Andrey Fedorov, Ph.D.
Local hosts: Robert Gillies, Ph.D., Olya Grove, Ph.D.
Dates: Dec 16-17, 2014
Working meeting times:
- Tue 3-4pm
- Wed 9-10:30am
- Wed 1-3pm
Notes and references for the meeting
- Prerequisites: nightly and stable build of Slicer, Windows 64bit http://download.slicer.org
- DICOM RT conversion
- Prerequisites: SlicerRT extension, conversion script added in the last week's version of SlicerRT
- extensions are located on Windows in
C:\Users\<your_user_name>\AppData\Roaming\NA-MIC
- to enable showing hidden folders see http://windows.microsoft.com/en-us/windows/show-hidden-files#show-hidden-files=windows-7
- running Slicer python script from the command line:
Slicer.exe --no-splash --no-main-window --python-script <script> <arguments>
- to see console messages (in python interactor), run without --no-main-window flag
- make sure script name has '/', not '\', as path separator
- make sure image volume for the RTSTRUCT is in the input folder
- Lung and lesion segmentation
- FastMarching effect in Editor module
- GrowCut effect in Editor module, FastGrowCut extension
- Interfacing Matlab
- MatlabBridge extension
- Tutorial, documentation, teaching videos: http://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/MatlabBridge
- General introduction user tutorials: http://wiki.slicer.org/slicerWiki/index.php/Documentation/4.3/Training#General_Introduction
- Developer tutorials: http://wiki.slicer.org/slicerWiki/index.php/Documentation/4.3/Training#Tutorials_for_software_developers
- Feature extraction: HeterogeneityCAD extension: http://wiki.slicer.org/slicerWiki/index.php/Documentation/Nightly/Modules/HeterogeneityCAD
Batch processing needed:
- Load DICOM volume and corresponding label
- Extract features
- save features in txt file
Follow-up items
- Lung and nodule segmentation and feature extraction screencast: http://youtu.be/koHKAJWGNhU
- Scripts for converting legacy PGM segmentations into Slicer-compatible format:
First, convert PGM into PNG (PGM is not recognized by Slicer image readers). Python script to do this is below. Save as a .py file, make sure python is installed, run from command line (modify the input and output directories as needed):
import Image input = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung/' output = '/Users/fedorov/ImageData/Moffitt/Label_conversion/MOFFITT/P2/lung-png/' for fn in range(len(input)): flong = "%06i" % (fn) print flong Image.open(input+str(fn)+'.pgm').save(output+flong+'.png')
Once converted to PNG, run the following script to convert the label slices into 3d format:
import sys, os, slicer, vtk
''' Usage: Slicer.exe --no-splash --no-main-window --python-script converter.py <directory with DICOM files> <directory with segmentation files> <output directory> ''' dcmDir = sys.argv[1] segDir = sys.argv[2] outputDir = sys.argv[3] print(dcmDir) print(segDir) print(outputDir) # get lists of DICOM and seg files with full path names # DICOM files fill be sorted by the slice positions for volume reconstruction dcmList = [] for dcm in os.listdir(dcmDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(dcmDir+'/'+dcm) # segmentation files need to be sorted, # assuming here that alphabetical sorting is consistent with the sorting # applied to DICOM files segList = [] for seg in os.listdir(segDir): # assume segmentations are saved in PNG format, change here if another one segList.append(segDir+'/'+seg) segList.sort() segList.reverse() print(str(segList)) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() # index input DICOM series indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dcmDir) indexer.waitForImportFinished() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() # load input DICOM volume dcmVolume = scalarVolumePlugin.load(loadables[0]) # save DICOM volume as single file nrrd format dcmStorage = slicer.vtkMRMLVolumeArchetypeStorageNode() dcmStorage.SetWriteFileFormat('nrrd') dcmStorage.SetFileName(os.path.join(outputDir,'dcm_volume.nrrd')) dcmStorage.WriteData(dcmVolume) print('Before instantiating') segStorage = slicer.vtkMRMLVolumeArchetypeStorageNode() segStorage.ResetFileNameList() for seg in segList: segStorage.AddFileName(seg) segStorage.SetFileName(segList[0]) print(str(segList)) segStorage.SetSingleFile(0) segVolume = slicer.vtkMRMLScalarVolumeNode() print('Before reading') segStorage.ReadData(segVolume) print('After reading') # convert to unsigned short pixel type cast = vtk.vtkImageCast() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(segVolume.GetImageData()) else: cast.SetInputData(segVolume.GetImageData()) cast.SetOutputScalarTypeToShort() cast.Update() # assign segmentation the same geometry as the DICOM volume ijkToRAS = vtk.vtkMatrix4x4() dcmVolume.GetIJKToRASMatrix(ijkToRAS) segVolume.SetIJKToRASMatrix(ijkToRAS) segVolume.SetAndObserveImageData(cast.GetOutput()) # save segmentation as a 3d volume in nrrd format segStorage.SetWriteFileFormat('nrrd') segStorage.SetFileName(os.path.join(outputDir,'seg_volume.nrrd')) segStorage.WriteData(segVolume) sys.exit()
Raul San Jose: Airway inspector development in Slicer: http://lmi.bwh.harvard.edu/~rjosest/