# python script to transform DCAO's snd data to netCDF
# L. Fita, CIMA. Sept. 2018

## e.g. # snd_DCAO_netcdf.py -f pedidoLluis200212.dat

### ASCII files from DCAO can have more than one sounding per file
### Script spect to find
#       ESTACION: 87155    RESISTENCIA AERO    27.30S  59.00W (  52 M)            
                                                                                 
#                  1-12-2002    6 UTC                                             
                                                                                 
                                                                                 
#                      ::: NIVELES SIGNIFICATIVOS :::                             
                                                                                 
#       NIVEL   PP(MB) TT(C)  TD(C)     TP(K) TPE(K)  HR  Z(MGP)  GRAD.           
                                                                                 
#          1      996   26.2   23.9      300   354    87     52                   
#          2      951   24.6   22.3      302   354    87    461   NORMAL          
#          3      930   26.4   21.4      306   357    74    658  INVERS.          
#          4      793   16.6   16.1      310   353    97   2047   NORMAL          
#          5      701   11.6    8.6      315   346    82   3092   NORMAL          
#          6      644    6.6    4.6      317   343    87   3797   NORMAL          
#          7      621    7.6   -4.4      322   336    43   4097  INVERS.          
#          8      610    6.2   -5.8      322   335    42   4244  ADIABAT          
#          9      607    6.4   -5.6      322   336    42   4284  ADIABAT          
#         10      567    2.8  -10.2      325   335    38   4840   NORMAL          
#         11      565    2.6  -10.4      325   335    38   4869  ADIABAT          
#         12      472   -9.1  -22.1      327   332    34   6292   NORMAL          
#         13      432  -12.3  -29.3      332   335    23   6973   NORMAL          
#         14      350  -25.9  -47.9      334   334    10   8540   NORMAL          
#         15      346  -25.9  -48.9      335   335     9   8623  ISOTERM          
#         16      335  -26.9  -41.9      337   338    22   8857   NORMAL          
#         17      333  -27.9  -47.9      336   337    12   8900  ADIABAT          
#         18      259  -41.7  -59.7      341   341    11  10654   NORMAL          
#         19      258  -41.7  -59.7      341   341    11  10680  ADIABAT          
                                                                                 
                                                                                 
#                          ::: NIVELES TIPO :::                                   
                                                                                 
#       NIVEL   PP(MB) TT(C)  TD(C)  HR   Z(MGP)  DD FFF   CAPA   AD.3HS          
                                                                                 
#        SUP.    996   26.2   23.9   87      52   20   7                          
#         1     1000  *****  *****  ***      17  *** *** 1000-850  *****          
#         2      850   20.9   18.4   86    1442  330  44  850-700    0.6          
#         3      700   11.5    8.5   82    3104  320  31  700-500    0.8          
#         4      500   -5.4  -18.4   36    5836  285  32  500-400    0.0          
#         5      400  -17.3  -36.1   18    7546  285  48  400-300    1.5          
#         6      300  -33.6  -52.8   12    9628  270  68  300-250  *****          
                                                                                 
#                    ::VTOS NIV. FIJOS H:(MGP);NIV.SIG.P(MB.)::                   
#        H^P?  DD FF(KT)      H^P?  DD FF(KT)      H^P?  DD FF(KT)                
#         996  20   7          940 350  48          845 325  43                   
#         645 315  33          562 290  22          424 290  50                   
#         374 280  47          320 270  72          317 270  72                   
#         269 270  67            0  20   7          300  15  15                   
#         600  35  17          900  50  16         2100  30   1                   
#       VIENTO TERMICO DE LOS  196/  31 KT  ESPESOR(500/1000)   5819 MGP          
#       V.MAX EN: 317 MBS 9240 MGP DE LOS 270 GR  72 KT CORT(KT/KM)******         
                                                                                 
#       NCA:  963 MB  23.4 G.C.   296 MGP                                         
#       NCC:  834 MB  19.7 G.C.  1554 MGP T.CRIT:  34.9 G.C.                      
                                                                                 
#       ISOTERMA DE CERO GRADO                                                    
#                    PRESION:  543 MB   ALTURA:  5133 MGP                         
                                                                                 
#       INDICES DE INESTABILIDAD:                                                 
#       K: 41.6 SH: -4.1 LI: -4.3 FM: -4.3                                        
#       CT:23.8 VT:26.2 TT:50.0 SWEAT: 491.8                                      
#                                                                                 
#       AGUA PRECIPITABLE:  58.6 MM    TEMP. POT. EQUIV. 850 MB: 354.8            
#                                                                                 
#       TOPE AREA  POSITIVA                                                       
#       PRES:  258 MB  TEMP: ***** C  ALT:10680 MGP  AREA:2077.2 KJ/TON           
#       GRUPO DE NUBES: 20970                                                     
# 1                                                                               
 
from optparse import OptionParser
import numpy as np
from netCDF4 import Dataset as NetCDFFile
import os
import re
import numpy.ma as ma
# Importing generic tools file 'nc_var_tools.py'
import nc_var_tools as ncvar
# Importing generic tools file 'generic_tools.py'
import generic_tools as gen
import subprocess as sub
import time

main = 'snd_DCAO_netCDF.py'

###### ###### ##### #### ### ## #
errormsg = 'ERROR -- error -- ERROR -- error'

Lstring = 256

