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

root/sodar/trunk/sodar/processedData.py

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

Fulfill ticket #21: Move array normalization methods to new ProcessedData class

Line 
1 #!/usr/bin/python
2 """
3 Classes to handle processed sodar data samples.
4
5 """
6
7 __author__ = 'Chris Calloway'
8 __email__ = 'cbc@unc.edu'
9 __copyright__ = 'Copyright 2007 UNC-CH Department of Marine Science'
10 __license__ = 'GPL2'
11
12 import rawData
13 import numpy as n
14 import datetime
15
16 class ProcessedData(list):
17    
18     """Processed daily sodar file data."""
19    
20     def __init__(self, data):
21         """Prepare raw sodar daily data for analysis."""
22         super(ProcessedData, self).__init__()
23         self.data = data
24         self._normalize()
25
26     def _normalize(self):
27         """Clean up data for analysis."""
28         self._copy()
29         self._convert()
30         self._stamp()
31         self._sampleInterval()
32         # correct for missing times
33         self._minimumAltitude()
34         self._maximumAltitude()
35         # compute number of altitudes
36         # compute altitude interval
37         # correct for missing altitudes
38         # mark maximum altitude with good values for each sample
39         # mark minimum altitude with invalid values for each sample
40         # convert direction to radians
41         # compute u,v,c components
42         # compute colorspecs
43         # compute plotting parameters
44    
45     def _copy(self):
46         """Create a deep copy as a list of Sample copies."""
47         self.extend([sample._copy() for sample in self.data])
48    
49     def _convert(self):
50         """Convert to numbers and correct for invalid values."""
51         INVALID = "-9999"
52         for sample in self:
53             for altitude in sample['body']:
54                 for key,value in altitude.items():
55                     try:
56                         if value == INVALID:
57                             raise ValueError
58                         altitude[key] = float(value)
59                     except (ValueError, TypeError, KeyError):
60                         altitude[key] = n.NaN
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, KeyError):
67                     sample['header'][key] = n.NaN
68    
69     def _stamp(self):
70         """Add a datetime stamp to each sample."""
71         for sample in self:
72             try:
73                 header = sample['header']
74                 sample['stamp'] = datetime.datetime(header['YEAR'],
75                                                     header['MONTH'],
76                                                     header['DAY'],
77                                                     header['HOUR'],
78                                                     header['MIN'])
79             except (KeyError, TypeError):
80                 sample['stamp'] = datetime.datetime.min
81    
82     def _sampleInterval(self):
83         """Add a sample interval attribute."""
84         intervals = zip([sample['stamp'] for sample in self[:-1]],
85                         [sample['stamp'] for sample in self[1:]])
86         intervals = [interval[1] - interval[0] for interval in intervals]
87         accumulator = {}
88         for interval in intervals:
89             if interval in accumulator:
90                 accumulator[interval] += 1
91             else:
92                 accumulator[interval] = 1
93         maxVotes = max(accumulator.values())
94         for key,value in accumulator.items():
95             if value == maxVotes:
96                 self.sampleInterval = key
97                 break
98         self.sampleInterval = getattr(self,
99                                     'sampleInterval',
100                                     datetime.timedelta.resolution)
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     pass
145
146 if __name__ == "__main__":
147     _main()
Note: See TracBrowser for help on using the browser.