emodpy 1.35.0__py3-none-any.whl
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/__init__.py +1 -0
- emodpy/analyzers/__init__.py +0 -0
- emodpy/analyzers/adult_vectors_analyzer.py +38 -0
- emodpy/analyzers/population_analyzer.py +52 -0
- emodpy/analyzers/timeseries_analyzer.py +117 -0
- emodpy/collections_utils.py +92 -0
- emodpy/defaults/__init__.py +2 -0
- emodpy/defaults/emod_sir.py +195 -0
- emodpy/defaults/ep4/__init__.py +0 -0
- emodpy/defaults/ep4/dtk_in_process.py +20 -0
- emodpy/defaults/ep4/dtk_post_process.py +20 -0
- emodpy/defaults/ep4/dtk_pre_process.py +55 -0
- emodpy/defaults/iemod_default.py +20 -0
- emodpy/emod_campaign.py +118 -0
- emodpy/emod_file.py +399 -0
- emodpy/emod_task.py +891 -0
- emodpy/generic/__init__.py +0 -0
- emodpy/generic/serialization.py +64 -0
- emodpy/interventions/__init__.py +2 -0
- emodpy/interventions/emod_empty_campaign.py +12 -0
- emodpy/reporters/__init__.py +1 -0
- emodpy/reporters/base.py +258 -0
- emodpy/reporters/builtin.py +22 -0
- emodpy/reporters/custom.py +104 -0
- emodpy/utils.py +11 -0
- emodpy-1.35.0.dist-info/METADATA +160 -0
- emodpy-1.35.0.dist-info/RECORD +31 -0
- emodpy-1.35.0.dist-info/WHEEL +5 -0
- emodpy-1.35.0.dist-info/entry_points.txt +5 -0
- emodpy-1.35.0.dist-info/licenses/LICENSE +21 -0
- emodpy-1.35.0.dist-info/top_level.txt +1 -0
emodpy/__init__.py
ADDED
|
@@ -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,195 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
from emodpy.defaults.iemod_default import IEMODDefault
|
|
3
|
+
from emodpy.emod_campaign import EMODCampaign
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EMODSir(IEMODDefault):
|
|
7
|
+
@staticmethod
|
|
8
|
+
def config(erad_path) -> Dict:
|
|
9
|
+
return {
|
|
10
|
+
"Acquisition_Blocking_Immunity_Decay_Rate": 0.1,
|
|
11
|
+
"Acquisition_Blocking_Immunity_Duration_Before_Decay": 60,
|
|
12
|
+
"Age_Initialization_Distribution_Type": "DISTRIBUTION_SIMPLE",
|
|
13
|
+
"Animal_Reservoir_Type": "NO_ZOONOSIS",
|
|
14
|
+
"Base_Incubation_Period": 0,
|
|
15
|
+
"Base_Individual_Sample_Rate": 1,
|
|
16
|
+
"Base_Infectious_Period": 4,
|
|
17
|
+
"Base_Infectivity": 3.5,
|
|
18
|
+
"Base_Mortality": 0,
|
|
19
|
+
"Base_Population_Scale_Factor": 1,
|
|
20
|
+
"Birth_Rate_Dependence": "POPULATION_DEP_RATE",
|
|
21
|
+
"Birth_Rate_Time_Dependence": "NONE",
|
|
22
|
+
"Burnin_Cache_Mode": "none",
|
|
23
|
+
"Burnin_Cache_Period": 0,
|
|
24
|
+
"Burnin_Name": "",
|
|
25
|
+
"Campaign_Filename": "campaign.json",
|
|
26
|
+
"Climate_Model": "CLIMATE_OFF",
|
|
27
|
+
"Config_Name": "01_SIR",
|
|
28
|
+
"Custom_Coordinator_Events": [],
|
|
29
|
+
"Custom_Individual_Events": [],
|
|
30
|
+
"Custom_Node_Events": [],
|
|
31
|
+
"Custom_Reports_Filename": "NoCustomReports",
|
|
32
|
+
"Default_Geography_Initial_Node_Population": 1000,
|
|
33
|
+
"Default_Geography_Torus_Size": 10,
|
|
34
|
+
"Demographics_Filenames": ["generic_scenarios_demographics.json"],
|
|
35
|
+
"Enable_Default_Reporting": 1,
|
|
36
|
+
"Enable_Default_Shedding_Function": 1,
|
|
37
|
+
"Enable_Demographics_Birth": 0,
|
|
38
|
+
"Enable_Demographics_Builtin": 0,
|
|
39
|
+
"Enable_Demographics_Gender": 1,
|
|
40
|
+
"Enable_Demographics_Other": 0,
|
|
41
|
+
"Enable_Demographics_Reporting": 1,
|
|
42
|
+
"Enable_Disease_Mortality": 0,
|
|
43
|
+
"Enable_Heterogeneous_Intranode_Transmission": 0,
|
|
44
|
+
"Enable_Immune_Decay": 0,
|
|
45
|
+
"Enable_Immunity": 1,
|
|
46
|
+
"Enable_Infectivity_Reservoir": 0,
|
|
47
|
+
"Enable_Initial_Prevalence": 0,
|
|
48
|
+
"Enable_Infectivity_Scaling": 0,
|
|
49
|
+
"Enable_Initial_Susceptibility_Distribution": 0,
|
|
50
|
+
"Enable_Interventions": 1,
|
|
51
|
+
"Enable_Maternal_Transmission": 0,
|
|
52
|
+
"Enable_Maternal_Protection": 0,
|
|
53
|
+
"Enable_Property_Output": 0,
|
|
54
|
+
"Enable_Skipping": 0,
|
|
55
|
+
"Enable_Spatial_Output": 0,
|
|
56
|
+
"Enable_Strain_Tracking": 0,
|
|
57
|
+
"Enable_Superinfection": 0,
|
|
58
|
+
"Enable_Susceptibility_Scaling": 0,
|
|
59
|
+
"Enable_Termination_On_Zero_Total_Infectivity": 0,
|
|
60
|
+
"Enable_Vital_Dynamics": 0,
|
|
61
|
+
"Geography": "SamplesInput",
|
|
62
|
+
"Immunity_Acquisition_Factor": 0,
|
|
63
|
+
"Immunity_Initialization_Distribution_Type": "DISTRIBUTION_OFF",
|
|
64
|
+
"Immunity_Mortality_Factor": 0,
|
|
65
|
+
"Immunity_Transmission_Factor": 0,
|
|
66
|
+
"Incubation_Period_Constant": 0,
|
|
67
|
+
"Incubation_Period_Distribution": "CONSTANT_DISTRIBUTION",
|
|
68
|
+
"Individual_Sampling_Type": "TRACK_ALL",
|
|
69
|
+
"Infection_Updates_Per_Timestep": 1,
|
|
70
|
+
"Infectious_Period_Exponential": 4,
|
|
71
|
+
"Infectious_Period_Distribution": "EXPONENTIAL_DISTRIBUTION",
|
|
72
|
+
"Infectivity_Scale_Type": "CONSTANT_INFECTIVITY",
|
|
73
|
+
"Job_Node_Groups": "Chassis08",
|
|
74
|
+
"Job_Priority": "BELOWNORMAL",
|
|
75
|
+
"Listed_Events": [],
|
|
76
|
+
"Load_Balance_Filename": "",
|
|
77
|
+
"Local_Simulation": 0,
|
|
78
|
+
"Maternal_Transmission_Probability": 0,
|
|
79
|
+
"Max_Individual_Infections": 1,
|
|
80
|
+
"Max_Node_Population_Samples": 40,
|
|
81
|
+
"Migration_Model": "NO_MIGRATION",
|
|
82
|
+
"Minimum_Adult_Age_Years": 15,
|
|
83
|
+
"Mortality_Blocking_Immunity_Decay_Rate": 0.001,
|
|
84
|
+
"Mortality_Blocking_Immunity_Duration_Before_Decay": 60,
|
|
85
|
+
"Mortality_Time_Course": "DAILY_MORTALITY",
|
|
86
|
+
"Node_Grid_Size": 0.042,
|
|
87
|
+
"Num_Cores": 1,
|
|
88
|
+
"Number_Basestrains": 1,
|
|
89
|
+
"Number_Substrains": 1,
|
|
90
|
+
"PKPD_Model": "FIXED_DURATION_CONSTANT_EFFECT",
|
|
91
|
+
"Population_Density_C50": 30,
|
|
92
|
+
"Population_Density_Infectivity_Correction": "CONSTANT_INFECTIVITY",
|
|
93
|
+
"Population_Scale_Type": "USE_INPUT_FILE",
|
|
94
|
+
"Post_Infection_Acquisition_Multiplier": 0,
|
|
95
|
+
"Post_Infection_Mortality_Multiplier": 0,
|
|
96
|
+
"Post_Infection_Transmission_Multiplier": 0,
|
|
97
|
+
"Report_Coordinator_Event_Recorder": 0,
|
|
98
|
+
"Report_Event_Recorder": 0,
|
|
99
|
+
"Report_Node_Event_Recorder": 0,
|
|
100
|
+
"Report_Surveillance_Event_Recorder": 0,
|
|
101
|
+
"Run_Number": 1,
|
|
102
|
+
"Sample_Rate_0_18mo": 1,
|
|
103
|
+
"Sample_Rate_10_14": 1,
|
|
104
|
+
"Sample_Rate_15_19": 1,
|
|
105
|
+
"Sample_Rate_18mo_4yr": 1,
|
|
106
|
+
"Sample_Rate_20_Plus": 1,
|
|
107
|
+
"Sample_Rate_5_9": 1,
|
|
108
|
+
"Sample_Rate_Birth": 1,
|
|
109
|
+
"Serialization_Type": "NONE",
|
|
110
|
+
"Simulation_Duration": 90,
|
|
111
|
+
"Simulation_Timestep": 1,
|
|
112
|
+
"Simulation_Type": "GENERIC_SIM",
|
|
113
|
+
"Start_Time": 0,
|
|
114
|
+
"Susceptibility_Scale_Type": "CONSTANT_SUSCEPTIBILITY",
|
|
115
|
+
"Symptomatic_Infectious_Offset": 0,
|
|
116
|
+
"Transmission_Blocking_Immunity_Decay_Rate": 0.1,
|
|
117
|
+
"Transmission_Blocking_Immunity_Duration_Before_Decay": 60,
|
|
118
|
+
"x_Air_Migration": 1,
|
|
119
|
+
"x_Birth": 1,
|
|
120
|
+
"x_Local_Migration": 1,
|
|
121
|
+
"x_Other_Mortality": 1,
|
|
122
|
+
"x_Population_Immunity": 1,
|
|
123
|
+
"x_Regional_Migration": 1,
|
|
124
|
+
"x_Sea_Migration": 1,
|
|
125
|
+
"x_Temporary_Larval_Habitat": 1,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def campaign() -> EMODCampaign:
|
|
130
|
+
return EMODCampaign.load_from_dict(
|
|
131
|
+
{
|
|
132
|
+
"Campaign_Name": "Initial Seeding",
|
|
133
|
+
"Events": [
|
|
134
|
+
{
|
|
135
|
+
"Event_Coordinator_Config": {
|
|
136
|
+
"Demographic_Coverage": 0.0005,
|
|
137
|
+
"Intervention_Config": {"Outbreak_Source": "PrevalenceIncrease", "class": "OutbreakIndividual"},
|
|
138
|
+
"class": "StandardInterventionDistributionEventCoordinator",
|
|
139
|
+
},
|
|
140
|
+
"Event_Name": "Outbreak",
|
|
141
|
+
"Nodeset_Config": {"class": "NodeSetAll"},
|
|
142
|
+
"class": "CampaignEvent",
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"Use_Defaults": 1,
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def demographics() -> Dict:
|
|
151
|
+
nodes = [
|
|
152
|
+
(0, 0.3, 311),
|
|
153
|
+
(0, 0.2, 511),
|
|
154
|
+
(0, 0.1, 711),
|
|
155
|
+
(0.1, 0.3, 911),
|
|
156
|
+
(0.1, 0.2, 1111),
|
|
157
|
+
(0.1, 0.1, 1311),
|
|
158
|
+
(0.2, 0.3, 1511),
|
|
159
|
+
(0.2, 0.2, 1711),
|
|
160
|
+
(0.2, 0.1, 1911),
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
"generic_scenarios_demographics.json": {
|
|
165
|
+
"Metadata": {
|
|
166
|
+
"DateCreated": "Mon Nov 4 07:00:00 2019",
|
|
167
|
+
"Tool": "notepad",
|
|
168
|
+
"Author": "YeChen",
|
|
169
|
+
"IdReference": "0",
|
|
170
|
+
"NodeCount": 9,
|
|
171
|
+
"Resolution": 150,
|
|
172
|
+
},
|
|
173
|
+
"Defaults": {
|
|
174
|
+
"NodeAttributes": {"Altitude": 0, "Airport": 0, "Region": 1, "Seaport": 0, "BirthRate": 0.0, "InitialPopulation": 0},
|
|
175
|
+
"IndividualAttributes": {
|
|
176
|
+
"AgeDistributionFlag": 1,
|
|
177
|
+
"AgeDistribution1": 0.0,
|
|
178
|
+
"AgeDistribution2": 43800.0,
|
|
179
|
+
"PrevalenceDistributionFlag": 0,
|
|
180
|
+
"PrevalenceDistribution1": 0.0,
|
|
181
|
+
"PrevalenceDistribution2": 0.0,
|
|
182
|
+
"SusceptibilityDistributionFlag": 0,
|
|
183
|
+
"SusceptibilityDistribution1": 1,
|
|
184
|
+
"SusceptibilityDistribution2": 0,
|
|
185
|
+
"RiskDistributionFlag": 0,
|
|
186
|
+
"RiskDistribution1": 1,
|
|
187
|
+
"RiskDistribution2": 0,
|
|
188
|
+
"MigrationHeterogeneityDistributionFlag": 2,
|
|
189
|
+
"MigrationHeterogeneityDistribution1": 15,
|
|
190
|
+
"MigrationHeterogeneityDistribution2": 5,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
"Nodes": [{"NodeID": i + 1, "NodeAttributes": {"Longitude": n[0], "Latitude": n[1], "InitialPopulation": n[2]}} for i, n in enumerate(nodes)],
|
|
194
|
+
}
|
|
195
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
CURRENT_DIRECTORY = os.path.dirname(__file__)
|
|
7
|
+
LIBRARY_PATH = os.path.join(CURRENT_DIRECTORY, "..", "site-packages") # Need to site_packages level!!!
|
|
8
|
+
sys.path.insert(0, LIBRARY_PATH) # Very Important!
|
|
9
|
+
|
|
10
|
+
# import emod_api.config as conf
|
|
11
|
+
# import emod_api.campaign as camp
|
|
12
|
+
# import emod_api.demographics as demo
|
|
13
|
+
# import emod_api.migration as mig
|
|
14
|
+
# import emod_api.weather as clim
|
|
15
|
+
# import emod_api.serialization as serial
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def application(timestep):
|
|
19
|
+
print(f"Hello from dtk_in_process.py at timestep {timestep}.")
|
|
20
|
+
return ""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import emod_api.config.dtk_post_process_adhocevents as dpp
|
|
6
|
+
|
|
7
|
+
CURRENT_DIRECTORY = os.path.dirname(__file__)
|
|
8
|
+
LIBRARY_PATH = os.path.join(CURRENT_DIRECTORY, "..", "site-packages") # Need to site_packages level!!!
|
|
9
|
+
sys.path.insert(0, LIBRARY_PATH) # Very Important!
|
|
10
|
+
|
|
11
|
+
# import emod_api.channelreports as emod_json
|
|
12
|
+
# import emod_api.spatialreports as spat
|
|
13
|
+
# import emod_api.tabularoutput as emod_csv
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def application(output_path):
|
|
17
|
+
if os.path.exists("config_xform.json") is False:
|
|
18
|
+
return
|
|
19
|
+
dpp.application(output_path)
|
|
20
|
+
print("dtk_post_process.py ran!")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
# import sys
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
# CURRENT_DIRECTORY = os.path.dirname(__file__)
|
|
8
|
+
# LIBRARY_PATH = os.path.join(CURRENT_DIRECTORY, "..", "site-packages") # Need to site_packages level!!!
|
|
9
|
+
# sys.path.insert(0, LIBRARY_PATH) # Very Important!
|
|
10
|
+
|
|
11
|
+
# import emod_api.config.dtk_pre_process_adhocevents as adhoc # the code in this emod_api submodule should be updated then we can use it instad of having our own modified version.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def convert_plugin_reports(config_json):
|
|
15
|
+
# Could do a nifty for loop but obsessing about copy-pasting can sometimes lead to unnecessarily opaque code
|
|
16
|
+
crf = ""
|
|
17
|
+
if "Custom_Reports_Filename" in config_json["parameters"]:
|
|
18
|
+
crf = config_json["parameters"]["Custom_Reports_Filename"]
|
|
19
|
+
if os.path.exists(crf):
|
|
20
|
+
report_json = None
|
|
21
|
+
with open(crf) as crf_handle:
|
|
22
|
+
# could just read string, do replace, and write string but seems nasty to skip json parsing....
|
|
23
|
+
report_json_str = json.dumps(json.load(crf_handle))
|
|
24
|
+
event_map = config_json["parameters"]["Event_Map"]
|
|
25
|
+
for replacement, event in event_map.items():
|
|
26
|
+
report_json_str = report_json_str.replace(f'"{event}"', f'"{replacement}"')
|
|
27
|
+
report_json = json.loads(report_json_str)
|
|
28
|
+
|
|
29
|
+
with open("custom_reports_xform.json", "w") as report_json_handle:
|
|
30
|
+
report_json_handle.write(json.dumps(report_json, sort_keys=True, indent=4))
|
|
31
|
+
|
|
32
|
+
config_json["parameters"]["Custom_Reports_Filename"] = "custom_reports_xform.json"
|
|
33
|
+
|
|
34
|
+
return config_json
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def application(json_config_path):
|
|
38
|
+
# Check if config.json has "Adhoc_Events". If so, process
|
|
39
|
+
config_json = json.load(open(json_config_path, "r"))
|
|
40
|
+
# campaign is written with GP_EVENT_XXX's but custom_reports need to be modified.
|
|
41
|
+
if "Event_Map" in config_json["parameters"] and len(config_json["parameters"]["Event_Map"]) > 0:
|
|
42
|
+
event_map = config_json["parameters"]["Event_Map"]
|
|
43
|
+
config_json = convert_plugin_reports(config_json)
|
|
44
|
+
|
|
45
|
+
config_json_str = json.dumps(config_json)
|
|
46
|
+
for replacement, event in event_map.items():
|
|
47
|
+
config_json_str = config_json_str.replace(f'"{event}"', f'"{replacement}"')
|
|
48
|
+
config_json = json.loads(config_json_str)
|
|
49
|
+
config_json["parameters"]["Event_Map"] = event_map
|
|
50
|
+
with open("config_xform.json", "w") as new_config:
|
|
51
|
+
json.dump(config_json, new_config)
|
|
52
|
+
return "config_xform.json"
|
|
53
|
+
# return adhoc.do_mapping_from_events( json_config_path, adhoc_events )
|
|
54
|
+
else:
|
|
55
|
+
return json_config_path
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from abc import ABCMeta
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
from emodpy.emod_campaign import EMODCampaign
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IEMODDefault(metaclass=ABCMeta):
|
|
8
|
+
def config(self, erad_path) -> Dict:
|
|
9
|
+
return {}
|
|
10
|
+
|
|
11
|
+
def campaign(self) -> Dict:
|
|
12
|
+
return EMODCampaign()
|
|
13
|
+
|
|
14
|
+
def demographics(self) -> Dict:
|
|
15
|
+
return {}
|
|
16
|
+
|
|
17
|
+
def process_simulation(self, simulation):
|
|
18
|
+
simulation.campaign = self.campaign()
|
|
19
|
+
|
|
20
|
+
simulation.config = self.config()
|