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.
Files changed (53) hide show
  1. emodpy-1.35.0/LICENSE +21 -0
  2. emodpy-1.35.0/MANIFEST.in +3 -0
  3. emodpy-1.35.0/PKG-INFO +160 -0
  4. emodpy-1.35.0/README.md +122 -0
  5. emodpy-1.35.0/emodpy/__init__.py +1 -0
  6. emodpy-1.35.0/emodpy/analyzers/__init__.py +0 -0
  7. emodpy-1.35.0/emodpy/analyzers/adult_vectors_analyzer.py +38 -0
  8. emodpy-1.35.0/emodpy/analyzers/population_analyzer.py +52 -0
  9. emodpy-1.35.0/emodpy/analyzers/timeseries_analyzer.py +117 -0
  10. emodpy-1.35.0/emodpy/collections_utils.py +92 -0
  11. emodpy-1.35.0/emodpy/defaults/__init__.py +2 -0
  12. emodpy-1.35.0/emodpy/defaults/emod_sir.py +195 -0
  13. emodpy-1.35.0/emodpy/defaults/ep4/__init__.py +0 -0
  14. emodpy-1.35.0/emodpy/defaults/ep4/dtk_in_process.py +20 -0
  15. emodpy-1.35.0/emodpy/defaults/ep4/dtk_post_process.py +20 -0
  16. emodpy-1.35.0/emodpy/defaults/ep4/dtk_pre_process.py +55 -0
  17. emodpy-1.35.0/emodpy/defaults/iemod_default.py +20 -0
  18. emodpy-1.35.0/emodpy/emod_campaign.py +118 -0
  19. emodpy-1.35.0/emodpy/emod_file.py +399 -0
  20. emodpy-1.35.0/emodpy/emod_task.py +891 -0
  21. emodpy-1.35.0/emodpy/generic/__init__.py +0 -0
  22. emodpy-1.35.0/emodpy/generic/serialization.py +64 -0
  23. emodpy-1.35.0/emodpy/interventions/__init__.py +2 -0
  24. emodpy-1.35.0/emodpy/interventions/emod_empty_campaign.py +12 -0
  25. emodpy-1.35.0/emodpy/reporters/__init__.py +1 -0
  26. emodpy-1.35.0/emodpy/reporters/base.py +258 -0
  27. emodpy-1.35.0/emodpy/reporters/builtin.py +22 -0
  28. emodpy-1.35.0/emodpy/reporters/custom.py +104 -0
  29. emodpy-1.35.0/emodpy/utils.py +11 -0
  30. emodpy-1.35.0/emodpy.egg-info/PKG-INFO +160 -0
  31. emodpy-1.35.0/emodpy.egg-info/SOURCES.txt +51 -0
  32. emodpy-1.35.0/emodpy.egg-info/dependency_links.txt +1 -0
  33. emodpy-1.35.0/emodpy.egg-info/entry_points.txt +5 -0
  34. emodpy-1.35.0/emodpy.egg-info/requires.txt +19 -0
  35. emodpy-1.35.0/emodpy.egg-info/top_level.txt +1 -0
  36. emodpy-1.35.0/pyproject.toml +76 -0
  37. emodpy-1.35.0/setup.cfg +4 -0
  38. emodpy-1.35.0/tests/test_139.py +32 -0
  39. emodpy-1.35.0/tests/test_add_campaign_from_script.py +152 -0
  40. emodpy-1.35.0/tests/test_analyzers_emod_comps.py +315 -0
  41. emodpy-1.35.0/tests/test_download_from_package.py +26 -0
  42. emodpy-1.35.0/tests/test_e2e.py +243 -0
  43. emodpy-1.35.0/tests/test_emod_experiment.py +412 -0
  44. emodpy-1.35.0/tests/test_emod_task.py +608 -0
  45. emodpy-1.35.0/tests/test_emodpy_imports.py +93 -0
  46. emodpy-1.35.0/tests/test_experiment_simulations.py +209 -0
  47. emodpy-1.35.0/tests/test_pre_post_process.py +296 -0
  48. emodpy-1.35.0/tests/test_serialization.py +158 -0
  49. emodpy-1.35.0/tests/test_vitaldynamics_demographics.py +216 -0
  50. emodpy-1.35.0/tests/test_workflow_campaign.py +240 -0
  51. emodpy-1.35.0/tests/test_workflow_config.py +320 -0
  52. emodpy-1.35.0/tests/test_workflow_demographics.py +663 -0
  53. 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.
@@ -0,0 +1,3 @@
1
+ include requirements.txt
2
+ include README.md
3
+ recursive-exclude dir tests/**
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
+ ![Staging: emodpy](https://github.com/InstituteforDiseaseModeling/emodpy-idmtools/workflows/Staging:%20emodpy/badge.svg)
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.
@@ -0,0 +1,122 @@
1
+ ![Staging: emodpy](https://github.com/InstituteforDiseaseModeling/emodpy-idmtools/workflows/Staging:%20emodpy/badge.svg)
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
@@ -0,0 +1,2 @@
1
+ # flake8: noqa F821
2
+ from emodpy.defaults.emod_sir import EMODSir