I am using the scattermapbox via the python API and have no trouble creating a plot. However, I am unable to figure out how to set the visible area.
For example, if I am plotting markers on a US map and all of the markers are in Florida, I only want to show the state of Florida (or specific lat/long ranges). But if there are points in Texas and Florida, I will want to show all of the states from Texas to Florida. This works easily with Plotly’s scattergeo by passing the following in the geo dict:
But when using ScatterMapbox, there doesn’t appear to be a similar setting. The only thing that can be controlled is the center lat/long points and the zoom level. That would be fine, but it isn’t at all obvious how to set the zoom to achieve the same results as setting the lonaxis and lataxis as in the ScatterGeo.
Is there some other way to achieve this? While a user could control the zoom and the visible area in the interactive chart, I am trying to also generate a static PNG or PDF image so I need to be able to control the visible area.
In my application I have a list of lat/long points. So I calculate the min and max lat and long and then set the zoom in the mapbox field of the layout using this function:
def getBoundsZoomLevel(bounds, mapDim):
"""
source: https://stackoverflow.com/questions/6048975/google-maps-v3-how-to-calculate-the-zoom-level-for-a-given-bounds
:param bounds: list of ne and sw lat/lon
:param mapDim: dictionary with image size in pixels
:return: zoom level to fit bounds in the visible area
"""
ne_lat = bounds[0]
ne_long = bounds[1]
sw_lat = bounds[2]
sw_long = bounds[3]
scale = 2 # adjustment to reflect MapBox base tiles are 512x512 vs. Google's 256x256
WORLD_DIM = {'height': 256 * scale, 'width': 256 * scale}
ZOOM_MAX = 18
def latRad(lat):
sin = np.sin(lat * np.pi / 180)
radX2 = np.log((1 + sin) / (1 - sin)) / 2
return max(min(radX2, np.pi), -np.pi) / 2
def zoom(mapPx, worldPx, fraction):
return np.floor(np.log(mapPx / worldPx / fraction) / np.log(2))
latFraction = (latRad(ne_lat) - latRad(sw_lat)) / np.pi
lngDiff = ne_long - sw_long
lngFraction = ((lngDiff + 360) if lngDiff < 0 else lngDiff) / 360
latZoom = zoom(mapDim['height'], WORLD_DIM['height'], latFraction)
lngZoom = zoom(mapDim['width'], WORLD_DIM['width'], lngFraction)
return min(latZoom, lngZoom, ZOOM_MAX)