#!/usr/bin/python """ Classes to handle processed sodar data samples. """ __author__ = 'Chris Calloway' __email__ = 'cbc@unc.edu' __copyright__ = 'Copyright 2007 UNC-CH Department of Marine Science' __license__ = 'GPL2' import rawData import numpy as n import datetime class ProcessedData(list): """Processed daily sodar file data.""" def __init__(self, data): """Prepare raw sodar daily data for analysis.""" super(ProcessedData, self).__init__() self.data = data self._normalize() def _normalize(self): """Clean up data for analysis.""" self._copy() self._convert() self._stamp() self._sampleInterval() # correct for missing times self._minimumAltitude() self._maximumAltitude() # compute number of altitudes # compute altitude interval # correct for missing altitudes # mark maximum altitude with good values for each sample # mark minimum altitude with invalid values for each sample # convert direction to radians # compute u,v,c components # compute colorspecs # compute plotting parameters def _copy(self): """Create a deep copy as a list of Sample copies.""" self.extend([sample._copy() for sample in self.data]) def _convert(self): """Convert to numbers and correct for invalid values.""" INVALID = "-9999" for sample in self: for altitude in sample['body']: for key,value in altitude.items(): try: if value == INVALID: raise ValueError altitude[key] = float(value) except (ValueError, TypeError, KeyError): altitude[key] = n.NaN for key,value in sample['header'].items(): try: if value == INVALID: raise ValueError sample['header'][key] = int(value) except (ValueError, TypeError, KeyError): sample['header'][key] = n.NaN def _stamp(self): """Add a datetime stamp to each sample.""" for sample in self: try: header = sample['header'] sample['stamp'] = datetime.datetime(header['YEAR'], header['MONTH'], header['DAY'], header['HOUR'], header['MIN']) except (KeyError, TypeError): sample['stamp'] = datetime.datetime.min def _sampleInterval(self): """Add a sample interval attribute.""" intervals = zip([sample['stamp'] for sample in self[:-1]], [sample['stamp'] for sample in self[1:]]) intervals = [interval[1] - interval[0] for interval in intervals] accumulator = {} for interval in intervals: if interval in accumulator: accumulator[interval] += 1 else: accumulator[interval] = 1 maxVotes = max(accumulator.values()) for key,value in accumulator.items(): if value == maxVotes: self.sampleInterval = key break self.sampleInterval = getattr(self, 'sampleInterval', datetime.timedelta.resolution) def _minimumAltitude(self): """Add an overall minimum altitude attribute.""" accumulator = {} for sample in self: minalt = sample['body'][0]['ALT'] sample['header']['minalt'] = minalt if minalt is not n.NaN: if minalt in accumulator: accumulator[minalt] += 1 else: accumulator[minalt] = 1 maxVotes = max(accumulator.values()) for key,value in accumulator.items(): if value == maxVotes: self.minimumAltitude = key break self.minimumAltitude = getattr(self, 'minimumAltitude', n.NaN) def _maximumAltitude(self): """Add an overall maximum altitude attribute.""" accumulator = {} for sample in self: maxalt = sample['body'][-1]['ALT'] sample['header']['maxalt'] = maxalt if maxalt is not n.NaN: if maxalt in accumulator: accumulator[maxalt] += 1 else: accumulator[maxalt] = 1 maxVotes = max(accumulator.values()) for key,value in accumulator.items(): if value == maxVotes: self.maximumAltitude = key break self.maximumAltitude = getattr(self, 'maximumAltitude', n.NaN) def _main(): """Process as script from command line.""" pass if __name__ == "__main__": _main()