Skip to content

Implemented pColorMeshItem#1273

Merged
j9ac9k merged 18 commits intopyqtgraph:masterfrom
edumur:develop
Oct 12, 2020
Merged

Implemented pColorMeshItem#1273
j9ac9k merged 18 commits intopyqtgraph:masterfrom
edumur:develop

Conversation

@edumur
Copy link
Copy Markdown
Contributor

@edumur edumur commented Jun 23, 2020

As discussed in the issue #1262 I proposed here a minimal implementation of an item mimicking the pcolormesh function of matplotlib.
As I didn't know what to do to make the pull request valid I decided to make it as minimal as possible.
I am willing to integrate it more into pyqtgraph if someone gives me some directions.
In particular a I think a kind of pColorMeshWidget with axis and Histogram would be an excellent end result of this work.

Fixes #146
Fixes #1262

@j9ac9k j9ac9k changed the base branch from develop to master June 24, 2020 03:37
@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 24, 2020

Updating the base to merge to master; I need to update CONTRIBUTING.md

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 24, 2020

Ooof...this CI is blowing up due to matplotlib not being installed... looking at the diff, matplotlib is wanted for the Normalize function, and for the viridis colormap.

An approximation of viridis is available in pygraph/graphicsItems/GradientEditorItem.py but I've been wanting to move the colormaps from matplotlib into this library in a way other libraries such as bokeh do. You can see how they make the color maps available here:

https://github.com/bokeh/bokeh/blob/7cc500601cdb688c4b6b2153704097f3345dd91c/bokeh/palettes.py

I understand that this is outside the scope of this PR, but having matplotlib as a test dependency is rough, especially for just those methods.

@ixjlyons
Copy link
Copy Markdown
Member

Ideally we'd have test coverage of the matplotlib exporter/widget, so it could be required for tests eventually anyway. That said, I agree it would be better to avoid requiring it for users for the color map.

Also the class name might be more consistent with the library as PseudoColorMeshItem or PColorMeshItem (latter might be more intuitive/recognizable).

@2xB
Copy link
Copy Markdown
Contributor

2xB commented Jun 24, 2020

For this PR, I did not have time for a reasonable review, just from first glance I noticed that the naming pColorMeshItem - especially with the lowercase prefix - does not fit the naming scheme used for pyqtgraph, which should probably be changed.

For matplotlib colormaps, I've found this repository by @honkomonk some time ago: https://github.com/honkomonk/pyqtgraph_sandbox It might not be the ideal way though, but maybe a good start if someone wants to look into that.

@2xB
Copy link
Copy Markdown
Contributor

2xB commented Jun 24, 2020

Also, if the last lines of the first comment are the following two, then GitHub automatically links the merge of this PR to closing the according issues:

Fixes #146
Fixes #1262

@honkomonk
Copy link
Copy Markdown

honkomonk commented Jun 25, 2020

Regarding the colormaps (so a bit off-topic):
tl;dr: In maptplotlib Viridis is just implemented as a list of 256 pre-computed colors, while in pyqtgraph's Gradient it's defined with only 5 colors. The easiest way for a more accurate Viridis colormap would be to just add more reference points.

The longer answer:
Matplotlib offers multiple methods for defining colormaps (1. equally spaces color values, like Viridis; 2. color values with positional argument, like in pyqtgraph; 3. functionally generated maps, like Cubehelix). In the code that @2xB cited I tried to convert all of them to pyqtgraph gradients. That's why it got so messy and I never got to clean it up for a PR.
I could image to integrate it into the ColorMap class as an importer for matplotlib cmaps.

Bokeh just copied matplotlibs color tables and converted them into their format. So no magic is happening there.

PS: It's an interesting story how Viridis was created: https://bids.github.io/colormap/

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jun 25, 2020

Hi all,

I removed all dependencies to matplotlib so that we can focus on the Item itself.
I also changed the name as suggested.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 25, 2020

all pipelines failed with:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/vsts/work/1/s/pyqtgraph/__init__.py", line 221, in <module>
    from .graphicsItems.PColorMeshItem import * 
ModuleNotFoundError: No module named 'pyqtgraph.graphicsItems.PColorMeshItem'
display information
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.8.3/x64/lib/python3.8/runpy.py", line 185, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "/opt/hostedtoolcache/Python/3.8.3/x64/lib/python3.8/runpy.py", line 111, in _get_module_details
    __import__(pkg_name)
  File "/home/vsts/work/1/s/pyqtgraph/__init__.py", line 221, in <module>
    from .graphicsItems.PColorMeshItem import * 
ModuleNotFoundError: No module named 'pyqtgraph.graphicsItems.PColorMeshItem'
openGL information
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/vsts/work/1/s/pyqtgraph/__init__.py", line 221, in <module>
    from .graphicsItems.PColorMeshItem import * 
ModuleNotFoundError: No module named 'pyqtgraph.graphicsItems.PColorMeshItem'

EDIT: I think you need to rename the file:

pyqtgraph/graphicsItems/pColorMeshItem.py to pyqtgraph/graphicsItems/PColorMeshItem.py

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jun 25, 2020

This is weird, I renamed all the files with an uppercase "P":
image

And the example file works on my laptop and gives this:
image

Is there a way for me to test these "pipeline" online before pushing anything?

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 25, 2020

you could try running pytest, which will run through the test suite and see what happens... (fair warning, if you have a hidpi display on windows, you'll see some failures that are unrelated). Since Windows is not case sensitive, you likely have some shenanigans at play.

I would recommend renaming the file to lower case in windows, then run

git mv pyqtgraph/graphicsItems/pColorMesh.py pyqtgraph/graphicsItems/PColorMesh.py

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jun 25, 2020

Ok, will try the pytest thing.
I followed your advice and I am going to bed now.
See you ;) .

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 25, 2020

FYI that looks to have done the trick, some pipelines have passed (some are still running).

EDIT: CI came back all green!

@2xB
Copy link
Copy Markdown
Contributor

2xB commented Jun 26, 2020

Just out of curiosity: Is the P there at the beginning out of a reason? I would imagine just ColorMeshItem to be simpler and more intuitive, so there is probably a reason against it?

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jun 26, 2020

Just out of curiosity: Is the P there at the beginning out of a reason? I would imagine just ColorMeshItem to be simpler and more intuitive, so there is probably a reason against it?

The idea was to copy the matplotlib function pcolormesh, see doc.
The "p" stands for pseudocolor and I don't really know it's meaning, in the doubt I would leave it.

@honkomonk
Very cool to have you here, you will be pleased to know that your function cmapToColormap helped years ago and I still use it:
image
Thanks for your work on that ;) .

@j9ac9k What will be the next step for me? I would like to have a final item with axis and histogram but would like your advice on the road to take to go there.

"""
**Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>`

TODO
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fill out docstring


self.axisOrder = getConfigOption('imageAxisOrder')

if cmap in list(Gradients.keys()):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to convert to a list here? doing in lookups in the dict.keys() I know works in python3, does it not work in python2? (added bonus of not converting to list, is that in lookups in the hashed objects are significantly faster.


if self.z is None:
return QtCore.QRectF(0., 0., 0., 0.)
return QtCore.QRectF(0., 0., float(self.width()), float(self.height())) No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line at the end of the file

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jun 26, 2020

@edumur this PR looks good to me, I made some in-line comments for suggested changes and questions. I haven't worked w/ these graphical objects before so I'm going to let some other folks around here give things a look over.

Thanks for the PR!

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jun 26, 2020

@j9ac9k ok, I will work on your comments and follow with a PColorMeshView that will offer axis and histogram as ImageView.

edumur added 3 commits June 26, 2020 18:12
Make an example displaying more clearly the Item capability.
Correct few bugs in the Item class.
Improve overall comments.
Allow user to set the polygons edge color.
@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jul 17, 2020

ok so what I did is putting myself in the examples folder and then did the git rename command.
Apparently doing this doesn't work
Let's see how it goes now.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jul 17, 2020

closer, all pyside pipelines are failing

----------------------------- Captured stdout call -----------------------------
PColorMeshItem 

Python 2.7.18 |Anaconda, Inc.| (default, Apr 23 2020, 22:42:48) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> >>> ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "PColorMeshItem.py", line 77, in <module>
    updateData()
  File "PColorMeshItem.py", line 72, in updateData
    new_z)
  File "/home/vsts/work/1/s/pyqtgraph/graphicsItems/PColorMeshItem.py", line 204, in setData
    QtCore.QPointF(self.x[xi][yi+1],   self.y[xi][yi+1]))
TypeError: drawConvexPolygon() takes exactly one argument (4 given)
>>> 
QPaintDevice: Cannot destroy paint device that is being painted
Fatal Python error: Segmentation fault

Current thread 0x00007fd0771a5580 <python> (most recent call first):

I can replicate locally with a PySide Qt bindings installed and running

pytest -k "PColorMeshItem"

(so you don't have to run the entire test suite).

In case it helps, here's the captured output from pytest when I ran locally

------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------
PColorMeshItem

Python 3.8.3 (default, Jun 19 2020, 21:28:39)
[Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> >>> ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py", line 77, in <module>
    updateData()
  File "/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py", line 70, in updateData
    pcmi.setData(new_x,
  File "/Users/ogi/Developer/pyqtgraph/pyqtgraph/graphicsItems/PColorMeshItem.py", line 201, in setData
    p.drawConvexPolygon(QtCore.QPointF(self.x[xi][yi],     self.y[xi][yi]),
TypeError: drawConvexPolygon() takes exactly one argument (4 given)
>>>

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jul 17, 2020

Doing a little work procrastination; tinkering with this, wrapping the qpoint's with a [] makes it work for pyside but it fails on with pyqt5

>>> >>> ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py", line 77, in <module>
    updateData()
  File "/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py", line 70, in updateData
    pcmi.setData(new_x,
  File "/Users/ogi/Developer/pyqtgraph/pyqtgraph/graphicsItems/PColorMeshItem.py", line 203, in setData
    p.drawConvexPolygon([QtCore.QPointF(self.x[xi][yi],     self.y[xi][yi]),
TypeError: arguments did not match any overloaded call:
  drawConvexPolygon(self, Union[QPointF, QPoint], *): argument 1 has unexpected type 'list'
  drawConvexPolygon(self, QPolygonF): argument 1 has unexpected type 'list'
  drawConvexPolygon(self, QPoint, *): argument 1 has unexpected type 'list'
  drawConvexPolygon(self, QPolygon): argument 1 has unexpected type 'list'
>>>

will keep messing with it...

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jul 17, 2020

Got it working with both configurations made the change in PColorMeshItem.py such that drawConvexPolygon() took a QPolygonF type object.

                polygon = QtGui.QPolygonF(
                    [QtCore.QPointF(self.x[xi][yi],     self.y[xi][yi]),
                     QtCore.QPointF(self.x[xi+1][yi],   self.y[xi+1][yi]),
                     QtCore.QPointF(self.x[xi+1][yi+1], self.y[xi+1][yi+1]),
                     QtCore.QPointF(self.x[xi][yi+1],   self.y[xi][yi+1])]
                )

                # DrawConvexPlygon is faster
                p.drawConvexPolygon(polygon)

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jul 17, 2020

I am thankful !
I will integrate the change in a few days.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jul 21, 2020

I'm good with this as is, @ixjlyons any other requested changes?

Copy link
Copy Markdown
Member

@ixjlyons ixjlyons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good to me. There are some issues with docs noted with line comments (sidenote: maybe we should have a docs build job just to catch warnings and errors before merging).

Also, I don't know if anyone else is observing this, but the example shows some artifacts at the edges of the mesh when I zoom and pan around. I'll try to put up a screenshot later today.

GridItem
HistogramLUTItem
ImageItem
PColorMeshItem
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually sure these "make" files do anything in the current docs build. I'm not aware of something like this being part of sphinx - my guess is this was part of an older build setup to generate the stub files for the API reference. Could you copy one of the other files in the doc/source/graphicsItems folder?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand what you mean by "Could you copy one of the other files in the doc/source/graphicsItems folder?".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now at least, the API docs are manually created, so the .rst files in doc/source/graphicsItems/ are all stub files with pretty much the same content. So the idea was to copy one of those files and replace the class name with PColorMeshItem. legenditem.rst would be a good example since it includes the top class-level doc and the __init__ method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, the file looks like this:

PColorMeshItem
==============

.. autoclass:: pyqtgraph.PColorMeshItem
    :members:

    .. automethod:: pyqtgraph.PColorMeshItem.__init__

If x and y is None, the polygons will be displaced on a grid
otherwise x and y will be used as polygons vertices coordinates as:

(x[i+1, j], y[i+1, j]) (x[i+1, j+1], y[i+1, j+1])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These diagrams probably need to be put in a code environment to render correctly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I do that?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can take a look at how matplotlib is doing it: https://matplotlib.org/3.3.0/_modules/matplotlib/axes/_axes.html#Axes.pcolormesh

Basically, you can make a double-colon :: where you already have one and then indent the code block one level more than the text it's surrounded by.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, it looks like this:

"""
            otherwise x and y will be used as polygons vertices coordinates as::

                (x[i+1, j], y[i+1, j])           (x[i+1, j+1], y[i+1, j+1])
                                    +---------+
                                    | z[i, j] |
                                    +---------+
                    (x[i, j], y[i, j])           (x[i, j+1], y[i, j+1])
"""

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Jul 22, 2020

Yep, I see the artifacts as well:
image

I tried to remove them but so far it didn't work.
My guess is that since the y axis change over time the height function return a value to the boundingRect function which exclude part of the previous QPicture and so leave these artifacts.

return

profile('p.drawPicture')
p.drawPicture(0, 0, self.qpicture)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may be able to redo this as something like

if self.qpicture is not None:
    self.qpicture.play(p)

The implementation taken from TargetItem.py https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/graphicsItems/TargetItem.py#L73-L76

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, that probably does nothing, was reading the docs:

This function does exactly the same as QPainter::drawPicture() with (x, y) = (0, 0).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so this is clearly it because if I add a coefficient in the boundingRect method to return, for instance, QtCore.QRectF(0., 0., float(self.width())*2., float(self.height())*2.) then the artifacts disappear.

I tried fix to make it better but so far it didn't work well...


if shapeChanged:
self.informViewBoundsChanged()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this would change the result of boundingRect(), then you should also call self.prepareGeometryChange().
See: https://doc.qt.io/qt-5/qgraphicsitem.html#boundingRect




def boundingRect(self):
Copy link
Copy Markdown
Member

@campagnola campagnola Sep 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: returning QtCore.QRectF(self.picture.boundingRect()) here might help with the motion artifacts.
(See BarGraphItem for example)

@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Sep 23, 2020

Thanks all, I implemented your suggestions.
Unfortunately the "artifacts" are still here.
They basically appear because a polygon is drawn somewhere at one frame and not erase at the next frame because its location does not overlap other polygons of that frame...
It is clearly not an issue for static data visualization.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 10, 2020

hey @edumur just wanted to let you know I haven't forgotten about this, I want to get this merged as this is an awesome feature. I just started experimenting w/ QPainter for the first time on my own project; I feel like there must be something really small to try and capture those artifacts... I'm messing around w/ your branch locally (I moved recently so I took a bit of a break from dev work while I got unpacked).

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 10, 2020

I'm likely not telling you anything you don't know; but doing some debugging here, and I suspect the issue is that your boundRect() value is changing, but you're not calling prepareGeometryChange() beforehand (even w/ @campagnola 's changes)

I added a couple of print statements

        if shapeChanged:
            self.informViewBoundsChanged()
            self.prepareGeometryChange()
            print("shape changed")

and

    def paint(self, p, *args):
        profile = debug.Profiler()
        if self.z is None:
            return

        profile('p.drawPicture')
        p.drawPicture(0, 0, self.qpicture)
        print(self.boundingRect())

wanting the console I get the following

pyqtgraph-pyqt5-latest ❯ python -m examples
/Users/ogi/.zinit/plugins/pyenv---pyenv/versions/3.8.3/Python.framework/Versions/3.8/lib/python3.8/runpy.py:127: RuntimeWarning: 'examples.__main__' found in sys.modules after import of package 'examples', but prior to execution of 'examples.__main__'; this may result in unpredictable behaviour
  warn(RuntimeWarning(msg))
qt.qpa.fonts: Populating font family aliases took 296 ms. Replace uses of missing font family "FreeMono" with one that exists to avoid this cost.
Using PyQt5 (default graphics system)
shape changed
/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py:75: DeprecationWarning: an integer is required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.
  QtCore.QTimer.singleShot(1000/fps, updateData)
PyQt5.QtCore.QRectF(1.0, 0.0, 54.0, 47.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 48.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 48.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 46.0)
PyQt5.QtCore.QRectF(1.0, 0.0, 54.0, 45.0)

So we're having boundingRect change, but not calling prepareGeometryChange ahead of time... I'll see If I can see if we can determine more accurately when the boundingRect changes...

EDIT:

so storing the boundingRect() and at the end of setData() checking to see if self.boundingRect() is different from the previous stored one does result in a playback w/ no artifacts, but the image is definitely more...jumpy

        currentBoundingRect = self.boundingRect()
        if currentBoundingRect != self.previousBoundingRect:
            self.previousBoundingRect = currentBoundingRect
            self.prepareGeometryChange()
            self.informViewBoundsChanged()
            print("shape changed")
PyQt5.QtCore.QRectF(1.0, 0.0, 54.0, 47.0)
shape changed
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 49.0)
shape changed
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 50.0)
shape changed
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
PyQt5.QtCore.QRectF(1.0, -2.0, 54.0, 49.0)
shape changed
PyQt5.QtCore.QRectF(1.0, -1.0, 54.0, 47.0)

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 10, 2020

Ha, I think I got it, sure enough, a pretty dead simple change; move self.prepareGeometryChagne() to be outside the if shapeChanged block (just have that line run at the end of setData())... I'm not sure some of the colors within the PColorMeshItem are quite right (maybe not?) but there are no visible artifacts away from the animated body.


# We set the pen of all polygons once
if self.edgecolors is None:
p.setPen(QtGui.QColor(0, 0, 0, 0))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need to do p.setPen(fn.mkPen(QtGui.QColor(0, 0, 0, 0))) as I think setPen requires a QPen object

if np.any(self.x != args[0]) or np.any(self.y != args[1]):
shapeChanged = True

profile = debug.Profiler()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useful for debugging, but might as well remove from the version we merge.

for yi in range(self.z.shape[1]):

# Set the color of the polygon first
# print(xi, yi, norm[xi][yi])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for commented out print statement

# Set the color of the polygon first
# print(xi, yi, norm[xi][yi])
c = lut[norm[xi][yi]]
p.setBrush(QtGui.QColor(c[0], c[1], c[2]))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should also wrap this with a fn.mkBrush()

new_z)

i += wave_speed
QtCore.QTimer.singleShot(1000/fps, updateData)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting a deprecation warning here for using float

/Users/ogi/Developer/pyqtgraph/examples/PColorMeshItem.py:75: DeprecationWarning: an integer is required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.
  QtCore.QTimer.singleShot(1000/fps, updateData)

Probably should change this line to:

QtCore.QTimer.singleShot(1000//fps, updateData)


self.qpicture = QtGui.QPicture()
p = QtGui.QPainter(self.qpicture)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

totally optional here, but I've been experimenting on my own, but consider setting the anti-aliassing render hint

        p.setRenderHint(QtGui.QPainter.Antialiasing)

With this set, the lines were actually visible on my screen; admittedly that may not be what you want.

Add a parameter "antialiasing".
Remove profiler
Add pyqtgraph mkPen
@edumur
Copy link
Copy Markdown
Contributor Author

edumur commented Oct 12, 2020

Hi @j9ac9k,

Thanks for the comments.
I believed to have implemented everything you described.
I added an optional parameter to take into account the antialiasing.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 12, 2020

That's absolutely perfect; thanks so much for this feature @edumur , merging!

@j9ac9k j9ac9k merged commit 3f7a9bb into pyqtgraph:master Oct 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposition of equivalent item to pcolormesh from matplotlib 2D colormesh plot

6 participants