Reputation: 291
I am trying to plot a satellite ground track. I have a list of latitudes and longitudes in degrees. The longitude values are all from -180 to +180 deg. My first issue is with using the latlon
keyword (by the way, I'm using this in Julia via the PyCall.jl
package, so forgive the weird-looking syntax):
map = Basemap.Basemap(projection="mill",lon_0=0)
map[:drawcoastlines]()
map[:drawparallels](-90:30:90,labels=[1,0,0,0])
map[:drawmeridians](map[:lonmin]:60:map[:lonmax]+30,labels=[0,0,0,1])
map[:plot](lon,lat,color="red",latlon=true)
This is... not what that should look like. I'm not really sure what the problem is. However, if I convert to map coordinates first:
xx,yy = map(lon,lat)
map[:plot](xx,yy,color="red")
This is much better, except for the line at the point that the longitude wraps from +180 to -180. Any suggestions for making this look nicer?
The latitude, longitude pairs (in degrees) used for generating these plots can be found here.
Upvotes: 3
Views: 3339
Reputation: 486
At the beginning I thought this could be related to an old issue of Basemap
. However, I think your problem is not due to Basemap
, which is actually handling correctly the longitude wrapping, as you could see if you used only markers to plot the satellite ground track.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x,y = m(lon, lat)
m.plot(x, y, color="red", latlon=False, marker='.', linestyle='None')
The definitive solutions would be to split your ground track in multiple tracks and plot them using LineCollection
, as also explained here. A simpler approach (if you expect one discontinuity in the longitude):
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
latlon_ar = np.array(latlon)
threshold = 90
idx_wrap = np.nonzero(np.abs(np.diff(latlon_ar[:,1])) > threshold)[0]+1
lon_1 = lon[:idx_wrap]
lat_1 = lat[:idx_wrap]
lon_2 = lon[idx_wrap:]
lat_2 = lat[idx_wrap:]
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x1, y1 = m(lon_1, lat_1)
x2, y2 = m(lon_2, lat_2)
m.plot(x1, y1, color="red", latlon=False)
m.plot(x2, y2, color="blue", latlon=False)
Edit This confirmed bug in Basemap
is responsible for the behaviour in the first example of the question, where Basemap.plot
is called directly with latitude and longitude values, having set the latlon
flag to True
. There is a solution, that is to manually shift the input coordinates before plotting, as in the following code.
lons, lats = m.shiftdata(lon, lat)
m.plot(lons, lats, color="blue", latlon=True, marker='.', linestyle='None')
Upvotes: 8