Handle additional images as numpy arrays in Slicer

python

(Virginia ) #1

Hello,

In order to work on my imported MR image, I need to create a Python script in which I need to import as well (separately):

  • A txt file with numeric data
  • An image that should be handled as an array
    Would it be possible to do that in Slicer with Python? I’ve seen that to work with Images, you need to import at least cv2 or Image and they both aren’t available through the execution of “import &”. That leads me to the problem I already reported in a different topic with the importation of “medpy” module (Import medpy fails).

In particular, I’d like to know whether:

  • It’d be possible to perform the importation through a button, and add several filters that control the validity of the imported data i.e.: the size of the image
  • It’d be possible to convert the image (a JPG image) to an array with the available modules, and without that image being the volume added to Slicer

The reason why that image needs to be imported through the script is that it’s a fixed image (fixed folder and name) and I only want it to extract some coordinates. I don’t need to process it as an image, nor displaying it.

Thank you in advance for any input about this.

Virginia Fernández


(Steve Pieper) #2

Hi @virginia_fgc I see there was never a reply to this (sorry about that) - were you able to find the information you needed?


(Virginia ) #3

Hi Steve,

The processing I had to apply to the other image I was talking about was far too complex to be programmed in Python/Slicer, thus I decided to handle that process in Matlab to get an output .txt file with coordinates. Basically, I would like to import numeric data from two .txt files into Slicer so that I can tag the voxels from my volume with the coordinates / values stored in the .txt.

I still haven’t found out how to do it. If I do I will update this issue. Any help is kindly appreciated.

Thank you for the reply, and best regards

Virginia


(Andras Lasso) #4

I’m not exactly sure what you would like to do, but setting voxel coordinates listed in a file to specific value is a single-line operation in Python:

# Specify some input data

import SampleData
volume=SampleData.SampleDataLogic().downloadMRHead()
volumeArray=slicer.util.arrayFromVolume(volume)

coords_KJI=[(47,58,60,65),(127,127,127,127),(142,142,142,142)]
voxelValue = 250

# Set voxel values at specified coordinates
volumeArray[coords_KJI] = voxelValue

# Update display (see 4 voxels near the center of the red slice view becoming very bright as a result)
slicer.util.arrayFromVolumeModified(volume)

It should not be much more complicated if you need to set different value for each point.

If you need to fill a complete volume (interpolate between known points) then you can use VTK: create a point set with associated point scalar data, apply Delaunay triangulation, and use probe filter to create a volume. This would be probably a few ten lines of code.


(Virginia ) #5

Hello,

Thank you very much for that valuable answer.
However, I am more concerned with the importing itself. I need to create a loadable module, that needs to have a volume selector (I have seen how to do that in the Slicer tutorials), as well as two buttons that load the content of .txt files into two different arrays. One of thes texts is the one containing the coordinates.
I know how to do process that information (in Python, with open, readline etc.), but not how to do it in an ‘interactive’ way.

The workflow would be:

  1. User selects the "Import TEXT FILE 1 Button’
  2. A window opens with a File Explorer that enables the user to select a txt
  3. The .txt is copied into a variable (I guess that this can be done with ‘open’ if step 2 provides the path).

Is there a way to perform step 2 and get the path so that 3 can be executed thereafter?

Thank you


(Andras Lasso) #6

You can use ctk.ctkPathLineEdit() widget to get input paths. See for example how it is done in the DICOM Patcher module.


(Virginia ) #7

Dear Andras,

Apologises for not having replied to this before. Thank you very much for the answer. It solved my issue. Instead of using the directories, I used the Files directly.

#create input selector for Files
self.inputFileSelector_myIS = ctk.ctkPathLineEdit()
self.inputFileSelector_myIS = ctk.ctkPathLineEdit.Files

#And then was able to get the path (directory+name) on the function with:
path = self.inputFileSelector_myIS.currentPath
#And open it with:
my_file = open(path)

Only one additional question. I have noticed that there’s a default value for the file that is always displayed when I run Slicer. That default value has not been defined in the code, yet it is always appearing and can be confusing. Is there a way to leave the space blank?

Thank you very much and kind regards,

Virginia


(Andras Lasso) #8

File history is a very useful feature, so I would recommend that you keep it. You have full control over it - see documentation of settingKey property.


(saima safdar) #9

Hi Andras,
I want to display the array data in the red slice view. The outputArrayImage is an np multidimensional array with floating data. I need to display it. I am pasting the code here. I see blank output in slicer.

volumeNode = slicer.mrmlScene.AddNewNodeByClass(‘vtkMRMLScalarVolumeNode’)
volumeNode.CreateDefaultDisplayNodes()
updateVolumeFromArray(volumeNode, outputArrayImage)
setSliceViewerLayers(background=volumeNode)

red_logic = slicer.app.layoutManager().sliceWidget("Red").sliceLogic()
red_cn = red_logic.GetSliceCompositeNode()
red_logic.GetSliceCompositeNode().SetBackgroundVolumeID(volumeNode.GetID())
slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)
display()

(Andras Lasso) #10

You can use slicer.util.updateVolumeFromArray to set voxels of a volume node from a numpy array.