allow gradient position to be configured on a histogram (#1729)

* NEW features for HistgramLUTItem

* gradientPosition=('left', 'right')
* only paint if item is visible (is faster)
* link hisogram to other histograms

* fixes to be able to merge

 * drop linkHistogram (rgba needs to be better integrated)
 * make sure defaults to same as current behavior
 * draw connecting lines correctly on each side
 * add example use
This commit is contained in:
Martin Chase 2021-04-20 19:57:15 -07:00 committed by GitHub
parent a6f9a2be12
commit d531a808e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 23 deletions

View File

@ -3,45 +3,49 @@
Use a HistogramLUTWidget to control the contrast / coloration of an image.
"""
## Add path to library (just for examples; you do not need this)
# Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
app = pg.mkQApp("Histogram Lookup Table Example")
win = QtGui.QMainWindow()
win.resize(800,600)
win.resize(880, 600)
win.show()
win.setWindowTitle('pyqtgraph example: Histogram LUT')
cw = QtGui.QWidget()
win.setCentralWidget(cw)
l = QtGui.QGridLayout()
cw.setLayout(l)
l.setSpacing(0)
layout = QtGui.QGridLayout()
cw.setLayout(layout)
layout.setSpacing(0)
v = pg.GraphicsView()
view = pg.GraphicsView()
vb = pg.ViewBox()
vb.setAspectLocked()
v.setCentralItem(vb)
l.addWidget(v, 0, 0, 3, 1)
view.setCentralItem(vb)
layout.addWidget(view, 0, 1, 3, 1)
hist = pg.HistogramLUTWidget(gradientPosition="left")
layout.addWidget(hist, 0, 2)
w = pg.HistogramLUTWidget()
l.addWidget(w, 0, 1)
monoRadio = QtGui.QRadioButton('mono')
rgbaRadio = QtGui.QRadioButton('rgba')
l.addWidget(monoRadio, 1, 1)
l.addWidget(rgbaRadio, 2, 1)
layout.addWidget(monoRadio, 1, 2)
layout.addWidget(rgbaRadio, 2, 2)
monoRadio.setChecked(True)
def setLevelMode():
mode = 'mono' if monoRadio.isChecked() else 'rgba'
w.setLevelMode(mode)
hist.setLevelMode(mode)
monoRadio.toggled.connect(setLevelMode)
data = pg.gaussianFilter(np.random.normal(size=(256, 256, 3)), (20, 20, 0))
@ -52,7 +56,7 @@ img = pg.ImageItem(data)
vb.addItem(img)
vb.autoRange()
w.setImageItem(img)
hist.setImageItem(img)
if __name__ == '__main__':
pg.mkQApp().exec_()

View File

@ -46,6 +46,8 @@ class HistogramLUTItem(GraphicsWidget):
black/white level lines is drawn, and the levels apply to
all channels in the image. If 'rgba', then one set of
levels is drawn for each channel.
gradientPosition 'right' (default) OR 'left'. Which side of the histogram to
put the LUT gradient.
================ ===========================================================
"""
@ -53,12 +55,13 @@ class HistogramLUTItem(GraphicsWidget):
sigLevelsChanged = QtCore.Signal(object)
sigLevelChangeFinished = QtCore.Signal(object)
def __init__(self, image=None, fillHistogram=True, rgbHistogram=False, levelMode='mono'):
def __init__(self, image=None, fillHistogram=True, rgbHistogram=False, levelMode='mono', gradientPosition='right'):
GraphicsWidget.__init__(self)
self.lut = None
self.imageItem = lambda: None # fake a dead weakref
self.levelMode = levelMode
self.rgbHistogram = rgbHistogram
self.gradientPosition = gradientPosition
self.layout = QtGui.QGraphicsGridLayout()
self.setLayout(self.layout)
@ -69,7 +72,7 @@ class HistogramLUTItem(GraphicsWidget):
self.vb.setMinimumWidth(45)
self.vb.setMouseEnabled(x=False, y=True)
self.gradient = GradientEditorItem()
self.gradient.setOrientation('right')
self.gradient.setOrientation(gradientPosition)
self.gradient.loadPreset('grey')
self.regions = [
LinearRegionItem([0, 1], 'horizontal', swapMode='block'),
@ -94,7 +97,9 @@ class HistogramLUTItem(GraphicsWidget):
self.axis = AxisItem('left', linkView=self.vb, maxTickLength=-10, parent=self)
self.layout.addItem(self.axis, 0, 0)
self.layout.addItem(self.vb, 0, 1)
self.layout.addItem(self.gradient, 0, 2)
pos = (0, 2) if gradientPosition == 'right' else (2, 0)
self.layout.addItem(self.axis, 0, pos[0])
self.layout.addItem(self.gradient, 0, pos[1])
self.range = None
self.gradient.setFlag(self.gradient.ItemStacksBehindParent)
self.vb.setFlag(self.gradient.ItemStacksBehindParent)
@ -134,7 +139,7 @@ class HistogramLUTItem(GraphicsWidget):
plot.setFillLevel(None)
def paint(self, p, *args):
if self.levelMode != 'mono':
if self.levelMode != 'mono' or not self.region.isVisible():
return
pen = self.region.lines[0].pen
@ -145,11 +150,15 @@ class HistogramLUTItem(GraphicsWidget):
p.setRenderHint(QtGui.QPainter.Antialiasing)
for pen in [fn.mkPen((0, 0, 0, 100), width=3), pen]:
p.setPen(pen)
p.drawLine(p1 + Point(0, 5), gradRect.bottomLeft())
p.drawLine(p2 - Point(0, 5), gradRect.topLeft())
if self.gradientPosition == 'right':
p.drawLine(p1 + Point(0, 5), gradRect.bottomLeft())
p.drawLine(p2 - Point(0, 5), gradRect.topLeft())
else:
p.drawLine(p1 + Point(0, 5), gradRect.bottomRight())
p.drawLine(p2 - Point(0, 5), gradRect.topRight())
p.drawLine(gradRect.topLeft(), gradRect.topRight())
p.drawLine(gradRect.bottomLeft(), gradRect.bottomRight())
def setHistogramRange(self, mn, mx, padding=0.1):
"""Set the Y range on the histogram plot. This disables auto-scaling."""
self.vb.enableAutoRange(self.vb.YAxis, False)