Skip to content

Commit 1369cac

Browse files
committed
Merge branch 'main' of github.com:SciCompMod/memilio-tutorials
2 parents bb5a226 + b3c3212 commit 1369cac

6 files changed

Lines changed: 48 additions & 32 deletions

File tree

cpp-tutorials/exercises/exercise03.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ int main()
4848
// all currently active dampings of one level and different types are summed up. If two dampings have different
4949
// levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping`
5050
// of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced
51-
// by 10% and 40%, respectively. To always retain a minimum level of contacts, a minimum contact frequency can
51+
// by 90% and 60%, respectively. To always retain a minimum level of contacts, a minimum contact frequency can
5252
// be set that is never deceeded. In our example we set this minimum contact rate to 0.
5353
contact_matrix[0].add_damping(0.9, mio::SimulationTime<ScalarType>(10.));
5454
contact_matrix[0].add_damping(0.6, mio::SimulationTime<ScalarType>(20.));
5555

56-
//EXERCISE: Please create a damping that replaces the 10% reduction after 10 days by a 20% reduction. Additionally, add a damping after 40 days that increases the contact rate by 50%.
56+
//EXERCISE: Please create a damping that replaces the 90% reduction after 10 days by a 20% reduction. Additionally, add a damping after 40 days that increases the contact rate by 50%.
5757

5858
// Again, we start with 0.5% of the population initially in `Exposed` and 0.5% initially in `InfectedNoSymptoms`
5959
// while the remaining 99% is `Susceptible`.

cpp-tutorials/tutorial03.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int main()
4646
// all currently active dampings of one level and different types are summed up. If two dampings have different
4747
// levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping`
4848
// of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced
49-
// by 10% and 40%, respectively. To always retain a minimum level of contacts, a minimum contact frequency can
49+
// by 90% and 60%, respectively. To always retain a minimum level of contacts, a minimum contact frequency can
5050
// be set that is never deceeded. In our example we set this minimum contact rate to 0.
5151
contact_matrix[0].add_damping(0.9, mio::SimulationTime<ScalarType>(10.));
5252
contact_matrix[0].add_damping(0.6, mio::SimulationTime<ScalarType>(20.));

exercises/exercise02.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,14 @@ def _(np):
7676
model.parameters.DeathsPerCritical[group] = 0.3
7777

7878
# Set contact frequency
79-
model.parameters.ContactPatterns.cont_freq_mat[0].baseline = np.ones((1, 1)) * 10
79+
model.parameters.ContactPatterns.cont_freq_mat[0].baseline = np.ones(
80+
(1, 1)) * 10
8081

8182
# Initialize compartments
82-
model.populations[group, osecir.InfectionState.Exposed] = 0.005 * total_population
83-
model.populations[group, osecir.InfectionState.InfectedNoSymptoms] = 0.005 * total_population
83+
model.populations[group,
84+
osecir.InfectionState.Exposed] = 0.005 * total_population
85+
model.populations[group,
86+
osecir.InfectionState.InfectedNoSymptoms] = 0.005 * total_population
8487
model.populations.set_difference_from_total(
8588
(group, osecir.InfectionState.Susceptible), total_population)
8689
return dt, model, osecir, t0, tmax
@@ -122,7 +125,8 @@ def _(dt, model, osecir, t0, tmax):
122125

123126
@app.cell
124127
def _(results):
125-
compartments = results[0] # The first element of results contains the compartment data
128+
# The first element of results contains the compartment data
129+
compartments = results[0]
126130
flows = results[1] # The second element of results contains the flow data
127131
return compartments, flows
128132

@@ -162,7 +166,6 @@ def _(flows, np, osecir):
162166
plot_time = time_days[1:]
163167

164168
print(flow_array.shape)
165-
print("ji")
166169
return daily_flows, plot_time
167170

168171

@@ -196,12 +199,13 @@ def _(mo):
196199
def _(compartments, daily_flows, osecir, plot_time, plt):
197200
# 1. Prepare compartment data for comparison
198201
# Interpolate to match the time grid of our flows
199-
comp_array = osecir.interpolate_simulation_result(compartments).as_ndarray()
202+
comp_array = osecir.interpolate_simulation_result(
203+
compartments).as_ndarray()
200204

