Skip to content

Commit 11b3150

Browse files
committed
removed timer, get data from volumina stack. Not less hacky. Need for caches, storing raw datasources
1 parent bb26c28 commit 11b3150

File tree

4 files changed

+59
-109
lines changed

4 files changed

+59
-109
lines changed

volumina/patchAccessor.py

+6
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ def getPatchesForRect(self, startx, starty, endx, endy):
105105
ex = min(ex, self._cX)
106106
ey = min(ey, self._cY)
107107

108+
# always return at least one index
109+
if sx==ex:
110+
ex = ex + 1
111+
if sy==ey:
112+
ey = ey + 1
113+
108114
nums = []
109115
for y in range(sy, ey):
110116
nums += list(range(y * self._cX + sx, y * self._cX + ex))

volumina/positionModel.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ class PositionModel(QObject):
3838
in the same way as would be possible by manipulating the
3939
viewer with a mouse.
4040
"""
41-
42-
timeChanged = pyqtSignal(int)
43-
channelChanged = pyqtSignal(int)
44-
cursorPositionChanged = pyqtSignal(object, object)
41+
timeChanged = pyqtSignal(int)
42+
channelChanged = pyqtSignal(int)
43+
cursorPositionChanged = pyqtSignal(object, object)
4544
slicingPositionChanged = pyqtSignal(object, object)
4645
slicingPositionSettled = pyqtSignal(bool)
4746

volumina/sliceSelectorHud.py

+47-102
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from functools import partial
2727

2828
#PyQt
29-
from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QSize, QTimer
29+
from PyQt5.QtCore import pyqtSignal, Qt, QPointF, QPoint, QRect, QSize
3030
from PyQt5.QtGui import QPen, QPainter, QPixmap, QColor, QFont, QPainterPath, QBrush, QTransform, QIcon
3131

3232
from PyQt5.QtWidgets import (
@@ -41,6 +41,7 @@
4141
QSizePolicy,
4242
QSlider,
4343
QToolButton,
44+
QLineEdit
4445
)
4546

4647

@@ -416,53 +417,16 @@ def setAxes(self, rotation, swapped):
416417
self.buttons["swap-axes"].swapped = swapped
417418

418419

419-
def _get_pos_widget(name, backgroundColor, foregroundColor):
420-
label = QLabel()
421-
label.setAttribute(Qt.WA_TransparentForMouseEvents, True)
422-
423-
pixmap = QPixmap(25 * 10, 25 * 10)
424-
pixmap.fill(backgroundColor)
425-
painter = QPainter()
426-
painter.begin(pixmap)
427-
pen = QPen(foregroundColor)
428-
painter.setPen(pen)
429-
painter.setRenderHint(QPainter.Antialiasing)
430-
font = QFont()
431-
font.setBold(True)
432-
font.setPixelSize(25 * 10 - 30)
433-
path = QPainterPath()
434-
path.addText(QPointF(50, 25 * 10 - 50), font, name)
435-
brush = QBrush(foregroundColor)
436-
painter.setBrush(brush)
437-
painter.drawPath(path)
438-
painter.setFont(font)
439-
painter.end()
440-
pixmap = pixmap.scaled(QSize(20, 20), Qt.KeepAspectRatio, Qt.SmoothTransformation)
441-
label.setPixmap(pixmap)
442-
443-
spinbox = DelayedSpinBox(750)
444-
spinbox.setAlignment(Qt.AlignCenter)
445-
spinbox.setToolTip("{0} Spin Box".format(name))
446-
spinbox.setButtonSymbols(QAbstractSpinBox.NoButtons)
447-
spinbox.setMaximumHeight(20)
448-
font = spinbox.font()
449-
font.setPixelSize(14)
450-
spinbox.setFont(font)
451-
sheet = TEMPLATE.format(foregroundColor.name(), backgroundColor.name())
452-
spinbox.setStyleSheet(sheet)
453-
return label, spinbox
454-
455-
456420
class QuadStatusBar(QHBoxLayout):
457421

458-
positionChanged = pyqtSignal(int, int, int) # x,y,z
459-
460-
def __init__(self, parent=None):
422+
positionChanged = pyqtSignal(int, int, int) # x,y,z
423+
424+
def __init__(self, volumeEditor, parent=None):
461425
QHBoxLayout.__init__(self, parent)
462426
self.setContentsMargins(0, 4, 0, 0)
463427
self.setSpacing(0)
464428
self.timeControlFontSize = 12
465-
self.layerStack = layerStack
429+
self.editor = volumeEditor
466430

467431
def showXYCoordinates(self):
468432
self.zLabel.setHidden(True)
@@ -491,11 +455,14 @@ def setToolTipTimeSlider(self, croppingFlag=False):
491455
self.timeSlider.setToolTip("Choose the time coordinate of the current dataset.")
492456

493457
def createQuadViewStatusBar(
494-
self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor
458+
self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor,
459+
zforegroundColor, labelbackgroundColor, labelforegroundColor
495460
):
496-
self.xLabel, self.xSpinBox = _get_pos_widget("X", xbackgroundColor, xforegroundColor)
497-
self.yLabel, self.ySpinBox = _get_pos_widget("Y", ybackgroundColor, yforegroundColor)
498-
self.zLabel, self.zSpinBox = _get_pos_widget("Z", zbackgroundColor, zforegroundColor)
461+
self.xLabel, self.xSpinBox = self._get_pos_widget("X", xbackgroundColor, xforegroundColor)
462+
self.yLabel, self.ySpinBox = self._get_pos_widget("Y", ybackgroundColor, yforegroundColor)
463+
self.zLabel, self.zSpinBox = self._get_pos_widget("Z", zbackgroundColor, zforegroundColor)
464+
self.labelWidget = self._get_posMeta_widget(labelbackgroundColor, labelforegroundColor)
465+
self.labelbackgroundColor = labelbackgroundColor
499466

500467
self.xSpinBox.delayedValueChanged.connect(partial(self._handlePositionBoxValueChanged, "x"))
501468
self.ySpinBox.delayedValueChanged.connect(partial(self._handlePositionBoxValueChanged, "y"))
@@ -624,10 +591,7 @@ def _get_pos_widget(self, name, backgroundColor, foregroundColor):
624591
spinbox.setStyleSheet(sheet)
625592
return label, spinbox
626593

627-
def _get_label_widget(self, backgroundColor, foregroundColor):
628-
ticker = QTimer()
629-
ticker.setInterval(200)
630-
ticker.setSingleShot(True)
594+
def _get_posMeta_widget(self, backgroundColor, foregroundColor):
631595
ledit = QLineEdit()
632596
ledit.setAlignment(Qt.AlignCenter)
633597
ledit.setMaximumHeight(20)
@@ -641,58 +605,39 @@ def _get_label_widget(self, backgroundColor, foregroundColor):
641605
f"background-color: {backgroundColor.name()};"
642606
f"border: none")
643607

644-
return ledit, ticker
608+
return ledit
645609

646-
def _set_label_widget(self, x, y, z, t):
610+
def _set_posMeta_widget(self, x, y, z):
647611
"""Updates the label widget according to current mouse cursor position (x,y,z) and selectet time frame (t)"""
648-
# from lazyflow.roi import TinyVector
649-
# from collections import namedtuple
650-
651-
# no need for the color dimension (last element) here.
652-
slicing = [slice(int(i), int(i + 1)) for i in [t, x, y, z]] + [slice(0,1)]
653-
# Roi = namedtuple('Roi', 'start stop')
654-
# roi = Roi(start=TinyVector([int(t),int(y),int(x),int(z)]), stop=TinyVector([int(t+1),int(y+1),int(x+1),int(z+1)]))
655612
label = None
613+
coords = [int(val) for val in [x,y,z]]
614+
imgView = self.editor.posModel.activeView
615+
blockSize = self.editor.imageViews[imgView].scene()._tileProvider.tiling.blockSize
616+
del coords[imgView]
617+
x,y = (val for val in coords)
618+
if imgView == 0:
619+
x,y = (y,x)
656620
try:
657-
def findLayer(layer):
658-
if "Segmentation (Label " in layer.name:
659-
return True
660-
labelings = self.layerStack.findMatchingIndices(findLayer) # this throws exception if no layer found
661-
for lbl in labelings:
662-
try:
663-
fixed = []
664-
# FIXME This is really hacky, need to find another way of retrieving the cached values without the cache blocking the request
665-
for op in self.layerStack[lbl].datasources[0].dataSlot.getRealOperator().opPredictionPipeline.innerOperators[0].prediction_cache_gui._innerOps:
666-
fixed.append(op._opCacheFixer._fixed)
667-
op._opCacheFixer._fixed = False
668-
669-
# Get the whole dataset (debugging purposes)
670-
# whole_set_roi = Roi(start=TinyVector([0, 0, 0, 0]),
671-
# whole_set_slicing = [slice(int(0), int(i)) for i in [2, 1343, 1022, 1]] + [slice(0,1)]
672-
# set_fromRoi = self.layerStack[lbl].datasources[0].dataSlot.get(whole_set_roi).wait()
673-
# set_fromSlice = self.layerStack[lbl].datasources[0].request(whole_set_slicing).wait()
674-
# set_fromVal = self.layerStack[lbl].datasources[0].dataSlot.value
675-
676-
# Equivalent calls to opCacheFixer
677-
# val = self.layerStack[lbl].datasources[0].dataSlot.get(roi).wait()
678-
# val = self.layerStack[lbl].datasources[0].dataSlot(roi.start, roi.stop).wait()
679-
val = self.layerStack[lbl].datasources[0].request(slicing).wait()
680-
681-
# This does not call cached values, hence no need to hack the cache. But it is way to slow
682-
# val = self.layerStack[lbl].datasources[0].dataSlot.value[int(t),int(y),int(x),int(z)]
683-
finally:
684-
if fixed:
685-
for fx, op in zip(fixed, self.layerStack[lbl].datasources[0].dataSlot.getRealOperator().opPredictionPipeline.innerOperators[0].prediction_cache_gui._innerOps):
686-
op._opCacheFixer._fixed = fx
687-
if val == 1: # indicates, that 'sclicing' is labelled with the label 'lbl'
688-
name = self.layerStack[lbl].name
689-
label = name[name.find("(") + 1:name.find(")")]
690-
color = self.layerStack[lbl].tintColor.name()
691-
self.labelWidget.setStyleSheet(f"color: white;"
692-
f"background-color: {color};"
693-
f"border: none")
694-
self.labelWidget.setText(f"{label}")
695-
break
621+
for layer in self.editor.layerStack:
622+
if layer.visible:
623+
layer_id = self.editor.imagepumps[imgView].stackedImageSources._layerToIms[layer]
624+
stack_id = self.editor.imageViews[imgView].scene()._tileProvider._current_stack_id
625+
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
626+
627+
with self.editor.imageViews[imgView].scene()._tileProvider._cache:
628+
image = self.editor.imageViews[imgView].scene()._tileProvider._cache.layer(stack_id, layer_id,
629+
tile_id)
630+
if image is not None:
631+
colorVal = image.pixelColor(x%blockSize,y%blockSize)
632+
if "Segmentation (Label " in layer.name and colorVal.getRgb() != (0,0,0,0):
633+
name = layer.name
634+
label = name[name.find("(") + 1:name.find(")")]
635+
color = layer.tintColor.name()
636+
self.labelWidget.setStyleSheet(f"color: white;"
637+
f"background-color: {color};"
638+
f"border: none")
639+
self.labelWidget.setText(f"{label}")
640+
break
696641
if label is None:
697642
raise ValueError("No matching layer in stack.")
698643
except ValueError as e:
@@ -703,6 +648,8 @@ def findLayer(layer):
703648

704649
if str(e) != "No matching layer in stack.":
705650
raise
651+
except:
652+
raise
706653

707654
def _registerTimeframeShortcuts(self, enabled=True, remove=True):
708655
""" Register or deregister "," and "." as keyboard shortcuts for scrolling in time """
@@ -817,13 +764,11 @@ def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax):
817764
self.zSpinBox.setValue(shape5DcropMin[3])
818765
self.timeSlider.setValue(shape5DcropMin[0])
819766

820-
def setMouseCoords(self, x, y, z, t):
767+
def setMouseCoords(self, x, y, z):
821768
self.xSpinBox.setValueWithoutSignal(x)
822769
self.ySpinBox.setValueWithoutSignal(y)
823770
self.zSpinBox.setValueWithoutSignal(z)
824-
if not self.pos_info_ticker.isActive():
825-
self._set_label_widget(x, y, z, t)
826-
self.pos_info_ticker.start()
771+
self._set_posMeta_widget(x, y, z)
827772

828773

829774
if __name__ == "__main__":

volumina/volumeEditorWidget.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def onViewFocused():
161161
self, self.editor.imageViews[2], self.editor.imageViews[0], self.editor.imageViews[1], self.editor.view3d
162162
)
163163
self.quadview.installEventFilter(self)
164-
self.quadViewStatusBar = QuadStatusBar(self.editor.layerStack)
164+
self.quadViewStatusBar = QuadStatusBar(self.editor)
165165
self.quadViewStatusBar.createQuadViewStatusBar(
166166
QColor("#dc143c"), QColor("white"), QColor("green"), QColor("white"), QColor("blue"), QColor("white"),
167167
QColor("black"), QColor("white")
@@ -457,8 +457,8 @@ def jumpToLastSlice(axis):
457457
),
458458
)
459459

460-
def _updateInfoLabels(self, pos, oldpos, time):
461-
self.quadViewStatusBar.setMouseCoords(*pos, time)
460+
def _updateInfoLabels(self, pos):
461+
self.quadViewStatusBar.setMouseCoords(*pos)
462462

463463
def eventFilter(self, watched, event):
464464
# If the user performs a ctrl+scroll on the splitter itself,

0 commit comments

Comments
 (0)