title: Plotting geographic data in 3d with matplotlib
body: <p>I'm trying to plot data that contains lat, lon, and altitude as a 3d scatter plot in mpl.  What I've found for documentation so far is either how to plot 2d geographic data using Basemap, OR how to plot 3d data using Axes3D, but not both.  The specific coding issue I'm running into is how to set my lat/lon data to be interpreted as geographic lat and lon, but to keep my alt data as... well, altitude.  I know Basemap contains the latlon setting: </p>
  
  <blockquote>
    <p>"If latlon keyword is set to True, x,y are intrepreted as longitude
    and latitude in degrees. Data and longitudes are automatically shifted
    to match map projection region for cylindrical and pseudocylindrical
    projections, and x,y are transformed to map projection coordinates."</p>
  </blockquote>
  
  <p>However if I'm plotting in 3d, Axes3D doesn't support the latlon argument.  The reason having geographic coordinates is so important is that I'm plotting the data over a basemap for visual reference.  </p>
  
  <p>My code: </p>
  
  <pre><code>import os
  os.environ['PROJ_LIB'] = r'E:\Programs\Anaconda3\pkgs\proj4-5.2.0-ha925a31_1\Library\share'
  import matplotlib as mpl
  import matplotlib.pyplot as plt
  import numpy as np
  from mpl_toolkits.basemap import Basemap
  from mpl_toolkits.mplot3d import Axes3D
  
  
  
  fig = plt.figure()
  ax = fig.gca(projection='3d')
  
  # Define lower left, uperright lontitude and lattitude respectively
  extent = [-180, 180, -90, 90]
  # Create a basemap instance that draws the Earth layer
  #bm = Basemap(llcrnrlon=extent[0], llcrnrlat=extent[2],
  #             urcrnrlon=extent[1], urcrnrlat=extent[3],
  #             projection='cyl', resolution='l', fix_aspect=False, ax=ax)
  bm = Basemap(llcrnrlon=-73,llcrnrlat=41,urcrnrlon=-69.5,urcrnrlat=43.5,projection='lcc', resolution='i', lat_0=42, lon_0=-71, ax=ax, fix_aspect=True)
  # Add Basemap to the figure
  ax.add_collection3d(bm.drawcoastlines(linewidth=0.35))
  ax.add_collection3d(bm.drawstates(linewidth=0.25))
  #ax.add_collection3d(bm.drawcounties(linewidth=0.15))
  #ax.set_axis_off()
  ax.view_init(azim=230, elev=50)
  ax.set_xlabel('Longitude (°E)', labelpad=20)
  ax.set_ylabel('Latitude (°N)', labelpad=20)
  ax.set_zlabel('Altitude (ft)', labelpad=20)
  # Add meridian and parallel gridlines
  #lon_step = 5
  #lat_step = 5
  #meridians = np.arange(extent[0], extent[1] + lon_step, lon_step)
  #parallels = np.arange(extent[2], extent[3] + lat_step, lat_step)
  #ax.set_yticks(parallels)
  #ax.set_yticklabels(parallels)
  #ax.set_xticks(meridians)
  #ax.set_xticklabels(meridians)
  ax.set_zlim(0., 50000.)
  #ax.set_xlim(-69., -73.)
  #ax.set_ylim(40.,44.)
  
  
  # empty array for place holder
  lons = np.array([]) # longtitude
  lats = np.array([]) # latitude
  alt = np.array([]) # altitude
  
  # Make sure your working directory is the directory contains this script and the data file.
  #directory = os.fsencode('.')
  
  # Import data to illustrate
  
  lons, lats, alt = np.loadtxt('adsb-csv-2019-07-07_xzyonly_small.csv', delimiter=',', unpack=True, skiprows=1)
  
  #alons, alats = map(lons, lats, latlon=True)
  
  # scatter map based on lons, lats, alts
  p = ax.scatter(lons, lats, alt, c=alt, cmap='jet')
  # Add a colorbar to reference the intensity
  #fig.colorbar(p, label='Aircraft Altitude')
  
  plt.show()
  </code></pre>
  
  <p>This was adapted from code <a href="https://medium.com/@lkhphuc/how-to-plot-a-3d-earth-map-using-basemap-and-matplotlib-2bc026483fe4" rel="nofollow noreferrer">written by Phúc Lê.</a>  </p>
  
  <p>Any help would be much appreciated!</p>