Skip to content

Commit

Permalink
Adding showValue function to layer context menu. Add dynamic widgets …
Browse files Browse the repository at this point in the history
…that show respective layer value if showValue active. Exceptional case for segmentation.
  • Loading branch information
paulhfu committed Apr 8, 2019
1 parent d4568d9 commit 2b6551d
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 71 deletions.
27 changes: 27 additions & 0 deletions volumina/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ def toolTip(self):
def setToolTip(self, tip):
self._toolTip = tip

def setValueWidget(self, value):
"""
This function needs to be overwritten by every layer.
This function is called by QuadStatusBar.setMouseCoords. It is expected to return a tuple of information for
the position widgets, showing current pixelvalues of respective layer.
:param val: layer value at current cursor position
:return: ((String)text, (QColor)foregroundcolor, (QColor)backgroundcolor) for respective widget
"""
if value is not None:
return self.name + str(value), QColor(255, 255, 255), QColor(0, 0, 0)
return None, QColor(255, 255, 255), QColor(0, 0, 0)

def isDifferentEnough(self, other_layer):
"""This ugly function is here to support the updateAllLayers function in the layerViewerGui in ilastik"""
if type(other_layer) != type(self):
Expand Down Expand Up @@ -417,6 +429,11 @@ def isDifferentEnough(self, other_layer):
return True
return self._window_leveling != other_layer._window_leveling

def setValueWidget(self, value):
if value is not None:
return 'Gray:' + str(value.black()), QColor(value.black(), value.black(), value.black()), value
return None, QColor(255, 255, 255), QColor(0, 0, 0)

def __init__(self, datasource, range=None, normalize=None, direct=False, window_leveling=False):
assert isinstance(datasource, SourceABC)
super(GrayscaleLayer, self).__init__([datasource], range, normalize, direct=direct)
Expand All @@ -441,6 +458,16 @@ def tintColor(self, c):
self._tintColor = c
self.tintColorChanged.emit()

def setValueWidget(self, value):
if value is None:
return None, QColor(255, 255, 255), QColor(0, 0, 0)
elif "Segmentation (Label " in self.name:
if value.getRgb() == (0,0,0,0):
return None, QColor(255, 255, 255), QColor(0, 0, 0)
return self.name[self.name.find("(") + 1:self.name.find(")")], QColor(255, 255, 255), self.tintColor
else:
return self.name + str(value.getRgb()), QColor(255, 255, 255), QColor(0, 0, 0)

def __init__(self, datasource, tintColor=QColor(255, 0, 0), range=(0, 255), normalize=None):
assert isinstance(datasource, SourceABC)
super(AlphaModulatedLayer, self).__init__([datasource], range, normalize)
Expand Down
188 changes: 117 additions & 71 deletions volumina/sliceSelectorHud.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,7 @@ def createQuadViewStatusBar(
self.xLabel, self.xSpinBox = self._get_pos_widget("X", xbackgroundColor, xforegroundColor)
self.yLabel, self.ySpinBox = self._get_pos_widget("Y", ybackgroundColor, yforegroundColor)
self.zLabel, self.zSpinBox = self._get_pos_widget("Z", zbackgroundColor, zforegroundColor)
self.labelWidget = self._get_posMeta_widget(labelbackgroundColor, labelforegroundColor)
self.labelbackgroundColor = labelbackgroundColor
self.layerValueWidgets = self._get_layer_value_widgets()

self.xSpinBox.delayedValueChanged.connect(partial(self._handlePositionBoxValueChanged, "x"))
self.ySpinBox.delayedValueChanged.connect(partial(self._handlePositionBoxValueChanged, "y"))
Expand All @@ -474,7 +473,8 @@ def createQuadViewStatusBar(
self.addWidget(self.ySpinBox)
self.addWidget(self.zLabel)
self.addWidget(self.zSpinBox)
self.addWidget(self.labelWidget)
for valueWidget in self.layerValueWidgets.values():
self.addWidget(valueWidget)

self.addSpacing(10)

Expand Down Expand Up @@ -591,16 +591,7 @@ def _get_pos_widget(self, name, backgroundColor, foregroundColor):
spinbox.setStyleSheet(sheet)
return label, spinbox

def _layer_show_value_Changed(self, layer, visible):
return

def _layer_added(self, layer, row):
layer.showValueChanged.connect(self._layer_show_value_Changed)
pass

def _get_posMeta_widget(self, backgroundColor, foregroundColor):
self.editor.layerStack.layerAdded.connect(self._layer_added)

def _get_posMeta_widget(self):
ledit = QLineEdit()
ledit.setAlignment(Qt.AlignCenter)
ledit.setMaximumHeight(20)
Expand All @@ -610,67 +601,74 @@ def _get_posMeta_widget(self, backgroundColor, foregroundColor):
font.setPixelSize(14)
font.setBold(True)
ledit.setFont(font)
ledit.setStyleSheet(f"color: {foregroundColor.name()};"
f"background-color: {backgroundColor.name()};"
ledit.setStyleSheet(f"color: white;"
f"background-color: black;"
f"border: none")

return ledit

def _get_visible_layerData(self, x, y, z):
"""Returns the value of all curretnly visible layers at the x,y,z position of currently active image scene
:return [...,(layername, value) ,...]
"""
layer_values = []
coords = [int(val) for val in [x,y,z]]
imgView = self.editor.posModel.activeView
blockSize = self.editor.imageViews[imgView].scene()._tileProvider.tiling.blockSize

del coords[imgView]
x,y = (val for val in coords)
if imgView == 0:
x,y = (y,x)

for layer in self.editor.layerStack:
if layer.visible:
layer_id = self.editor.imagepumps[imgView].stackedImageSources._layerToIms[layer]
stack_id = self.editor.imageViews[imgView].scene()._tileProvider._current_stack_id
tile_id = self.editor.imageViews[imgView].scene()._tileProvider.tiling.intersected(
QRect(QPoint(x, y), QPoint(x, y)))[
0] # There will be just one tile, since we have just a single point
with self.editor.imageViews[imgView].scene()._tileProvider._cache:
image = self.editor.imageViews[imgView].scene()._tileProvider._cache.layer(stack_id, layer_id,
tile_id)
if image is not None:
layer_values.append((layer, image.pixelColor(x % blockSize, y % blockSize).getRgb()))
return layer_values

def _set_posMeta_widget(self, x, y, z):
"""Updates the label widget according to current mouse cursor position (x,y,z) and selectet time frame (t)"""
try:
dataValues = self._get_visible_layerData(x, y, z)
label = None
for item in dataValues:
layer, data = item
if "Segmentation (Label " in layer.name and data != (0,0,0,0):
label = layer.name[layer.name.find("(") + 1:layer.name.find(")")]
color = layer.tintColor.name()
self.labelWidget.setStyleSheet(f"color: white;"
f"background-color: {color};"
f"border: none")
self.labelWidget.setText(f"{label}")
break
if label is None:
raise ValueError("No matching layer in stack.")
except ValueError as e:
self.labelWidget.setStyleSheet(f"color: white;"
f"background-color: black;"
f"border: none")
self.labelWidget.setText(f"Label: -")
def _layer_show_value_Changed(self, layer, showVal):
if showVal:
if "Segmentation (Label " in layer.name:
for key in self.layerValueWidgets.keys():
if "Segmentation (Label " in key.name:
self.layerValueWidgets[layer] = self.layerValueWidgets[key]
return
self.layerValueWidgets[layer] = self._get_posMeta_widget()
self.addWidget(self.layerValueWidgets[layer])
else:
widget = self.layerValueWidgets[layer]
del self.layerValueWidgets[layer]
if "Segmentation (Label " in layer.name:
for key in self.layerValueWidgets.keys():
if "Segmentation (Label " in key.name:
return
self.removeWidget(widget)
widget.deleteLater()

if str(e) != "No matching layer in stack.":
raise
except:
raise
def _layer_added(self, layer, row):
layer.showValueChanged.connect(self._layer_show_value_Changed)
if layer.showValue:
if "Segmentation (Label " in layer.name:
for key in self.layerValueWidgets.keys():
if "Segmentation (Label " in key.name:
self.layerValueWidgets[layer] = self.layerValueWidgets[key]
break
else:
continue
continue
self.layerValueWidgets[layer] = self._get_posMeta_widget()
self.addWidget(self.layerValueWidgets[layer])

def _layer_removed(self, layer, row):
layer.showValueChanged.disconnect(self._layer_show_value_Changed)
if layer in self.layerValueWidgets:
widget = self.layerValueWidgets[layer]
del self.layerValueWidgets[layer]
if "Segmentation (Label " in layer.name:
for key in self.layerValueWidgets.keys():
if "Segmentation (Label " in key.name:
return
self.removeWidget(widget)
widget.deleteLater()

def _get_layer_value_widgets(self):
layerValueWidgets = {}
self.editor.layerStack.layerAdded.connect(self._layer_added)
self.editor.layerStack.layerRemoved.connect(self._layer_removed)
for layer in self.editor.layerStack: # Just to be sure, however layerStack should be empty at this point
layer.showValueChanged.connect(self._layer_show_value_Changed())
if layer.showValue:
if "Segmentation (Label " in layer.name:
for key in positionMeta.keys():
if "Segmentation (Label " in key.name:
layerValueWidgets[layer] = layerValueWidgets[key]
break
else:
continue
continue
layerValueWidgets[layer] = self._get_posMeta_widget()

return layerValueWidgets

def _registerTimeframeShortcuts(self, enabled=True, remove=True):
""" Register or deregister "," and "." as keyboard shortcuts for scrolling in time """
Expand Down Expand Up @@ -789,7 +787,55 @@ def setMouseCoords(self, x, y, z):
self.xSpinBox.setValueWithoutSignal(x)
self.ySpinBox.setValueWithoutSignal(y)
self.zSpinBox.setValueWithoutSignal(z)
self._set_posMeta_widget(x, y, z)

coords = [int(val) for val in [x,y,z]]
imgView = self.editor.posModel.activeView
blockSize = self.editor.imageViews[imgView].scene()._tileProvider.tiling.blockSize
labelSet = False

del coords[imgView]
x,y = (val for val in coords)
if imgView == 0: # the y-z view is inverted in tileProvider
x,y = (y,x)

for layer, widget in self.layerValueWidgets.items():
value = None
layer_id = self.editor.imagepumps[imgView].stackedImageSources._layerToIms[layer]
stack_id = self.editor.imageViews[imgView].scene()._tileProvider._current_stack_id
tile_id = self.editor.imageViews[imgView].scene()._tileProvider.tiling.intersected(
QRect(QPoint(x, y), QPoint(x, y)))[
0] # There will be just one tile, since we have just a single point
with self.editor.imageViews[imgView].scene()._tileProvider._cache:
image = self.editor.imageViews[imgView].scene()._tileProvider._cache.layer(stack_id, layer_id,
tile_id)
if image is not None:
value = image.pixelColor(x % blockSize, y % blockSize)

lbl, foreground, background = layer.setValueWidget(value)

if "Segmentation (Label " in layer.name:
if not labelSet:
if lbl is None:
widget.setStyleSheet(f"color: {foreground.name()};"
f"background-color: {background.name()};"
f"border: none")
widget.setText(f"{'-'}")
continue
widget.setStyleSheet(f"color: {foreground.name()};"
f"background-color: {background.name()};"
f"border: none")
widget.setText(f"{lbl}")
labelSet = True
elif lbl is not None:
widget.setStyleSheet(f"color: {foreground.name()};"
f"background-color: {background.name()};"
f"border: none")
widget.setText(f"{lbl}")
else:
widget.setStyleSheet(f"color: {foreground.name()};"
f"background-color: {background.name()};"
f"border: none")
widget.setText(f"-")


if __name__ == "__main__":
Expand Down

0 comments on commit 2b6551d

Please sign in to comment.