Skip to content
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

Arrow annotations behave differently between 1.3.1 and 1.4.2 #4012

Closed
QuLogic opened this issue Jan 19, 2015 · 22 comments
Closed

Arrow annotations behave differently between 1.3.1 and 1.4.2 #4012

QuLogic opened this issue Jan 19, 2015 · 22 comments
Assignees
Labels
Difficulty: Medium https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues topic: mpl_toolkit
Milestone

Comments

@QuLogic
Copy link
Member

QuLogic commented Jan 19, 2015

Sorry, here's another one without a simplified test case. I will try and get to that tomorrow. For this, you will need matplotlib 1.4.2 and the development version of ObsPy. Then run obspy3-runtests -d obspy.station.tests.test_station.StationTest.test_response_plot. Test case is below.

With mpl 1.3.1, the plot is as so:
station_response

With mpl 1.4.2 (and master), the plot is as so:
station_response

station_response-failed-diff

You can see that the arrows are thinner and shifted a bit.

I believe the relevant bit of code is the following, but I will try to simplify it later:

            trans_above = blended_transform_factory(ax1.transData,
                                                    ax1.transAxes)
            trans_right = blended_transform_factory(ax1.transAxes,
                                                    ax1.transData)
            arrowprops = dict(
                arrowstyle="wedge,tail_width=1.4,shrink_factor=0.8", fc=color)
            bbox = dict(boxstyle="round", fc="w")
            ax1.annotate("%.1g" % self.instrument_sensitivity.frequency,
                         (self.instrument_sensitivity.frequency, 1.0),
                         xytext=(self.instrument_sensitivity.frequency, 1.1),
                         xycoords=trans_above, textcoords=trans_above,
                         ha="center", va="bottom",
                         arrowprops=arrowprops, bbox=bbox)
            ax1.annotate("%.1e" % self.instrument_sensitivity.value,
                         (1.0, self.instrument_sensitivity.value),
                         xytext=(1.05, self.instrument_sensitivity.value),
                         xycoords=trans_right, textcoords=trans_right,
                         ha="left", va="center",
                         arrowprops=arrowprops, bbox=bbox)

I did a bisect and the bad commit was:

3363b125715724ad89d4b33cbddb23e31e7277d5 is the first bad commit
commit 3363b125715724ad89d4b33cbddb23e31e7277d5
Author: Thomas A Caswell <tcaswell@gmail.com>
Date:   Tue Aug 27 17:07:58 2013 -0500

    re factored `_AnnoationBase` to push keeping track of there the
    secondary object is to the sub-classes.

    Added properties to maintain back-compatibility

    added properties to replace xytext and textcoords (xyann, anncoords)

    properly deprecated `textcoord` and `xytext` in favor of `anncoords`
    and `xyann`.

:040000 040000 f17d8e1a70232471435f96b1faa8550bc697ec32 567d4a0a86bb3d1fb7ec55dc0fa98e86c1dec71a M  doc
:040000 040000 34339e9d0d9f49477908fc3c3227b1b7b55735b4 4dc225e1358d422aa86f9361672c36e127955bee M  lib
@tacaswell
Copy link
Member

man, that commit message is embarrassing ...

@tacaswell tacaswell added this to the v1.4.3 milestone Jan 19, 2015
@tacaswell tacaswell self-assigned this Jan 19, 2015
@tacaswell
Copy link
Member

I suspect something subtle got broken when annotations changed from a 'has-a' to 'is-a' Text object.

My guess is that something changed about where the base of the arrow is calculated and poor interaction with the FancyArrowPatch object that gets created.

I am some what more distressed by the extra blue lines around the vertical blue dashed lines.

@tacaswell
Copy link
Member

