1 |
# |
---|
2 |
# PROGRAM: codar2shape_nc_radial.py |
---|
3 |
# |
---|
4 |
# USAGE: python codar2shape_nc_radial.py site_location |
---|
5 |
# (site_locations are duck or haty) |
---|
6 |
# Note: User should edit variables under the 'Default / user |
---|
7 |
# defined variables' section below to set desired processing |
---|
8 |
# parameters. Variables include: |
---|
9 |
# url - OPeNDAP server (dataset) URL |
---|
10 |
# workspace - filesystem directory location for processing |
---|
11 |
# ShapeFile - name of output shapefile |
---|
12 |
# subSample - data subsampling (skip) factor (0 = full dataset) |
---|
13 |
# xUnit - X dimension name (ie. 'lon' or longitude) |
---|
14 |
# yUnit - Y dimension name (ie. 'lat' or latitude) |
---|
15 |
# tUnit - Time dimension name (ie. 'time_series'), if present. |
---|
16 |
# uUnit - U dimension name (ie. 'sstb' or Sea Surface Temp.) |
---|
17 |
# vUnit - V dimension name |
---|
18 |
# tValue - Specify which timestep in the time array to download. |
---|
19 |
# If time dimension is not present in the dataset, the |
---|
20 |
# program will ignore this parameter. |
---|
21 |
# (default = -9999; program will automatically calculate |
---|
22 |
# and use the last timestep in the time array) |
---|
23 |
# |
---|
24 |
|
---|
25 |
# |
---|
26 |
# Default / user defined variables |
---|
27 |
# |
---|
28 |
|
---|
29 |
workspace = "/home/jcleary/data/codar/nccoos/" |
---|
30 |
subSample = 0 |
---|
31 |
xUnit = "longitude" |
---|
32 |
yUnit = "latitude" |
---|
33 |
tUnit = "time" |
---|
34 |
tValue = -9999 # -9999 specifies to use last timestep in the time array (default action) |
---|
35 |
uUnit = "radial_water_u" |
---|
36 |
vUnit = "radial_water_v" |
---|
37 |
lUnit = "location" |
---|
38 |
timeDimPresent = 0 |
---|
39 |
noData = '-9999.0' |
---|
40 |
|
---|
41 |
# |
---|
42 |
# Import required modules |
---|
43 |
# |
---|
44 |
|
---|
45 |
import sys, time, os, shutil, string |
---|
46 |
|
---|
47 |
from math import atan2 |
---|
48 |
from math import pi |
---|
49 |
|
---|
50 |
from dap.client import * |
---|
51 |
from dap.proxy import * |
---|
52 |
from types import * |
---|
53 |
import dap |
---|
54 |
from dap.parsers import dds, das |
---|
55 |
|
---|
56 |
# |
---|
57 |
# arguments for individual CODAR sites |
---|
58 |
# |
---|
59 |
try: |
---|
60 |
arg = sys.argv[1] |
---|
61 |
if arg == "duck": |
---|
62 |
url = "http://nemo.isis.unc.edu/cgi-bin/nph-dods/data/nc-coos/latest_v2.0/nccoos-duck-codar-latest.nc" |
---|
63 |
outPrefix = "duck" |
---|
64 |
elif arg == "haty": |
---|
65 |
url = "http://nemo.isis.unc.edu/cgi-bin/nph-dods/data/nc-coos/latest_v2.0/nccoos-haty-codar-latest.nc" |
---|
66 |
outPrefix = "haty" |
---|
67 |
except: |
---|
68 |
print "No site argument supplied (options are duck or haty)." |
---|
69 |
sys.exit() |
---|
70 |
|
---|
71 |
# |
---|
72 |
# set pathnames based on site name |
---|
73 |
asciiOut = workspace + "ascii_" + outPrefix + ".csv" |
---|
74 |
ShapeOut = workspace + outPrefix + ".shp" |
---|
75 |
|
---|
76 |
|
---|
77 |
|
---|
78 |
#----------------------------------------------------------------------------- |
---|
79 |
# |
---|
80 |
# Functions |
---|
81 |
# |
---|
82 |
|
---|
83 |
def cleanWorkspace(): # Sync and close (and delete) data files |
---|
84 |
print |
---|
85 |
try: |
---|
86 |
asciiExport.close() |
---|
87 |
except: |
---|
88 |
print "ASCII data file not closed" |
---|
89 |
try: |
---|
90 |
os.remove(asciiOut) |
---|
91 |
except: |
---|
92 |
print "Unable to remove ASCII out file" |
---|
93 |
print "Workspace cleaned, all temporary files removed." |
---|
94 |
|
---|
95 |
#----------------------------------------------------------------------------- |
---|
96 |
# |
---|
97 |
# Main Function |
---|
98 |
# |
---|
99 |
|
---|
100 |
print |
---|
101 |
print "***" |
---|
102 |
print "*** Importing OPeNDAP Codar radial vectors (point locations) to a Shapefile" |
---|
103 |
print "***" |
---|
104 |
print |
---|
105 |
print "Importing OPeNDAP data from URL: " + url |
---|
106 |
|
---|
107 |
# |
---|
108 |
# Assign/validate X, Y, T, U & V vector variables, set X, Y, & T array sizes |
---|
109 |
|
---|
110 |
data = open(url) #JC |
---|
111 |
|
---|
112 |
try: |
---|
113 |
xVar = data[xUnit] |
---|
114 |
xShape = xVar.shape[0] |
---|
115 |
except: |
---|
116 |
print "Error,",xUnit,"dimension does not exist in",url |
---|
117 |
sys.exit() |
---|
118 |
|
---|
119 |
try: |
---|
120 |
yVar = data[yUnit] |
---|
121 |
yShape = yVar.shape[0] |
---|
122 |
except: |
---|
123 |
print "Error,",yUnit,"dimension does not exist in",url |
---|
124 |
sys.exit() |
---|
125 |
|
---|
126 |
try: |
---|
127 |
tVar = data[tUnit] |
---|
128 |
tShape = tVar.shape[0] |
---|
129 |
timeDimPresent = 1 |
---|
130 |
except: |
---|
131 |
print "Note,",tUnit,"dimension does not exist in",url |
---|
132 |
|
---|
133 |
try: |
---|
134 |
uVar = data[uUnit] |
---|
135 |
except: |
---|
136 |
print "Error,",uUnit,"dimension does not exist in",url |
---|
137 |
sys.exit() |
---|
138 |
|
---|
139 |
try: |
---|
140 |
vVar = data[vUnit] |
---|
141 |
except: |
---|
142 |
print "Error,",vUnit,"dimension does not exist in",url |
---|
143 |
sys.exit() |
---|
144 |
|
---|
145 |
|
---|
146 |
print |
---|
147 |
print "Subsample factor:",subSample |
---|
148 |
print "Time dim. present:",timeDimPresent |
---|
149 |
|
---|
150 |
# |
---|
151 |
# Check the validity of the L & T dimensions in the U attrib. vector |
---|
152 |
print "U attibute type:",uUnit |
---|
153 |
a = 0 |
---|
154 |
while 1: |
---|
155 |
try: |
---|
156 |
uVar.dimensions[a] |
---|
157 |
except: |
---|
158 |
break |
---|
159 |
print uUnit,"dimension",a,":",uVar.dimensions[a] |
---|
160 |
if uVar.dimensions[a] not in [lUnit, tUnit]: |
---|
161 |
print "Error - " + uVar.dimensions[a] + " is an invalid dimension." |
---|
162 |
sys.exit() |
---|
163 |
a += 1 |
---|
164 |
|
---|
165 |
# Check the validity of the L & T dimensions in the V attrib. vector |
---|
166 |
print "V attibute type:",vUnit |
---|
167 |
b = 0 |
---|
168 |
while 1: |
---|
169 |
try: |
---|
170 |
vVar.dimensions[b] |
---|
171 |
except: |
---|
172 |
break |
---|
173 |
print vUnit,"dimension",b,":",vVar.dimensions[b] |
---|
174 |
if vVar.dimensions[b] not in [lUnit, tUnit]: |
---|
175 |
print "Error - " + vVar.dimensions[b] + " is an invalid dimension." |
---|
176 |
sys.exit() |
---|
177 |
b += 1 |
---|
178 |
|
---|
179 |
|
---|
180 |
# |
---|
181 |
# Establish time step value and time array index location |
---|
182 |
if timeDimPresent: # Deal w/ time dimension if present |
---|
183 |
tArray = tVar[0:tShape] |
---|
184 |
if (tValue <= noData): # No time step specified by user |
---|
185 |
tStep = tShape - 1 # Select single element (last) in time step array |
---|
186 |
tValue = tArray[tShape - 1] |
---|
187 |
else: # Validate user timestep value & set array location |
---|
188 |
tStep = 0 |
---|
189 |
for tElement in tArray: |
---|
190 |
if tElement == tValue: |
---|
191 |
break |
---|
192 |
tStep += 1 |
---|
193 |
else: |
---|
194 |
print "Error: ", tValue, " is an invalid timestep value." |
---|
195 |
print "Valid timestep values: ", tArray |
---|
196 |
sys.exit() |
---|
197 |
print "X array shape = ", xShape |
---|
198 |
print "Y array shape = ", yShape |
---|
199 |
print "time array step = ", tStep |
---|
200 |
print "time step value = ", tValue |
---|
201 |
timeHandle = time.strftime('%m-%d-%Y %H:00 UTC',(time.gmtime(tValue))) |
---|
202 |
print "Readable time stamp: ", timeHandle |
---|
203 |
|
---|
204 |
|
---|
205 |
# |
---|
206 |
# Download X, Y, U, & V data arrays from OPeNDAP server |
---|
207 |
print |
---|
208 |
print "Downloading " + xUnit + ", " + yUnit + ", " + lUnit + ', ' + uUnit + ", " + vUnit + " data arrays..." |
---|
209 |
xArray = xVar[0:xShape-1:subSample] |
---|
210 |
yArray = yVar[0:yShape-1:subSample] |
---|
211 |
|
---|
212 |
if timeDimPresent: # 3 dimensional vector (T,L) for U and V arrays |
---|
213 |
uArray = uVar[tStep, 0:xShape-1:subSample] |
---|
214 |
vArray = vVar[tStep, 0:xShape-1:subSample] |
---|
215 |
|
---|
216 |
else: # 2 dimensional vector (X,Y) for U and V arrays |
---|
217 |
uArray = uVar[0:xShape-1:subSample, 0:yShape-1:subSample] |
---|
218 |
vArray = vVar[0:xShape-1:subSample, 0:yShape-1:subSample] |
---|
219 |
|
---|
220 |
print |
---|
221 |
print "Number of Long. values:",xShape |
---|
222 |
print "Number of Lat. values:",yShape |
---|
223 |
print "ASCII temp file:",asciiOut |
---|
224 |
print "Total number of dimensions in",uUnit,"=",a |
---|
225 |
print "Total number of dimensions in",vUnit,"=",b |
---|
226 |
|
---|
227 |
# |
---|
228 |
# Setup temp. process file(s) |
---|
229 |
try: |
---|
230 |
asciiExport = file(asciiOut,'w') |
---|
231 |
except IOError: |
---|
232 |
print "Unable to create temp ASCII data file. Check dir. rights..." |
---|
233 |
sys.exit() |
---|
234 |
|
---|
235 |
|
---|
236 |
# |
---|
237 |
# Load data into ASCII data file (comma delimited -> ESRI shapefile - points) |
---|
238 |
l = 0 |
---|
239 |
t = 0 |
---|
240 |
# Write column header |
---|
241 |
asciiExport.write("time," + xUnit + "," + yUnit + "," + lUnit + ",U,V,speed_ms,speed_mph,speed_knots,dir,dir_ms\n") |
---|
242 |
# Write X, Y, Z data to temp. ASCII file |
---|
243 |
print |
---|
244 |
print "Writing Timestamp, " + xUnit + ", " + yUnit + ", " + lUnit + ', ' + uUnit + ", " + vUnit + ", speed(3), and direction(2) data to " + asciiOut + "..." |
---|
245 |
while l < len(xArray): |
---|
246 |
if timeDimPresent: # 3 dimensional vector (T,X,Y) for U and V array |
---|
247 |
asciiExport.write(timeHandle + ",") |
---|
248 |
if float(xArray[l]) > 180.: # shift X values from 0 - 360 to -180 - 180 |
---|
249 |
asciiExport.write(str(xArray[l] - 360.) + ",") |
---|
250 |
else: |
---|
251 |
asciiExport.write(str(xArray[l]) + ",") |
---|
252 |
asciiExport.write(str(yArray[l]) + ",") |
---|
253 |
asciiExport.write(str(l) + ",") |
---|
254 |
asciiExport.write(str(uArray[t,l]) + ",") |
---|
255 |
asciiExport.write(str(vArray[t,l]) + ",") |
---|
256 |
|
---|
257 |
# code to derive Speed from U and V components |
---|
258 |
# (U^2 + V^2)^0.5 |
---|
259 |
speed = (uArray[t,l]**2 + vArray[t,l]**2)**.5 #in CM/S |
---|
260 |
speed_ms = speed/100 |
---|
261 |
speed_mph = (speed/100) * 2.237 |
---|
262 |
speed_knots = (speed/100) * 1.944 |
---|
263 |
asciiExport.write(str(speed_ms) + "," + str(speed_mph) + "," + str(speed_knots) + ",") |
---|
264 |
|
---|
265 |
# code to derive Direction from U and V components |
---|
266 |
# atan2(-U,-V) * (180/pi) - 180 |
---|
267 |
direction = atan2(-uArray[t,l],-vArray[t,l]) * (180/pi) - 180 |
---|
268 |
if direction < 0: |
---|
269 |
azimuth = direction + 360 |
---|
270 |
elif direction > 360: |
---|
271 |
azimuth = direction - 360 |
---|
272 |
ms_azimuth = -azimuth |
---|
273 |
asciiExport.write(str(azimuth) + "," + str(ms_azimuth)) |
---|
274 |
asciiExport.write('\n') |
---|
275 |
|
---|
276 |
else: # 2 dimensional vector (X,Y) for U and V array |
---|
277 |
if float(xArray[x]) > 180.: # shift X values from 0 - 360 to -180 - 180 |
---|
278 |
asciiExport.write(str(xArray[l] - 360.) + ",") |
---|
279 |
else: |
---|
280 |
asciiExport.write(str(float(xArray[l])) + ",") |
---|
281 |
asciiExport.write(str(yArray[l]) + ",") |
---|
282 |
asciiExport.write(str(uArray[l]) + ",") |
---|
283 |
asciiExport.write(str(vArray[l])) |
---|
284 |
asciiExport.write('\n') |
---|
285 |
l += 1 |
---|
286 |
|
---|
287 |
asciiExport.write(timeHandle + ",5,10,NaN,777,777,NaN,NaN,NaN,NaN,Nan") |
---|
288 |
asciiExport.close() |
---|
289 |
|
---|
290 |
# |
---|
291 |
# OGR2OGR Process: ASCII CSV to Shapefile |
---|
292 |
print |
---|
293 |
print "Removing existing files (OGR cannot overwite shapefiles)" |
---|
294 |
print |
---|
295 |
os.system("rm -f " + workspace + outPrefix + "*") |
---|
296 |
|
---|
297 |
print "Using OGR to create shapefile..." |
---|
298 |
cmd = '/usr/local/bin/ogr2ogr -f "ESRI Shapefile" -where \'U != "' + noData + '"\' ' + ShapeOut + ' /home/jcleary/data/source_files/' + outPrefix + '_pydap.vrt' |
---|
299 |
print cmd |
---|
300 |
os.system(cmd) |
---|
301 |
|
---|
302 |
cleanWorkspace() |
---|
303 |
|
---|
304 |
print |
---|
305 |
print "***" |
---|
306 |
print "*** Data import and conversion complete." |
---|
307 |
print "***" |
---|
308 |
print |
---|
309 |
|
---|
310 |
sys.exit() |
---|