From c3ef0bae00ca44bb9f2cbfd2d5a8948d437abe5f Mon Sep 17 00:00:00 2001 From: cotswoldsmaker Date: Tue, 26 Mar 2024 20:28:41 +0000 Subject: [PATCH] Update lesson 1 exercises and answers --- _site/module-1/slides/3-python-basics.html | 127 +++++++++++------- _site/search.json | 11 +- module-1/hands-on/.streamlit/config.toml | 9 ++ module-1/hands-on/answers/lesson_2_anwers.py | 25 ++-- module-1/hands-on/answers/lesson_3_answers.py | 100 ++++++++++++++ module-1/hands-on/lesson_1.py | 31 +++-- module-1/hands-on/lesson_2.py | 124 ++++++++++++----- module-1/hands-on/lesson_3.py | 69 ++++++++++ module-1/slides/3-python-basics.qmd | 40 ++++-- module-1/slides/4-lets-build.qmd | 13 ++ requirements.txt | 1 + 11 files changed, 431 insertions(+), 119 deletions(-) create mode 100644 module-1/hands-on/.streamlit/config.toml create mode 100644 module-1/hands-on/answers/lesson_3_answers.py create mode 100644 module-1/hands-on/lesson_3.py create mode 100644 module-1/slides/4-lets-build.qmd create mode 100644 requirements.txt diff --git a/_site/module-1/slides/3-python-basics.html b/_site/module-1/slides/3-python-basics.html index 5d0a47c..555d6e3 100644 --- a/_site/module-1/slides/3-python-basics.html +++ b/_site/module-1/slides/3-python-basics.html @@ -654,6 +654,35 @@

Naming conventions

+
+

Comments

+ +
+
+
comments.py
+
+
# This is a single line comment
+a_string = "a string"
+
+""" Double quotation mark multiline comment
+    Here is some more of the comment
+"""
+def i_am_a_function():
+    return True
+
+''' Single quotation mark multiline comment
+    Here is some more of the comment
+'''
+def i_am_another_function():
+    return True
+
+

Basic Operators

Control flow - for loops

@@ -708,10 +737,10 @@

Control flow - for loops

for_loop.py
-
list_of_numbers = [1, 2, 3, 4, 5]
-
-for number in list_of_numbers:
-    print(number)
+
list_of_numbers = [1, 2, 3, 4, 5]
+
+for number in list_of_numbers:
+    print(number)

Output

    1
@@ -726,11 +755,11 @@ 

Control flow - while loops

while_loop.py
-
count = 1
-
-while count <= 5:
-    print(count)
-    count += 1
+
count = 1
+
+while count <= 5:
+    print(count)
+    count += 1

Output

    1
@@ -754,13 +783,13 @@ 

Functions (methods)

functions.py
-
def name_of_function(argument_1, argument_2):
-    a_variable = argument_1 + argument_2
-    another_variable = "a return value"
-
-    print (a_variable)
-
-    return another_variable
+
def name_of_function(argument_1, argument_2):
+    a_variable = argument_1 + argument_2
+    another_variable = "a return value"
+
+    print (a_variable)
+
+    return another_variable
@@ -796,12 +825,12 @@

Error Handling

functions.py
-
try:
-    variable = 1 + "a"
-except:
-    print("I knew that you could not add an integer and a string!")
-else:
-    print("Somehow I did not get an error!")
+
try:
+    variable = 1 + "a"
+except:
+    print("I knew that you could not add an integer and a string!")
+else:
+    print("Somehow I did not get an error!")

Output

    I knew that you could not add an integer and a string!
@@ -843,27 +872,27 @@

Compare the Traceback to the code

functions.py
-
class FruitPrices:
-    def __init__(self):
-        self.prices = {"apple": 1.55, "banana": 2.44}
-
-    def get_price(self, fruit):
-        return self._price(fruit)
-
-    def _price(self, fruit):
-        return self.prices[fruit]
-
-
-fruit_prices = FruitPrices()
-
-print(fruit_prices.get_price("pear")) # 'pear' key does not exist!
+
class FruitPrices:
+    def __init__(self):
+        self.prices = {"apple": 1.55, "banana": 2.44}
+
+    def get_price(self, fruit):
+        return self._price(fruit)
+
+    def _price(self, fruit):
+        return self.prices[fruit]
+
+
+fruit_prices = FruitPrices()
+
+print(fruit_prices.get_price("pear")) # 'pear' key does not exist!

