""" Module to handle Scintec sodar .mnd files. >>> from sodar.scintec import maindata """ __author__ = 'Chris Calloway' __email__ = 'cbc@chriscalloway.org' __copyright__ = 'Copyright 2009 UNC-CH Department of Marine Science' __license__ = 'GPL2' class MainData(list): """ Contain data from a Scintec sodar .mnd file. Parse a known good .mnd file: >>> main_data = MainData(good_mnd) Parse the format header: >>> len(main_data._format_header) 4 >>> main_data._format_header[0] 'FORMAT-1' Parse the file header after the format header: >>> len(main_data._file_header_body) 26 >>> main_data._file_header_body[1] '# file information' Parse the profile data: >>> len(main_data) 48 Parse the first profile: >>> len(main_data[0]) 39 >>> main_data[0].timestamp '2009-11-17 00:30:00 00:30:00' >>> main_data[0].variables == ['z', 'speed', 'dir', 'W', ... 'sigW', 'bck', 'error'] True >>> main_data[0][0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', ... 'error':'0'} True >>> main_data[0][-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', ... 'error':'0'} True Parse the last profile: >>> len(main_data[-1]) 39 >>> main_data[-1].timestamp '2009-11-18 00:00:00 00:30:00' >>> main_data[-1].variables == ['z', 'speed', 'dir', 'W', ... 'sigW', 'bck', 'error'] True >>> main_data[-1][0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.32', 'sigW':'99.99', 'bck':'9.99E+37', ... 'error':'0'} True >>> main_data[-1][-1] == {'z':'200', 'speed':'15.05', 'dir':'71.8', ... 'W':'-0.19', 'sigW':'0.53', 'bck':'9.99E+37', ... 'error':'0'} True """ def __init__(self, mnd, *args): """ Parse main daily Scintec sodar .mnd file. MainData(mnd[,file_name[,file_path]]) -> Where: mnd is a str object containing the complete contents read from a Scintec .mnd daily sodar file including all line endings, file_name is an optional str object representing a file name for a file which contains the referenced .mnd daily sodar file, file_path is an optional str object representing the path to file_name. Parse a known good .mnd file: >>> main_data = MainData(good_mnd) >>> main_data = MainData(good_mnd,good_name) >>> main_data.file_name == good_name True >>> main_data = MainData(good_mnd,good_name,good_path) >>> main_data.file_name == good_name True >>> main_data.file_path == good_path True """ super(MainData, self).__init__() self.file_name = '' self.file_path = '' try: self.file_name = str(args[0]) self.file_path = str(args[1]) except IndexError: pass self._blocks = [self._block.strip() for self._block in mnd.split('\n\n') if self._block.strip()] self._format_header = [self._line.strip() for self._line in self._blocks[0].split('\n') if self._line.strip()] self._file_header_body = [self._line.strip() for self._line in self._blocks[1].split('\n') if self._line.strip()] self.extend([Profile([self._line.strip() for self._line in self._block.split('\n') if self._line.strip()]) for self._block in self._blocks[2:]]) del self._blocks, self._block, self._line class Profile(list): """ Contain data for single profile from a Scintec sodar .mnd file. Parse a known good profile block: >>> profile = Profile(good_profile) >>> profile.timestamp '2009-11-17 00:30:00 00:30:00' >>> profile.variables == ['z', 'speed', 'dir', 'W', ... 'sigW', 'bck', 'error'] True >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', ... 'error':'0'} True >>> profile[-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', ... 'error':'0'} True """ def __init__(self, profile_block): """ Parse a profile block from a main daily Scintec sodar .mnd file. Profile(profile_data) -> Where: profile_block is a list of str objects containing all the lines from a single profile in a Scintec .mnd daily sodar file. Parse a known good profile block: >>> profile = Profile(good_profile) >>> profile.timestamp '2009-11-17 00:30:00 00:30:00' >>> profile.variables == ['z', 'speed', 'dir', 'W', ... 'sigW', 'bck', 'error'] True >>> profile[0] == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', ... 'error':'0'} True >>> profile[-1] == {'z':'200', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.07', 'sigW':'99.99', 'bck':'9.99E+37', ... 'error':'0'} True """ super(Profile, self).__init__() self.timestamp = profile_block[0] self.variables = profile_block[1].split()[1:] self.extend([Observation(observation.split(),self.variables) for observation in profile_block[2:]]) class Observation(dict): """ Contain data for single observation from a Scintec sodar .mnd files. Parse a known good observation: >>> observation = Observation(good_observation,good_variables) >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', ... 'error':'0'} True """ def __init__(self,data,variables): """ Parse an observation from a main daily Scintec sodar .mnd file. Observation(data,variables) -> Where: data is a list of str object representing variable values, variables is a list of str objects representing variable labels. Parse a known good observation: >>> observation = Observation(good_observation,good_variables) >>> observation == {'z':'10', 'speed':'99.99', 'dir':'999.9', ... 'W':'-0.05', 'sigW':'0.40', 'bck':'5.46E+03', ... 'error':'0'} True """ super(Observation, self).__init__() self.update(dict(zip(variables,data))) def _test(): """ Run module tests in script mode. >>> from sodar.scintec.maindata import _test """ import doctest from sodar.tests import suite mnd_path,mnd_file,mnd,profile,variables,observation = \ suite.setUpGoodMndData() doctest.testmod(extraglobs=dict(good_mnd=mnd, good_name=mnd_file, good_path=mnd_path, good_profile=profile, good_variables=variables, good_observation=observation), optionflags=doctest.NORMALIZE_WHITESPACE) if __name__ == "__main__": _test()