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 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,2 @@
1
+ # flake8: noqa F821
2
+ from emodpy.defaults.emod_sir import EMODSir
@@ -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()