You got all that?

    -
  • Now it is your turn
  • -
  • Time for some hands on coding in Lesson 2
  • +
  • Now it is your turn.
  • +
  • Time for some hands on coding in Lesson 2.
diff --git a/_site/search.json b/_site/search.json index 7785711..d60c6d7 100644 --- a/_site/search.json +++ b/_site/search.json @@ -879,7 +879,7 @@ "href": "module-1/slides/3-python-basics.html#control-flow---if-statements", "title": "Python basics", "section": "Control flow - if statements", - "text": "Control flow - if statements\n\n\nif_statement.py\n\nsky = \"dark\"\n\nif sky == \"blue\":\n time_of_day = \"day time\"\nelif sky == \"grey\"\n time_of_day = \"dusk or dawn\"\nelse:\n time_of_day = \"night time\"\n\nprint(\"Time of day is: \", time_of_day)\n\nOutput\n Time of day is: night time" + "text": "Control flow - if statements\n\n\nif_statement.py\n\npatient_allergy = \"amoxicillin\"\n\nif patient_allergy == \"amoxicillin\":\n allergy_group = \"penicillins\"\nelif patient_allergy == \"tazocin\":\n allergy_group = \"penicillins\"\nelse:\n allergy_group = \"others\"\n\nprint(\"Patient is allergic to\", allergy_group)\n\nOutput\n Patient is allergic to penicillins" }, { "objectID": "module-1/slides/3-python-basics.html#control-flow---for-loops", @@ -949,7 +949,7 @@ "href": "module-1/slides/3-python-basics.html#you-got-all-that", "title": "Python basics", "section": "You got all that?", - "text": "You got all that?\n\nNow it is your turn\nTime for some hands on coding in Lesson 2" + "text": "You got all that?\n\nNow it is your turn.\nTime for some hands on coding in Lesson 2." }, { "objectID": "module-1/slides/3-python-basics.html#computers-are-pedantic", @@ -957,5 +957,12 @@ "title": "Python basics", "section": "Computers are pedantic!", "text": "Computers are pedantic!\n\nRemember that computers think in True and False, e.g. 1 and 0s. They are literal thinkers.\nEven one character being out of place can break an entire code base. So watch out for that unpaired quotation mark, look out for that space that should not be there, and make sure you match your indentiations to your if statements.\nNow go have some fun in your tutor groups with hands-on coding and debugging." + }, + { + "objectID": "module-1/slides/3-python-basics.html#comments", + "href": "module-1/slides/3-python-basics.html#comments", + "title": "Python basics", + "section": "Comments", + "text": "Comments\n\nComments are useful in explaining what code is supposed to do.\nThey are essential for when you, and others, need to read your code later to problem solve or add to your code.\nUse them sparingly, as they can clutter code.\nTry and make variable and function names self explanatory.\nYou can comment with the hastag or encapsulate with triple quotation marks:\n\n\n\ncomments.py\n\n# This is a single line comment\na_string = \"a string\"\n\n\"\"\" Double quotation mark multiline comment\n Here is some more of the comment\n\"\"\"\ndef i_am_a_function():\n return True\n\n''' Single quotation mark multiline comment\n Here is some more of the comment\n'''\ndef i_am_another_function():\n return True" } ] \ No newline at end of file diff --git a/module-1/hands-on/.streamlit/config.toml b/module-1/hands-on/.streamlit/config.toml new file mode 100644 index 0000000..ca2fcae --- /dev/null +++ b/module-1/hands-on/.streamlit/config.toml @@ -0,0 +1,9 @@ +[theme] +primaryColor="#F63366" +backgroundColor="#FFFFFF" +secondaryBackgroundColor="#F0F2F6" +textColor="#000000" +codeColor="#000000" + +[runner] +magicEnabled = false \ No newline at end of file diff --git a/module-1/hands-on/answers/lesson_2_anwers.py b/module-1/hands-on/answers/lesson_2_anwers.py index 5cd0496..5ac27b0 100644 --- a/module-1/hands-on/answers/lesson_2_anwers.py +++ b/module-1/hands-on/answers/lesson_2_anwers.py @@ -1,22 +1,27 @@ """ Lesson 1 answers""" -def statement(question, answer) -> bool: +def statement(answer) -> bool: """Checks if question and answer match""" global all_correct - question_and_answer_bank: dict[str, str] = { - "a comment is": "used to provide helpful information for your later self and others to better understand your code at a later date", - } - - if (question, answer) in question_and_answer_bank.items(): - print(f"* Correct, '{ question } { answer }'!") + answer_bank: list[str] = [ + "A comment is used to provide helpful information for your later self and others to better understand your code at a later date", + "A variable is a set space in the computer’s memory.", + "A dictionary stores key and value pairs.", + "A string can store any character on the keyboard.", + "snake_case_is_used_for_variables_functions_methods_and_modules.", + "CONSTANT_CASE_IS_USED_FOR_CONSTANTS.", + "CamelCaseIsUsedForClasses.", + "lowercasepackagenamesareusedforpackages.", + ] + + if answer in answer_bank: + print(f"* Correct, '{ answer }'!") return True else: - print( - f"* Sorry, the following statement is not correct: '{ question } { answer }'" - ) + print(f"* Sorry, the following statement is not correct: '{ answer }'") return False return diff --git a/module-1/hands-on/answers/lesson_3_answers.py b/module-1/hands-on/answers/lesson_3_answers.py new file mode 100644 index 0000000..9994871 --- /dev/null +++ b/module-1/hands-on/answers/lesson_3_answers.py @@ -0,0 +1,100 @@ +"""Lesson 3 answers + +""" + +import streamlit as st + + +def calculate_egfr(creatinine, age, gender, race): + """Calculate eGFR + + Calculate estimated glomerular filtration rate (eGFR) using serum creatinine levels, + age, gender, and race. + + Formula (for adults): eGFR = 175 * ((creatinine × 0.011312) ^ (-1.154)) x (age ^ (-0.203)) + x (0.742 if female) x (1.212 if Afro-Caribbean) + Args: + creatinine: Serum creatinine level (mg/dL) + age: Age of the patient + gender: Gender of the patient (Male, Female) + race: Race of the patient (Afro-Caribbean or other) + Returns: + float: Estimated glomerular filtration rate (eGFR) + """ + if gender == "Male": + gender_factor = 1 + elif gender == "Female": + gender_factor = 0.742 + else: + raise ValueError( + "Invalid gender. Please specify 'Male' for male or 'Female' for female." + ) + + if race == "Afro-Caribbean": + race_factor = 1.212 + elif race == "other": + race_factor = 1 + else: + raise ValueError( + "Invalid race. Please specify 'Afro-Caribbean' or 'other'." + ) + + eGFR = ( + 175 + * ((creatinine * 0.011312) ** (-1.154)) + * (age ** (-0.203)) + * gender_factor + * race_factor + ) + return int(eGFR) + + +def get_ckd_stage(egfr): + """Get CKD stage + + Determine the stage of chronic kidney disease (CKD) based on estimated glomerular filtration rate (eGFR). + + Args: + egfr: Estimated glomerular filtration rate (eGFR) + + Returns: + str: CKD stage + """ + if egfr > 90: + return "1" + elif 60 <= egfr <= 89: + return "2" + elif 45 <= egfr <= 59: + return "3a" + elif 30 <= egfr <= 44: + return "3b" + elif 15 <= egfr <= 29: + return "4" + else: + return "5" + + +def main(): + """The main Streamlit code + + Runs the Streamlit web app + """ + st.title("eGFR calculator") + + creatinine = st.number_input("Creatinine:", step=1) + age = st.number_input("Age:", step=1) + gender = st.selectbox("Gender:", ["", "Male", "Female"]) + race = st.selectbox("Gender:", ["", "Afro-Caribbean", "other"]) + + try: + egfr = calculate_egfr(creatinine, age, gender, race) + except Exception as e: + st.write(f"Awaiting appropriate inputs") + else: + ckd_stage = get_ckd_stage(egfr) + st.write(f"eGFR: { egfr }") + st.write(f"CKD stage { ckd_stage }") + + +if __name__ == "__main__": + main() diff --git a/module-1/hands-on/lesson_1.py b/module-1/hands-on/lesson_1.py index b6836b7..0a6127d 100644 --- a/module-1/hands-on/lesson_1.py +++ b/module-1/hands-on/lesson_1.py @@ -1,31 +1,36 @@ """ Lesson 1 - Some basic terminal and python exercises - Gotten stuck, look at the slides at +Some basic terminal and python exercises +Gotten stuck, look at the slides at """ -""" Exercise 1 - Just run this python script +"""Exercise 1 +Just run this python script """ -""" Exercise 2 - Change the output from the print function to print your name. +"""Exercise 2 +Change the output from the print function to print your name. """ print("Hello world!") -""" Exercise 3 - Run a terminal command to show all files and folders in your current directory. +"""Exercise 3 +Run a terminal command to show all files and folders in your current directory. """ -""" Exercise 4 - Run a terminal command to take you back one level in the directory path. - Then run a terminal command to take you back to where you started. +"""Exercise 4 +1. Run a terminal command to take you back one level in the directory path. +2. Run a terminal command to take you back to where you started. """ -""" Exercise 4 - Run a terminal command to show what is your current directory path. +"""Exercise 4 +Run a terminal command to show what is your current directory path. +""" + +"""Finished +Let your tutor know when you have finished the above. We will restart go to +next session when everyone is finished with this exercise. """ diff --git a/module-1/hands-on/lesson_2.py b/module-1/hands-on/lesson_2.py index afaf1c0..9db6fd8 100644 --- a/module-1/hands-on/lesson_2.py +++ b/module-1/hands-on/lesson_2.py @@ -1,75 +1,125 @@ -"""Lesson 2""" +"""Lesson 2 +Learning about basic python programming +""" + +"""Ignore this code up until... + +""" -"""Ignore this code up until...""" -import answers.lesson_1_anwers as answers +import answers.lesson_2_anwers as answers all_correct = True -def statement(Exercise, answer): +def statement(answer): global all_correct - if not answers.statement(Exercise, answer): + if not answers.statement(answer): all_correct = False return -class FruitPrices: - def __init__(self): - self.prices = {"apple": 1.55, "banana": 2.44} +"""... here""" - def get_price(self, fruit): - return self._price(fruit) +"""START HERE!""" - def _price(self, fruit): - return self.prices[fruit] +"""Exercise 1 - What is in a comment? +What is a comment? Uncomment the correct answer below +""" +# statement("A comment is code that the computer must run.") +# statement("A comment is a pretty addition to the code.") +# statement("A comment is something that every line of code needs.") +# statement("A comment is used to provide helpful information for your later self and others to better understand your code at a later date") +# statement("A comment is a waste of time") -fruit_prices = FruitPrices() -print(fruit_prices.get_price("pear")) +"""Exercise 2 - variables +Uncomment the correct answers +""" +# statement("A variable is a set space in the computer’s memory.") +# statement("Afloat can", "store lists of numbers.") +# statement("A dictionary stores", "key and value pairs.") +# statement("A string can ", "store any character on the keyboard.") +# statement("A boolean can", "store True, False and maybe.") -"""... here""" +"""Exercise 3 - spaces +Uncomment the below code. What happens when you run it from the terminal? +Can you spot the problem and fix it? +""" -"""START HERE!""" +# drug name = "Amoxicillin" -""" Exercise 1 - What is a comment? Uncomment the correct answer below +"""Exercise 4 - quotation marks +Uncomment the below code. What happens when you run it from the terminal? +Can you spot the problem and fix it? """ -# statement("a comment is", "a fish") -# statement("a comment is", "annoying") -# statement("a comment is", "helpful") -# statement("a comment is", "used to provide helpful information for your later self and others to better understand your code at a later date") -# statement("a comment is", "a fish") +""" +patient_id = "1523" +patient_name = "John Smith' +patient_DOB = "01/01/1990" +""" -""" Exercise 2 - What is a variable? +"""Exercise 5 - indentation +Why is the below code not printing out anything? Can you fix it? """ -""" Exercise 3 - What is a type? + +def a_function(): + print("I am a line of code that wants to be printed!") + return + + a_function() + + +"""Exercise 6 - naming conventions +Uncomment the correct answers """ -""" Exercise 4 - What is flow control +# statement("snake_case_is_used_for_variables_functions_methods_and_modules.") +# statement("CONSTANT_CASE_IS_USED_FOR_CONSTANTS.") +# statement("CamelCaseIsUsedForClasses.") +# statement("lowercasepackagenamesareusedforpackages.") + +"""Exercise 7 - control the flow +Uncomment the below function and try and change the value of 'patient_allergy' """ -""" Exercise - """ +patient_allergy = "amoxicillin" + +if patient_allergy == "amoxicillin": + allergy_group = "penicillins" +elif patient_allergy == "tazocin": + allergy_group = "penicillins" +else: + allergy_group = "others" -""" Exercise - +print("Patient is allergic to", allergy_group) """ -""" Exercise - +""" Exercise 8 - for loops + Write code to print out each element of the below list + Hint (use 'for' and 'in') + Feeling more adventurous, try using 'while' instead """ -""" Exercise - +hb_values = [12, 12.3, 12.4, 13] + +"""Exercise 9 - calling a function +Convert the comments below into code. A userful link: +https://www.nhs.uk/health-assessment-tools/calculate-your-body-mass-index/calculate-bmi-for-adults """ +def bmi_calculator(weight, height): + # write code to calculate BMI () + # print out the BMI + return + + +# call the bmi_calculator above + + # End print answers.end(all_correct) diff --git a/module-1/hands-on/lesson_3.py b/module-1/hands-on/lesson_3.py new file mode 100644 index 0000000..f836005 --- /dev/null +++ b/module-1/hands-on/lesson_3.py @@ -0,0 +1,69 @@ +"""Lesson 3 + +Let's build an app. Some useful link + +https://pathlabs.rlbuht.nhs.uk/eGFRcalculator.htm +https://www.nhs.uk/conditions/kidney-disease/diagnosis/ +""" + +import streamlit as st + +"""Exercise 1 - 'Hello world!' web app style! +Run the app using the command: +$ streamlit run lesson_3.py +""" + + +"""def main(): + st.write(f"Hello world!") + return + + +if __name__ == "__main__": + main()""" + +"""Exercise 2 +1. Comment out the above code. +2. Uncomment the code below +3. Follow the steps below +""" + +""" +# Write a function named 'calculate_egfr'. +# Define a variable in this function called egfr and set it to '45'. +# Have this function return egfr. + + +def main(): + # Call the 'calculate_egfr' function above + # Print the returned value to the browser + return + + +if __name__ == "__main__": + main() + +# Run the above code and see if you have the nubmer 45 in the browser window +""" + +"""Exercise 3 +1. Comment out the above code. +2. Uncomment the code below +3. Follow the steps below +""" + + +# Add arguements 'creatinine, age, gender, race' to function below +def calculate_egf(): + egfr = 45 + return egfr + + +def main(): + egfr = calculate_egf() + st.write(f"{egfr}") + return + + +if __name__ == "__main__": + main() diff --git a/module-1/slides/3-python-basics.qmd b/module-1/slides/3-python-basics.qmd index 955fd41..df043dc 100644 --- a/module-1/slides/3-python-basics.qmd +++ b/module-1/slides/3-python-basics.qmd @@ -208,6 +208,30 @@ Output (if drug has been prescribed and given) * Packages (a collection of modules) * `lowercasepackagenames` +## Comments {.smaller} + +* Comments are useful in explaining what code is supposed to do. +* They are essential for when you, and others, need to read your code later to problem solve or add to your code. +* Use them sparingly, as they can clutter code. +* Try and make variable and function names self explanatory. +* You can comment with the hastag or encapsulate with triple quotation marks: + +```{.python filename="comments.py"} +# This is a single line comment +a_string = "a string" + +""" Double quotation mark multiline comment + Here is some more of the comment +""" +def i_am_a_function(): + return True + +''' Single quotation mark multiline comment + Here is some more of the comment +''' +def i_am_another_function(): + return True +``` ## Basic Operators @@ -231,21 +255,21 @@ Output (if drug has been prescribed and given) ## Control flow - if statements ```{.python filename="if_statement.py"} -sky = "dark" +patient_allergy = "amoxicillin" -if sky == "blue": - time_of_day = "day time" -elif sky == "grey" - time_of_day = "dusk or dawn" +if patient_allergy == "amoxicillin": + allergy_group = "penicillins" +elif patient_allergy == "tazocin": + allergy_group = "penicillins" else: - time_of_day = "night time" + allergy_group = "others" -print("Time of day is: ", time_of_day) +print("Patient is allergic to", allergy_group) ``` Output - Time of day is: night time + Patient is allergic to penicillins ## Control flow - for loops diff --git a/module-1/slides/4-lets-build.qmd b/module-1/slides/4-lets-build.qmd new file mode 100644 index 0000000..a400c5b --- /dev/null +++ b/module-1/slides/4-lets-build.qmd @@ -0,0 +1,13 @@ +--- +title: "Let's build an app" +subtitle: Module 1 +author: "Clinicians who code" +format: revealjs +logo: /images/cwc-logo.png +css: /slides.css +title-slide-attributes: + data-background-image: /images/python-scales.jpg +--- + + +## What to build diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e251330 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +streamlit \ No newline at end of file