Skip to content

Commit 03e0310

Browse files
committed
add tests for all layers implementing getPosInfo and also for 5d data. Optimize the functions in layers
1 parent 8a0de3c commit 03e0310

File tree

3 files changed

+240
-163
lines changed

3 files changed

+240
-163
lines changed

tests/quadStatusBar_test.py

+192-91
Original file line numberDiff line numberDiff line change
@@ -21,67 +21,120 @@
2121
###############################################################################
2222
import pytest
2323
from PyQt5.QtWidgets import QMainWindow
24-
from PyQt5.QtCore import QPointF, Qt
24+
from PyQt5.QtCore import QPointF, Qt, QCoreApplication
2525
from PyQt5.QtGui import QColor
2626

2727
import numpy as np
2828
import vigra
2929
from ilastik.applets.layerViewer.layerViewerGui import LayerViewerGui
30-
from lazyflow.operators.opReorderAxes import OpReorderAxes
3130
from volumina.volumeEditor import VolumeEditor
3231
from volumina.volumeEditorWidget import VolumeEditorWidget
3332
from volumina.layerstack import LayerStackModel
3433
from volumina.pixelpipeline.datasources import LazyflowSource
35-
from volumina.layer import AlphaModulatedLayer
34+
from volumina.layer import AlphaModulatedLayer, ColortableLayer, NormalizableLayer, RGBALayer
3635
from lazyflow.graph import Operator, InputSlot, OutputSlot, Graph
3736

37+
# taken from https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/
38+
default16_new = [
39+
QColor(0, 0, 0, 0).rgba(), # transparent
40+
QColor(255, 225, 25).rgba(), # yellow
41+
QColor(0, 130, 200).rgba(), # blue
42+
QColor(230, 25, 75).rgba(), # red
43+
QColor(70, 240, 240).rgba(), # cyan
44+
QColor(60, 180, 75).rgba(), # green
45+
QColor(250, 190, 190).rgba(), # pink
46+
QColor(170, 110, 40).rgba(), # brown
47+
QColor(145, 30, 180).rgba(), # purple
48+
QColor(0, 128, 128).rgba(), # teal
49+
QColor(245, 130, 48).rgba(), # orange
50+
QColor(240, 50, 230).rgba(), # magenta
51+
QColor(210, 245, 60).rgba(), # lime
52+
QColor(255, 215, 180).rgba(), # coral
53+
QColor(230, 190, 255).rgba(), # lavender
54+
QColor(128, 128, 128).rgba(), # gray
55+
]
3856

3957
class MainWindow(QMainWindow):
4058
def __init__(self):
4159
super().__init__()
4260
self.volumeEditorWidget = VolumeEditorWidget(parent=self)
4361

4462

45-
class OpTestImgaeSlots(Operator):
63+
class OpTestImageSlots(Operator):
4664
"""test operator, containing 3-dim test data"""
47-
48-
GrayscaleImageIn = InputSlot()
49-
Label1ImageIn = InputSlot()
50-
Label2ImageIn = InputSlot()
51-
52-
GrayscaleImageOut = OutputSlot()
53-
Label1ImageOut = OutputSlot()
54-
Label2ImageOut = OutputSlot()
65+
GrayscaleIn = InputSlot()
66+
RgbaIn = InputSlot(level=1)
67+
ColorTblIn1 = InputSlot()
68+
ColorTblIn2 = InputSlot()
69+
AlphaModulatedIn = InputSlot()
70+
Segmentation1In = InputSlot()
71+
Segmentation2In = InputSlot()
72+
73+
GrayscaleOut = OutputSlot()
74+
RgbaOut = OutputSlot(level=1)
75+
ColorTblOut1 = OutputSlot()
76+
ColorTblOut2 = OutputSlot()
77+
AlphaModulatedOut = OutputSlot()
78+
Segmentation1Out = OutputSlot()
79+
Segmentation2Out = OutputSlot()
5580

5681
def __init__(self, *args, **kwargs):
5782
super().__init__(*args, **kwargs)
5883

59-
width, height, depth = 300, 200, 40
60-
61-
# create 2-dimensional images
62-
grayscaleImageSource = np.random.randint(0, 255, (depth, height, width, 1))
63-
label1ImageSource = np.zeros((depth, height, width, 3), dtype=np.int32)
64-
label2ImageSource = np.zeros((depth, height, width, 3), dtype=np.int32)
65-
66-
for z, set1 in enumerate(grayscaleImageSource[:, :, :, 0]):
67-
for y, set2 in enumerate(set1):
68-
for x, set3 in enumerate(set2):
69-
if z in range(5, 20) and y in range(20, 30) and x in range(80, 140):
70-
label1ImageSource[z, y, x, :] = [255, 255, 255]
71-
if z in range(25, 37) and y in range(100, 150) and x in range(10, 60):
72-
label2ImageSource[z, y, x, :] = [255, 255, 255]
73-
74-
self.GrayscaleImageIn.setValue(grayscaleImageSource, notify=False, check_changed=False)
75-
self.Label1ImageIn.setValue(label1ImageSource, notify=False, check_changed=False)
76-
self.Label2ImageIn.setValue(label2ImageSource, notify=False, check_changed=False)
77-
78-
self.GrayscaleImageIn.meta.axistags = vigra.defaultAxistags("tzyxc"[5 - len(self.GrayscaleImageIn.meta.shape):])
79-
self.Label1ImageIn.meta.axistags = vigra.defaultAxistags("tzyxc"[5 - len(self.Label1ImageIn.meta.shape):])
80-
self.Label2ImageIn.meta.axistags = vigra.defaultAxistags("tzyxc"[5 - len(self.Label2ImageIn.meta.shape):])
81-
82-
self.GrayscaleImageOut.connect(self.GrayscaleImageIn)
83-
self.Label1ImageOut.connect(self.Label1ImageIn)
84-
self.Label2ImageOut.connect(self.Label2ImageIn)
84+
time, width, height, depth = 4, 300, 200, 10
85+
self.dataShape = (time, width, height, depth, 1)
86+
shape4d = (time, width, height, depth, 1)
87+
shape5d1 = (4, time, width, height, depth, 1)
88+
shape5d2 = (time, width, height, depth, 3)
89+
90+
# create images
91+
grayscaleImage = np.random.randint(0, 255, shape4d)
92+
rgbaImage = np.random.randint(0, 255, shape5d1)
93+
colorTblImage1 = np.random.randint(0, 10, shape4d)
94+
colorTblImage2 = np.random.randint(0, 10, shape4d)
95+
AlphaModImage = np.zeros(shape5d2, dtype=np.int32)
96+
Segment1Image = np.zeros(shape5d2, dtype=np.int32)
97+
Segment2Image = np.zeros(shape5d2, dtype=np.int32)
98+
99+
# define some dummy segmentations
100+
for t in range(time):
101+
for x in range(width):
102+
for y in range(height):
103+
for z in range(depth):
104+
if t==3 and z in range(5, 9) and y in range(20, 30) and x in range(80, 140):
105+
Segment1Image[t, x, y, z, :] = [255, 255, 255]
106+
AlphaModImage[t, x, y, z, :] = [255, 255, 255]
107+
colorTblImage1[t, x, y, z, :] = 0
108+
if t==1 and z in range(0, 6) and y in range(100, 150) and x in range(10, 60):
109+
Segment2Image[t, x, y, z, :] = [255, 255, 255]
110+
colorTblImage2[t, x, y, z, :] = 0
111+
112+
self.GrayscaleIn.setValue(grayscaleImage, notify=False, check_changed=False)
113+
self.RgbaIn.setValues(rgbaImage)
114+
self.ColorTblIn1.setValue(colorTblImage1, notify=False, check_changed=False)
115+
self.ColorTblIn2.setValue(colorTblImage2, notify=False, check_changed=False)
116+
self.AlphaModulatedIn.setValue(AlphaModImage, notify=False, check_changed=False)
117+
self.Segmentation1In.setValue(Segment1Image, notify=False, check_changed=False)
118+
self.Segmentation2In.setValue(Segment2Image, notify=False, check_changed=False)
119+
120+
atags3d = "txyzc"[5 - len(shape4d):]
121+
atags4d2 = "txyzc"[5 - len(shape5d2):]
122+
self.GrayscaleIn.meta.axistags = vigra.defaultAxistags(atags3d)
123+
for i in range(4):
124+
self.RgbaIn[i].meta.axistags = vigra.defaultAxistags(atags3d)
125+
self.ColorTblIn1.meta.axistags = vigra.defaultAxistags(atags3d)
126+
self.ColorTblIn2.meta.axistags = vigra.defaultAxistags(atags3d)
127+
self.AlphaModulatedIn.meta.axistags = vigra.defaultAxistags(atags4d2)
128+
self.Segmentation1In.meta.axistags = vigra.defaultAxistags(atags4d2)
129+
self.Segmentation2In.meta.axistags = vigra.defaultAxistags(atags4d2)
130+
131+
self.GrayscaleOut.connect(self.GrayscaleIn)
132+
self.RgbaOut.connect(self.RgbaIn)
133+
self.ColorTblOut1.connect(self.ColorTblIn1)
134+
self.ColorTblOut2.connect(self.ColorTblIn2)
135+
self.AlphaModulatedOut.connect(self.AlphaModulatedIn)
136+
self.Segmentation1Out.connect(self.Segmentation1In)
137+
self.Segmentation2Out.connect(self.Segmentation2In)
85138

