NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/sodar/trunk/sodar/formattedData.py

Revision 78 (checked in by cbc, 17 years ago)

Fulfill tickets #13, #14, #18, #22.

Line 
1 #!/usr/bin/python
2 """
3 Module to handle formatting sodar data samples.
4
5 A list of sample data.
6
7 A sample: formattedDataObject[0] -> dictionary
8
9 A sample header: formattedDataObject[0]['header'] -> dictionary
10
11 A sample body: formattedDataObject[0]['body'] -> list of dictionaries
12
13 Altitude data from a sample: formattedDataObject[0]['body'][0] -> dictionary
14 """
15
16 __author__ = 'Chris Calloway'
17 __email__ = 'cbc@unc.edu'
18 __copyright__ = 'Copyright 2007 UNC-CH Department of Marine Science'
19 __license__ = 'GPL2'
20
21 import rawData
22 import numpy as n
23 import datetime
24
25 class FormattedData(list):
26    
27     """Class to handle formatted daily sodar file data.
28     
29        A list of samples.
30     """
31    
32     def __init__(self, data):
33         """Create formatted sodar daily data."""
34         super(FormattedData, self).__init__()
35         self.extend([sample.data() for sample in data])
36         self._format()
37    
38     def _format(self):
39         """Format raw sodar daily data."""
40         self._convert()
41         self._stamp()
42         self._timeInterval()
43         self._minAltitude()
44         self._maxAltitude()
45         self._numAltitudes()
46         self._altInterval()
47         # correct for missing times
48         # correct for missing altitudes
49         # mark maximum altitude with good values for each sample
50         # mark minimum altitude with invalid values for each sample
51         # convert direction to radians
52         # compute u,v,c components
53         # compute colorspecs
54         # compute plotting parameters
55     
56     def _convert(self):
57         """Convert data to numbers and correct for invalid values."""
58         INVALID = "-9999"
59         for sample in self:
60             # convert header data to integers
61             for key,value in sample['header'].items():
62                 try:
63                     if value == INVALID:
64                         raise ValueError
65                     sample['header'][key] = int(value)
66                 except (ValueError, TypeError):
67                     sample['header'][key] = n.NaN
68             # convert body data to floats
69             for altitude in sample['body']:
70                 for key,value in altitude.items():
71                     try:
72                         if value == INVALID:
73                             raise ValueError
74                         altitude[key] = float(value)
75                     except (ValueError, TypeError):
76                         altitude[key] = n.NaN
77    
78     def _stamp(self):
79         """Add a datetime stamp item to each sample."""
80         for sample in self:
81             header = sample['header']
82             sample['stamp'] = datetime.datetime(header['YEAR'],
83                                                 header['MONTH'],
84                                                 header['DAY'],
85                                                 header['HOUR'],
86                                                 header['MIN'])
87    
88     def _timeInterval(self):
89         """Add a time interval attribute."""
90         intervals = zip([sample['stamp'] for sample in self[:-1]],
91                         [sample['stamp'] for sample in self[1:]])
92         intervals = [interval[1] - interval[0] for interval in intervals]
93         self.timeInterval = min(intervals)
94    
95     def _minAltitude(self):
96         """Add an overall minimum altitude attribute."""
97         altitudes = [sample['body'][0]['ALT'] for sample in self]
98         self.minAltitude = min(altitudes)
99    
100     def _maxAltitude(self):
101         """Add an overall maximum altitude attribute."""
102         altitudes = [sample['body'][-1]['ALT'] for sample in self]
103         self.maxAltitude = max(altitudes)
104    
105     def _numAltitudes(self):
106         """Add an overall maximum number of altitudes attribute"""
107         self.numAltitudes = max([len(sample['body']) for sample in self])
108    
109     def _altInterval(self):
110         """Add an overall altitude interval attribute."""
111         self.altInterval = (self.maxAltitude - self.minAltitude) / \
112                            (self.numAltitudes - 1)
113
114
115 def _main():
116     """Process as script from command line."""
117     import urllib2
118     try:
119         rawDataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/'\
120                                         'data/nccoos/level0/dukeforest/sodar/'\
121                                         'store/2007-06/20070601.dat')
122         rawDataString = rawDataHandle.read()
123     except:
124         raise IOError("Failure to read raw test data")
125     rawDataObject = rawData.RawData(rawDataString)
126     formattedDataObject = FormattedData(rawDataObject)
127     print "Time Interval =", formattedDataObject.timeInterval
128     print "Minumum Altitude =", formattedDataObject.minAltitude
129     print "Maximum Altitude =", formattedDataObject.maxAltitude
130     print "Number of Altitudes =", formattedDataObject.numAltitudes
131     print "Altitude Interval =", formattedDataObject.altInterval
132
133 if __name__ == "__main__":
134     _main()
Note: See TracBrowser for help on using the browser.