114 | | def _normalize(self): |
---|
115 | | """Clean up data for analysis.""" |
---|
116 | | self._copy() |
---|
117 | | self._convert() |
---|
118 | | self._stamp() |
---|
119 | | self._sampleInterval() |
---|
120 | | # correct for missing times |
---|
121 | | self._minimumAltitude() |
---|
122 | | self._maximumAltitude() |
---|
123 | | # compute number of altitudes |
---|
124 | | # compute altitude interval |
---|
125 | | # correct for missing altitudes |
---|
126 | | # mark maximum altitude with good values for each sample |
---|
127 | | # mark minimum altitude with invalid values for each sample |
---|
128 | | # convert direction to radians |
---|
129 | | # compute u,v,c components |
---|
130 | | # compute colorspecs |
---|
131 | | # compute plotting parameters |
---|
132 | | |
---|
133 | | def _copy(self): |
---|
134 | | """Create a deep copy as a list of Sample copies.""" |
---|
135 | | self.samples = [sample._copy() for sample in self] |
---|
136 | | |
---|
137 | | def _convert(self): |
---|
138 | | """Convert to numbers and correct for invalid values.""" |
---|
139 | | INVALID = "-9999" |
---|
140 | | for sample in self.samples: |
---|
141 | | for altitude in sample['body']: |
---|
142 | | for key,value in altitude.items(): |
---|
143 | | try: |
---|
144 | | if value == INVALID: |
---|
145 | | raise ValueError |
---|
146 | | altitude[key] = float(value) |
---|
147 | | except (ValueError, TypeError, KeyError): |
---|
148 | | altitude[key] = n.NaN |
---|
149 | | for key,value in sample['header'].items(): |
---|
150 | | try: |
---|
151 | | if value == INVALID: |
---|
152 | | raise ValueError |
---|
153 | | sample['header'][key] = int(value) |
---|
154 | | except (ValueError, TypeError, KeyError): |
---|
155 | | sample['header'][key] = n.NaN |
---|
156 | | |
---|
157 | | def _stamp(self): |
---|
158 | | """Add a datetime stamp to each sample.""" |
---|
159 | | for sample in self.samples: |
---|
160 | | try: |
---|
161 | | header = sample['header'] |
---|
162 | | sample['stamp'] = datetime.datetime(header['YEAR'], |
---|
163 | | header['MONTH'], |
---|
164 | | header['DAY'], |
---|
165 | | header['HOUR'], |
---|
166 | | header['MIN']) |
---|
167 | | except (KeyError, TypeError): |
---|
168 | | sample['stamp'] = datetime.datetime.min |
---|
169 | | |
---|
170 | | def _sampleInterval(self): |
---|
171 | | """Add a sample interval attribute.""" |
---|
172 | | intervals = zip([sample['stamp'] for sample in self.samples[:-1]], |
---|
173 | | [sample['stamp'] for sample in self.samples[1:]]) |
---|
174 | | intervals = [interval[1] - interval[0] for interval in intervals] |
---|
175 | | accumulator = {} |
---|
176 | | for interval in intervals: |
---|
177 | | if interval in accumulator: |
---|
178 | | accumulator[interval] += 1 |
---|
179 | | else: |
---|
180 | | accumulator[interval] = 1 |
---|
181 | | maxVotes = max(accumulator.values()) |
---|
182 | | for key,value in accumulator.items(): |
---|
183 | | if value == maxVotes: |
---|
184 | | self.sampleInterval = key |
---|
185 | | break |
---|
186 | | self.sampleInterval = getattr(self, |
---|
187 | | 'sampleInterval', |
---|
188 | | datetime.timedelta.resolution) |
---|
189 | | |
---|
190 | | def _minimumAltitude(self): |
---|
191 | | """Add an overall minimum altitude attribute.""" |
---|
192 | | accumulator = {} |
---|
193 | | for sample in self.samples: |
---|
194 | | minalt = sample['body'][0]['ALT'] |
---|
195 | | sample['header']['minalt'] = minalt |
---|
196 | | if minalt is not n.NaN: |
---|
197 | | if minalt in accumulator: |
---|
198 | | accumulator[minalt] += 1 |
---|
199 | | else: |
---|
200 | | accumulator[minalt] = 1 |
---|
201 | | maxVotes = max(accumulator.values()) |
---|
202 | | for key,value in accumulator.items(): |
---|
203 | | if value == maxVotes: |
---|
204 | | self.minimumAltitude = key |
---|
205 | | break |
---|
206 | | self.minimumAltitude = getattr(self, |
---|
207 | | 'minimumAltitude', |
---|
208 | | n.NaN) |
---|
209 | | |
---|
210 | | |
---|
211 | | def _maximumAltitude(self): |
---|
212 | | """Add an overall maximum altitude attribute.""" |
---|
213 | | accumulator = {} |
---|
214 | | for sample in self.samples: |
---|
215 | | maxalt = sample['body'][-1]['ALT'] |
---|
216 | | sample['header']['maxalt'] = maxalt |
---|
217 | | if maxalt is not n.NaN: |
---|
218 | | if maxalt in accumulator: |
---|
219 | | accumulator[maxalt] += 1 |
---|
220 | | else: |
---|
221 | | accumulator[maxalt] = 1 |
---|
222 | | maxVotes = max(accumulator.values()) |
---|
223 | | for key,value in accumulator.items(): |
---|
224 | | if value == maxVotes: |
---|
225 | | self.maximumAltitude = key |
---|
226 | | break |
---|
227 | | self.maximumAltitude = getattr(self, |
---|
228 | | 'maximumAltitude', |
---|
229 | | n.NaN) |
---|