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

root/sodar/trunk/sodar/processedData.py

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

Saving tested refactoring.

Line 
1 #!/usr/bin/python
2 """
3 Classes to handle processed sodar data samples.
4
5 A list of sample data.
6
7 A list of dictionaries, each with an item for header and body data.
8
9 A list of dictionaries of sample data, each with a two items:
10     a header dictionary, and
11     a body list of alitude dictionaries.
12 """
13
14 __author__ = 'Chris Calloway'
15 __email__ = 'cbc@unc.edu'
16 __copyright__ = 'Copyright 2007 UNC-CH Department of Marine Science'
17 __license__ = 'GPL2'
18
19 import rawData
20 import numpy as n
21 import datetime
22
23 class ProcessedData(list):
24    
25     """Processed daily sodar file data.
26     
27        A list of rawData.Sample deep copies.
28     """
29    
30     def __init__(self, data):
31         """Prepare raw sodar daily data for analysis."""
32         super(ProcessedData, self).__init__()
33         self.extend([sample.data() for sample in data])
34         self._normalize()
35
36     def _normalize(self):
37         """Clean up data for analysis."""
38         self._convert()
39         self._stamp()
40         self._sampleInterval()
41         # correct for missing times
42         self._minimumAltitude()
43         self._maximumAltitude()
44         # compute number of altitudes
45         # compute altitude interval
46         # correct for missing altitudes
47         # mark maximum altitude with good values for each sample
48         # mark minimum altitude with invalid values for each sample
49         # convert direction to radians
50         # compute u,v,c components
51         # compute colorspecs
52         # compute plotting parameters
53     
54     def _convert(self):
55         """Convert data to numbers and correct for invalid values."""
56         INVALID = "-9999"
57         for sample in self:
58             # convert header data to integers
59             for key,value in sample['header'].items():
60                 try:
61                     if value == INVALID:
62                         raise ValueError
63                     sample['header'][key] = int(value)
64                 except (ValueError, TypeError):
65                     sample['header'][key] = n.NaN
66             # convert body data to floats
67             for altitude in sample['body']:
68                 for key,value in altitude.items():
69                     try:
70                         if value == INVALID:
71                             raise ValueError
72                         altitude[key] = float(value)
73                     except (ValueError, TypeError):
74                         altitude[key] = n.NaN
75    
76     def _stamp(self):
77         """Add a datetime stamp item to each sample."""
78         for sample in self:
79             try:
80                 header = sample['header']
81                 sample['stamp'] = datetime.datetime(header['YEAR'],
82                                                     header['MONTH'],
83                                                     header['DAY'],
84                                                     header['HOUR'],
85                                                     header['MIN'])
86             except (KeyError, TypeError):
87                 sample['stamp'] = datetime.datetime.min
88    
89     def _sampleInterval(self):
90         """Add a sample interval attribute."""
91         intervals = zip([sample['stamp'] for sample in self[:-1]],
92                         [sample['stamp'] for sample in self[1:]])
93         intervals = [interval[1] - interval[0] for interval in intervals]
94         intervals = [interval for interval in intervals if interval]
95         intervals = [interval for interval in intervals
96                      if interval != datetime.datetime.min]
97         try:
98             self.interval = min(intervals)
99         except ValueError:
100             self.interval = datetime.datetime.min
101    
102     def _minimumAltitude(self):
103         """Add an overall minimum altitude attribute."""
104         accumulator = {}
105         for sample in self:
106             minalt = sample['body'][0]['ALT']
107             sample['header']['minalt'] = minalt
108             if minalt is not n.NaN:
109                 if minalt in accumulator:
110                     accumulator[minalt] += 1
111                 else:
112                     accumulator[minalt] = 1
113         maxVotes = max(accumulator.values())
114         for key,value in accumulator.items():
115             if value == maxVotes:
116                 self.minimumAltitude = key
117                 break
118         self.minimumAltitude = getattr(self,
119                                        'minimumAltitude',
120                                        n.NaN)
121
122    
123     def _maximumAltitude(self):
124         """Add an overall maximum altitude attribute."""
125         accumulator = {}
126         for sample in self:
127             maxalt = sample['body'][-1]['ALT']
128             sample['header']['maxalt'] = maxalt
129             if maxalt is not n.NaN:
130                 if maxalt in accumulator:
131                     accumulator[maxalt] += 1
132                 else:
133                     accumulator[maxalt] = 1
134         maxVotes = max(accumulator.values())
135         for key,value in accumulator.items():
136             if value == maxVotes:
137                 self.maximumAltitude = key
138                 break
139         self.maximumAltitude = getattr(self,
140                                        'maximumAltitude',
141                                        n.NaN)
142 def _main():
143     """Process as script from command line."""
144     import urllib2
145     try:
146         rawDataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/'\
147                                         'data/nccoos/level0/dukeforest/sodar/'\
148                                         'store/2007-06/20070601.dat')
149         rawDataString = rawDataHandle.read()
150     except:
151         raise IOError("Failure to read raw test data")
152     rawDataObject = rawData.RawData(rawDataString)
153     processedDataObject = ProcessedData(rawDataObject)
154
155 if __name__ == "__main__":
156     _main()
Note: See TracBrowser for help on using the browser.