Created
February 5, 2016 23:52
-
-
Save jhamman/8bee9f287ccde4200666 to your computer and use it in GitHub Desktop.
Parsing VIC global parameter files in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import warnings | |
| from collections import namedtuple, OrderedDict | |
| class Forcing(object): | |
| def __init__(self, *args, version='4'): | |
| # initialize variables | |
| self.name = None | |
| self.path = None | |
| self.types = [] | |
| if version.startswith('4') or version == '5.0 classic': | |
| self.format = None | |
| self.endian = None | |
| self.year = None | |
| self.month = None | |
| self.day = None | |
| if version.startswith('5'): | |
| self.steps_per_day = None | |
| else: | |
| self.dt = None | |
| if args: | |
| self.update(*args) | |
| def update(self, *args): | |
| for arg in args: | |
| if arg[0].startswith('FORCING'): | |
| self.name = arg[0] | |
| self.path = arg[1] | |
| elif arg[0] == 'FORCE_FORMAT': | |
| self.format = arg[1] | |
| if self.format == 'BINARY': | |
| self._force_type = namedtuple('force_type_binary', ('type', 'sign', 'mult')) | |
| self._type_slice = slice(1, 4) | |
| elif self.format == 'ASCII': | |
| self._force_type = namedtuple('force_type_ascii', ('type')) | |
| self._type_slice = slice(1, 2) | |
| else: | |
| raise ValueError('Unknown FORCE_FORMAT: %s' % self.format) | |
| elif arg[0] == 'FORCE_ENDIAN': | |
| if self.format == 'BINARY': | |
| self.endian = arg[1] | |
| else: | |
| warnings.warn('Ignoring FORCE_ENDIAN option since FORCE_FORMAT != BINARY') | |
| elif arg[0] == 'FORCE_TYPE': | |
| if self.format == 'BINARY': | |
| self.types.append(self._force_type(arg[self._type_slice])) | |
| if self.format == 'BINARY': | |
| self.types.append(self._force_type(arg[self._type_slice])) | |
| elif arg[0] == 'FORCE_DT': | |
| self.dt = arg[1] | |
| elif arg[0] == 'FORCE_STEPS_PER_DAY': | |
| self.steps_per_day = arg[1] | |
| elif arg[0] == 'FORCEYEAR': | |
| self.year = arg[1] | |
| elif arg[0] == 'FORCEMONTH': | |
| self.month = arg[1] | |
| elif arg[0] == 'FORCEDAY': | |
| self.day = arg[1] | |
| else: | |
| raise ValueError('Unknown forcing argument: %s' % arg) | |
| def __repr__(self): | |
| return 'VIC Forcing Configuration: %s' % self.name | |
| def global_param_options(fname, version='4'): | |
| options = OrderedDict() | |
| with open(fname, 'r') as f: | |
| lines = f.readlines() | |
| for line in lines: | |
| line = line.strip() # remove extra whitespace around lines | |
| if line.startswith('#') or not len(line): | |
| # line is a comment or is empty | |
| continue | |
| # strip trailing comments | |
| if '#' in line: | |
| line = line.split(sep='#', maxsplit=1)[0] | |
| # split the key/value combination | |
| ops = line.split() | |
| key = ops[0] | |
| values = ops[1:] | |
| if key.startswith('FORCING'): | |
| forcing_name = key | |
| options[key] = Forcing(ops, version='4') | |
| elif not any(key.startswith(s) for s in ['FORCE', 'OUTVAR']): | |
| options[key] = values | |
| return options | |
| # Usage example: | |
| # opts = global_param_options('./samples/global.param.sample.classic.txt', version='5.0 classic') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment