Skip to content

Commit 6d01187

Browse files
HenrZuMaxBetzDLR
andauthored
85 Python Bindings for first first paper simulation (#653)
Co-authored-by: MaxBetzDLR <[email protected]>
1 parent 1b9dbf7 commit 6d01187

9 files changed

Lines changed: 828 additions & 1 deletion

File tree

cpp/models/ode_secir/parameters_io.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,15 @@ export_input_data_county_timeseries(std::vector<Model>& model, const std::string
276276

277277
return success();
278278
}
279-
279+
#else
280+
template <class Model>
281+
IOResult<void> export_input_data_county_timeseries(std::vector<Model>&, const std::string&, std::vector<int> const&,
282+
Date, const std::vector<double>&, double, int, const std::string&,
283+
const std::string&, const std::string&)
284+
{
285+
mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data.");
286+
return success();
287+
}
280288
#endif // MEMILIO_HAS_HDF5
281289

282290
/**

pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py

Lines changed: 472 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2020-2023 German Aerospace Center (DLR-SC)
3+
*
4+
* Authors: Henrik Zunker, Maximilian Betz
5+
*
6+
* Contact: Martin J. Kuehn <[email protected]>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
#ifndef PYMIO_EPI_DYNAMIC_LOCKDOWN_H
21+
#define PYMIO_EPI_DYNAMIC_LOCKDOWN_H
22+
23+
#include "memilio/config.h"
24+
#include "memilio/epidemiology/damping.h"
25+
#include "memilio/epidemiology/damping_sampling.h"
26+
#include "memilio/epidemiology/dynamic_npis.h"
27+
#include "pybind_util.h"
28+
29+
#include "pybind11/pybind11.h"
30+
#include <utility>
31+
32+
namespace pymio
33+
{
34+
35+
void bind_dynamicNPI_members(pybind11::module_& m, std::string const& name)
36+
{
37+
bind_Range<decltype(std::declval<mio::DynamicNPIs>().get_thresholds())>(m, "_ThresholdRange");
38+
using C = mio::DynamicNPIs;
39+
pybind11::class_<C>(m, name.c_str())
40+
.def(pybind11::init<>())
41+
.def_property(
42+
"interval",
43+
[](mio::DynamicNPIs& self) {
44+
return static_cast<double>(self.get_interval());
45+
},
46+
[](mio::DynamicNPIs& self, double v) {
47+
self.set_interval(mio::SimulationTime(v));
48+
})
49+
.def_property(
50+
"duration",
51+
[](mio::DynamicNPIs& self) {
52+
return static_cast<double>(self.get_duration());
53+
},
54+
[](mio::DynamicNPIs& self, double v) {
55+
self.set_duration(mio::SimulationTime(v));
56+
})
57+
.def_property(
58+
"base_value",
59+
[](mio::DynamicNPIs& self) {
60+
return static_cast<double>(self.get_base_value());
61+
},
62+
[](mio::DynamicNPIs& self, double v) {
63+
self.set_base_value(v);
64+
})
65+
.def_property_readonly("threshold",
66+
[](mio::DynamicNPIs& self) {
67+
return self.get_thresholds();
68+
})
69+
.def("set_threshold", [](mio::DynamicNPIs& self, double threshold, const std::vector<mio::DampingSampling>& v) {
70+
self.set_threshold(threshold, v);
71+
});
72+
}
73+
74+
} // namespace pymio
75+
76+
#endif //PYMIO_EPI_DYNAMIC_LOCKDOWN_H
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC)
3+
*
4+
* Authors: Maximilian Betz
5+
*
6+
* Contact: Martin J. Kuehn <[email protected]>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
#ifndef PYMIO_MOBILITY_IO_H
21+
#define PYMIO_MOBILITY_IO_H
22+
23+
#include "memilio/mobility/metapopulation_mobility_instant.h"
24+
#include "memilio/io/mobility_io.h"
25+
26+
#include "pybind11/pybind11.h"
27+
#include <cstddef>
28+
29+
namespace pymio
30+
{
31+
32+
template <class Model>
33+
void bind_write_graph(pybind11::module_& m)
34+
{
35+
m.def("write_graph", [&](const mio::Graph<Model, mio::MigrationParameters>& graph, const std::string& directory) {
36+
int ioflags = mio::IOF_None;
37+
mio::write_graph<Model>(graph, directory, ioflags);
38+
});
39+
}
40+
41+
} // namespace pymio
42+
43+
#endif //PYMIO_MOBILITY_IO_H
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC)
3+
*
4+
* Authors: Henrik Zunker, Maximilian Betz
5+
*
6+
* Contact: Martin J. Kuehn <[email protected]>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
#ifndef PYMIO_IO_RESULT_IO_H
21+
#define PYMIO_IO_RESULT_IO_H
22+
23+
#include "memilio/config.h"
24+
25+
#ifdef MEMILIO_HAS_HDF5
26+
27+
#include "memilio/io/result_io.h"
28+
29+
#include "pybind11/pybind11.h"
30+
31+
namespace pymio
32+
{
33+
34+
template <class Model>
35+
void bind_save_results(pybind11::module_& m)
36+
{
37+
m.def("save_results",
38+
[&](const std::vector<std::vector<mio::TimeSeries<double>>>& ensemble_results,
39+
const std::vector<std::vector<Model>>& ensemble_params, const std::vector<int>& county_ids,
40+
const std::string& result_dir, bool save_single_runs, bool save_percentiles) {
41+
boost::filesystem::path dir(result_dir);
42+
mio::save_results<Model>(ensemble_results, ensemble_params, county_ids, dir, save_single_runs,
43+
save_percentiles);
44+
return NULL;
45+
});
46+
}
47+
48+
} // namespace pymio
49+
50+
#endif // MEMILIO_HAS_HDF5
51+
52+
#endif //PYMIO_IO_RESULT_IO_H

pycode/memilio-simulation/memilio/simulation/pybind_util.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "memilio/math/matrix_shape.h"
2424
#include "pickle_serializer.h"
25+
#include "memilio/io/io.h"
2526

2627
#include "pybind11/pybind11.h"
2728

@@ -55,6 +56,21 @@ decltype(auto) pybind_pickle_class(pybind11::module_& m, const char* name)
5556
return pickle_class;
5657
}
5758

59+
template <typename T>
60+
T check_and_throw(mio::IOResult<T>& result)
61+
{
62+
if (result.has_error()) {
63+
auto status = result.error();
64+
if (status.code() == std::errc::no_such_file_or_directory) {
65+
throw pybind11::value_error(status.message());
66+
} else {
67+
throw std::runtime_error(status.message());
68+
}
69+
} else {
70+
return result.value();
71+
}
72+
}
73+
5874
// the following functions help bind class template realizations
5975
//https://stackoverflow.com/questions/64552878/how-can-i-automatically-bind-templated-member-functions-of-variadic-class-templa
6076
template <typename T>

pycode/memilio-simulation/memilio/simulation/secir.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* limitations under the License.
1919
*/
2020

21+
#include "memilio/config.h"
2122
#include "pybind_util.h"
2223
#include "compartments/simulation.h"
2324
#include "compartments/compartmentalmodel.h"
@@ -27,12 +28,19 @@
2728
#include "utils/index.h"
2829
#include "mobility/graph_simulation.h"
2930
#include "mobility/metapopulation_mobility_instant.h"
31+
#include "io/mobility_io.h"
32+
#include "io/result_io.h"
3033
#include "ode_secir/model.h"
3134
#include "ode_secir/analyze_result.h"
3235
#include "ode_secir/parameter_space.h"
36+
#include "ode_secir/parameters_io.h"
3337
#include "memilio/compartments/parameter_studies.h"
38+
#include "memilio/mobility/graph.h"
39+
#include "memilio/io/mobility_io.h"
40+
#include "memilio/io/epi_data.h"
3441
#include "Eigen/Core"
3542
#include "pybind11/stl_bind.h"
43+
3644
#include <vector>
3745

3846
namespace py = pybind11;
@@ -124,6 +132,15 @@ void bind_ParameterStudy(py::module_& m, std::string const& name)
124132
});
125133
}
126134

