Skip to content
Advertisement

matplotlib.pyplot.clim counterpart in pyqtgraph

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. enter image description here enter image description here

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!

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement