Note
Click here to download the full example code
Measurements on a volumeΒΆ
Complete example with a specific graphical interface that embeds an Anatomist window and a matplotlib widget. Shows a 4D volume and a curve of the values in a selected voxel or the mean of values in a selected region.
from __future__ import absolute_import
import sys
import os
import weakref
import gc
import operator
import anatomist.direct.api as anatomist
from soma.qt_gui.qt_backend.QtCore import Qt, QPoint
from soma.qt_gui.qt_backend.QtGui import QSplitter, QListWidget, QTextEdit, \
QApplication
from soma import aims
from soma.qt_gui import qt_backend
import six
from six.moves import zip
from functools import reduce
qt_backend.init_matplotlib_backend()
import matplotlib
import numpy
import pylab
FigureCanvas = qt_backend.FigureCanvas
from matplotlib.figure import Figure
class MeasuresWindow(QSplitter):
def __init__(self, fileName, roiIterator=None, parent=None,
anatomistInstance=None):
QSplitter.__init__(self, Qt.Horizontal, parent)
if anatomistInstance is None:
# initialize Anatomist
self.anatomist = anatomist.Anatomist()
else:
self.anatomist = anatomistInstance
# open an axial window
self.aWindow = self.anatomist.createWindow(
'Axial', no_decoration=True)
self.aWindow.setParent(self)
if roiIterator is not None:
self.roiList = QListWidget(self)
self.maskIterators = []
# Iterate on each region
while roiIterator.isValid():
self.roiList.addItem(roiIterator.regionName())
maskIterator = roiIterator.maskIterator().get()
maskIterator.bucket = None
self.maskIterators.append(maskIterator)
next(roiIterator)
self.selectedBucket = None
self.roiList.currentRowChanged.connect(self.regionSelected)
else:
self.roiList = None
self.infoSplitter = QSplitter(Qt.Vertical, self)
self.info = QTextEdit(self.infoSplitter)
self.info.setReadOnly(True)
self.matplotFigure = Figure()
self.matplotAxes = self.matplotFigure.add_subplot(111)
# We want the axes cleared every time plot() is called
self.matplotAxes.hold(False)
self.matplotCanvas = FigureCanvas(self.matplotFigure)
self.matplotCanvas.setParent(self.infoSplitter)
self.matplotCanvas.updateGeometry()
self.anatomist.onCursorNotifier.add(self.clicked2)
self.resize(800, 600)
# Read the image
dir, base = os.path.split(fileName)
if dir:
self.setWindowTitle(base + ' (' + dir + ')')
else:
self.setWindowTitle(base)
# load any volume as a aims.Volume_* object
r = aims.Reader({'Volume': 'AimsData'})
self.volume = r.read(fileName)
self.interpolator = aims.aims.getLinearInterpolator(self.volume).get()
# convert the AimsData volume to Anatomist API
avol = self.anatomist.toAObject(self.volume)
avol.releaseAppRef()
# put volume in window
self.aWindow.addObjects(avol)
self._ignoreClicked = False
voxelSize = self.volume.header()['voxel_size']
tmp = self.volume.header()['volume_dimension']
volumeSize = [int(i) for i in tmp]
volumeCenter = [v * s / 2 for v, s in zip(volumeSize, voxelSize)]
self.clicked(volumeCenter)
infoHeight = self.info.sizeHint().height()
self.infoSplitter.setSizes([infoHeight, self.height() - infoHeight])
def clicked2(self, eventName, eventParameters):
self.clicked(eventParameters['position'], eventParameters['window'])
def clicked(self, posMM, aWindow=None):
posMM = [float(i) for i in posMM]
if self._ignoreClicked:
return
text = '<html><body>\n'
text += '<b>Coordinate millimeters:</b> %.2f, %.2f, %.2f, %.2f' % tuple(
posMM) + '<br/>\n'
voxelSize = self.volume.header()['voxel_size']
posVoxel = [int(round(i / j)) for i, j in zip(posMM, voxelSize)]
text += '<b>Coordinate voxels:</b> %d, %d, %d, %d' % tuple(
posVoxel) + '<br/>\n'
tmp = self.volume.header()['volume_dimension']
volumeSize = [int(i) for i in tmp]
if not [None for i in posVoxel if i < 0] and \
not [None for i, j in zip(posVoxel, volumeSize) if i >= j]:
text += '<b>Voxel value</b>: ' + \
str(self.volume.value(*posVoxel)) + '<br/>\n'
if volumeSize[3] > 1:
indices = numpy.arange(volumeSize[3])
# Extract values as numarray structure
values = self.interpolator.values(posVoxel[0] * voxelSize[0],
posVoxel[1] * voxelSize[1],
posVoxel[2] * voxelSize[2])
self.matplotAxes.plot(indices, numpy.array(values))
self.matplotCanvas.draw()
text += '</body></html>'
self.info.setText(text)
def regionSelected(self):
index = self.roiList.currentRow()
if index >= 0:
text = '<html><body>\n'
text += '<h2>' + \
six.text_type(self.roiList.item(index).text()) + '</h2>\n'
maskIterator = self.maskIterators[index]
if maskIterator.bucket is None:
roiCenter = aims.Point3df(0, 0, 0)
bucket = aims.BucketMap_VOID()
bucket.setSizeXYZT(
*list(maskIterator.voxelSize().items()) + (1,))
maskIterator.restart()
valid = 0
invalid = 0
sum = None
# Iterate on each point of a region
while maskIterator.isValid():
bucket[0][maskIterator.value()] = 1
p = maskIterator.valueMillimeters()
roiCenter += p
# Check if the point is in the image limit
if self.interpolator.isValid(p):
values = self.interpolator.values(p)
if sum is None:
sum = values
else:
sum = [s + v for s, v in zip(sum, values)]
valid += 1
else:
invalid += 1
next(maskIterator)
text += '<b>valid points:</b> ' + str(valid) + '<br/>\n'
text += '<b>invalid points:</b> ' + str(invalid) + '<br/>\n'
if valid:
means = [s / float(valid) for s in sum]
mean = reduce(operator.add, means) / len(means)
else:
means = []
mean = 'N/A'
text += '<b>mean:</b> ' + str(mean) + '<br/>\n'
text += '</body></html>'
maskIterator.text = text
# convert the BucketMap to Anatomist API
maskIterator.bucket = self.anatomist.toAObject(bucket)
maskIterator.bucket.releaseAppRef()
maskIterator.bucket.setName(
str(self.roiList.item(index).text()))
maskIterator.bucket.setChanged()
count = valid + invalid
if count:
maskIterator.roiCenter = [
c / count for c in roiCenter.items()]
else:
maskIterator.roiCenter = None
maskIterator.means = means
# put bucket in window
self.info.setText(maskIterator.text)
self.aWindow.addObjects([maskIterator.bucket])
# Set selected color to bucket
maskIterator.bucket.setMaterial(self.anatomist.Material(
diffuse=[1, 0, 0, 0.5],
lighting=0,
face_culling=1,
))
# Set unselected color to previously selected bucket
if self.selectedBucket is not None:
self.selectedBucket.setMaterial(
self.anatomist.Material(diffuse=[0, 0.8, 0.8, 0.8]))
self.selectedBucket = maskIterator.bucket
if maskIterator.roiCenter is not None:
self._ignoreClicked = True
self.aWindow.moveLinkedCursor(maskIterator.roiCenter)
self._ignoreClicked = False
if len(maskIterator.means) > 1:
indices = numpy.arange(len(maskIterator.means))
self.matplotAxes.plot(
indices, numpy.array(maskIterator.means))
self.matplotCanvas.draw()
if __name__ == '__main__':
qApp = QApplication(sys.argv)
if len(sys.argv) == 3:
roiIterator = aims.aims.getRoiIterator(sys.argv[2]).get()
w = MeasuresWindow(sys.argv[1], roiIterator=roiIterator)
else:
w = MeasuresWindow(sys.argv[1])
w.show()
anatomist.Anatomist().getControlWindow().hide()
qApp.exec_()
del w
Total running time of the script: ( 0 minutes 0.000 seconds)