135+
enum class ContactLocation
136+
{
137+
Home = 0,
138+
School,
139+
Work,
140+
Other,
141+
Count,
142+
};
143+
127144
using Simulation = mio::osecir::Simulation<>;
128145
using MigrationGraph = mio::Graph<mio::SimulationNode<Simulation>, mio::MigrationEdge>;
129146

@@ -226,6 +243,82 @@ PYBIND11_MODULE(_simulation_secir, m)
226243
},
227244
py::arg("model"));
228245

246+
// These functions are in general not secir dependent, only with the current config
247+
m.def(
248+
"set_nodes",
249+
[](const mio::osecir::Parameters& params, mio::Date start_date, mio::Date end_date, const std::string& data_dir,
250+
const std::string& population_data_path, bool is_node_for_county,
251+
mio::Graph<mio::osecir::Model, mio::MigrationParameters>& params_graph,
252+
const std::vector<double>& scaling_factor_inf, double scaling_factor_icu, double tnt_capacity_factor,
253+
int num_days = 0, bool export_time_series = false) {
254+
auto result = mio::set_nodes<mio::osecir::TestAndTraceCapacity, mio::osecir::ContactPatterns,
255+
mio::osecir::Model, mio::MigrationParameters, mio::osecir::Parameters,
256+
decltype(mio::osecir::read_input_data_county<mio::osecir::Model>),
257+
decltype(mio::get_node_ids)>(
258+
params, start_date, end_date, data_dir, population_data_path, is_node_for_county, params_graph,
259+
mio::osecir::read_input_data_county<mio::osecir::Model>, mio::get_node_ids, scaling_factor_inf,
260+
scaling_factor_icu, tnt_capacity_factor, num_days, export_time_series);
261+
return pymio::check_and_throw(result);
262+
},
263+
py::return_value_policy::move);
264+
265+
pymio::iterable_enum<ContactLocation>(m, "ContactLocation")
266+
.value("Home", ContactLocation::Home)
267+
.value("School", ContactLocation::School)
268+
.value("Work", ContactLocation::Work)
269+
.value("Other", ContactLocation::Other);
270+
271+
m.def(
272+
"set_edges",
273+
[](const std::string& data_dir, mio::Graph<mio::osecir::Model, mio::MigrationParameters>& params_graph,
274+
size_t contact_locations_size) {
275+
auto migrating_comp = {mio::osecir::InfectionState::Susceptible, mio::osecir::InfectionState::Exposed,
276+
mio::osecir::InfectionState::InfectedNoSymptoms,
277+
mio::osecir::InfectionState::InfectedSymptoms,
278+
mio::osecir::InfectionState::Recovered};
279+
auto weights = std::vector<ScalarType>{0., 0., 1.0, 1.0, 0.33, 0., 0.};
280+
auto result = mio::set_edges<ContactLocation, mio::osecir::Model, mio::MigrationParameters,
281+
mio::MigrationCoefficientGroup, mio::osecir::InfectionState,
282+
decltype(mio::read_mobility_plain)>(
283+
data_dir, params_graph, migrating_comp, contact_locations_size, mio::read_mobility_plain, weights);
284+
return pymio::check_and_throw(result);
285+
},
286+
py::return_value_policy::move);
287+
288+
#ifdef MEMILIO_HAS_HDF5
289+
pymio::bind_save_results<mio::osecir::Model>(m);
290+
#endif // MEMILIO_HAS_HDF5
291+
292+
#ifdef MEMILIO_HAS_JSONCPP
293+
pymio::bind_write_graph<mio::osecir::Model>(m);
294+
m.def(
295+
"read_input_data_county",
296+
[](std::vector<mio::osecir::Model>& model, mio::Date date, const std::vector<int>& county,
297+
const std::vector<double>& scaling_factor_inf, double scaling_factor_icu, const std::string& dir,
298+
int num_days = 0, bool export_time_series = false) {
299+
auto result = mio::osecir::read_input_data_county<mio::osecir::Model>(
300+
model, date, county, scaling_factor_inf, scaling_factor_icu, dir, num_days, export_time_series);
301+
return pymio::check_and_throw(result);
302+
},
303+
py::return_value_policy::move);
304+
305+
m.def(
306+
"get_node_ids",
307+
[](const std::string& path, bool is_node_for_county) {
308+
auto result = mio::get_node_ids(path, is_node_for_county);
309+
return pymio::check_and_throw(result);
310+
},
311+
py::return_value_policy::move);
312+
#endif // MEMILIO_HAS_JSONCPP
313+
314+
m.def(
315+
"read_mobility_plain",
316+
[](const std::string& filename) {
317+
auto result = mio::read_mobility_plain(filename);
318+
return pymio::check_and_throw(result);
319+
},
320+
py::return_value_policy::move);
321+
229322
m.def("interpolate_simulation_result",
230323
py::overload_cast<const MigrationGraph&>(&mio::interpolate_simulation_result<Simulation>));
231324

pycode/memilio-simulation/memilio/simulation/simulation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "epidemiology/contact_matrix.h"
2424
#include "epidemiology/damping_sampling.h"
2525
#include "epidemiology/uncertain_matrix.h"
26+
#include "epidemiology/dynamic_npis.h"
2627
#include "mobility/metapopulation_mobility_instant.h"
2728
#include "utils/date.h"
2829
#include "utils/logging.h"
@@ -95,6 +96,8 @@ PYBIND11_MODULE(_simulation, m)
9596
auto migration_coeff_group_class = py::class_<mio::MigrationCoefficientGroup>(m, "MigrationCoefficientGroup");
9697
pymio::bind_damping_expression_group_members(migration_coeff_group_class);
9798

99+
pymio::bind_dynamicNPI_members(m, "DynamicNPIs");
100+
98101
pymio::bind_migration_parameters(m, "MigrationParameters");
99102
pymio::bind_migration_parameter_edge(m, "MigrationParameterEdge");
100103
pymio::bind_migration(m, "Migration");

0 commit comments

Comments
 (0)