From fc4a18fedf5723a9c47d2a513bf2062f18a82c92 Mon Sep 17 00:00:00 2001
From: kgao <kenny.gao@ssec.wisc.edu>
Date: Fri, 29 Jul 2016 18:01:33 +0000
Subject: [PATCH] Created level_a1 draft Only works when -s and -e are
 specified at the moment Created draft nc file might need to change altitude
 value

---
 aosstower/level_a0/__init__.py |   1 +
 aosstower/level_a0/nc.py       | 246 +++++++++++++++++++++++++++++++++
 2 files changed, 247 insertions(+)
 create mode 100644 aosstower/level_a0/__init__.py
 create mode 100644 aosstower/level_a0/nc.py

diff --git a/aosstower/level_a0/__init__.py b/aosstower/level_a0/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/aosstower/level_a0/__init__.py
@@ -0,0 +1 @@
+
diff --git a/aosstower/level_a0/nc.py b/aosstower/level_a0/nc.py
new file mode 100644
index 0000000..977fd9c
--- /dev/null
+++ b/aosstower/level_a0/nc.py
@@ -0,0 +1,246 @@
+import os
+import sys
+import logging
+import pandas as pd
+from datetime import datetime as dt
+from aosstower.l00 import parser
+from netCDF4 import Dataset
+import numpy as np 
+import platform
+from aosstower import station
+
+LOG = logging.getLogger(__name__)
+
+# The purpose of this function is to write the dimensions
+# for the nc file
+# no parameters
+# no returns
+
+def writeDimensions(ncFile, stamps):
+    ncFile.createDimension('time', len(stamps))
+    ncFile.createDimension('strlen', 256)
+
+    return ncFile
+
+def createVariables(ncFile, firstStamp):
+    #base_time long name
+    btln = 'base time as unix timestamp'
+
+    #base time units
+    btu = 'seconds since 1970-01-01 00:00:00'
+
+    #base time string
+    bts = firstStamp.strftime('%Y-%m-%d 00:00:00Z')
+
+    #time long name
+    tln = 'time offset from midnight UTC'
+
+    #time units
+    tu = 'seconds since ' + firstStamp.strftime('%Y-%m-%d 00:00:00Z')
+
+    coordinates = {
+                      #fields: type, dimension, fille, positive, valid_min, std_name, longname, units, valid_max, cf_role, axis
+                      'lon': [np.float32, None, float(-999), '-180L', 'longitude', None, 'degrees_east', '180L', None],
+                      'lat': [np.float32, None, float(-999), '-90L', 'latitude', None, 'degrees_north', '90L', None],
+                      'alt': [np.float32, None, float(-999), None, 'height', 'vertical distance', 'm', None, None],
+                      'base_time': [np.float32, None, float(-999), None, 'time', btln, btu, None, None],
+                      'time': [np.float32, 'time', float(-999), None, 'time', tln, tu, None, None],
+                      'station_name': ['c', 'strlen', '-', None, None, 'station name', None, None, 'timeseries_id']   
+                  }
+
+    for key in coordinates:
+        attr = coordinates[key]
+
+        #create variable
+        if(attr[1]):
+            variable = ncFile.createVariable(key, attr[0], dimensions=(attr[1]), fill_value=attr[2])
+        else:
+            variable = ncFile.createVariable(key, attr[0], fill_value=attr[1])
+
+        #create var attributes
+        if key == 'alt':
+            variable.positive = 'up'
+            variable.axis = 'Z'
+
+        if(attr[3]):
+            variable.valid_min = attr[3]
+            variable.valid_max = attr[7]
+
+        if(attr[4]):
+            variable.standard_name = attr[4]
+
+        if(attr[5]):
+            variable.long_name = attr[5]
+
+        if(attr[6]):
+            variable.units = attr[6]
+
+        if(attr[8]):
+             variable.cf_role = attr[8]
+
+        if key == 'base_time':
+            variable.string = bts
+
+    for entry in parser.database:
+        if(entry == 'stamp'):
+            continue
+
+        varTup = parser.database[entry]
+        
+        variable = ncFile.createVariable(entry, np.float32,
+        dimensions=('time'), fill_value=float(-999))
+        variable.standard_name = varTup[1]
+        variable.description = varTup[3]
+        variable.units = varTup[4]
+
+    #create global attributes
+    ncFile.source = 'surface observation'
+    ncFile.conventions = 'CF-1.6'
+    ncFile.institution = 'UW SSEC'
+    ncFile.featureType = 'timeSeries'
+
+    #generate history
+    ncFile.history = ' '.join(platform.uname()) + " " + os.path.basename(__file__)
+    
+    return ncFile
+
+def getData(inputFiles):
+    dictData = {}
+
+    for filename in inputFiles:
+        for frame in parser.read_frames(filename):
+            if 'stamp' not in frame:
+                continue
+
+            stamp = frame['stamp']
+            del frame['stamp']
+
+            dictData[stamp] = frame
+
+    return pd.DataFrame(dictData).transpose()
+
+def writeVars(ncFile, frame):
+    stamps = list(frame.index)
+
+    baseDTObj = dt.strptime(str(stamps[0]).split(' ')[0], '%Y-%m-%d')
+
+    #find out how much time elapsed
+    #since the origin to the start of the day
+    #in seconds
+    baseTimeValue = baseDTObj - dt(1970,1,1)
+    baseTimeValue = baseTimeValue.total_seconds()
+
+    #create time numpy
+    timeNumpy = np.empty(len(stamps), dtype='float32')
+
+    counter = 0
+
+    #write stamps in, yo
+
+    for stamp in stamps:
+        stampObj = dt.strptime(str(stamp), '%Y-%m-%d %H:%M:%S')
+        timeValue = (stampObj - baseDTObj).total_seconds()
+
+        timeNumpy[counter] = timeValue
+        counter += 1
+
+    fileVar = ncFile.variables
+
+    fileVar['base_time'].assignValue(baseTimeValue)
+    fileVar['time'][:] = timeNumpy
+
+    #write coordinate var values to file
+    #alt might not be right, need to verify
+    fileVar['lon'].assignValue(station.LONGITUDE)
+    fileVar['lat'].assignValue(station.LATITUDE)
+    fileVar['alt'].assignValue(328)
+
+    #might change
+    stationName = ("AOSS Tower")
+    
+    #transfer station name into array of chars
+    statChars = list(stationName)
+    statNumpy = np.asarray(statChars)
+
+    #write station name to file
+    fileVar['station_name'][0:len(statNumpy)]
+
+    #writes data into file
+    for varName in frame:
+        dataList = frame[varName].tolist()
+        dataArray = np.asarray(dataList)
+        fileVar[varName][:] = dataArray
+        
+    return ncFile
+
+#The purpose of this method is to take a begin date, and end date
+# input filenames and output filename and create a netCDF file 
+# based upon that
+# @param start time - a start datetime object
+# @param end time - an end datetime object
+# @param input filenames - list of filenames
+# @param output filename - filename of the netcdf file
+
+def createGiantNetCDF(start, end, inputFiles, outputName):
+    frame = getData(inputFiles)
+
+    frame = frame[start.strftime('%Y-%m-%d %H:%M:%S'): end.strftime('%Y-%m-%d %H:%M:%S')]
+
+    firstStamp = dt.strptime(str(list(frame.index)[0]), '%Y-%m-%d %H:%M:%S')
+
+    if not outputName: 
+        outputName = firstStamp.strftime('aoss_tower.%Y-%m-%d.nc')
+
+    ncFile = Dataset(outputName, 'w')
+
+    ncFile = writeDimensions(ncFile, list(frame.index))
+
+    ncFile = createVariables(ncFile, firstStamp)
+
+    ncFile = writeVars(ncFile, frame)
+
+    ncFile.close()
+    
+#The purpose of this method is to take a string in the format
+# YYYY-mm-ddTHH:MM:SS and convert that to a datetime object
+# used in coordination with argparse -s and -e params
+# @param datetime string
+# @return datetime object
+
+def _dt_convert(datetime_str):
+    #parse datetime string, return datetime object
+    return dt.strptime(datetime_str, '%Y-%m-%dT%H:%M:%S')
+ 
+def main():
+    import argparse
+
+    #argparse description
+    parser = argparse.ArgumentParser(description="Convert level_00 aoss tower data to level_a0")
+
+    #argparse verbosity info
+    parser.add_argument('-v', '--verbose', action="count", default=int(os.environ.get("VERBOSITY", 2)),
+                         dest='verbosity',
+                         help='each occurrence increases verbosity 1 level through ERROR-WARNING-INFO-DEBUG (default INFO)')
+
+    #argparse start and end times
+    parser.add_argument('-s', '--start-time', type=_dt_convert, help="Start time of massive netcdf file")
+    parser.add_argument('-e', '--end-time', type=_dt_convert, help='End time of massive netcdf file')
+
+    parser.add_argument("input_files", nargs="+",
+                         help="aoss_tower level_00 paths")
+
+    parser.add_argument('-o', '--output', help="filename pattern or filename. " +
+    "Should be along the lines of <filepath>/aoss_tower.YYYY-MM-DD.nc")
+    args = parser.parse_args()
+
+    levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG]
+    level=levels[min(3, args.verbosity)]
+    logging.basicConfig(level=level)
+
+    if(args.start_time and args.end_time):
+        createGiantNetCDF(args.start_time, args.end_time, args.input_files, args.output)
+
+    else:
+        createNetCDF(args.input_files, args.ouput)
+if __name__ == "__main__":
+    main()
-- 
GitLab