vivarium-validation 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vivarium_validation-0.1.0/.readthedocs.yaml +37 -0
- vivarium_validation-0.1.0/CHANGELOG.rst +4 -0
- vivarium_validation-0.1.0/Jenkinsfile +40 -0
- vivarium_validation-0.1.0/LICENSE +27 -0
- vivarium_validation-0.1.0/Makefile +101 -0
- vivarium_validation-0.1.0/PKG-INFO +97 -0
- vivarium_validation-0.1.0/README.rst +38 -0
- vivarium_validation-0.1.0/docs/Makefile +22 -0
- vivarium_validation-0.1.0/docs/nitpick-exceptions +4 -0
- vivarium_validation-0.1.0/docs/source/_static/.gitkeep +0 -0
- vivarium_validation-0.1.0/docs/source/automated_v_and_v/index.rst +168 -0
- vivarium_validation-0.1.0/docs/source/conf.py +237 -0
- vivarium_validation-0.1.0/docs/source/index.rst +16 -0
- vivarium_validation-0.1.0/pyproject.toml +162 -0
- vivarium_validation-0.1.0/python_versions.json +1 -0
- vivarium_validation-0.1.0/setup.cfg +4 -0
- vivarium_validation-0.1.0/src/vivarium/validation/__init__.py +12 -0
- vivarium_validation-0.1.0/src/vivarium/validation/bundle.py +193 -0
- vivarium_validation-0.1.0/src/vivarium/validation/comparison.py +375 -0
- vivarium_validation-0.1.0/src/vivarium/validation/constants.py +51 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_loader.py +298 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/__init__.py +0 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/age_groups.py +710 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/calculations.py +284 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/data_schema.py +44 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/formatting.py +133 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/measures.py +594 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/rate_aggregation.py +30 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/report.py +117 -0
- vivarium_validation-0.1.0/src/vivarium/validation/data_transformation/utils.py +155 -0
- vivarium_validation-0.1.0/src/vivarium/validation/interface.py +955 -0
- vivarium_validation-0.1.0/src/vivarium/validation/py.typed +0 -0
- vivarium_validation-0.1.0/src/vivarium/validation/results.py +17 -0
- vivarium_validation-0.1.0/src/vivarium/validation/templates/report_template.html +919 -0
- vivarium_validation-0.1.0/src/vivarium/validation/visualization/__init__.py +0 -0
- vivarium_validation-0.1.0/src/vivarium/validation/visualization/dataframe_utils.py +120 -0
- vivarium_validation-0.1.0/src/vivarium/validation/visualization/plot_utils.py +321 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/PKG-INFO +97 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/SOURCES.txt +61 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/dependency_links.txt +1 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/requires.txt +43 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/scm_file_list.json +58 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/scm_version.json +8 -0
- vivarium_validation-0.1.0/src/vivarium_validation.egg-info/top_level.txt +1 -0
- vivarium_validation-0.1.0/tests/__init__.py +0 -0
- vivarium_validation-0.1.0/tests/automated_validation/conftest.py +779 -0
- vivarium_validation-0.1.0/tests/automated_validation/data_transformation/test_age_groups.py +634 -0
- vivarium_validation-0.1.0/tests/automated_validation/data_transformation/test_calculations.py +419 -0
- vivarium_validation-0.1.0/tests/automated_validation/data_transformation/test_data_schema.py +93 -0
- vivarium_validation-0.1.0/tests/automated_validation/data_transformation/test_formatting.py +279 -0
- vivarium_validation-0.1.0/tests/automated_validation/data_transformation/test_measures.py +710 -0
- vivarium_validation-0.1.0/tests/automated_validation/gbd_data/exposure.csv +17 -0
- vivarium_validation-0.1.0/tests/automated_validation/gbd_data/incidence.csv +13 -0
- vivarium_validation-0.1.0/tests/automated_validation/gbd_data/population_structure.csv +5 -0
- vivarium_validation-0.1.0/tests/automated_validation/gbd_data/relative_risks.csv +113 -0
- vivarium_validation-0.1.0/tests/automated_validation/gbd_data/remission_rate.csv +401 -0
- vivarium_validation-0.1.0/tests/automated_validation/test_comparison.py +405 -0
- vivarium_validation-0.1.0/tests/automated_validation/test_data_bundle.py +298 -0
- vivarium_validation-0.1.0/tests/automated_validation/test_data_loader.py +402 -0
- vivarium_validation-0.1.0/tests/automated_validation/test_interface.py +1115 -0
- vivarium_validation-0.1.0/tests/automated_validation/visualization/test_dataframe_utils.py +121 -0
- vivarium_validation-0.1.0/tests/automated_validation/visualization/test_plot_utils.py +450 -0
- vivarium_validation-0.1.0/tests/test_package.py +48 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Paths are repo-root-relative even when this file lives in a subdirectory,
|
|
2
|
+
# so the package path must be qualified with libs/validation/.
|
|
3
|
+
#
|
|
4
|
+
# This file is read by RTD only when the vivarium-validation RTD
|
|
5
|
+
# project's Admin > Advanced Settings > "Path for .readthedocs.yaml" points
|
|
6
|
+
# here. The root-level /.readthedocs.yaml is a placeholder used by the
|
|
7
|
+
# import wizard and ignored for any project that has overridden the path.
|
|
8
|
+
version: 2
|
|
9
|
+
|
|
10
|
+
sphinx:
|
|
11
|
+
configuration: libs/validation/docs/source/conf.py
|
|
12
|
+
fail_on_warning: true
|
|
13
|
+
|
|
14
|
+
build:
|
|
15
|
+
os: ubuntu-22.04
|
|
16
|
+
tools:
|
|
17
|
+
python: "3.13"
|
|
18
|
+
jobs:
|
|
19
|
+
post_checkout:
|
|
20
|
+
- git fetch --unshallow origin 2>/dev/null || git fetch origin main
|
|
21
|
+
# Cancel PR (external) builds that don't touch this lib (Exit 183 is RTD's
|
|
22
|
+
# signal to cancel the build immediately).
|
|
23
|
+
- |
|
|
24
|
+
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet "origin/main...HEAD" -- libs/validation/; then
|
|
25
|
+
echo "Skipping docs build: this PR changes nothing under libs/validation/."
|
|
26
|
+
exit 183
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
python:
|
|
30
|
+
install:
|
|
31
|
+
- method: pip
|
|
32
|
+
path: libs/validation
|
|
33
|
+
extra_requirements:
|
|
34
|
+
- docs
|
|
35
|
+
|
|
36
|
+
formats:
|
|
37
|
+
- pdf
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* This Jenkinsfile simply loads the `reusable_pipeline` pipeline from the
|
|
2
|
+
vivarium-build-utils package, which lives at ``libs/build-utils/`` inside the
|
|
3
|
+
``ihmeuw/vivarium-suite`` monorepo (https://github.com/ihmeuw/vivarium-suite).
|
|
4
|
+
|
|
5
|
+
vivarium-build-utils is loaded as a Jenkins shared library
|
|
6
|
+
(https://www.jenkins.io/doc/book/pipeline/shared-libraries/).
|
|
7
|
+
Jenkins shared library convention dictates that importable modules must be stored
|
|
8
|
+
in the 'vars' folder.
|
|
9
|
+
|
|
10
|
+
Jenkins shared libraries can be configured in the Jenkins UI:
|
|
11
|
+
* Manage Jenkins
|
|
12
|
+
* Configure System
|
|
13
|
+
* Global Pipeline Libraries section
|
|
14
|
+
* Library subsection
|
|
15
|
+
* Name: The Name for the lib
|
|
16
|
+
* Version: The branch you want to use. Throws an error
|
|
17
|
+
for nonexistent branches.
|
|
18
|
+
* Project Repository: Url to the shared lib
|
|
19
|
+
* Credentials: SSH key to access the repo
|
|
20
|
+
|
|
21
|
+
Note that updating the shared repo will take effect on the next pipeline invocation.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// Load the get_vbu_version function from build-utils/bootstrap/
|
|
25
|
+
// (the directory to load from is defined in the Jenkins shared library configuration)
|
|
26
|
+
@Library("get_vbu_version@main") _
|
|
27
|
+
|
|
28
|
+
// Load the full vivarium_build_utils library at the expected version
|
|
29
|
+
library("vivarium_build_utils@${get_vbu_version()}")
|
|
30
|
+
|
|
31
|
+
reusable_pipeline(
|
|
32
|
+
scheduled_branches: [
|
|
33
|
+
// Add additional branches for cron jobs below.
|
|
34
|
+
// Note: Newly added branches will require a manual trigger of the first build
|
|
35
|
+
// for subsequent scheduled builds to run.
|
|
36
|
+
"main",
|
|
37
|
+
],
|
|
38
|
+
skip_doc_build: true,
|
|
39
|
+
env_reqs: "ci_jenkins",
|
|
40
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright 2024 Institute for Health Metrics and Evaluation
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this list
|
|
9
|
+
of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this
|
|
12
|
+
list of conditions and the following disclaimer in the documentation and/or other
|
|
13
|
+
materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its contributors may
|
|
16
|
+
be used to endorse or promote products derived from this software without specific
|
|
17
|
+
prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY
|
|
20
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
21
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
22
|
+
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
24
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
25
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
27
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Check if we're running in Jenkins
|
|
2
|
+
ifdef JENKINS_URL
|
|
3
|
+
# Files are already in workspace from shared library
|
|
4
|
+
MAKE_INCLUDES := .
|
|
5
|
+
else
|
|
6
|
+
# For local dev, use the installed vivarium.build_utils package if it exists
|
|
7
|
+
# First, check if we can import vivarium.build_utils and assign 'yes' or 'no'.
|
|
8
|
+
# We do this by importing the package in python and redirecting stderr to the null device.
|
|
9
|
+
# If the import is successful (&&), it will print 'yes', otherwise (||) it will print 'no'.
|
|
10
|
+
VIVARIUM_BUILD_UTILS_AVAILABLE := $(shell python -c "import vivarium.build_utils" 2>/dev/null && echo "yes" || echo "no")
|
|
11
|
+
# If vivarium.build_utils is available, get the makefiles path or else set it to empty
|
|
12
|
+
ifeq ($(VIVARIUM_BUILD_UTILS_AVAILABLE),yes)
|
|
13
|
+
MAKE_INCLUDES := $(shell python -c "from vivarium.build_utils.resources import get_makefiles_path; print(get_makefiles_path())")
|
|
14
|
+
else
|
|
15
|
+
MAKE_INCLUDES :=
|
|
16
|
+
endif
|
|
17
|
+
endif
|
|
18
|
+
|
|
19
|
+
# Set the package name as the last part of this file's parent directory path
|
|
20
|
+
PACKAGE_NAME = $(notdir $(CURDIR))
|
|
21
|
+
|
|
22
|
+
ifneq ($(MAKE_INCLUDES),) # not empty
|
|
23
|
+
# Include makefiles from vivarium.build_utils
|
|
24
|
+
include $(MAKE_INCLUDES)/base.mk
|
|
25
|
+
include $(MAKE_INCLUDES)/test.mk
|
|
26
|
+
else # empty
|
|
27
|
+
# Use this help message (since the vivarium.build_utils version is not available)
|
|
28
|
+
help:
|
|
29
|
+
@echo
|
|
30
|
+
@echo "For Make's standard help, run 'make --help'."
|
|
31
|
+
@echo
|
|
32
|
+
@echo "Most of our Makefile targets are provided by the vivarium.build_utils"
|
|
33
|
+
@echo "package. To access them, you need to create a development environment first."
|
|
34
|
+
@echo
|
|
35
|
+
@echo "make build-env"
|
|
36
|
+
@echo
|
|
37
|
+
@echo "USAGE:"
|
|
38
|
+
@echo " make build-env [name=<environment name>] [py=<python version>] [artifactory_access=<yes|no>]"
|
|
39
|
+
@echo
|
|
40
|
+
@echo "ARGUMENTS:"
|
|
41
|
+
@echo " name [optional]"
|
|
42
|
+
@echo " Name of the conda environment to create (defaults to <PACKAGE_NAME>)"
|
|
43
|
+
@echo " py [optional]"
|
|
44
|
+
@echo " Python version (defaults to latest supported)"
|
|
45
|
+
@echo " artifactory_access [optional]"
|
|
46
|
+
@echo " Whether the build host can reach the IHME artifactory. Either 'yes'"
|
|
47
|
+
@echo " (default) or 'no'; use 'no' to build off-VPN without artifactory."
|
|
48
|
+
@echo
|
|
49
|
+
@echo "After creating the environment:"
|
|
50
|
+
@echo " 1. Activate it: 'conda activate <environment_name>'"
|
|
51
|
+
@echo " 2. Run 'make help' again to see all newly available targets"
|
|
52
|
+
@echo
|
|
53
|
+
endif
|
|
54
|
+
|
|
55
|
+
build-env: # Create a new environment with installed packages
|
|
56
|
+
# Validate arguments - exit if unsupported arguments are passed
|
|
57
|
+
@allowed="name py artifactory_access"; \
|
|
58
|
+
for arg in $(filter-out build-env,$(MAKECMDGOALS)) $(MAKEFLAGS); do \
|
|
59
|
+
case $$arg in \
|
|
60
|
+
*=*) \
|
|
61
|
+
arg_name=$${arg%%=*}; \
|
|
62
|
+
if ! echo " $$allowed " | grep -q " $$arg_name "; then \
|
|
63
|
+
allowed_list=$$(echo $$allowed | sed 's/ /, /g'); \
|
|
64
|
+
echo "Error: Invalid argument '$$arg_name'. Allowed arguments are: $$allowed_list" >&2; \
|
|
65
|
+
exit 1; \
|
|
66
|
+
fi \
|
|
67
|
+
;; \
|
|
68
|
+
esac; \
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
# Handle arguments and set defaults
|
|
72
|
+
# name
|
|
73
|
+
@$(eval name ?= $(PACKAGE_NAME))
|
|
74
|
+
# python version - validate if specified, else get default from json file
|
|
75
|
+
@supported_versions=$$(python -c "import json; print(' '.join(json.load(open('python_versions.json'))))" 2>/dev/null || echo ""); \
|
|
76
|
+
if [ -n "$(py)" ] && ! echo "$$supported_versions" | grep -q "$(py)"; then \
|
|
77
|
+
echo "Error: Python version '$(py)' is not supported. Available: $$(echo $$supported_versions | sed 's/ /, /g')" >&2; \
|
|
78
|
+
exit 1; \
|
|
79
|
+
fi
|
|
80
|
+
@$(eval py ?= $(shell python -c "import json; print(max(json.load(open('python_versions.json')), key=lambda x: tuple(map(int, x.split('.')))))"))
|
|
81
|
+
# artifactory_access
|
|
82
|
+
@$(eval artifactory_access ?= yes)
|
|
83
|
+
@case "$(artifactory_access)" in \
|
|
84
|
+
yes|no) ;; \
|
|
85
|
+
*) echo "Error: 'artifactory_access' must be 'yes' or 'no', got '$(artifactory_access)'" >&2; exit 1 ;; \
|
|
86
|
+
esac
|
|
87
|
+
|
|
88
|
+
conda create -n $(name) python=$(py) --yes
|
|
89
|
+
# Bootstrap vivarium.build_utils into the new environment
|
|
90
|
+
conda run -n $(name) pip install vivarium-build-utils
|
|
91
|
+
# artifactory_access=no passes an empty IHME_PYPI, which clears base.mk's EXTRA_INDEX_FLAGS
|
|
92
|
+
conda run -n $(name) make install $(if $(filter no,$(artifactory_access)),IHME_PYPI=)
|
|
93
|
+
|
|
94
|
+
@echo
|
|
95
|
+
@echo "Finished building environment"
|
|
96
|
+
@echo " name: $(name)"
|
|
97
|
+
@echo " python version: $(py)"
|
|
98
|
+
@echo
|
|
99
|
+
@echo "Don't forget to activate it with:"
|
|
100
|
+
@echo "conda activate $(name)"
|
|
101
|
+
@echo
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vivarium-validation
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automated verification and validation tooling for Vivarium simulations.
|
|
5
|
+
Author-email: The vivarium developers <vivarium.dev@gmail.com>
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Intended Audience :: Education
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
11
|
+
Classifier: Natural Language :: English
|
|
12
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
13
|
+
Classifier: Operating System :: POSIX
|
|
14
|
+
Classifier: Operating System :: POSIX :: BSD
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
+
Classifier: Topic :: Education
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/x-rst
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: vivarium-dependencies[loguru,numpy,pandas,pyyaml]
|
|
26
|
+
Requires-Dist: vivarium-build-utils<5.0.0,>=4.0.0
|
|
27
|
+
Requires-Dist: vivarium-config-tree
|
|
28
|
+
Requires-Dist: vivarium-fuzzy-checker
|
|
29
|
+
Provides-Extra: cluster
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: vivarium-dependencies[pytest]; extra == "test"
|
|
32
|
+
Requires-Dist: pytest-check; extra == "test"
|
|
33
|
+
Requires-Dist: vivarium-testing-utils; extra == "test"
|
|
34
|
+
Provides-Extra: docs
|
|
35
|
+
Requires-Dist: vivarium-dependencies[docutils,ipython,matplotlib,sphinx,sphinx-click]; extra == "docs"
|
|
36
|
+
Provides-Extra: interactive
|
|
37
|
+
Requires-Dist: vivarium-dependencies[interactive]; extra == "interactive"
|
|
38
|
+
Provides-Extra: pandera
|
|
39
|
+
Requires-Dist: pandera<0.23.0; extra == "pandera"
|
|
40
|
+
Provides-Extra: lint
|
|
41
|
+
Requires-Dist: vivarium-dependencies[lint]; extra == "lint"
|
|
42
|
+
Requires-Dist: vivarium-validation[pandera]; extra == "lint"
|
|
43
|
+
Provides-Extra: validation
|
|
44
|
+
Requires-Dist: vivarium-artifact; extra == "validation"
|
|
45
|
+
Requires-Dist: vivarium-gbd-mapping; extra == "validation"
|
|
46
|
+
Requires-Dist: vivarium-inputs<9.0.0,>=8.0.0; extra == "validation"
|
|
47
|
+
Requires-Dist: vivarium-validation[pandera]; extra == "validation"
|
|
48
|
+
Requires-Dist: pyarrow; extra == "validation"
|
|
49
|
+
Requires-Dist: seaborn; extra == "validation"
|
|
50
|
+
Requires-Dist: jinja2>=3.0.0; extra == "validation"
|
|
51
|
+
Requires-Dist: vivarium-dependencies[ipython,matplotlib]; extra == "validation"
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Requires-Dist: vivarium-validation[docs,interactive,lint,test,validation]; extra == "dev"
|
|
54
|
+
Provides-Extra: ci-github
|
|
55
|
+
Requires-Dist: vivarium-validation[docs,lint,test]; extra == "ci-github"
|
|
56
|
+
Provides-Extra: ci-jenkins
|
|
57
|
+
Requires-Dist: vivarium-validation[ci_github,cluster,validation]; extra == "ci-jenkins"
|
|
58
|
+
Dynamic: license-file
|
|
59
|
+
|
|
60
|
+
============================
|
|
61
|
+
Vivarium Validation
|
|
62
|
+
============================
|
|
63
|
+
|
|
64
|
+
.. image:: https://badge.fury.io/py/vivarium-validation.svg
|
|
65
|
+
:target: https://badge.fury.io/py/vivarium-validation
|
|
66
|
+
|
|
67
|
+
.. image:: https://readthedocs.org/projects/vivarium-validation/badge/?version=latest
|
|
68
|
+
:target: https://vivarium-validation.readthedocs.io/en/latest/?badge=latest
|
|
69
|
+
:alt: Documentation Status
|
|
70
|
+
|
|
71
|
+
This library provides tooling for automated verification and validation (V&V) of
|
|
72
|
+
Vivarium simulations, including data loading, measure comparison, and reporting.
|
|
73
|
+
|
|
74
|
+
**Supported Python versions: 3.10, 3.11**
|
|
75
|
+
|
|
76
|
+
You can install ``vivarium-validation`` from PyPI with pip:
|
|
77
|
+
|
|
78
|
+
.. code-block:: bash
|
|
79
|
+
|
|
80
|
+
pip install vivarium-validation
|
|
81
|
+
|
|
82
|
+
or build it from source by cloning the monorepo and installing this package:
|
|
83
|
+
|
|
84
|
+
.. code-block:: bash
|
|
85
|
+
|
|
86
|
+
git clone https://github.com/ihmeuw/vivarium-suite.git
|
|
87
|
+
cd vivarium-suite
|
|
88
|
+
pip install libs/validation
|
|
89
|
+
|
|
90
|
+
Note that the validation feature depends on ``vivarium-inputs``, which is only
|
|
91
|
+
available from the IHME artifactory.
|
|
92
|
+
|
|
93
|
+
For broader monorepo development setup, see the monorepo README at
|
|
94
|
+
https://github.com/ihmeuw/vivarium-suite.
|
|
95
|
+
|
|
96
|
+
`Check out the docs! <https://vivarium-validation.readthedocs.io/en/latest/>`_
|
|
97
|
+
-----------------------------------------------------------------------------------
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
============================
|
|
2
|
+
Vivarium Validation
|
|
3
|
+
============================
|
|
4
|
+
|
|
5
|
+
.. image:: https://badge.fury.io/py/vivarium-validation.svg
|
|
6
|
+
:target: https://badge.fury.io/py/vivarium-validation
|
|
7
|
+
|
|
8
|
+
.. image:: https://readthedocs.org/projects/vivarium-validation/badge/?version=latest
|
|
9
|
+
:target: https://vivarium-validation.readthedocs.io/en/latest/?badge=latest
|
|
10
|
+
:alt: Documentation Status
|
|
11
|
+
|
|
12
|
+
This library provides tooling for automated verification and validation (V&V) of
|
|
13
|
+
Vivarium simulations, including data loading, measure comparison, and reporting.
|
|
14
|
+
|
|
15
|
+
**Supported Python versions: 3.10, 3.11**
|
|
16
|
+
|
|
17
|
+
You can install ``vivarium-validation`` from PyPI with pip:
|
|
18
|
+
|
|
19
|
+
.. code-block:: bash
|
|
20
|
+
|
|
21
|
+
pip install vivarium-validation
|
|
22
|
+
|
|
23
|
+
or build it from source by cloning the monorepo and installing this package:
|
|
24
|
+
|
|
25
|
+
.. code-block:: bash
|
|
26
|
+
|
|
27
|
+
git clone https://github.com/ihmeuw/vivarium-suite.git
|
|
28
|
+
cd vivarium-suite
|
|
29
|
+
pip install libs/validation
|
|
30
|
+
|
|
31
|
+
Note that the validation feature depends on ``vivarium-inputs``, which is only
|
|
32
|
+
available from the IHME artifactory.
|
|
33
|
+
|
|
34
|
+
For broader monorepo development setup, see the monorepo README at
|
|
35
|
+
https://github.com/ihmeuw/vivarium-suite.
|
|
36
|
+
|
|
37
|
+
`Check out the docs! <https://vivarium-validation.readthedocs.io/en/latest/>`_
|
|
38
|
+
-----------------------------------------------------------------------------------
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
|
|
3
|
+
# You can set these variables from the command line.
|
|
4
|
+
SPHINXOPTS =
|
|
5
|
+
SPHINXBUILD = sphinx-build
|
|
6
|
+
SPHINXPROJ = vivarium.validation
|
|
7
|
+
SOURCEDIR = source
|
|
8
|
+
BUILDDIR = build
|
|
9
|
+
|
|
10
|
+
# Put it first so that "make" without argument is like "make help".
|
|
11
|
+
help:
|
|
12
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
13
|
+
|
|
14
|
+
.PHONY: help Makefile
|
|
15
|
+
|
|
16
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
17
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
18
|
+
%: Makefile
|
|
19
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
20
|
+
|
|
21
|
+
clean:
|
|
22
|
+
rm -rf build/*
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Add "py:class <target>" entries here for cross-references that Sphinx's
|
|
2
|
+
# nitpicky mode cannot resolve. Empty for now: these docs are narrative-only,
|
|
3
|
+
# so no autodoc-generated type references need suppressing. Populate this when
|
|
4
|
+
# the package starts auto-documenting its API.
|
|
File without changes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
..
|
|
2
|
+
Section title decorators for this document:
|
|
3
|
+
|
|
4
|
+
==============
|
|
5
|
+
Document Title
|
|
6
|
+
==============
|
|
7
|
+
Section Level 1
|
|
8
|
+
---------------
|
|
9
|
+
Section Level 2
|
|
10
|
+
+++++++++++++++
|
|
11
|
+
Section Level 3
|
|
12
|
+
~~~~~~~~~~~~~~~
|
|
13
|
+
Section Level 4
|
|
14
|
+
^^^^^^^^^^^^^^^
|
|
15
|
+
Section Level 5
|
|
16
|
+
'''''''''''''''
|
|
17
|
+
|
|
18
|
+
The depth of each section level is determined by the order in which each
|
|
19
|
+
decorator is encountered below. If you need an even deeper section level, just
|
|
20
|
+
choose a new decorator symbol from the list here:
|
|
21
|
+
https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#sections
|
|
22
|
+
And then add it to the list of decorators above.
|
|
23
|
+
|
|
24
|
+
.. _automated_v_and_v:
|
|
25
|
+
|
|
26
|
+
.. role:: underline
|
|
27
|
+
:class: underline
|
|
28
|
+
|
|
29
|
+
=========================================================
|
|
30
|
+
Automated verification and validation (V&V)
|
|
31
|
+
=========================================================
|
|
32
|
+
|
|
33
|
+
.. contents::
|
|
34
|
+
:local:
|
|
35
|
+
|
|
36
|
+
Background/Motivation
|
|
37
|
+
---------------------
|
|
38
|
+
|
|
39
|
+
Our team uses :ref:`a process called verification and validation (V&V) <vivarium_best_practices_results_processing>`
|
|
40
|
+
to ensure that our models are behaving as we expect.
|
|
41
|
+
:ref:`The current process for V&V <vivarium_v_and_v_process>`
|
|
42
|
+
works well but can be quite labor intensive.
|
|
43
|
+
Due to the long runtime of simulations and the number of people involved,
|
|
44
|
+
each V&V cycle generally takes *at least* one day, which makes it difficult to find and fix issues quickly.
|
|
45
|
+
|
|
46
|
+
Automating more of the V&V process would help us catch issues faster and with less work.
|
|
47
|
+
We can **incrementally** automate V&V by building tools to do the repetitive parts,
|
|
48
|
+
and over time stitching these tools together to make the process more and more automatic.
|
|
49
|
+
|
|
50
|
+
As we develop the tools, there are also some process questions to work out about this transformation:
|
|
51
|
+
|
|
52
|
+
* Who investigates the cause of automated V&V failures?
|
|
53
|
+
If the answer is "it depends on the failure," how do we route the right failures to the right people?
|
|
54
|
+
* How and when do we run automated V&V?
|
|
55
|
+
|
|
56
|
+
Automated V&V comparisons
|
|
57
|
+
-------------------------
|
|
58
|
+
|
|
59
|
+
Automated V&V plots
|
|
60
|
+
-------------------
|
|
61
|
+
|
|
62
|
+
Automated V&V checks
|
|
63
|
+
--------------------
|
|
64
|
+
|
|
65
|
+
Automating V&V checks refers to replacing the manual process of looking at graphs (to check that simulation
|
|
66
|
+
results are close enough to known targets) with an automatic equivalent.
|
|
67
|
+
This requires transforming the manual process into something that can be executed by a computer
|
|
68
|
+
and generate an unambiguous verdict on whether or not there is an issue that needs to be investigated.
|
|
69
|
+
|
|
70
|
+
.. note::
|
|
71
|
+
In the future, we could explore having a result more complex than just "investigate" or
|
|
72
|
+
"don't investigate," such as multiple levels of priority for potential issues to be reviewed by a human.
|
|
73
|
+
For now, we stick to a binary result.
|
|
74
|
+
|
|
75
|
+
For checks where the expectation is that the simulation result should exactly match a target or respect
|
|
76
|
+
a constraint (e.g. 0% coverage of an intervention among those not eligible) it is fairly straightforward
|
|
77
|
+
to use a Python :code:`assert` statement in addition to, or instead of, a plot.
|
|
78
|
+
This approach can be used in notebooks or in automated tests run with :code:`pytest`.
|
|
79
|
+
|
|
80
|
+
The statistical methodology behind fuzzy checking lives in the
|
|
81
|
+
`vivarium-fuzzy-checker documentation
|
|
82
|
+
<https://vivarium-fuzzy-checker.readthedocs.io/en/latest/fuzzy_checking.html>`_.
|
|
83
|
+
|
|
84
|
+
Automated V&V runs
|
|
85
|
+
------------------
|
|
86
|
+
|
|
87
|
+
.. todo::
|
|
88
|
+
Due to technical limitations in the :code:`pytest` tool, integration tests currently must select a simulation
|
|
89
|
+
"size" (population, draws, time span), run it completely, and then check the results.
|
|
90
|
+
It would likely lead to a much quicker iteration cycle if we ran a small simulation, checked the results,
|
|
91
|
+
then added more population/draws/time and checked the results again, etc, similar to how we expand runs with
|
|
92
|
+
:code:`psimulate`.
|
|
93
|
+
This way, egregious bugs could be caught very quickly.
|
|
94
|
+
|
|
95
|
+
History/case studies
|
|
96
|
+
--------------------
|
|
97
|
+
|
|
98
|
+
Probabilistic record linkage (PRL) synthetic population simulation
|
|
99
|
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
100
|
+
|
|
101
|
+
The :ref:`PRL synthetic population simulation <vivarium_census_prl_synth_data>`
|
|
102
|
+
used an atypical V&V process,
|
|
103
|
+
and was used as a testbed for some of these automation ideas.
|
|
104
|
+
|
|
105
|
+
Rather than researchers performing V&V in notebooks, V&V for this simulation
|
|
106
|
+
was entirely done via `integration tests <https://en.wikipedia.org/wiki/Integration_testing>`_,
|
|
107
|
+
which ran the simulation for a given number of time steps and checked certain conditions.
|
|
108
|
+
When the model exhibited unexpected behavior,
|
|
109
|
+
the tests failed.
|
|
110
|
+
For example, there was a test that checked that each non-GQ household in the simulation had exactly one
|
|
111
|
+
living reference person, a condition which should always be true.
|
|
112
|
+
|
|
113
|
+
These tests have access to intermediate simulation states, not only simulation outputs, and can check
|
|
114
|
+
conditions at each time step.
|
|
115
|
+
Therefore, they are quite similar to :ref:`interactive simulation V&V <vivarium_interactive_simulation>` we have done in the past.
|
|
116
|
+
Because not much changes over time in the PRL simulation (there is nothing like an intervention scale-up),
|
|
117
|
+
we test only the first 10 time steps.
|
|
118
|
+
|
|
119
|
+
Test coverage was not complete; notably, none of the observers had integration tests.
|
|
120
|
+
The test suite can be found `in the simulation repository's integration tests directory <https://github.com/ihmeuw/vivarium_census_prl_synth_pop/tree/main/tests/integration>`_.
|
|
121
|
+
The tests all ran in just a few minutes, so engineers were expected to run them before merging any pull request,
|
|
122
|
+
though we did not have continuous integration (CI).
|
|
123
|
+
|
|
124
|
+
These integration tests were the first place we used fuzzy checking,
|
|
125
|
+
specifically for rates of simulant migration into and within the US (fuzzy checking was not implemented for emigration).
|
|
126
|
+
These rates are stratified by a number
|
|
127
|
+
of demographic factors, and some of these factors (e.g. race/ethnicity) have highly imbalanced categories.
|
|
128
|
+
Therefore, verifying rates within each demographic combination would require a large population size.
|
|
129
|
+
|
|
130
|
+
Instead, the integration tests do a combination of verification and validation by checking
|
|
131
|
+
**population-level** migration rates against the corresponding rates in our data source (the American Communities Survey).
|
|
132
|
+
These should be similar, since the simulation's rates are calculated using this data source,
|
|
133
|
+
and the demographic composition of the population is initialized from the same data.
|
|
134
|
+
However, simulation rates can drift slightly from population-level rates in the data, without being indicative of a bug,
|
|
135
|
+
due to demographic change over the course of the simulation.
|
|
136
|
+
All these checks were implemented as proportion checks on the proportion of simulants experiencing the vent.
|
|
137
|
+
Checking at the population level makes use of the binomial approximation to the Poisson binomial,
|
|
138
|
+
as described in the proportions section of the `vivarium-fuzzy-checker documentation
|
|
139
|
+
<https://vivarium-fuzzy-checker.readthedocs.io/en/latest/fuzzy_checking.html>`_.
|
|
140
|
+
|
|
141
|
+
For rates of migration within the US, we check the migration rate at each time step, and overall.
|
|
142
|
+
We set the target range for each time step by assuming with 95% certainty that the drift will be at most 1% per time step that has elapsed
|
|
143
|
+
since initialization.
|
|
144
|
+
Overall, we set a UI of +/-10% the ACS value.
|
|
145
|
+
|
|
146
|
+
Migration into the US is a bit different; it is not an event with a rate of occurrence among
|
|
147
|
+
an at-risk population.
|
|
148
|
+
The only stochastic part of determining the number of immigration events is the
|
|
149
|
+
:ref:`"stochastic rounding" used <census_prl_international_immigration>`.
|
|
150
|
+
We check this rounding as a set of Bernoulli trials, one per time step:
|
|
151
|
+
whether to round up or down.
|
|
152
|
+
|
|
153
|
+
The PRL integration tests are run very frequently by the software engineering team.
|
|
154
|
+
Due to how frequently they are run and the difficulty of debugging a failed test
|
|
155
|
+
(perhaps requiring researcher input in some cases),
|
|
156
|
+
it is important for these tests to be highly **specific**;
|
|
157
|
+
they should very rarely fail by chance.
|
|
158
|
+
That is the main reason we have set the default Bayes factor cutoff to 100, commonly called "decisive,"
|
|
159
|
+
in *addition* to the generally conservative approximations described above.
|
|
160
|
+
In practice, by manually introducing bugs in the simulation, we have found that even with this very conservative approach, automated V&V is quite sensitive.
|
|
161
|
+
|
|
162
|
+
pseudopeople noise tests
|
|
163
|
+
++++++++++++++++++++++++
|
|
164
|
+
|
|
165
|
+
Our `pseudopeople <https://pseudopeople.readthedocs.io/>`_ package applies random noise to data derived from the PRL synthetic population simulation.
|
|
166
|
+
We used fuzzy checking in both the `unit <https://github.com/ihmeuw/pseudopeople/tree/main/tests/unit>`_ and `integration <https://github.com/ihmeuw/pseudopeople/tree/main/tests/integration>`_ tests of pseudopeople to check that
|
|
167
|
+
noise was happening at the expected rates.
|
|
168
|
+
We did not have any false alarms, and fuzzy checking caught some `very subtle bugs <https://github.com/ihmeuw/pseudopeople/pull/373>`_.
|