Skip to content

Fix containment test with nonlinear transforms. #7844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Jan 16, 2017

Fixes #3540; see in particular #3540 (comment).

Edit: Also fixes #7655.

@mdboom Would it be reasonable to remove the definition of Transform.__array__ and only keep Affine2D.__array__, thus forcing call sites to explicitly only pass in affine transforms to the C++ code, rather than sometimes silently dropping the nonlinear part (as in this case)?

@codecov-io
Copy link

Current coverage is 62.10% (diff: 60.00%)

Merging #7844 into master will increase coverage by <.01%

@@             master      #7844   diff @@
==========================================
  Files           174        174          
  Lines         56051      56054     +3   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits          34808      34811     +3   
  Misses        21243      21243          
  Partials          0          0          

Powered by Codecov. Last update 3b9a92d...050b20c

@NelleV
Copy link
Member

NelleV commented Jan 28, 2017

Can you add a regression test?

@anntzer
Copy link
Contributor Author

anntzer commented Jan 28, 2017

Done.

NelleV
NelleV previously approved these changes Jan 28, 2017
Copy link
Member

@NelleV NelleV left a comment

Choose a reason for hiding this comment

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

It looks good.
Can you move the import at the top of module?

result = _path.point_in_path(point[0], point[1], radius, self,
transform)
return result
from .transforms import Affine2D
Copy link
Member

Choose a reason for hiding this comment

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

Any reason to have this here and not at the top of the module as python convention require?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably dates back to when I implemented this as a quickfix. Moved up.

@anntzer
Copy link
Contributor Author

anntzer commented Jan 28, 2017

Actually there is a circular import between transforms.py and path.py, so I left the Affine2D import inside the function, with a note to that effect.

@anntzer
Copy link
Contributor Author

anntzer commented Jan 28, 2017

Test failure is probably related to pytest migration... we can wait until it is done, as that seems close(?).

@NelleV NelleV changed the title Fix containment test with nonlinear transforms. [MRG+1] Fix containment test with nonlinear transforms. Jan 29, 2017
@NelleV
Copy link
Member

NelleV commented Jan 29, 2017

Let's wait until the pytest migration is over.

But, can we fix the circular import in a more robust way?

@anntzer
Copy link
Contributor Author

anntzer commented Jan 29, 2017

This would likely imply a small performance cost as transforms relies on passing a Path to update_path_extent to compute not only extremal points (which is just as cheap in numpy) but also minpos (and x[x > 0].min() is very likely slower than a C loop). (Fixing #7413 would probably help.)

@NelleV
Copy link
Member

NelleV commented Jan 29, 2017

I would feel much more comfortable with fixing the circular import.

@anntzer
Copy link
Contributor Author

anntzer commented Jan 29, 2017

There's also transform_path_affine, which currently reads

    def transform_path_affine(self, path):
        return Path(self.transform_affine(path.vertices),
                    path.codes, path._interpolation_steps)

and would have to become something like

    def transform_path_affine(self, path):
        return type(path)(self.transform_affine(path.vertices),
                    path.codes, path._interpolation_steps)

which is worse than a circular import IMO.

@NelleV NelleV changed the title [MRG+1] Fix containment test with nonlinear transforms. Fix containment test with nonlinear transforms. Jan 29, 2017
@NelleV NelleV dismissed their stale review January 29, 2017 20:39

I don't think this should be merge with a circular import.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 21, 2017

What is you preferred solution other than the circular import, then? As mentioned above I can work around it by obfuscating the implementation of transform_path_affine to sneakily get a handle to the Path class without a circular import, but that's not really better IMO.

# We need to import Affine2D here to prevent a circular import between
# the .path and .transforms modules.
from .transforms import Affine2D
if transform and not isinstance(transform, Affine2D):
Copy link
Member

Choose a reason for hiding this comment

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

Can't this be if not transform.is_affine: ? That seems way better that isinstance anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, done.

@anntzer anntzer force-pushed the nonlinear-transformed-path-containment branch from 7d67293 to ffd60aa Compare February 21, 2017 01:46
@tacaswell tacaswell added this to the 2.1 (next point release) milestone Feb 23, 2017
@anntzer anntzer changed the title Fix containment test with nonlinear transforms. [MRG] Fix containment test with nonlinear transforms. Mar 15, 2017
Copy link
Member

@NelleV NelleV left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@NelleV NelleV changed the title [MRG] Fix containment test with nonlinear transforms. [MRG+"] Fix containment test with nonlinear transforms. Mar 19, 2017
@NelleV NelleV changed the title [MRG+"] Fix containment test with nonlinear transforms. [MRG+1] Fix containment test with nonlinear transforms. Mar 19, 2017
polygon = ax.axvspan(1, 10)
assert polygon.get_path().contains_point(
ax.transData.transform_point((5, .5)), ax.transData)

Copy link
Member

Choose a reason for hiding this comment

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

May also be worth checking that the points (0.5, 0.5) and (20, 0.5) are not inside polygon

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

# transform the path ourselves. If `transform` is affine, letting
# `point_in_path` handle the transform avoids allocating an extra
# buffer.
if transform and not transform.is_affine:
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason not to just do the transformation here even if it is an affine transformation? (thus removing the if block)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess you may save the creation of a large temporary (if the c++ code does the transform one point at a time), which would be relevant for very large paths.

To be honest I don't know but decided not to take any risks.

@anntzer anntzer force-pushed the nonlinear-transformed-path-containment branch from ffd60aa to 76173e1 Compare March 19, 2017 19:11
Copy link
Member

@dstansby dstansby left a comment

Choose a reason for hiding this comment

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

👍 Will merge if/when tests pass

@dstansby dstansby self-assigned this Mar 19, 2017
@dstansby dstansby merged commit 0611b61 into matplotlib:master Mar 19, 2017
@dstansby dstansby changed the title [MRG+1] Fix containment test with nonlinear transforms. Fix containment test with nonlinear transforms. Mar 19, 2017
@anntzer anntzer deleted the nonlinear-transformed-path-containment branch March 19, 2017 20:33
@dstansby dstansby removed their assignment Apr 10, 2017
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.

Event picking does not seem to work on polar bar plots Pick events broken in log axes
5 participants