FIX: Contour lines rendered incorrectly when closed loops#19623
FIX: Contour lines rendered incorrectly when closed loops#19623QuLogic merged 6 commits intomatplotlib:masterfrom
Conversation
|
As you mentioned in the issue, the C++ code creates the codes, and it seems like those are returned in both cases: matplotlib/lib/matplotlib/contour.py Line 826 in 0b9a0fe Can you not use that in the _make_paths call?
|
|
Ah no, I see it doesn't: matplotlib/lib/matplotlib/contour.py Lines 1399 to 1416 in 0b9a0fe But wouldn't it be less trouble to go to that directly? |
Not really. Returning the kind codes from C++ would save us a few lines of Python but make the C++ more complicated, and it needs to be in both [Aside: The major performance issue for contour lines in the example here is that Python/C++ create 318k numpy arrays of vertices and 318k numpy arrays of kind codes which are passed to the renderer for consumption. That is a lot of memory thrashing. It is only done this way because it was necessary for the 'new' (2014) contour algorithm to match the 'old' (2005) one. After 7 years I think we can be brave enough to change this to, for example, a smaller number of larger numpy arrays. But that needs to be done carefully and is outside the scope of this PR.] As you have asked, I have added a commit that returns the kind codes from the C++. Interestingly it is marginally slower than the Python-only solution but my timings are not comprehensive. I'd be happy to roll back the PR to the Python-only changes if that is preferred. It is certainly simpler and lower risk. |
9e14863 to
178012d
Compare
3d6bfb9 to
f8b6a5c
Compare
|
Tests are passing now that I have modified the examples and mplot3d in line with the other changes. I've also added some new tests to increase the coverage. There are two possible solutions here:
Either would be acceptable in terms of fixing the problem. I slightly favour of the C++ approach but could be persuaded either way. It is riskier than the Python-only solution in that there will almost certainly be some glitches caused by it, but I have the time and motivation to deal with these so now seems as good a time as any. |
|
I guess I don't understand the tradeoffs in putting the work in the C++ code. Certainly there are a lot of changes, but they seem to be mostly just adding codes to the structure? The python changes are simpler, so what is the goal of pushing it down to C++? |
|
The two implementations (Python and C++) are functionally equivalent and produce identical output. The difference is where the codes are calculated. The benefit of the C++ implementation is that it is faster at determining if each contour line is a closed line loop or open line strip. However, this performance benefit is not a practical benefit as the time taken to create lots of numpy arrays swamps everything else. When I eventually improve the performance of contouring this will become important, but it isn't yet. |
jklymak
left a comment
There was a problem hiding this comment.
This seems fine, and the tests look good. I wonder if this is an opportunity to ask for a few more comments, particularly in the C++ code as a guide to the uninitiated. These don't have to be voluminous, but a few more guideposts as to what is going on would be helpful?
|
The git diff isn't hugely helpful here; looking at the changed C++ is probably better as the relationship between the vertices and codes arrays is more obvious. But yes, I am happy to add more comments. |
|
@jklymak I've added more comments to |
jklymak
left a comment
There was a problem hiding this comment.
I'm going to approve, because it looks complete, there are good amount of comments, and there are new tests. I'm not at all claiming I followed all of it ;-)
Also, update documentation for Attributes. Followup to matplotlib#19623; fixes matplotlib#20906.
Also, update documentation for Attributes. Followup to matplotlib#19623; fixes matplotlib#20906.
Also, update documentation for Attributes. Followup to matplotlib#19623; fixes matplotlib#20906.
Also, update documentation for Attributes. Followup to matplotlib#19623; fixes matplotlib#20906.
PR Summary
Fixes issue #19568 so that closed contour line loops are rendered correctly.
Solution is to use
PathCollections rather thanLineCollections, the same as for filled contours. Added a specific test for this, and updated the 11 test images affected by the change.To test the performance impact I've used the following code:
which creates an 8000x4000 PNG with 117,000 line loops and 201,000 line strips. I timed it before and after this PR, 10 times each (yes I should have used
timeitbut I didn't) and the walltimes are:So minimum run time is 2.3% slower, mean run time is 1.8% slower. Let's call it 2% slower (on my new but cheap laptop). It is slower for 2 reasons:
Item 2 could be made faster by moving the calculations from Python to C++. I would prefer to not to that now and instead consider it as part of a larger study into improving contouring performance.
PR Checklist
pytestpasses).flake8on changed files to check).flake8-docstringsand runflake8 --docstring-convention=all).doc/users/next_whats_new/(follow instructions in README.rst there).doc/api/next_api_changes/(follow instructions in README.rst there).