in _update_positoin_xytext there are a bunch of calls to get_window_extent which is where I suspect the issue is (as the reported extent of the annotation object may have changed.

(mostly notes to my self)

@WeatherGod
Copy link
Member

"something changed about where the base of the arrow is calculated"

This sounds familiar. I think we fixed a real bug wrt how the arrow was
positioned awhile back.

On Mon, Jan 19, 2015 at 11:49 AM, Thomas A Caswell <notifications@github.com

wrote:

I suspect something subtle got broken when annotations changed from a
'has-a' to 'is-a' Text object.

My guess is that something changed about where the base of the arrow is
calculated and poor interaction with the FancyArrowPatch object that gets
created.

I am some what more distressed by the extra blue lines around the vertical
blue dashed lines.


Reply to this email directly or view it on GitHub
#4012 (comment)
.

@tacaswell
Copy link
Member

@WeatherGod How recently?

@WeatherGod
Copy link
Member

Perhaps this (or one of the ones referenced in it)?
#566
But, for some reason, I am thinking of something more recently (like, a bug
fixed for 1.3.x)

On Mon, Jan 19, 2015 at 2:57 PM, Thomas A Caswell notifications@github.com
wrote:

@WeatherGod https://github.com/WeatherGod How recently?


Reply to this email directly or view it on GitHub
#4012 (comment)
.

@QuLogic
Copy link
Member Author

QuLogic commented Jan 20, 2015

For a simpler example, I took the annotation_demo.py example and changed the arrowprops to match the one in ObsPy.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse


fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-1,5), ylim=(-3,5))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2 * np.pi * t)
ax.plot(t, s, lw=3, color='purple')

arrowprops = dict(arrowstyle="wedge,tail_width=1.4,shrink_factor=0.8")

ax.annotate('axes center', xy=(.5, .5),  xycoords='axes fraction',
            horizontalalignment='center', verticalalignment='center',
            arrowprops=arrowprops)

ax.annotate('pixels', xy=(20, 20),  xycoords='figure pixels',
            arrowprops=arrowprops)

ax.annotate('points', xy=(100, 300),  xycoords='figure points',
            arrowprops=arrowprops)

ax.annotate('offset', xy=(1, 1),  xycoords='data',
            xytext=(-15, 10), textcoords='offset points',
            horizontalalignment='right', verticalalignment='bottom',
            arrowprops=arrowprops)

ax.annotate('local max', xy=(3, 1),  xycoords='data',
            xytext=(0.8, 0.95), textcoords='axes fraction',
            horizontalalignment='right', verticalalignment='top',
            arrowprops=arrowprops)

ax.annotate('a fractional title', xy=(.025, .975),
            xycoords='figure fraction',
            horizontalalignment='left', verticalalignment='top',
            fontsize=20,
            arrowprops=arrowprops)

ax.annotate('bottom right (points)', xy=(-10, 10),
            xycoords='axes points',
            horizontalalignment='right', verticalalignment='bottom',
            fontsize=20,
            arrowprops=arrowprops)

plt.show()

Here is 1.3.1:
mpl131

Here is 1.4.2:
mpl142

And the diff:
diff

I'm not sure if this adequately replicates the above issue, but it does point to xycoords='axes points' being broken in some way.

@QuLogic
Copy link
Member Author

QuLogic commented Jan 20, 2015

I am some what more distressed by the extra blue lines around the vertical blue dashed lines.

Yea, that's odd too. I will try to see where those lines originate.

@QuLogic
Copy link
Member Author

QuLogic commented Jan 21, 2015

I am some what more distressed by the extra blue lines around the vertical blue dashed lines.

Yea, that's odd too. I will try to see where those lines originate.

I honestly don't know where these are from, and they stopped showing up, so I wouldn't worry about them.

@tacaswell
Copy link
Member

this seems to be fixed by #4019

@QuLogic
Copy link
Member Author

QuLogic commented Jan 21, 2015

I'm sorry, it seems that simple example exposes a different bug. Here is a test case that should only trigger the bug in the first post:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import blended_transform_factory

fig = plt.figure()
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-1,5), ylim=(-3,5))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2 * np.pi * t)
ax.plot(t, s, lw=3, color='purple')

trans_above = blended_transform_factory(ax.transData,
                                        ax.transAxes)
trans_right = blended_transform_factory(ax.transAxes,
                                        ax.transData)

bbox = dict(boxstyle="round", fc="w")

arrowprops = dict(arrowstyle="wedge,tail_width=1.4,shrink_factor=0.8")

ax.annotate("0.1",
            (3, 1.0),
            xytext=(3, 1.1),
            xycoords=trans_above, textcoords=trans_above,
            ha="center", va="bottom",
            arrowprops=arrowprops, bbox=bbox)

