Hi,
Funnily enough I was looking for a pcolormesh equivalent in pyqtgraph just
the other day, and searching didn't come up with much except this old
thread (which is not a suitable solution for me -- my pixel sizes are
dramatically different sizes).
The way matplotlib does the pcolormesh is by creating a large number of
rectangular patches, each rectangle is the width/height of the pixel size,
with a face color mapped to the z value. The hundreds (thousands?!) of
patches are then placed on the plot axes. You can see this when exporting
to a vector graphic (SVG, PDF) versus a raster (PNG) -- the vector graphic
is larger file size and horribly slow to render!
The quick and dirty workaround for this is to simply interpolate the
irregularly spaced data onto a regular grid. I was going to try this first,
as it's pretty easy. The issue is that with drastically different sized
pixels, we need to choose an interpolation grid size. If we choose the
smallest increment, then the resulting image may be enormous (large memory
usage, possibly slow to pan/render). If we choose a larger pixel size, then
we will lose detail when zooming in to the regions where the pixels were
small.
Anyway, if you wanted to try this, look at the 2D interpolation routines
from scipy. Something like:
import numpy as np
from scipy import interpolate
# Generate some test data on an irregular grid
irreg_xlabels = np.array([0,1,3,7])
irreg_ylabels = np.array([0,2,5,9])
irreg_data = np.outer(irreg_xlabels, irreg_ylabels)
# Choose the finest step size as our new pixel size
# Will give best detail, but large image size!
step_x = np.ediff1d(irreg_xlabels).min()
step_y = np.ediff1d(irreg_ylabels).min()
# Function to generate interpolated values from our irregular grid
f = interpolate.RectBivariateSpline(irreg_xlabels, irreg_ylabels,
irreg_data)
# Generate new data on the regular grid
xlabels = np.arange(irreg_xlabels[0], irreg_xlabels[-1] + step_x, step_x)
ylabels = np.arange(irreg_ylabels[0], irreg_ylabels[-1] + step_y, step_y)
data = f(xlabels, ylabels)
then set the ImageItem data and translations/scale using the new, regular
grid offset and step size.
If memory use and performance is acceptable, then that should do it. If
not, then it would be possible to dynamically generate the new interpolated
image data when the range of the view changes. Then only get interpolated
values between the view range and at a resolution that matches the viewport
size.
Patrick
On Thursday, 16 August 2018 06:17:08 UTC+9:30, Luke Carroll wrote:
>
> Hey, I've tried replicating the suggestions but cant seem to get anything
> to appear, I wrote the script below and ran it from the windows command
> prompt using Python. I'm using numpy 1.14, pyqt 5.9 and pyqtgraph 0.10.
> When I just use the code suggested by Samuel Palato nothing gets displayed
> either. I've also tried running this in a jupyter notebook but to no avail.
>
> import numpy as np
> import pyqtgraph as pg
> from pyqtgraph.Qt import QtGui, QtCore
>
>
> class IndexedAxis(pg.AxisItem):
> """
> Axis where pixels are mapped using a numpy array
> """
> def __init__(self, orientation, mapping=None, **kw):
> super(IndexedAxis, self).__init__(orientation, **kw)
> self.mapping = mapping
> self.fmt = "{:.02f}"
>
> def tickStrings(self, values, scale, spacing):
> if self.mapping is None:
> return super(IndexedAxis, self).tickStrings(values, scale,
> spacing)
> # count values smaller than 0
> labels = []
> idx = np.array(values, dtype=np.int)-1
> left_pad = np.count_nonzero(idx < 0)
> right_pad = np.count_nonzero(idx >= self.mapping.size)
> idx = np.compress(np.logical_and(idx>=0, idx< self.mapping.size),
> idx)
> labels.extend([""]*left_pad)
> labels.extend([self.fmt.format(v) for v in self.mapping[idx]])
> labels.extend([""]*right_pad)
> return labels
>
> app = QtGui.QApplication([])
> mw = QtGui.QMainWindow
> view = pg.GraphicsLayoutWidget()
> w1 = view.addPlot()
>
> x_values = np.linspace(-100, 100)
> mapped_axis = IndexedAxis('bottom', mapping=x_values)
> plot_item = pg.PlotItem(axisItems={'bottom': mapped_axis})
> image_item =pg.ImageItem()
> plot_item.addItem(image_item)
>
> w1.addItem(plot_item)
>
>
>
>
>
> On Tuesday, April 19, 2016 at 6:50:05 PM UTC+1, Samuel Palato wrote:
>>
>> Hi,
>>
>> I managed to do something similar.
>>
>> My data has x and y axes with almost constant spacing, so I'm ok with
>> even sized pixels on display. However, the x and y axes display custom
>> values, looked up from the corresponding arrays. This is a bit closer to
>> the behavior of `matplotlib.imshow` with the `extent` keyword.
>>
>> The trick is to subclass `AxisItem` in order to display custom tick
>> labels. See:
>> https://bitbucket.org/snippets/spalato/X6nL4/indexed-axis#file-IndexedAxis.py
>> You then need to create the axis items and pass them to the PlotItem your
>> ImageItem is going to reside in:
>> x_values = np.linspace(-100, 100, n=51)
>> mapped_axis = IndexedAxis('bottom', mapping=x_values)
>> plot_item = pg.PlotItem(axisItems={'bottom': mapped_axis})
>> image_item =pg.ImageItem()
>> plot_item.addItem(image_item)
>> Or something similar.
>> To update the axis values, you need to update the axis' `mapping`
>> attribute to the new values.
>>
>> So far, this works, but I get an extra set of axes in the top right
>> corner. (which brought me here...)
>>
>> If constant pixels are unacceptable, you could try creating a display
>> image using nearest interpolation, and plotting the resulting image using
>> the technique described above.
>>
>> Hope this helps,
>> Samuel Palato
>>
>>
>> On Thursday, 17 March 2016 09:37:17 UTC-4, Nicola Creati wrote:
>>>
>>> Hello,
>>> I'm trying to move from Matplotlib to PyQtGraph but I need something
>>> equivalent to the Matplotlib pcolormesh/pcolor command that accepts X, Y
>>> and C as input. *X* and *Y *specify the (*x*, *y*) coordinates of the
>>> colored quadrilaterals and C is the array of values. Can I get the same
>>> with PyQtGraph, please?
>>> Thanks.
>>>
>>> Nicola
>>>
>>
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/3117568c-fb25-4c31-9ca0-26629cd871ad%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.