Index: sodar/trunk/sodar/rawData.py =================================================================== --- sodar/trunk/sodar/data.py (revision 70) +++ sodar/trunk/sodar/rawData.py (revision 71) @@ -1,36 +1,39 @@ #!/usr/bin/python """ -Classes to handle sodar data samples. - -Sodar data samples are collected into daily files. Each sample consists of a +Classes to handle raw sodar data samples. + +Raw sodar data samples are collected into daily files. Each sample consists of a header followed by an observation for each height. -The daily file is split into a list (modeled by the class Data) of samples -(modeled by the class Sample) in chronological order. A Data object is +The daily file is split into a list (modeled by the class RawData) of samples +(modeled by the class Sample) in chronological order. A RawData object is initialized with a string representing the daily file data: - dataHandle = open('20070601.dat') - dataString = data.read() - dataObject = Data(dataString) + rawDataHandle = open('20070601.dat') + rawDataString = rawDataHandle.read() + rawDataObject = RawData(rawDataString) Each Sample object has attributes for a Header and Body object. The Samples -within a Data object may also be accessed by time using a string of the format -YYYY-MM-DD-HH-MM as in index on the Data object to return the first matching -Sample in the Data object: - - dataObject[0] # the first Sample object of the day - dataObject['2007-06-01-09-15'] # the Sample object for 9:15am - dataObject[15].header # the Header object of the 16th Sample - dataObject['2007-06-01-09-15'].body # the Body object for 9:15am +within a RawData object may also be accessed by time using a string of the format +YYYY-MM-DD-HH-MM as in index on the RawData object to return the first matching +Sample in the RawData object: + + rawDataObject[0] # the first Sample object of the day + rawDataObject['2007-06-01-09-15'] # the Sample object for 9:15am + rawDataObject[15].header # the Header object of the 16th Sample + rawDataObject['2007-06-01-09-15'].body # the Body object for 9:15am Header objects act as dictionaries. Access each sample-wide parameter of interest using the header parameter name as a keyword on the Header object: - dataObject[15].header['VAL2'] # the number of validations for beam 2 - dataObject['2007-06-01-09-15'].header['SPU3'] # normalized false signal - # probability on beam 3 - dataObject[0].header['SNR1'] # signal to noise on beam 1 + rawDataObject[15].header['VAL2'] # the number of validations for beam 2 + rawDataObject['2007-06-01-09-15'].header['SPU3'] # normalized false signal + # probability on beam 3 + rawDataObject[0].header['SNR1'] # signal to noise on beam 1 Consult your Sodar documentation for a complete list of header parameters. +Different sodar models have different sets of header parameters. This model +seeks to be model agnostic, and parses the header parameter names from the +raw data itself. Body objects act as lists of dictionaries. The dictionaries access @@ -39,16 +42,16 @@ an altitude string: - dataObject[15].body[0] # the data for the lowest altitude, 16th sample - dataObject['2007-06-01-09-15'].body['70'] # the data for 70 meters - dataObject[15].body[0]['SPEED'] # wind speed at lowest altitude - dataObject['2007-06-01-09-15'].body['70']['DIR'] # wind direction - # at 70 meters + rawDataObject[15].body[0] # the data for the lowest altitude, 16th sample + rawDataObject['2007-06-01-09-15'].body['70'] # the data for 70 meters + rawDataObject[15].body[0]['SPEED'] # wind speed at lowest altitude + rawDataObject['2007-06-01-09-15'].body['70']['DIR'] # wind direction + # at 70 meters The body attribute of a Sample object may also be indexed directly on a Sample object for the most convenient semantics: - dataObject[15][0]['SPEED'] # wind speed at lowest altitude, 16th sample - dataObject['2007-06-01-09-15']['70']['DIR'] # wind direction, - # 70 meters, 9:15am + rawDataObject[15][0]['SPEED'] # wind speed at lowest altitude, 16th sample + rawDataObject['2007-06-01-09-15']['70']['DIR'] # wind direction, + # 70 meters, 9:15am """ @@ -62,7 +65,7 @@ import datetime -class Data(list): - - """Daily sodar file data. +class RawData(list): + + """Raw daily sodar file data. (A chronologically ordered list of samples.) @@ -71,5 +74,5 @@ def __init__(self, data): """Divide daily string into list of Samples separated by $.""" - super(Data, self).__init__() + super(RawData, self).__init__() self.extend([Sample(sample) for sample in @@ -81,12 +84,12 @@ """Allow sample retrieval by Sample time in header.""" try: - return super(Data,self).__getitem__(index) + return super(RawData,self).__getitem__(index) except TypeError: return self._find(index) def _find(self, index): - """Find Sample in Data + """Find Sample in RawData. - where sample time of form YYYY-MM-DD-HH-MM. + Where sample time of form YYYY-MM-DD-HH-MM. """ @@ -94,7 +97,7 @@ year,month,day,hour,minute = index.split('-') except ValueError: - raise ValueError('Data index by date must be "YYYY-MM-DD-HH-MM"') + raise ValueError('RawData index by date must be "YYYY-MM-DD-HH-MM"') except AttributeError: - raise AttributeError('Data index by date must be "YYYY-MM-DD-HH-MM"') + raise AttributeError('RawData index by date must be "YYYY-MM-DD-HH-MM"') for sample in self: try: @@ -107,5 +110,5 @@ except TypeError: # sample.header may not exist continue - raise IndexError('Data index out of range') + raise IndexError('RawData index out of range') def _normalize(self): @@ -163,5 +166,5 @@ header['MIN']) except (KeyError, TypeError): - sample['stamp'] = datatime.datetime.min + sample['stamp'] = datetime.datetime.min def _sampleInterval(self): @@ -228,5 +231,5 @@ class Sample(object): - """A single sample from daily sodar file data. + """A single sample from raw daily sodar file data. (A header and a body attribute.) @@ -264,5 +267,5 @@ class Header(dict): - """A sodar data sample header. + """A raw sodar data sample header. (A dictionary of sample-wide parameters.) @@ -292,5 +295,5 @@ class Body(list): - """A sodar data sample body. + """A raw sodar data sample body. (A list of dictionariess at each altitude.) @@ -317,5 +320,5 @@ def __getitem__(self, index): - """Return altitude data by altitude string.""" + """Return raw altitude data by altitude string.""" try: return super(Body, self).__getitem__(index) @@ -324,5 +327,5 @@ def _find(self, index): - """Find altitude data in Body.""" + """Find raw altitude data in Body.""" for altitude in self: try: @@ -342,10 +345,10 @@ import urllib2 try: - dataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/data/nccoos/level0/dukeforest/sodar/store/2007-06/20070601.dat') - dataString = dataHandle.read() + rawDataHandle = urllib2.urlopen('http://nemo.isis.unc.edu/data/nccoos/level0/dukeforest/sodar/store/2007-06/20070601.dat') + rawDataString = rawDataHandle.read() except: - raise IOError("Failure to read test data") - dataObject = Data(dataString) - print dataObject['2007-06-01-09-15']['70']['SPEED'] + raise IOError("Failure to read raw test data") + rawDataObject = RawData(rawDataString) + print rawDataObject['2007-06-01-09-15']['70']['SPEED'] if __name__ == "__main__":