ax.annotate("0.2",
            (1.0, 0.75),
            xytext=(1.05, 0.75),
            xycoords=trans_right, textcoords=trans_right,
            ha="left", va="center",
            arrowprops=arrowprops, bbox=bbox)

plt.show()

With 1.3.1:
mpl131
and with 1.4.2:
mpl142
Diff:
diff

If you remove the bbox, they work the same.

@tacaswell tacaswell added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jan 31, 2015
@tacaswell
Copy link
Member

Digging into this I still have no idea what the problem is. My suspicion is that something I changed had a crucial side effect...

@tacaswell
Copy link
Member

I am going to take one more pass at this tomorrow, if I can't figure it out I am going to boot this to 1.4.x as this seems to be only an issue when using both the FancyArrowPatch and FancyBoundingBox at the same time.

@tacaswell tacaswell removed the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Feb 1, 2015
@tacaswell tacaswell modified the milestones: v1.4.x, v1.4.3 Feb 2, 2015
@tacaswell tacaswell added the Difficulty: Medium https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues label Feb 7, 2015
@tacaswell tacaswell modified the milestones: v1.5.x, v1.4.x Feb 7, 2015
@tacaswell
Copy link
Member

attn @leejjoon Can you point me in the right direction on this? I think something in getting out of sync in updating where the center of the text is with the bounding box.

@tacaswell tacaswell modified the milestones: next point release, proposed next point release Jul 22, 2015
@tacaswell
Copy link
Member

@QuLogic Can you check your examples with current master, I think #4178 fixes part of the issues.

so

@QuLogic
Copy link
Member Author

QuLogic commented Jul 22, 2015

It's pretty close now. There's a slight difference in the box, but that may be due to font changes (the tick labels have also shifted a little)?

mpl-master-diff

@tacaswell
Copy link
Member

I am more concerned about the shift in the plotted line. Did you make the diff from my png, or from running it on your system?

@QuLogic
Copy link
Member Author

QuLogic commented Jul 22, 2015

From running it on my system, using the original mpl131.png I generated a while back for reference (which is byte-for-byte the same as the one here, it seems.)

@efiring
Copy link
Member

efiring commented Jul 22, 2015

On 2015/07/22 10:47 AM, Thomas A Caswell wrote:

I am more concerned about the shift in the plotted line.

That looks to me like a difference in rendered width, not in position.

@QuLogic
Copy link
Member Author

QuLogic commented Jul 22, 2015

If you're really interested in the shift, the bisect was inconclusive:

There are only 'skip'ped commits left to test.
The first bad commit could be any of:
4a56cda
cfbf8d5
339537d
8dae818
6e19dac
a225968
697b3ef
c5ab747
5204635
af578f5
0624664
6d07179
ba40160
d862c47
d8c1d0d
We cannot bisect more!
bisect run cannot continue any more

@tacaswell
Copy link
Member

@QuLogic That is inside of the massive re-work of how we expose Agg up to python.

We have also done some changes to how white space around fonts is handled.

@mdboom I am inclined to call this good enough?

tacaswell added a commit to tacaswell/matplotlib that referenced this issue Jul 31, 2015
…rds"

This reverts commit d6e1577, reversing
changes made to b280f7d.

For 1.4.0 tacaswell refactored annotations (matplotlib#2351 ) but missed that
{'axes points', 'axes pixel', 'figure points', 'figure pixel'} were
special cased to wrap. Presumably from the function name to maintain
back compatibility. This was an unintentional and undocumented API
break.

This API break was noticed in matplotlib#4012 and fixed in matplotlib#4019 but that catches
too many of the coordinate systems (should not be all things that start
with 'axes') so fixed one API, but broke others.

There were two reasonable courses of action:

    1. revert back to 1.4.2 behavior with nothing wrapping.
    2. revert back to 1.3.1 behavior with somethings wrapping.

In the discussion in matplotlib#4292 where the consensus was to go with
option 1, hence this reversion.
@tacaswell
Copy link
Member

Closing this as 'good enough'.

@QuLogic Please ping to have this re-opened if you disagree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Medium https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues topic: mpl_toolkit
Projects
None yet
Development

No branches or pull requests

4 participants