Changeset 71
- Timestamp:
- 09/05/07 12:17:11
- Files:
-
- sodar/trunk/sodar/rawData.py (moved) (moved from sodar/trunk/sodar/data.py) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
sodar/trunk/sodar/rawData.py
r70 r71 1 1 #!/usr/bin/python 2 2 """ 3 Classes to handle sodar data samples.4 5 Sodar data samples are collected into daily files. Each sample consists of a3 Classes to handle raw sodar data samples. 4 5 Raw sodar data samples are collected into daily files. Each sample consists of a 6 6 header followed by an observation for each height. 7 7 8 The daily file is split into a list (modeled by the class Data) of samples9 (modeled by the class Sample) in chronological order. A Data object is8 The daily file is split into a list (modeled by the class RawData) of samples 9 (modeled by the class Sample) in chronological order. A RawData object is 10 10 initialized with a string representing the daily file data: 11 11 12 dataHandle = open('20070601.dat')13 dataString = data.read()14 dataObject = Data(dataString)12 rawDataHandle = open('20070601.dat') 13 rawDataString = rawDataHandle.read() 14 rawDataObject = RawData(rawDataString) 15 15 16 16 Each Sample object has attributes for a Header and Body object. The Samples 17 within a Data object may also be accessed by time using a string of the format18 YYYY-MM-DD-HH-MM as in index on the Data object to return the first matching19 Sample in the Data object:20 21 dataObject[0] # the first Sample object of the day22 dataObject['2007-06-01-09-15'] # the Sample object for 9:15am23 dataObject[15].header # the Header object of the 16th Sample24 dataObject['2007-06-01-09-15'].body # the Body object for 9:15am17 within a RawData object may also be accessed by time using a string of the format 18 YYYY-MM-DD-HH-MM as in index on the RawData object to return the first matching 19 Sample in the RawData object: 20 21 rawDataObject[0] # the first Sample object of the day 22 rawDataObject['2007-06-01-09-15'] # the Sample object for 9:15am 23 rawDataObject[15].header # the Header object of the 16th Sample 24 rawDataObject['2007-06-01-09-15'].body # the Body object for 9:15am 25 25 26 26 Header objects act as dictionaries. Access each sample-wide parameter of 27 27 interest using the header parameter name as a keyword on the Header object: 28 28 29 dataObject[15].header['VAL2'] # the number of validations for beam 230 dataObject['2007-06-01-09-15'].header['SPU3'] # normalized false signal31 # probability on beam 332 dataObject[0].header['SNR1'] # signal to noise on beam 129 rawDataObject[15].header['VAL2'] # the number of validations for beam 2 30 rawDataObject['2007-06-01-09-15'].header['SPU3'] # normalized false signal 31 # probability on beam 3 32 rawDataObject[0].header['SNR1'] # signal to noise on beam 1 33 33 34 34 Consult your Sodar documentation for a complete list of header parameters. 35 Different sodar models have different sets of header parameters. This model 36 seeks to be model agnostic, and parses the header parameter names from the 37 raw data itself. 35 38 36 39 Body objects act as lists of dictionaries. The dictionaries access … … 39 42 an altitude string: 40 43 41 dataObject[15].body[0] # the data for the lowest altitude, 16th sample42 dataObject['2007-06-01-09-15'].body['70'] # the data for 70 meters43 dataObject[15].body[0]['SPEED'] # wind speed at lowest altitude44 dataObject['2007-06-01-09-15'].body['70']['DIR'] # wind direction45 # at 70 meters44 rawDataObject[15].body[0] # the data for the lowest altitude, 16th sample 45 rawDataObject['2007-06-01-09-15'].body['70'] # the data for 70 meters 46 rawDataObject[15].body[0]['SPEED'] # wind speed at lowest altitude 47 rawDataObject['2007-06-01-09-15'].body['70']['DIR'] # wind direction 48 # at 70 meters 46 49 47 50 The body attribute of a Sample object may also be indexed directly on a Sample 48 51 object for the most convenient semantics: 49 52 50 dataObject[15][0]['SPEED'] # wind speed at lowest altitude, 16th sample51 dataObject['2007-06-01-09-15']['70']['DIR'] # wind direction,52 # 70 meters, 9:15am53 rawDataObject[15][0]['SPEED'] # wind speed at lowest altitude, 16th sample 54 rawDataObject['2007-06-01-09-15']['70']['DIR'] # wind direction, 55 # 70 meters, 9:15am 53 56 """ 54 57 … … 62 65 import datetime 63 66 64 class Data(list):65 66 """ Daily sodar file data.67 class RawData(list): 68 69 """Raw daily sodar file data. 67 70 68 71 (A chronologically ordered list of samples.) … … 71 74 def __init__(self, data): 72 75 """Divide daily string into list of Samples separated by $.""" 73 super( Data, self).__init__()76 super(RawData, self).__init__() 74 77 self.extend([Sample(sample) 75 78 for sample in … … 81 84 """Allow sample retrieval by Sample time in header.""" 82 85 try: 83 return super( Data,self).__getitem__(index)86 return super(RawData,self).__getitem__(index) 84 87 except TypeError: 85 88 return self._find(index) 86 89 87 90 def _find(self, index): 88 """Find Sample in Data91 """Find Sample in RawData. 89 92 90 where sample time of form YYYY-MM-DD-HH-MM.93 Where sample time of form YYYY-MM-DD-HH-MM. 91 94 """ 92 95 … … 94 97 year,month,day,hour,minute = index.split('-') 95 98 except ValueError: 96 raise ValueError(' Data index by date must be "YYYY-MM-DD-HH-MM"')99 raise ValueError('RawData index by date must be "YYYY-MM-DD-HH-MM"') 97 100 except AttributeError: 98 raise AttributeError(' Data index by date must be "YYYY-MM-DD-HH-MM"')101 raise AttributeError('RawData index by date must be "YYYY-MM-DD-HH-MM"') 99 102 for sample in self: 100 103 try: … … 107 110 except TypeError: # sample.header may not exist 108 111 continue 109 raise IndexError(' Data index out of range')112 raise IndexError('RawData index out of range') 110 113 111 114 def _normalize(self): … … 163 166 header['MIN']) 164 167 except (KeyError, TypeError): 165 sample['stamp'] = dat atime.datetime.min168 sample['stamp'] = datetime.datetime.min 166 169 167 170 def _sampleInterval(self): … … 228 231 class Sample(object): 229 232 230 """A single sample from daily sodar file data.233 """A single sample from raw daily sodar file data. 231 234 232 235 (A header and a body attribute.) … … 264 267 class Header(dict): 265 268 266 """A sodar data sample header.269 """A raw sodar data sample header. 267 270 268 271 (A dictionary of sample-wide parameters.) … … 292 295 class Body(list): 293 296 294 """A sodar data sample body.297 """A raw sodar data sample body. 295 298 296 299 (A list of dictionariess at each altitude.) … … 317 320 318 321 def __getitem__(self, index): 319 """Return altitude data by altitude string."""322 """Return raw altitude data by altitude string.""" 320 323 try: 321 324 return super(Body, self).__getitem__(index) … … 324 327 325 328 def _find(self, index): 326 """Find altitude data in Body."""329 """Find raw altitude data in Body.""" 327 330 for altitude in self: 328 331 try: … … 342 345 import urllib2 343 346 try: 344 dataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/data/nccoos/level0/dukeforest/sodar/store/2007-06/20070601.dat')345 dataString = dataHandle.read()347 rawDataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/data/nccoos/level0/dukeforest/sodar/store/2007-06/20070601.dat') 348 rawDataString = rawDataHandle.read() 346 349 except: 347 raise IOError("Failure to read test data")348 dataObject = Data(dataString)349 print dataObject['2007-06-01-09-15']['70']['SPEED']350 raise IOError("Failure to read raw test data") 351 rawDataObject = RawData(rawDataString) 352 print rawDataObject['2007-06-01-09-15']['70']['SPEED'] 350 353 351 354 if __name__ == "__main__":