Source code for easyvvuq.params_specification
"""Data structures to ensure consistency during serialization for databases.
"""
import logging
import cerberus
import json
import numpy
__copyright__ = """
Copyright 2018 Robin A. Richardson, David W. Wright
This file is part of EasyVVUQ
EasyVVUQ is free software: you can redistribute it and/or modify
it under the terms of the Lesser GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
EasyVVUQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Lesser GNU General Public License for more details.
You should have received a copy of the Lesser GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
__license__ = "LGPL"
logger = logging.getLogger(__name__)
[docs]class EasyVVUQValidator(cerberus.Validator):
def __init__(self, *args, **kwargs):
super(EasyVVUQValidator, self).__init__(*args, **kwargs)
# Add numpy.int64 as an acceptable 'integer' type
integer_type = cerberus.TypeDefinition('integer', (int, numpy.int64), ())
cerberus.Validator.types_mapping['integer'] = integer_type
# Add 'fixture' type (for now, it's expected just to be a string)
fixture_type = cerberus.TypeDefinition('fixture', (str), ())
cerberus.Validator.types_mapping['fixture'] = fixture_type
[docs]class ParamsSpecification:
def __init__(self, params, appname=None):
if not isinstance(params, dict):
msg = "params must be of type 'dict'"
logger.error(msg)
raise Exception(msg)
if not params:
msg = ("params must not be empty. At least one parameter "
"should be specified.")
logger.error(msg)
raise Exception(msg)
# Check each param has a dict as a value, and that dict has a "default" defined
for param_key, param_def in params.items():
if not isinstance(param_def, dict):
msg = f"Entry for param '{param_key}' must be a dictionary"
logger.error(msg)
raise Exception(msg)
if "default" not in param_def:
msg = (
f"Entry for param '{param_key}' must be a dictionary"
f"defining a 'default' value for this parameter."
)
logger.error(msg)
raise Exception(msg)
self.params_dict = params
self.appname = appname
# Create a validator for the schema defined by params_dict
self.cerberus_validator = EasyVVUQValidator(self.params_dict)
[docs] def process_run(self, new_run, verify=True):
# If necessary parameter names are missing, fill them in from the
# default values in params_info
for param in self.params_dict.keys():
if param not in new_run.keys():
default_val = self.params_dict[param]["default"]
new_run[param] = default_val
# Optionally verify that all params are known for this app, that the types are
# correct, params are within specified ranges etc. Uses cerberus for this.
if verify:
if not self.cerberus_validator.validate(new_run):
errors = self.cerberus_validator.errors
msg = (
f"Error when verifying the following new run:\n"
f"{new_run}\n"
f"Identified errors were:\n"
f"{errors}\n")
errors_list = [error[0] for error in self.cerberus_validator.errors.values()]
if 'unknown field' in errors_list:
msg += (
f"The allowed parameter names for this app are:\n"
f"{list(self.params_dict.keys())}")
logger.error(msg)
raise RuntimeError(msg)
return new_run
[docs] def serialize(self):
return json.dumps(self.params_dict)
[docs] @staticmethod
def deserialize(serialized_params):
return ParamsSpecification(json.loads(serialized_params))