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

Axis auto-range improvements #1876

Open
etpinard opened this issue Jul 12, 2017 · 60 comments
Open

Axis auto-range improvements #1876

etpinard opened this issue Jul 12, 2017 · 60 comments
Labels
feature something new P3 not needed for current cycle

Comments

@etpinard
Copy link
Contributor

This issue attempts to combine ideas from several individual feature requests into coherent picture (i.e. the least number of new attribute possible).

In a private conversation with @alexcjohnson , we proposed adding two new (cartesian) axis attributes: bounds and boundmode. bounds would expect 2-item array values similar to the current range. bounds can be thought of as representing the maximum possible extend of the axis ranges. In turn, boundmode would determine if bounds applies during the auto-range routine (i.e. on first view - discuss in #1861 (comment)) or during interactions as well (as proposed in #887). For example,

xaxis: {
  autorange: true,
  boundmode: 'soft',
  bounds: [0, 100]
}

would restrict the auto-range logic to compute an x-axis range between 0 and 100. This might be useful when plotting percentages where users don't want the axis ranges to go beyond 100%.

xaxis: {
  boundmode: 'hard',
  bounds: [0, 100]
}

would restrict the axis range to [0,100] in the auto-range logic and during interactions.

In doing so, 1-way bounds values such as [null, 100] or [0, null] should be allowed. null items here mean don't restrict the min (or max) bound acting. This behavior is similar to cmin and cmax for color scales. This call signature should also be extended to the axis range attribute - taking care of #400


A few more things to think about:

@alexcjohnson
Copy link
Collaborator

One other idea we've discussed is autoranging one axis based on only the data that's visible on the opposite axis or axes - for example zoom in on a particular x range and autorange y based only on the x data in that range. Perhaps autorange: 'visible'?

@petergaultney
Copy link

Thanks to @cldougl for pointing me in this direction. I just want to throw my 2 cents in and say that, as per plotly/plotly.py#826, it would be nice if plots where all traces set fill tonexty or tozero did not automatically (or could be configured not to) eliminate all padding on the X and Y axes of cartesian plots. My use case involves adding markers to the lines that make up the filled traces, and those markers get "cut off" near the edges by the forced elimination of all padding around the plot.

@alexcjohnson
Copy link
Collaborator

@petergaultney thanks for the note - we definitely intend to make all of this more configurable. But another (fairly new) option that might be useful to you is plotly/plotly.py#1861 - cliponaxis: false, perhaps in conjunction with the layout option margin.pad.

@petergaultney
Copy link

sure enough, with those two options combined my problem is actually solvable. I set cliponaxis=False on each of my traces, and then added margin.pad on the layout. thanks!!

@etpinard
Copy link
Contributor Author

There's also #1022 about adding rangemode="symmetric" which sounds very reasonable.

@alexcjohnson
Copy link
Collaborator

From plotly/plotly.py#2083 - certain trace types (bars, fill to zero) currently force the axis autorange to include zero. We should let the user override that.

@apalchys
Copy link
Contributor

Does anyone have a clear picture how to combine all ideas?

Since #2158 closed in favor of this issue, I am ready to contribute but I think I need some guidance.

@etpinard
Copy link
Contributor Author

etpinard commented Nov 20, 2017

Since plotly/plotly.py#2158 closed in favor of this issue, I am ready to contribute but I think I need some guidance.

For resolving plotly/plotly.py#2158, I think all you need (API-wise) is adding autorange: 'once'.

That is, autorange: true (set or implied) would auto-range the axes every time new data comes in. autorange: 'once' would corresponds to the current (arguably-wrong) behavior.

@apalchys
Copy link
Contributor

@etpinard sorry, I am a little bit confused.
Based on the discussion above, I need autorange:'visible', not autorange:once

Demo: https://codepen.io/plotly-demo/pen/JOERgj
Expect behaviour for plotly/plotly.py#2158 is to enable autorange when a user changes visible area or scroll zoom in/out. @alexcjohnson described it here #1876 (comment)

Nevertheless, autorange: 'visible' brings an issue. For example, I want to have autorange when new data comes (auto) and enable autorange when a user interacts with a chart (visible). It leads to an issue: autorange should be flaglist not enumerated, but some values are mutually exclusive.
I suggest to keep autorange for the input data only and add a new axis property autosize (?) which will will be responsible for user interactions.

@apalchys
Copy link
Contributor

JFYI: Since this issue is about addressing all auto-range related issues and requires significant amount of time to do in a right way, for now, I will implement a wrapper around PlotlyJS in order to solve my case and continue to watch on progress.

@alexcjohnson
Copy link
Collaborator

Per @ IanWorthington in plotly/plotly.py#2439 - we should make sure yaxis.autorange: 'visible' or whatever we end up calling it works with range sliders - ie when you zoom in x with the rangeslider, the y rescales to the visible points.

@jacobq
Copy link

jacobq commented Mar 16, 2018

I think this use case will be covered by the options discussed above, however, I would like to share it anyway since it hasn't been said explicitly. Often I am working with data sets that whose X or Y coordinates are, for example, only positive, as demonstrated here: jsbin/winaki/6. I would really like to be able to prevent the pan and zoom controls from adjusting the axes to go beyond set limits (instead they should "snap"/"stick"/"rubber band" when they reach them).

@SebastianB12
Copy link

Any news on this subject? Especially the "bug" that the y-axis range is not updating when x-axis rangeslider is used (see: plotly/plotly.js#6958, plotly/plotly.py#2439 , #912) and the white spaces when using the "lines+text" mode plotly/plotly.py#1775 .
The option yaxis.autorange: 'visible' by @alexcjohnson sounds very reasonable in my opinion.
Let me know, if I somehow can help to fast-track the solution by buying a Developer Support plan? I love Plotly, but especially the first function is very basic and very crucial for a lot of use cases.

@grandsmarquis
Copy link

grandsmarquis commented Aug 10, 2018

Any news for this?
The yaxis.autorange: 'visible' is really needed across the forums and is making lot of people moving to other libs.

@hp8wvvvgnj6asjm7
Copy link

can we start sponsoring this feature? how much?

@hp8wvvvgnj6asjm7
Copy link

did people give up on this? wow

@nicolaskruchten
Copy link
Contributor

The sponsorship amount is listed above, and so far no one has stepped up to sponsor, and it's not on the core team's roadmap at this point, although we'd be happy to accept some pull requests :)

@dberardo-com
Copy link

dberardo-com commented Jul 25, 2022

+1

@hypercube-ai-dev
Copy link

hypercube-ai-dev commented Aug 30, 2022

The most reasonable way to implement this manually would be to hook into onRescale and iterate over your data to determine Y axis dinamically?

ive been able to implement this by catching "xaxis.range" in the arguments keys during .on("plotly_relayout", function(event, arguments {}) then getting the indexes of the new start and end values for x axis, after that i get the min and max from my y value arrays between those indexes and then create an update

var update = {
yaxis.range: [newmin, newmax]
}
then just call relayout with this update, so you're pretty close, hope this helps!

ps: with some comments and console logs sprinkled in this implementation took me 40 lines of code so its not terribly hard to implement yourself using existing charts

charlesons added a commit to GSS-Cogs/chart-builder that referenced this issue Sep 28, 2022
- This can be useful for highlighting data points that are separate to the main series
- Note that Plotly automatically adds padding to the left and right of the series when marker dots are selected. This behaviour is discussed here: plotly/plotly.js#1876
@Ranothil
Copy link

Ranothil commented Feb 7, 2023

+1

@andoks
Copy link

andoks commented Mar 9, 2023

Discovered this issue when looking for if plotly.js (the javascript version specifically) supported "soft ranges" similar to how grafana does it, with the Y-axes min/max being expanded to encompass all visible data. This would be great for us to avoid making mountains out of mole-hills, but still display all data in view if data unexpectedly extends beyond the min/max range set.

@HugoGit39
Copy link

HugoGit39 commented Apr 12, 2023

Is this feature still not possible in R? I understand it is in Phyton right with fig.update_yaxes(fixedrange=False)?

@MattWolf74

This comment was marked as abuse.

@agusterodin

This comment was marked as off-topic.

@MattWolf74

This comment was marked as abuse.

@AxelBreuer
Copy link

AxelBreuer commented May 9, 2023

Hi,

I went through many forums, but couldn't find any recent update on that feature i.e. auto-scaling of y-axis according to the "visible" x values (a subset of all x values selected via range-slider). I really need that feature :-) but setting yaxis_autorange=True didn't do the trick.

From my understanding the need has been expressed since 2017, but there wasn't any progress because this feature is complex and would require a substantive sponsorship (between 15,000$ and 20,000 $).

Am I missing something ? I would be so happy to hear that this feature exists !

@MattWolf74
Copy link

The issue is anything but complex. I used a callback on any change of the visible x-axis range and then within the callback derived the y-min and y-max within the currently visible x-axis range and subsequently update the y-axis range. Done.

I uploaded an example screen capture of a solution implemented in Bokeh (I was not sure how plotly callbacks are implemented).

It really is very straightforward, I have no idea why so many here find this a complex issue.

Recording.2023-05-09.091324.mp4

@hypercube-ai-dev
Copy link

The issue is anything but complex. I used a callback on any change of the visible x-axis range and then within the callback derived the y-min and y-max within the currently visible x-axis range and subsequently update the y-axis range. Done.

I uploaded an example screen capture of a solution implemented in Bokeh (I was not sure how plotly callbacks are implemented).

It really is very straightforward, I have no idea why so many here find this a complex issue.

Recording.2023-05-09.091324.mp4

you just have to do this for the x axis change event (not sure why this was downvoted lol) #1876 (comment)

@MattWolf74
Copy link

MattWolf74 commented May 9, 2023

Very similar to how I have done this. Not sure why this would require a significant amount of sponsorship to implement a few lines of code and to write a few tests. My implementation in the JS callback took me 16 lines of code (though its a Bokeh implementation). From multiple posts on this issue by core contributors it appears that the feature is not really understood to begin with.

@alexcjohnson
Copy link
Collaborator

I'm happy to see the extra discussion around this topic - FYI we have a PR currently in progress to cover a lot of these use cases: #6547 - we have a bit more work to do on it, but comments are welcome.

@Abhinavk910
Copy link

By utilizing relayoutData and figure, you can effortlessly achieve these features through a single, straightforward callback(max 20 lines of code).

@alexcjohnson
Copy link
Collaborator

#6547 (released in v2.26.0) covered a lot of the use cases here, but there's a lot that's been discussed here, I see at least three more pieces still open:

  • autoranging one axis based on only the data that's visible based on the range set on the opposite axis.
  • rangemode: symmetric (has its own issue Update to CircleCI 2.0 plotly.py#1022)
  • making the trace-dependent autorange adjustments configurable: padding added beyond the data range, whether we ensure the range goes to zero

Any I missed?

@archmoj I wonder if we should make new issues for the two pieces that don't already have their own issues, and close this one? It's gotten too big and diffuse to be very useful anymore, and most of it is done.

@carlandreolsen
Copy link

Bumping this for visibility. What would be the sponsorship cost for a soft autorange mode?

My interpretation of soft autorange mode:

  • Configurable axis range
  • If value on axis range passes outside the configured range, the axis is scaled with autorange.

Hard max and hard min can hide important data in many cases, so I'm very hesitant to implement something like that.

@gvwilson gvwilson self-assigned this Jun 10, 2024
@gvwilson gvwilson removed their assignment Aug 2, 2024
@gvwilson gvwilson added P3 not needed for current cycle and removed ♥ NEEDS SPON$OR labels Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 not needed for current cycle
Projects
None yet
Development

No branches or pull requests