86139

87140
class TestSpinBoxImageView(object):
@@ -98,42 +151,47 @@ def setupClass(self, qtbot):
98151
self.layerStack = LayerStackModel()
99152

100153
g = Graph()
101-
self.op = OpTestImgaeSlots(graph=g)
102-
103-
self.grayscaleLayer = LayerViewerGui._create_grayscale_layer_from_slot(self.op.GrayscaleImageOut, 1)
104-
self.labelLayer1 = AlphaModulatedLayer(LazyflowSource(self.op.Label1ImageOut), tintColor=QColor(Qt.cyan),
105-
range=(0, 255), normalize=(0, 255))
106-
self.labelLayer2 = AlphaModulatedLayer(LazyflowSource(self.op.Label2ImageOut), tintColor=QColor(Qt.yellow),
107-
range=(0, 255), normalize=(0, 255))
108-
109-
self.labelLayer1.name = "Segmentation (Label 1)"
110-
self.labelLayer2.name = "Segmentation (Label 2)"
154+
self.op = OpTestImageSlots(graph=g)
155+
156+
self.grayscaleLayer = LayerViewerGui._create_grayscale_layer_from_slot(self.op.GrayscaleOut, 1)
157+
self.segLayer1 = AlphaModulatedLayer(LazyflowSource(self.op.Segmentation1Out), tintColor=QColor(Qt.cyan),
158+
range=(0, 255), normalize=(0, 255))
159+
self.segLayer2 = AlphaModulatedLayer(LazyflowSource(self.op.Segmentation2Out), tintColor=QColor(Qt.yellow),
160+
range=(0, 255), normalize=(0, 255))
161+
self.alphaModLayer = AlphaModulatedLayer(LazyflowSource(self.op.AlphaModulatedOut),
162+
tintColor=QColor(Qt.magenta), range=(0, 255), normalize=(0, 255))
163+
self.colorTblLayer1 = ColortableLayer(LazyflowSource(self.op.ColorTblOut1), default16_new)
164+
self.colorTblLayer2 = ColortableLayer(LazyflowSource(self.op.ColorTblOut2), default16_new)
165+
self.rgbaLayer = RGBALayer(red=LazyflowSource(self.op.RgbaOut[0]), green=LazyflowSource(self.op.RgbaOut[1]),
166+
blue=LazyflowSource(self.op.RgbaOut[2]), alpha=LazyflowSource(self.op.RgbaOut[3]))
167+
self.emptyRgbaLayer = RGBALayer()
168+
169+
self.segLayer1.name = "Segmentation (Label 1)"
170+
self.segLayer2.name = "Segmentation (Label 2)"
171+
self.grayscaleLayer.name = "Raw Input"
172+
self.colorTblLayer1.name = "Labels"
173+
self.colorTblLayer2.name = "pos info in Normalizable"
174+
self.rgbaLayer.name = "rgba layer"
175+
self.emptyRgbaLayer.name = "empty rgba layer"
176+
self.alphaModLayer.name = "alpha modulated layer"
111177

112178
self.layerStack.append(self.grayscaleLayer)
113-
self.layerStack.append(self.labelLayer1)
114-
self.layerStack.append(self.labelLayer2)
115-
116-
activeOutSlot = self.op.GrayscaleImageOut # take any out slot here
117-
if activeOutSlot.ready() and activeOutSlot.meta.axistags is not None:
118-
# Use an OpReorderAxes adapter to transpose the shape for us.
119-
op5 = OpReorderAxes(graph=g)
120-
op5.Input.connect(activeOutSlot)
121-
op5.AxisOrder.setValue('txyzc')
122-
shape = op5.Output.meta.shape
123-
124-
# We just needed the op to determine the transposed shape.
125-
# Disconnect it so it can be garbage collected.
126-
op5.Input.disconnect()
127-
op5.cleanUp()
179+
self.layerStack.append(self.segLayer1)
180+
self.layerStack.append(self.segLayer2)
181+
self.layerStack.append(self.colorTblLayer1)
182+
self.layerStack.append(self.colorTblLayer2)
183+
self.layerStack.append(self.rgbaLayer)
184+
self.layerStack.append(self.emptyRgbaLayer)
185+
self.layerStack.append(self.alphaModLayer)
128186

129187
self.editor = VolumeEditor(self.layerStack, self.main)
130188
self.editorWidget = self.main.volumeEditorWidget
131189
self.editorWidget.init(self.editor)
132190

133-
self.editor.dataShape = shape
191+
self.editor.dataShape = self.op.dataShape
134192

135-
# Find the xyz midpoint
136-
midpos5d = [x // 2 for x in shape]
193+
# Find the xyz origin
194+
midpos5d = [x // 2 for x in self.op.dataShape]
137195
# center viewer there
138196
# set xyz position
139197
midpos3d = midpos5d[1:4]
@@ -143,18 +201,23 @@ def setupClass(self, qtbot):
143201
self.editor.navCtrl.changeSliceAbsolute(midpos3d[i], i)
144202

145203
self.main.setCentralWidget(self.editorWidget)
204+
self.main.setFixedSize(1000, 800)
146205
self.main.show()
147206
self.qtbot.addWidget(self.main)
148207

149208
def testAddingAndRemovingPosVal(self):
150209
assert 0 == len(self.editorWidget.quadViewStatusBar.layerValueWidgets)
151210

152211
for layer in self.layerStack:
212+
layer.visible = True
153213
if not layer.showPosValue:
154214
layer.showPosValue = True
155215
if not layer.visible:
156216
layer.visible = True
157217

218+
for i in range(30):
219+
QCoreApplication.processEvents()
220+
158221
for layer in self.layerStack:
159222
assert layer in self.editorWidget.quadViewStatusBar.layerValueWidgets
160223

@@ -174,47 +237,85 @@ def testLayerPositionValueStrings(self):
174237
if not layer.visible:
175238
layer.visible = True
176239

177-
x, y, z = 90, 25, 10
240+
t, x, y, z = 3, 90, 25, 6
241+
242+
grayValidationString = "Raw I.:" + str(self.op.GrayscaleIn.value[t, x, y, z, 0])
243+
labelValidationString = "Label 1"
244+
colorTbl1ValidationString = "-"
245+
colorTbl2ValidationString = "pos i. i. N.:" + str(self.op.ColorTblOut2.value[t, x, y, z, 0])
246+
rgbaValidationString = "rgba l.:{};{};{};{}".format(*[str(slot.value[t, x, y, z, 0]) for slot in self.op.RgbaIn])
247+
emptyRgbaValidationString = "empty r. l.:0;0;0;255"
248+
alphaModValidationString = "alpha m. l.:" + str(self.op.AlphaModulatedOut.value[t, x, y, z, 0])
178249

179-
posVal = 255-int(self.op.GrayscaleImageIn.value[z, y, x, 0])
180-
grayValidationStrings = ["Gray:" + str(posVal), "Gray:" + str(posVal+1), "Gray:" + str(posVal-1)]
181-
label1ValidationString = "Label 1"
182-
label2ValidationString = "Label 2"
183250

184251
signal = self.editor.posModel.cursorPositionChanged
185252
with self.qtbot.waitSignal(signal, timeout=1000):
186253
self.editor.navCtrl.changeSliceAbsolute(z, 2)
254+
self.editor.navCtrl.changeTime(t)
187255

188-
# After change of crosshair positions tiles are marked dirty.
189-
self.updateAllTiles(self.editor.imageScenes) # Wait for all tiles being refreshed
256+
QCoreApplication.processEvents()
257+
QCoreApplication.processEvents()
258+
QCoreApplication.processEvents()
259+
QCoreApplication.processEvents()
190260

191-
signals = [self.editorWidget.quadViewStatusBar.layerValueWidgets[self.grayscaleLayer].textChanged,
192-
self.editorWidget.quadViewStatusBar.layerValueWidgets[self.labelLayer1].textChanged]
193-
with self.qtbot.waitSignals(signals, timeout=1000):
194-
self.editor.navCtrl.positionDataCursor(QPointF(x, y), 2)
195261

196-
self.updateAllTiles(self.editor.imageScenes) # Wait for all tiles being refreshed
262+
self.editor.navCtrl.positionDataCursor(QPointF(0, 0), 2)
197263

264+
self.editor.navCtrl.positionDataCursor(QPointF(x, y), 2)
265+
266+
assert self.editorWidget.quadViewStatusBar.xSpinBox.value() == x
267+
assert self.editorWidget.quadViewStatusBar.ySpinBox.value() == y
268+
assert self.editorWidget.quadViewStatusBar.zSpinBox.value() == z
269+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
270+
self.grayscaleLayer].text() == grayValidationString
271+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
272+
self.segLayer1].text() == labelValidationString
198273
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
199-
self.grayscaleLayer].text() in grayValidationStrings
200-
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[self.labelLayer1].text() == label1ValidationString
274+
self.segLayer2].text() == labelValidationString
275+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
276+
self.colorTblLayer1].text() == colorTbl1ValidationString
277+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
278+
self.colorTblLayer2].text() == colorTbl2ValidationString
279+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
280+
self.rgbaLayer].text() == rgbaValidationString
281+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
282+
self.emptyRgbaLayer].text() == emptyRgbaValidationString
283+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
284+
self.alphaModLayer].text() == alphaModValidationString
201285

