21 KiB
Reminder: Do not rename this file (or allow your computer to do that)¶
Please overwrite the original exercise release file(s) when uploading your assignment. I still had to fix some of your submissions last week.
# You must run this cell, but you can ignore its contents.
import hashlib
def ads_hash(ty):
"""Return a unique string for input"""
ty_str = str(ty).encode()
m = hashlib.sha256()
m.update(ty_str)
return m.hexdigest()[:10]
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
assert ads_hash(is_over10(9)) == '60a33e6cf5'
assert ads_hash(is_over10(9.9999)) == '60a33e6cf5'
assert ads_hash(is_over10(11)) == '3cbc87c768'
assert ads_hash(is_over10(10.000001)) == '3cbc87c768'
Q2¶
Write a function called is_over_a
which accepts two input arguments x
(the first argument) and a
(the second argument). The function should return the boolean True
if x
is greater to or equal than a
. Otherwise the function should return False
.
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
assert ads_hash(is_over_a(9,10)) == '60a33e6cf5'
assert ads_hash(is_over_a(9.9999,10)) == '60a33e6cf5'
assert ads_hash(is_over_a(10,10)) == '3cbc87c768'
assert ads_hash(is_over_a(11,10)) == '3cbc87c768'
assert ads_hash(is_over_a(10.000001,10)) == '3cbc87c768'
assert ads_hash(is_over_a(-9,-10)) == '3cbc87c768'
assert ads_hash(is_over_a(-9,10)) == '60a33e6cf5'
Flow control - while
loops using $R_t$, the effective reproduction number¶
To make our examples more interesting, we are going to use some concepts from epidemiology. We will perform some simple epidemiological modeling of disease spread. First, let's define $R_t$, the effective reproduction number. This is the the average number of new infections caused by a single infected individual at time $t$ in a partially susceptible population.
Let's do some simulations to understand the effect different $R_t$ values would have.
Consider this python code:
Rt = 1.5
infected = 1
num_generations = 0
while infected < 1000:
infected = infected*Rt
num_generations += 1
print(f"It took {num_generations} generations to reach 1000 infected")
If we wanted to write this using mathematical notation, we would write this as
$N_{t+1} = R_t N_t$
where $N_t$ is the number of infected individuals at generation $t$ and $N_{t+1}$ is the number of infected individuals at the next generation ($t+1$).
What is a "generation"? What we call "generation" here is called the serial interval (SI) in the scientific literature. According to this paper, "the serial interval (SI), defined as the time between disease symptom onset of a case and that of its infector, is a surrogate for the generation interval— an unobservable quantity defined as the time between the infection of a case and the time of infection of its infector."
With regard to SARS-CoV-2 in Germany, according to the Corona-Warn-App FAQ (Section "App Features" / "Other features" / "In-App statistics"), "The concept of the R-value and the data basis of its calculation is described in detail in the Epidemiological Bulletin of the RKI (#17/2020 of 04/23/2020). Sample calculations and the daily updated R-values (4-day and 7-day R-value) are available as an Excel table at http://www.rki.de/covid-19-nowcasting." The data from 2 March 2020 to 17 June 2023 are available at github.com/robert-koch-institut/SARS-CoV-2-Nowcastingund-R-Schaetzung.
Here is a guide to R from July 2020.
Q1¶
Modify the code above so that you create a variable called generations_to_1000
which has the number of generations required for 1 person to reach 1000 people infected.
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
assert ads_hash(generations_to_1000)=='4ec9599fc2'
Q2¶
Now create a function called find_cycles_to_reach_1000
which takes 1 argument, Rt
. This function should return the number of cycles required to reach 1000 infected people.
Your function signature should look like this:
def find_generations_to_reach_1000(Rt):
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
assert ads_hash(find_generations_to_reach_1000(1.1))=='96061e92f5'
assert ads_hash(find_generations_to_reach_1000(1.5))=='4ec9599fc2'
assert ads_hash(find_generations_to_reach_1000(2.0))=='4a44dc1536'
Q3¶
Now create a function called simulate_generation
which takes two arguments, a
and Rt
. This function should return None
. The first argument a
will be a list with the number of infected individuals and Rt
is the effective reproduction number, as before. The function should compute the number of newly infected individuals after one generation and append this to the list passed as the first argument.
Your function signature should look like this:
def simulate_generation(a,Rt):
Here is an example that works:
b = [1]
simulate_generation(b,3)
simulate_generation(b,3)
simulate_generation(b,3)
b
In this above example, b
would be equal to [1, 3, 9, 27]
at the end.
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
aa = [1]
assert ads_hash(simulate_generation(aa, 22)) == 'dc937b5989'
assert ads_hash(aa)=='c7e4ccf872'
Q4¶
Now create a function called calculate_timeseries_to_1000
which takes one argument, Rt
. This function should return a list containing the number of infected individuals after each cycle up to and including the first value over 1000 individuals.
Your function signature should look like this:
def calculate_timeseries_to_1000(Rt):
Your code should work so that calculate_timeseries_to_1000(2)
would return [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
and that calculate_timeseries_to_1000(3)
would return [1, 3, 9, 27, 81, 243, 729, 2187]
.
# YOUR CODE HERE
raise NotImplementedError()
assert ads_hash(calculate_timeseries_to_1000(2))=='a9ad958975'
assert ads_hash(calculate_timeseries_to_1000(3))=='7aa0d3bbca'
Bonus - plotting the results¶
Let's now see the result of these simulations.
# Below, we will use matplotlib, so we need to import it here.
import matplotlib.pyplot as plt
plt.plot(calculate_timeseries_to_1000(1.1), label="$R_t$ = 1.1")
plt.plot(calculate_timeseries_to_1000(1.5), label="$R_t$ = 1.5")
plt.plot(calculate_timeseries_to_1000(2.0), label="$R_t$ = 2.0")
plt.xlabel("cycles")
plt.ylabel("number of infected individuals")
plt.legend();
String formatting¶
Remember from lecture various ways of formatting strings with template in Python. We are going to use f-strings here.
Here is an example:
city="Freiburg"
continent="Europe"
result = f"The city {city} is in the continent {continent}"
This will set result
to 'The city Freiburg is in the continent Europe'
.
Q1¶
Create a function named greeting
which takes two arguments, name
and age
. It should return a string with these values inserted in to a string so that when called like
result = greeting("Andrew",7)
result
will be 'Hello. My name is Andrew. My age is 7'
.
The function signature will be
def greeting(name, age):
# YOUR CODE HERE
raise NotImplementedError()
# If this runs without error, it means the answer in your previous cell was correct.
assert ads_hash(greeting("Andrew",7))=='1370611a0d'
assert ads_hash(greeting("Bob",47))=='3b8fd03444'
Running Python from the terminal¶
Q1¶
Create a Python script called my_name.py
which does two things:
1) prints your name 2) computes the value of 1001 * 22 and then prints this
Final upload of your assignment today¶
When you upload your assignnment, you should upload:
- This
1__Flow_control_Plotting_Strings.ipynb
notebook file as you completed it. Remember not to change its name. - The Python script
my_name.py
which does the correct actions. Both these files should be placed in therelease/exercise-04
directory.