[2142] | 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 | |
---|
[2150] | 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 | |
---|
[2142] | 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: |
---|
[2150] | 210 | print linevals |
---|
| 211 | print siglev, Nsiglev, tipolev, Ntipolev, fijolev, Nfijolev, indices, Nindices |
---|
| 212 | |
---|
| 213 | # Starting of record by finding 'ESTACION:' |
---|
[2142] | 214 | if linevals[0] == 'ESTACION:': |
---|
| 215 | statinf = station_inf(linevals) |
---|
[2150] | 216 | siglev = False |
---|
| 217 | tipolev = False |
---|
| 218 | fijolev = False |
---|
| 219 | indices = False |
---|
[2142] | 220 | |
---|
[2150] | 221 | # date/time of record by finding 'UTC' |
---|
[2142] | 222 | elif gen.searchInlist(linevals, 'UTC'): |
---|
| 223 | statTinf = station_timeinf(linevals) |
---|
| 224 | |
---|
| 225 | statinf = statinf + statTinf |
---|
| 226 | |
---|
[2150] | 227 | # significative levels |
---|
| 228 | elif gen.searchInlist(linevals, 'SIGNIFICATIVOS'): |
---|
| 229 | siglev = True |
---|
| 230 | Nsiglev = 0 |
---|
[2142] | 231 | |
---|
[2150] | 232 | # tipo levels |
---|
| 233 | elif gen.searchInlist(linevals, 'TIPO'): |
---|
| 234 | siglev = False |
---|
| 235 | # Removing headers |
---|
| 236 | Nsiglev = Nsiglev - 2 |
---|
[2142] | 237 | |
---|
[2150] | 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() |
---|