import numarray, cPickle from numarray import nd_image # example to demonstrate plotting data on a map projection. # requires numarray, proj module (which in turn requires # proj command from http://proj.maptools.org) # set up map projection parameters (lambert conformal conic, # standard parallels at 50 deg N, center longitued 107 deg W. params = {} params['proj'] = 'lcc' params['R'] = 63712000 params['lat_1'] = 50 params['lat_2'] = 50 params['lon_0'] = -107 proj = Proj(params) llcornerx, llcornery = proj(-145.5,1.) xmax=11297266.68; ymax=8959901.16 params['x_0'] = -llcornerx # add cartesian offset so lower left corner = (0,0) params['y_0'] = -llcornery # create a Proj instance for desired map. proj = Proj(params) # define grid (nx x ny regularly spaced native projection grid) nx = 349; ny = 277 dx = xmax/(nx-1); dy = ymax/(ny-1) xgrid = dx*numarray.indices((ny,nx))[1,:,:] ygrid = dy*numarray.indices((ny,nx))[0,:,:] # compute lons, lats of regular projection grid. lonout, latout = proj(xgrid, ygrid, inverse=True) # make sure lons are between 0 and 360
def __init__(self,llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat,\ resolution='c',area_thresh=10000.,projection='cyl',rsphere=6371009.,\ lat_ts=None,lat_1=None,lat_2=None,lat_0=None,lon_0=None): """ create a Basemap instance. mandatory input arguments: llcrnrlon - longitude of lower left hand corner of the desired map domain. llcrnrlon - latitude of lower left hand corner of the desired map domain. urcrnrlon - longitude of upper right hand corner of the desired map domain. urcrnrlon - latitude of upper right hand corner of the desired map domain. optional keyword parameters: resolution - resolution of coastline database to use. Can be 'c' (crude, roughly 25 km resolution) or 'l' (low, roughly 5 km resolution). Default 'c'. Coastline data is from the GSHHS (http://www.soest.hawaii.edu/wessel/gshhs/gshhs.html). area_thresh - coastline with an area smaller than area_thresh in km^2 will not be plotted. Default 10,000. projection - map projection. 'cyl' - cylindrical equidistant, 'merc' - mercator, 'lcc' - lambert conformal conic, 'stere' - stereographic, 'aea' - albers equal area conic, and 'laea' - lambert azimuthal equal area currently available. Default 'cyl'. rsphere - radius of the sphere used to define map projection (default 6371009 meters, close to the arithmetic mean radius of the earth). The following parameters are map projection parameters which all default to None. Not all parameters are used by all projections, some are ignored. lat_ts - latitude of natural origin (used for mercator and stereographic projections). lat_1 - first standard parallel for lambert conformal and albers equal area projections. lat_2 - second standard parallel for lambert conformal and albers equal area projections. lat_0 - central latitude (y-axis origin) - used by stereographic and lambert azimuthal projections). lon_0 - central meridian (x-axis origin - used by lambert conformal and lambert azimuthal and stereographic projections). """ # read in coastline data. coastlons = [] coastlats = [] coastsegind = [] coastsegarea = [] i = 0 # the current ind for line in open(os.path.join(_datadir, 'gshhs_' + resolution + '.txt')): linesplit = line.split() if line.startswith('P'): coastsegind.append(i) coastsegarea.append(float(linesplit[5])) continue # lon/lat lon, lat = [float(val) for val in linesplit] coastlons.append(lon) coastlats.append(lat) i += 1 # read in country boundary data. cntrylons = [] cntrylats = [] cntrysegind = [] i = 0 # the current ind for line in open( os.path.join(_datadir, 'countries_' + resolution + '.txt')): linesplit = line.split() if line.startswith('>'): cntrysegind.append(i) continue # lon/lat lon, lat = [float(val) for val in linesplit] cntrylons.append(lon) cntrylats.append(lat) i += 1 # read in state boundaries (Americas only). statelons = [] statelats = [] statesegind = [] i = 0 # the current ind for line in open( os.path.join(_datadir, 'states_' + resolution + '.txt')): linesplit = line.split() if line.startswith('>'): statesegind.append(i) continue # lon/lat lon, lat = [float(val) for val in linesplit] statelons.append(lon) statelats.append(lat) i += 1 # extend longitudes around the earth a second time # (in case projection region straddles Greenwich meridian). # also include negative longitudes, so valid longitudes # can range from -360 to 720. coastlons2 = [lon + 360. for lon in coastlons] cntrylons2 = [lon + 360. for lon in cntrylons] statelons2 = [lon + 360. for lon in statelons] coastlons3 = [lon - 360. for lon in coastlons] cntrylons3 = [lon - 360. for lon in cntrylons] statelons3 = [lon - 360. for lon in statelons] # set up projections using Proj class. self.projection = projection self.llcrnrlon = llcrnrlon self.llcrnrlat = llcrnrlat self.urcrnrlon = urcrnrlon self.urcrnrlat = urcrnrlat projparams = {} projparams['proj'] = projection projparams['R'] = rsphere self.rsphere = rsphere if projection == 'lcc': if lat_1 is None or lon_0 is None: raise ValueError, 'must specify lat_1 and lon_0 for Lambert Conformal basemap' projparams['lat_1'] = lat_1 if lat_2 != None: projparams['lat_2'] = lat_2 projparams['lon_0'] = lon_0 proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) elif projection == 'aea': if lat_1 is None or lat_2 is None or lon_0 is None: raise ValueError, 'must specify lat_1, lat_2 and lon_0 for Albers Equal Area basemap' projparams['lat_1'] = lat_1 projparams['lat_2'] = lat_2 projparams['lon_0'] = lon_0 proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) elif projection == 'stere': if lat_ts is None or lat_0 is None or lon_0 is None: raise ValueError, 'must specify lat_ts,lat_0 and lon_0 for Stereographic basemap' projparams['lat_ts'] = lat_ts projparams['lat_0'] = lat_0 projparams['lon_0'] = lon_0 proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) elif projection == 'laea': if None or lat_0 is None or lon_0 is None: raise ValueError, 'must specify lat_0 and lon_0 for Lambert Azimuthal basemap' projparams['lat_0'] = lat_0 projparams['lon_0'] = lon_0 proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) elif projection == 'merc': if lat_ts is None: raise ValueError, 'must specify lat_ts for Mercator basemap' projparams['lat_ts'] = lat_ts proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) elif projection == 'cyl': proj = Proj(projparams, llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat) else: raise ValueError, 'unsupported projection' # make Proj instance a Basemap instance variable. self.projtran = proj # set instance variables defining map region. self.xmin = proj.xmin self.xmax = proj.xmax self.ymin = proj.ymin self.ymax = proj.ymax if projection == 'cyl' or projection == 'merc': self.aspect = (urcrnrlat - llcrnrlat) / (urcrnrlon - llcrnrlon) else: self.aspect = (proj.ymax - proj.ymin) / (proj.xmax - proj.xmin) self.llcrnrx = proj.llcrnrx self.llcrnry = proj.llcrnry self.urcrnrx = proj.urcrnrx self.urcrnry = proj.urcrnry # transform coastline polygons to native map coordinates. xc, yc = proj(N.array(coastlons, 'f'), N.array(coastlats, 'f')) xc2, yc2 = proj(N.array(coastlons2, 'f'), N.array(coastlats, 'f')) xc3, yc3 = proj(N.array(coastlons3, 'f'), N.array(coastlats, 'f')) if projection == 'merc': yc2 = yc # set up segments in form needed for LineCollection, # ignoring 'inf' values that are off the map, and skipping # polygons that have an area > area_thresh.. segments = [ zip(xc[i0:i1], yc[i0:i1]) for a, i0, i1 in zip( coastsegarea[:-1], coastsegind[:-1], coastsegind[1:]) if a > area_thresh ] segments2 = [ zip(xc2[i0:i1], yc2[i0:i1]) for a, i0, i1 in zip( coastsegarea[:-1], coastsegind[:-1], coastsegind[1:]) if a > area_thresh and max(xc2[i0:i1]) < 1.e20 and max(yc2[i0:i1]) < 1.e20 ] segments3 = [ zip(xc3[i0:i1], yc3[i0:i1]) for a, i0, i1 in zip( coastsegarea[:-1], coastsegind[:-1], coastsegind[1:]) if a > area_thresh and max(xc3[i0:i1]) < 1.e20 and max(yc3[i0:i1]) < 1.e20 ] self.coastsegs = segments + segments2 + segments3 # same as above for country polygons. xc, yc = proj(N.array(cntrylons, 'f'), N.array(cntrylats, 'f')) xc2, yc2 = proj(N.array(cntrylons2, 'f'), N.array(cntrylats, 'f')) xc3, yc3 = proj(N.array(cntrylons2, 'f'), N.array(cntrylats, 'f')) segments = [ zip(xc[i0:i1], yc[i0:i1]) for i0, i1 in zip(cntrysegind[:-1], cntrysegind[1:]) ] segments2 = [ zip(xc2[i0:i1], yc2[i0:i1]) for i0, i1 in zip(cntrysegind[:-1], cntrysegind[1:]) if max(xc2[i0:i1]) < 1.e20 and max(yc2[i0:i1]) < 1.e20 ] segments3 = [ zip(xc3[i0:i1], yc3[i0:i1]) for i0, i1 in zip(cntrysegind[:-1], cntrysegind[1:]) if max(xc3[i0:i1]) < 1.e20 and max(yc3[i0:i1]) < 1.e20 ] self.cntrysegs = segments + segments2 + segments3 # same as above for state polygons. xc, yc = proj(N.array(statelons, 'f'), N.array(statelats, 'f')) xc2, yc2 = proj(N.array(statelons2, 'f'), N.array(statelats, 'f')) xc3, yc3 = proj(N.array(statelons3, 'f'), N.array(statelats, 'f')) segments = [ zip(xc[i0:i1], yc[i0:i1]) for i0, i1 in zip(statesegind[:-1], statesegind[1:]) ] segments2 = [ zip(xc2[i0:i1], yc2[i0:i1]) for i0, i1 in zip(statesegind[:-1], statesegind[1:]) if max(xc2[i0:i1]) < 1.e20 and max(yc2[i0:i1]) < 1.e20 ] segments3 = [ zip(xc3[i0:i1], yc3[i0:i1]) for i0, i1 in zip(statesegind[:-1], statesegind[1:]) if max(xc3[i0:i1]) < 1.e20 and max(yc3[i0:i1]) < 1.e20 ] self.statesegs = segments + segments2 + segments3 # store coast polygons for filling. # special treatment (kludge) for Antarctica. self.coastpolygons = [] if projection == 'merc': xsp, ysp = proj(0., -89.9) # s. pole coordinates. xa, ya = proj(0., -68.0) # edge of antarctica. for seg in self.coastsegs: x = [lon for lon, lat in seg] y = [lat for lon, lat in seg] # the antarctic polygon is a nuisance, since it # spans all longitudes, it's not closed and will not be filled # without some projection dependant tweaking. if projection == 'cyl': if x[-1] == 0.000 and y[-1] < -68.: # close antarctica x.append(0.) y.append(-90.0000) x.insert(0, 360.) y.insert(0, -90) if x[-1] == 360.000 and y[-1] < -68.: x.append(360.) y.append(-90) x.insert(0, 720.) y.insert(0, -90) if x[-1] == -360.000 and y[-1] < -68.: x.append(-360.) y.append(-90) x.insert(0, 0.) y.insert(0, -90) elif projection == 'merc': if x[-1] == 0.000 and y[-1] < ya: # close antarctica x.append(0.) y.append(ysp) x.insert(0, 360.) y.insert(0, ysp) if x[-1] == 360.000 and y[-1] < ya: x.append(360.) y.append(ysp) x.insert(0, 720.) y.insert(0, ysp) if x[-1] == -360.000 and y[-1] < ya: x.append(-360.) y.append(ysp) x.insert(0, 0.) y.insert(0, ysp) self.coastpolygons.append((x, y))