5
5
from PyQt6 .QtGui import QPainter
6
6
from PyQt6 .QtWidgets import QApplication , QRadioButton , QWidget , QDialog , QButtonGroup , QSlider , QStyle , QStyleOptionSlider , QGridLayout , QPushButton , QLabel , QLineEdit , QDialogButtonBox , QComboBox
7
7
import pyqtgraph as pg
8
- from pyqtgraph import Point
8
+ from pyqtgraph . Point import Point
9
9
import numpy as np
10
10
import os
11
11
from omnipose .core import affinity_to_boundary
@@ -1214,7 +1214,6 @@ def __pixelPosToRangeValue(self, pos):
1214
1214
opt .upsideDown )
1215
1215
1216
1216
1217
-
1218
1217
class HistLUT (pg .HistogramLUTItem ):
1219
1218
# sigLookupTableChanged = QtCore.pyqtSignal(object)
1220
1219
# sigLevelsChanged = QtCore.pyqtSignal(object)
@@ -1232,12 +1231,15 @@ def __init__(self, image=None, fillHistogram=True, levelMode='mono',
1232
1231
self ._orig_mousePressEvent = super ().mousePressEvent
1233
1232
self ._orig_mouseMoveEvent = super ().mouseMoveEvent
1234
1233
self ._orig_mouseReleaseEvent = super ().mouseReleaseEvent
1234
+ self ._orig_paint = super ().paint
1235
+
1235
1236
1236
1237
self .imageitem = image
1237
1238
self ._view = 0
1238
1239
# Make sure there's a place to store full item states for each view.
1239
1240
if not hasattr (self , 'view_states' ):
1240
1241
self .view_states = {}
1242
+
1241
1243
1242
1244
# Connect signals for color stops...
1243
1245
if hasattr (self .gradient , 'sigGradientChanged' ):
@@ -1248,12 +1250,22 @@ def __init__(self, image=None, fillHistogram=True, levelMode='mono',
1248
1250
# ...and region/levels so we capture user changes to min/max handles.
1249
1251
self .region .sigRegionChanged .connect (self ._on_region_changed )
1250
1252
self .region .sigRegionChangeFinished .connect (self ._on_region_changed )
1251
-
1253
+
1254
+ # def paint(self, painter, option, widget=None):
1255
+ # old_brush = self.gradient.gradRect.brush()
1256
+ # if getattr(self, 'discrete_mode', False):
1257
+ # # In discrete mode, skip the default overlay drawing.
1258
+ # # return
1259
+ # self.gradient.gradRect.setBrush(QtGui.QBrush(QtCore.Qt.BrushStyle.NoBrush))
1260
+ # # Otherwise, call the original painting.
1261
+ # self._orig_paint(painter, option, widget)
1262
+ # self.gradient.gradRect.setBrush(old_brush)
1263
+ # self.gradient.backgroundRect.hide() # the cause of the hatching pattern
1264
+
1265
+
1252
1266
def set_view (self , v , preset = None , default_cmaps = None ):
1253
1267
self ._view = v
1254
1268
state = self .view_states .get (v ) # This is the *full item* state, not just gradient.
1255
-
1256
-
1257
1269
1258
1270
if state is not None :
1259
1271
self .restoreState (state ) # calls HistogramLUTItem.restoreState(state)
@@ -1293,7 +1305,7 @@ def setDiscreteMode(self, discrete: bool, n_bands: int = 5):
1293
1305
if st .get ('mode' , '' ).lower () == 'hsv' :
1294
1306
st ['mode' ] = 'rgb'
1295
1307
self .gradient .restoreState (st )
1296
- # Save original paint method if not already saved.
1308
+ # Save original paint method if not already saved.
1297
1309
if not hasattr (self .gradient , '_original_paint' ):
1298
1310
self .gradient ._original_paint = self .gradient .paint
1299
1311
# Store the number of discrete bands.
@@ -1304,18 +1316,13 @@ def setDiscreteMode(self, discrete: bool, n_bands: int = 5):
1304
1316
self .gradient .paint = self ._discrete_gradient_paint .__get__ (self .gradient , type (self .gradient ))
1305
1317
# Hide the continuous gradient: disable gradRect painting and caching.
1306
1318
self .gradient .gradRect .hide ()
1307
- self .gradient .setCacheMode (QGraphicsItem .CacheMode .NoCache )
1308
- self .gradient .gradRect .setCacheMode (QGraphicsItem .CacheMode .NoCache )
1309
- self .gradient .gradRect .setFlag (QGraphicsItem .GraphicsItemFlag .ItemHasNoContents , True )
1310
1319
1311
- self .gradient .update ()
1312
1320
else :
1313
1321
if hasattr (self .gradient , '_original_paint' ):
1314
1322
self .gradient .paint = self .gradient ._original_paint
1315
1323
self .gradient .gradRect .show ()
1316
- self .gradient .gradRect .setFlag (QGraphicsItem .GraphicsItemFlag .ItemHasNoContents , False )
1317
1324
1318
- self .gradient .update ()
1325
+ self .gradient .update ()
1319
1326
1320
1327
1321
1328
def _discrete_gradient_paint (self , painter , opt , widget = None ):
@@ -1326,10 +1333,9 @@ def _discrete_gradient_paint(self, painter, opt, widget=None):
1326
1333
between adjacent bands to cover any rounding gaps.
1327
1334
"""
1328
1335
painter .save ()
1329
- painter .setRenderHint (QtGui .QPainter .RenderHint .Antialiasing , False )
1330
- painter .setRenderHint (QtGui .QPainter .RenderHint .SmoothPixmapTransform , False )
1331
- painter .setCompositionMode (QtGui .QPainter .CompositionMode_Source )
1332
- # painter.setPen(Qt.NoPen)
1336
+ painter .setPen (Qt .NoPen )
1337
+ # painter.setPen(self.tickPen)
1338
+
1333
1339
1334
1340
# Get the drawing rectangle from gradRect as an integer QRect.
1335
1341
rect = self .gradRect .rect ().toRect ()
@@ -1349,7 +1355,9 @@ def _discrete_gradient_paint(self, painter, opt, widget=None):
1349
1355
bandRect = QtCore .QRect (x , rect .top (), w + 1 , rect .height ())
1350
1356
else :
1351
1357
bandRect = QtCore .QRect (x , rect .top (), w , rect .height ())
1352
- frac = (i + 0.5 ) / nBands
1358
+ # frac = (i + 0.5) / nBands
1359
+ frac = (i ) / (nBands - 1 )
1360
+
1353
1361
qcol = self ._parent_histlut ._sample_colormap (frac )
1354
1362
painter .setBrush (QtGui .QBrush (qcol , Qt .BrushStyle .SolidPattern ))
1355
1363
painter .drawRect (bandRect )
@@ -1373,8 +1381,15 @@ def _discrete_gradient_paint(self, painter, opt, widget=None):
1373
1381
painter .drawRect (bandRect )
1374
1382
y += h
1375
1383
1384
+ # drow the border
1385
+ pen = self .tickPen
1386
+ painter .setPen (pen )
1387
+ painter .setBrush (QtCore .Qt .BrushStyle .NoBrush )
1388
+ painter .drawRect (rect )
1389
+
1376
1390
painter .restore ()
1377
-
1391
+
1392
+
1378
1393
def _sample_colormap (self , fraction : float ) -> QtGui .QColor :
1379
1394
"""
1380
1395
Sample the current colormap at the given fraction (0 to 1) and return a fully opaque QColor.
@@ -1395,7 +1410,7 @@ def _sample_colormap(self, fraction: float) -> QtGui.QColor:
1395
1410
a = 255
1396
1411
else :
1397
1412
r , g , b , a = entry
1398
- return QtGui .QColor (r , g , b , 255 )
1413
+ return QtGui .QColor (r , g , b , a )
1399
1414
1400
1415
def _on_gradient_changed (self ):
1401
1416
# Called when the user moves color stops in the gradient
@@ -1459,54 +1474,65 @@ def autoRange(self):
1459
1474
self .region .setRegion ((min_val , max_val )) # sets the slider region
1460
1475
1461
1476
1462
- # def paint(self, p, *args):
1463
- # # paint the bounding edges of the region item and gradient item with lines
1464
- # # connecting them
1465
- # if self.levelMode != 'mono' or not self.region.isVisible():
1466
- # return
1467
- # print('ddd')
1468
- # pen = self.region.lines[0].pen
1469
-
1470
- # mn, mx = self.getLevels()
1471
- # vbc = self.vb.viewRect().center()
1472
- # gradRect = self.gradient.mapRectToParent(self.gradient.gradRect.rect())
1473
- # if self.orientation == 'vertical':
1474
- # p1mn = self.vb.mapFromViewToItem(self, Point(vbc.x(), mn)) + Point(0, 5)
1475
- # p1mx = self.vb.mapFromViewToItem(self, Point(vbc.x(), mx)) - Point(0, 5)
1476
- # if self.gradientPosition == 'right':
1477
- # p2mn = gradRect.bottomLeft()
1478
- # p2mx = gradRect.topLeft()
1479
- # else:
1480
- # p2mn = gradRect.bottomRight()
1481
- # p2mx = gradRect.topRight()
1482
- # else:
1483
- # p1mn = self.vb.mapFromViewToItem(self, Point(mn, vbc.y())) - Point(5, 0)
1484
- # p1mx = self.vb.mapFromViewToItem(self, Point(mx, vbc.y())) + Point(5, 0)
1485
- # if self.gradientPosition == 'bottom':
1486
- # p2mn = gradRect.topLeft()
1487
- # p2mx = gradRect.topRight()
1488
- # else:
1489
- # p2mn = gradRect.bottomLeft()
1490
- # p2mx = gradRect.bottomRight()
1491
-
1492
- # p.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing)
1493
-
1494
- # for pen in [pen]: #get rid of first entry, shadow of some sort
1495
- # p.setPen(pen)
1496
-
1497
- # # lines from the linear region item bounds to the gradient item bounds
1498
- # p.drawLine(p1mn, p2mn)
1499
- # p.drawLine(p1mx, p2mx)
1500
-
1501
- # # lines bounding the edges of the gradient item
1502
- # if self.orientation == 'vertical':
1503
- # p.drawLine(gradRect.topLeft(), gradRect.topRight())
1504
- # p.drawLine(gradRect.bottomLeft(), gradRect.bottomRight())
1505
- # else:
1506
- # p.drawLine(gradRect.topLeft(), gradRect.bottomLeft())
1507
- # p.drawLine(gradRect.topRight(), gradRect.bottomRight())
1508
-
1477
+ def paint (self , p , * args ):
1478
+ # paint the bounding edges of the region item and gradient item with lines
1479
+ # connecting them
1480
+ if self .levelMode != 'mono' or not self .region .isVisible ():
1481
+ return
1509
1482
1483
+ pen = self .region .lines [0 ].pen
1484
+
1485
+ mn , mx = self .getLevels ()
1486
+ vbc = self .vb .viewRect ().center ()
1487
+ gradRect = self .gradient .mapRectToParent (self .gradient .gradRect .rect ())
1488
+ if self .orientation == 'vertical' :
1489
+ p1mn = self .vb .mapFromViewToItem (self , Point (vbc .x (), mn )) + Point (0 , 5 )
1490
+ p1mx = self .vb .mapFromViewToItem (self , Point (vbc .x (), mx )) - Point (0 , 5 )
1491
+ if self .gradientPosition == 'right' :
1492
+ p2mn = gradRect .bottomLeft ()
1493
+ p2mx = gradRect .topLeft ()
1494
+ else :
1495
+ p2mn = gradRect .bottomRight ()
1496
+ p2mx = gradRect .topRight ()
1497
+ else :
1498
+ p1mn = self .vb .mapFromViewToItem (self , Point (mn , vbc .y ())) - Point (5 , 0 )
1499
+ p1mx = self .vb .mapFromViewToItem (self , Point (mx , vbc .y ())) + Point (5 , 0 )
1500
+ if self .gradientPosition == 'bottom' :
1501
+ p2mn = gradRect .topLeft ()
1502
+ p2mx = gradRect .topRight ()
1503
+ else :
1504
+ p2mn = gradRect .bottomLeft ()
1505
+ p2mx = gradRect .bottomRight ()
1506
+
1507
+ p .setRenderHint (QtGui .QPainter .RenderHint .Antialiasing , True )
1508
+ p .setRenderHint (QtGui .QPainter .RenderHint .SmoothPixmapTransform , True )
1509
+
1510
+ for pen in [pen ]: #get rid of first entry, shadow of some sort
1511
+ p .setPen (pen )
1512
+
1513
+ # lines from the linear region item bounds to the gradient item bounds
1514
+ p .drawLine (p1mn , p2mn )
1515
+ p .drawLine (p1mx , p2mx )
1516
+
1517
+ # lines bounding the edges of the gradient item
1518
+ if self .orientation == 'vertical' :
1519
+ p .drawLine (gradRect .topLeft (), gradRect .topRight ())
1520
+ p .drawLine (gradRect .bottomLeft (), gradRect .bottomRight ())
1521
+ else :
1522
+ p .drawLine (gradRect .topLeft (), gradRect .bottomLeft ())
1523
+ p .drawLine (gradRect .topRight (), gradRect .bottomRight ())
1524
+
1525
+ # def paint(self, painter, option, widget=None):
1526
+ old_brush = self .gradient .gradRect .brush ()
1527
+ if getattr (self , 'discrete_mode' , False ):
1528
+ # In discrete mode, skip the default overlay drawing.
1529
+ # return
1530
+ self .gradient .gradRect .setBrush (QtGui .QBrush (QtCore .Qt .BrushStyle .NoBrush ))
1531
+ # Otherwise, call the original painting.
1532
+ self ._orig_paint (p , * args ) # painter, option, widget)
1533
+ self .gradient .gradRect .setBrush (old_brush )
1534
+ self .gradient .backgroundRect .hide () # the cause of the hatching pattern
1535
+
1510
1536
1511
1537
1512
1538
@@ -1557,17 +1583,15 @@ def update_icons(self):
1557
1583
def _emit_toggled (self ):
1558
1584
"""Emit the toggled signal when the button is clicked."""
1559
1585
self .toggled .emit (self .isChecked ())
1560
-
1561
- import numpy as np
1562
- import pyqtgraph as pg
1586
+
1587
+
1563
1588
from pyqtgraph import GraphicsObject
1564
1589
from PyQt6 .QtWidgets import QGraphicsItem
1565
1590
from PyQt6 .QtGui import QPainter
1566
1591
from PyQt6 .QtCore import QRectF , Qt
1567
1592
1568
1593
import OpenGL .GL as gl
1569
1594
1570
-
1571
1595
class GLPixelGridOverlay (GraphicsObject ):
1572
1596
"""
1573
1597
A QGraphicsItem that draws lines between centers of adjacent pixels
0 commit comments