def station_inf(linev):
    """ Function to retrieve station information
      linev: values from line retrieved from file (detected by linev[0]=='ESTACION:')
    """
    fname = 'station_inf'

    if linev[0] != 'ESTACION:':
        print errormsg
        print '  ' + fname + ": first value must be 'ESTACION:', but I got '" +      \
          linev[0] + "' !!"
        quit(-1)

    Lvals = len(linevals)
    stid = int(linevals[1])
    stn = ' '.join(linevals[3:Lvals-5])
    stlat = linevals[Lvals-5]
    stlon = linevals[Lvals-4]
    sth = np.float(linevals[Lvals-2])

    # conversion lon, lat
    Lstlat = len(stlat)
    if stlat[Lstlat-1:Lstlat] == 'S': stlat = -np.float(stlat[0:Lstlat-1])
    else: stlat = np.float(stlat[0:Lstlat-1])
    
    Lstlon = len(stlon)
    if stlon[Lstlon-1:Lstlon] == 'S': stlon = -np.float(stlon[0:Lstlon-1])
    else: stlon = np.float(stlon[0:Lstlon-1])

    stinf = [stid, stn, stlat, stlon, sth]

    return stinf

def station_timeinf(linev):
    """ Function to get date-time from record
      linev: values from line (linev has 'UTC')
    """
    fname = 'station_timeinf'

    if not gen.searchInlist(linev, 'UTC'):
        print errormsg
        print '  ' + fname + ": values do not have 'UTC' !!"
        print '    values passed:', linev
        quit(-1)

    # Getting time data
    stdate = linevals[0]
    sttime = linevals[1].zfill(2)

    # Transforming to CFdate
    refdate = '1949-12-01 00:00:00'
    tunits = 'minutes'

    datev = stdate.split('-')
    dateeng = datev[2] + '-' + datev[1] + '-' + datev[0]

    stCFtime = gen.datetimeStr_conversion(dateeng+' '+sttime+':00:00', 'Y-m-d H:M:S',\
      'cfTime,' + tunits + ' since ' + refdate)

    sttinf = [stdate, sttime, stCFtime, refdate, tunits]

    return sttinf

# Arguments
##
parser = OptionParser()
parser.add_option("-D", "--Debug", dest="debug", 
  help="debug prints",  metavar="BOOL")
parser.add_option("-f", "--snd_file", dest="sndfile", 
  help="UDCAO sounding (from Gustavo Pittaluga - Banco de datos DCAO <banco@at.fcen.uba.ar>) file to use", 
  metavar="FILE")

(opts, args) = parser.parse_args()

#######    #######
## MAIN
    #######

if opts.debug is None:
    print gen.infmsg
    print '  ' + main + ": no debug value provided!!"
    print '    assuming:', False
    debug = False
else:
    debug = gen.Str_Bool(opts.debug)

if not os.path.isfile(opts.sndfile):
      print gen.errormsg
      print '   ' + main + ": sounding file '" + opts.sndfile + "' does not exist !!"
      quit(-1)    

# Reading sounding file
osnd = open(opts.sndfile, 'r')

# Dictionary with station data
stations = {}

siglev = False
tipolev = False
fijolev = False
indices = False
Nsiglev = 0
Ntipolev = 0
Nfijolev = 0
Nindices = 0

# Recovering information from file
for line in osnd:
    if line[0:1] != '#' and len(line) > 1:
        # getting values removing spurious spaces
        linevals = gen.values_line(line, ' ', ['\t', '\n', '\r'])

        # Got trhought lines with data!
        if len(linevals) != 0:
            print linevals
            print siglev, Nsiglev, tipolev, Ntipolev, fijolev, Nfijolev, indices, Nindices

            # Starting of record by finding 'ESTACION:'
            if linevals[0] == 'ESTACION:':
                statinf = station_inf(linevals)
                siglev = False
                tipolev = False
                fijolev = False
                indices = False

            # date/time  of record by finding 'UTC'
            elif gen.searchInlist(linevals, 'UTC'):
                statTinf = station_timeinf(linevals)

                statinf = statinf + statTinf

            # significative levels
            elif gen.searchInlist(linevals, 'SIGNIFICATIVOS'):
                siglev = True
                Nsiglev = 0

            # tipo levels
            elif gen.searchInlist(linevals, 'TIPO'):
                siglev = False
                # Removing headers
                Nsiglev = Nsiglev - 2

                tipolev = True
                Ntipolev = 0

            # fijo levels
            elif gen.searchInlist(linevals, 'FIJOS'):
                tipolev = False
                # Removing headers
                Ntipolev = Ntipolev - 2

                fijolev = True
                Nfijolev = 0

            # indices
            elif gen.searchInlist(linevals, 'TERMICO'):
                fijolev = False
                # Removing headers
                Nfijolev = Nfijolev - 2

                indices = True
                Nindices = 0

            # End record
            elif linevals[0] == '1' and indices:
                indices = False

                stvals = statinf + [Nsiglev, Ntipolev, Nfijolev, Nindices]
                if not stations.has_key(statinf[0]):
                    stations[statinf[0]] = [stvals]
                else:
                    stv = stations[statinf[0]]
                    stv.append(stvals)
                    stations[statinf[0]] = stv

                print stvals
                quit(-1)

            elif tipolev: 
                Ntipolev = Ntipolev + 1

            elif siglev: 
                Nsiglev = Nsiglev + 1

            elif fijolev: 
                Nfijolev = Nfijolev + 1

            elif indices: 
                Nindices = Nindices + 1

gen.printing_dictionary(stations)
osnd.close()
