I want to apply a colormap (“hot”) only to a certain range of values of an image. I already know this functionality from matplotlib.pyplot.clim where you have to specify a minimum and a maximum value for the scaling. As I understood it, you should use setLevels([min,max]) for this. I have included a minimal example which shows that both representations are unfortunately not equivalent.
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
import os
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui#, QtWidgets
#import PyQt5.QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QFileDialog,
QScrollArea, QVBoxLayout, QGroupBox, QLabel, QFormLayout, QComboBox, QHBoxLayout
from skimage import io
import sys
def main():
imarray = np.random.rand(100, 100) * 515
imarray = np.clip(imarray, 0, 515)
plt_example(imarray)
pyqtgraph_example(imarray)
def plt_example(data):
plt.imshow(data, cmap='hot')
c = plt.colorbar()
plt.clim(0, 200)
plt.show()
def pyqtgraph_example(data):
colormap = cm.get_cmap("hot")
colormap._init()
lut = (colormap._lut * 255).view(np.ndarray)
app = pg.mkQApp("Test")
win = pg.GraphicsLayoutWidget()
win.show()
win.setWindowTitle('pyqtgraph example: ImageItem')
view = win.addViewBox()
## lock the aspect ratio so pixels are always square
view.setAspectLocked(True)
## Create image item
img = pg.ImageItem()
view.addItem(img)
img.setImage(data)
img.setLevels([0, 200]) # same functionality as clim?
img.setLookupTable(lut)
app.exec()
if __name__ == "__main__":
main()
Do you know a way how I can get the same representation in pyqtgraph as with clim in matplotlib?
The first image shows the result using matplotlib and the second shows the result using pyqtgraph.
Advertisement
Answer
This question made its way to the pyqtgraph issue tracker here: https://github.com/pyqtgraph/pyqtgraph/pull/1985#issuecomment-932223288
Here is some code to generate identical results between the two libraries
import matplotlib.pyplot as plt
import numpy as np
import pyqtgraph as pg
def main():
imarray = np.random.rand(100, 100) * 515
imarray = np.clip(imarray, 0, 515)
plt_example(imarray)
pyqtgraph_example(imarray)
def plt_example(data):
plt.imshow(data, cmap='hot')
c = plt.colorbar()
plt.clim(0, 200)
plt.show(block=False)
def pyqtgraph_example(data):
app = pg.mkQApp("Test")
win = pg.GraphicsLayoutWidget()
win.setWindowTitle('pyqtgraph example: ImageItem')
win.show()
# add plot with correct axis orientation and locked aspect ratio
plot = win.addPlot()
plot.setAspectLocked(True)
plot.invertY()
# Create image item
img = pg.ImageItem(data, axisOrder='row-major')
plot.addItem(img)
# Create color bar and have it control image levels
cmap = pg.colormap.getFromMatplotlib('hot')
cbi = pg.ColorBarItem(colorMap=cmap)
cbi.setImageItem(img, insert_in=plot)
cbi.setLevels([0, 200]) # colormap range
app.exec()
if __name__ == "__main__":
main()
The poster of this code in the issue tracker noted that the “overflow” values seem to render to white in matplotlib, and black to pyqtgraph. In addition, the pyqtgraph image is rotated 90 degrees left since the axis order is not set and the y-axis is likely reversed.
to get the right rotation orientation, the code has two lines of note
plot.invertY()
and
pg.ImageItem(data, axisOrder='row-major')
Hopefully this helps!