Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Issue #3755 Bug Fix for: Shapes and Annotations With yref Parameter Not Drawing on Correct Axis #4177

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

@zfoltz
Copy link
Contributor

@zfoltz zfoltz commented Apr 27, 2023
edited
Loading

This PR is related to issue #3755 which, to put more generally, is that shapes and annotations when supplied with a yref parameter are automatically drawn on the primary y-axis despite the supplied yref value. The only way that a shape or annotation can currently be drawn on an axis that differs from the primary axes is when the figure object is created with subplots.make_subplots() with the specs list parameter set to 'secondary_y':True for that specific subplot. In the case of a non-subplotted figure object, it is impossible as the following line:

self.layout[layout_obj][-1].update(xref="x", yref="y")
explicitly sets yref = 'y' when there is not more than one subplot. It is also possible to make a figure object with subplot grid of (1,1) when using plotly express. Using that method there is no way to allow the secondary_y:True to the figure object therefore specifying yref will result in the shape or annotation plotting on the primary y axis regarless of the specified yref and if the secondary_y=True parameter is supplied in the method to add the shape or annotation, that will result in the following error:
if len(refs) == 1 and secondary_y:
raise ValueError(
"""
Cannot add {prop_singular} to secondary y-axis of subplot at position ({r}, {c})
because subplot does not have a secondary y-axis"""
)

This error is also missing it's string.format() method and parameters which are fixed in this as well.

For subplots that use the subplots.make_subplots() with the specs list parameter set to 'secondary_y':True this change does not cause the loss of any functionality it just extends the ability to draw shapes and annotations on additional y-axes when generating figure objects without the subplots.make_subplots() method. Specifying yref and if the secondary_y parameters will not result in an error when used with plotly express (a figure object with a (1,1) subplot grid) or a non subplotted figure object (such as when using go.Figure()), it will just proceed with applying it to the specified yref.

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the codegen files and not generated files.
  • I have added tests (if submitting a new feature or correcting a bug) or
    modified existing tests.
  • For a new feature, I have added documentation examples in an existing or
    new tutorial notebook (please see the doc checklist as well).
  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.
  • For a new feature or a change in behaviour, I have updated the relevant docstrings in the code to describe the feature or behaviour (please see the doc checklist as well).

zfoltz and others added 11 commits April 21, 2023 16:15
Copy link
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

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

@zfoltz this looks great - thanks!! Very nice tests 🎉
💃 Will merge once the tests pass.

Copy link
Collaborator

Hmm the doc build test looks like it might point to a bug here?

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_length", y="sepal_width", facet_col="species")
# sources of images
sources = [
 "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Iris_setosa_var._setosa_%282595031014%29.jpg/360px-Iris_setosa_var._setosa_%282595031014%29.jpg",
 "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Iris_versicolor_quebec_1.jpg/320px-Iris_versicolor_quebec_1.jpg",
 "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Iris_virginica_2.jpg/480px-Iris_virginica_2.jpg",
]
# add images
for col, src in enumerate(sources):
 fig.add_layout_image(
 row=1,
 col=col + 1,
 source=src,
 xref="x domain",
 yref="y domain",
 x=1,
 y=1,
 xanchor="right",
 yanchor="top",
 sizex=0.2,
 sizey=0.2,
 )
fig.show()

Gives the error:

ValueError:
 Invalid value of type 'builtins.str' received for the 'yref' property of layout.image
 Received value: 'y domain domain'

Copy link
Collaborator

Also we should add a changelog entry for this fix 🎉

Copy link
Contributor Author

zfoltz commented May 8, 2023

Yes, you are right! From the looks of it, I think there is a pretty straightforward fix, I'll try to verify and update later today. Thanks for taking a look at this!

Copy link
Contributor Author

zfoltz commented May 10, 2023

The bug showing in the build-doc is fixed and I updated changelog! 👍

  • I have added a CHANGELOG entry if fixing/changing/adding anything substantial.

Copy link

endursa commented May 11, 2023

I tried the bugfix, and while the hline is now working if set to yref=y3 for example, an annotation_text is not displayed at all!

Copy link
Contributor Author

zfoltz commented May 12, 2023
edited
Loading

Hey @endursa, can you post what you are working with? I tried to reproduce the error you mentioned but the following test I ran is working correctly:

import plotly.graph_objects as go
fig = go.Figure()
fig.add_traces(go.Scatter(x=[1,2,3],y=[1,2,3], yaxis='y',name='y1 trace'))
fig.add_traces(go.Scatter(x=[1,2,3],y=[3,2,1], yaxis='y2',name='y2 trace'))
fig.add_traces(go.Scatter(x=[2,3,4],y=[4,4,3], yaxis='y3',name='y3 trace'))
fig.add_hline(y=3, yref='y3', label={'text':'hline annotation text on y3'})
fig.add_hrect(y0=3.5, y1=4, annotation_text='hrect annotation text on y3', yref='y3')
fig.update_layout(
 xaxis=dict(domain=[0, 0.9]),
 yaxis=dict(title="yaxis1 title"),
 yaxis2=dict(title="yaxis2 title",overlaying="y",side="right",position=0.9,),
 yaxis3=dict(title="yaxis3 title",overlaying="y",side="right",position=1,)
)
fig.show()

This results in the following plot:
image

So maybe I'm misunderstanding what you mean by an annotation_text or it could be something else causing the bug. Can you please post a MWE or provide details on how you generate the non-displayed annotation-text? Is it a subplotted figure object or non-subplotted figure object? Is the annotation text supposed to be on an hline,hrect,layout_image,etc.? I'm happy to investigate but just can't seem to reproduce it.

Copy link

endursa commented May 12, 2023
edited
Loading

yes of course, my problem looks like this:
import plotly
import plotly.graph_objects as go

fig = go.Figure()
fig.add_traces(go.Scatter(x=[1,2,3],y=[-0.009,-0.008,-0.01], yaxis='y',name='y1 trace'))
fig.add_traces(go.Scatter(x=[2,3,4],y=[-50,-52,-58], yaxis='y3',name='y3 trace'))
fig.add_hline(y=-58., 
 line_color='darkblue',
 yref = 'y3',
 line_dash='dot',
 annotation_text='annotation goes here (y3)',
 annotation_position='bottom right'
 )
fig.add_hline(y=-52., 
 line_color='darkblue',
 yref = 'y3',
 line_dash='dot',
 annotation_text='annotation goes here (y3)',
 annotation_position='bottom right'
 ) 
fig.update_layout(
 xaxis=dict(
 title='some x axis',
 domain=[0.04,0.92],
 range=['2023-1-1','2024-1-1']), 
 yaxis=dict(
 title='some y axis',
 range=[-0.017,-0.0068],
 gridcolor='lightgrey'
 ),
 yaxis3=dict(
 title='another y axis',
 anchor='x',
 overlaying='y',
 side='right',
 tickmode='array',
 tickvals=[-52,-55,-58],
 range=[-60,-21],
 ),
)
plotly.offline.plot(fig,filename='plot_temp.html')

If one changes the yaxis range to

Figure 2023年05月12日 095508

range=[-60,-0.0068]
Figure 2023年05月12日 095556

the annotation and another hline appear

sideinfo:
I am running Python 3.10.9

Copy link
Contributor Author

zfoltz commented May 12, 2023
edited
Loading

Thanks for pointing this out and the code @endursa! Looks like I've got it figured out. It appears that when using the annotation_text parameter, the add_annotation function is called without passing the supplied yref see https://github.com/plotly/plotly.py/blob/fc3ef002c7a7898b9244b1549757a64e8df266dd/packages/python/plotly/plotly/basedatatypes.py#L4031-4037
So what is happening is the annotation is showing on the primary y and your shape is showing on the yaxis corresponding to the yref given. Interestingly, adding annotation text by passing text values in the label parameter such as:
label={'text':'my custom annotation'}
actually operates differently under the hood and therefore does not result in this bug. Regardless, I added the necessary yref kwarg to the offending function call and now it's working properly.

endursa reacted with thumbs up emoji

Copy link

endursa commented May 15, 2023

Thank you very much!
As far as my use case is concerned, it works now as expected :)

Copy link
Contributor Author

zfoltz commented May 23, 2023
edited
Loading

Hey @alexcjohnson anything else needed before merge?

Copy link
Collaborator

Thanks for the nudge @zfoltz - I made a couple of minor changes, unfortunately I expect the tests will now fail not because of any issues here, but due to the same issue as in #4217 that I'm still trying to track down. Regardless, we'll get this into the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@alexcjohnson alexcjohnson alexcjohnson approved these changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /