emodpy 1.35.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.
- emodpy-1.35.0/LICENSE +21 -0
- emodpy-1.35.0/MANIFEST.in +3 -0
- emodpy-1.35.0/PKG-INFO +160 -0
- emodpy-1.35.0/README.md +122 -0
- emodpy-1.35.0/emodpy/__init__.py +1 -0
- emodpy-1.35.0/emodpy/analyzers/__init__.py +0 -0
- emodpy-1.35.0/emodpy/analyzers/adult_vectors_analyzer.py +38 -0
- emodpy-1.35.0/emodpy/analyzers/population_analyzer.py +52 -0
- emodpy-1.35.0/emodpy/analyzers/timeseries_analyzer.py +117 -0
- emodpy-1.35.0/emodpy/collections_utils.py +92 -0
- emodpy-1.35.0/emodpy/defaults/__init__.py +2 -0
- emodpy-1.35.0/emodpy/defaults/emod_sir.py +195 -0
- emodpy-1.35.0/emodpy/defaults/ep4/__init__.py +0 -0
- emodpy-1.35.0/emodpy/defaults/ep4/dtk_in_process.py +20 -0
- emodpy-1.35.0/emodpy/defaults/ep4/dtk_post_process.py +20 -0
- emodpy-1.35.0/emodpy/defaults/ep4/dtk_pre_process.py +55 -0
- emodpy-1.35.0/emodpy/defaults/iemod_default.py +20 -0
- emodpy-1.35.0/emodpy/emod_campaign.py +118 -0
- emodpy-1.35.0/emodpy/emod_file.py +399 -0
- emodpy-1.35.0/emodpy/emod_task.py +891 -0
- emodpy-1.35.0/emodpy/generic/__init__.py +0 -0
- emodpy-1.35.0/emodpy/generic/serialization.py +64 -0
- emodpy-1.35.0/emodpy/interventions/__init__.py +2 -0
- emodpy-1.35.0/emodpy/interventions/emod_empty_campaign.py +12 -0
- emodpy-1.35.0/emodpy/reporters/__init__.py +1 -0
- emodpy-1.35.0/emodpy/reporters/base.py +258 -0
- emodpy-1.35.0/emodpy/reporters/builtin.py +22 -0
- emodpy-1.35.0/emodpy/reporters/custom.py +104 -0
- emodpy-1.35.0/emodpy/utils.py +11 -0
- emodpy-1.35.0/emodpy.egg-info/PKG-INFO +160 -0
- emodpy-1.35.0/emodpy.egg-info/SOURCES.txt +51 -0
- emodpy-1.35.0/emodpy.egg-info/dependency_links.txt +1 -0
- emodpy-1.35.0/emodpy.egg-info/entry_points.txt +5 -0
- emodpy-1.35.0/emodpy.egg-info/requires.txt +19 -0
- emodpy-1.35.0/emodpy.egg-info/top_level.txt +1 -0
- emodpy-1.35.0/pyproject.toml +76 -0
- emodpy-1.35.0/setup.cfg +4 -0
- emodpy-1.35.0/tests/test_139.py +32 -0
- emodpy-1.35.0/tests/test_add_campaign_from_script.py +152 -0
- emodpy-1.35.0/tests/test_analyzers_emod_comps.py +315 -0
- emodpy-1.35.0/tests/test_download_from_package.py +26 -0
- emodpy-1.35.0/tests/test_e2e.py +243 -0
- emodpy-1.35.0/tests/test_emod_experiment.py +412 -0
- emodpy-1.35.0/tests/test_emod_task.py +608 -0
- emodpy-1.35.0/tests/test_emodpy_imports.py +93 -0
- emodpy-1.35.0/tests/test_experiment_simulations.py +209 -0
- emodpy-1.35.0/tests/test_pre_post_process.py +296 -0
- emodpy-1.35.0/tests/test_serialization.py +158 -0
- emodpy-1.35.0/tests/test_vitaldynamics_demographics.py +216 -0
- emodpy-1.35.0/tests/test_workflow_campaign.py +240 -0
- emodpy-1.35.0/tests/test_workflow_config.py +320 -0
- emodpy-1.35.0/tests/test_workflow_demographics.py +663 -0
- emodpy-1.35.0/tests/test_workflow_migration.py +545 -0
emodpy-1.35.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 - 2024 Bill & Melinda Gates Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
emodpy-1.35.0/PKG-INFO
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: emodpy
|
|
3
|
+
Version: 1.35.0
|
|
4
|
+
Summary: Core tools for modeling using EMOD
|
|
5
|
+
Author-email: Sharon Chen <sharon.chen@gatesfoundation.org>, Zhaowei Du <zhaowei.du@gatesfoundation.org>, Clark Kirkman IV <clark.kirkmand@gatesfoundation.org>, Daniel Bridenbecker <daniel.bridenbecker@gatesfoundation.org>, Svetlana Titova <svetlana.titova@gatesfoundation.org>, Ye Chen <ye.chen@gatesfoundation.org>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/EMOD-Hub/emodpy
|
|
8
|
+
Project-URL: Issues, https://github.com/EMOD-Hub/emodpy/issues
|
|
9
|
+
Keywords: modeling,IDM
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: idmtools[full]~=3.0
|
|
22
|
+
Requires-Dist: emod-api~=1.35.0
|
|
23
|
+
Provides-Extra: docs
|
|
24
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
25
|
+
Requires-Dist: mkdocs-include-markdown-plugin; extra == "docs"
|
|
26
|
+
Requires-Dist: mkdocstrings-python; extra == "docs"
|
|
27
|
+
Requires-Dist: mkdocs-autoapi; extra == "docs"
|
|
28
|
+
Requires-Dist: mkdocs-glightbox; extra == "docs"
|
|
29
|
+
Provides-Extra: lint
|
|
30
|
+
Requires-Dist: flake8; extra == "lint"
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: emod-common; extra == "test"
|
|
33
|
+
Requires-Dist: emod-malaria; extra == "test"
|
|
34
|
+
Requires-Dist: pytest; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-xdist; extra == "test"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
# emodpy
|
|
42
|
+
|
|
43
|
+
## Documentation
|
|
44
|
+
|
|
45
|
+
Documentation available at https://docs.idmod.org/projects/emodpy/en/latest/.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
To build the documentation locally, do the following:
|
|
49
|
+
|
|
50
|
+
1. Create and activate a venv.
|
|
51
|
+
2. Navigate to the root directory of the repo and enter the following
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
pip install -r requirements.txt
|
|
55
|
+
cd docs
|
|
56
|
+
pip install -r requirements.txt
|
|
57
|
+
cd ..
|
|
58
|
+
pip install -e .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
62
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
63
|
+
**Table of Contents**
|
|
64
|
+
|
|
65
|
+
- [User Installation](#user-installation)
|
|
66
|
+
- [Pre-requisites](#pre-requisites)
|
|
67
|
+
- [Development Environment Setup](#development-environment-setup)
|
|
68
|
+
- [First Time Setup](#first-time-setup)
|
|
69
|
+
- [Development Tips](#development-tips)
|
|
70
|
+
- [To run examples or tests](#to-run-examples-or-tests)
|
|
71
|
+
- [Building docs](#building-docs)
|
|
72
|
+
- [Community](#community)
|
|
73
|
+
- [Disclaimer](#disclaimer)
|
|
74
|
+
|
|
75
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# User Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install emodpy --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Pre-requisites
|
|
85
|
+
- Python 3.6/3.7 x64
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Development Environment Setup
|
|
89
|
+
|
|
90
|
+
When setting up your environment for the first time, you can use the following instructions
|
|
91
|
+
|
|
92
|
+
## First Time Setup
|
|
93
|
+
1) Clone the repository:
|
|
94
|
+
```bash
|
|
95
|
+
> git clone https://github.com/InstituteforDiseaseModeling/emodpy.git
|
|
96
|
+
```
|
|
97
|
+
2) Create a virtualenv. On Windows, please use venv to create the environment
|
|
98
|
+
`python -m venv idmtools`
|
|
99
|
+
On Unix(Mac/Linux) you can use venv or virtualenv
|
|
100
|
+
3) Activate the virtualenv
|
|
101
|
+
4) If you are on windows, run `pip install py-make --upgrade --force-reinstall`
|
|
102
|
+
5) Then run `python ./.dev_scripts/bootstrap.py`. This will install all the tools.
|
|
103
|
+
|
|
104
|
+
## Development Tips
|
|
105
|
+
|
|
106
|
+
There is a Makefile file available for most common development tasks. Here is a list of commands
|
|
107
|
+
```bash
|
|
108
|
+
clean - Clean up temproary files
|
|
109
|
+
lint - Lint package and tests
|
|
110
|
+
test - Run All tests
|
|
111
|
+
coverage - Run tests and generate coverage report that is shown in browser
|
|
112
|
+
```
|
|
113
|
+
On Windows, you can use `pymake` instead of `make`
|
|
114
|
+
|
|
115
|
+
## To run examples or tests
|
|
116
|
+
|
|
117
|
+
First, install idmtools packages including emodpy package from idm artifactory
|
|
118
|
+
|
|
119
|
+
staging artifactory with nightly build packages:
|
|
120
|
+
```bash
|
|
121
|
+
pip install idmtools[idm] --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
122
|
+
OR
|
|
123
|
+
pip install idmtools[full] --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
124
|
+
```
|
|
125
|
+
[idm] option will install all idmtools packages except idmtools_platform_local package
|
|
126
|
+
|
|
127
|
+
[full] option will install all idmtools packages including idmtools_platform_local package
|
|
128
|
+
|
|
129
|
+
email:password is your company login credentials. password should be encoded for specially characters
|
|
130
|
+
|
|
131
|
+
production artifactory with latest release packages:
|
|
132
|
+
```bash
|
|
133
|
+
pip install idmtools[idm] --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
134
|
+
OR
|
|
135
|
+
pip install idmtools[full] --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
136
|
+
```
|
|
137
|
+
To run integration tests or examples, you also need to install idmtools-test package
|
|
138
|
+
```bash
|
|
139
|
+
pip install idmtools-test --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
140
|
+
OR
|
|
141
|
+
pip install idmtools-test --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Building docs
|
|
145
|
+
|
|
146
|
+
Install all necessary documentation tools using ``pip install -r doc/requirements.txt`` and install emodpy in the same environment. Navigate to the docs folder and enter ``make html``. If you make updates to the docstrings, you must reinstall emodpy to pick up the latest changes in the documentation build. It's also good practice to run ``make clean`` before rebuilding the documentation to avoid missing errors or warnings. These steps are only for testing the build locally before committing changes. The documentation build on Read the Docs will run automatically when new code is committed.
|
|
147
|
+
|
|
148
|
+
# Community
|
|
149
|
+
The EMOD Community is made up of researchers and software developers, primarily focused on malaria and HIV research.
|
|
150
|
+
We value mutual respect, openness, and a collaborative spirit. If these values resonate with you,
|
|
151
|
+
we invite you to join our EMOD Slack Community by completing this form:
|
|
152
|
+
|
|
153
|
+
https://forms.office.com/r/sjncGvBjvZ
|
|
154
|
+
|
|
155
|
+
# Disclaimer
|
|
156
|
+
|
|
157
|
+
The code in this repository was developed by IDM and other collaborators to support our joint research on flexible agent-based modeling.
|
|
158
|
+
We've made it publicly available under the MIT License to provide others with a better understanding of our research and an opportunity to build upon it for
|
|
159
|
+
their own work. We make no representations that the code works as intended or that we will provide support, address issues that are found, or accept pull requests.
|
|
160
|
+
You are welcome to create your own fork and modify the code to suit your own modeling needs as permitted under the MIT License.
|
emodpy-1.35.0/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# emodpy
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
Documentation available at https://docs.idmod.org/projects/emodpy/en/latest/.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
To build the documentation locally, do the following:
|
|
11
|
+
|
|
12
|
+
1. Create and activate a venv.
|
|
13
|
+
2. Navigate to the root directory of the repo and enter the following
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
pip install -r requirements.txt
|
|
17
|
+
cd docs
|
|
18
|
+
pip install -r requirements.txt
|
|
19
|
+
cd ..
|
|
20
|
+
pip install -e .
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
24
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
25
|
+
**Table of Contents**
|
|
26
|
+
|
|
27
|
+
- [User Installation](#user-installation)
|
|
28
|
+
- [Pre-requisites](#pre-requisites)
|
|
29
|
+
- [Development Environment Setup](#development-environment-setup)
|
|
30
|
+
- [First Time Setup](#first-time-setup)
|
|
31
|
+
- [Development Tips](#development-tips)
|
|
32
|
+
- [To run examples or tests](#to-run-examples-or-tests)
|
|
33
|
+
- [Building docs](#building-docs)
|
|
34
|
+
- [Community](#community)
|
|
35
|
+
- [Disclaimer](#disclaimer)
|
|
36
|
+
|
|
37
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# User Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install emodpy --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Pre-requisites
|
|
47
|
+
- Python 3.6/3.7 x64
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Development Environment Setup
|
|
51
|
+
|
|
52
|
+
When setting up your environment for the first time, you can use the following instructions
|
|
53
|
+
|
|
54
|
+
## First Time Setup
|
|
55
|
+
1) Clone the repository:
|
|
56
|
+
```bash
|
|
57
|
+
> git clone https://github.com/InstituteforDiseaseModeling/emodpy.git
|
|
58
|
+
```
|
|
59
|
+
2) Create a virtualenv. On Windows, please use venv to create the environment
|
|
60
|
+
`python -m venv idmtools`
|
|
61
|
+
On Unix(Mac/Linux) you can use venv or virtualenv
|
|
62
|
+
3) Activate the virtualenv
|
|
63
|
+
4) If you are on windows, run `pip install py-make --upgrade --force-reinstall`
|
|
64
|
+
5) Then run `python ./.dev_scripts/bootstrap.py`. This will install all the tools.
|
|
65
|
+
|
|
66
|
+
## Development Tips
|
|
67
|
+
|
|
68
|
+
There is a Makefile file available for most common development tasks. Here is a list of commands
|
|
69
|
+
```bash
|
|
70
|
+
clean - Clean up temproary files
|
|
71
|
+
lint - Lint package and tests
|
|
72
|
+
test - Run All tests
|
|
73
|
+
coverage - Run tests and generate coverage report that is shown in browser
|
|
74
|
+
```
|
|
75
|
+
On Windows, you can use `pymake` instead of `make`
|
|
76
|
+
|
|
77
|
+
## To run examples or tests
|
|
78
|
+
|
|
79
|
+
First, install idmtools packages including emodpy package from idm artifactory
|
|
80
|
+
|
|
81
|
+
staging artifactory with nightly build packages:
|
|
82
|
+
```bash
|
|
83
|
+
pip install idmtools[idm] --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
84
|
+
OR
|
|
85
|
+
pip install idmtools[full] --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
86
|
+
```
|
|
87
|
+
[idm] option will install all idmtools packages except idmtools_platform_local package
|
|
88
|
+
|
|
89
|
+
[full] option will install all idmtools packages including idmtools_platform_local package
|
|
90
|
+
|
|
91
|
+
email:password is your company login credentials. password should be encoded for specially characters
|
|
92
|
+
|
|
93
|
+
production artifactory with latest release packages:
|
|
94
|
+
```bash
|
|
95
|
+
pip install idmtools[idm] --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
96
|
+
OR
|
|
97
|
+
pip install idmtools[full] --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
98
|
+
```
|
|
99
|
+
To run integration tests or examples, you also need to install idmtools-test package
|
|
100
|
+
```bash
|
|
101
|
+
pip install idmtools-test --index-url=https://email:password@packages.idmod.org/api/pypi/pypi-staging/simple
|
|
102
|
+
OR
|
|
103
|
+
pip install idmtools-test --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Building docs
|
|
107
|
+
|
|
108
|
+
Install all necessary documentation tools using ``pip install -r doc/requirements.txt`` and install emodpy in the same environment. Navigate to the docs folder and enter ``make html``. If you make updates to the docstrings, you must reinstall emodpy to pick up the latest changes in the documentation build. It's also good practice to run ``make clean`` before rebuilding the documentation to avoid missing errors or warnings. These steps are only for testing the build locally before committing changes. The documentation build on Read the Docs will run automatically when new code is committed.
|
|
109
|
+
|
|
110
|
+
# Community
|
|
111
|
+
The EMOD Community is made up of researchers and software developers, primarily focused on malaria and HIV research.
|
|
112
|
+
We value mutual respect, openness, and a collaborative spirit. If these values resonate with you,
|
|
113
|
+
we invite you to join our EMOD Slack Community by completing this form:
|
|
114
|
+
|
|
115
|
+
https://forms.office.com/r/sjncGvBjvZ
|
|
116
|
+
|
|
117
|
+
# Disclaimer
|
|
118
|
+
|
|
119
|
+
The code in this repository was developed by IDM and other collaborators to support our joint research on flexible agent-based modeling.
|
|
120
|
+
We've made it publicly available under the MIT License to provide others with a better understanding of our research and an opportunity to build upon it for
|
|
121
|
+
their own work. We make no representations that the code works as intended or that we will provide support, address issues that are found, or accept pull requests.
|
|
122
|
+
You are welcome to create your own fork and modify the code to suit your own modeling needs as permitted under the MIT License.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.35.0"
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from idmtools.core.interfaces.iitem import IItem
|
|
6
|
+
|
|
7
|
+
from idmtools.entities.ianalyzer import IAnalyzer as BaseAnalyzer
|
|
8
|
+
import matplotlib as mpl
|
|
9
|
+
mpl.use('Agg')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AdultVectorsAnalyzer(BaseAnalyzer):
|
|
13
|
+
|
|
14
|
+
def __init__(self, name='hi'):
|
|
15
|
+
super().__init__(filenames=["output\\InsetChart.json"])
|
|
16
|
+
print(name)
|
|
17
|
+
|
|
18
|
+
def initialize(self):
|
|
19
|
+
if not os.path.exists(os.path.join(self.working_dir, "output")):
|
|
20
|
+
os.mkdir(os.path.join(self.working_dir, "output"))
|
|
21
|
+
|
|
22
|
+
def map(self, data: Any, item: IItem) -> Any:
|
|
23
|
+
return data[self.filenames[0]]["Channels"]["Adult Vectors"]["Data"]
|
|
24
|
+
|
|
25
|
+
def reduce(self, all_data: dict) -> Any:
|
|
26
|
+
output_dir = os.path.join(self.working_dir, "output")
|
|
27
|
+
with open(os.path.join(output_dir, "adult_vectors.json"), "w") as fp:
|
|
28
|
+
json.dump({str(s.uid): v for s, v in all_data.items()}, fp)
|
|
29
|
+
|
|
30
|
+
import matplotlib.pyplot as plt
|
|
31
|
+
|
|
32
|
+
fig = plt.figure()
|
|
33
|
+
ax = fig.add_subplot(111)
|
|
34
|
+
|
|
35
|
+
for pop in list(all_data.values()):
|
|
36
|
+
ax.plot(pop)
|
|
37
|
+
ax.legend([str(s.uid) for s in all_data.keys()])
|
|
38
|
+
fig.savefig(os.path.join(output_dir, "adult_vectors.png"))
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from idmtools.core.interfaces.iitem import IItem
|
|
6
|
+
from idmtools.entities.ianalyzer import IAnalyzer as BaseAnalyzer
|
|
7
|
+
import matplotlib as mpl
|
|
8
|
+
|
|
9
|
+
mpl.use('Agg')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PopulationAnalyzer(BaseAnalyzer):
|
|
13
|
+
|
|
14
|
+
def __init__(self, name='idm'):
|
|
15
|
+
super().__init__(filenames=["output/InsetChart.json"])
|
|
16
|
+
print(name)
|
|
17
|
+
|
|
18
|
+
def initialize(self):
|
|
19
|
+
if not os.path.exists(os.path.join(self.working_dir, "output")):
|
|
20
|
+
os.mkdir(os.path.join(self.working_dir, "output"))
|
|
21
|
+
|
|
22
|
+
# idmtools analyzer
|
|
23
|
+
def map(self, data: Any, item: IItem) -> Any:
|
|
24
|
+
return data[self.filenames[0]]["Channels"]["Statistical Population"]["Data"]
|
|
25
|
+
|
|
26
|
+
def reduce(self, all_data: dict) -> Any:
|
|
27
|
+
output_dir = os.path.join(self.working_dir, "output")
|
|
28
|
+
|
|
29
|
+
with open(os.path.join(output_dir, "population.json"), "w") as fp:
|
|
30
|
+
json.dump({str(s.uid): v for s, v in all_data.items()}, fp)
|
|
31
|
+
|
|
32
|
+
import matplotlib.pyplot as plt
|
|
33
|
+
|
|
34
|
+
fig = plt.figure()
|
|
35
|
+
ax = fig.add_subplot(111)
|
|
36
|
+
|
|
37
|
+
for pop in list(all_data.values()):
|
|
38
|
+
ax.plot(pop)
|
|
39
|
+
ax.legend([str(s.uid) for s in all_data.keys()])
|
|
40
|
+
fig.savefig(os.path.join(output_dir, "population.png"))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# uncomment following lines with idmtools analyzer
|
|
44
|
+
# if __name__ == "__main__":
|
|
45
|
+
# platform = Platform('COMPS2')
|
|
46
|
+
#
|
|
47
|
+
# filenames = ['output/InsetChart.json']
|
|
48
|
+
# analyzers = [PopulationAnalyzer(working_dir=".")]
|
|
49
|
+
#
|
|
50
|
+
# exp_id = '8bb8ae8f-793c-ea11-a2be-f0921c167861' # comps2 exp_id
|
|
51
|
+
# manager = AnalyzeManager(platform=platform, ids=[(exp_id, ItemType.EXPERIMENT)], analyzers=analyzers)
|
|
52
|
+
# manager.analyze()
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from idmtools.analysis.analyze_manager import AnalyzeManager
|
|
8
|
+
from idmtools.core import ItemType
|
|
9
|
+
from idmtools.core.platform_factory import Platform
|
|
10
|
+
from idmtools.entities import IAnalyzer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TimeseriesAnalyzer(IAnalyzer):
|
|
14
|
+
data_group_names = ['group', 'sim_id', 'channel']
|
|
15
|
+
ordered_levels = ['channel', 'group', 'sim_id']
|
|
16
|
+
output_file = 'timeseries.csv'
|
|
17
|
+
|
|
18
|
+
def __init__(self, filenames=[os.path.join('output', 'InsetChart.json')], channels=('Statistical Population',
|
|
19
|
+
'Infectious Population',
|
|
20
|
+
'Infected',
|
|
21
|
+
'Waning Population'),
|
|
22
|
+
save_output=True):
|
|
23
|
+
|
|
24
|
+
super(TimeseriesAnalyzer, self).__init__(filenames=filenames)
|
|
25
|
+
self.channels = set(channels)
|
|
26
|
+
self.save_output = save_output
|
|
27
|
+
|
|
28
|
+
def initialize(self):
|
|
29
|
+
if not os.path.exists(os.path.join(self.working_dir, "output")):
|
|
30
|
+
os.mkdir(os.path.join(self.working_dir, "output"))
|
|
31
|
+
|
|
32
|
+
def default_select_fn(self, ts):
|
|
33
|
+
return pd.Series(ts)
|
|
34
|
+
|
|
35
|
+
def default_group_fn(self, k, v):
|
|
36
|
+
return k
|
|
37
|
+
|
|
38
|
+
def default_plot_fn(self, df, ax):
|
|
39
|
+
grouped = df.groupby(level=['group'], axis=1)
|
|
40
|
+
m = grouped.mean()
|
|
41
|
+
m.plot(ax=ax, legend=False)
|
|
42
|
+
|
|
43
|
+
def default_filter_fn(self, md):
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
def filter(self, simulation):
|
|
47
|
+
return self.default_filter_fn(simulation.tags)
|
|
48
|
+
|
|
49
|
+
def get_channel_data(self, data_by_channel, selected_channels):
|
|
50
|
+
channel_series = [self.default_select_fn(data_by_channel[channel]["Data"]) for channel in selected_channels]
|
|
51
|
+
return pd.concat(channel_series, axis=1, keys=selected_channels)
|
|
52
|
+
|
|
53
|
+
def map(self, data, simulation):
|
|
54
|
+
cdata = data[self.filenames[0]]['Channels']
|
|
55
|
+
selected_channels = self.channels.intersection(cdata.keys()) if self.channels else cdata.keys()
|
|
56
|
+
return self.get_channel_data(cdata, selected_channels)
|
|
57
|
+
|
|
58
|
+
def plot_by_channel(self, channels, plot_fn):
|
|
59
|
+
|
|
60
|
+
import matplotlib.pyplot as plt
|
|
61
|
+
|
|
62
|
+
ncol = int(1 + len(channels) / 4)
|
|
63
|
+
nrow = int(np.ceil(float(len(channels)) / ncol))
|
|
64
|
+
|
|
65
|
+
fig, axs = plt.subplots(figsize=(max(6, min(8, 4 * ncol)), min(6, 3 * nrow)), nrows=nrow, ncols=ncol,
|
|
66
|
+
sharex=True)
|
|
67
|
+
|
|
68
|
+
flat_axes = [axs] if ncol * nrow == 1 else axs.flat
|
|
69
|
+
for (channel, ax) in zip(channels, flat_axes):
|
|
70
|
+
ax.set_title(channel)
|
|
71
|
+
plot_fn(channel, ax)
|
|
72
|
+
|
|
73
|
+
def reduce(self, all_data):
|
|
74
|
+
output_dir = os.path.join(self.working_dir, "output")
|
|
75
|
+
selected = []
|
|
76
|
+
for sim, data in all_data.items():
|
|
77
|
+
# Enrich the data with info
|
|
78
|
+
data.group = self.default_group_fn(sim.uid, sim.tags)
|
|
79
|
+
data.sim_id = sim.uid
|
|
80
|
+
selected.append(data)
|
|
81
|
+
|
|
82
|
+
if len(selected) == 0:
|
|
83
|
+
print("\n No data have been returned... Exiting...")
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
# Combining selected data...
|
|
87
|
+
combined = pd.concat(selected, axis=1,
|
|
88
|
+
keys=[(d.group, d.sim_id) for d in selected],
|
|
89
|
+
names=self.data_group_names)
|
|
90
|
+
|
|
91
|
+
# Re-ordering multi-index levels...
|
|
92
|
+
data = combined.reorder_levels(self.ordered_levels, axis=1).sort_index(axis=1)
|
|
93
|
+
|
|
94
|
+
if self.save_output:
|
|
95
|
+
data.to_csv(os.path.join(output_dir, self.output_file))
|
|
96
|
+
|
|
97
|
+
def plot_fn(channel, ax):
|
|
98
|
+
self.default_plot_fn(data[channel].dropna(), ax)
|
|
99
|
+
|
|
100
|
+
channels = data.columns.levels[0]
|
|
101
|
+
self.plot_by_channel(channels, plot_fn)
|
|
102
|
+
|
|
103
|
+
plt.legend()
|
|
104
|
+
# plt.show()
|
|
105
|
+
plt.savefig(os.path.join(output_dir, 'timeseries.png'))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
platform = Platform('COMPS2')
|
|
110
|
+
|
|
111
|
+
exp_id = '8a7ff62a-fe7f-ea11-a2bf-f0921c167862' # comps2 exp_id
|
|
112
|
+
|
|
113
|
+
filenames = ['output/InsetChart.json']
|
|
114
|
+
analyzers = [TimeseriesAnalyzer(filenames=filenames)]
|
|
115
|
+
|
|
116
|
+
manager = AnalyzeManager(platform=platform, ids=[(exp_id, ItemType.EXPERIMENT)], analyzers=analyzers)
|
|
117
|
+
manager.analyze()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from typing import Tuple, List, Mapping, Union, Iterable
|
|
2
|
+
|
|
3
|
+
from more_itertools import take
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def cut_iterable_to(obj: Iterable, to: int) -> Tuple[Union[List, Mapping], int]:
|
|
7
|
+
"""
|
|
8
|
+
Cut an iterable to a certain length.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
obj: The iterable to cut.
|
|
12
|
+
to: The number of elements to return.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
A list or dictionary (depending on the type of object) of elements and
|
|
16
|
+
the remaining elements in the original list or dictionary.
|
|
17
|
+
"""
|
|
18
|
+
if isinstance(obj, dict):
|
|
19
|
+
slice = {k: v for (k, v) in take(to, obj.items())}
|
|
20
|
+
else:
|
|
21
|
+
slice = take(to, obj)
|
|
22
|
+
|
|
23
|
+
remaining = len(obj) - to
|
|
24
|
+
remaining = 0 if remaining < 0 else remaining
|
|
25
|
+
return slice, remaining
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
####
|
|
29
|
+
# DicDeep v2
|
|
30
|
+
# https://github.com/mbello/dict-deep/blob/master/dict_deep/dict_deep.py
|
|
31
|
+
def deep_get(d, key, default: callable = None, getter: callable = None, sep: str = '.'):
|
|
32
|
+
getter = __getter(getter, default)
|
|
33
|
+
keys = __keys(key, sep)
|
|
34
|
+
|
|
35
|
+
for k in keys:
|
|
36
|
+
d = getter(d, k)
|
|
37
|
+
|
|
38
|
+
return d
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def deep_set(d, key, value, default: callable = None, getter: callable = None, setter: callable = None, sep: str = '.'):
|
|
42
|
+
keys = __keys(key, sep)
|
|
43
|
+
getter = __getter(getter, default)
|
|
44
|
+
setter = __setter(setter)
|
|
45
|
+
|
|
46
|
+
for i in range(len(keys) - 1):
|
|
47
|
+
d = getter(d, keys[i])
|
|
48
|
+
|
|
49
|
+
setter(d, keys[-1], value)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def deep_del(d: dict, key, getter: callable = None, deleter: callable = None, sep: str = '.'):
|
|
53
|
+
keys = __keys(key, sep)
|
|
54
|
+
getter = getter if getter is not None else lambda o, k: o.get(k)
|
|
55
|
+
|
|
56
|
+
for i in range(len(keys) - 1):
|
|
57
|
+
if d is None:
|
|
58
|
+
return False, None
|
|
59
|
+
d = getter(d, keys[i])
|
|
60
|
+
|
|
61
|
+
if d is not None and isinstance(d, dict) and keys[-1] in d:
|
|
62
|
+
retval = getter(d, keys[-1])
|
|
63
|
+
if deleter is None:
|
|
64
|
+
del d[keys[-1]]
|
|
65
|
+
else:
|
|
66
|
+
deleter(d, keys[-1])
|
|
67
|
+
return True, retval
|
|
68
|
+
else:
|
|
69
|
+
return False, None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def __keys(key, sep: str):
|
|
73
|
+
if isinstance(key, str):
|
|
74
|
+
return key.split(sep=sep)
|
|
75
|
+
else:
|
|
76
|
+
return list(key)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def __getter(getter: callable, default: callable):
|
|
80
|
+
if getter is not None:
|
|
81
|
+
return getter
|
|
82
|
+
elif default is not None:
|
|
83
|
+
return lambda o, k: o.setdefault(k, default())
|
|
84
|
+
else:
|
|
85
|
+
return lambda o, k: o[k]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def __setter(setter: callable):
|
|
89
|
+
def __default_setter(o, k, v):
|
|
90
|
+
o[k] = v
|
|
91
|
+
|
|
92
|
+
return setter if setter is not None else __default_setter
|