Menu

[r6270]: / trunk / htdocs / screenshots / proj.py  Maximize  Restore  History

Download this file

172 lines (159 with data), 6.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import os, array, numarray, math, tempfile
_rad2dg = 180./math.pi
_dg2rad = math.pi/180.
class Proj:
"""
peforms cartographic transformations (converts from longitude,latitude
to native map projection x,y coordinates and vice versa) using proj
(http://www.remotesensing.org/proj/).
__init__ method sets up projection information.
__call__ method compute transformations.
See docstrings for __init__ and __call__ for details.
Jeff Whitaker <jeffrey.s.whitaker@noaa.gov>
20040711
"""
def __init__(self,params,projcmd='proj'):
"""
initialize a Proj class instance.
Input 'params' is a dictionary containing proj map
projection control parameter key/value pairs.
See the proj documentation (http://www.remotesensing.org/proj/)
for details.
Optional keyword 'projcmd' is the full path to the proj exectuable.
Default will work if proj is in the unix PATH.
"""
# make sure proj parameter specified.
# (no other checking done in proj parameters)
if 'proj' not in params.keys():
raise KeyError, "need to specify proj parameter"
# build proj command.
for key,value in map(None,params.keys(),params.values()):
if key == 'x_0' or key == 'y_0':
value=10*value # convert false easting, northing to cm.
projcmd = projcmd + " +"+key+"="+str(value)
self.projcmd = projcmd + ' -b'
def __call__(self,lon,lat,inverse=False):
"""
Calling a Proj class instance with the arguments lon, lat will
convert lon/lat (in degrees) to x/y native map projection
coordinates (in meters). If optional keyword 'inverse' is
True (default is False), the inverse transformation from x/y
to lon/lat is performed.
Example usage:
>>> from proj import Proj
>>> params = {}
>>> params['proj'] = 'lcc' # lambert conformal conic
>>> params['lat_1'] = 30. # standard parallel 1
>>> params['lat_2'] = 50. # standard parallel 2
>>> params['lon_0'] = -96 # central meridian
>>> map = Proj(params)
>>> x,y = map(-107,40) # find x,y coords of lon=-107,lat=40
>>> print x,y
-92272.1004461 477477.890988
lon,lat can be either scalar floats or numarray arrays.
"""
npts = 1
# if inputs are numarray arrays, get shape and total number of pts.
try:
shapein = lon.shape
npts = reduce(lambda x, y: x*y, shapein)
lontypein = lon.typecode()
lattypein = lat.typecode()
except:
shapein = False
# make sure inputs have same shape.
if shapein and lat.shape != shapein:
raise ValueError, 'lon, lat must be scalars or numarray arrays with the same shape'
# make a rank 1 array with x/y (or lon/lat) pairs.
xy = numarray.zeros(2*npts,'d')
xy[::2] = numarray.ravel(lon)
xy[1::2] = numarray.ravel(lat)
# convert degrees to radians, meters to cm.
if not inverse:
xy = _dg2rad*xy
else:
xy = 10.*xy
# write input data to binary file.
xyout = array.array('d')
xyout.fromlist(xy.tolist())
# set up cmd string, scale factor for output.
if inverse:
cmd = self.projcmd+' -I'
scale = _rad2dg
else:
cmd = self.projcmd
scale = 0.1
# use pipes for input and output if amount of
# data less than default buffer size (usually 8192).
# otherwise use pipe for input, tempfile for output
if 2*npts*8 > 8192:
fd, fn=tempfile.mkstemp(); os.close(fd); stdout=open(fn,'rb')
cmd = cmd+' > '+fn
stdin=os.popen(cmd,'w')
xyout.tofile(stdin)
stdin.close()
outxy = scale*numarray.fromstring(stdout.read(),'d')
stdout.close()
os.remove(fn)
else:
stdin,stdout=os.popen2(cmd,mode='b')
xyout.tofile(stdin)
stdin.close()
outxy = scale*numarray.fromstring(stdout.read(),'d')
stdout.close()
# return numarray arrays or scalars, depending on type of input.
if shapein:
outx = numarray.reshape(outxy[::2],shapein).astype(lontypein)
outy = numarray.reshape(outxy[1::2],shapein).astype(lattypein)
else:
outx = outxy[0]; outy = outxy[1]
return outx,outy
if __name__ == "__main__":
params = {}
params['proj'] = 'lcc'
params['R'] = 63712000
params['lat_1'] = 50
params['lat_2'] = 50
params['lon_0'] = -107
awips221 = Proj(params)
# AWIPS grid 221 parameters
# (from http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html)
nx = 349; ny = 277; dx = 32463.41; dy = dx
llcornerx, llcornery = awips221(-145.5,1.)
params['x_0'] = -llcornerx # add cartesian offset so llcorner = (0,0)
params['y_0'] = -llcornery
awips221 = Proj(params)
# find 4 lon/lat corners of AWIPS grid 221.
llcornerx = 0.; llcornery = 0.
lrcornerx = dx*(nx-1); lrcornery = 0.
ulcornerx = 0.,; ulcornery = dy*(ny-1)
urcornerx = dx*(nx-1); urcornery = dy*(ny-1)
llcornerlon, llcornerlat = awips221(llcornerx, llcornery, inverse=True)
lrcornerlon, lrcornerlat = awips221(lrcornerx, lrcornery, inverse=True)
urcornerlon, urcornerlat = awips221(urcornerx, urcornery, inverse=True)
ulcornerlon, ulcornerlat = awips221(ulcornerx, ulcornery, inverse=True)
print '4 corners of AWIPS grid 221:'
print llcornerlon, llcornerlat
print lrcornerlon, lrcornerlat
print urcornerlon, urcornerlat
print ulcornerlon, ulcornerlat
print 'from GRIB docs'
print '(see http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html)'
print ' -145.5 1.0'
print ' -68.318 0.897'
print ' -2.566 46.352'
print ' 148.639 46.635'
# compute lons and lats for the whole AWIPS grid 221 (377x249).
x = numarray.zeros((nx,ny),'d')
y = numarray.zeros((nx,ny),'d')
x = dx*numarray.indices(x.shape)[0,:,:]
y = dy*numarray.indices(y.shape)[1,:,:]
import time; t1 = time.clock()
lons, lats = awips221(x, y, inverse=True)
t2 = time.clock()
print 'compute lats/lons for all points on AWIPS 221 grid (%sx%s)' %(nx,ny)
print 'max/min lons'
print min(numarray.ravel(lons)),max(numarray.ravel(lons))
print 'max/min lats'
print min(numarray.ravel(lats)),max(numarray.ravel(lats))
print 'took',t2-t1,'secs'
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.