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

[Feature Request | Bug Report] Plot Area / Colorbar Size Variance (Geos) #3288

Closed
tony-zeidan opened this issue Jul 6, 2021 · 15 comments
Closed

Comments

@tony-zeidan
Copy link

tony-zeidan commented Jul 6, 2021

Hi there,

I am using Plotly for an application of mine and I am having trouble matching the size of the color bar to the size of the plot area itself. I want my code to do this automatically.

I am using the Plotly graph objects API in order to do this.

I am noticing variance in the size of the plot area which doesn't let me modify the color bar properties in my code easily.

I believe this plot area size variance to be a bug? If we could change the size of the plot area independently from the figure size, that would be an excellent feature as well.

I have an example of this variance using GeoPandas, which I tried to make as short as possible:

from plotly.graph_objs import Choropleth, Figure
import geopandas as gpd
import json

gdf = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
gdf['value_field'] = 0

# first figure: hone in on canada
canada_gdf = gdf[gdf['name'] == 'Canada']
choro = Choropleth(geojson=json.loads(canada_gdf.to_json()), z=canada_gdf['value_field'], locations=canada_gdf.index)

fig = Figure()
fig.update_layout(margin=dict(b=5, t=5, l=5, r=5), height=600, width=800)
fig.add_trace(choro)
fig.update_geos(projection_type='orthographic', lataxis_range=[40, 90], lonaxis_range=[-145, - 50], projection_rotation=dict(lat=62, lon=-96))
fig.show()

# second figure: hone in on france
france_gdf = gdf[gdf['name'] == 'France']
choro = Choropleth(geojson=json.loads(france_gdf.to_json()), z=france_gdf['value_field'], locations=france_gdf.index)

fig = Figure()
fig.update_layout(margin=dict(b=5, t=5, l=5, r=5), height=600, width=800)
fig.add_trace(choro)
fig.update_geos(projection_type='orthographic', lataxis_range=[40, 60], lonaxis_range=[-10, 20], projection_rotation=dict(lat=46, lon=2.5))
fig.show()

Canada image:
image

France image:
image

Any help concerning how to do this automatically or even a formula to calculate would also be greatly appreciated.

@tony-zeidan
Copy link
Author

This is of great importance to me, and I am 95% sure this is a feature request (one to allow the user to see plot area size, and overall better functions for alteration and retrieval of dimensions in a figure).

@tony-zeidan tony-zeidan changed the title Plot Area / Colorbar Size Variance (Geos) [Feature Request | Bug Report] Plot Area / Colorbar Size Variance (Geos) Jul 12, 2021
@nicolaskruchten
Copy link
Contributor

I think the problem is that you two regions have different aspect ratios, and the Plotly engine is scaling things so as to fit the biggest possible viewing area, which is helpful in general, but not in your specific case. I don't know what the formula would be that you'd have to use to guarantee the same aspect ratio for two different regions, but I'm sure there is one :)

@tony-zeidan
Copy link
Author

tony-zeidan commented Jul 14, 2021

I think the problem is that you two regions have different aspect ratios, and the Plotly engine is scaling things so as to fit the biggest possible viewing area, which is helpful in general, but not in your specific case. I don't know what the formula would be that you'd have to use to guarantee the same aspect ratio for two different regions, but I'm sure there is one :)

I've tried every single possible thing that I can think of. I want a figure with minimal whitespace and I don't care about the aspect ratio, all I need is the positioning of the colorbar and its height to be correct. The figure size remains constant yet the plot area size changes and the colorbar position and length remains the same. How can I move the colorbar to be beside the plot area in the middle of the figure and automate that process? Without dimensions of the plot area or some sort of Plotly automatic calculation I cannot do this. Plotly's margin_autoexpand and autosize layout attributes do nothing. I need the process to be automated as I stated before, regardless of lataxis_range, lonaxis_range and overall plot area dimensions.

@nicolaskruchten
Copy link
Contributor

I certainly understand what you're trying to do, I just don't know how to do it either :)

@tony-zeidan
Copy link
Author

I certainly understand what you're trying to do, I just don't know how to do it either :)

Do you know what I can do? Who to contact? I've posted on the forum many many times with no responses and this matter is kind of pressing.

@nicolaskruchten
Copy link
Contributor

You basically need to work through the math to figure out how to grow/shrink your lataxis/lonaxis range so that the aspect ratio is always square. I'm not sure who can help you do that for the orthographic projection, but if you switch to equirectangular you should be able to manage it more easily.

@tony-zeidan
Copy link
Author

You basically need to work through the math to figure out how to grow/shrink your lataxis/lonaxis range so that the aspect ratio is always square. I'm not sure who can help you do that for the orthographic projection, but if you switch to equirectangular you should be able to manage it more easily.

For the purposes of our application, we need to support every kind of projection that Plotly offers. The aspect ratio does not always need to be square, it just needs to be not overly rectangular it seems. Does Plotly not offer any functions to automatically adjust the plot properly? The size of and positioning of the color bar always stays the same, as well as the overall figure size. If the plot area size is too small, however, this looks absolutely terrible (no offense). What I am getting at is there exists no function to automatically adjust the figure size to the size of the components within it? Or at least scales up the components within to match the figure size?

@nicolaskruchten
Copy link
Contributor

There is nothing in our library that does what you're looking for, no. The figure size is always taken as given, and then margins are applied to define the available plotting area. You can make a map with an arbitrary aspect ratio by setting lat/lon ranges and projection, and then Plotly will take your rectangle and fit it within the available area: if the map is wider than tall it will fit the width, and the map is taller than wide it will fit the height. That's just how it works today and I'm not sure how it could work otherwise 🤷 . The color bar is sized independently from any subplots. I'm sorry if it doesn't automatically do what you need and that you need to write extra code in your application for your specific requirements :)

@nicolaskruchten
Copy link
Contributor

To expand on my answer a little bit, here's how things work today:

  1. the figure width/height are taken to be fixed and are never modified
  2. the colorbar is positioned with respect to the figure, taking into account margins
  3. geos are basically subplots, and there can be arbitrarily-many of them
  4. subplots have domains which are drawn in "paper coordinates" (0,0 is the bottom-left of the figure, taking into account margins, and 1,1 is the top-left)
  5. geos have aspect ratios and are drawn so as to fit within their domain

Under these constraints, if you want a figure with maps of arbitrary aspect ratios and color bars that are always of the same height as the map and not a lot of whitespace above and below, then we'd need to implement a couple of different features:

  1. resizing the figure based on its contents
  2. sizing colorbars based on subplots

Absent that, you could try to compute bounds for your map that always result in a map which is a little taller than wide while still showing the entire feature you care about, and then tune your margins so that the height of the colorbar has the right relationship to the height of your map (this is the formula that I'm sure exists for every projection, but I don't have it on hand and I'm not going to have time to sit down and work it out myself).

A different way would be for us to somehow expose the paper coordinates of the bounding box of the rendered map, so you could iteratively call fig.full_figure_for_development() to re-size your map until it's filling your figure nicely.

Do you know what I can do? Who to contact? I've posted on the forum many many times with no responses and this matter is kind of pressing.

Posting on the community forum or StackOverflow is basically your best bet for figuring out how to do things without getting the features above implemented. If you need the features above, we would probably accept a pull request for some of these if you want to implement them, although they're likely quite a lift, or barring that, if your project is funded, you could sponsor some of these features and we would be able to add them to our roadmap.

I hope this helps.

@tony-zeidan
Copy link
Author

To expand on my answer a little bit, here's how things work today:

  1. the figure width/height are taken to be fixed and are never modified
  2. the colorbar is positioned with respect to the figure, taking into account margins
  3. geos are basically subplots, and there can be arbitrarily-many of them
  4. subplots have domains which are drawn in "paper coordinates" (0,0 is the bottom-left of the figure, taking into account margins, and 1,1 is the top-left)
  5. geos have aspect ratios and are drawn so as to fit within their domain

Under these constraints, if you want a figure with maps of arbitrary aspect ratios and color bars that are always of the same height as the map and not a lot of whitespace above and below, then we'd need to implement a couple of different features:

  1. resizing the figure based on its contents
  2. sizing colorbars based on subplots

Absent that, you could try to compute bounds for your map that always result in a map which is a little taller than wide while still showing the entire feature you care about, and then tune your margins so that the height of the colorbar has the right relationship to the height of your map (this is the formula that I'm sure exists for every projection, but I don't have it on hand and I'm not going to have time to sit down and work it out myself).

A different way would be for us to somehow expose the paper coordinates of the bounding box of the rendered map, so you could iteratively call fig.full_figure_for_development() to re-size your map until it's filling your figure nicely.

Do you know what I can do? Who to contact? I've posted on the forum many many times with no responses and this matter is kind of pressing.

Posting on the community forum or StackOverflow is basically your best bet for figuring out how to do things without getting the features above implemented. If you need the features above, we would probably accept a pull request for some of these if you want to implement them, although they're likely quite a lift, or barring that, if your project is funded, you could sponsor some of these features and we would be able to add them to our roadmap.

I hope this helps.

Thank you so much for your timely replies, I will try to continue to try other methods of calculating the dimensions and such of the plot. Rather than adding a whole new feature for these things, could it be possible to make information such as the plot area dimensions available to the user? I think that would be a much more fitting and less intensive solution to these problems.

@nicolaskruchten
Copy link
Contributor

could it be possible to make information such as the plot area dimensions available to the user?

This would need to be on a subplot-by-subplot basis, so for every geo object, say. Yes, it is in principle possible, and would need to be implemented in Plotly.js. We did something similar with margins here: plotly/plotly.js#5203

@tony-zeidan
Copy link
Author

could it be possible to make information such as the plot area dimensions available to the user?

This would need to be on a subplot-by-subplot basis, so for every geo object, say. Yes, it is in principle possible, and would need to be implemented in Plotly.js. We did something similar with margins here: plotly/plotly.js#5203

This would be an amazing feature! Although it would still require some math on our part, it would provide us with information to calculate stuff.

@tony-zeidan
Copy link
Author

could it be possible to make information such as the plot area dimensions available to the user?

This would need to be on a subplot-by-subplot basis, so for every geo object, say. Yes, it is in principle possible, and would need to be implemented in Plotly.js. We did something similar with margins here: plotly/plotly.js#5203

Also it would be beneficial to have the user be able to manually set the dimensions of the plot area itself instead of plotly auto calculating all of the time.

@nicolaskruchten
Copy link
Contributor

I generally agree, although neither of these features are something our team can work on in the near future without a financial sponsor or a community member doing most of the development.

@gvwilson
Copy link
Contributor

Hi - we are trying to tidy up the stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for several years, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. Thanks for your help - @gvwilson

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

No branches or pull requests

3 participants