Difference between revisions of "Moffitt 2014"
From NAMIC Wiki
(Created page with '==Notes for the meeting with users and developers== * Prerequisites: '''nightly''' and '''stable''' build of Slicer, Windows 64bit http://download.slicer.org * DICOM RT conversi…') |
m (Text replacement - "http://www.slicer.org/slicerWiki/index.php/" to "https://www.slicer.org/wiki/") |
||
(16 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | ==Notes for the meeting | + | ==Logistics== |
+ | 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 | ||
+ | |||
+ | [[File:Moffitt-Slicer-Workshop-2014-pic1.jpg|350px]] | ||
+ | [[File:Moffitt-Slicer-Workshop-2014-pic2.jpg|350px]] | ||
+ | |||
+ | [[File:Moffitt-Slicer-Workshop-2014-pic3.jpg|350px]] | ||
+ | [[File:Moffitt-Slicer-Workshop-2014-pic4.jpg|350px]] | ||
+ | |||
+ | [[File:Moffitt-Slicer-Workshop-2014-pic5.jpg|350px]] | ||
+ | |||
+ | |||
+ | ==Notes and references for the meeting== | ||
* Prerequisites: '''nightly''' and '''stable''' build of Slicer, Windows 64bit http://download.slicer.org | * Prerequisites: '''nightly''' and '''stable''' build of Slicer, Windows 64bit http://download.slicer.org | ||
* DICOM RT conversion | * DICOM RT conversion | ||
− | ** Prerequisites: SlicerRT extension, conversion script | + | ** Prerequisites: SlicerRT extension, conversion script added in the last week's version of SlicerRT |
** extensions are located on Windows in | ** extensions are located on Windows in | ||
C:\Users\<your_user_name>\AppData\Roaming\NA-MIC | 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 | ** 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> | + | ** 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 script name has '/', not '\', as path separator | ||
** make sure image volume for the RTSTRUCT is in the input folder | ** make sure image volume for the RTSTRUCT is in the input folder | ||
Line 17: | Line 40: | ||
* Interfacing Matlab | * Interfacing Matlab | ||
** MatlabBridge extension | ** MatlabBridge extension | ||
− | ** Tutorial, documentation, teaching videos: | + | ** Tutorial, documentation, teaching videos: https://www.slicer.org/wiki/Documentation/Nightly/Extensions/MatlabBridge |
* General introduction user tutorials: http://wiki.slicer.org/slicerWiki/index.php/Documentation/4.3/Training#General_Introduction | * 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 | * 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): | ||
+ | |||
+ | <pre> | ||
+ | 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') | ||
+ | </pre> | ||
+ | |||
+ | 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/ | ||
+ | |||
+ | ==Slicer bugs identified during the visit== | ||
+ | * LabelStatistics does not work occasionally. Not always reproducible. Workaround suggested: Install IASEM extension, use "Label Object Statistics" module instead. | ||
+ | * Volume rendering of a segmented label volume is not automatically updated when editing is done: reproducible, bug reported: http://www.na-mic.org/Bug/view.php?id=3928 | ||
+ | * It seems that the image slice rendered in the 3d viewer does not go through the middle of the slice, at least when examined with slice segmentation volume rendered. May be related to existing issue: http://www.na-mic.org/Bug/view.php?id=3886 | ||
+ | * |
Latest revision as of 18:07, 10 July 2017
Home < Moffitt 2014Contents
Logistics
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: https://www.slicer.org/wiki/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/
Slicer bugs identified during the visit
- LabelStatistics does not work occasionally. Not always reproducible. Workaround suggested: Install IASEM extension, use "Label Object Statistics" module instead.
- Volume rendering of a segmented label volume is not automatically updated when editing is done: reproducible, bug reported: http://www.na-mic.org/Bug/view.php?id=3928
- It seems that the image slice rendered in the 3d viewer does not go through the middle of the slice, at least when examined with slice segmentation volume rendered. May be related to existing issue: http://www.na-mic.org/Bug/view.php?id=3886