Nice post, @ThomasN !
To add to this, if you want to make an image of your MapView
, you can extract the geojson
from the MapResult
. Here is a snippet of how you can set up your map view (taking the example provided in the documentation):
def _get_map_view(self, params):
# Create some points using coordinates
markers = [
MapPoint(25.7617, -80.1918, description='Miami'),
MapPoint(18.4655, -66.1057, description='Puerto Rico'),
MapPoint(32.3078, -64.7505, description='Bermudas')
]
# Create a polygon
polygon = MapPolygon(markers)
# Visualize map
features = markers + [polygon]
return MapResult(features)
@MapView('Map view', duration_guess=1)
def get_map_view(self, params, **kwargs):
return self._get_map_view(params)
Then, using the geojson
property on the MapResult
object, you can extract the geojson
. Here is the snippet combining the code presented above:
def make_plotly_map(self, params, **kwargs):
geojson = self._get_map_view(params).geojson
geo_df = gpd.GeoDataFrame.from_features(geojson["features"])
# get average of bounds
fig = px.choropleth_mapbox(geo_df,
geojson=geo_df.geometry,
locations=geo_df.index,
color=geo_df.fill,
opacity=0.3,
mapbox_style="open-street-map",
title="VIKTOR developers around the world",
zoom=self._get_map_zoom(geo_df),
center=self._get_map_center(geo_df),
)
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
return fig
Notice that I’ve added methods to the zoom
and center
arguments. Here is the map center method:
@staticmethod
def _get_map_center(geo_dataframe):
lat_min = geo_dataframe.bounds['miny'].min()
lat_max = geo_dataframe.bounds['maxy'].max()
lon_min = geo_dataframe.bounds['minx'].min()
lon_max = geo_dataframe.bounds['maxx'].max()
lat = (lat_min + lat_max) / 2
lon = (lon_min + lon_max) / 2
return {'lat': lat, 'lon': lon}
Basically, I’m taking the bounds of the geodataframe, and averaging them to get the center.
For the zoom, it was a bit more difficult, and definitely not accurate. For this I’ve applied my own crude algorithm (I recommend adjusting the constants if they do not fit the cases that you would apply it to):
@staticmethod
def _get_map_zoom(geo_dataframe):
lat_min = geo_dataframe.bounds['miny'].min()
lat_max = geo_dataframe.bounds['maxy'].max()
lon_min = geo_dataframe.bounds['minx'].min()
lon_max = geo_dataframe.bounds['maxx'].max()
lat_diff = lat_max - lat_min
lon_diff = lon_max - lon_min
alpha = 20
beta = 0.55
# set up a simple algorithm based on two constants
zoom = alpha / (max(lat_diff, lon_diff)) ** beta
return zoom
I’ve only hacked this together quickly, and noticed that many things can be improved to making the maps similar. Hopefully we can get more developers onboard to get this snippet improved.
Here is my test case comparison:
MapView
Plotly image