Skip to content

Instantly share code, notes, and snippets.

@jhamman
Created February 5, 2016 23:52
Show Gist options
  • Select an option

  • Save jhamman/8bee9f287ccde4200666 to your computer and use it in GitHub Desktop.

Select an option

Save jhamman/8bee9f287ccde4200666 to your computer and use it in GitHub Desktop.
Parsing VIC global parameter files in Python
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