1 | # python script to transform DCAO's snd data to netCDF |
---|
2 | # L. Fita, CIMA. Sept. 2018 |
---|
3 | |
---|
4 | ## e.g. # snd_DCAO_netcdf.py -f pedidoLluis200212.dat |
---|
5 | |
---|
6 | ### ASCII files from DCAO can have more than one sounding per file |
---|
7 | ### Script spect to find |
---|
8 | # ESTACION: 87155 RESISTENCIA AERO 27.30S 59.00W ( 52 M) |
---|
9 | |
---|
10 | # 1-12-2002 6 UTC |
---|
11 | |
---|
12 | |
---|
13 | # ::: NIVELES SIGNIFICATIVOS ::: |
---|
14 | |
---|
15 | # NIVEL PP(MB) TT(C) TD(C) TP(K) TPE(K) HR Z(MGP) GRAD. |
---|
16 | |
---|
17 | # 1 996 26.2 23.9 300 354 87 52 |
---|
18 | # 2 951 24.6 22.3 302 354 87 461 NORMAL |
---|
19 | # 3 930 26.4 21.4 306 357 74 658 INVERS. |
---|
20 | # 4 793 16.6 16.1 310 353 97 2047 NORMAL |
---|
21 | # 5 701 11.6 8.6 315 346 82 3092 NORMAL |
---|
22 | # 6 644 6.6 4.6 317 343 87 3797 NORMAL |
---|
23 | # 7 621 7.6 -4.4 322 336 43 4097 INVERS. |
---|
24 | # 8 610 6.2 -5.8 322 335 42 4244 ADIABAT |
---|
25 | # 9 607 6.4 -5.6 322 336 42 4284 ADIABAT |
---|
26 | # 10 567 2.8 -10.2 325 335 38 4840 NORMAL |
---|
27 | # 11 565 2.6 -10.4 325 335 38 4869 ADIABAT |
---|
28 | # 12 472 -9.1 -22.1 327 332 34 6292 NORMAL |
---|
29 | # 13 432 -12.3 -29.3 332 335 23 6973 NORMAL |
---|
30 | # 14 350 -25.9 -47.9 334 334 10 8540 NORMAL |
---|
31 | # 15 346 -25.9 -48.9 335 335 9 8623 ISOTERM |
---|
32 | # 16 335 -26.9 -41.9 337 338 22 8857 NORMAL |
---|
33 | # 17 333 -27.9 -47.9 336 337 12 8900 ADIABAT |
---|
34 | # 18 259 -41.7 -59.7 341 341 11 10654 NORMAL |
---|
35 | # 19 258 -41.7 -59.7 341 341 11 10680 ADIABAT |
---|
36 | |
---|
37 | |
---|
38 | # ::: NIVELES TIPO ::: |
---|
39 | |
---|
40 | # NIVEL PP(MB) TT(C) TD(C) HR Z(MGP) DD FFF CAPA AD.3HS |
---|
41 | |
---|
42 | # SUP. 996 26.2 23.9 87 52 20 7 |
---|
43 | # 1 1000 ***** ***** *** 17 *** *** 1000-850 ***** |
---|
44 | # 2 850 20.9 18.4 86 1442 330 44 850-700 0.6 |
---|
45 | # 3 700 11.5 8.5 82 3104 320 31 700-500 0.8 |
---|
46 | # 4 500 -5.4 -18.4 36 5836 285 32 500-400 0.0 |
---|
47 | # 5 400 -17.3 -36.1 18 7546 285 48 400-300 1.5 |
---|
48 | # 6 300 -33.6 -52.8 12 9628 270 68 300-250 ***** |
---|
49 | |
---|
50 | # ::VTOS NIV. FIJOS H:(MGP);NIV.SIG.P(MB.):: |
---|
51 | # H^P? DD FF(KT) H^P? DD FF(KT) H^P? DD FF(KT) |
---|
52 | # 996 20 7 940 350 48 845 325 43 |
---|
53 | # 645 315 33 562 290 22 424 290 50 |
---|
54 | # 374 280 47 320 270 72 317 270 72 |
---|
55 | # 269 270 67 0 20 7 300 15 15 |
---|
56 | # 600 35 17 900 50 16 2100 30 1 |
---|
57 | # VIENTO TERMICO DE LOS 196/ 31 KT ESPESOR(500/1000) 5819 MGP |
---|
58 | # V.MAX EN: 317 MBS 9240 MGP DE LOS 270 GR 72 KT CORT(KT/KM)****** |
---|
59 | |
---|
60 | # NCA: 963 MB 23.4 G.C. 296 MGP |
---|
61 | # NCC: 834 MB 19.7 G.C. 1554 MGP T.CRIT: 34.9 G.C. |
---|
62 | |
---|
63 | # ISOTERMA DE CERO GRADO |
---|
64 | # PRESION: 543 MB ALTURA: 5133 MGP |
---|
65 | |
---|
66 | # INDICES DE INESTABILIDAD: |
---|
67 | # K: 41.6 SH: -4.1 LI: -4.3 FM: -4.3 |
---|
68 | # CT:23.8 VT:26.2 TT:50.0 SWEAT: 491.8 |
---|
69 | # |
---|
70 | # AGUA PRECIPITABLE: 58.6 MM TEMP. POT. EQUIV. 850 MB: 354.8 |
---|
71 | # |
---|
72 | # TOPE AREA POSITIVA |
---|
73 | # PRES: 258 MB TEMP: ***** C ALT:10680 MGP AREA:2077.2 KJ/TON |
---|
74 | # GRUPO DE NUBES: 20970 |
---|
75 | # 1 |
---|
76 | |
---|
77 | from optparse import OptionParser |
---|
78 | import numpy as np |
---|
79 | from netCDF4 import Dataset as NetCDFFile |
---|
80 | import os |
---|
81 | import re |
---|
82 | import numpy.ma as ma |
---|
83 | # Importing generic tools file 'nc_var_tools.py' |
---|
84 | import nc_var_tools as ncvar |
---|
85 | # Importing generic tools file 'generic_tools.py' |
---|
86 | import generic_tools as gen |
---|
87 | import subprocess as sub |
---|
88 | import time |
---|
89 | |
---|
90 | main = 'snd_DCAO_netCDF.py' |
---|
91 | |
---|
92 | ###### ###### ##### #### ### ## # |
---|
93 | errormsg = 'ERROR -- error -- ERROR -- error' |
---|
94 | |
---|
95 | Lstring = 256 |
---|
96 | |
---|
97 | def station_inf(linev): |
---|
98 | """ Function to retrieve station information |
---|
99 | linev: values from line retrieved from file (detected by linev[0]=='ESTACION:') |
---|
100 | """ |
---|
101 | fname = 'station_inf' |
---|
102 | |
---|
103 | if linev[0] != 'ESTACION:': |
---|
104 | print errormsg |
---|
105 | print ' ' + fname + ": first value must be 'ESTACION:', but I got '" + \ |
---|
106 | linev[0] + "' !!" |
---|
107 | quit(-1) |
---|
108 | |
---|
109 | Lvals = len(linevals) |
---|
110 | stid = int(linevals[1]) |
---|
111 | stn = ' '.join(linevals[3:Lvals-5]) |
---|
112 | stlat = linevals[Lvals-5] |
---|
113 | stlon = linevals[Lvals-4] |
---|
114 | sth = np.float(linevals[Lvals-2]) |
---|
115 | |
---|
116 | # conversion lon, lat |
---|
117 | Lstlat = len(stlat) |
---|
118 | if stlat[Lstlat-1:Lstlat] == 'S': stlat = -np.float(stlat[0:Lstlat-1]) |
---|
119 | else: stlat = np.float(stlat[0:Lstlat-1]) |
---|
120 | |
---|
121 | Lstlon = len(stlon) |
---|
122 | if stlon[Lstlon-1:Lstlon] == 'S': stlon = -np.float(stlon[0:Lstlon-1]) |
---|
123 | else: stlon = np.float(stlon[0:Lstlon-1]) |
---|
124 | |
---|
125 | stinf = [stid, stn, stlat, stlon, sth] |
---|
126 | |
---|
127 | return stinf |
---|
128 | |
---|
129 | def station_timeinf(linev): |
---|
130 | """ Function to get date-time from record |
---|
131 | linev: values from line (linev has 'UTC') |
---|
132 | """ |
---|
133 | fname = 'station_timeinf' |
---|
134 | |
---|
135 | if not gen.searchInlist(linev, 'UTC'): |
---|
136 | print errormsg |
---|
137 | print ' ' + fname + ": values do not have 'UTC' !!" |
---|
138 | print ' values passed:', linev |
---|
139 | quit(-1) |
---|
140 | |
---|
141 | # Getting time data |
---|
142 | stdate = linevals[0] |
---|
143 | sttime = linevals[1].zfill(2) |
---|
144 | |
---|
145 | # Transforming to CFdate |
---|
146 | refdate = '1949-12-01 00:00:00' |
---|
147 | tunits = 'minutes' |
---|
148 | |
---|
149 | datev = stdate.split('-') |
---|
150 | dateeng = datev[2] + '-' + datev[1] + '-' + datev[0] |
---|
151 | |
---|
152 | stCFtime = gen.datetimeStr_conversion(dateeng+' '+sttime+':00:00', 'Y-m-d H:M:S',\ |
---|
153 | 'cfTime,' + tunits + ' since ' + refdate) |
---|
154 | |
---|
155 | sttinf = [stdate, sttime, stCFtime, refdate, tunits] |
---|
156 | |
---|
157 | return sttinf |
---|
158 | |
---|
159 | # Arguments |
---|
160 | ## |
---|
161 | parser = OptionParser() |
---|
162 | parser.add_option("-D", "--Debug", dest="debug", |
---|
163 | help="debug prints", metavar="BOOL") |
---|
164 | parser.add_option("-f", "--snd_file", dest="sndfile", |
---|
165 | help="UDCAO sounding (from Gustavo Pittaluga - Banco de datos DCAO <banco@at.fcen.uba.ar>) file to use", |
---|
166 | metavar="FILE") |
---|
167 | |
---|
168 | (opts, args) = parser.parse_args() |
---|
169 | |
---|
170 | ####### ####### |
---|
171 | ## MAIN |
---|
172 | ####### |
---|
173 | |
---|
174 | if opts.debug is None: |
---|
175 | print gen.infmsg |
---|
176 | print ' ' + main + ": no debug value provided!!" |
---|
177 | print ' assuming:', False |
---|
178 | debug = False |
---|
179 | else: |
---|
180 | debug = gen.Str_Bool(opts.debug) |
---|
181 | |
---|
182 | if not os.path.isfile(opts.sndfile): |
---|
183 | print gen.errormsg |
---|
184 | print ' ' + main + ": sounding file '" + opts.sndfile + "' does not exist !!" |
---|
185 | quit(-1) |
---|
186 | |
---|
187 | # Reading sounding file |
---|
188 | osnd = open(opts.sndfile, 'r') |
---|
189 | |
---|
190 | # Dictionary with station data |
---|
191 | stations = {} |
---|
192 | |
---|
193 | siglev = False |
---|
194 | tipolev = False |
---|
195 | fijolev = False |
---|
196 | indices = False |
---|
197 | Nsiglev = 0 |
---|
198 | Ntipolev = 0 |
---|
199 | Nfijolev = 0 |
---|
200 | Nindices = 0 |
---|
201 | |
---|
202 | # Recovering information from file |
---|
203 | for line in osnd: |
---|
204 | if line[0:1] != '#' and len(line) > 1: |
---|
205 | # getting values removing spurious spaces |
---|
206 | linevals = gen.values_line(line, ' ', ['\t', '\n', '\r']) |
---|
207 | |
---|
208 | # Got trhought lines with data! |
---|
209 | if len(linevals) != 0: |
---|
210 | print linevals |
---|
211 | print siglev, Nsiglev, tipolev, Ntipolev, fijolev, Nfijolev, indices, Nindices |
---|
212 | |
---|
213 | # Starting of record by finding 'ESTACION:' |
---|
214 | if linevals[0] == 'ESTACION:': |
---|
215 | statinf = station_inf(linevals) |
---|
216 | siglev = False |
---|
217 | tipolev = False |
---|
218 | fijolev = False |
---|
219 | indices = False |
---|
220 | |
---|
221 | # date/time of record by finding 'UTC' |
---|
222 | elif gen.searchInlist(linevals, 'UTC'): |
---|
223 | statTinf = station_timeinf(linevals) |
---|
224 | |
---|
225 | statinf = statinf + statTinf |
---|
226 | |
---|
227 | # significative levels |
---|
228 | elif gen.searchInlist(linevals, 'SIGNIFICATIVOS'): |
---|
229 | siglev = True |
---|
230 | Nsiglev = 0 |
---|
231 | |
---|
232 | # tipo levels |
---|
233 | elif gen.searchInlist(linevals, 'TIPO'): |
---|
234 | siglev = False |
---|
235 | # Removing headers |
---|
236 | Nsiglev = Nsiglev - 2 |
---|
237 | |
---|
238 | tipolev = True |
---|
239 | Ntipolev = 0 |
---|
240 | |
---|
241 | # fijo levels |
---|
242 | elif gen.searchInlist(linevals, 'FIJOS'): |
---|
243 | tipolev = False |
---|
244 | # Removing headers |
---|
245 | Ntipolev = Ntipolev - 2 |
---|
246 | |
---|
247 | fijolev = True |
---|
248 | Nfijolev = 0 |
---|
249 | |
---|
250 | # indices |
---|
251 | elif gen.searchInlist(linevals, 'TERMICO'): |
---|
252 | fijolev = False |
---|
253 | # Removing headers |
---|
254 | Nfijolev = Nfijolev - 2 |
---|
255 | |
---|
256 | indices = True |
---|
257 | Nindices = 0 |
---|
258 | |
---|
259 | # End record |
---|
260 | elif linevals[0] == '1' and indices: |
---|
261 | indices = False |
---|
262 | |
---|
263 | stvals = statinf + [Nsiglev, Ntipolev, Nfijolev, Nindices] |
---|
264 | if not stations.has_key(statinf[0]): |
---|
265 | stations[statinf[0]] = [stvals] |
---|
266 | else: |
---|
267 | stv = stations[statinf[0]] |
---|
268 | stv.append(stvals) |
---|
269 | stations[statinf[0]] = stv |
---|
270 | |
---|
271 | print stvals |
---|
272 | quit(-1) |
---|
273 | |
---|
274 | elif tipolev: |
---|
275 | Ntipolev = Ntipolev + 1 |
---|
276 | |
---|
277 | elif siglev: |
---|
278 | Nsiglev = Nsiglev + 1 |
---|
279 | |
---|
280 | elif fijolev: |
---|
281 | Nfijolev = Nfijolev + 1 |
---|
282 | |
---|
283 | elif indices: |
---|
284 | Nindices = Nindices + 1 |
---|
285 | |
---|
286 | gen.printing_dictionary(stations) |
---|
287 | osnd.close() |
---|