I want to plot some data far North using basemap. Unfortunately I cannot get the meridians to be displayed. I think this is because they are not shown north of 80 degrees. Any way to fix this?
Basically, I use this code:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(num=None, figsize=(12, 8) )
m = Basemap(projection='poly', resolution=None,
lon_0=16, lat_0=81.8,
llcrnrlon=9.5, llcrnrlat=80,
urcrnrlon=22, urcrnrlat=82.5)
m.drawparallels(np.arange(80. ,82.5 ,0.5),labels=[True,False,False,False])
m.drawmeridians(np.arange(10.0, 22.0, 2.0),labels=[True,True,False,True])
m.drawmapboundary(fill_color='lightblue')
plt.show()
which produces this figure:
But I want the meridians to be also displayed. How to do this?
Your findings are some of many shortcomings that exist in Basemap. That's the reason why Cartopy was created. For a simple workaround to get your plot done, you can use plot() function to draw the missing meridional curves as follows.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(num=None, figsize=(12, 8))
m = Basemap(projection='poly', resolution=None,
lon_0=16, lat_0=81.8,
llcrnrlon=9.5, llcrnrlat=80,
urcrnrlon=22, urcrnrlat=82.5)
m.drawparallels(np.arange(80.0, 83.0, 0.5), labels=[True,False,False,False])
# this does not fully work, only labels are rendered, but not lines
m.drawmeridians(np.arange(10.0, 22.0, 2.0), labels=[True,True,False,True])
# a workaround to get meridians plotted
phs = np.arange(80, 83, 0.05)
for ea in np.arange(8.0, 22.0, 2.0):
lds = np.ones(len(phs))*ea
m.plot(lds, phs, latlon=True, color="k", linewidth=0.5)
m.drawmapboundary(fill_color='lightblue')
plt.show()
The resulting plot:
Related
I was happy with basemap showing some points of interest I have visited, but since basemap is dead, I am moving over to cartopy.
So far so good, I have transferred all the map features (country borders, etc.) without major problems, but I have noticed my points of interest are shifted a bit to North-East in cartopy.
Minimal example from the old basemap (showing two points of interest on the Germany-Czech border):
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
map = Basemap(projection='merc', epsg='3395',
llcrnrlon = 11.5, urcrnrlon = 12.5,
llcrnrlat = 50, urcrnrlat = 50.7,
resolution = 'f')
map.fillcontinents(color='Bisque',lake_color='LightSkyBlue')
map.drawcountries(linewidth=0.2)
lats = [50.3182289, 50.2523744]
lons = [12.1010486, 12.0906336]
x, y = map(lons, lats)
map.plot(x, y, marker = '.', markersize=1, mfc = 'red', mew = 1, mec = 'red', ls = 'None')
plt.savefig('example-basemap.png', dpi=200, bbox_inches='tight', pad_inches=0)
And the same example from cartopy - both points are slightly shifted to North-East as can be verified also e.g. via google maps:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.Mercator())
ax.set_extent([11.5, 12.5, 50, 50.7])
ax.add_feature(cfeature.LAND.with_scale('10m'), color='Bisque')
ax.add_feature(cfeature.LAKES.with_scale('10m'), alpha=0.5)
ax.add_feature(cfeature.BORDERS.with_scale('10m'), linewidth=0.2)
lats = [50.3182289, 50.2523744]
lons = [12.1010486, 12.0906336]
ax.plot(lons, lats, transform=ccrs.Geodetic(),
marker = '.', markersize=1, mfc = 'red', mew = 1, mec = 'red', ls = 'None')
plt.savefig('cartopy.png', dpi=200, bbox_inches='tight', pad_inches=0)
Any idea how to get cartopy plot the points on expected coordinates? Tried cartopy 0.18 and 0.20 with the same result.
I would like to fill oceans for my basemap in 3D but
ax.add_collection3d(m.drawmapboundary(fill_color='aqua'))
doesn't seem to work because the basemap drawmapboundary method doesn’t return an object supported by add_collection3d but a matplotlib.collections.PatchCollection object. Is there any workaround similar to the one done for land polygons here? Thank you!
Drawing a rectangle (polygon) below the map is one solution. Here is the working code that you may try.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
from matplotlib.collections import PolyCollection
map = Basemap()
fig = plt.figure()
ax = Axes3D(fig)
ax.azim = 270
ax.elev = 50
ax.dist = 8
ax.add_collection3d(map.drawcoastlines(linewidth=0.20))
ax.add_collection3d(map.drawcountries(linewidth=0.15))
polys = []
for polygon in map.landpolygons:
polys.append(polygon.get_coords())
# This fills polygons with colors
lc = PolyCollection(polys, edgecolor='black', linewidth=0.3, \
facecolor='#BBAAAA', alpha=1.0, closed=False)
lcs = ax.add_collection3d(lc, zs=0) # set zero zs
# Create underlying blue color rectangle
# It's `zs` value is -0.003, so it is plotted below land polygons
bpgon = np.array([[-180., -90],
[-180, 90],
[180, 90],
[180, -90]])
polys2 = []
polys2.append(bpgon)
lc2 = PolyCollection(polys2, edgecolor='none', linewidth=0.1, \
facecolor='#445599', alpha=1.0, closed=False)
lcs2 = ax.add_collection3d(lc2, zs=-0.003) # set negative zs value
plt.show()
The resulting plot:
Hello Stackoverflow forks,
I'm a enthusiastic python learner.
I have studied python to visualiza my personal project about population density.
I have gone through tutorials about matplotlib and basemap in python.
I came across with the idea about
mapping my 3dimensional graph on top of the basemap which allows me to use geographycal coordinate information.
Can anyone let me know how I could use basemap as a base plane for the 3dimensional graph?
Please let me know which tutorial or references I could go with for developing this.
Best,
Thank you always Stackoverflow forks.
The basemap documentation has a small section on 3D plotting. Here's a simple script to get you started:
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
extent = [-127, -65, 25, 51]
# make the map and axis.
m = Basemap(llcrnrlon=extent[0], llcrnrlat=extent[2],
urcrnrlon=extent[1], urcrnrlat=extent[3],
projection='cyl', resolution='l', fix_aspect=False, ax=ax)
ax.add_collection3d(m.drawcoastlines(linewidth=0.25))
ax.add_collection3d(m.drawcountries(linewidth=0.25))
ax.add_collection3d(m.drawstates(linewidth=0.25))
ax.view_init(azim = 230, elev = 15)
ax.set_xlabel(u'Longitude (°E)', labelpad=10)
ax.set_ylabel(u'Latitude (°N)', labelpad=10)
ax.set_zlabel(u'Altitude (ft)', labelpad=20)
# values to plot - change as needed. Plots 2 dots, one at elevation 0 and another 100.
# also draws a line between the two.
x, y = m(-85.4808, 32.6099)
ax.plot3D([x, x], [y, y], [0, 100], color = 'green', lw = 0.5)
ax.scatter3D(x, y, 100, s = 5, c = 'k', zorder = 4)
ax.scatter3D(x, y, 0, s = 2, c = 'k', zorder = 4)
ax.set_zlim(0., 400.)
plt.show()
I am using basemap on Python 2.7 but would like to go for Python 3, and therefor, moving to cartopy. It would be fantastic if you would give me some advises how to change my code from basemap to cartopy:
This is the basemap code:
from mpl_toolkits.basemap import Basemap
# plot map without continents and coastlines
m = Basemap(projection='kav7',lon_0=0)
# draw map boundary, transparent
m.drawmapboundary()
m.drawcoastlines()
# draw paralells and medians, no labels
if (TheLatInfo[1] == len(TheLatList)) & (TheLonInfo[1] == len(TheLonList)):
m.drawparallels(np.arange(-90,90.,30.))
m.drawmeridians(np.arange(-180,180.,60.))
grids = m.pcolor(LngArrLons,LngArrLats,MSKTheCandData,cmap=cmap,norm=norm,latlon='TRUE')
This is the cartopy example I found and have changed some bits:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cpf
ax = plt.axes(projection=ccrs.Robinson())
ax.coastlines()
ax.set_boundary
ax.gridlines(draw_labels=False)
plt.show()
I am not sure about how to set the gridlines in the exact positions and how to color them black instead of grey. Furthermore, I wonder how to insert/overlay my actual map with data then. Is "ax.pcolor" well enough supported by cartopy?
Thank you!
To color your gridlines black, you can use a color= keyword:
ax.gridlines(color='black')
To specify lat/lon gridline placement, you really only need a few extra lines, if you don't care about labels:
import matplotlib.ticker as mticker
gl = ax.gridlines(color='black')
gl.xlocator = mticker.FixedLocator([-180, -90, 0, 90, 180])
gl.ylocator = mticker.FixedLocator([-90,-45,0,45,90])
(As of writing this, Robinson projections don't support gridline labels.)
To overlay your data on the map,pcolor should work, but it's famously slow. I would recommend pcolormesh, though you can substitute one for another in this syntax:
ax.pcolormesh(lon_values, lat_values, data)
Note that if your data come on a different projection than the map projection you're plotting (typically true), you need to specify the data's projection in the plotting syntax using the transform= keyword. That tells cartopy to transform your data from their original projection to that of the map. Plate Carrée is the same as cylindrical equidistant (typical for climate model output, for example):
ax.pcolormesh(lon_values, lat_values, data, transform=ccrs.PlateCarree())
I'm trying to use PanTool and ZoomTool in a Chaco plot whose origin is set to 'top left' but the behavior of these tools is not as expected. Panning moves in the opposite direction and box zooming doesn't necessarily zoom to the highlighted region. Example code is:
plot.plot((x_key, y_key), origin='top left')
plot.tools.append(PanTool(plot))
plot.overlays.append(ZoomTool(plot, tool_mode='box', always_on=False))
If origin='top left' is removed, the panning and zooming behavior is as I'd expect.
This is a really late reply, but basically the origin needs to be set on the main Plot instance, instead of the call to its plot method. (The origin set when initializing Plot gets passed into plot also)
import numpy as np
from enable.api import Component, ComponentEditor
from traits.api import HasTraits, Instance
from traitsui.api import UItem, Group, View
from chaco.api import ArrayPlotData, Plot
from chaco.tools.api import PanTool, ZoomTool
class Demo(HasTraits):
plot = Instance(Component)
traits_view = View(
Group(
UItem('plot', editor=ComponentEditor(size=(900, 500))),
),
)
def _plot_default(self):
x = np.linspace(-2.0, 10.0, 100)
data = ArrayPlotData(x=x, y=np.sin(x))
# This works
plot = Plot(data, origin='top left')
plot.plot(('x', 'y'))
# This doesn't
# plot = Plot(data)
# plot.plot(('x', 'y'), origin='top left')
plot.tools.append(PanTool(plot))
zoom = ZoomTool(component=plot, tool_mode="box", always_on=False)
plot.overlays.append(zoom)
return plot
if __name__ == "__main__":
demo = Demo()
demo.configure_traits()