202-
x, y, z = 39, 130, 30
286+
t, x, y, z = 1, 39, 130, 3
203287

204-
posVal = 255-int(self.op.GrayscaleImageIn.value[z, y, x, 0])
205-
grayValidationStrings = ["Gray:" + str(posVal), "Gray:" + str(posVal+1), "Gray:" + str(posVal-1)]
288+
grayValidationString = "Raw I.:" + str(self.op.GrayscaleIn.value[t, x, y, z, 0])
289+
labelValidationString = "Label 2"
290+
colorTbl1ValidationString = "Labels:" + str(self.op.ColorTblIn1.value[t, x, y, z, 0])
291+
colorTbl2ValidationString = "pos i. i. N.:" + str(self.op.ColorTblIn2.value[t, x, y, z, 0])
292+
rgbaValidationString = "rgba l.:{};{};{};{}".format(*[str(slot.value[t, x, y, z, 0]) for slot in self.op.RgbaIn])
293+
emptyRgbaValidationString = "empty r. l.:0;0;0;255"
294+
alphaModValidationString = "alpha m. l.:" + str(self.op.AlphaModulatedIn.value[t, x, y, z, 0])
206295

207296
with self.qtbot.waitSignal(signal, timeout=1000):
208297
self.editor.navCtrl.changeSliceAbsolute(y, 1)
298+
self.editor.navCtrl.changeTime(t)
209299

210-
self.updateAllTiles(self.editor.imageScenes) # Wait for all tiles being refreshed
211-
212-
with self.qtbot.waitSignals(signals, timeout=1000):
213-
self.editor.navCtrl.positionDataCursor(QPointF(x, z), 1)
214-
215-
self.updateAllTiles(self.editor.imageScenes) # Wait for all tiles being refreshed
300+
self.editor.navCtrl.positionDataCursor(QPointF(x, z), 1)
216301

302+
assert self.editorWidget.quadViewStatusBar.xSpinBox.value() == x
303+
assert self.editorWidget.quadViewStatusBar.ySpinBox.value() == y
304+
assert self.editorWidget.quadViewStatusBar.zSpinBox.value() == z
305+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
306+
self.grayscaleLayer].text() == grayValidationString
307+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
308+
self.segLayer1].text() == labelValidationString
309+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
310+
self.segLayer2].text() == labelValidationString
311+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
312+
self.colorTblLayer1].text() == colorTbl1ValidationString
313+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
314+
self.colorTblLayer2].text() == colorTbl2ValidationString
315+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
316+
self.rgbaLayer].text() == rgbaValidationString
317+
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
318+
self.emptyRgbaLayer].text() == emptyRgbaValidationString
217319
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[
218-
self.grayscaleLayer].text() in grayValidationStrings
219-
assert self.editorWidget.quadViewStatusBar.layerValueWidgets[self.labelLayer2].text() == label2ValidationString
320+
self.alphaModLayer].text() == alphaModValidationString
220321

0 commit comments

Comments
 (0)