201205
# Extract the "InfectedSevere" compartment (Currently Hospitalized)
202206
# Adding 1 because row 0 is the time axis
203207
state_severe_idx = 1 + int(osecir.InfectionState.InfectedSevere)
204-
current_severe = comp_array[state_severe_idx, 1:]
208+
current_severe = comp_array[state_severe_idx, 1:]
205209

206210
# 2. Flow indices
207211
new_symptomatic_idx = 2
@@ -216,8 +220,10 @@ def _(compartments, daily_flows, osecir, plot_time, plt):
216220
fig, ax = plt.subplots(1, 2, figsize=(14, 6))
217221

218222
# --- Subplot 1: Disease Progression (The Time Lag) ---
219-
ax[0].bar(plot_time, daily_flows[new_symptomatic_idx, :], color='coral', alpha=0.5, label='New Symptomatic Cases')
220-
ax[0].bar(plot_time, daily_flows[new_hospitalized_idx, :], color='darkred', alpha=0.8, label='New Hospitalizations')
223+
ax[0].bar(plot_time, daily_flows[new_symptomatic_idx, :],
224+
color='coral', alpha=0.5, label='New Symptomatic Cases')
225+
ax[0].bar(plot_time, daily_flows[new_hospitalized_idx, :],
226+
color='darkred', alpha=0.8, label='New Hospitalizations')
221227
# EXERCISE: Extend subplot 1 to also show new ICU admissions.
222228
# Hint: add a third bar for daily_flows[new_icu_idx, :] with a suitable color and label,
223229
# e.g. color='maroon', alpha=0.9, label='New ICU Admissions'.
@@ -228,14 +234,16 @@ def _(compartments, daily_flows, osecir, plot_time, plt):
228234

229235
# --- Subplot 2: Incidence vs. Bed Occupancy ---
230236
# Axis 1: Daily New Cases (Incidence)
231-
ax[1].bar(plot_time, daily_flows[new_hospitalized_idx, :], color='steelblue', alpha=0.5, label='Daily Admissions (Incidence)')
237+
ax[1].bar(plot_time, daily_flows[new_hospitalized_idx, :],
238+
color='steelblue', alpha=0.5, label='Daily Admissions (Incidence)')
232239
ax[1].set_xlabel('Time [days]')
233240
ax[1].set_ylabel('Daily New Hospitalizations [#]', color='steelblue')
234241
ax[1].tick_params(axis='y', labelcolor='steelblue')
235242

236243
# Axis 2: Current Occupancy
237244
ax2 = ax[1].twinx()
238-
ax2.plot(plot_time, current_severe, color='black', linewidth=3, label='Currently Hospitalized')
245+
ax2.plot(plot_time, current_severe, color='black',
246+
linewidth=3, label='Currently Hospitalized')
239247
ax2.set_ylabel('Total Hospital Bed Occupancy [#]', color='black')
240248
ax2.tick_params(axis='y', labelcolor='black')
241249

exercises/exercise03.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def _():
105105
@app.cell
106106
def _(mo):
107107
mo.md(r"""
108-
After the model initialization, we add a contact reduction (`Damping`) that represents an NPI like e.g. mask wearing or social distancing. Dampings are a factor applied to the contact frequency and can be added to the model at fixed simulation time points before simulating. They have a *Level* and a *Type*. A damping with a given level and type replaces the previously active one with the same level and type, while all currently active dampings of one level and different types are summed up. If two dampings have different levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping` of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced by 10% and 40%, respectively. In general, it is also possible to increase the contact rate by using Damping values greater than 1. To always retain a minimum level of contacts, a minimum contact frequency can be set that is never deceeded. In our example we set this minimum contact rate to 0.
108+
After the model initialization, we add a contact reduction (`Damping`) that represents an NPI like e.g. mask wearing or social distancing. Dampings are a factor applied to the contact frequency and can be added to the model at fixed simulation time points before simulating. They have a *Level* and a *Type*. A damping with a given level and type replaces the previously active one with the same level and type, while all currently active dampings of one level and different types are summed up. If two dampings have different levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping` of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced by 90% and 60%, respectively. In general, it is also possible to increase the contact rate by using negative Damping values. To always retain a minimum level of contacts, a minimum contact frequency can be set that is never deceeded. In our example we set this minimum contact rate to 0.
109109
""")
110110
return
111111

@@ -115,9 +115,9 @@ def _(Damping, model, np):
115115
# Set minimum contact frequency
116116
model.parameters.ContactPatterns.cont_freq_mat[0].minimum = np.zeros((1, 1))
117117

118-
# Add contact reduction by 10% after 10 days
118+
# Add contact reduction by 90% after 10 days
119119
model.parameters.ContactPatterns.cont_freq_mat.add_damping(Damping(coeffs=np.ones((1, 1)) * 0.9, t=10.0, level=0, type=0))
120-
# Add contact reduction by 40% after 20 days
120+
# Add contact reduction by 60% after 20 days
121121
model.parameters.ContactPatterns.cont_freq_mat.add_damping(Damping(coeffs=np.ones((1, 1)) * 0.6, t=20.0, level=0, type=0))
122122
return
123123

@@ -126,7 +126,7 @@ def _(Damping, model, np):
126126
def _(mo):
127127
mo.md(r"""
128128
### Exercise
129-
Please create a damping that replaces the 10% reduction after 10 days by a 20% reduction. Additionally, add a damping after 40 days that increases the contact rate by 50%.
129+
Please create a damping that replaces the 90% reduction after 10 days by a 20% reduction. Additionally, add a damping after 40 days that increases the contact rate by 50%.
130130
""")
131131
return
132132

tutorial02.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,14 @@ def _(np):
7676
model.parameters.DeathsPerCritical[group] = 0.3
7777

7878
# Set contact frequency
79-
model.parameters.ContactPatterns.cont_freq_mat[0].baseline = np.ones((1, 1)) * 10
79+
model.parameters.ContactPatterns.cont_freq_mat[0].baseline = np.ones(
80+
(1, 1)) * 10
8081

8182
# Initialize compartments
82-
model.populations[group, osecir.InfectionState.Exposed] = 0.005 * total_population
83-
model.populations[group, osecir.InfectionState.InfectedNoSymptoms] = 0.005 * total_population
83+
model.populations[group,
84+
osecir.InfectionState.Exposed] = 0.005 * total_population
85+
model.populations[group,
86+
osecir.InfectionState.InfectedNoSymptoms] = 0.005 * total_population
8487
model.populations.set_difference_from_total(
8588
(group, osecir.InfectionState.Susceptible), total_population)
8689
return dt, model, osecir, t0, tmax
@@ -123,7 +126,8 @@ def _(dt, model, osecir, t0, tmax):
123126

124127
@app.cell
125128
def _(results):
126-
compartments = results[0] # The first element of results contains the compartment data
129+
# The first element of results contains the compartment data
130+
compartments = results[0]
127131
flows = results[1] # The second element of results contains the flow data
128132
return compartments, flows
129133

@@ -163,7 +167,6 @@ def _(flows, np, osecir):
163167
plot_time = time_days[1:]
164168

165169
print(flow_array.shape)
166-
print("ji")
167170
return daily_flows, plot_time
168171

169172

@@ -197,12 +200,13 @@ def _(mo):
197200
def _(compartments, daily_flows, osecir, plot_time, plt):
198201
# 1. Prepare compartment data for comparison
199202
# Interpolate to match the time grid of our flows
200-
comp_array = osecir.interpolate_simulation_result(compartments).as_ndarray()
203+
comp_array = osecir.interpolate_simulation_result(
204+
compartments).as_ndarray()
201205

202206
# Extract the "InfectedSevere" compartment (Currently Hospitalized)
203207
# Adding 1 because row 0 is the time axis
204208
state_severe_idx = 1 + int(osecir.InfectionState.InfectedSevere)
205-
current_severe = comp_array[state_severe_idx, 1:]
209+
current_severe = comp_array[state_severe_idx, 1:]
206210

207211
# 2. Flow indices
208212
new_symptomatic_idx = 2
@@ -212,23 +216,27 @@ def _(compartments, daily_flows, osecir, plot_time, plt):
212216
fig, ax = plt.subplots(1, 2, figsize=(14, 6))
213217

214218
# --- Subplot 1: Disease Progression (The Time Lag) ---
215-
ax[0].bar(plot_time, daily_flows[new_symptomatic_idx, :], color='coral', alpha=0.5, label='New Symptomatic Cases')
216-
ax[0].bar(plot_time, daily_flows[new_hospitalized_idx, :], color='darkred', alpha=0.8, label='New Hospitalizations')
219+
ax[0].bar(plot_time, daily_flows[new_symptomatic_idx, :],
220+
color='coral', alpha=0.5, label='New Symptomatic Cases')
221+
ax[0].bar(plot_time, daily_flows[new_hospitalized_idx, :],
222+
color='darkred', alpha=0.8, label='New Hospitalizations')
217223
ax[0].set_title('Disease Progression: Infection to Hospitalization')
218224
ax[0].set_xlabel('Time [days]')
219225
ax[0].set_ylabel('Daily New Cases [#]')
220226
ax[0].legend()
221227

222228
# --- Subplot 2: Incidence vs. Bed Occupancy ---
223229
# Axis 1: Daily New Cases (Incidence)
224-
ax[1].bar(plot_time, daily_flows[new_hospitalized_idx, :], color='steelblue', alpha=0.5, label='Daily Admissions (Incidence)')
230+
ax[1].bar(plot_time, daily_flows[new_hospitalized_idx, :],
231+
color='steelblue', alpha=0.5, label='Daily Admissions (Incidence)')
225232
ax[1].set_xlabel('Time [days]')
226233
ax[1].set_ylabel('Daily New Hospitalizations [#]', color='steelblue')
227234
ax[1].tick_params(axis='y', labelcolor='steelblue')
228235

229236
# Axis 2: Current Occupancy
230237
ax2 = ax[1].twinx()
231-
ax2.plot(plot_time, current_severe, color='black', linewidth=3, label='Currently Hospitalized')
238+
ax2.plot(plot_time, current_severe, color='black',
239+
linewidth=3, label='Currently Hospitalized')
232240
ax2.set_ylabel('Total Hospital Bed Occupancy [#]', color='black')
233241
ax2.tick_params(axis='y', labelcolor='black')
234242

tutorial03.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def _(AgeGroup, np, osecir):
9090
@app.cell
9191
def _(mo):
9292
mo.md(r"""
93-
After the model initialization, we add a contact reduction (`Damping`) that represents an NPI like e.g. mask wearing or social distancing. Dampings are a factor applied to the contact frequency and can be added to the model at fixed simulation time points before simulating. They have a *Level* and a *Type*. A damping with a given level and type replaces the previously active one with the same level and type, while all currently active dampings of one level and different types are summed up. If two dampings have different levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping` of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced by 10% and 40%, respectively. In general, it is also possible to increase the contact rate by using negative Damping values. To always retain a minimum level of contacts, a minimum contact frequency can be set that is never deceeded. In our example we set this minimum contact rate to 0.
93+
After the model initialization, we add a contact reduction (`Damping`) that represents an NPI like e.g. mask wearing or social distancing. Dampings are a factor applied to the contact frequency and can be added to the model at fixed simulation time points before simulating. They have a *Level* and a *Type*. A damping with a given level and type replaces the previously active one with the same level and type, while all currently active dampings of one level and different types are summed up. If two dampings have different levels (independent of the type) they are combined multiplicatively. In the following we apply a `Damping` of 0.9 after 10 days and another damping of 0.6 after 20 days which means that the contacts are reduced by 90% and 60%, respectively. In general, it is also possible to increase the contact rate by using negative Damping values. To always retain a minimum level of contacts, a minimum contact frequency can be set that is never deceeded. In our example we set this minimum contact rate to 0.
9494
""")
9595
return
9696

@@ -100,9 +100,9 @@ def _(Damping, model, np):
100100
# Set minimum contact frequency
101101
model.parameters.ContactPatterns.cont_freq_mat[0].minimum = np.zeros((1, 1))
102102

103-
# Add contact reduction by 10% after 10 days
103+
# Add contact reduction by 90% after 10 days
104104
model.parameters.ContactPatterns.cont_freq_mat.add_damping(Damping(coeffs=np.ones((1, 1)) * 0.9, t=10.0, level=0, type=0))
105-
# Add contact reduction by 40% after 20 days
105+
# Add contact reduction by 60% after 20 days
106106
model.parameters.ContactPatterns.cont_freq_mat.add_damping(Damping(coeffs=np.ones((1, 1)) * 0.6, t=20.0, level=0, type=0))
107107
return
108108

0 commit comments

Comments
 (0)